[ld] Alias symbols of reordered code are not migrated to new location

Originator:jmaebe
Number:rdar://7198997 Date Originated:04-Sep-2009 06:00 PM
Status:Open Resolved:
Product:Developer Tools Product Version:3.2/ld64-95.2.12
Classification:Serious bug Reproducible:Always
 
* Description

This bug is probably the same as the one I submitted as http://openradar.appspot.com/radar?id=69403, but the cause is now (hopefully) explained more clearly (and the code is i386 rather than ARM).

The basic problem is that if multiple global symbols are associated with a single atom and the atom is moved around, then only symbols referenced in the current object file (or possibly also from object files read before the current one) are moved along.

The result is that the automatic init code reordering causes errors in case one of the functions called from a .mod_init_func has multiple global symbols associated with its start address, and some of these symbols are only referred from other object files


* Steps to reproduce

1) unpack the attached archive
2) cd ldreorderbug
3) ./build.sh
4) ./runtestc

* Expected results

This output:
---
Here
in callee
Here
Here prog
in callee
Here prog
---


* Actual results
This output:
---
Here
in callee
Here
Here prog
Illegal instruction
---

The problem in short:
1) both _callee and _callee_alias are global symbols pointing to the same code
2) "_callee" is called from the library's initialiser function "_libmain", and these two functions are in the source/object file (clib.c/o)
3) "_callee_alias" is called from the function "_myextern", which resides a different source/object file (clib2.c/o)
4) A dylib is created from clib.o and clib2.o.
5) ld reorders "_callee" to the front of the text section (because it's called from an initialiser), but does not move the "_callee_alias" symbol that referred to the same code (but now no longer does)
6) when the "_myextern" function is called from the main program, it now jumps to the invalid opcode coming after the original "callee" function rather than the "callee" function itself, because of the misplaced "_callee_alias" symbol.


* Notes

The overal "project" looks like this:
a) clib.c: contains the initialiser (libmain) and function called from the initialiser (callee) for the library
b) clib2.c: contains another function for the library (myextern), which also calls callee via an alias
c) runtest.c: a test program that is linked against the library. It calls the myextern() function from main.

The interesting file in the archive is clib.s. It has been generated from clib.c using "gcc -arch i386 -S -o clib.s clib.c", and was then slightly modified. All modifications are marked using #-comments. The modifications I made were
a) add a global alias for the "_callee" symbol called "_callee_alias"
b) add a dummy routine after the "_callee" function called "dummy", which consists of a single illegal instruction (along with a .reference to it, so the linker doesn't discard it)
c) add a .mod_init_func section that designates the "_libmain" function as initialiser (which in turn calls callee)

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!