[PATCH] ld/PE: Handle MS style import libraries for files named *.exe too
Jan Beulich
jbeulich@suse.com
Mon Nov 11 11:55:48 GMT 2024
On 08.11.2024 13:09, Martin Storsjö wrote:
> On Fri, 8 Nov 2024, Jan Beulich wrote:
>> On 07.11.2024 13:21, Martin Storsjö wrote:
>>> On Thu, 7 Nov 2024, Jan Beulich wrote:
>>>> On 06.11.2024 10:31, Martin Storsjö wrote:
>>>>> When handling MS style import libraries (also called short import
>>>>> libraries, or ILF), we need to detect the kind of library.
>>>>>
>>>>> So far, this has been done by looking at the member file names
>>>>> in the import library - in an MS style import library, all the
>>>>> member files for a specific library have the same member file
>>>>> name - the name of the runtime module to link against. Usually
>>>>> this is a DLL - thus we do a case insensitive comparison and
>>>>> check if the suffix is .dll.
>>>>>
>>>>> However, an .exe can also export symbols which can be linked
>>>>> against in the same way. In particular, if linking against
>>>>> WDK (Windows Driver Kit) import libraries, e.g. wdmsec.lib, the
>>>>> import libraries can provide imports for ntoskrnl.exe.
>>>>>
>>>>> Thus extend the preexisting check from checking for the .dll
>>>>> suffix to also checking for .exe. While this isn't entirely
>>>>> complete and scalable (in theory, such libraries could have
>>>>> any suffix), this should cover a larger majority of them.
>>>>
>>>> How difficult would it be to remove this dependency on file name
>>>> extensions? I really don't like going from 1 to 2, when - as you
>>>> validly say - any can be used. Just think of drivers, using .drv.
>>>
>>> I haven't fully thought it through, but I think it's unfortunately less
>>> easy than it seems on first glance.
>>>
>>> For the long import libraries that GNU tools generate, the import
>>> libraries consist of a bunch of files named <common_base><suffix>.o - all
>>> of these are regular object files.
>>>
>>> For the MS import libraries, all member file names are named the same,
>>> e.g. "kernel32.dll". Most of them (for each imported symbol) aren't object
>>> files, but the special short import file format, and it should be simple
>>> to detect this just by looking at the contents of the files. But for the
>>> header and trailer object files, those are plain regular object files,
>>> just like in the long import libraries.
>>>
>>> So for the individual symbols, we can easily detect this, but for
>>> headers/trailers, we don't see anything different than just regular object
>>> files.
>>
>> Is that really the case? Would an ordinary object file ever have (non-
>> empty, i.e. not just marker) .idata$<N> sections?
>
> Normal (user code) object files normally wouldn't have such sections - but
> some special cases (custom user code doing things similar to import
> libraries) might, e.g. it wouldn't surprise me if Wine had something like
> that somewhere.
>
>> IOW can't the file name check simply be dropped, relying on
>>
>> /* An archive member named .dll, but not having any .idata
>> sections - apparently not a Microsoft import object
>> after all: Skip renaming it. */
>> if (!idata)
>> continue;
>>
>> in the middle of the loop instead (with the comment adjusted)?
>
> No, I don't think that would work entirely as wanted.
>
> Then it would try to do renaming of every archive member, skip it for
> normal code object files (which don't have .idata sections), but it would
> do renaming of all the archive members in GNU style import libraries too,
> as those all contain .idata sections.
>
> It's possible that it would be benign and end up working anyway - but
> ideally we shouldn't be doing this fixup for anything else than the MS
> import libraries.
>
> Another alternative would be to invert the condition - skipping this for
> any member which is named *.o, which should cover practically all the GNU
> import libraries (and also skipping it if it doesn't contain .idata
> sections). But that's only marginally better than the current solution,
> looking for *.dll and/or *.exe.
Checking for *.o wouldn't be any better. No file name checks whatsoever
will be. However, for Windows-style libraries actual section contents
(and relocations) are "manufactured" by pe_ILF_build_a_bfd(). Can't that
flag the resulting bfd-s in some way, to at least mostly eliminate the
need for heuristics? Then again that wouldn't cover the non-ILF form
that MS also used ages ago (which I expect you mean when talking about
GNU format import libraries), where this (admittedly odd) re-ordering
would also appear to be necessary.
I wonder how LINK.EXE actually manages to get the objects / section
constituents correctly ordered. The numbering of the sub-portions of the
section (.idata$2 etc) alone doesn't look to be sufficient (when pretty
clearly that must have been the original goal).
Jan
More information about the Binutils
mailing list