thread stack size on Windows (Visual C++) - windows

Is there a call to determine the stack size of a running thread? I've been looking in MSDN thread functions documentation, and can't seem to find one.

Whilst there isn't an API to find out stack size directly, contiguous virtual address space must be reserved up to the maximum stack size - it's just that a lot of that space isn't committed yet. You can take advantage of this and make two calls to VirtualQuery.
For the first call, pass it the address of any value on the stack to get the base address and size, in bytes, of the committed stack space. On an x86 machine where the stack grows downwards, subtract the size from the base address and VirtualQuery again: this will give you the size of the space reserved for the stack (assuming you're not precisely on the limit of stack size at the time). Summing the two naturally gives you the total stack size.

You can get the current committed size from the Top and Bottom in the TEB. You can get the process initial reserve and commit sizes from the PE header. But you cannot retrieve the actual sizes passed to CreateThread, nor is there any API to get the remaining size of reserved nor committed from current stack, see Thread Stack Size.

Related

Assembly - How to modify stack size?

I am a newbie in assembly programming and I am using push and pop instructions that use the memory stack.
So, What is the stack default size, How to modify it and What is the limit if its size?
Stack size depends upon a lot of factors.
It depends on where you start the stack, how much memory you have, what CPU you are using etc.
The CPU you are using is not called a "Windows CPU".
If you are specifying what CPU you are using, you specify the name of that CPU in detail and also, very important, the architecture of the CPU. In this case, you are probably using x86 architecture.
Here is a memory map for x86 architecture:
All addresses Before 0X100000 - Free
0x100000 - 0xc0000 - BIOS
0xc0000 - 0xa0000 - Video Memory
0xa0000 - 0x9fc00 - Extended BIOS data area
0x9fC00 - 0x7e00 - Free
0x7e00 - 0x7c00 - Boot loader
0x7c00 - 0x500 - Free
0x500 - 0x400 - BIOS data area
0x400 - 0x00 - Interupt vector table
In x86, stack information is held by two registers:
Base pointer (bp): Holds starting address of the stack
Stack pointer (sp): Holds the address in which next value will be stored
These registers have different names in different modes:
`Base pointer Stack pointer`
16 bit real mode: bp sp
32 bit protected mode: ebp esp
64 bit mode: rbp rsp
When you set up a stack, stack pointer and base pointer gets the same address.
Stack is setup in the address specified in base pointer register.
You can set up your stack anywhere in memory that is free and the stack grows downwards.
Each time you "push" something on to the stack, the value is stored in the address specified by stack pointer (which is same as base pointer at the beginning), and the stack pointer register is decremented.
Each time you "pop" something from the stack, the value stored in address specified by stack pointer register is stored in a register specified by the programmer and the stack pointer register is incremented.
In 16 bit real mode, you "push" and "pop" 16 bits. So each time you "push" or "pop", The stack pointer register is decremented or incremented by 0x02, since each address holds 8 bits..
In 32 bit protected mode, you "push" and "pop" 32 bits. So each time you "push" or "pop", The stack pointer register is decremented or incremented by 0x04, since each address holds 8 bits.
You will have to setup the stack in the right place dpending upon how many values you are going to be "pushing".
If you keep "pushing" your stack keeps growing downwards and at some point of time your stack may overwrite something. So be wise and set up the stack in a address in the memory where there is plenty of room for the stack to grow downwards.
For example:
If you setup your stack at 0x7c00, just below the bootloader and you "push" too many values, your stack might overwrite the BIOS data area at some point of time which causes a lot of errors.
You should have a basic idea of a stack and the size of it by now.
Whatever loaded ("the loader") your program into memory, and passed control to it, determines where in memory the stack is located, and how much space is available for the stack.
It does so by the simple artifice of loading the stack pointer, typically using a MOV ESP, ... instruction before calling/jumping to your code. Your program then uses the stack area supplied.
If your program uses too much, it will write beyond the end of the allocated stack area. This is a program bug, because the memory past the end may be allocated for some other purpose in the application. Writing on that other memory is likely to change the program behavior (e.g., "bug") when that memory gets used, and finding the cause of that bug is likely to be difficult (people assume that stacks don't damage program data and vice versa).
If your application wants to use a larger stack, generally all you have to do is allocate your own area, large enough for your purposes, and do a MOV ESP, ... yourself to set the stack to the chosen location. How you allocate an area depends on the execution environment in which you run. (You need to respect ESP conventions: must be a multiple of 4, should be initialized to the bottom of a cache line, often useful to initialize to the bottom of virtual memory page).
It is generally a good idea when "switching" stacks to save the old value of ESP provided by the loader, and restore ESP to that old value before returning control to the loader/caller/OS. Likewise, you should free the extended stack space no longer being used.
This scheme will work if you know the amount of stack space you need in advance. In practice, this is rather hard to "guess" (and may be impossible if your code has a recursive algorithm that nests deeply). So you can either pick a really huge number bigger than you need (ick) or you can use an organized approach to switch stacks when it is clear to the program that it needs more.
See How does a stackless language work? for more discussion.

What is the value of stack pointer?

Consider a processor with byte-addressable memory. Assume that all registers, including Program Counter (PC) and Program Status Word (PSW), are of size 2 bytes. A stack in the main memory is implemented from memory location (0100)hex and it grows upward. The stack pointer (SP) points to the top element of the stack. The current value of SP is (016E)hex. The CALL instruction is of two words, the first word is the op-code and second word is the starting address of the subroutine
(one word = 2 Bytes). The CALL instruction is implemented as follows:
Store the current value of PC in the Stack
Store the value of PSW register in the stack
Load the starting address of the subroutine in PC
The content of PC just before the fetch of a CALL instruction is (5FA0)hex. After execution of the CALL instruction, the value of the stack pointer is
A. 016A
B. 016C
C. 0170
D. 0172
This question was asked in GATE 2015 Computer science.
I marked D as answer please help me to verify my answer, because I am not sure whether I have done it right or not.
Thanks in Advance.
CALL stores two words in the stack so it changes SP by 4. Stack grows up on this architecture so its value is increased as more data are stored. So finally you can compute the result:
0x16e + 4 = 0x172

What are the safe values for CONFIG_FRAME_WARN on x86 arch?

I am compiling driver modules and getting warnings like warning: the frame size of 1064 bytes is larger than 1024 bytes
Yep, it means the space allocated in stack for local variables is big a slightly.
But what is the maximum safe value?
I cannot rely on http://elinux.org/Kernel_Small_Stacks that says up to 8192 bytes.
There are no significant sources.
Thank you.
There is no specific safe value.
What matters is how much stack is actually used, i.e., the sum of the stack frames of all active functions.
This warning does not guarantee that you will overflow the stack space; it just shows that this function makes an overflow more likely (when used together with other big-frame functions, or with many smaller functions).
Linux kernel defines stack size 8192 bytes for each kernel thread, so the maximum safe value is the value that will not overflow total of 8192 bytes in the whole call path.

Is VirtualAlloc alignment consistent with size of allocation?

When using the VirtualAlloc API to allocate and commit a region of virtual memory with a power of two size of the page boundary such as:
void* address = VirtualAlloc(0, 0x10000, MEM_COMMIT, PAGE_READWRITE); // Get 64KB
The address seems to always be in 64KB alignment, not just the page boundary, which in my case is 4KB.
The question is: Is this alignment reliable and prescribed, or is it just coincidence? The docs state that it is guaranteed to be on a page boundary, but does not address the behavior I'm seeing. I ask because I'd later like to take an arbitrary pointer (provided by a pool allocator that uses this chunk) and determine which 64KB chunk it belongs to by something similar to:
void* chunk = (void*)((uintptr_t)ptr & 0xFFFF0000);
The documentation for VirtualAlloc describes the behavior for 2 scenarios: 1) Reserving memory and 2) Committing memory:
If the memory is being reserved, the specified address is rounded down to the nearest multiple of the allocation granularity.
If the memory is already reserved and is being committed, the address is rounded down to the next page boundary.
In other words, memory is allocated (reserved) in multiples of the allocation granularity and committed in multiples of a page size. If you are reserving and committing memory in a single step, it will be be aligned at a multiple of the allocation granularity. When committing already reserved memory it will be aligned at a page boundary.
To query a system's page size and allocation granularity, call GetSystemInfo. The SYSTEM_INFO structure's dwPageSize and dwAllocationGranularity will hold the page size and allocation granularity, respectively.
This is entirely normal. 64KB is the value of SYSTEM_INFO.dwAllocationGranularity. It is a simple counter-measure against address space fragmentation, 4KB pages are too small. The memory manager will still sub-divide 64KB chunks as needed if you change page protection of individual pages within the chunk.
Use HeapAlloc() to sub-allocate. The heap manager has specific counter-measures against fragmentation.

How to view the current stack size of a windows thread when it overflows

I have a process that is overflowing the stack when run from within an IIS process, but works fine when run on its own. I suspect that on its own it gets the default 1MB stack, but within IIS gets somewhat less.
To avoid messing with the IIS worker processes I am using a sub-thread within the IIS process to allocate a bigger stack, but I suspect the stack size argument to Thread creation is being ignored as per the documentation (http://msdn.microsoft.com/en-us/library/ms149581.aspx)
When the stack overflows I can view the halted process in the debugger, but how do I find out how big a stack was actually allocated?
The answer is as follows.
In debugger, add a watch on the pseudo register TIB (http://msdn.microsoft.com/en-us/library/aa232399(v=vs.60).aspx )
Now take this value and display that address in a memory window. Subtract the third 4 byte word from the second 4 byte word, remembering to use little endian byte ordering.
http://en.wikipedia.org/wiki/Win32_Thread_Information_Block

Resources