Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When does stack grow? How does OS know when to grow stack?

Note: This question is about x86_64 architecture and Linux ABI.

When the program is launched, some space is allocated for stack. Later on, during program execution the stack area can get resized (when more space is required) up to some maximum specified by OS.

Let's take for instance simple program:

int main() {
    char bytes[7 * 1024 * 1024];
}

Let's run it under gdb and set breakpoints: before main and after declaring an array.

gdb> b *main
gdb> b main
gdb> r
gdb> info proc mapping // breakpoint before pushing stack
          Start Addr           End Addr       Size     Offset objfile
      0x7ffffffde000     0x7ffffffff000    0x21000        0x0 [stack]
gdb> c
gdb> info proc mapping // breakpoint after pushing stack
          Start Addr           End Addr       Size     Offset objfile
      0x7fffff8fe000     0x7ffffffff000   0x701000        0x0 [stack]

So we can see the stack actually got resized.

The question is how does the OS know when the stack has to be resized?. Some internet resources say OS handles page fault exception and if the accessed address is within possible stack address range, it gets resized.

But when I was debugging the program step by step, it turned out, the stack got resized just after following instruction:

0x40129d <main+4>     sub    rsp, 0x700010

So (as far as I know), there is no page fault yet since we are not accessing the addresses actually. We only change rsp register. So how is it possible OS handles it? Or maybe there is a page fault exception after changing rsp?

like image 666
Andy Avatar asked Mar 03 '20 11:03

Andy


People also ask

How can you determine whether the stack is growing up or down?

The memory needs to be contiguous for an array. So, though stack grows downward, for arrays the stack grows up. In addition if you want to check whether stack grows upward or downward. Declare a local variable in main function.

How does the stack grow in MIPS?

The MIPS stack — The stack grows downward in terms of memory addresses. — The address of the top element of the stack is stored (by convention) in the “stack pointer” register, $sp. MIPS does not provide “push” and “pop” instructions. Instead, they must be done explicitly by the programmer.

How does stack grow in memory?

This stack grows downward from its origin. The stack pointer points to the current topmost datum on the stack. A push operation decrements the pointer and copies the data to the stack; a pop operation copies data from the stack and then increments the pointer.


1 Answers

But when I was debugging the program step by step, it turned out, the stack got resized just after following instruction:

0x40129d <main+4>     sub    rsp, 0x700010

That's not correct. If you step the program you have shown (even if compiled without optimizations), there is no increase in the mapping at all since there are no writes to the stack pages.

But even if you step a less trivial program, you will also see the mapping does not change on the sub instruction, but rather on every ever-increasing access to the stack.

For instance, if you do:

bytes[0] = 42;

you will see it increases by 0x70000, since you are writing into the top. But if you instead do something like:

bytes[3 * 1024 * 1024] = 42;

You will see it increases up only by 0x40000.

Note that you may be getting confused if you are hitting an instruction that happens to push into the stack, like a call.

like image 125
Acorn Avatar answered Oct 20 '22 00:10

Acorn