Mailing-List: contact cygwin-help AT sourceware DOT cygnus DOT com; run by ezmlm List-Subscribe: List-Archive: List-Post: List-Help: , Sender: cygwin-owner AT sources DOT redhat DOT com Delivered-To: mailing list cygwin AT sources DOT redhat DOT com Message-ID: <3B891172.9000207@ece.gatech.edu> Date: Sun, 26 Aug 2001 11:10:42 -0400 From: Charles Wilson User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:0.9.2) Gecko/20010713 X-Accept-Language: en-us MIME-Version: 1.0 To: DJ Delorie CC: binutils AT sources DOT redhat DOT com, cygwin AT cygwin DOT com Subject: Re: [aida_s AT mx12 DOT freecom DOT ne DOT jp: A serious bug of "ld --enable-auto-import"] References: <3B8884F6 DOT 80708 AT ece DOT gatech DOT edu> <200108260530 DOT BAA28221 AT envy DOT delorie DOT com> <3B888D76 DOT 6090102 AT ece DOT gatech DOT edu> <200108260613 DOT CAA28557 AT envy DOT delorie DOT com> Content-Type: text/plain; charset=us-ascii; format=flowed Content-Transfer-Encoding: 7bit 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 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 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...) -- Unsubscribe info: http://cygwin.com/ml/#unsubscribe-simple Bug reporting: http://cygwin.com/bugs.html Documentation: http://cygwin.com/docs.html FAQ: http://cygwin.com/faq/