* [aida_s@mx12.freecom.ne.jp: A serious bug of "ld --enable-auto-import"]
@ 2001-08-25 10:50 Christopher Faylor
0 siblings, 0 replies; 11+ messages in thread
From: Christopher Faylor @ 2001-08-25 10:50 UTC (permalink / raw)
To: binutils
----- Forwarded message from AIDA Shinra <aida_s@mx12.freecom.ne.jp> -----
From: "AIDA Shinra" <aida_s@mx12.freecom.ne.jp>
To: <cygwin@cygwin.com>
Subject: A serious bug of "ld --enable-auto-import"
Date: Fri, 24 Aug 2001 16:44:51 +0900
I found a bug of ld(included in binutils 20010802-1).
Following is a simple test program.
----hello.c----
#include <stdio.h>
extern char hwstr1[];
extern char hwstr2[];
int main(void){
char *p;
hwstr1[12]='!';
p=hwstr2;
p[12]='!';
puts(hwstr1);
puts(hwstr2);
return 0;
}
----hwstr.c----
char hwstr1[]="Hello, World?";
char hwstr2[]="Hello, World?";
----Makefile----
CC = gcc
CFLAGS = -g -Wall -save-temps
LDFLAGS = -Wl,--enable-auto-import
DLL_LDFLAGS = -Wl,--export-all-symbols -Wl,-enable-auto-image-base \
-Wl,--enable-auto-import
.c.o:
gcc -c $(CFLAGS) -o $@ $<
all: hello.exe
cyghwstr.dll libhwstr.dll.a: hwstr.o
gcc -shared -Wl,--out-implib=libhwstr.dll.a $(DLL_LDFLAGS) \
-o cyghwstr.dll hwstr.o
hello.exe: hello.o cyghwstr.dll libhwstr.dll.a
$(CC) $(LDFLAGS) -o hello.exe hello.o -L. -lhwstr
clean:
rm -f hello.exe cyghwstr.dll libhwstr.dll.a *.o *.s *.i
--------
Of course, the correct result of "./hello" is like this:
Hello, World!
Hello, World!
But I got a result like this:
!ello, World?
Hello, World!
This probrem is seemed to be caused by a bug of the linker,
not the compiler. See this:
--summury of hello.s--
_main:
pushl %ebp
movl %esp,%ebp
subl $24,%esp
.stabn 68,0,5,LM1-_main
LM1:
call ___main
.stabn 68,0,6,LM2-_main
LM2:
LBB2:
.stabn 68,0,8,LM3-_main
LM3:
movb $33,_hwstr1+12
.stabn 68,0,9,LM4-_main
LM4:
movl $_hwstr2,-4(%ebp)
.stabn 68,0,10,LM5-_main
LM5:
movl -4(%ebp),%eax
addl $12,%eax
movb $33,(%eax)
.stabn 68,0,11,LM6-_main
LM6:
addl $-12,%esp
pushl $_hwstr1
call _puts
addl $16,%esp
.stabn 68,0,12,LM7-_main
LM7:
addl $-12,%esp
pushl $_hwstr2
call _puts
addl $16,%esp
.stabn 68,0,13,LM8-_main
LM8:
xorl %eax,%eax
jmp L10
.stabn 68,0,14,LM9-_main
LM9:
LBE2:
.stabn 68,0,14,LM10-_main
LM10:
.align 4
L10:
movl %ebp,%esp
popl %ebp
ret
--------
At least the compilation seemes to be succeeded.
In addition, when I used "__declspec(dllimport)" instead of
"-Wl,--enable-auto-import", I got the correct result.
AIDA Shinra
----- End forwarded message -----
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [aida_s@mx12.freecom.ne.jp: A serious bug of "ld --enable-auto-import"]
@ 2001-08-25 22:11 Charles S. Wilson
2001-08-25 22:30 ` DJ Delorie
0 siblings, 1 reply; 11+ messages in thread
From: Charles S. Wilson @ 2001-08-25 22:11 UTC (permalink / raw)
To: binutils; +Cc: cygwin
Confirmed bug. (using the same example posted in the original report)
the auto-import stuff is ignoring the "+12" in this asm statement:
movb $33,_hwstr1+12
The .o file (disassembled) shows:
hello.o: file format pe-i386
Disassembly of section .text:
00000000 <_main>:
0: 55 push %ebp
1: 89 e5 mov %esp,%ebp
3: 83 ec 18 sub $0x18,%esp
6: e8 00 00 00 00 call b <_main+0xb>
b: c6 05 0c 00 00 00 21 movb $0x21,0xc
12: c7 45 fc 00 00 00 00 movl $0x0,0xfffffffc(%ebp)
19: 8b 45 fc mov 0xfffffffc(%ebp),%eax
1c: 83 c0 0a add $0xa,%eax
1f: c6 00 21 movb $0x21,(%eax)
22: 83 c4 f4 add $0xfffffff4,%esp
25: 68 00 00 00 00 push $0x0
2a: e8 00 00 00 00 call 2f <_main+0x2f>
2f: 83 c4 10 add $0x10,%esp
32: 83 c4 f4 add $0xfffffff4,%esp
35: 68 00 00 00 00 push $0x0
3a: e8 00 00 00 00 call 3f <_main+0x3f>
3f: 83 c4 10 add $0x10,%esp
42: 31 c0 xor %eax,%eax
44: eb 02 jmp 48 <_main+0x48>
46: 89 f6 mov %esi,%esi
48: 89 ec mov %ebp,%esp
4a: 5d pop %ebp
4b: c3 ret
And the .relocs section of hello.o sez:
hello.o: file format pe-i386
RELOCATION RECORDS FOR [.text]:
OFFSET TYPE VALUE
00000007 DISP32 ___main
0000000d dir32 _hwstr1
00000015 dir32 _hwstr2
00000026 dir32 _hwstr1
0000002b DISP32 _puts
00000036 dir32 _hwstr2
0000003b DISP32 _puts
RELOCATION RECORDS FOR [.stab]:
OFFSET TYPE VALUE
00000014 dir32 .text
00000020 dir32 .text
00000590 dir32 .text
00000644 dir32 .text
------------------------------------
so, what *should* happen is that in hello.o at offset 0x00d, the address
of _hwstr1 should be added to the current contents of 0x00d--0x010 (0c
00 00 00). What currently happens is that 0x00d--0x010 is simply
replaced by the address of _hwstr1 and the 0000000c is just thrown away.
Using --enable-extra-pe-debug when linking, I see this output (format is
<symbol>@<offset>: add=< arelent->addend >)
pe_find_data_imports:_hwstr1
->__head_cyghwstr_dll
arelent: _hwstr1@0xd: add=0 <<<< this should be "add=12", right?
arelent: _hwstr1@0x26: add=0
pe_find_data_imports:_hwstr2
->__head_cyghwstr_dll
arelent: _hwstr2@0x15: add=0
arelent: _hwstr2@0x36: add=0
Unfortunately, that's as far as I can go. I don't know where the
arelent structure gets filled with the approprate data from the .o, so I
can't track down WHY the "12" isn't going into (arelent)->addend.
Can anyone else shed some light, here?
--Chuck
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [aida_s@mx12.freecom.ne.jp: A serious bug of "ld --enable-auto-import"]
2001-08-25 22:11 Charles S. Wilson
@ 2001-08-25 22:30 ` DJ Delorie
2001-08-25 22:47 ` Charles Wilson
0 siblings, 1 reply; 11+ messages in thread
From: DJ Delorie @ 2001-08-25 22:30 UTC (permalink / raw)
To: cwilson; +Cc: binutils, cygwin
> pe_find_data_imports:_hwstr1
> ->__head_cyghwstr_dll
> arelent: _hwstr1@0xd: add=0 <<<< this should be "add=12", right?
Not always. Sometimes the addend is in the relent, and sometimes the
addend is in the data stream. It depends on the target format.
> Unfortunately, that's as far as I can go. I don't know where the
> arelent structure gets filled with the approprate data from the .o, so I
> can't track down WHY the "12" isn't going into (arelent)->addend.
Gas puts it there. Probably in src/gas/config/tc-i386.c's
tc_gen_reloc, but other places convert it from a bfd reloc to an
i386-specific reloc.
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [aida_s@mx12.freecom.ne.jp: A serious bug of "ld --enable-auto-import"]
2001-08-25 22:30 ` DJ Delorie
@ 2001-08-25 22:47 ` Charles Wilson
2001-08-25 23:14 ` DJ Delorie
0 siblings, 1 reply; 11+ messages in thread
From: Charles Wilson @ 2001-08-25 22:47 UTC (permalink / raw)
To: DJ Delorie; +Cc: binutils, cygwin
DJ Delorie wrote:
>>pe_find_data_imports:_hwstr1
>>->__head_cyghwstr_dll
>>arelent: _hwstr1@0xd: add=0 <<<< this should be "add=12", right?
>>
>
> Not always. Sometimes the addend is in the relent, and sometimes the
> addend is in the data stream. It depends on the target format.
>
Well, in *this* case we're talking about pe-386....
>
>>Unfortunately, that's as far as I can go. I don't know where the
>>arelent structure gets filled with the approprate data from the .o, so I
>>can't track down WHY the "12" isn't going into (arelent)->addend.
>>
>
> Gas puts it there. Probably in src/gas/config/tc-i386.c's
> tc_gen_reloc, but other places convert it from a bfd reloc to an
> i386-specific reloc.
Hmm...but the original bug report said (and I verified) that it works
fine if you add the appropriate __declspec(dll??port) modifiers.
Somehow, this is tied to the autoimport additions -- but none of that
touched gas.
Anyway, I'm confused. The .o file already contains the "12" (actually,
0c 00 00 00 in on-disk byte order), so gas has already done its work --
properly. The problem occurs during the linking step -- ld is ignoring
the offset stored within the opcode and is blindly stuffing in the
relocation address without adding the offset.
That doesn't involve gas at all, does it?--gas is done, at this point.
As *ld* runs, it has to fill arelent structures in order to actually
*perform* the relocation, right? *That's* the part that is not
happening correctly.
--Chuck
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [aida_s@mx12.freecom.ne.jp: A serious bug of "ld --enable-auto-import"]
2001-08-25 22:47 ` Charles Wilson
@ 2001-08-25 23:14 ` DJ Delorie
2001-08-26 8:10 ` Charles Wilson
0 siblings, 1 reply; 11+ messages in thread
From: DJ Delorie @ 2001-08-25 23:14 UTC (permalink / raw)
To: cwilson; +Cc: binutils, cygwin
> Anyway, I'm confused. The .o file already contains the "12" (actually,
> 0c 00 00 00 in on-disk byte order), so gas has already done its work --
> properly. The problem occurs during the linking step -- ld is ignoring
> the offset stored within the opcode and is blindly stuffing in the
> relocation address without adding the offset.
Ok, a couple of things:
In make_import_fixup in ld/emultempl/pe.em, it uses rel->addend
without also checking for the inline offset. For formats that use an
inline addend, rel->addend may be zero.
Addends are very tricky in PE. There's lots of comments about adding,
subtracting, adding, subtracting, etc, in various places in the code.
I don't think an import library *can* specify an offset to be added at
runtime. From my understanding of the dll import/export system,
windows simply places the address of the thing being imported in the
location indicated.
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [aida_s@mx12.freecom.ne.jp: A serious bug of "ld --enable-auto-import"]
2001-08-25 23:14 ` DJ Delorie
@ 2001-08-26 8:10 ` Charles Wilson
2001-08-26 8:43 ` DJ Delorie
0 siblings, 1 reply; 11+ messages in thread
From: Charles Wilson @ 2001-08-26 8:10 UTC (permalink / raw)
To: DJ Delorie; +Cc: binutils, cygwin
DJ Delorie wrote:
>>Anyway, I'm confused. The .o file already contains the "12" (actually,
>>0c 00 00 00 in on-disk byte order), so gas has already done its work --
>>properly. The problem occurs during the linking step -- ld is ignoring
>>the offset stored within the opcode and is blindly stuffing in the
>>relocation address without adding the offset.
>>
>
> Ok, a couple of things:
>
> In make_import_fixup in ld/emultempl/pe.em, it uses rel->addend
> without also checking for the inline offset. For formats that use an
> inline addend, rel->addend may be zero.
????
> Addends are very tricky in PE. There's lots of comments about adding,
> subtracting, adding, subtracting, etc, in various places in the code.
>
> I don't think an import library *can* specify an offset to be added at
> runtime.
Well, that's not exactly what we're trying to do here. We want hello.o
(which will be linked against the import library) to specify a runtime
offset. The import library doesn't specify it. But that's beside the
point; It looks like NOBODY can specify a runtime offset, because:
> From my understanding of the dll import/export system,
> windows simply places the address of the thing being imported in the
> location indicated.
seems to be correct.
Urk. Here's what hello.o looks like when hello.c uses
__declspec(dllimport) (and hwstr.c uses __declspec(dllexport)). Recall
that this configuration works as expected.
hello.o: file format pe-i386
Disassembly of section .text:
00000000 <_main>:
0: 55 push %ebp
1: 89 e5 mov %esp,%ebp
3: 83 ec 18 sub $0x18,%esp
6: e8 00 00 00 00 call b <_main+0xb>
b: a1 00 00 00 00 mov 0x0,%eax
10: c6 40 0c 21 movb $0x21,0xc(%eax)
14: a1 00 00 00 00 mov 0x0,%eax
19: 89 45 fc mov %eax,0xfffffffc(%ebp)
1c: 8b 45 fc mov 0xfffffffc(%ebp),%eax
<snip>
And the relocs:
hello.o: file format pe-i386
RELOCATION RECORDS FOR [.text]:
OFFSET TYPE VALUE
00000007 DISP32 ___main
0000000c dir32 __imp__hwstr1
00000015 dir32 __imp__hwstr2
00000029 dir32 __imp__hwstr1
0000002f DISP32 _puts
0000003a dir32 __imp__hwstr2
00000040 DISP32 _puts
<snip>
Now, sure, you EXPECT the compiler to generate different asm code when
you use __declspec() modifiers. BUT the difference here is instructive:
hwstr1[12]='!'; generates THIS (with declspec'ed hwstr1)
b: a1 00 00 00 00 mov 0x0,%eax
10: c6 40 0c 21 movb $0x21,0xc(%eax)
instead of (without declspec'ed hwstr1)
b: c6 05 0c 00 00 00 21 movb $0x21,0xc
In the declspec case, a runtime offset is avoided (because the windows
loader "can't do that" ???).
This looks very bad for auto-import. One way to fix this is to change
the compiler to always generate the two-line assembler version instead
of the one-line version -- for all extern vars (because in the
auto-import world, you can't tell the difference between statically
linked externs and DLL-linked externs). But that would add a lot of
extra code even in cases when it's not needed, and could slow execution.
I really hope there's another way to fix this, since my idea is unlikely
to be accepted by gcc.
--Chuck
P.S. going back the the non-declspec-decorated versions, if we just link
hello.o and hwstr.o together (no dll's involved) it "just works".
hello.o has the one-line assembler:
b: c6 05 0c 00 00 00 21 movb $0x21,0xc
and the linker includes uses the address of _hwstr1 from hwstr.o, adds
"12" to it, and stuffs it into 0x00d---0x010.
from hello.exe:
40104f: c6 05 10 20 40 00 21 movb $0x21,0x402010
Sections:
Idx Name Size VMA LMA File off Algn
0 .text 00000400 00401000 00401000 00000400 2**2
CONTENTS, ALLOC, LOAD, READONLY, CODE
1 .data 00000200 00402000 00402000 00000800 2**2
CONTENTS, ALLOC, LOAD, DATA
[288](sec 2)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x00000004 _hwstr1
So, _hwstr1 is located at 0x00402000 + 0x00000004 = 0x00402004.
_hwstr1[12] is 0x00402010, which is exactly what is stuffed into the
machine opcode above.
(Yeah, I know this is obvious & is what you'd expect to see; but at this
point I'm manually verifying even the obvious stuff...)
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [aida_s@mx12.freecom.ne.jp: A serious bug of "ld --enable-auto-import"]
2001-08-26 8:10 ` Charles Wilson
@ 2001-08-26 8:43 ` DJ Delorie
2001-08-26 9:04 ` Charles Wilson
0 siblings, 1 reply; 11+ messages in thread
From: DJ Delorie @ 2001-08-26 8:43 UTC (permalink / raw)
To: cwilson; +Cc: binutils, cygwin
> Urk.
I love these types of comments ;-)
> Here's what hello.o looks like when hello.c uses
> __declspec(dllimport) (and hwstr.c uses __declspec(dllexport)).
> Recall that this configuration works as expected.
Right, because we're effectively telling gcc that hwstr1 is a pointer,
not an array. That changes how gcc generates code. Pointers must be
indexed at runtime, arrays may be indexed at compile time.
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [aida_s@mx12.freecom.ne.jp: A serious bug of "ld --enable-auto-import"]
2001-08-26 8:43 ` DJ Delorie
@ 2001-08-26 9:04 ` Charles Wilson
2001-08-26 9:43 ` DJ Delorie
2001-08-26 12:27 ` Kurt Roeckx
0 siblings, 2 replies; 11+ messages in thread
From: Charles Wilson @ 2001-08-26 9:04 UTC (permalink / raw)
To: DJ Delorie; +Cc: binutils, cygwin
DJ Delorie wrote:
>>Here's what hello.o looks like when hello.c uses
>>__declspec(dllimport) (and hwstr.c uses __declspec(dllexport)).
>>Recall that this configuration works as expected.
>>
>
> Right, because we're effectively telling gcc that hwstr1 is a pointer,
> not an array. That changes how gcc generates code. Pointers must be
> indexed at runtime, arrays may be indexed at compile time.
Well, that's interesting. Since arrays ARE pointers(*), then perhaps
it's enough to change gcc's behavior from
"arrays may be indexed at compile time" -- and currently, ARE indexed at
compile time
to
arrays indexed at runtime. (for pe-i386 targets)
That leaves two questions:
a) will it fix the observed problem
b) will gcc accept it
(Is there a gcc option to force runtime indexing of arrays?)
--Chuck
(*) okay, I'm C-biased. I'm not sure how a change of the type proposed
here would affect C++, Fortran, Ada, Java, .... but turning OFF this
optimization shouldn't break anything, should it?
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [aida_s@mx12.freecom.ne.jp: A serious bug of "ld --enable-auto-import"]
2001-08-26 9:04 ` Charles Wilson
@ 2001-08-26 9:43 ` DJ Delorie
2001-08-26 15:35 ` Charles Wilson
2001-08-26 12:27 ` Kurt Roeckx
1 sibling, 1 reply; 11+ messages in thread
From: DJ Delorie @ 2001-08-26 9:43 UTC (permalink / raw)
To: cwilson; +Cc: binutils, cygwin
> Well, that's interesting. Since arrays ARE pointers(*), then perhaps
> it's enough to change gcc's behavior from
Not from gcc's perspective. From C's perspective, array symbols and
pointer symbols are mostly interchangeable, but they are not the same.
For example, these two declarations:
extern char *foo;
extern char foo[];
are *not* the same, and using the wrong one results in a broken
program.
For our purposes, a pointer is a symbol referencing a four-byte range
of memory that holds the address of a range of memory that holds a
sequence of characters, and an array is a symbol referencing a range
of memory that holds a sequence of characters. Because a pointer
requires an extra indirection, gcc is limited in the optimizations it
can do on it, but dealing with imports becomes simpler because the
address occurs in exactly one place.
Since a symbol is always a constant (regardless of what it refers to),
offsetting it by a constant results in a sum that can always be
computed at compile time (well, link time) and gcc will always do it
that way. This is a fairly fundamental concept in gcc, and I doubt it
would be practical to tell gcc to do it otherwise.
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [aida_s@mx12.freecom.ne.jp: A serious bug of "ld --enable-auto-import"]
2001-08-26 9:43 ` DJ Delorie
@ 2001-08-26 15:35 ` Charles Wilson
0 siblings, 0 replies; 11+ messages in thread
From: Charles Wilson @ 2001-08-26 15:35 UTC (permalink / raw)
To: DJ Delorie; +Cc: binutils, cygwin, Paul Sokolovsky
DJ Delorie wrote:
>>Well, that's interesting. Since arrays ARE pointers(*), then perhaps
>>it's enough to change gcc's behavior from
>>
>
> Not from gcc's perspective. From C's perspective, array symbols and
> pointer symbols are mostly interchangeable, but they are not the same.
> For example, these two declarations:
>
> extern char *foo;
> extern char foo[];
>
> are *not* the same, and using the wrong one results in a broken
> program.
Thanks for not ridiculing my thinko. I knew this.
> For our purposes, a pointer is a symbol referencing a four-byte range
> of memory that holds the address of a range of memory that holds a
> sequence of characters, and an array is a symbol referencing a range
> of memory that holds a sequence of characters. Because a pointer
> requires an extra indirection, gcc is limited in the optimizations it
> can do on it, but dealing with imports becomes simpler because the
> address occurs in exactly one place.
>
> Since a symbol is always a constant (regardless of what it refers to),
> offsetting it by a constant results in a sum that can always be
> computed at compile time (well, link time) and gcc will always do it
> that way. This is a fairly fundamental concept in gcc, and I doubt it
> would be practical to tell gcc to do it otherwise.
>
AHA! But that the auto-import code replaces the extra indirection (for
DATA access into a DLL) with the actual address in the loaded DLL. (see
docs pasted below). Perhaps the auto-import needs to create additional
pseudo-symbols for index-array access. E.g.
hwstr
hwstr[1]
hwstr[2]
hwstr[12]
could each be mapped to *different* "fake" symbols. The, the runtime
loader would just replace them as before -- but this time, with the
correct (offset) address in the DLL.
Downside: could lead to an explosion of symbols, if there's a lot of
constant-offset indexing into arrays exported by the DLL. (Variable
offsets are computed at runtime, of course. No problem there. And it
seems that ONLY arrays are subject to this problem...if I understand
correctly)
Oh shoot. I just realized that the above is garbage. How will the DLL
know *which* fake symbols to export? It can't know how an external
client will access an array variable, so the DLL has to export fake
symbols for every conceivable constant index. This is *possible* --
since we're talking about arrays (e.g. with fixed length; these are
*not* pointers <g>) -- but not really practical. A simple array
foo[4096] leads to 4097 exported symbols. No, that's just silly.
I'm going back to square one on this problem. I'm out of ideas on this
one. Paul? Paaauuulll?
FWIW, this is what a disassembly of hello.exe looks like (no declspec
decorators, using the auto-import stuff. Notice the "fixup" labels
__fuN__symbol):
00401044 <_main>:
401044: 55 push %ebp
401045: 89 e5 mov %esp,%ebp
401047: 83 ec 18 sub $0x18,%esp
40104a: e8 8d 00 00 00 call 4010dc <___main>
40104f: c6 05 04 41 40 00 21 movb $0x21,0x404104
^^^^^^^^
this is off by 12
00401051 <__fu0__hwstr1>:
401051: 04 41 add $0x41,%al
401053: 40 inc %eax
401054: 00 21 add %ah,(%ecx)
401056: c7 45 fc fc 40 40 00 movl $0x4040fc,0xfffffffc(%ebp)
00401059 <__fu2__hwstr2>:
401059: fc cld
40105a: 40 inc %eax
40105b: 40 inc %eax
40105c: 00 8b 45 fc 83 c0 add %cl,0xc083fc45(%ebx)
401062: 0c c6 or $0xc6,%al
401064: 00 21 add %ah,(%ecx)
401066: 83 c4 f4 add $0xfffffff4,%esp
401069: 68 f8 40 40 00 push $0x4040f8
0040106a <__fu1__hwstr1>:
40106a: f8 clc
40106b: 40 inc %eax
40106c: 40 inc %eax
40106d: 00 e8 add %ch,%al
40106f: 71 00 jno 401071 <__fu1__hwstr1+0x7>
401071: 00 00 add %al,(%eax)
401073: 83 c4 10 add $0x10,%esp
401076: 83 c4 f4 add $0xfffffff4,%esp
401079: 68 fc 40 40 00 push $0x4040fc
0040107a <__fu3__hwstr2>:
40107a: fc cld
40107b: 40 inc %eax
40107c: 40 inc %eax
40107d: 00 e8 add %ch,%al
40107f: 61 popa
401080: 00 00 add %al,(%eax)
401082: 00 83 c4 10 31 c0 add %al,0xc03110c4(%ebx)
401088: eb 02 jmp 40108c <__fu3__hwstr2+0x12>
40108a: 89 f6 mov %esi,%esi
40108c: 89 ec mov %ebp,%esp
40108e: 5d pop %ebp
40108f: c3 ret
Funky, huh?
--Chuck
Quoting from the pe-dll.c:
------------------------------------
Auto-import feature by Paul Sokolovsky
Quick facts:
1. With this feature on, DLL clients can import variables from DLL
without any concern from their side (for example, without any source
code modifications).
2. This is done completely in bounds of the PE specification (to be
fair, there's a place where it pokes nose out of, but in practise it
works). So, resulting module can be used with any other PE compiler/linker.
3. Auto-import is fully compatible with standard import method and
they can be mixed together.
4. Overheads: space: 8 bytes per imported symbol, plus 20 for each
reference to it; load time: negligible; virtual/physical memory: should
be less than effect of DLL relocation, and I sincerely hope it doesn't
affect DLL sharability (too much).
Idea
The obvious and only way to get rid of dllimport insanity is to make
client access variable directly in the DLL, bypassing extra dereference.
I.e., whenever client contains someting like
mov dll_var,%eax,
address of dll_var in the command should be relocated to point into
loaded DLL. The aim is to make OS loader do so, and than make ld help
with that. Import section of PE made following way: there's a vector of
structures each describing imports from particular DLL. Each such
structure points to two other parellel vectors: one holding imported
names, and one which will hold address of corresponding imported name.
So, the solution is de-vectorize these structures, making import
locations be sparse and pointing directly into code. Before continuing,
it is worth a note that, while authors strives to make PE act ELF-like,
there're some other people make ELF act PE-like: elfvector, ;-) .
Implementation
For each reference of data symbol to be imported from DLL (to set of
which belong symbols with name <sym>, if __imp_<sym> is found in
implib), the import fixup entry is generated. That entry is of type
IMAGE_IMPORT_DESCRIPTOR and stored in .idata$3 subsection. Each fixup
entry contains pointer to symbol's address within .text section (marked
with __fuN_<sym> symbol, where N is integer), pointer to DLL name (so,
DLL name is referenced by multiple entries), and pointer to symbol name
thunk. Symbol name thunk is singleton vector (__nm_th_<symbol>) pointing
to IMAGE_IMPORT_BY_NAME structure (__nm_<symbol>) directly containing
imported name. Here comes that "om the edge" problem mentioned above: PE
specification rambles that name vector (OriginalFirstThunk) should run
in parallel with addresses vector (FirstThunk), i.e. that they (so, DLL
name is referenced by multiple entries), and pointer to symbol name
thunk. Symbol name thunk is singleton vector (__nm_th_<symbol>) pointing
to IMAGE_IMPORT_BY_NAME structure (__nm_<symbol>) directly containing
imported name. Here comes that "om the edge" problem mentioned above: PE
specification rambles that name vector (OriginalFirstThunk) should run
in parallel with addresses vector (FirstThunk), i.e. that they should
have same number of elements and terminated with zero. We violate this,
since FirstThunk points directly into machine code. But in practise, OS
loader implemented the sane way: it goes thru OriginalFirstThunk and
puts addresses to FirstThunk, not something else. It once again should
be noted that dll and symbol name structures are reused across fixup
entries and should be there anyway to support standard import stuff, so
sustained overhead is 20 bytes per reference. Other question is whether
having several IMAGE_IMPORT_DESCRIPTORS for the same DLL is possible.
Answer is yes, it is done even by native compiler/linker (libth32's
functions are in fact reside in windows9x kernel32.dll, so if you use
it, you have two IMAGE_IMPORT_DESCRIPTORS for kernel32.dll). Yet other
question is whether referencing the same PE structures several times is
valid. The answer is why not, prohibitting that (detecting violation)
would require more work on behalf of loader than not doing it.
--------------------------------------------
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [aida_s@mx12.freecom.ne.jp: A serious bug of "ld --enable-auto-import"]
2001-08-26 9:04 ` Charles Wilson
2001-08-26 9:43 ` DJ Delorie
@ 2001-08-26 12:27 ` Kurt Roeckx
1 sibling, 0 replies; 11+ messages in thread
From: Kurt Roeckx @ 2001-08-26 12:27 UTC (permalink / raw)
To: Charles Wilson; +Cc: DJ Delorie, binutils, cygwin
On Sun, Aug 26, 2001 at 12:04:51PM -0400, Charles Wilson wrote:
>
> Since arrays ARE pointers
They are NOT the same. The only place you can change an array
into a pointer is in a function call, because that is how an
array is passed to a function. You can also do the same
arithmetic with pointers as you can with arrays.
To put it simple, an array allocates storage for data, while the
pointer allocates storage to hold the pointer. You need to make
the pointer point to allocated storage.
There are other differences, like a pointer has a modifiable
lvalue, and an array hasn't.
It also generates different code when you derefence a pointer or
array. With an array, it starts at the addres of the array, and
adds to that, while with a pointer it first has to get the
address it points to, and add to that.
Kurt
^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2001-08-26 15:35 UTC | newest]
Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2001-08-25 10:50 [aida_s@mx12.freecom.ne.jp: A serious bug of "ld --enable-auto-import"] Christopher Faylor
2001-08-25 22:11 Charles S. Wilson
2001-08-25 22:30 ` DJ Delorie
2001-08-25 22:47 ` Charles Wilson
2001-08-25 23:14 ` DJ Delorie
2001-08-26 8:10 ` Charles Wilson
2001-08-26 8:43 ` DJ Delorie
2001-08-26 9:04 ` Charles Wilson
2001-08-26 9:43 ` DJ Delorie
2001-08-26 15:35 ` Charles Wilson
2001-08-26 12:27 ` Kurt Roeckx
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).