Import library incompatability between MSVC and Binutils (link.exe bug)
まだ誰も着手していません。
評価
- 難易度
- 5/5
- 見積もり時間
- 1週間以上
- 初心者へのやさしさ
- 35/100
調査の方向性
Start with lower.def and upper.c, then reproduce the two builds using MSVC lib.exe, Binutils dlltool, and ld --out-implib. Inspect the resulting PE imports with dumpbin /imports and objdump -p, focusing on the nonzero final import-directory fields. Done would require determining whether the incompatibility belongs in Binutils, MSVC link.exe, or both, and identifying a concrete correction.
索引モデルが issue の本文から書いたものです。
説明
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:
LIBRARY lower
EXPORTS
func
Then a program that uses it, upper.c:
__declspec(dllimport) void func(void);
void mainCRTStartup(void) { func(); }
If I use MSVC lib.exe to generate the import library, everything is fine:
$ lib /nologo /def:lower.def
$ cl /nologo upper.c /link /subsystem:console lower.lib
However, if I use Binutils dlltool instead:
$ dlltool -d lower.def -l lower.lib
$ cl /nologo upper.c /link /subsystem:console lower.lib
Then upper.exe is an invalid PE image. dumpbin /imports notices:
Section contains the following imports:
...
<Invalid RVA>
402130 Import Address Table
40214C Import Name Table
0 time date stamp
75660001 Index of first forwarder reference
Note the "Invalid RVA". It's observable with objdump -p as well, though it doesn't notice enough to produce an error message:
The Import Tables (interpreted .rdata section contents)
vma: Hint Time Forward DLL First
Table Stamp Chain Name Thunk
00002104 00002118 00000000 00000000 0000212c 00002000
DLL Name: lower.dll
vma: Hint/Ord Member-Name Bound-To
2120 1 func
00002118 00002120 00000000 75660001 0000636e 00002104
The five fields in the last line should have been all zero. Per the PE specification:
The last directory entry is empty (filled with null values), which indicates the end of the directory table.
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 fix link.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.
- 主要言語
- C
- スター
- 5k
- フォーク
- 408
- 平均マージ
- 4時間 40分
- マージ済み PR(30日)
- 2
環境構築
- Dockerfile または Docker Compose ファイルあり
- プルリクエストのテンプレートなし
- コントリビューションガイドなし
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
skeeto/w64devkit のほかの issue
-
難易度 2/5 1〜3時間 初心者へのやさしさ 62/100
-
難易度 4/5 3〜5日 初心者へのやさしさ 46/100
-
難易度 3/5 1〜2日 初心者へのやさしさ 52/100
-
難易度 5/5 1週間以上 初心者へのやさしさ 25/100
-
難易度 5/5 1週間以上 初心者へのやさしさ 35/100
skeeto/w64devkit の issue をすべて見る
似ている issue
-
LLVM versionsオープン
難易度 2/5 1〜3時間 初心者へのやさしさ 67/100
メンテナーはふだん 1 日以内に返信
-
bug good first issue help wanted
難易度 1/5 1時間未満 初心者へのやさしさ 86/100
-
難易度 1/5 1時間未満 初心者へのやさしさ 88/100
メンテナーはふだん 1 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 72/100
JustAResearcher/gpu-unlock-ada#145 · リアクション 1 件 ·
メンテナーはふだん 1 日以内に返信
-
難易度 1/5 1時間未満 初心者へのやさしさ 62/100