http://bugs.winehq.org/show_bug.cgi?id=10273
--- Comment #10 from Anastasius Focht focht@gmx.net 2007-11-04 14:18:25 --- Hello again,
well I digged further...
--- quote --- 7b8303fc l F .text 00000000 .hidden __i686.get_pc_thunk.cx 7b8140e7 l F .text 00000000 .hidden __i686.get_pc_thunk.bx
The address of "__i686.get_pc_thunk.cx" is within "visible" PE section space (starts at 7b820000) whereas "__i686.get_pc_thunk.bx" is not. Both calculate global offset table addresses (choice is probably made by compiler what register does not need to be saved in that code context). If the code location could be fixed to "visible" PE section space like for the get_pc_thunk.cx we might fix this problem while keeping -fPIC. --- quote ---
I dumped some of the generated kernel32 object files. Because they have been compiled with "-fPIC" all of them have "__i686.get_pc_thunk.bx" and some have additionally "__i686.get_pc_thunk.cx" defined. Both functions have their own .text, flagged as gnu linkonce (important for linking step).
--- snip --- .text.__i686.get_pc_thunk.bx:080000DE public __i686_get_pc_thunk_bx .text.__i686.get_pc_thunk.bx:080000DE __i686_get_pc_thunk_bx proc near .text.__i686.get_pc_thunk.bx:080000DE mov ebx, [esp+0] .text.__i686.get_pc_thunk.bx:080000E1 retn .text.__i686.get_pc_thunk.bx:080000E1 __i686_get_pc_thunk_bx endp --- snip ---
I outputted the linker script of my (wine)gcc, using -Wl,--verbose to see how it handles .text sections:
--- snip --- .. .text : { *(.text .stub .text.* .gnu.linkonce.t.*) KEEP (*(.text.*personality*)) /* .gnu.warning sections are handled specially by elf32.em. */ *(.gnu.warning) } =0x90909090 .. --- snip ---
The final .text section is composed of all the .text, .stub, .text.*, and .gnu.linkonce.t.* sections that the linker encounters from all input files - in that (file) order. Supplying the verbose flag to linker it outputs the following:
--- snip --- .. attempt to open /usr/lib/gcc/i386-redhat-linux/4.1.2/../../../crti.o succeeded /usr/lib/gcc/i386-redhat-linux/4.1.2/../../../crti.o attempt to open /usr/lib/gcc/i386-redhat-linux/4.1.2/crtbeginS.o succeeded /usr/lib/gcc/i386-redhat-linux/4.1.2/crtbeginS.o attempt to open kernel32.dll-tWCtEp.spec.o succeeded kernel32.dll-tWCtEp.spec.o attempt to open comm.drv.spec.o succeeded comm.drv.spec.o attempt to open krnl386.exe.spec.o succeeded krnl386.exe.spec.o attempt to open stress.spec.o succeeded stress.spec.o .. --- snip ---
The culprit is "crtbeginS.o". That module contains code to deal with global constructors and destructors (_init and _fini functions). The "S" version is built with ... guess .. -fPIC.
Dumping the object code for this library indeed reveals that "__i686_get_pc_thunk_bx" is defined here.
Due to "gcc -shared" this object file is automagically used as one of the first (implicit) object file arguments to the linker. Because the linker combines .text sections in order of supplied files, the definition of "__i686_get_pc_thunk_bx" is pulled in by object files that deal with startup code (before wine code runs) - within ELF .text section part - just before the dll PE header/section begin.
.init section -> _init_proc() -> call_gmon_start(), frame_dummy(), __wine_spec_init_ctor() ....
The reason that "__i686.get_pc_thunk.cx" code is within "valid" PE section space is because none of the internal startup code defines/needs it. The definition is taken from first kernel32 object file that defines/references it.
So it seems the issue is out of wine's scope, one has either to drop -fPIC or to use dummy data exports :(
Regards