DLL memory model

Kernel, Loader, code execution and working with memory
Post Reply
User avatar
adimetrius
Posts: 68
Joined: Sun Aug 04, 2019 1:02 pm

DLL memory model

Post by adimetrius »

Reading the Kernel module, I have noticed two memory models distinguished by the variable dllMem: BOOLEAN;
Also, the Kernel module used in Linux for the cross-platform BlackBox does not have two memory models, but only one; and it looks like the one used in Linux Kernel matches the dllMem model in Windows. Is there anywhere a discussion of these models in Windows, and why it is necessary to have two instead of one?

In the changes list, there is this line: 20120906, luowy, deallocate cluster only if dllMem. What is the rationale behind this decision, as opposed to the ~dllMem => leave cluster allocated?
User avatar
adimetrius
Posts: 68
Joined: Sun Aug 04, 2019 1:02 pm

Re: DLL memory model

Post by adimetrius »

I have discovered that Kernel uses WinApi.VirtualAlloc/VirtualFree for 'module memory': code, global vars, metainformation; and WinApi.HeapAlloc/HeapFree to allocate clusters of memory that are used for dynamic variables.
I wonder if it makse sense to use HeapAlloc/Free. These functions allow to allocate memory with byte granularity. Of course, this comes at a cost: WinApi keeps track of these granularity-free blocks; HeapAlloc/Free make in turn calls to VirtualAlloc/Free as necessary.
However, BlackBox does not need byte-granular memory for it's clusters. In fact, special care is taken to make sure Kernel.Cluster variables are aligned at 16-byte (it seems) boundary. In fact, BlackBox allocates clusters of 64 or 256 kilobytes.
So, I wonder if Kernel could do away with HeapAlloc/Free and use VirtualAlloc/Free for cluster allocation as well.

Also, it seems that when in .exe memory model, Kernel does not free address space after, say, a module is unloaded; rather, it only frees the memory pages. The only rationale for this that I can think of is to prevent the possibility of some other data or code being allocated at the same addresses, and then some old pointer into this range being used, most likely resulting in a trap or a crash. Are there any other reasons? Would the same have to hold for dynamic memory - wouldn't it be safer to never reuse addresses once allocated for dynamic variables?
Josef Templ
Posts: 262
Joined: Tue Sep 17, 2013 6:50 am

Re: DLL memory model

Post by Josef Templ »

If I remember correctly, modules are marked as "unusable" when unloaded. If a procedure variable is called that calls such a code address, a trap is generated and it is discovered and reported correctly that a call to an unloaded module has been made.
However, the physical memory pages are recovered after unload but the virtual memory space remains allocated. So you can do a lot of load/unload cycles but not infinitely many.

This cannot be done with heap memory. The unloaded code could simply be executed via a procedure variable as long as the memory is not reused. But executing such code is unsafe because the heap roots (global variables) are no longer tracked by the garbage collector. In addition the physical memory pages are not recovered after unload and you cannot have a lot of load/unload cycles.

There are probably even more subtle trade-offs between the two kinds of memory such as the available address space, fragmentation, etc.

- Josef
Post Reply