Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

creating constant jump table; xcode; clang; asm

I have quite strange issue when try to create the jump table in my asm program for iphone (arm64):

.globl my_func
my_func:
...
//jump (switch) table
.L.f_switch:
    .short .L.case0 - .L.f_switch
    .short .L.case1 - .L.f_switch
    ...
.L.case0:
//some case code
...
.L.case1:
//other case code 

After compilation this table is filled by zeros instead of actual values. It could be seen by dumping compiled object file.

(__TEXT,__text) section
_my_func:
0000000000000000    adr x4, #16
0000000000000004    ldrh    w5, [x4, x3, lsl #1]
0000000000000008    add x4, x4, w5, uxth
000000000000000c    br  x4
.L.f_switch:
0000000000000010    .long   0x00000000
0000000000000014    .long   0x00000000
0000000000000018    .long   0x00000000
000000000000001c    nop

How to resolve it?

like image 830
user3124812 Avatar asked May 13 '26 09:05

user3124812


1 Answers

I believe that what you are observing with entries being set to 0 is related to relocation. The compiler may emit relocation information that the linker will ultimately resolve. To that end I created this small sample program:

test.s

.text
.align 4
.globl _main
_main:
    adr  x0, .L.f_switch
    ldr  w1, [x0, x1, LSL#2]
    add  x0, x0, x1
    br   x0

.L.f_switch:
    .word  .L.case0 - .L.f_switch
    .word  .L.case1 - .L.f_switch
    .word  .L.case2 - .L.f_switch

.L.case0:
    nop

.L.case1:
    nop

.L.case2:
    nop

    ret

I'm using XCode 7 and clang reports this version info for clang --version:

Apple LLVM version 7.0.0 (clang-700.0.72)
Target: x86_64-apple-darwin14.5.0
Thread model: posix

To simplify things at the command line I set an environment variable to point to my iPhone SDK with:

export ISYSROOT="/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/"

First experiment is to compile test.s to test.o. I use this command:

clang -x assembler  -arch arm64 test.s -o test.o -c

Now if I dump test.o with otool using:

otool -drGtv test.o

I get this:

test.o:
Data in code table (0 entries)
offset     length kind
Relocation information (__TEXT,__text) 6 entries
address  pcrel length extern type    scattered symbolnum/value
00000018 False long   True   SUB     False     .L.f_switch
00000018 False long   True   UNSIGND False     .L.case2
00000014 False long   True   SUB     False     .L.f_switch
00000014 False long   True   UNSIGND False     .L.case1
00000010 False long   True   SUB     False     .L.f_switch
00000010 False long   True   UNSIGND False     .L.case0
(__TEXT,__text) section
_main:
0000000000000000        adr     x0, #16
0000000000000004        ldr     w1, [x0, x1, lsl #2]
0000000000000008        add      x0, x0, x1
000000000000000c        br      x0
.L.f_switch:
0000000000000010        .long   0x00000000
0000000000000014        .long   0x00000000
0000000000000018        .long   0x00000000
.L.case0:
000000000000001c        nop
.L.case1:
0000000000000020        nop
.L.case2:
0000000000000024        nop
0000000000000028        ret

The compiler(assembler) has emitted relocation entries for 00000010, 00000014, and 00000018 for both parts of the equation (.L.case# and .L.F_switch). The table itself is filled with place holder zeros. It will be the linker's job to resolve the relocations. I can manually link the test.o above with a command like:

ld  -demangle -dynamic -arch arm64 -iphoneos_version_min 5.0.0 -syslibroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/ -o test -L/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk//usr/lib/system test.o -lSystem /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/clang/7.0.0/lib/darwin/libclang_rt.ios.a

I can now use otool to dump the final executable with a command like:

otool -drGtv test

And get this output:

test:
Data in code table (0 entries)
offset     length kind
(__TEXT,__text) section
_main:
0000000100007f80        adr     x0, #16
0000000100007f84        ldr     w1, [x0, x1, lsl #2]
0000000100007f88        add      x0, x0, x1
0000000100007f8c        br      x0
.L.f_switch:
0000000100007f90        .long   0x0000000c
0000000100007f94        .long   0x00000010
0000000100007f98        .long   0x00000014
.L.case0:
0000000100007f9c        nop
.L.case1:
0000000100007fa0        nop
.L.case2:
0000000100007fa4        nop
0000000100007fa8        ret

Notice that all the relocations have been resolved by the linker in the final executable.

Alternatively I could have compiled and linked all in one step to produce the executable test with a command like:

clang -x assembler  -arch arm64 -L$ISYSROOT/usr/lib/system --sysroot=$ISYSROOT test.s -o test

I split it up to show what the object file looked like and then the resulting executable after linking.

like image 107
Michael Petch Avatar answered May 16 '26 00:05

Michael Petch



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!