从DLL导入时符号的问题

虽然DLL互相调用啊啥的玩得不少了,但是其实没有认真研究过符号和__declspec(import)这类东西之间的关系。今天碰巧遇到了,就稍微看一下。

 

编译DLL的时候加了__declspec(dllexport)就能把符号导出,这是没问题的,也能生成一个导入库LIB,这个LIB用来以导入表的方式链接到DLL里的符号用。

但是在调用DLL里这些函数啊什么的时候,又有一个问题,就是写函数声明的时候,加__declspec(dllimport)也可以,不加也可以。经过对比研究,汇编级跟踪,大致弄明白是怎么一回事了。

使用__declspec(dllimport)声明的时候,生成的代码是 CALL [xxxxxxxx] 这样,其中的xxxxxxxx就是导入的符号在导入表中的地址,xxxxxxxx对应的符号是__imp__打头的那些。

如果不使用__declspec(dllimport)声明,那么生成的代码是 CALL xxxxxxxx这样的,其中xxxxxxxx指向的是一句 jmp [yyyyyyyy] 这样的代码,其中xxxxxxxx对应的符号是不带__imp__前缀的那些,yyyyyyyy是导入的符号在导入表中的位置。我推测这一句jmp(似乎俗称stub)是LIB文件中提供的代码。

也就是说在使用nasm编译一个obj来塞入LIB用来干点什么事的时候,对于__imp__系的符号,要用dd,放在.data节;对于不带__imp__前缀的符号,要用 jmp xxxxxxxx,放在.code节。

 

对了顺便说一下,如果是使用equ让它指向另外一个地址的话,我尝试的时候,让它指向extern的某个符号是失败的,最终会导致这个equ到另一个常量的符号没有导出,具体可见这篇博客。但是可以给它一个常量。

发表评论