lldb memory read error on Mac - c

I'm experimenting with lldb and I wrote a simple C application. I want to debug it in terminal using lldb. When I want to see the stack frame, i get a memory read error:
(lldb) target create "./auth_overflow"
Current executable set to './auth_overflow' (x86_64).
(lldb) br s -l 25
Breakpoint 1: where = auth_overflow`main + 69 at auth_overflow.c:25, address = 0x0000000100000e25
(lldb) br s -l 9
Breakpoint 2: where = auth_overflow`check_authentication + 47 at auth_overflow.c:9, address = 0x0000000100000d5f
(lldb) br s -l 16
Breakpoint 3: where = auth_overflow`check_authentication + 138 at auth_overflow.c:16, address = 0x0000000100000dba
(lldb) run AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
Process 413 launched: './auth_overflow' (x86_64)
Process 413 stopped
* thread #1: tid = 0x33d2, 0x0000000100000e25 auth_overflow`main(argc=2, argv=0x00007fff5fbffcc0) + 69 at auth_overflow.c:25, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
frame #0: 0x0000000100000e25 auth_overflow`main(argc=2, argv=0x00007fff5fbffcc0) + 69 at auth_overflow.c:25
22 exit(0);
23 }
24
-> 25 if(check_authentication(argv[1])) {
26 printf("\n-=-=-=-=-=-=-=-=-=-=-=-=-=-\n");
27 printf(" Access Granted.\n");
28 printf("-=-=-=-=-=-=-=-=-=-=-=-=-=-\n");
(lldb) re r esp
esp = 0x5fbffc70
(lldb) x/16xw $esp
error: memory read failed for 0x5fbffc00
(lldb)
What do you suggest , I should do?
EDIT : Actually I don't want to debug the application, just to see how it works on lower level. Because of this I'd like to see the content of the current stack frame, something like this:
(lldb) x/16xw $esp
0xbffff7e0: 0xb8000ce0 0x00000002 0x00000000 0xb7fd6ff4
0xbffff7f0: 0x40f5f7f0 0x00000000 0x00000002 0x08048474
0xbffff800: 0x08048510 0xbffff874 0x00000001 0x00000001
0xbffff810: 0xbffff848 0x00000000 0xb8000ff4 0x08048371
(lldb)

This:
Current executable set to './auth_overflow' (x86_64).
shows you're on a 64 bit machine. That being the case, you want the 64 bit rsp register, not the 32 bit esp register. esp will give you the least significant 32 bits of the contents of rsp, which in this case is obviously not yielding a valid address for you.
x/16xw $rsp
is what you're looking for.
Sample LLDB session:
paul#horus:~/Documents/src/sandbox$ lldb ./testldb
(lldb) target create "./testldb"
Current executable set to './testldb' (x86_64).
(lldb) list testldb.c
1 #include <stdio.h>
2
3 void func(int i) {
4 printf("In func() with value %d\n", i);
5 }
6
7 int main(void) {
8 func(3);
9 return 0;
10 }
11
(lldb) b testldb.c:4
Breakpoint 1: where = testldb`func + 18 at testldb.c:4, address = 0x0000000100000f22
(lldb) run
Process 48270 launched: './testldb' (x86_64)
Process 48270 stopped
* thread #1: tid = 0xb8dbca, 0x0000000100000f22 testldb`func(i=3) + 18 at testldb.c:4, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
frame #0: 0x0000000100000f22 testldb`func(i=3) + 18 at testldb.c:4
1 #include <stdio.h>
2
3 void func(int i) {
-> 4 printf("In func() with value %d\n", i);
5 }
6
7 int main(void) {
(lldb) frame variable
(int) i = 3
(lldb) print &i
(int *) $0 = 0x00007fff5fbff9dc
(lldb) register read $rsp
rsp = 0x00007fff5fbff9d0
(lldb) x/16xw $rsp
0x7fff5fbff9d0: 0x00000000 0x00000000 0x00000000 0x00000003
0x7fff5fbff9e0: 0x5fbffa00 0x00007fff 0x00000f59 0x00000001
0x7fff5fbff9f0: 0x5fbffa18 0x00007fff 0x5fc0105e 0x00000000
0x7fff5fbffa00: 0x5fbffa18 0x00007fff 0x8fdc25fd 0x00007fff
(lldb)

Related

How to use buffer overflow to "skip" to a specific line in the code?

I'm currently learning about C and trying to find out more about how memory in a stack works, and how gdb can be used to help.
Below is a code snippet of my problem:
bool thisEvaluatesToFalse(char* something) {
return false;
}
void main() {
char something[10];
puts("My plan is to input a specific string over 10 characters than will achieve my goal:");
gets(something);
if (thisEvaluatesToFalse(something)) {
puts("If this runs, its a success!");
}
}
The idea is, my success message will never run unless I exploit gets to input a something over 10 characters, causing an overflow that overwrites the return address of the function to where the success message is.
I understand I'm supposed to take a look at the assembly code with gdb and look out for an address, but I'm not exactly sure how to do this.
Could anyone guide me or show me an example? Thanks!
Try this, hope it helps you figure this out. Good luck!
Consider moving gets into thisEvaluatesToFalse to overwrite the return address pushed by main so the return from thisEvaluatesToFalse will return to the puts of success.
Like this:
#include <stdio.h>
unsigned int thisEvaluatesToFalse() {
char something[10];
gets(something);
return 0xdeadbeef;
}
int main() {
puts("My plan is to input a specific string over 10 characters than will achieve my goal:");
if (thisEvaluatesToFalse()) {
puts("If this runs, its a success!");
}
return 0;
}
Here are the highlights of working w/ gdb.
gcc main.c -fno-stack-protector -ggdb
gdb a.out
(gdb) disass main
0x0000000100003eeb <+27>: call 0x100003eb0 <thisEvaluatesToFalse>
0x0000000100003ef0 <+32>: cmp $0x0,%eax
0x0000000100003ef3 <+35>: je 0x100003f05 <main+53>
0x0000000100003ef9 <+41>: lea 0x94(%rip),%rdi # 0x100003f94
0x0000000100003f00 <+48>: call 0x100003f14
# ORIG RETURN ADDRESS IS 0x0000000100003ef0
# EXPLOIT RETURN ADDRESS FOR SUCCESS IS 0x0000000100003ef9
(gdb) break thisEvaluatesToFalse
(gdb) run
(gdb) x/16x $sp
0x7ff7bfeff930: 0x000c8060 0x00000001 0x00003ed0 0x00000001
0x7ff7bfeff940: 0xbfeff960 0x00007ff7 0x00003ef0 0x00000001
0x7ff7bfeff950: 0x00000013 0x00000000 0x000c8060 0x00000000
0x7ff7bfeff960: 0xbfeffa70 0x00007ff7 0x0001552e 0x00000001
# NOTICE THE VALUE AT 0x7ff7bfeff948 IS 0x00003ef0 (ORIG RETURN)
# NOTICE THE VALUE AT 0x7ff7bfeff94C IS 0x00000001 (ORIG RETURN)
(gdb) s
warning: this program uses gets(), which is unsafe.
1234567890AAAABBBBCCCCDDDD
(gdb) x/16x $sp
0x7ff7bfeff930: 0x000c8060 0x32310001 0x36353433 0x30393837
0x7ff7bfeff940: 0x41414141 0x42424242 0x43434343 0x44444444
0x7ff7bfeff950: 0x00000000 0x00000000 0x000c8060 0x00000000
0x7ff7bfeff960: 0xbfeffa70 0x00007ff7 0x0001552e 0x00000001
# NOTICE THE VALUE AT 0x7ff7bfeff948 IS 0x43434343 (LETTER C)
# NOTICE THE VALUE AT 0x7ff7bfeff94C IS 0x44444444 (LETTER D)
(gdb) set *0x7ff7bfeff948 = 0x00003ef9
(gdb) set *0x7ff7bfeff94C = 0x00000001
(gdb) x/16x $sp
0x7ff7bfeff930: 0x000c8060 0x32310001 0x36353433 0x30393837
0x7ff7bfeff940: 0x41414141 0x42424242 0x00003ef9 0x00000001
(gdb) s
main () at main.c:17
17 puts("If this runs, its a success!");
(gdb) s
If this runs, its a success!
19 return 0;
Leaving it up to you to figure out how to input values for gets that perform the actions that replace C and D with the values you need.
If you can choose a different approach, then instead of using gets for the overflow try using memcpy and copy more than 10 bytes. Same impact, the stack gets modified.

For gdb, should an rwatch breakpoint activate the commands written to that breakpoint? Mine don't

After I finished writing this I saw that rwatch actives a signal, SIGTRAP, which seems to be different than a breakpoint. I'm confused now because the command 'info breakpoints' still lists it as a breakpoint.
I don't know if this is expected behavior or if I'm setting up something wrong.
I have a setup running gdb (from ARM toolchain) and openocd with the target being a stm32 discovery board.
I'm trying to run certain gdb commands on a watchpoint using the command
commands [breakpointnumber]
Then I add the commands when prompted, I'm using 'p x' and 'p y' to print the x and y variable, and end it with 'end' like it says I should.
This does work when I set a breakpoint using
b [linenumber]
Here is an example of it running on gdb
(gdb) b 15
Breakpoint 5 at 0x8000134: file main.c, line 15.
(gdb) commands 5
Type commands for breakpoint(s) 5, one per line.
End with a line saying just "end".
>p x
>p y
>end
(gdb) info breakpoints
Num Type Disp Enb Address What
5 breakpoint keep y 0x08000134 in main at main.c:15
p x
p y
(gdb) c
Continuing.
Breakpoint 5, main () at main.c:15
15 y++;
$21 = 46 '.'
$22 = 44 ','
(gdb) c
Continuing.
Breakpoint 5, main () at main.c:15
15 y++;
$23 = 47 '/'
$24 = 46 '.'
(gdb) c
Continuing.
Breakpoint 5, main () at main.c:15
15 y++;
$25 = 48 '0'
$26 = 48 '0'
but if I use the rwatch command such as
rwatch x
and set the commands like before, those commands don't run when the program reaches the rwatch breakpoint.
Here is gdb running using rwatch
(gdb) delete
Delete all breakpoints? (y or n) y
(gdb) rwatch x
Hardware read watchpoint 6: x
(gdb) commands 6
Type commands for breakpoint(s) 6, one per line.
End with a line saying just "end".
>p x
>p y
>end
(gdb) info breakpoints
Num Type Disp Enb Address What
6 read watchpoint keep y x
p x
p y
(gdb) c
Continuing.
Program received signal SIGTRAP, Trace/breakpoint trap.
0x0800012c in main () at main.c:14
14 x++;
(gdb) c
Continuing.
Program received signal SIGTRAP, Trace/breakpoint trap.
0x0800012c in main () at main.c:14
14 x++;
(gdb) c
Continuing.
Program received signal SIGTRAP, Trace/breakpoint trap.
0x0800012c in main () at main.c:14
14 x++;
I have deleted all other breakpoints.
Using 'info breakpoints' shows the commands are associated with the breakpoint
It's just a test program as I learn gdb and openocd so it's really short.
#include "stdint.h"
5 uint8_t checker = 0x50;
4 uint8_t x = 0x21;
3 uint8_t y = 0x14;
2 int main(void)
1 {
12 while(1)
1 {
2 x++;
3 y++;
4 y++;
5 ;
6 if(x == 5000)
7 {
8 x = 0;
9 }
10 if(y == 10000)
11 {
12 y = 0;
13 }
14 }
15 }
I suspect that this is an openocd bug. That the watchpoint is being reported as a SIGTRAP is not the correct behaviour, but most likely reflects what GDB is being told by openocd.
If we look at the behaviour of GDB running on native Linux, I see this behaviour:
$ gdb -q test
Reading symbols from test...
(gdb) start
Temporary breakpoint 1 at 0x401123: file test.c, line 10.
Starting program: /tmp/rwatch/test
Temporary breakpoint 1, main () at test.c:10
10 int var = 0;
(gdb) rwatch var
Hardware read watchpoint 2: var
(gdb) commands
Type commands for breakpoint(s) 2, one per line.
End with a line saying just "end".
>echo hello world\n
>end
(gdb) c
Continuing.
Hardware read watchpoint 2: var
Value = 0
main () at test.c:12
12 func (&var);
hello world
(gdb)
And, if I use gdbserver, then I see the same behaviour:
> gdb -q test
Reading symbols from test...
(gdb) target remote :54321
Remote debugging using :54321
... snip lots of library loading text ...
(gdb) b main
Breakpoint 1 at 0x401123: file test.c, line 10.
(gdb) c
Continuing.
... snip lots more library loading text ...
Breakpoint 1, main () at test.c:10
10 int var = 0;
(gdb) rwatch var
Hardware read watchpoint 2: var
(gdb) command
Type commands for breakpoint(s) 2, one per line.
End with a line saying just "end".
>echo hello world\n
>end
(gdb) c
Continuing.
Hardware read watchpoint 2: var
Value = 0
main () at test.c:12
12 func (&var);
hello world
(gdb)
So we can see that GDB can handle read watchpoints better than just reporting a SIGTRAP, so I suspect the problem here is openocd reporting that the stop is due to a SIGTRAP, rather than being due to a read watchpoint triggering.
You might be able to work around this problem by making use of the Python API, there is a gdb.StopEvent, you could catch these and then try printing out the variables you are interested in maybe? The following Python code, placed into a file and then sourced into GDB should do the job:
def stop_handler (event):
if (type (event) == gdb.SignalEvent
and event.stop_signal == 'SIGTRAP'):
print ("Use gdb.execute to run arbitrary commands here!")
gdb.events.stop.connect (stop_handler)

how to get line numbers same as lldb using atos/addr2line/llvm-symbolizer/lldb image lookup --address

I want to programmatically convert backtrace stack addresses (eg obtained from backtrace_symbols/libunwind) to file:line:column. I'm on OSX but doubt this makes a difference.
All of these give wrong line number (line 11) for the call to fun1():
atos
addr2line
llvm-symbolizer
lldb image lookup --address using lldb's pc addresses in bt
lldb bt itself gives correct file:line:column, (line 7) as shown below.
How do I programmatically get the correct stack address such that, when using atos/addr2line/llvm-symbolizer/image lookup --address, it would resolve to the correct line number? lldb bt is doing it correctly, so there must be a way to do it. Note that if I use backtrace_symbols or libunwind (subtracted from info.dli_saddr after calling dladdr), I'd end up with the same address 0x0000000100000f74 as shown in lldb bt that points to the wrong line number 11
Note: in .lldbinit, if I add settings set frame-format frame start-addr:${line.start-addr}\n it will show the correct address (ie resolve to 0x0000000100000f6f instead of 0x0000000100000f74, which will resolve to the correct line 7). However, how do I programmatically generate start-addr from a c program without calling spawning a call to lldb -p $pid (calling lldb has other issues, eg overhead compared to llvm-symbolizer, and in fact can hang forever even with -batch).
clang -g -o /tmp/z04 test_D20191123T162239.c
test_D20191123T162239.c:
void fun1(){
}
void fun1_aux(){
int a = 0;
fun1(); // line 7
mylabel:
if(1){
a++; // line 11
}
}
int main(int argc, char *argv[]) {
fun1_aux();
return 0;
}
lldb /tmp/z04
(lldb) target create "/tmp/z04"
Current executable set to '/tmp/z04' (x86_64).
(lldb) b fun1
Breakpoint 1: where = z04`fun1 + 4 at test_D20191123T162239.c:2:1, address = 0x0000000100000f54
(lldb) r
Process 7258 launched: '/tmp/z04' (x86_64)
Process 7258 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
frame #0: 0x0000000100000f54 z04 fun1 + 4 at test_D20191123T162239.c:2:1
1 void fun1(){
-> 2 }
3
4 void fun1_aux(){
5 int a = 0;
6
7 fun1();
Target 0: (z04) stopped.
(lldb) bt
* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
* frame #0: 0x0000000100000f54 z04 fun1 + 4 at test_D20191123T162239.c:2:1
frame #1: 0x0000000100000f74 z04 fun1_aux + 20 at test_D20191123T162239.c:7:3
frame #2: 0x0000000100000fab z04 main(argc=1, argv=0x00007ffeefbfb748) + 27 at test_D20191123T162239.c:16:3
frame #3: 0x00007fff71c182e5 libdyld.dylib start + 1
frame #4: 0x00007fff71c182e5 libdyld.dylib start + 1
(lldb)
(lldb) image lookup --address 0x0000000100000f74
Address: z04[0x0000000100000f74] (z04.__TEXT.__text + 36)
Summary: z04`fun1_aux + 20 at test_D20191123T162239.c:11:8
echo 0x0000000100000f74 | llvm-symbolizer -obj=/tmp/z04
fun1_aux
test_D20191123T162239.c:11:8
atos -o /tmp/z04 0x0000000100000f74
fun1_aux (in z04) (test_D20191123T162239.c:11)
likewise with addr2line
It's easier to understand if you look at the disassembly for fun1_aux -- you'll see a CALLQ instruction to fun1, followed by something like a mov %rax, $rbp-16 or something like that, the first instruction of your a++ line. When you have called fun1, the return address is the instruction that will be executed when fun1 exits, the mov %rax, $rbp-16 or whatever.
This isn't intuitively how most people think of the computer working -- they expect to look at frame 1, fun1_aux, and see the "current pc value" be the CALLQ, because the call is executing. But of course, that's not correct, the call instruction has completed, and the saved pc is going to point to the next instruction.
In cases like this, the next instruction is part of the next source line, so it's a little extra confusing. Even better is if you have a function that calls a "noreturn" function like abort() -- the final instruction in the function will be a CALLQ, and if you look at the return address instruction, it may point to the next function.
So when lldb is symbolicating stack frames above frame #0, it knows to do a symbol lookup with saved_pc - 1 to move the address back into the CALLQ instruction. That's not a valid address, so it should never show you saved_pc - 1, but it should do symbol / file & line lookups based on it.
You can get the same effect for your manual symbolication by doing the same thing. The one caveat is if you have an asynchronous interrupt (_sigtramp on macOS), the frame above _sigtramp should not have its saved pc value decremented. You could be executing the first instruction of a function when the signal is received, and decrementing it would put you in the previous function which would be very confusing.

How do I trace "fate" of a particular value?

I see some value in some place, but unsure where it has originated in my program. How do I figure out where this value initially comes from?
I expect the following event types to be logged:
A value originated from constant, arithmetical expression or syscall - the initial event;
The value was assigned to (or retrieved from) some variable;
The value was passed as an argument or returned from some function;
The value was stored to (or retrieved from) some struct;
By annotating source code with something specific, I triggered the history dump for this value.
For example, for this sample code:
#include <stdlib.h>
struct SomeStruct {
int a;
int b;
};
struct SomeStruct *globalvar;
int f1(struct SomeStruct* par) {
return par->a;
}
int f2(struct SomeStruct* par, int q) {
par->a = q;
return par->b;
}
void trace_value(int g) {} /* dummy */
int main(void) {
int f = 31337;
globalvar = malloc(sizeof(*globalvar));
f2(globalvar, f);
struct SomeStruct q = *globalvar;
int g = f1(&q);
trace_value(g);
return 0;
}
it should return something like
value 31337 originated from constant at fate.c:18
assigned to variable at fate.c:18
retrieved from variable at fate.c:21
passed as argument to function at fate.c:21
received as arument to a function at fate.c:12
assigned to struct field at fate.c:13
copied as a part of struct at fate.c:22
retrieved from struct field at fate.c:9
returned from function at fate.c:10
assigned to variable at fate.c:23
retrieved from variable at fate.c:25
traced at fate.c:25
How do I do this or something similar? I expect Valgrind or GDB or some combination should be able to do this.
Combined idea1 of using reverse gdb and idea2 from MarkPlotnick's comment of using gdb watchpoints. Here is the demo session, more complete than in original answer:
$ gcc -ggdb -Dtrace_value=exit fate.c -o fate
$ gdb -quiet -args ./fate
Reading symbols from /home/vi/code/_/fate...done.
(gdb) break main
Breakpoint 1 at 0x8048482: file fate.c, line 18.
(gdb) r
Starting program: /home/vi/code/_/fate
warning: Could not load shared library symbols for linux-gate.so.1.
Do you need "set solib-search-path" or "set sysroot"?
Breakpoint 1, main () at fate.c:18
18 int f = 31337;
(gdb) record
(gdb) break 25
(gdb) # traced at fate.c:25
Breakpoint 2 at 0x80484d2: file fate.c, line 25.
(gdb) c
Continuing.
Breakpoint 2, main () at fate.c:25
25 trace_value(g);
(gdb) # retrieved from variable at fate.c:25
(gdb) watch g
Hardware watchpoint 3: g
(gdb) reverse-continue
Continuing.
Hardware watchpoint 3: g
Old value = 31337
New value = 134513899
0x080484ce in main () at fate.c:23
23 int g = f1(&q);
(gdb) # assigned to variable at fate.c:23
(gdb) # returned from function at fate.c:10
(gdb) reverse-step
f1 (par=0xffffd670) at fate.c:10
10 }
(gdb) list
5
6 struct SomeStruct *globalvar;
7
8 int f1(struct SomeStruct* par) {
9 return par->a;
10 }
11
12 int f2(struct SomeStruct* par, int q) {
13 par->a = q;
14 return par->b;
(gdb) # retrieved from struct field at fate.c:9
(gdb) print par
$3 = (struct SomeStruct *) 0xffffd670
(gdb) print ((struct SomeStruct *) 0xffffd670)->a
$4 = 31337
(gdb) watch ((struct SomeStruct *) 0xffffd670)->a
Hardware watchpoint 4: ((struct SomeStruct *) 0xffffd670)->a
(gdb) reverse-continue
Continuing.
Hardware watchpoint 4: ((struct SomeStruct *) 0xffffd670)->a
Old value = 31337
New value = -134716508
0x080484ba in main () at fate.c:22
22 struct SomeStruct q = *globalvar;
(gdb) # copied as a part of struct at fate.c:22
(gdb) print globalvar->a
$5 = 31337
(gdb) watch globalvar->a
Hardware watchpoint 5: globalvar->a
(gdb) reverse-continue
Continuing.
Hardware watchpoint 5: globalvar->a
Old value = 31337
New value = 0
0x0804846f in f2 (par=0x804a008, q=31337) at fate.c:13
13 par->a = q;
(gdb) # assigned to struct field at fate.c:13
(gdb) # received as arument to a function at fate.c:12
(gdb) list
8 int f1(struct SomeStruct* par) {
9 return par->a;
10 }
11
12 int f2(struct SomeStruct* par, int q) {
13 par->a = q;
14 return par->b;
15 }
16
17 int main() {
(gdb) bt
#0 0x0804846f in f2 (par=0x804a008, q=31337) at fate.c:13
#1 0x080484b0 in main () at fate.c:21
(gdb) reverse-finish
Run back to call of #0 0x0804846f in f2 (par=0x804a008, q=31337) at fate.c:13
0x080484ab in main () at fate.c:21
21 f2(globalvar, f);
(gdb) # passed as argument to function at fate.c:21
(gdb) # retrieved from variable at fate.c:21
(gdb) watch f
Hardware watchpoint 6: f
(gdb) reverse-finish
"finish" not meaningful in the outermost frame.
(gdb) reverse-continue
Continuing.
Warning:
Could not insert hardware watchpoint 6.
Could not insert hardware breakpoints:
You may have requested too many hardware breakpoints/watchpoints.
(gdb) delete
Delete all breakpoints? (y or n) y
(gdb) watch f
Hardware watchpoint 7: f
(gdb) reverse-continue
Continuing.
No more reverse-execution history.
main () at fate.c:18
18 int f = 31337;
(gdb) # assigned to variable at fate.c:18
(gdb) # value 31337 originated from constant at fate.c:18
All expected messages in the question statement correspond to some info you have seen in gdb output (as shown in comments).
I believe it could be accomplished manually (i.e. running on gdb session) in runtime by technique called "reverse debugging". I haven't tried it yet, but GDB version 7.0 documentation claims, that it is supported on some platforms.
The method would be something like:
localize single step where variable is used in the last place (that is, your "starting point")
analyze source code (so you need debugging symbol and code section available) of stack frame (e.g. by list), so you get how this value is obtained (or possibly modified) witihin (e.g. from parameter passed to function)
step back to previous stack frame and repeat from previous step unless you find its origin
Here is some proof-of-concept session for your sample code. I edited it a bit, as trace_value function was undefined. Note that record command may heavily slow down program's execution.
$ gdb -q a.out
Reading symbols from /home/grzegorz/workspace/a.out...done.
(gdb) b main
Breakpoint 1 at 0x400502: file fate.c, line 22.
(gdb) run
Starting program: /home/grzegorz/workspace/a.out
Breakpoint 1, main () at fate.c:22
22 int f = 31337;
Missing separate debuginfos, use: debuginfo-install glibc-2.12-1.149.el6_6.5.x86_64
(gdb) record
(gdb) b trace_value
Breakpoint 2 at 0x4004f8: file fate.c, line 19.
(gdb) c
Continuing.
Breakpoint 2, trace_value (g=31337) at fate.c:19
19 void trace_value(int g){}
(gdb) info args
g = 31337
(gdb) reverse-finish
Run back to call of #0 trace_value (g=31337) at fate.c:19
0x0000000000400550 in main () at fate.c:29
29 trace_value(g);
(gdb) bt
#0 0x0000000000400550 in main () at fate.c:29
(gdb) list 29
24 globalvar = malloc(sizeof(*globalvar));
25 f2(globalvar, f);
26 struct SomeStruct q = *globalvar;
27 int g = f1(&q);
28
29 trace_value(g);
30
31 return 0;
32 }
Few things maybe require some explanation. You need to set breakpoint for main at first, as this is when the program execution begins, then enable session recording by record command. Then set second breakpoint at trace_value function and use continue command (c in short). This allows you to record whole execution up to moment when trace_value is entered. You may think of it as this "starting point", described above.
This of course not the full story. As I described earlier you need to analyze source code of current stack frame an then decide what to do next. You may use reverse-step or reverse-finish command accordingly to current situation.

gdb debugging integer printing information

I am trying to find out how to print an integer value (I saw that it is x/d) but I am missing something.
So, my code is the following
1 #include <stdio.h>
2 main(){
3 int a;
4 int b;
5 int c;
6 int d;
7 int multiplied;
8 a = 5;
9 b = 6;
10 c = 7;
11 d = adding(a,b,c);
12 multiplied = multiply(a,b,c);
13 printf("The value of d is %d \n",d);
14 printf("The multiplied values are %d \n", multiplied);
15 }
16 int adding(a,b,c){
17 int e;
18 e = a+b+c;
19 return e;
20 }
21 int multiply(a,b,c){
22 int f = a*b*c;
23 return f;
24 }
// I compiled with -q and I want to print the values of the variables (from their addresses) So...
(gdb) disassemble main
0x080483ed <+9>: mov DWORD PTR [esp+0x2c],0x5
0x080483f5 <+17>: mov DWORD PTR [esp+0x28],0x6
0x080483fd <+25>: mov DWORD PTR [esp+0x24],0x7
0x08048405 <+33>: mov eax,DWORD PTR [esp+0x24] <code>
I put some breakpoints in main / multiply / adding and then I was trying to do the following thing.
I used
print $esp+0x24
and
(gdb) x/4d 0xbffff47c but im not getting the right answers back.
I used the 4d because I thought that an integer is 4 bytes (or maybe again im missing something) but the results arent showing the value 5.
Can you please help me? Thanks and sorry for the bad output / format of gdb.. seriously i cant understand whats wrong
(gdb) print $esp+0x2c
$2 = (void *) 0xbffff494
(gdb) print $esp+0x28
$3 = (void *) 0xbffff490
(gdb) print $esp+0x24
$4 = (void *) 0xbffff48c
(gdb) x/d 0xbffff494
0xbffff494: -1208180748
(gdb) x/d 0xbffff490
0xbffff490: -1208179932
(gdb) x/d 0xbffff48c
0xbffff48c: 134513881
Also this happens ofcourse after the first breakpoint of main and actually the same values are coming all the time in all breakpoints (except the one before main...)
Another interesting thing that I found is the following... Im sure that the first values are garbages. But why it considers 0x5 as an address when it should print the actual value?
Breakpoint 1, main () at functioncalling.c:10
10 a = 5;
(gdb) x/s a
0xb7fc9ff4: "|M\025"
(gdb) cont
Continuing.
Breakpoint 3, adding (a=5, b=6, c=7) at functioncalling.c:21
21 e = a+b+c;
(gdb) x/s a
0x5: <Address 0x5 out of bounds>
I compiled your program with -g and no optimization, and set a breakpoint before line 11. My stack addresses are a bit different from yours, which isn't surprising given the variety of systems out there.
(gdb) print $esp+0x2c
$2 = (void *) 0xbffff44c
This is printing the address of a. To confirm:
(gdb) print &a
$4 = (int *) 0xbffff44c
Use x/wd to show a 4-byte integer in decimal.
(gdb) x/wd $esp+0x2c
0xbffff44c: 5
x/4d will show 4 values (4 is the repeat count) starting at the address. If you omit the size letter w here, the x command will default to the size previously used.
(gdb) x/4d $esp+0x2c
0xbffff44c: 5 134513856 0 -1073744680
There's your 5. As for the 3 other numbers, they are things further up the stack.
(gdb) x/4a $esp+0x2c
0xbffff44c: 0x5 0x80484c0 <__libc_csu_init> 0x0 0xbffff4d8
Your next question:
Another interesting thing that I found is the following... Im sure that the first values are garbages. But why it considers 0x5 as an address when it should print the actual value?
Breakpoint 3, adding (a=5, b=6, c=7) at functioncalling.c:21
21 e = a+b+c;
(gdb) x/s a
0x5: <Address 0x5 out of bounds>
The x command, when given a program's variable as its argument, retrieves its value and uses that as the address. x/s a means to retrieve the value in a and use it as the starting address of a NUL-terminated string. If a were of type char * and contained a suitable value, x/s would print sensible output. To print a's actual value, give the x command the argument &a.
(gdb) x/wd &a
0xbffff44c: 5
This may seem counterintuitive. Just consider the x command to operate just like the C statement printf(fmt, *(argument)) would. The argument to the x command is almost always a literal memory address or an address expression involving the stack pointer, base pointer, or pc registers.

Resources