What do SizeOfStackReserve and SizeOfStackCommit mean for a DLL?


Those fields in the IMAGE_OPTIONAL_HEADER structure are meaningful only when they appear in the EXE. The values provided in DLLs are ignored.

Size­Of­Heap­Reserve and Size­Of­Heap­Commit fall into the same category. In general, flags and fields which control process settings have no effect when declared in a DLL. We've seen a few examples already, like the /LARGE­ADDRESS­AWARE flag or the markers which indicate the default layout direction.

Comments (5)
  1. Adam Rosenfield says:

    I should hope so — it'd be an awful shame if the program loader went around changing the carpets in the EXE's house when the guest DLL wanders over.

  2. Myria says:

    Random tidbit: /LARGEADDRESSAWARE actually has meaning in a 64-bit EXE.  If you add /LARGEADDRESSAWARE:NO to the linker command line for a 64-bit executable, you will get a 64-bit executable whose address space is limited to 0x7FFFFFFF.  Obviously, it defaults to on when building for 64-bit architectures.  (Matteo Italia is wrong in the link.)

  3. Peter Newman says:

    We found this out just recently with work software. While we didn't expect it to change the stack allocations for existing threads, we were hoping it would work for threads created from code in the DLL. Unfortunately, no such luck.

    We ended up doing a slightly odd work around involving allocating a stack of memory and changing registers to convince the problem function (a section of JIT compiled code) it was a completely fresh stack. And that was the lesser of two oddities.

    [How does the kernel know that the thread was created by your DLL? Do you want it to check the return address? For people who use _beginthread, that means that it will always MSVCR80'd thread preferences! -raymond]
  4. Myria says:

    @Peter: If you swap the stack, be sure to also change that thread's NT_TIB::StackBase and NT_TIB::StackLimit so that the kernel knows the bounds of your stack.  This will allow the kernel to automatically extend the stack if you have a separated reserve/commit system and guard page like the normal stacks.  Also, the kernel will say STATUS_STACK_OVERFLOW instead of STATUS_ACCESS_VIOLATION in the event of an overrun.

    I believe that StackBase and StackLimit are backward from the usual meaning of the words – you'll have to see what it is for a normal stack.

    x86-32: NT_TIB *tib = reinterpret_cast<NT_TIB *>(static_cast<uintptr_t>(__readfsdword(FIELD_OFFSET(NT_TIB, Self))));

    x86-64: NT_TIB *tib = reinterpret_cast<NT_TIB *>(static_cast<uintptr_t>(__readgsqword(FIELD_OFFSET(NT_TIB, Self))));

    [Even better: Use CreateFiber to create a stack and SwitchToFiber to switch to it. Now your code is portable. -Raymond]
  5. Joshua says:

    @Myria: Or just don't overflow your shadow stack. I'm used to allocating them in the middle of the heap so they don't have room to grow anyway.

Comments are closed.

Skip to main content