lecture9 - CIS 450 Computer Architecture and Organization...

Info iconThis preview shows page 1. Sign up to view the full content.

View Full Document Right Arrow Icon
This is the end of the preview. Sign up to access the rest of the document.

Unformatted text preview: CIS 450 Computer Architecture and Organization Lecture 9: Defensive Programming Mitch Neilsen neilsen@ksu.edu 219D Nichols Hall Topics x86-64 Stack Discipline Argument passing in registers Minimizing stack usage Using stack pointer as only reference Debugging gdb Gnu DeBugger 2 x86-64 General Purpose Registers %rax %rbx %rcx %rdx %rsi %rdi %rsp %rbp %eax %ebx %ecx %edx %esi %edi %esp %ebp %r8 %r9 %r10 %r11 %r12 %r13 %r14 %r15 %r8d %r9d %r10d %r11d %r12d %r13d %r14d %r15d Twice the number of registers 3 Accessible as 8, 16, 32, or 64 bits x86-64 Register Conventions %rax %rbx %rcx %rdx %rsi %rdi %rsp %rbp Return Value Callee Saved Argument #4 Argument #3 Argument #2 Argument #1 Stack Pointer Callee Saved %r8 %r9 %r10 %r11 %r12 %r13 %r14 %r15 Argument #5 Argument #6 Callee Saved Used for linking C: Callee Saved Callee Saved Callee Saved Callee Saved 4 x86-64 Registers Arguments passed to functions via registers If more than 6 integral parameters, then pass rest on stack These registers can be used as caller-saved as well All References to Stack Frame via Stack Pointer Eliminates need to update %ebp Other Registers 6+1 callee saved 2 or 3 have special uses 5 x86-64 Long Swap void swap(long *xp, long *yp) { long t0 = *xp; long t1 = *yp; *xp = t1; *yp = t0; } swap: movq movq movq movq ret (%rdi), %rdx (%rsi), %rax %rax, (%rdi) %rdx, (%rsi) Operands passed in registers First (xp) in %rdi, second (yp) in %rsi 64-bit pointers No stack operations required Avoiding Stack Can hold all local information in registers 6 x86-64 Locals in the Red Zone /* Swap, using local array */ void swap_a(long *xp, long *yp) { volatile long loc[2]; loc[0] = *xp; loc[1] = *yp; *xp = loc[1]; *yp = loc[0]; } Avoiding Stack Pointer Change Can hold all information within small window beyond stack pointer swap_a: movq movq movq movq movq movq movq movq ret (%rdi), %rax %rax, -24(%rsp) (%rsi), %rax %rax, -16(%rsp) -16(%rsp), %rax %rax, (%rdi) -24(%rsp), %rax %rax, (%rsi) rtn Ptr -8 unused -16 loc[1] -24 loc[0] %rsp 7 x86-64 NonLeaf without Stack Frame long scount = 0; /* Swap a[i] & a[i+1] */ void swap_ele_se (long a, int i) { swap(&a[i], &a[i+1]); scount++; } No values held while swap being invoked No callee save registers needed swap_ele_se: movslq %esi,%rsi # Sign extend i leaq (%rdi,%rsi,8), %rdi # &a[i] leaq 8(%rdi), %rsi # &a[i+1] call swap # swap() incq scount(%rip) # scount++; ret 8 x86-64 Call using Jump long scount = 0; /* Swap a[i] & a[i+1] */ void swap_ele (long a, int i) { swap(&a[i], &a[i+1]); } When swap executes ret, it will return from swap_ele Possible since swap is a "tail call" swap_ele: movslq %esi,%rsi # Sign extend i leaq (%rdi,%rsi,8), %rdi # &a[i] leaq 8(%rdi), %rsi # &a[i+1] jmp swap # swap() 9 x86-64 Stack Frame Example long sum = 0; /* Swap a[i] & a[i+1] */ void swap_ele_su (long a, int i) { swap(&a[i], &a[i+1]); sum += a[i]; } Keeps values of a and i in callee save registers Must set up stack frame to save these registers swap_ele_su: movq %rbx, -16(%rsp) movslq %esi,%rbx movq %r12, -8(%rsp) movq %rdi, %r12 leaq (%rdi,%rbx,8), %rdi subq $16, %rsp leaq 8(%rdi), %rsi call swap movq (%r12,%rbx,8), %rax addq %rax, sum(%rip) movq (%rsp), %rbx movq 8(%rsp), %r12 addq $16, %rsp ret 10 Understanding x86-64 Stack Frame swap_ele_su: movq %rbx, -16(%rsp) # Save %rbx movslq %esi,%rbx # Extend & save i movq %r12, -8(%rsp) # Save %r12 movq %rdi, %r12 # Save a leaq (%rdi,%rbx,8), %rdi # &a[i] subq $16, %rsp # Allocate stack frame leaq 8(%rdi), %rsi # &a[i+1] call swap # swap() movq (%r12,%rbx,8), %rax # a[i] addq %rax, sum(%rip) # sum += a[i] movq (%rsp), %rbx # Restore %rbx movq 8(%rsp), %r12 # Restore %r12 addq $16, %rsp # Deallocate stack frame ret 11 Stack Operations movq movq %rbx, -16(%rsp) %r12, -8(%rsp) # Save %rbx # Save %r12 %rsp -8 -16 rtn Ptr %r12 %rbx subq $16, %rsp # Allocate stack frame rtn Ptr movq movq (%rsp), %rbx 8(%rsp), %r12 # Restore %rbx %rsp +8 %r12 %rbx # Restore %r12 addq 12 $16, %rsp # Deallocate stack frame Interesting Features of Stack Frame Allocate Entire Frame at Once All stack accesses can be relative to %rsp Do by decrementing stack pointer Can delay allocation, since safe to temporarily use red zone Simple Deallocation Increment stack pointer 13 x86-64 Procedure Summary Heavy Use of Registers Parameter passing More temporaries Minimal Use of Stack Sometimes none Allocate/deallocate entire block Many Tricky Optimizations What kind of stack frame to use Calling with jump Various allocation techniques 14 Defensive Programming 5-20 Bugs per 1000 lines of code (InfoWorld, Oct. 2003) Programmers must anticipate bugs, even if your code is bug-free. How? Check for errors at all possible opportunities: detecting bugs early eases finding the root cause. Maintain a clean, modular structure with documented interfaces: goto's, global variables, long-jumps, clever/obscure macros, etc. considered harmful dangerous. Anticipate common errors: buffer overrun, off-by-one,... Consider corner cases: 0/1 loops, empty lists, ... Provide debugging support in your program: debugging messages, data structure checkers (like the Heap-checker from the malloc-lab), print-function for complicated structures, test-case generators, ... Add redundancy Maintain test cases for regression testing: use version control systems (CVS, RCS, BitKeeper, Subversion, ...) Use all the help you can get: heed compiler warnings, use debuggers, verifyers, IDE's, code generators, high-level tools,... 15 Assertions Explicitly state what you expect to be true in your program: invariants, argument ranges, etc. Assert-macro (ISO9899, ANSI C): #define MAX_ARRAY_SIZE 10 void foo(double a, double b, int n) { int i; double *a_ptr = a, *b_ptr = b; assert(n > 1 && n <= MAX_ARRAY_SIZE); for (i = n; --i;) { /* ... */ a_ptr++; /* ... */ b_ptr++; } assert(a_ptr == &(a[n]) && b_ptr == &(b[n])); 16 } #include <assert.h> Generates no tests if "NODEBUG" is defined Assertions (cont.) Reasons for using assertions: Catch failures early Verify & document interfaces Express invariants to aid debugging 17 Debug Messages Use of cpp-macros and conditional compilation: #ifdef DEBUG extern int debug_level; #define DEBUG_PRINT(level, format, args...) \ { if((level) < debug_level) {\ fprintf(stderr, "DEBUG_PRINT line=%d in file='%s':\n",\ __LINE__, __FILE__);\ fprintf(stderr, format , ## args);}\ } #else #define DEBUG_PRINT(level, format, args...) #endif foo(int a, int b) { DEBUG_PRINT(0, "foo(a=%d, b=%d) started\n", a, b); } 18 Add Redundancy Engineering tradeoff between robustness and performance. Extreme case Google: Data structures have software maintained checksums Distributed system (> 10,000 machines): need fail-stop characteristic, handle failures at higher level Simple Cases: Count item and compare to pointer difference (see assertion example) Compute simple, inexpensive invariants (for example: the sum of allocated and free memory objects in the heap ought to equal the heap size) 19 Integrated Development Environment Program-editor (with syntax support), version control system, compiler, debugger, build-system, profiler, graphical user interface, and integration = IDE Microsoft Visual-* IBM's Eclipse project Kdevelop (open source) Pro: convenience Con: often platform dependent No silver bullet 20 Debugging History In 1945 Grace Hopper found the first "bug" in IBM's Harvard Mark I, an electro-mechanical computer: 21 Early Debugging Use of front pannel switches & lights: Other tools included: Core dumps Print statements Hardware monitors Speakers 22 Know your Bugs Common bugs in C-programs Pointer bugs Dynamic memory allocation / deallocation bugs Memory leaks (missing / extra free()calls) Buffer overflow bugs Arrays out of bound errors (off-by-one) Exception handling Variable scope problems (see linking lecture) Race conditions in multi-threaded codes Other bugs not considered in this class: Specification errors Performance bugs Program logic errors (bad algorithms, data structures, etc.) 23 Encounter with a Bug Program produces unexpected result and/or crashes Is this behavior reproducible? Does it depend on input data? Does it change with compilation options? (-g vs. O2) First goal: narrow the possible code range that could be responsible for the bug: Divide & Conquer Simplify the code that shows the bug In case of rare/intermittent bugs: try to cause the program to fail more frequently Add logging or debugging printouts to pinpoint the approximate location of the failure 24 GDB (GNU DeBugger) Basic functionality: Can run programs in an observable environment Uses ptrace-interface to insert breakpoint, single step, inspect & change registers and variables Does not require compilation with "-g", but works much better if it has the symbol tables available Maintains source line numbers and can inspect source files Ability to attach to a running process Ability to watch memory locations Conditional breakpoints Some graphical user interfaces exist (DDD, KDbg, ...) 25 DDD Graphical front-end to GDB with extended data visualization support: http://www.gnu.org/software/ddd 26 Debugging What can debuggers do? Run programs Make the program stops on specified places or on specified conditions Give information about current variables' values, the memory and the stack Let you examine the program execution step by step - stepping Let you examine the change of program variables' values - tracing To be able to debug your program, you should compile it with the -g option (generates the symbol table) ! $ gcc g o myProg myProg.c 27 GDB - Freeware GNU Debugger Starting GDB: $ gdb Loading the executable code and symbol table (if available): > file myProg Start GDB and load the symbol table in one step: $ gdb myProg Exit GDB: > quit Executing shell commands: make is a special case: > shell command args > make args 28 GDB Commands Command names may be truncated if the abbreviation is unambiguous: s (for step), r (for run) UNIX style TAB completion for the command names. Alternative way: > complete chars. results in: Ex.: > complete h handle hbreak help Getting help: help (or h) lists all classes of commands. h command - displays a short description of the command 29 GDB Running Programs Running a program: > run (or r) -- creates an inferior process that runs your program. if there are no execution errors the program will finish and results will be displayed in case of error, the GDB will show: - the line the program has stopped on and - a short description of what it believes has caused the error There is a certain information that affects the execution of a program: program's arguments program's environment program's working directory standard input and output 30 GDB Program's arguments Specifying command-line arguments for your program: As arguments to run: With set args command: Notes: > run without arguments uses the same arguments used by the previous run. > set args without arguments removes all arguments. > show args command shows the arguments your program has been started with. > run arg1 arg2 ... > set args arg1 arg2 ... 31 GDB Program's environment Changing the PATH environment variable: > path dir add the directory dir at the beginning of the PATH variable. You may specify several directory names separated by `:' or white space. > show paths displays the search paths for executables. Changing the working directory: > cd dir to change the working directory Redirecting output: > run > outfile - direct the output to the file outfile. 32 GDB -- Debugging an already-running process Debugging an already-running process From inside GDB: > attach process-id / To get the process ID use the UNIX command ps / From outside GDB: > gdb myPprog process-id The first thing GDB does after arranging to debug the specified process is to stop it. > detach detaches the currently attached process from the GDB control. A detached process continues its own execution. 33 GDB Breakpoints and watchpoints Breakpoints and watchpoints allow you to specify the places or the conditions where you want your program to stop. > break arg stops when the execution reaches the specified line / arg function name, line number, +/- offset / > watch expr stops whenever the value of the expression changes > clear [arg] Without arguments deletes any breakpoint at the next instruction to be executed in the current stack frame > delete [bnum] Without arguments deletes all breakpoints. 34 GDB Examining variables Global variables can be examined from every point in the source file. Local variables can be examined only in their scope or using: file::variable or function::variable The variable type: Current value: Automatic display: > ptype var > print var > display var - adds var to the automatic display list. > undisplay dnum ___________________________________________________ Specifying the output format (x, o, d, u, t, a, f, and c) : > print /t var - prints the value of var in binary format 35 GDB Value history The value history keeps the values printed by the print command. Previously printed values can be accessed by typing $ followed by their history number. $ - refers to the most recent value and $$n - refers to the n-th value from the end. > show values [n|+] Without argument the last 10 values. n 10 values centered around n + 10 values after the last printed 36 GDB Stepping through the program > step [count] program execution continue to next source line going into function calls. > next [count] program execution continue to the next source line omitting function calls. > continue resume program execution > until continue until the next source line in the current stack frame is reached. /useful to exit from loops/ 37 GDB Altering execution Returning from a function > finish - forced return > return [ret_value] pops the current stack frame Continuing at different address > jump line_num | *address Altering the value of a variable > set i=256 Proceeding to a specified point: > until [line_num | *address | function_name] 38 GDB The stack frame Stack frames are identified by their addresses, which are kept in the frame pointer register. Selecting a frame: > frame n|addr > up n 0 1 2 > down n Information about the current frame > frame brief description > info args shows function arguments > info locals shows local variables 39 GDB Convenience variables Convenience variables are used to store values that you may want to refer later. Any string preceded by $ is regarded as a convenience variable. Ex.: $table = *table_ptr There are several automatically created convenience variables: $pc program counter $sp stack pointer $fp frame pointer $ps processor status $_ - contains the last examined address $__ - the value in the last examined address $_exitcode - the exit code of the debugged program 40 DDD - The Data Display Debugger DDD is a GUI debugger that can work with several inferior debuggers including GDB. GDB commands can be typed in the debugger console window. DDD sets some GDB settings automatically and will not work correctly if you change them. These are: set height 0 set width 0 set verbose off set prompt (gdb) ! 41 DDD View argument field command tool source window debugger console 42 DDD GUI Advantages Frequently used commands are on the toolbars, have assigned shortcut keys or can be done just with a mouse click. Easy browsing through the source ! Examining current variables values directly by placing the mouse pointer over them. Possibility to graphically display the program data. Help menu. 43 DDD Command menu 44 GDB Examining memory The x command (for "examine"): > x/nfu addr specify the number of units (n), the display format (f) and the unit size (u) of the memory you want to examine, starting from the address addr. Unit size can be b, h (half), w and g (giant). > x addr start printing from the address addr, others default > x all default Registers Registers names are different for each machine. Use > info registers to see the names used on your machine. GDB has four "standard" registers names that are available on most machines: program counter, stack pointer, frame pointer and processor status. 45 GDB Additional process information > info proc summarize available information about the current process. > info proc mappings address range accessible in the program. > info proc times starting time, user CPU time and system CPU time for your program and its children. > help info > info signals information about the system signals and how GDB handles them. 46 The Binary Bomb Lab Your task is to use GDB to diffuse a binary bomb! Good luck!!! 47 ...
View Full Document

This note was uploaded on 04/09/2008 for the course CIS 450 taught by Professor Neilsen,mitch during the Spring '08 term at Kansas State University.

Ask a homework question - tutors are online