首先抱歉我的英语不好。
我现在正在编写一个工具来在windows中构建一个dll的导入库,它将输出obj文件的二进制形式。然后我可以通过链接器将它们组合在一起 目前它可以生成带有导入描述符,导入查找表,导入thunk的OBJ。 我几乎让它工作但遇到了一些问题。
我研究了VC和GCC生成的导入库(.lib)文件,决定模仿GCC做什么。
我发现它包含IMAGE_IMPORT_DESCRIPTOR和IMAGE_THUNK_DATA32s,就像我在EXE中看到的一样。
所以我自己创建了一个,但链接器不会生成我想要的EXE。
我希望它按此顺序链接我的lib:
.idata$2 (IMAGE_IMPORT_DESCRIPTOR)
.idata$4 as FirstThunk
.idata$4 contains NullThunk
.idata$5 as OriginalFirstThunk
.idata$5 contains NullThunk
.idata$6 contains DLL's filename
我知道节名+ $之后的数字可以指示链接器按顺序放置数据,并且.idata $ 3中的NULL_IMPORT_DESCRIPTOR可以。
问题是,链接器剥离了未引用的部分,即使同一个obj中的另一个部分被引用。例如,我将NullThunk和DLL的名称放在一个名为dllname的文件中,包含
section 1: .idata$4, 0x00000000
section 2: .idata$5, 0x00000000
section 3: .idata$6, a.dll\0
symbols: _DllName, external, sect3+0
_DllName由导入描述符引用,因此它被链接,但.idata $ 4和.idata $ 5被剥离。
所以NullThunk没有链接,我在CFF资源管理器中看到的是链接器生成的EXE从我的DLL导入了数百个符号。
第二个问题是,如何指示链接器确保在IAT之后放置NullThunk?因为它们都在.idata $ 5中。
另一个问题,当我尝试让我的lib包含2个导入的函数时,链接器只选择其中一个,抛弃另一个。详细地说,我有2个函数:int __stdcall add (int,int);和子。在链接器生成的代码中,对sub的调用似乎是正确的,但调用add变为“call [RVA:0](ff 25 00400000)”。发生了什么事?
经过一周的试验和错误,我终于放弃了,转而寻求帮助。
这是我的工具生成的文件(我将它们打包到lib中): http://filebin.ca/19oJUzj8z1vN/add.lib
当链接到此导入库时,GCC和VC都没有生成正确的EXE。
我该如何解决这些问题?
的问候,
雷鸣
答案 0 :(得分:0)
我已经解决了这个问题。
我只是将生成的存档(.lib文件)中的所有成员重命名为相同的名称, 并将nullthunk对象放在归档的末尾(最后一个成员), 3个问题消失了。
我不知道详细原因,但它确实有效。
现在我的工具可以成功生成导入库。
和其他需要关注的点是第一个链接成员和第二个链接成员中的偏移,字符串的顺序。存档成员之间的填充也是一个需要关注的点。