public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
* [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-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

* 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  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  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-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-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 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: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: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

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).