Reuben Scratton
Reuben Scratton

Reputation: 38707

LLVM ARM64 assembly: Getting a symbol/label address?

I am porting some 32-bit ARM code to 64-bit and am having trouble determining the 64-bit version of this instruction:

ldr  r1, =_fns

Where _fns is a symbol defined in some C source file elsewhere in the project.

I've tried the below but both give errors:

adr  x1, _fns     <== "error: unknown AArch64 fixup kind!"
adrl  x1, _fns    <== "error: unrecognized instruction mnemonic"

The assembler is LLVM in the iOS SDK (XCode 7.1).

I've noticed that if _fns is locally defined (i.e. in the same .S file) then "adr x1,_fns" works fine. However that's not a fix as _fns has to be in C code (i.e. in a different translation unit).

What is the right way to do this with LLVM ARM assembler?

Upvotes: 2

Views: 5781

Answers (2)

Andy
Andy

Reputation: 11

this work well for me, xcode7.1 LLVM7.0 IOS9.1

In 32bit arm
ldr r9,=JumpTab

Change to 64bit arm

adrp x9,JumpTab@PAGE
add x9,x9,JumpTab@PAGEOFF

By the way,you need care registers' number, some registers have specific useful in arm64

Upvotes: 1

Richard Pennington
Richard Pennington

Reputation: 19965

If I feed

extern char ar[];

char *f()
{
  return ar;
}

into the ELLCC (clang based) demo, I get:

Output from the compiler targeting ARM AArch64

    .text
    .file   "/tmp/webcompile/_3793_0.c"
    .globl  f
    .align  2
    .type   f,@function
f:                                      // @f
// BB#0:                                // %entry
    adrp    x0, ar
    add x0, x0, :lo12:ar
    ret
.Lfunc_end0:
    .size   f, .Lfunc_end0-f


    .ident  "ecc 0.1.13 based on clang version 3.7.0 (trunk) (based on LLVM 3.7.0svn)"
    .section    ".note.GNU-stack","",@progbits

The adrp instruction gets the "page" address of ar into x0. The symbol argument to adrp translates into a 21 bit PC relative offset to the 4K page in which the symbol resides. That offset is added to the PC to get the actual start of the page. The add instruction adds the low 12 bits of the symbol address to get the actual symbol address.

This instruction sequence allows the address of a symbol within +/-4GB of the PC to be loaded.

As far as I can tell, there doesn't seem to be a way of getting functionality similar to 32 bit ARM's "=ar" in C. I assembly language, it looks like this will work:

        .text
        .file   "atest.s"
        .globl  f
        .align  2
f:
        ldr     x0, p
        ret
        .align  3
p:
        .xword  _fns

This is very similar to what the 32 bit ARM does under the hood.

The only reason I started out with the C version was to show how I usually attack a problem like this, especially if I'm not that familiar with the target assembly language.

Upvotes: 4

Related Questions