The document provides an introduction to debuggers, focusing on using gdb to debug a simple C program called crash1.c that has two bugs. It explains how to compile the program with debugging information, run it in gdb, and diagnose the segmentation fault that occurs when the program is executed without command line arguments. The guide details the use of various gdb commands to inspect the state of the program and locate errors, emphasizing the importance of proper compilation for effective debugging.
Overview of debugging, mentioning Grace Hopper as the first documented bug case.
Saumil Shah introduces himself as the CEO of Net-square, with credentials in computer science from Purdue University.
An introduction to the concept of debuggers and their functionalities.
Definition of a debugger, detailing its control over process execution, CPU state, and memory inspection.
Various functionalities provided by debuggers, with examples such as gdb and windbg.
Engagement in practical usage of debuggers through a code example using crash1.c and identifying bugs.Introduction of gdb as the chosen debugger to debug crash1.c, noting its initial complexity but power.
Instructions on compiling crash1.c and running it within gdb, leading to a segmentation fault.
Determination of crash point using gdb commands, identifying that the crash occurs post-atoi() call.
Learning how to examine memory contents at the crash point using gdb commands.
Inspection of registers and local variables to determine the cause of the segmentation fault.
Use of gdb commands to inspect local variable information, noting absence of debugging info.
Guidance on recompiling crash1.c with debugging info to resolve symbol issues.
Utilization of gdb commands to view program listing to locate the point of crash.
Instruction on setting breakpoints in gdb to better observe program execution flow.
Usage of the print command in gdb to check variable values at breakpoints.
Identification of two bugs with detailed analysis of the first bug regarding null pointers.
Engagement in identifying the second bug related to pointer assignments and memory referencing.
Discussion of assembly level instructions related to encountered bugs in program execution.
The mechanics of crashes in programming, specifically linked to memory management issues.
Summary of debugging lessons learned, commands used, and understanding of process crashes.
What is adebugger?A program used for debugging other programs or process. It provides...
8.
What is adebugger?A program used for debugging other programs or process. It provides...Fine grained control over process executionInspection of CPU stateInspection of process memory
crash1.cint main(int argc,char *argv[]){ int number; int *pointer; number = atoi(argv[1]); pointer = number; printnum(pointer);}void printnum(int *x){ printf("The number supplied is %d\n", *x);}
What does crash1.cdo?crash1 takes the first command line argument and converts it to an integer
17.
What does crash1.cdo?crash1 takes the first command line argument and converts it to an integerIt then assigns a pointer to this integer......and passes it to a function - printnum()
18.
What does crash1.cdo?crash1 takes the first command line argument and converts it to an integerIt then assigns a pointer to this integer......and passes it to a function - printnum()There are TWO bugs in this programCan you spot them?
Compile crash1.c andload it using gdb$ gcc crash1.c -o crash1$ gdb crash1GNU gdb (GDB) 7.2Copyright (C) 2010 Free Software Foundation, Inc.License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>This is free software: you are free to change and redistribute it.There is NO WARRANTY, to the extent permitted by law. Type "show copying"and "show warranty" for details.This GDB was configured as "i686-pc-linux-gnu".For bug reporting instructions, please see:<http://www.gnu.org/software/gdb/bugs/>...Reading symbols from /home/user0/crash1...done.(gdb)
Now run it......withno command line arguments.(gdb) runStarting program: /home/user0/crash1 Program received signal SIGSEGV, Segmentation fault.0x40044c2e in __strtol_internal () from /lib/i686/libc.so.6
29.
Now run it......withno command line arguments.(gdb) runStarting program: /home/user0/crash1 Program received signal SIGSEGV, Segmentation fault.0x40044c2e in __strtol_internal () from /lib/i686/libc.so.6The program crashes.
30.
Now run it......withno command line arguments.(gdb) runStarting program: /home/user0/crash1 Program received signal SIGSEGV, Segmentation fault.0x40044c2e in __strtol_internal () from /lib/i686/libc.so.6The program crashes.Where in the code did it crash?
31.
Now run it......withno command line arguments.(gdb) runStarting program: /home/user0/crash1 Program received signal SIGSEGV, Segmentation fault.0x40044c2e in __strtol_internal () from /lib/i686/libc.so.6The program crashes.Where in the code did it crash?Let us find out where exactly it has crashed.
Use gdb command"backtrace"It tries to reconstruct frames on the stack.We can find out the sequence of function calls at the time of the crash.
34.
Use gdb command"backtrace"It tries to reconstruct frames on the stack.We can find out the sequence of function calls at the time of the crash.(gdb) backtrace#0 0x40044c2e in __strtol_internal () from /lib/i686/libc.so.6#1 0x40042579 in atoi () from /lib/i686/libc.so.6#2 0x0804838c in main ()
35.
Use gdb command"backtrace"It tries to reconstruct frames on the stack.We can find out the sequence of function calls at the time of the crash.(gdb) backtrace#0 0x40044c2e in __strtol_internal () from /lib/i686/libc.so.6#1 0x40042579 in atoi () from /lib/i686/libc.so.6#2 0x0804838c in main ()Looks like it crashed after calling atoi().
36.
Use gdb command"backtrace"It tries to reconstruct frames on the stack.We can find out the sequence of function calls at the time of the crash.(gdb) backtrace#0 0x40044c2e in __strtol_internal () from /lib/i686/libc.so.6#1 0x40042579 in atoi () from /lib/i686/libc.so.6#2 0x0804838c in main ()Looks like it crashed after calling atoi().That's right. Let us check out the instructions in the code where it has crashed. EIP points to the last instruction executed.
"x" to examinememory(gdb) x/10i $eip=> 0x40044c2e: movzx ecx,BYTE PTR [edi] 0x40044c31: mov eax,DWORD PTR [esi] 0x40044c33: movsx edx,cl 0x40044c36: movzx eax,WORD PTR [eax+edx*2] 0x40044c3a: and eax,0x2000 0x40044c3f: test ax,ax
39.
"x" to examinememory(gdb) x/10i $eip=> 0x40044c2e: movzx ecx,BYTE PTR [edi] 0x40044c31: mov eax,DWORD PTR [esi] 0x40044c33: movsx edx,cl 0x40044c36: movzx eax,WORD PTR [eax+edx*2] 0x40044c3a: and eax,0x2000 0x40044c3f: test ax,axSo what is x/10i ?
40.
"x" to examinememory(gdb) x/10i $eip=> 0x40044c2e: movzx ecx,BYTE PTR [edi] 0x40044c31: mov eax,DWORD PTR [esi] 0x40044c33: movsx edx,cl 0x40044c36: movzx eax,WORD PTR [eax+edx*2] 0x40044c3a: and eax,0x2000 0x40044c3f: test ax,axSo what is x/10i ?"x" displays memory contents in various formats. "i" is for instructions (disassembly). 10 is the count of instructions to disassemble.Here are some more options for "x"
Where did thefault occur?Let us see the faulting instruction again.
44.
Where did thefault occur?Let us see the faulting instruction again.(gdb) x/10i $eip=> 0x40044c2e: movzx ecx,BYTE PTR [edi]
45.
Where did thefault occur?Let us see the faulting instruction again.(gdb) x/10i $eip=> 0x40044c2e: movzx ecx,BYTE PTR [edi]movzx ecx, byte ptr [edi] takes the byte at memory address stored within EDI and copies it into the ECX register.
46.
Where did thefault occur?Let us see the faulting instruction again.(gdb) x/10i $eip=> 0x40044c2e: movzx ecx,BYTE PTR [edi]movzx ecx, byte ptr [edi] takes the byte at memory address stored within EDI and copies it into the ECX register.I see no apparent error here.
47.
Where did thefault occur?Let us see the faulting instruction again.(gdb) x/10i $eip=> 0x40044c2e: movzx ecx,BYTE PTR [edi]movzx ecx, byte ptr [edi] takes the byte at memory address stored within EDI and copies it into the ECX register.I see no apparent error here.It depends on where EDI points to. Let us inspect the registers.
Use the "inforegisters" command.(gdb) info registerseax 0x40136660 0x40136660ecx 0x0 0x0edx 0x0 0x0ebx 0x40148f50 0x40148f50esp 0xbffff8d0 0xbffff8d0ebp 0xbffff928 0xbffff928esi 0x4014b8b8 0x4014b8b8edi 0x0 0x0eip 0x40044c2e 0x40044c2e <__strtol_internal+142>eflags 0x10206 [ PF IF RF ]
50.
Use the "inforegisters" command.(gdb) info registerseax 0x40136660 0x40136660ecx 0x0 0x0edx 0x0 0x0ebx 0x40148f50 0x40148f50esp 0xbffff8d0 0xbffff8d0ebp 0xbffff928 0xbffff928esi 0x4014b8b8 0x4014b8b8edi 0x0 0x0eip 0x40044c2e 0x40044c2e <__strtol_internal+142>eflags 0x10206 [ PF IF RF ]I see that EDI is 0.
51.
Use the "inforegisters" command.(gdb) info registerseax 0x40136660 0x40136660ecx 0x0 0x0edx 0x0 0x0ebx 0x40148f50 0x40148f50esp 0xbffff8d0 0xbffff8d0ebp 0xbffff928 0xbffff928esi 0x4014b8b8 0x4014b8b8edi 0x0 0x0eip 0x40044c2e 0x40044c2e <__strtol_internal+142>eflags 0x10206 [ PF IF RF ]I see that EDI is 0.EDI is a NULL pointer. It points to non-existent memory. Hence the crash.
52.
Let us tryand inspect local variables and arguments, if any.
53.
Let us tryand inspect local variables and arguments, if any.Use the "info locals" and "info args" commands.
54.
Let us tryand inspect local variables and arguments, if any.Use the "info locals" and "info args" commands.(gdb) info locals No symbol table info available.(gdb) info args No symbol table info available.
55.
Let us tryand inspect local variables and arguments, if any.Use the "info locals" and "info args" commands.(gdb) info locals No symbol table info available.(gdb) info args No symbol table info available.What does this mean?
56.
Let us tryand inspect local variables and arguments, if any.Use the "info locals" and "info args" commands.(gdb) info locals No symbol table info available.(gdb) info args No symbol table info available.What does this mean?The compiled binary does not contain debugging information to resolve symbols.
57.
Let us tryand inspect local variables and arguments, if any.Use the "info locals" and "info args" commands.(gdb) info locals No symbol table info available.(gdb) info args No symbol table info available.What does this mean?The compiled binary does not contain debugging information to resolve symbols. We need to compile the binary again, this time with proper debugging information.
Quit the debugger(gdb)qRecompile with debugging information enabled.$ gcc -g crash1.c -o crash1
60.
Quit the debugger(gdb)qRecompile with debugging information enabled.$ gcc -g crash1.c -o crash1The "-g" flag tells the compiler to include symbolic debugging information in the compiled binary.
Load crash1 ingdb again$ gdb crash1GNU gdb (GDB) 7.2Copyright (C) 2010 Free Software Foundation, Inc.License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>This is free software: you are free to change and redistribute it.There is NO WARRANTY, to the extent permitted by law. Type "show copying"and "show warranty" for details.This GDB was configured as "i686-pc-linux-gnu".For bug reporting instructions, please see:<http://www.gnu.org/software/gdb/bugs/>...Reading symbols from /home/user0/crash1...done.(gdb)
63.
Load crash1 ingdb again$ gdb crash1GNU gdb (GDB) 7.2Copyright (C) 2010 Free Software Foundation, Inc.License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>This is free software: you are free to change and redistribute it.There is NO WARRANTY, to the extent permitted by law. Type "show copying"and "show warranty" for details.This GDB was configured as "i686-pc-linux-gnu".For bug reporting instructions, please see:<http://www.gnu.org/software/gdb/bugs/>...Reading symbols from /home/user0/crash1...done.(gdb)Let us look at the program listing, which is now available from the debugging information.
Use gdb's "list"command(gdb) list1 #include <stdio.h>2 3 void printnum(int *x);4 5 int main(int argc, char *argv[])6 {7 int number;8 int *pointer;9 10 number = atoi(argv[1]);
66.
Use gdb's "list"command(gdb) list1 #include <stdio.h>2 3 void printnum(int *x);4 5 int main(int argc, char *argv[])6 {7 int number;8 int *pointer;9 10 number = atoi(argv[1]);But there are more than 10 lines in this program.
67.
Use gdb's "list"command(gdb) list1 #include <stdio.h>2 3 void printnum(int *x);4 5 int main(int argc, char *argv[])6 {7 int number;8 int *pointer;9 10 number = atoi(argv[1]);But there are more than 10 lines in this program.Press Enter on a blank gdb prompt to get another screenful of program listing.
RecapWe know thatthe program crashed when executing atoi(argv[1]).We shall now set a breakpoint at the statement where atoi() is called.
70.
RecapWe know thatthe program crashed when executing atoi(argv[1]).We shall now set a breakpoint at the statement where atoi() is called.atoi() is called in line #10:7 int number;8 int *pointer;9 10 number = atoi(argv[1]);
Use gdb's "break"command to set a breakpoint.(gdb) break 10Breakpoint 1 at 0x804837c: file crash1.c, line 10.
73.
Use gdb's "break"command to set a breakpoint.(gdb) break 10Breakpoint 1 at 0x804837c: file crash1.c, line 10.Now let us run the program.
74.
Use gdb's "break"command to set a breakpoint.(gdb) break 10Breakpoint 1 at 0x804837c: file crash1.c, line 10.Now let us run the program.(gdb) runStarting program: /home/user0/crash1 Breakpoint 1, main (argc=0x1, argv=0xbffff9b4) at crash1.c:1010 number = atoi(argv[1]);
75.
Use gdb's "break"command to set a breakpoint.(gdb) break 10Breakpoint 1 at 0x804837c: file crash1.c, line 10.Now let us run the program.(gdb) runStarting program: /home/user0/crash1 Breakpoint 1, main (argc=0x1, argv=0xbffff9b4) at crash1.c:1010 number = atoi(argv[1]);Process execution is suspended when it reaches the breakpoint. Control is transferred to gdb.
76.
Use gdb's "break"command to set a breakpoint.(gdb) break 10Breakpoint 1 at 0x804837c: file crash1.c, line 10.Now let us run the program.(gdb) runStarting program: /home/user0/crash1 Breakpoint 1, main (argc=0x1, argv=0xbffff9b4) at crash1.c:1010 number = atoi(argv[1]);Process execution is suspended when it reaches the breakpoint. Control is transferred to gdb.Let us now look at argv[1]. gdb will now allow us to inspect variables symbolically.
gdb's "print" commandlets us inspect variables.(gdb) print argv[1]$1 = 0x0argv[1] is the culprit NULL pointer! This is what gets loaded into the EDI register (remember?)
80.
gdb's "print" commandlets us inspect variables.(gdb) print argv[1]$1 = 0x0argv[1] is the culprit NULL pointer! This is what gets loaded into the EDI register (remember?)Let us continue with the process execution.
81.
gdb's "print" commandlets us inspect variables.(gdb) print argv[1]$1 = 0x0argv[1] is the culprit NULL pointer! This is what gets loaded into the EDI register (remember?)Let us continue with the process execution.(gdb) continueContinuing.Program received signal SIGSEGV, Segmentation fault.0x40044c2e in __strtol_internal () from /lib/i686/libc.so.6
82.
gdb's "print" commandlets us inspect variables.(gdb) print argv[1]$1 = 0x0argv[1] is the culprit NULL pointer! This is what gets loaded into the EDI register (remember?)Let us continue with the process execution.(gdb) continueContinuing.Program received signal SIGSEGV, Segmentation fault.0x40044c2e in __strtol_internal () from /lib/i686/libc.so.6As expected, here's the segmentation fault. Verify the value of EDI using "info registers" and the disassembly of the crash using "x/10i $eip"
83.
Bug #1 -Null pointerTo fix this problem the programmer needs to check the number of command line arguments before using argv[1] in the program.
84.
Bug #1 -Null pointerTo fix this problem the programmer needs to check the number of command line arguments before using argv[1] in the program.For now, we shall run the program with a valid argv[1] supplied.
85.
Bug #1 -Null pointerTo fix this problem the programmer needs to check the number of command line arguments before using argv[1] in the program.For now, we shall run the program with a valid argv[1] supplied.On to bug #2.Quit gdb and load crash1 again.
Load crash1 ingdb again.$ gdb crash1GNU gdb (GDB) 7.2...Reading symbols from /home/user0/crash1...done.(gdb)Run it with argument 1 as 255 (or any number)(gdb) run 255Starting program: /home/user0/crash1 255Program received signal SIGSEGV, Segmentation fault.0x080483b4 in printnum (x=0xff) at crash1.c:1717 printf("The number supplied is %d\n", *x);
88.
Load crash1 ingdb again.$ gdb crash1GNU gdb (GDB) 7.2...Reading symbols from /home/user0/crash1...done.(gdb)Run it with argument 1 as 255 (or any number)(gdb) run 255Starting program: /home/user0/crash1 255Program received signal SIGSEGV, Segmentation fault.0x080483b4 in printnum (x=0xff) at crash1.c:1717 printf("The number supplied is %d\n", *x);Another segmentation fault. Another crash.
What do wedo now?I thought I asked the questions!We see where we crashed by examining frames from the stack. The "backtrace" command.(gdb) backtrace#0 0x080483b4 in printnum (x=0xff) at crash1.c:17#1 0x080483a3 in main (argc=0x2, argv=0xbffff9b4) at crash1.c:12
92.
What do wedo now?I thought I asked the questions!We see where we crashed by examining frames from the stack. The "backtrace" command.(gdb) backtrace#0 0x080483b4 in printnum (x=0xff) at crash1.c:17#1 0x080483a3 in main (argc=0x2, argv=0xbffff9b4) at crash1.c:12We crashed inside printnum(). Let us inspect the arguments passed to printnum().
93.
What do wedo now?I thought I asked the questions!We see where we crashed by examining frames from the stack. The "backtrace" command.(gdb) backtrace#0 0x080483b4 in printnum (x=0xff) at crash1.c:17#1 0x080483a3 in main (argc=0x2, argv=0xbffff9b4) at crash1.c:12We crashed inside printnum(). Let us inspect the arguments passed to printnum().(gdb) info argsx = 0xff
94.
What do wedo now?I thought I asked the questions!We see where we crashed by examining frames from the stack. The "backtrace" command.(gdb) backtrace#0 0x080483b4 in printnum (x=0xff) at crash1.c:17#1 0x080483a3 in main (argc=0x2, argv=0xbffff9b4) at crash1.c:12We crashed inside printnum(). Let us inspect the arguments passed to printnum().(gdb) info argsx = 0xffIsn't x a pointer to an integer (int *x)?
That's right. xis an integer pointer, set to 0xff.So it points to memory address 0x000000ff?
97.
That's right. xis an integer pointer, set to 0xff.So it points to memory address 0x000000ff?Yes. This memory cannot be referenced. Fetching its contents (*x) results in an error.
98.
That's right. xis an integer pointer, set to 0xff.So it points to memory address 0x000000ff?Yes. This memory cannot be referenced. Fetching its contents (*x) results in an error.How did x get set to 0x000000ff?
99.
That's right. xis an integer pointer, set to 0xff.So it points to memory address 0x000000ff?Yes. This memory cannot be referenced. Fetching its contents (*x) results in an error.How did x get set to 0x000000ff?The answer lies in how printnum() was called.
100.
That's right. xis an integer pointer, set to 0xff.So it points to memory address 0x000000ff?Yes. This memory cannot be referenced. Fetching its contents (*x) results in an error.How did x get set to 0x000000ff?The answer lies in how printnum() was called.Let us switch to its calling frame - frame 1 - and inspect frame 1's local variables.
gdb's "frame <n>"command lets you switch context to other frames.(gdb) frame 1#1 0x080483a3 in main (argc=0x2, argv=0xbffff9b4) at crash1.c:1212 printnum(pointer);
103.
gdb's "frame <n>"command lets you switch context to other frames.(gdb) frame 1#1 0x080483a3 in main (argc=0x2, argv=0xbffff9b4) at crash1.c:1212 printnum(pointer);Inspect frame 1's local variables.
104.
gdb's "frame <n>"command lets you switch context to other frames.(gdb) frame 1#1 0x080483a3 in main (argc=0x2, argv=0xbffff9b4) at crash1.c:1212 printnum(pointer);Inspect frame 1's local variables.(gdb) info localsnumber = 0xffpointer = 0xff
105.
gdb's "frame <n>"command lets you switch context to other frames.(gdb) frame 1#1 0x080483a3 in main (argc=0x2, argv=0xbffff9b4) at crash1.c:1212 printnum(pointer);Inspect frame 1's local variables.(gdb) info localsnumber = 0xffpointer = 0xffDo you see the second bug now?
106.
gdb's "frame <n>"command lets you switch context to other frames.(gdb) frame 1#1 0x080483a3 in main (argc=0x2, argv=0xbffff9b4) at crash1.c:1212 printnum(pointer);Inspect frame 1's local variables.(gdb) info localsnumber = 0xffpointer = 0xffDo you see the second bug now?We are reading the number 255 (0xff) and assigning it to the pointer directly.
Absolutely correct. Whatshould we do instead?Make the pointer POINT to the number.Set the pointer's value to be the ADDRESS of the number and not its value.
Bug #2 -Pointer mess-upThe faulting statement is:pointer = number;Instead it should be:pointer = &number; //address of number
112.
Bug #2 -Pointer mess-upThe faulting statement is:pointer = number;Instead it should be:pointer = &number; //address of numberLet us see what happens at assembly level.Dump instructions at EIP and inspect the registers.
(gdb) frame 0(gdb)x/10i $eip=> 0x80483b4 <printnum+12>: push DWORD PTR [eax] 0x80483b6 <printnum+14>: push 0x8048488 0x80483bb <printnum+19>: call 0x804828c <printf@plt> 0x80483c0 <printnum+24>: add esp,0x10 0x80483c3 <printnum+27>: leave 0x80483c4 <printnum+28>: ret (gdb) info registerseax 0xff 0xffecx 0x0 0x0edx 0x0 0x0ebx 0x40148f50 0x40148f50esp 0xbffff938 0xbffff938ebp 0xbffff948 0xbffff948esi 0x40012780 0x40012780edi 0xbffff9b4 0xbffff9b4eip 0x80483b4 0x80483b4 <printnum+12>eflags 0x10292 [ AF SF IF RF ]We are trying to push a value whose address is stored in EAX. This address is 0x000000ff.
117.
There are twoPUSHes. The first pushes the contents at address EAX onto the stack.
118.
There are twoPUSHes. The first pushes the contents at address EAX onto the stack.EAX stores the address of the pointer x.
119.
There are twoPUSHes. The first pushes the contents at address EAX onto the stack.EAX stores the address of the pointer x.DWORD PTR [EAX] implies *x (contents at addr x)
120.
There are twoPUSHes. The first pushes the contents at address EAX onto the stack.EAX stores the address of the pointer x.DWORD PTR [EAX] implies *x (contents at addr x)What does the second PUSH do? push 0x08048488
121.
There are twoPUSHes. The first pushes the contents at address EAX onto the stack.EAX stores the address of the pointer x.DWORD PTR [EAX] implies *x (contents at addr x)What does the second PUSH do? push 0x080484880x08048488 looks like a memory address. Notice that the next instruction is a CALL to printf.=> 0x80483b4 <printnum+12>: push DWORD PTR [eax] 0x80483b6 <printnum+14>: push 0x8048488 0x80483bb <printnum+19>: call 0x804828c <printf@plt>
122.
There are twoPUSHes. The first pushes the contents at address EAX onto the stack.EAX stores the address of the pointer x.DWORD PTR [EAX] implies *x (contents at addr x)What does the second PUSH do? push 0x080484880x08048488 looks like a memory address. Notice that the next instruction is a CALL to printf.=> 0x80483b4 <printnum+12>: push DWORD PTR [eax] 0x80483b6 <printnum+14>: push 0x8048488 0x80483bb <printnum+19>: call 0x804828c <printf@plt>The two PUSHes set up the parameters passed to printf().
So where doesaddress 0x08048488 point to?It should point to the string:"The number supplied is %d\n"
130.
So where doesaddress 0x08048488 point to?It should point to the string:"The number supplied is %d\n"Let us use the "x" command and find out. We shall use "x/s" to display the output as a string.
131.
So where doesaddress 0x08048488 point to?It should point to the string:"The number supplied is %d\n"Let us use the "x" command and find out. We shall use "x/s" to display the output as a string.(gdb) x/s 0x080484880x8048488: "The number supplied is %d\n"
132.
Disassembling printnum()To wrapthis up, let us dive into the assembly code of function printnum().We shall map out the concepts discussed in "HOW FUNCTIONS WORK".
Use the "disassemble"command(gdb) disassemble printnumDump of assembler code for function printnum: 0x080483a8 <+0>: push ebp 0x080483a9 <+1>: mov ebp,esp 0x080483ab <+3>: sub esp,0x8 0x080483ae <+6>: sub esp,0x8 0x080483b1 <+9>: mov eax,DWORD PTR [ebp+0x8]=> 0x080483b4 <+12>: push DWORD PTR [eax] 0x080483b6 <+14>: push 0x8048488 0x080483bb <+19>: call 0x804828c <printf@plt> 0x080483c0 <+24>: add esp,0x10 0x080483c3 <+27>: leave 0x080483c4 <+28>: ret End of assembler dump.
135.
Use the "disassemble"command(gdb) disassemble printnumDump of assembler code for function printnum: 0x080483a8 <+0>: push ebp 0x080483a9 <+1>: mov ebp,esp 0x080483ab <+3>: sub esp,0x8 0x080483ae <+6>: sub esp,0x8 0x080483b1 <+9>: mov eax,DWORD PTR [ebp+0x8]=> 0x080483b4 <+12>: push DWORD PTR [eax] 0x080483b6 <+14>: push 0x8048488 0x080483bb <+19>: call 0x804828c <printf@plt> 0x080483c0 <+24>: add esp,0x10 0x080483c3 <+27>: leave 0x080483c4 <+28>: ret End of assembler dump.Let us map this disassembly to the various components of a function.
136.
printnum() disassemblyPrologue push ebp mov ebp,esp sub esp,0x8 sub esp,0x8 mov eax,DWORD PTR [ebp+0x8] push DWORD PTR [eax] push 0x8048488 call 0x804828c <printf@plt> add esp,0x10 leave ret BodyEpilogueReturn
137.
printnum() disassemblyPrologue push ebp mov ebp,esp sub esp,0x8 sub esp,0x8 mov eax,DWORD PTR [ebp+0x8]> push DWORD PTR [eax] push 0x8048488 call 0x804828c <printf@plt> add esp,0x10 leave ret BodyEpilogueReturnCrash occurs at "push dword ptr [eax]".
138.
printnum() disassemblyPrologue push ebp mov ebp,esp sub esp,0x8 sub esp,0x8 mov eax,DWORD PTR [ebp+0x8]> push DWORD PTR [eax] push 0x8048488 call 0x804828c <printf@plt> add esp,0x10 leave ret BodyEpilogueReturnCrash occurs at "push dword ptr [eax]".Let us see how the stack is built up.
139.
Before printnum() iscalled push ebp mov ebp,esp sub esp,0x8 sub esp,0x8 mov eax,DWORD PTR [ebp+0x8] push DWORD PTR [eax] push 0x8048488 call 0x804828c <printf@plt> add esp,0x10 leave ret Pointer x is pushed on the stack...0x000000ffESP...EBP
140.
Before printnum() iscalled> push ebp mov ebp,esp sub esp,0x8 sub esp,0x8 mov eax,DWORD PTR [ebp+0x8] push DWORD PTR [eax] push 0x8048488 call 0x804828c <printf@plt> add esp,0x10 leave ret ...and printnum is CALLed.Saved EIPESP0x000000ffparam 1...EBP
141.
Prologuepush ebp>mov ebp,esp sub esp,0x8 sub esp,0x8 mov eax,DWORD PTR [ebp+0x8] push DWORD PTR [eax] push 0x8048488 call 0x804828c <printf@plt> add esp,0x10 leave ret Old EBPESPSave the old frame pointer.Saved EIP0x000000ffparam 1...EBP
142.
Prologuepush ebpmov ebp,esp> sub esp,0x8 sub esp,0x8 mov eax,DWORD PTR [ebp+0x8] push DWORD PTR [eax] push 0x8048488 call 0x804828c <printf@plt> add esp,0x10 leave ret Old EBPEBPESPSet the EBP to the current frame.Saved EIP0x000000ffparam 1...
143.
Prologuepush ebpmov ebp,esp sub esp,0x8 sub esp,0x8> mov eax,DWORD PTR [ebp+0x8] push DWORD PTR [eax] push 0x8048488 call 0x804828c <printf@plt> add esp,0x10 leave ret ...ESP.........Old EBPEBPLeave some space on the stack (16 bytes)Saved EIP0x000000ffparam 1...
144.
Bodypush ebpmov ebp,esp sub esp,0x8 sub esp,0x8mov eax,DWORD PTR [ebp+0x8]> push DWORD PTR [eax] push 0x8048488 call 0x804828c <printf@plt> add esp,0x10 leave ret ...ESP.........Old EBPEBPEAX = 0x000000ffSaved EIP0x000000ffparam 1...
145.
Segmentation Fault!push ebpmov ebp,esp sub esp,0x8 sub esp,0x8mov eax,DWORD PTR [ebp+0x8]>push DWORD PTR [eax] push 0x8048488 call 0x804828c <printf@plt> add esp,0x10 leave ret ...ESP.........Old EBPEBPMemory at 0x000000ff cannot be referenced.Saved EIP0x000000ffparam 1...
146.
Segmentation Fault!push ebpmov ebp,esp sub esp,0x8 sub esp,0x8mov eax,DWORD PTR [ebp+0x8]>push DWORD PTR [eax] push 0x8048488 call 0x804828c <printf@plt> add esp,0x10 leave ret ...ESP.........Old EBPEBPMemory at 0x000000ff cannot be referenced.Saved EIP0x000000ffparam 1What will stack memory contain at this moment?...