Windows DLL如何实际共享? [英] How are windows DLL actually shared?

查看:249
本文介绍了Windows DLL如何实际共享?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

通过检查我在Windows计算机中拥有的几个DLL(例如KERNEL32.DLL),我注意到它们的任何部分,甚至只读数据部分都没有设置IMAGE_SCN_MEM_SHARED标志。

By examing several DLLs I have in my windows machine (for instance KERNEL32.DLL) I've notice that none of their sections, not even the read only data section have the IMAGE_SCN_MEM_SHARED flag set.

DLL是从.dll文件映射的,因此仅当您读取文件的页面时,该文件才会复制到物理内存中,但是,如果同一页面的内核32进程A和进程B都访问.dll,则该页面在物理内存中将存在两次。 我要问最后一条语句的准确性。

DLLs are mapped from the .dll file so only when you read a page of the file it is copied to physical memory but still, if the same page of let's say kernel32.dll is accessed by both process A and process B then the page will exist twice in physical memory. I am asking for the veracity of this last statement.

如果共享的.text或.rodata段将被复制到物理文件中即使启用了ASLR,内存也只能存储一次,因为ASLR所做的工作是在首次加载模块时对模块的基础进行随机化(应用了相应的重定位),但是下一次加载该模块直到系统重新启动的过程将使模块位于相同的地址因此,.text和.rodata可以以相同的方式共享。

If the .text or the .rodata segment where shared they would get copied to physical memory only onced, even when ASLR is enabled because what ASLR does is randomize the base of a module when it is first loaded (with corresponding relocations applied) but the next process that loads this module untill system restart will get the module at the same address so the .text and .rodata could be shared in the same manner.

这些都是我所做的假设,请更正。

These are all assumptions I made, please correct me.

谢谢!

推荐答案

操作系统肯定能够将多个虚拟地址映射到同一物理内存页面,只要页面内容没有(需要)更改(对于不同的过程以不同的方式)。但是,如果代码使用绝对地址(在DLL的内部或外部),例如vtable /函数指针,指向全局数据的指针(恒定或非恒定)或仅使用绝对地址的函数调用,则该地址必须为进行了修改,以匹配操作系统给该内存部分的实际地址。

The OS will definitely be able to map multiple virtual addresses to the same physical memory page, as long as the page content does not (need to) change [in different ways for different processes]. However, if the code uses an absolute address (either internally or externally to the DLL), for example a vtable/function pointers, pointers to global data (constant or non-constant) or simply function calls with absolute addresses, the address must be modified to match the actual address given by the OS to that section of memory. This is called "relocation".

因此,至少从理论上讲,即使使用地址空间随机化,您也可以共享相同的DLL,这只需要一点点工作即可。编译器和/或程序员。特别是,它要求没有重定位(在很大一部分代码中)。如果代码具有根据代码地址重定位的绝对地址,则每个DLL需要具有一个副本。

So, at least in theory, you can share the same DLL even with address space randomization, it just requires a little more work from the compiler and/or programmer. In particular, it requires that there are no relocations (in large chunks of the code). If the code has absolute addresses that are relocated based on the code-address, then it will need to have one copy per DLL.

我实际上不是知道操作系统是如何处理的。一个简单的解决方案显然是每个DLL仅随机分配一次地址(直到卸载特定的DLL),而不管有多少应用程序使用同一DLL。对于外部人来说,仍然很难知道DLL的加载地址,因为每次第一次加载DLL时,它都会在一个不同的地址加载(更重要的是,对于所有机器,它都不是静态值)使用相同版本的OS,如果没有此功能,情况就是如此)。但是,这确实意味着可以通过例如从具有已知内容的堆栈中复制内容来检查长时间运行的进程。 Web服务器,数据库服务器和系统服务通常是长时间运行的进程,因此只有在系统关闭(或至少重新启动长时间运行的进程)时,它们才会具有不同的地址。

I don't actually know how the OS deals with this. A simple solution is obviously to randomize the address only once per DLL (until that particular DLL is unloaded), regardless of how many applications use the same DLL. It still makes it rather hard for an outsider to know what address the DLL is loaded at, since it will load at a different address each time it gets loaded the first time (and more importantly, it will not be a static value for ALL machines using the same version of OS, which would be the case without this feature). It does, however, mean that long-running processes can be "inspected" by copying content from for example the stack that has known content. Web servers, database servers and system services are typically long-running processes, and as such will have different addresses only when the system is "shut down" (or at least the long running process is restarted).

第二个稍微棘手的版本是检查特定页面(通常为4KB的内存区域)是否具有重定位,并共享所有没有重定位的页面。重新定位的页面每个基址需要具有一个副本。通常在DLL的一个块中( thunk节)具有所有对外部资源的引用,因此DLL的典型大部分不会考虑代码的基址是什么,这意味着肯定是可行的解决方案。

The second, slightly trickier version is to check if a particular page (typically 4KB region of memory) has relocations, and share all the pages that have no relocation. Relocated pages need to have one copy per base address. It is typical to have "all references to external resources" in one block in DLL's (a "thunk section"), so the typical big part of a DLL wouldn't regardless of what the base address of the code, which means that is definitely a workable solution.

如果这些方案在OS中都不起作用,那么您必须多次加载相同的DLL。无论如何,从OS的角度来看,这显然是可行的,因为在ASLR之前,如果两个DLL试图在同一地址加载(例如,不同供应商生产的DLL,碰巧为代码选择了相同的基地址,或者是经典且通用的我从未给出基地址,因此它使用默认地址)-操作系统将通过更改已加载的基地址来解决此类冲突首先。

If neither of these schemes "work" in the OS, then you have to load the same DLL multiple times. This clearly works from the perspective of the OS anyway, as prior to ASLR, the base-address of the same DLL will need to be moved in case of two DLL's trying to load at the same address (for example DLL's produced by different vendors, that happen to pick the same base-address for the code, or the classic and common "I never gave a base address, so it uses the default address") - the OS will resolve such conflicts by changing the base address of the one loaded first.

关于 IMAGE_SCN_MEM_SHARED 的含义,我以为开发人员会要求这样做, DLL中的页面共享是自动完成的。换句话说, IMAGE_SCN_MEM_SHARED 将由特定DLL或EXE的开发人员设置,以表示内容与相同内容的其他用户共享,而不是如果可以在不通知用户的情况下完成操作,则OS可以共享它(共享代码肯定是这种情况,并且(可写的)数据通常不在DLL之间共享。只读数据,例如只要没有重定位,就可以隐式地共享它(该内容的用户无法确定是否共享)。

As to the meaning of IMAGE_SCN_MEM_SHARED, I would have thought that the developer would request this, where the sharing of pages in a DLL is done automatically. In other words IMAGE_SCN_MEM_SHARED will be set by the developer of a particular DLL or EXE to signify the content should be shared with other users of the same content, rather than "the OS can share it if it can be done without the user of the content noticing" (which is certainly the case for sharing code, and (writeable) data is typically not shared between DLL's. Read-only data, as long as it has no relocations, can of course implicitly be shared [the user of that content can not tell if it is shared or not].

这篇关于Windows DLL如何实际共享?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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