Download Stack Discipline - Operating System Design and Implementation - Lecture Slides and more Slides Operating Systems in PDF only on Docsity! 1 15-410, F’13 Stack Discipline Aug. 28, 2013 Dave Eckhardt Todd Mowry Slides originally stolen from 15-213 15-410 “An Experience Like No Other” 2 15-410, F’13 Movie Night “Primer” Thursday, August 29th 19:30, GHC 4401 (“Rashid Auditorium”) $1 Pizza Presented by #!/cmu/cc Funded in part by your Student Activities Fee 5 15-410, F’13 Why Only 32? You may have learned x86-64 aka EMT64 aka AMD64 x86-64 is simpler than x86(-32) for user program code Lots of registers, registers more orthogonal Why will 410 be x86 / IA32? x86-64 is not simpler for kernel code Machine begins in 16-bit mode, then 32, finally 64 » You don't have time to write 32⇒64 transition code » If we gave it to you, it would be a big black box x86-64 is not simpler during debugging More registers means more registers to have wrong values x86-64 virtual memory is a bit of a drag More steps than x86-32, but not more intellectually stimulating There are still a lot of 32-bit machines in the world ...which can boot and run your personal OS 6 15-410, F’13 Private Address Spaces Each process has its own private address space. kernel virtual memory (code, data, heap, stack) memory mapped region for shared libraries run-time heap (managed by malloc) user stack (created at runtime) unused 0 %esp (stack pointer) memory invisible to user code brk 0xc0000000 0x08048000 0x40000000 read/write segments (.data, .bss) read-only segments (.init, .text, .rodata) loaded from the executable file 0xffffffff Warning: numbers specific to Linux 2.x on IA32!! Warning: details vary by OS and kernel version! 7 15-410, F’13 Linux Memory Layout Stack Runtime stack (8MB limit by default) Heap Dynamically allocated storage Managed by malloc(), calloc(), new Shared/Dynamic Libraries aka Shared Objects Library routines (e.g., printf(), malloc()) Linked into object code when first executed Windows has “DLLs” (semantic differences) Data, BSS Statically allocated data (BSS starts all-zero) e.g., arrays & variables declared in code Text, RODATA Text - Executable machine instructions RODATA – Read-only (e.g., “const”) String literals Upper 2 hex digits of address Red Hat v. 6.2 ~1920MB memory limit FF BF 7F 3F C0 80 40 00 Stack Shared Libraries Text Data Heap Heap 08 10 15-410, F’13 IA32 Stack Pushing Pushing pushl Src Fetch operand from Src Maybe a register: %ebp Maybe memory: 8(%ebp) Decrement %esp by 4 Store operand in memory at address given by %esp Stack Grows Down Increasing Addresses Stack “Top” Stack “Bottom” Stack Pointer %esp -4 11 15-410, F’13 IA32 Stack Popping Popping popl Dest Read memory at address given by %esp Increment %esp by 4 Store into Dest operand Stack Pointer %esp Stack Grows Down Increasing Addresses Stack “Top” Stack “Bottom” +4 12 15-410, F’13 %esp %eax %edx %esp %eax %edx %esp %eax %edx 0x104 555 0x108 0x108 0x10c 0x110 0x104 555 213 213 123 Stack Operation Examples 0x108 0x10c 0x110 555 213 123 0x108 4 pushl %eax 0x108 0x10c 0x110 213 123 0x104 213 popl %edx 8 213 15 15-410, F’13 %esp %eip 0x104 %esp %eip 0x80485910x8048591 0x1040x104 0x108 0x10c 0x110 0x8048553 123 Procedure Return Example 0x108 0x10c 0x110 123 ret 8048591: c3 ret 8 %eip is program counter 53 0x8048553 16 15-410, F’13 Stack-Based Languages Languages that support recursion e.g., C, Pascal, Java Code must be “reentrant” Multiple instantiations of a single procedure “live” at same time Need some place to store state of each instantiation Arguments Local variables Return pointer (maybe) Weird things (static links, exception handling, …) Stack discipline – key observation State for given procedure needed for limited time From time of call to time of return Note: callee returns before caller does Therefore stack allocated in nested frames State for single procedure instantiation 17 15-410, F’13 Call Chain Example Code Structure yoo(…) { • • who(); • • } who(…) { • • • amI(); • • • amI(); • • • } amI(…) { • • amI(); • • } yoo who amI amI amI Call Chain Procedure amI() recursive amI 20 15-410, F’13 swap() void swap(int *xp, int *yp) { int t0 = *xp; int t1 = *yp; *xp = t1; *yp = t0; } int zip1 = 15213; int zip2 = 91125; void call_swap() { swap(&zip1, &zip2); } call_swap: • • • pushl $zip2 # Global var pushl $zip1 # Global var call swap • • • &zip2 &zip1 Rtn adr %esp Resulting Stack • • • Calling swap from call_swap 21 15-410, F’13 swap() void swap(int *xp, int *yp) { int t0 = *xp; int t1 = *yp; *xp = t1; *yp = t0; } swap: pushl %ebp movl %esp,%ebp pushl %ebx movl 12(%ebp),%ecx movl 8(%ebp),%edx movl (%ecx),%eax movl (%edx),%ebx movl %eax,(%edx) movl %ebx,(%ecx) movl -4(%ebp),%ebx movl %ebp,%esp popl %ebp ret Body Set Up Finish Core 22 15-410, F’13 swap() Setup swap: pushl %ebp movl %esp,%ebp pushl %ebx &zip2 &zip1 Rtn adr %esp Entering Stack • • • %ebp 25 15-410, F’13 swap() Setup #3 swap: pushl %ebp movl %esp,%ebp pushl %ebx yp xp Rtn adr Old %ebp %ebp Resulting Stack • • • &zip2 &zip1 Rtn adr %esp Entering Stack • • • %ebp Old %ebx %esp 26 15-410, F’13 Effect of swap() Setup yp xp Rtn adr Old %ebp %ebp 0 4 8 12 Offset (relative to %ebp) Resulting Stack • • • &zip2 &zip1 Rtn adr %esp Entering Stack • • • %ebp Old %ebx %esp movl 12(%ebp),%ecx # get yp movl 8(%ebp),%edx # get xp . . . Body -4 27 15-410, F’13 swap() Finish #1 movl -4(%ebp),%ebx movl %ebp,%esp popl %ebp ret yp xp Rtn adr Old %ebp %ebp 0 4 8 12 Offset swap’s Stack • • • Old %ebx %esp-4 Observation Restoring saved register %ebx “Hold that thought” yp xp Rtn adr Old %ebp %ebp 0 4 8 12 Offset • • • Old %ebx %esp-4 30 15-410, F’13 swap() Finish #4 movl -4(%ebp),%ebx movl %ebp,%esp popl %ebp ret &zip2 &zip1 %esp Exiting Stack • • • %ebp Observation/query Saved & restored caller's register %ebx Didn't do so for %eax, %ecx, or %edx! yp xp Rtn adr %ebp 4 8 12 Offset swap’s Stack • • • %esp 31 15-410, F’13 Register Saving Conventions When procedure yoo() calls who(): yoo() is the caller, who() is the callee Can a register be used for temporary storage? Contents of register %edx overwritten by who() yoo: • • • movl $15213, %edx call who addl %edx, %eax • • • ret who: • • • movl 8(%ebp), %edx addl $91125, %edx • • • ret 32 15-410, F’13 Register Saving Conventions When procedure yoo() calls who(): yoo() is the caller, who() is the callee Can a register be used for temporary storage? Definitions “Caller Save” register Caller saves temporary in its frame before calling “Callee Save” register Callee saves temporary in its frame before using Conventions Which registers are caller-save, callee-save? 35 15-410, F’13 Before & After main() int main(int argc, char *argv[]) { if (argc > 1) { printf(“%s\n”, argv[1]); } else { char * av[3] = { 0, 0, 0 }; av[0] = argv[0]; av[1] = “Fred”; execvp(av[0], av); } return (0); } 36 15-410, F’13 The Mysterious Parts argc, argv Strings from one program Available while another program is running Which part of the memory map are they in? How did they get there? What happens when main() does “return(0)”??? There's no more program to run...right? Where does the 0 go? How does it get there? 410 students should seek to abolish mystery 37 15-410, F’13 The Mysterious Parts argc, argv Strings from one program Available while another program is running Inter-process sharing/information transfer is OS's job OS copies strings from old address space to new in exec() Traditionally placed “below bottom of stack” Other weird things (environment, auxiliary vector) (above argv) main() printf() .... arg vector 40 15-410, F’13 Project 0 - “Stack Crawler” C/Assembly function Can be called by any C function Prints stack frames in a symbolic way ---Stack Trace Follows--- Function fun3(c='c', d=2.090000), in Function fun2(f=35.000000), in Function fun1(count=0), in Function fun1(count=1), in Function fun1(count=2), in ... 41 15-410, F’13 Project 0 - “Stack Crawler” Conceptually easy Calling convention specifies layout of stack Stack is “just memory” - C happily lets you read & write Key questions How do I know 0x80334720 is “fun1”? How do I know fun3()'s second parameter is called “d”? 42 15-410, F’13 Project 0 “Data Flow” fun.c tb.c tb_globals.c symbol-table array many slots, blank 45 15-410, F’13 Project 0 “Data Flow” - P0 “Post-Linking” fun tb.o tb_globals.o fun.o debugger info simplify symtabgen mutate 46 15-410, F’13 Summary Review of stack knowledge What makes main() special Project 0 overview Look for handout this evening Start interviewing Project 2/3/4 partners!