Mailing-List: contact cygwin-help AT cygwin DOT com; run by ezmlm List-Subscribe: List-Archive: List-Post: List-Help: , Sender: cygwin-owner AT cygwin DOT com Mail-Followup-To: cygwin AT cygwin DOT com Delivered-To: mailing list cygwin AT cygwin DOT com Date: Wed, 22 Sep 2004 10:16:57 -0500 From: Brian Ford Reply-To: cygwin AT cygwin DOT com To: Charles Wilson cc: libtool-patches AT gnu DOT org, cygwin AT cygwin DOT com Subject: Re: cygwin, libtool, dlpreopen, and .rdata In-Reply-To: <41511C3F.7080003@cwilson.fastmail.fm> Message-ID: References: <41511C3F DOT 7080003 AT cwilson DOT fastmail DOT fm> MIME-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII X-IsSubscribed: yes On Wed, 22 Sep 2004, Charles Wilson wrote: > [cygwin list: I'm CC'ing this so that it goes into the archives, but > it's pretty technical about the innards of libtool...] This doesn't seem libtool related at all to me (other than it's a gcc bug that affects libtool). > With newer gcc's (cygwin version numbers 3.3.3-3, 3.4.1-1, but not > 3.3.1-3), const variables are placed in an .rdata section. This causes > problems when those variables contain references to OTHER vars that are > imported from a dll -- because the runtime relocation machinery can't > fixup the address, since the variable holding the address is const -- > and is in .rdata! Yes, I see. I hope Danny Smith might weigh in here? http://sources.redhat.com/ml/binutils/2004-02/msg00003.html > Concrete example: the demo test program from libtool itself. When > building helldl, libtool creates the following virtual lookup table: > > helldl.exeS.c (important bits only): > ************************************* > /* External symbol declarations for the compiler. */ > extern int foo; > extern int hello; > extern int nothing; > > /* The mapping between symbol names and symbols. */ > const struct { > const char *name; > lt_ptr address; > } > lt_preloaded_symbols[] = > { > {"libhello.a", (lt_ptr) 0}, > {"hello", (lt_ptr) &hello}, > {"foo", (lt_ptr) &foo}, > {"nothing", (lt_ptr) ¬hing}, > {0, (lt_ptr) 0} > }; > ************************************* > > Because lt_preloaded_symbols[] is an array of const structs, it is > placed in .rdata. However, the "nothing" symbol is a DATA export from > cyghello-2.dll -- so the runtime psuedo-reloc machinery needs to fixup > the address stored in "lt_preloaded_symbols[3].address" to point to the > actual, relocated memory location of the "nothing" variable. > > But it can't, because .rdata is non-writable. However, this is a > *runtime* error; the *link* succeeds. But when you run the app, you get > a popup window declaring: > > "The application failed to initialize properly (0xc0000005). Click on OK > to terminate the application." > > Note that > (1) the "nothing" relocation works fine for "normal" links; hell.exe > works ok, and imports "nothing" correctly. > > (2) the lt_preloaded_symbol[] object works fine, as long as it doesn't > contain references to DATA items imported from DLL's: staticly linked > helldl.exe works ok, and dynamically linked helldl.exe works IF > "nothing" is expunged from the application code (manually removed from > helldl.exeS.c, and from dlmain.c) > > (3) even with newer compilers, if lt_preloaded_symbol[] is in .data > (by changing its definition from "const struct" to "struct") then > everything works fine. Note that you only need to do this in > helldl.exeS.c; the application (dlmain.c, in this case) can still > declare 'extern const struct ....'). > > ************************************* > I see two solutions: a short term libtool-focused workaround, and a > longer term general solution. > > The short term workaround is to simply change lt_preloaded_symbol[]'s > constness in the *.exeS.c file, so that it goes in the .data section. > Mabye this could be done for cygwin/mingw only (but application code can > remain unchanged, declaring 'extern const struct ...'). But that won't > fix any OTHER problems out there which put the address of DLL DATA > imports into const variables. > > The long term solution is...er...hard. Somehow, ld/(gcc?) should be > modified to detect that a dllreloc is being put into an .rdata, and move > the entire enclosing variable into .data. This is difficult: > lt_preloaded_symbol[3].address can be flagged easily, but how can the > linker figure out that the whole lt_preloaded_symbol variable should be > moved from .rdata to .data? And didn't the compiler put the symbol into > .rdata in the first place -- so maybe gcc is the one who should detect > this? But gcc doesn't know how the link will be performed: it doesn't > know that "nothing" is a DATA import from a DLL, but "foo" is a function > import from a DLL! (Worse, you might link to a STATIC library and not a > DLL at all, so lt_preloaded_symbol could STAY in .rdata in that case.) > > This might be one of those "doctor, it hurts when I do this/OK, don't do > that" situations. > > Note, I found this problem in libtool-1.5.x, but it exists in HEAD, too. > The following patch is against HEAD... > > -- > Chuck -- Brian Ford Senior Realtime Software Engineer VITAL - Visual Simulation Systems FlightSafety International the best safety device in any aircraft is a well-trained pilot... -- Unsubscribe info: http://cygwin.com/ml/#unsubscribe-simple Problem reports: http://cygwin.com/problems.html Documentation: http://cygwin.com/docs.html FAQ: http://cygwin.com/faq/