-
Notifications
You must be signed in to change notification settings - Fork 222
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Import library incompatability between MSVC and Binutils (link.exe bug) #135
Comments
It gets even more complicated - binutils and msvc are apparently creating different import library formats.
I also noticed a related discussion on the mingw-w64 irc channel:
Probably not entirely related, but I add it for some context. This was news to me when I learned about it. |
Thanks for the followup! I hadn't realized there were "short" and "long" formats, which sheds light on the situation. As noted in your findings, these toolchains are typically compatible with import libraries. This is just an odd edge case I noticed in link.exe. Taking another look, I noticed the PE spec incompletely documents both formats, but neither MSVC lib.exe nor Bintuils outputs quite match the PE spec for either. When I tried to craft a "short" import library — writing a pseudo-COFF by hand, then creating an archive using a standard archive tool — I found two more toolchain bugs: an MSVC lib.exe "internal error" crash that produces a corrupt archive, and Binutils ar memory corruption also producing a corrupt archive. Seems neither archiver likes consuming pseudo-COFFs. To keep trying, I'll need to also craft the archive itself. For the record, to reproduce the two archiver bugs, first write a pseudo-COFF for a symbol
Try to archive it with
The resulting
So far everything seems fine, but all three linkers reject it as invalid. If I manually examine the contents I see the
If I archive with (It's pretty frustrating that the more I dig, the more bugs I turn up.) |
I've discovered a subtle import library incompatibility between MSVC and Binutils which goes back at least a quarter century. It's definitely a bug in MSVC
link.exe
(at least x86 and x64), but possibly also a bug in Binutils. I haven't gotten to the bottom of it, and probably will not any time soon, but I want to document it publicly for the future, in case anyone else wants to keep digging.Summary: Linking only Binutils-generated import libraries with
link.exe
will produce a PE image with a non-terminating import directory. It may crash on load — both Windows and Wine — depending on how the loader was written, and what happens to follow the directory in the image. I can reproduce the issue at least as far back as VS6 (1998). It's likely gone unnoticed so long because virtually nobody does this except for the occasional weirdo like me.The set up is trivial. First a library definition,
lower.def
:Then a program that uses it,
upper.c
:If I use MSVC
lib.exe
to generate the import library, everything is fine:However, if I use Binutils
dlltool
instead:Then
upper.exe
is an invalid PE image.dumpbin /imports
notices:Section contains the following imports:
...
Note the "Invalid RVA". It's observable with
objdump -p
as well, though it doesn't notice enough to produce an error message:The five fields in the last line should have been all zero. Per the PE specification:
The values shown are instead pieces of the first import lookup table, and then the idata string table, which immediately follow the import directory table.
objdump
notices garbage and stops reading the directory table.It's not just
dlltool
:ld --out-implib=...
has the same result.Linking at least one non-Binutils import library, in any position, fixes the problem. With all the implicitly-linked libraries present, this is nearly always the case — except for toolchain-hacking weirdos — so the bug almost never manifests in practice.
I suspect maybe Bintuils' import libraries are not quite formatted properly, which confuses
link.exe
. It's still a linker bug, because it shouldn't quietly link a broken PE image. Since it's unlikely I could get Microsoft to fixlink.exe
, perhaps it could be addressed in Bintuils. This is where things get more complicated. The import library format is undocumented — so who knows what's "correct" or not — and Bintuils' import libraries are especially messy, making them difficult to pick through by hand. Figuring this out would be the next step.The text was updated successfully, but these errors were encountered: