ARM linker bug when global aliased symbols are called from .mod_init_func code
Originator: | jmaebe | ||
Number: | rdar://7120987 | Date Originated: | 05-Aug-2009 11:08 PM |
Status: | Open | Resolved: | |
Product: | iPhone SDK | Product Version: | 3.0 |
Classification: | Serious Bug | Reproducible: | Always |
05-Aug-2009 11:08 PM Jonas Maebe: * Summary If all of the following conditions are true at the same time, the ARM linker assigns a wrong address to the "_calledfrominit" symbol: a) there is a .mod_init_term section pointing to a function, e.g. _initfunc b) this _initfunc calls another function, e.g. _calledfrominit c) the call from _initfun to _calledfrominit occurs via a symbol stub d) there is (at least?) one other global symbol with the same address as _calledfrominit I have however attached a simple, artificial test case that demonstrates this problem. I don't know how to make GCC generate such code (maybe using C++ with static initialisers in combination with some gcc extension to define symbol aliases), but the Free Pascal Compiler does generate such code (http://www.freepascal.org). If you want to see this bug in a real world example, you can download/install the Free Pascal Compiler for iPhone SDK from http://wiki.freepascal.org/iPhone/iPod_development (note that it always installs globally under /usr/local), create a new Xcode project using the "iPhone (FPC)" -> "OpenGL ES App" template, and build/run it. It will crash in the _start function. * Steps to reproduce (replace "/iphone3.0" in the commands below with whichever iPhoneSDK version you want to test) 1) tar xjf iphonelinkerbug.tbz 2) cd iphonelinkerbug 3) /iphone3.0/Platforms/iPhoneOS.platform/Developer/usr/bin/gcc-4.0 -arch armv6 -isysroot /iphone3.0/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS2.2.1.sdk main.s -o main 4) otool -tV main|less * Expected result Something like this: main: (__TEXT,__text) section _calledfrominitfuncalias: 00002000 e92d4080 stmdb sp!, {r7, lr} 00002004 e28d7000 add r7, sp, #0 ; 0x0 00002008 e59f300c ldr r3, [pc, #12] ; 0x201c 0000200c e08f3003 add r3, pc, r3 00002010 e1a00003 mov r0, r3 00002014 eb00002d bl 0x20d0 ; symbol stub for: _printf 00002018 e8bd8080 ldmia sp!, {r7, pc} 0000201c 000000d4 ldreqd r0, [r0], -r4 _initfunc: 00002020 e92d4080 stmdb sp!, {r7, lr} 00002024 e28d7000 add r7, sp, #0 ; 0x0 00002028 e59f3010 ldr r3, [pc, #16] ; 0x2040 0000202c e08f3003 add r3, pc, r3 00002030 e1a00003 mov r0, r3 00002034 eb000028 bl 0x20dc ; symbol stub for: _puts 00002038 ebfffff0 bl _calledfrominitfuncalias 0000203c e8bd8080 ldmia sp!, {r7, pc} 00002040 000000d0 ldreqd r0, [r0], -r0 start: 00002044 e59d0000 ldr r0, [sp] * Actual result (__TEXT,__text) section _calledfrominitfunc: 00002000 e92d4080 stmdb sp!, {r7, lr} 00002004 e28d7000 add r7, sp, #0 ; 0x0 00002008 e59f3010 ldr r3, [pc, #16] ; 0x2020 0000200c e08f3003 add r3, pc, r3 00002010 e1a00003 mov r0, r3 00002014 eb000030 bl 0x20dc ; symbol stub for: _puts 00002018 ebfffff8 bl _calledfrominitfunc 0000201c e8bd8080 ldmia sp!, {r7, pc} 00002020 000000f0 streqd r0, [r0], -r0 start: 00002024 e59d0000 ldr r0, [sp] [snip] _calledfrominitfuncalias: 0000209c e92d4080 stmdb sp!, {r7, lr} 000020a0 e28d7000 add r7, sp, #0 ; 0x0 000020a4 e59f300c ldr r3, [pc, #12] ; 0x20b8 000020a8 e08f3003 add r3, pc, r3 000020ac e1a00003 mov r0, r3 000020b0 eb000006 bl 0x20d0 ; symbol stub for: _printf 000020b4 e8bd8080 ldmia sp!, {r7, pc} 000020b8 00000038 andeq r0, r0, r8, lsr r0 otool displays _calledfrominitfunc as the symbol name for address 00002000, but nm shows that _initfunc also is at that address. So effectively, _calledfrominitfunc has now become an alias for _initfunc rather than for _calledfrominitfuncalias * Regression The above works fine with the tools from the iPhone SDK 2.2.1/9m2621a (final). It is still broken with the tools from the iPhone SDK 3.1 beta 3 (all under Leopartd/10.5.7) * Notes The main.c file included in the archive is the C file from which I started. I compiled it with -S and made a few changes to the generated assembler code (marked by "# added"). If you replace the "bl L_calledfrominitfunc$stub" with "bl _calledfrominitfunc" in the assembler code so that the stub is no longer used, then a) the code for _calledfrominitfunc is properly referenced from _initfunc, but b) the symbol alias _calledfrominitfuncalias now gets the same address as the "_main" symbol This, too, is wrong (but causes no immediate problems in our case). 'iphonelinkerbug.tbz' was successfully uploaded
Comments
Please note: Reports posted here will not necessarily be seen by Apple. All problems should be submitted at bugreport.apple.com before they are posted here. Please only post information for Radars that you have filed yourself, and please do not include Apple confidential information in your posts. Thank you!