Hi
I've got the following question: what detrmines the size of the stack of a process in Linux?
Below are two programs written in C and their disassembly (I know Prog1.c is not the way one should handle with pointers). The assembly codes are very similiar but execution of the first program causes segmentation fault. The initial stack of the first program is about 12 KB while for the second it's about 980 KB. What determines this, if the assembly codes are so similiar?
And even assumming that initial stack of the first program is 12 KB - why writing to address from within the stack limit (about 8 MB on my system) doesn't make the system expand the stack?
Is there any stack allocation at the binary level? Is the stack size determined by the compiler?
Prog1.c:
Prog1.s:Code:int main() { char a; char* b = &a; b = b - 999999; *b = '\0'; }
Prog2.c:Code:.file "prog1.c" .text .globl main .type main, @function main: pushl %ebp movl %esp, %ebp subl $16, %esp leal -5(%ebp), %eax movl %eax, -4(%ebp) subl $999999, -4(%ebp) movl -4(%ebp), %eax movb $0, (%eax) leave ret .size main, .-main .ident "GCC: (GNU) 4.4.3" .section .note.GNU-stack,"",@progbits
Prog2.s:Code:int main() { char a[1000000]; char* b = &a[0]; *b = '\0'; }
Code:.file "prog2.c" .text .globl main .type main, @function main: pushl %ebp movl %esp, %ebp subl $1000016, %esp leal -1000004(%ebp), %eax movl %eax, -4(%ebp) movl -4(%ebp), %eax movb $0, (%eax) leave ret .size main, .-main .ident "GCC: (GNU) 4.4.3" .section .note.GNU-stack,"",@progbits
The programs are completely different.
This one is allocating 1 variable a which is of size char and a pointer to char pointing at a.
Then you move the pointer from a to another address 999999 bytes away in memory. Probably a place in read-only memory or atleast a place where a user-space program shouldn't be writing to.
Prog1.c:
Prog1.s:Code:int main() { char a; char* b = &a; b = b - 999999; *b = '\0'; }
Code:.file "prog1.c" .text .globl main .type main, @function main: pushl %ebp movl %esp, %ebp subl $16, %esp leal -5(%ebp), %eax movl %eax, -4(%ebp) subl $999999, -4(%ebp) movl -4(%ebp), %eax movb $0, (%eax) leave ret .size main, .-main .ident "GCC: (GNU) 4.4.3" .section .note.GNU-stack,"",@progbits
This one allocates 1000000 chars in an char array and a pointer to char b which points at the first char in that char array then it sets the value of a[0] to '\0'
Prog2.c:
Prog2.s:Code:int main() { char a[1000000]; char* b = &a[0]; *b = '\0'; }
Code:.file "prog2.c" .text .globl main .type main, @function main: pushl %ebp movl %esp, %ebp subl $1000016, %esp leal -1000004(%ebp), %eax movl %eax, -4(%ebp) movl -4(%ebp), %eax movb $0, (%eax) leave ret .size main, .-main .ident "GCC: (GNU) 4.4.3" .section .note.GNU-stack,"",@progbits
"The best optimizer is between your ears" - Michael Abrash
Saying you can optimize a program is like saying you understand how a program works on every level of every facet on a specific machines configuration.
I finally found out that the thing is in a way Linux handles page faults. If a page fault related to an address beetwen stack top and stack limit occurs the kernel checks the value in stack pointer register. On x86 for instance stack size is expanded only if the address is not lower than stack pointer - 32.
The stack size of the second program is expanded because C likes to put local variables on the stack.
Code:subl $1000016, %esp
"The best optimizer is between your ears" - Michael Abrash
Saying you can optimize a program is like saying you understand how a program works on every level of every facet on a specific machines configuration.
There are currently 1 users browsing this thread. (0 members and 1 guests)
Bookmarks