From: marcus AT bighorn DOT dr DOT lucent DOT com Subject: Re: Linker switches [ was: Re: API's that certainly do work. ] 28 Mar 1997 15:47:23 -0800 Approved: cygnus DOT gnu-win32 AT cygnus DOT com Distribution: cygnus Message-ID: <199703281648.JAA16504.cygnus.gnu-win32@chorus.dr.lucent.com> Original-From: marcus AT drmail DOT dr DOT lucent DOT com Original-From: marcus AT drmail DOT dr DOT lucent DOT com Original-To: colin AT bird DOT fu DOT is DOT saga-u DOT ac DOT jp, drs AT inxpress DOT net Original-Cc: gnu-win32 AT cygnus DOT com X-Sun-Charset: US-ASCII Original-Sender: owner-gnu-win32 AT cygnus DOT com Colin Peters wrote: ] To summarize the summary: Don't link with -lkernel32 on your command ] line. DRS asks: > I guess my question is, why would you want to do this anyway? I have > been using -mwindows, which I thought was the recommended linker > switch for compiling a GUI app. I don't claim to know anything > about ld, except that it works for all the examples I have tried. > > I have been unable to find any documentation about the > linker switch in question (-lkernel32) except that it appears > to be mentioned in earlier versions of the distribution. > If someone wants to explain the in's and outs of these > various (win32 specific) switches and how they are supposed > to work, I'm all ears. Do doubt this information would be > of general interest. The -lkernel32 is not a switch itself, but a library to be included. The -l option tells the linker to look for lib.a in the library directories, so -lkernel32 tells it to search the libkernel32.a library. One is tempted to do this if they reference some routines from the kernel32 library, especially if you don't remember that -mwindows already does that for you. With a normal archive library, this is not a problem, but with a DLL library it is. The problem is that including the DLL library has to build an import descriptor table which is a fairly complex structure. The contents depend on the library routines actually referenced. Each routine referenced by the program is resolved by a stub file in the library which places a jump in the .text segment, one pointer into each of .idata$4 and .idata$5, and the function name in .idata$6. Additionally, the stub file references a symbol that will be resolved by another file from the library. This file supplies the head of the structure in .idata$2 and leaves more undefined symbols to bring in a file that terminates the .idata$4 and .idata$5 lists (for this DLL only) and a terminator for the entire descriptor list in .idata$3. The cygwin32 strategy is slightly different, and they forgot the .idata$3 terminator, but it is similar. So, what happens when the kernel32 library is included twice is that the undefined references from the program get resolved by the first -lkernel32 and the import table is built for that, then by the time that the libraries get processed for the -mwindows, there are more references to routines from the kernel32 library from other library routines (processing the library twice would be OK if there were not any new references to the library). These routines cause the jump instruction to be put into the .text section, pointers in the .idata$4 and .idata$5 sections, and the function name in .idata$6, but the reference that is supposed to bring in an import library header into .idata$2 is resolved to the already present header from the first include. However, since that import structure has already been built, the new functions do not get incorporated into the structure, so when the program is eventually loaded, these functions do not get their pointers updated to point into the DLL since they are not really in the import table. Then, when the function is called, the jump heads into the function name, not the function itself, and things crash. That's the problem with processing a DLL library twice. I'm pretty sure that it would occur with Microsoft LINK as well, but I haven't verified it. It's an intricate dance of the various segments to build the DLL import table, so some things like this are difficult to handle. I suppose it could be dealt with my using more .idata segments, something like .idata$4_kernel32 or some such, but this would definately be non-standard. marucs hall Lucent Technologies - For help on using this list, send a message to "gnu-win32-request AT cygnus DOT com" with one line of text: "help".