gdb watchpoint except when triggered in specific locations? - gdb

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.

Related

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

Find the variable change in GDB

I am working in a project where there are more than 100 files of source code. I am debugging it for find an error.
What I need to find is the time when a particular object assigned to a value. ie. This object is NULL at first, but some other file changes its value, which I don't know.
Are there any method to find when this variable changes its value ?
What I tried upto now is to put a breakpoint on the function where the variable is initilized. I also added a watchpoint. But it does not show any point where the value is changing.
But it does not show any point where the value is changing.
There are two possible explanations:
You've set the watchpoint incorrectly, or
The value changes while the process is in kernel mode (GDB watchpoints are not effective for detecting such change).
Example:
#include <unistd.h>
int global_a;
int global_b;
int foo()
{
global_a = 42;
read(0, &global_b, 1);
return global_a + global_b;
}
int main()
{
return foo();
}
gcc -g -Wall t.c
gdb -q ./a.out
(gdb) start
Temporary breakpoint 1 at 0x400563: file t.c, line 16.
Starting program: /tmp/a.out
Temporary breakpoint 1, main () at t.c:16
16 return foo();
(gdb) watch global_a
Hardware watchpoint 2: global_a
(gdb) watch global_b
Hardware watchpoint 3: global_b
(gdb) c
Continuing.
Hardware watchpoint 2: global_a
Old value = 0
New value = 42
This is a modification of global_a in user-space (via direct assignment), and it triggers watchpoint 2 as expected
foo () at t.c:9
9 read(0, &global_b, 1);
(gdb) c
Continuing.
# Press Enter here
This read 0xA == 10 into global_b.
[Inferior 1 (process 126196) exited with code 064]
Note that the exit code is 064 == 52 == 42+10, but the watchpoint 3 did not fire.
any method to find when this variable changes its value
If you are sure that your "normal" watchpoints are working (e.g. by running above test yourself) and suspect that the variable is being changed via a system call, you can:
Print the address of the variable and
Run your program under strace and look for system calls that could change the value at variable's address.
Using the same example:
(gdb) p &global_b
$1 = (int *) 0x601044 <global_b>
strace -e raw=all ./a.out < /dev/zero
execve(0x7ffe1853e530, 0x7ffe1853f920, 0x7ffe1853f930) = 0
brk(0) = 0x2253000
access(0x7fa66eee48c3, 0) = -1 (errno 2)
mmap(0, 0x2000, 0x3, 0x22, 0xffffffff, 0) = 0x7fa66f0e8000
...
munmap(0x7f57ece26000, 0x203a2) = 0
read(0, 0x601044, 0x1) = 0x1 ### &global_b is "covered" by the buffer being read into
exit_group(42) = ?
+++ exited with 42 +++

Where to put HW BP to catch the global variable address corruption?

Program in C/C++ runs on embedded PowerPC under debugger with HW break points capabilities.
There is global variable 'char Name[256]' known in 2 files and 2 tasks correspondingly. One task reads Name, another fills it with a text, '1234567...', for example.
At some moment, global variable Name gets corrupted. When asked for the variable address gdb shows (and application prints by debug printouts) address equal to 0x31323334.
How to catch this bug with HW breakpoints? I mean at what address to put HWBP.
When I look into assembler, I see:
lis 9,Name#ha
lwz 9,Namel#l(9)
So, how memory corruption can change the code without influencing the application flow - it should crash immediately, no?
Thanks a lot ahead
0x31323334 is "1234" sans null terminator. Further, "Global variable address corruption" does not make much sense "global variables" (whose addresses do not change), nor really for an array of size 256 (unless you're using a pointer somewhere and it's the pointer which is being corrupted). So I suspect you might be unfamiliar with GDB.
When using GNU gdb (Ubuntu 7.7.1-0ubuntu5~14.04.2) 7.7.1 on x86 (admittedly, not ppc, but basically the same software) with the following test file:
// g++ test.cpp -g
#include <iostream>
char Name[256] = "123456789";
int main() {
Name[0] = 'a';
std::cout << Name << std::endl;
}
I can get the following output from GDB:
(gdb) break main
Breakpoint 2 at 0x40086a: file test.cpp, line 6.
(gdb) r
Starting program: /home/keithb/dev/mytest/a.out
Breakpoint 2, main () at test.cpp:6
6 Name[0] = 'a';
(gdb) whatis Name
type = char [256]
(gdb) print Name
$1 = "123456789", '\000' <repeats 246 times>
(gdb) print &Name
$2 = (char (*)[256]) 0x6010c0 <Name>
In any case, if you really do want to set a "hardware breakpoint" (GDB calls those "watchpoints"), then you can do get the address of Name prior to corruption. Then just set the watchpoint and wait for your program to write to the address.
(gdb) c
Continuing.
a23456789
[Inferior 1 (process 21878) exited normally]
(gdb) delete 2
(gdb) watch *0x6010c0
Hardware watchpoint 3: *0x6010c0
(gdb) r
Starting program: /home/keithb/dev/mytest/a.out
Hardware watchpoint 3: *0x6010c0
Old value = 875770417
New value = 875770465
main () at test.cpp:7
7 std::cout << Name << std::endl;
(gdb)

gdb: break when a particular object is altered

I have an object defined in c++ with a pointer to it used in various functions and files throughout the project. I am having an issue with the data being updated, so I want to debug it to see what is happening. Ideally, I want to break every time the object is accessed. however, watch requires a specific memory address. So, for example, if I have:
class data{
public:
int a;
int b;
};
then gdb will only break when a is altered, since the pointer to data is pointed at a, but not when b is altered.
Is there a way to break whenever the entire range of memory covered by the data class is altered?
Is there a way to break whenever the entire range of memory covered by the data class is altered?
Perhaps.
GDB hardware watchpoints use special debug registers in hardware, and there is usually a limit on how such registers work. On x86, you can set up to 4 word-sized hardware watch points, so for example you gave you can set watchpoints on &data->a and &data->b, and that will "cover" entire memory of the data.
I am guessing that your actual data has many more members though, and so 4 word-sized watch points will not suffice.
If you are on platform which has Valgrind support, and if your program can execute under Valgrind, then you can use Valgrind's built-in gdbserver to set watchpoints on arbitrary regions of memory.
Update:
I looked through the page you linked to and couldn't find what I was looking for
I am not sure what you were looking for. Here is a sample session showing how it works:
#include <stdlib.h>
void foo(char *p)
{
*p = 'a';
}
typedef struct {
char buf[1024];
} data;
int main()
{
data *d = calloc(1, sizeof(data));
foo(d->buf + 999);
}
gcc -g main.c
valgrind --vgdb-error=0 ./a.out
...
==10345== TO DEBUG THIS PROCESS USING GDB: start GDB like this
==10345== /path/to/gdb ./a.out
==10345== and then give GDB the following command
==10345== target remote | vgdb --pid=10345
... Valgrind now waits for debugger to attach.
In another window:
gdb ./a.out
GNU gdb (GDB) 7.4
...
(gdb) target remote | vgdb --pid=10345
relaying data between gdb and process 10345
[Switching to Thread 10345]
0x0000000004000af0 in _start () from /lib64/ld-linux-x86-64.so.2
(gdb) b main
Breakpoint 1 at 0x40053d: file main.c, line 14.
(gdb) c
Breakpoint 1, main () at main.c:14
14 data *d = calloc(1, sizeof(data));
(gdb) n
15 foo(d->buf + 999);
(gdb) watch *d
Hardware watchpoint 2: *d
Note that a "hardware" watchpoint has been set on entire *d.
It's a hardware watchpoint only in the sense that Valgrind is the hardware.
(gdb) p d.buf[999]
$1 = 0 '\000'
(gdb) c
Hardware watchpoint 2: *d
Old value = {buf = '\000' <repeats 1023 times>}
New value = {buf = '\000' <repeats 999 times>, "a", '\000' <repeats 23 times>}
foo (p=0x51b6457 "a") at main.c:6
6 }
(gdb) q
Voila: the debugger stopped when 999th element was modified, proving that the watchpoint "covered" the entire structure.

How can I step through nested function calls in 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.