How can I step through nested function calls in GDB? - gdb

Sometimes I want to debug functions like this:
my_func1(my_func2(my_func3(val)));
Is there a way I can step through this nested call in GDB?
I want to step through my_func3, then my_func2, then my_func1, etc.

What command are you stepping with? next would go to next line when debugging my_func1(my_func2(my_func3(val)));, but step should enter my_func3.
Example:
int my_func1(int i)
{
return i;
}
int my_func2(int i)
{
return i;
}
int my_func3(int i)
{
return i;
}
int main(void)
{
return my_func1(my_func2(my_func3(1)));
}
Debugged:
(gdb) b main
Breakpoint 1 at 0x4004a4: file c.c, line 19.
(gdb) run
Starting program: test
Breakpoint 1, main () at c.c:19
19 return my_func1(my_func2(my_func3(1)));
(gdb) step
my_func3 (i=1) at c.c:14
14 return i;
(gdb) step
15 }
(gdb) step
my_func2 (i=1) at c.c:9
9 return i;
(gdb) step
10 }
(gdb) step
my_func1 (i=1) at c.c:4
4 return i;
(gdb) step
5 }
(gdb) step
main () at c.c:20
20 }
(gdb) cont
Continuing.
Program exited with code 01.
(gdb)

If you know the where the function definition is in the source code one solution will be to put break point inside that function.

Yes, although you may have get your hands dirty with the disassembly. First try the step command (abbreviation s). If that doesn't put you into my_func3(), try instead the stepi command (abbreviation si) to step one instruction at a time. This may take several invocations, since there can be a lot of instructions setting up the function call arguments and cleaning up afterwards.

Related

Continue debugging after SegFault in GDB?

I am debugging a huge program using GDB and there is a SegFault in my program.
Instead of re-running the program, is it possible to switch to a previous stack frame and continue execution from there?
On Unix and Linux systems, at least, you can use gdb's handle command to tell gdb to stop the program when a signal is received (with the stop keyword) and not to pass the signal to the program (with the nopass keyword). When the program stops, you can use the return command to return a value from the current frame, then continue the program.
$ gdb -q segvtest
Reading symbols from segvtest...done.
(gdb) list 1,99999
1 #include <stdio.h>
2
3 int a()
4 {
5 int *p = 0;
6 return *p;
7 }
8
9 int main()
10 {
11 int i = a();
12 printf("a() returned %d\n", i);
13 }
(gdb) handle SIGSEGV stop nopass
Signal Stop Print Pass to program Description
SIGSEGV Yes Yes No Segmentation fault
(gdb) run
Starting program: /home/mp/segvtest
Program received signal SIGSEGV, Segmentation fault.
0x00000000080006c0 in a () at segvtest.c:6
6 return *p;
(gdb) return 12345
Make a return now? (y or n) y
#0 0x00000000080006d6 in main () at segvtest.c:11
11 int i = a();
(gdb) c
Continuing.
a() returned 12345
[Inferior 1 (process 74) exited normally]
(gdb)
is it possible to switch to a previous stack frame and continue
execution from there?
Yes, you can do it with reverse debugging.
When you get segfault, run reverse-finish to go out of the current frame in reverse direction. You will stop in the previous frame where you are about to call the function that caused a segfault.

Can I execute commands silently in gdb?

Is there a way to execute a command silently so that it doesn't print feedback (such as Breakpoint 1 at 0x5c4 after setting a breakpoint)? Such a feature would be especially useful for me for a scripted debugging session.
#include <stdio.h>
int main() {
int i;
for(i=0;i<1000;i++) {
printf("%d\n", i);
}
return 0;
}
inside gdb
(gdb) break 6
(gdb) commands
(gdb) silent
(gdb) end
Alternatively, if you want to skip few initial breakpoints
ignore 1 999

gdb watchpoint except when triggered in specific locations?

I have a variable getting corrupted. I want to see where this is happening, so a watchpoint is the obvious choice, except this variable frequently gets set (in this case, processing network packets and it gets set once for each packet). I would like to exempt the watchpoint from the location where the variable is supposed to get written. Basically, what I would like is "watch variable if line_number != x"; the gdb docs seem to be a bit thin on the conditional expressions, so I'm not sure this is possible...
There are a couple of ways to do this, in the following source file.
struct stuff {
int watched;
};
void dont_hit(struct stuff *foo) {
begin:
for (int i = 0; i < 100; i++)
foo->watched = i;
end:
return;
}
void hit(struct stuff *foo) {
foo->watched = 1024;
}
int main()
{
struct stuff foo;
setup:
dont_hit(&foo);
hit(&foo);
dont_hit(&foo);
}
We can then use the watchpoint condition: if $pc != ...
as shown below:
(gdb) break main
(gdb) r
(gdb) watch foo.watched
(gdb) c
Hardware watchpoint 2: foo.watched
Old value = -8320
New value = 0
dont_hit (foo=0x7fffffffde90) at main.c:7
7 for (int i = 0; i < 100; i++)
(gdb) p $pc
$1 = (void (*)()) 0x4004c0 <dont_hit+26>
(gdb) watch -location foo->watched if $pc != 0x4004c0
ardware watchpoint 3: -location foo->watched
(gdb) delete 2
(gdb) c
Continuing.
Hardware watchpoint 3: -location foo->watched
Old value = 99
New value = 1024
hit (foo=0x7fffffffde90) at main.c:15
Another way is to use breakpoints to enable/disable the watchpoint in places we don't want it to trigger, I'm using the label's here setup/begin/end for clarity, but you can replace main:label with filename:line_number
break main:setup
run
watch -location foo.watched
break dont_hit:begin
commands
silent
disable 2
cont
end
break dont_hit:end
commands
silent
enable 2
cont
end
A third way, is going to use Python, and FinishBreakpoints to do the enabling/disabling.

C++ gdb print array gives No symbol "d" in context

I am trying to debug a C++ program but I face the below issue when trying to print the contents of the array.
I have declared a array of chars as below in the c++ program
using namespace std;
int main() {
string s;
cin >> s;
char d[s.size()];
int i=0;
int j=0;
while(j<s.size()) {
if(s[j] != '+') {
d[i++] = s[j];
}
j++;
}
}
I use the below commands to compile the above code and run gdb
g++ -g main.cpp -o main
gdb main
However when I debug and hit the below command in GDB I get the below error.
Command entered in GDB : p *d#10
No symbol "d" in current context.
Can you please let me know what I can do so that all the contents of the array is printed?
Until you run the program, there are no variables to print. For your program, you should set a breakpoint at the last line of main, and run the program. When the program stops at the breakpoint, you can then print d.
(gdb) list 15
10 while(j<s.size()) {
11 if(s[j] != '+') {
12 d[i++] = s[j];
13 }
14 j++;
15 }
16 }
(gdb) break 15
Breakpoint 1 at 0x80488b9: file x.cc, line 15.
(gdb) run
Starting program: /home/jxh/StackOverflow/gdb/a.out
1234567890
Breakpoint 1, main () at x.cc:15
15 }
(gdb) p *d#10
$2 = "1234567890"
(gdb)
Make sure to turn off compiler optimizations. This link gives a little more detail.

Why does gdb show two different returns?

Last week I was a debugging a code and a weird situation came up: gdb passes through two different return clauses. I made a simple example that illustrates the situation:
#include <iostream>
using namespace std;
int test() {
string a = "asd";
string b = "asd";
while (true) {
if (a == b) {
return 0;
}
}
return -1;
}
int main() {
int result = test();
cout << "result: " << result << endl;
}
When debugging the code I got:
(gdb) b main
Breakpoint 1 at 0x1d4c: file example.cpp, line 19.
(gdb) r
Starting program: /Users/yuppienet/temp/a.out
Reading symbols for shared libraries +++. done
Breakpoint 1, main () at example.cpp:19
19 int result = test();
(gdb) s
test () at example.cpp:7
7 string a = "asd";
(gdb) n
8 string b = "asd";
(gdb) n
11 if (a == b) {
(gdb) n
12 return 0;
(gdb) n
15 return -1;
(gdb) n
16 }
(gdb) n
main () at example.cpp:20
20 cout << "result: " << result << endl;
(gdb) n
result: 0
21 }
(gdb) n
0x00001ab2 in start ()
I noted that even if gdb shows line 15, the return value is 0 (the finish command confirms this as well).
So the question is: why does gdb show line 15: return -1, even if the function is not really returning this value?
Thanks!
Edit:
I forgot to mention that I compiled with the following line:
g++ -Wall -pedantic -g -pg example.cpp
I suspect you're seeing the function epilogue. Your two strings have destructors, which are being implicitly called on return. Check out what the disassembly says to be sure, but I suspect that both return statements are mapping to something along the lines of:
stash return_value;
goto epilogue;
and correspondingly:
epilogue:
destroy a; // on the stack, so destructor will be called
destroy b;
really_return(stashed value);
The epilogue appears to come from line 15 as a side-effect of how g++ does line numbering - a fairly simple format, really just a list of tags of the form "address X comes from line number Y" - and so it's reporting 15 as the closest match. Confusing in this case, but correct a lot of the time.
Probably because the program counter register passes through the instructions that best map to the final return, i.e. the function's exit sequence. The actual return value is probably kept in a register, so the first return just loads the proper value and jumps to the end of the function, and then that address is "back-mapped" to the source code line of the final return.
You don't say, but if you compiled with optimization that is exactly the kind of behavior you would see in gdb. You see the first line setting up the return value, and then it jumps to the real return instruction but in C++ you see the entire thing including the return value.