从.dll导入函数时,为什么需要.lib文件? [英] Why do we need .lib file in case of importing functions from .dll?

查看:45
本文介绍了从.dll导入函数时,为什么需要.lib文件?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

您能帮我理解为什么从dll导入函数和数据时为什么需要.lib文件吗?

我听说,它包含相应dll导出的函数和数据元素的列表,但是当我使用CFF Explorer浏览dll时,我发现dll已经具有导出函数的地址,因此从理论上讲我可以链接我的dll..dll程序,没有任何其他文件.

请您详细解释一下.lib文件中存储的数据类型.
而且,是的,我知道,Visual Studio迫使我们将.lib文件添加到其他依赖项部分,但是为什么它真正需要它们呢?

解决方案

当您的源代码静态调用导出的DLL函数或静态访问导出的DLL变量时,这些引用作为指针被编译到可执行文件的中间目标文件中,其值在运行时填充.

当链接器将编译器生成的目标文件组合成最终可执行文件时,它必须弄清楚所有编译器生成的引用实际上是指什么.如果它无法匹配可执行文件中某段代码的给定引用,则需要将其与外部DLL匹配.因此,它需要知道什至要查看哪些DLL,以及这些DLL如何导出内容.DLL可以按名称或按序号导出给定的函数/变量,因此链接器需要一种方法,将代码引用所使用的标识符映射到特定 EXPORTS 表中的特定条目..dll 文件(尤其是在普通商品导出商品的情况下).静态链接 .lib 文件为链接器提供了该映射信息(即 FunctionA 映射到DLL XYZ.dll FunctionB 映射到DLL ABC.dll 等中的名称 _FunctionB @ 4 .

然后,链接器可以使用有关所需的相应 EXPORTS 条目的信息填充可执行文件的 IMPORTS 表,然后使代码中的DLL引用指向正确的 IMPORTS 条目(如果链接器无法将编译器生成的引用解析为可执行文件中的一段代码或特定的DLL导出,则会因无法解析的外部"错误而中止)./p>

然后,在运行时加载可执行文件时,OS Loader会查看 IMPORTS 表以了解需要哪些DLL导出,因此可以将适当的DLL加载到内存中并进行更新 IMPORTS 表中的条目具有基于每个DLL的 EXPORTS 表的实际内存地址(如果引用的DLL无法加载,或者找不到引用的导出,,则OS Loader将中止加载可执行文件).这样,当您的代码调用DLL函数或访问DLL变量时,这些访问将转到正确的位置.

如果源代码动态在运行时通过显式调用 GetProcAddress()来访问DLL函数/变量,则情况将大为不同.在这种情况下,这些访问不需要静态链接 .lib 文件,因为您自己的代码正在处理将DLL加载到内存中并找到要使用的导出文件.

但是,有第三个选项将上述情况混合在一起:您可以编写代码来静态地访问DLL函数/变量,但可以使用链接器的 delay-load 功能(如果有).在这种情况下,您仍然需要为访问的每个延迟加载的DLL静态链接 .lib 文件,但是链接器会在可执行文件中使用对以下内容的引用填充单独的 DELAYLOAD 表DLL导出,而不是填充 IMPORTS 表.它将编译器生成的DLL引用指向编译器RTL中的存根,当在运行时首次访问存根时,它将用 GetProcAddress()中的地址替换引用,从而避免了需要用于在加载时由OS Loader填充的引用.即使加载时不存在DLL导出,这也可使您的可执行文件正常运行,并且即使从未使用过DLL也可能根本不需要加载DLL(当然,如果您的可执行文件确实尝试访问DLL导出)动态并且无法加载,您的代码可能会崩溃,但这是一个单独的问题.

Can you help me to understand, why do we need .lib files when importing functions and data from dll?

I've heard, that it contains a list of the exported functions and data elements from the corresponding dll, but when I used CFF Explorer to explore my dll, I found out that dll already has addresses of exporting functions so I theoretically can link my program with .dll without any additional files.

Can you, please, explain what kind of data is stored in the .lib files more detailed.
And, also, yes, I know, that visual studio forces us to add .lib files into additional dependencies section, but why does it really needs them?

解决方案

When your source code statically calls exported DLL functions, or statically accesses exported DLL variables, those references are compiled into your executable's intermediate object files as pointers, whose values get populated at run-time.

When the linker is combining the compiler-generated object files to make the final executable, it has to figure out what all of the compiler-generated references actually refer to. If it can't match a given reference to some piece of code in your executable, it needs to match it to an external DLL instead. So it needs to know which DLLs to even look at, and how those DLLs export things. A DLL may export a given function/variable by name OR by ordinal number, so the linker needs a way to map the identifiers used by your code references to specific entries in the EXPORTS tables of specific .dll files (especially in the case where things are exported by ordinals). Static-link .lib files provide the linker with that mapping information (ie FunctionA maps to Ordinal 123 in DLL XYZ.dll, FunctionB maps to name _FunctionB@4 in DLL ABC.dll, etc).

The linker can then populate the IMPORTS table of your executable with information about the appropriate EXPORTS entries needed, and then make the DLL references in your code point to the correct IMPORTS entries (if the linker can't resolve a compiler-generate reference to a piece of code in your executable, or to a specific DLL export, it aborts with an "unresolved external" error).

Then, when your executable is loaded at run-time, the OS Loader looks at the IMPORTS table to know which DLL exports are needed, so it can then load the appropriate DLLs into memory and update the entries in the IMPORTS table with real memory addresses that are based on each DLL's EXPORTS table (if a referenced DLL fails to load, or if a referenced export fails to be found, the OS Loader aborts loading your executable). That way, when your code calls DLL functions or accesses DLL variables, those accesses go to the right places.

Things are very different if your source code dynamically accesses DLL functions/variables via explicit calls to GetProcAddress() at run-time. In that case, static-link .lib files are not needed for those accesses, since your own code is handling the loading of DLLs into memory and locating the exports that it wants to use.

However, there is a 3rd option that blends the above scenarios together: you can write your code to access the DLL functions/variables statically but use your linker's delay-load feature (if it has one). In that case, you still need static-link .lib files for each delay-loaded DLL you access, but the linker populates a separate DELAYLOAD table in your executable with references to the DLL exports, instead of populating the IMPORTS table. It points the compiler-generated DLL references to stubs in your compiler's RTL that will replace the references with addresses from GetProcAddress() when the stubs are accessed for the first time at run-time, thus avoiding the need for the references to be populated by the OS Loader at load-time. This allows your executable to run normally even if the DLL exports are not present at load-time, and may not even need to load the DLLs at all if they are never used (of course, if your executable does try to access a DLL export dynamically and it fails to load, your code is likely to crash, but that is a separate issue).

这篇关于从.dll导入函数时,为什么需要.lib文件?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆