Is it possible to delete a watchpoint without knowing the watchpoint number?
I am using commands attached to a breakpoint to set a watchpoint on a memory location. I would like to have the watchpoint cleared at another breakpoint, but I can't figure out how to clear a watchpoint without the watchpoint number. Is there a command that can delete a watchpoint by memory location?
the easiest way is to use the $bpnum convenience variable, you'll probably want to store it in another convenience variable so it doesn't change when you create breakpoints/watchpoints later on.
(gdb) watch y
(gdb) set $foo_bp=$bpnum
Hardware watchpoint 2: y
(gdb) p $foo_bp
$1 = 2
(gdb) delete $foo_bp
What about saving a watchpoint number and then deleting the watchpoint using this number?
This is an example. I have a C++ program. I set three watchpoints when the breakpoint on the line 5 is hit. For the watchpoint #2 I save a gdb command file in order to delete it later. When the breakpoint on the 9 is hit I just execute this gdb command file:
This is main.cpp:
#include <stdio.h>
int main()
{
int v3=2, v2=1, v1 =0 ;
printf("Set a watchpoint\n");
v1 = 1;
v1 = 2;
printf("Clear the watchpoint\n");
v1 = 3;
v1 = 4;
return 0;
}
This is .gdbinit:
file ./a.out
b 5
commands
watch v2
watch v1
set pagination off
shell rm -f all_watchpoints
set logging file all_watchpoints
set logging on
info watchpoints
set logging off
shell rm -f delete_my_watchpoint
shell tail -n 1 all_watchpoints | awk ' {print "delete "$1 }' > delete_my_watchpoint
watch v3
echo Done\n
c
end
b 9
commands
source delete_my_watchpoint
info watchpoints
end
r
This is just a sligtly changed version of the .gdbinit that instead of saving a file with the command to delete the watchpoint saves the watchpoint number:
file ./a.out
b 5
commands
watch v2
watch v1
set pagination off
shell rm -f all_watchpoints
set logging file all_watchpoints
set logging on
info watchpoints
set logging off
shell rm -f delete_my_watchpoint
shell tail -n 1 all_watchpoints | awk ' {print "set $watchpoint_to_delete_later="$1 }' > save_my_watchpoint_number
source save_my_watchpoint_number
shell rm -f save_my_watchpoint_number
shell rm -f all_watchpoints
watch v3
echo Done\n
c
end
b 9
commands
delete $watchpoint_to_delete_later
info watchpoints
end
r
If you set a watchpoint using an address in this way:
(gdb) watch *((int*)0x22ff44)
Hardware watchpoint 3: *((int*)0x22ff44)
(gdb) info watchpoints
Num Type Disp Enb Address What
3 hw watchpoint keep y *((int*)0x22ff44)
You can also later find this address since it is dislayed in info watchpoints
(gdb) set logging file all_watchpoints
(gdb) set logging on
Copying output to all_watchpoints.
(gdb) info watchpoints
Num Type Disp Enb Address What
3 hw watchpoint keep y *((int*)0x22ff44)
4 hw watchpoint keep y *((int*)0x22ff48)
5 hw watchpoint keep y *((int*)0x22ff4B)
(gdb) set logging of
Done logging to all_watchpoints.
(gdb) shell grep 0x22ff48 all_watchpoints
4 hw watchpoint keep y *((int*)0x22ff48)
(gdb) shell grep 0x22ff48 all_watchpoints | awk ' {print $1}'
4
(gdb) shell grep 0x22ff48 all_watchpoints | awk ' {print "delete "$1}' > delete_watchpoint
(gdb) source delete_watchpoint
(gdb) info watchpoints
Num Type Disp Enb Address What
3 hw watchpoint keep y *((int*)0x22ff44)
5 hw watchpoint keep y *((int*)0x22ff4B)
Related
I am trying to debug two instances of the same application. Therefore I setup as followed:
(gdb) set target-async on
(gdb) set non-stop on
(gdb) attach pid1
(gdb) set scheduler-locking off
(gdb) add-inferior
(gdb) inferior 2
(gdb) attach pid2
(gdb) set scheduler-locking off
(gdb) b hello-world.cpp:8
Breakpoint 1 at 0x557a557761fd: ../hello-world.cpp:8. (2 locations)
(gdb) continue
The Problem I have is that only the currently selected inferior is continued. Is there a way to let all inferiors continue with one command?
Solution:
It works if the following sequnce is used:
(gdb) attach pid1
(gdb) add-inferior
(gdb) inferior 2
(gdb) attach pid2
(gdb) set schedule-multiple on
(gdb) b hello-world.cpp:8
Breakpoint 1 at 0x557a557761fd: ../hello-world.cpp:8. (2 locations)
(gdb) continue
Thanks to Klaus!
To continue all attached processes you have to set the scheduler mode in gdb.
set scheduler-locking off
A continue now let all threads continue.
For a detailed description of scheduler mode take a look here
As you ask in the comments what the complete procedure was:
(gdb) attach <pid 1>
(gdb) add-inferior
(gdb) inferior 2
(gdb) attach <pid 2>
(gdb) set scheduler-locking off
(gdb) b myprog.cpp:55
When I hit a breakpoint in GDB, and I need to find out what thread this is on, I do info thr. This prints out the list of all the threads in my program, and the current thread is marked with a *
Instead of having GDB dump the entire list of threads, and then manually reading what thread has the *, is there a command in gdb which simply prints out the current thread?
I need this because I am logging some behavior in my program. In other words, I have something like this -
(gdb) command 12
>> p " xyz just happpened"
>> whatThreadIsThis // I would like this
>> c
>> end
If GDB implemented something like the whatThreadIsThis command, then I could use GDB to log all occurrences of xyz with the threads they happened on.
You can use the "thread thread-id" command to switch to another thread as the docs mentions. What the docs doesn't seem to mention is that without any argument, it just prints the current thread:
(gdb) thread
[Current thread is 1 (Thread 0x7ffff7fc2700 (LWP 4641))]
gdb also has Convenience Variables.
One of the them is:
$_thread
The thread number of the current thread.
You can print it with:
(gdb) p $_thread
$2 = 2
Also it can be used in conditions:
condition 1 $_thread != 1
Oracle VirtualBox is holding one of the disk files. I want to release the lock on the file without having to kill the process or deleting the file. Is it possible?
Here is the output of lsof:
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
VBoxSVC 2935 vbox 23r REG 8,35 253360058368 12976130 /home/vbox/VirtualBoxVMs/virtm0/virtm0-disk1.vdi
FD = 23r meaning file descriptor 23 and it was opened for reading.
gdb tool can be used to release lock on this file
gdb -p $PID
p close($FD)
eg:
gdb -p 1737
.....
(gdb) p close(6)
$1 = 0
...
Quit anyway? (y or n) y
Detaching from program: /usr/lib/apache2/mpm-prefork/apache2, process 1737
Hope this helps.
(EDIT: per the first answer below the current "trick" seems to be using an Atom processor. But I hope some gdb guru can answer if this is a fundamental limitation, or whether there adding support for other processors is on the roadmap?)
Reverse execution seems to be working in my environment: I can reverse-continue, see a plausible record log, and move around within it:
(gdb) start
...Temporary breakpoint 5 at 0x8048460: file bang.cpp, line 13.
Starting program: /home/thomasg/temp/./bang
Temporary breakpoint 5, main () at bang.cpp:13
13 f(1000);
(gdb) record
(gdb) continue
Continuing.
Breakpoint 3, f (d=900) at bang.cpp:5
5 if(d) {
(gdb) info record
Active record target: record-full
Record mode:
Lowest recorded instruction number is 1.
Highest recorded instruction number is 1005.
Log contains 1005 instructions.
Max logged instructions is 200000.
(gdb) reverse-continue
Continuing.
Breakpoint 3, f (d=901) at bang.cpp:5
5 if(d) {
(gdb) record goto end
Go forward to insn number 1005
#0 f (d=900) at bang.cpp:5
5 if(d) {
However the instruction and function histories aren't available:
(gdb) record instruction-history
You can't do that when your target is `record-full'
(gdb) record function-call-history
You can't do that when your target is `record-full'
And the only target type available is full, the other documented type "btrace" fails with "Target does not support branch tracing."
So quite possibly it just isn't supported for this target, but as it's a mainstream modern one (gdb 7.6.1-ubuntu, on amd64 Linux Mint "Petra" running an "Intel(R) Core(TM) i5-3570") I'm hoping that I've overlooked a crucial step or config?
It seems that there is no other solution except a CPU that supports it.
More precisely, your kernel has to support Intel Processor Tracing (Intel PT). This can be checked in Linux with:
grep intel_pt /proc/cpuinfo
See also: https://unix.stackexchange.com/questions/43539/what-do-the-flags-in-proc-cpuinfo-mean
The commands only works in record btrace mode.
In the GDB source commit beab5d9, it is nat/linux-btrace.c:kernel_supports_pt that checks if we can enter btrace. The following checks are carried out:
check if /sys/bus/event_source/devices/intel_pt/type exists and read the type
do a syscall (SYS_perf_event_open, &attr, child, -1, -1, 0); with the read type, and see if it returns >=0. TODO: why not use the C wrapper?
The first check fails for me: the file does not exist.
Kernel side
cd into the kernel 4.1 source and:
git grep '"intel_pt"'
we find arch/x86/kernel/cpu/perf_event_intel_pt.c which sets up that file. In particular, it does:
if (!test_cpu_cap(&boot_cpu_data, X86_FEATURE_INTEL_PT))
goto fail;
so intel_pt is a pre-requisite.
How I've found kernel_supports_pt
First grep for:
git grep 'Target does not support branch tracing.'
which leads us to btrace.c:btrace_enable. After a quick debug with:
gdb -q -ex start -ex 'b btrace_enable' -ex c --args /home/ciro/git/binutils-gdb/install/bin/gdb --batch -ex start -ex 'record btrace' ./hello_world.out
Virtual box does not support it either: Extract execution log from gdb record in a VirtualBox VM
Intel SDE
Intel SDE 7.21 already has this CPU feature, checked with:
./sde64 -- cpuid | grep 'Intel processor trace'
But I'm not sure if the Linux kernel can be run on it: https://superuser.com/questions/950992/how-to-run-the-linux-kernel-on-intel-software-development-emulator-sde
Other GDB methods
More generic questions, with less efficient software solutions:
call graph: List of all function calls made in an application
instruction trace: Displaying each assembly instruction executed in gdb
At least a partial answer (for the "am I doing it wrong" aspect) - from gdb-7.6.50.20140108/gdb/NEWS
* A new record target "record-btrace" has been added. The new target
uses hardware support to record the control-flow of a process. It
does not support replaying the execution, but it implements the
below new commands for investigating the recorded execution log.
This new recording method can be enabled using:
record btrace
The "record-btrace" target is only available on Intel Atom processors
and requires a Linux kernel 2.6.32 or later.
* Two new commands have been added for record/replay to give information
about the recorded execution without having to replay the execution.
The commands are only supported by "record btrace".
record instruction-history prints the execution history at
instruction granularity
record function-call-history prints the execution history at
function granularity
It's not often that I envy the owner of an Atom processor ;-)
I'll edit the question to refocus upon the question of workarounds or plans for future support.
I want to write a script for gdb, which will save backtrace (stack) of process every 10 ms. How can I do this?
It can be smth like call graph profiling for 'penniless' (for people, who can't use any sort of advanced profiler).
Yes, there are a lot of advanced profilers. For popular CPUs and for popular OSes. Shark is very impressive and easy to use, but I want to get a basic functionality with such script, working with gdb.
Can you get lsstack? Perhaps you could run that from a script outside your app. Why 10ms? Percentages will be about the same at 100ms or more. If the app is too fast, you could artificially slow it down with an outer loop, and that wouldn't change the percentages either. For that matter, you could just use Ctrl-C to get the samples manually under gdb, if the app runs long enough and if your goal is to find out where the performance problems are.
(1) Manual. Execute the following in a shell. Keep pressing Ctrl+C repeatedly on shell prompt.
gdb -x print_callstack.gdb -p pid
or, (2) send signals to pid repeatedly same number of times on another shell as in below loop
let count=0; \
while [ $count -le 100 ]; do \
kill -INT pid ; sleep 0.10; \
let $count=$count+1; \
done
The source of print_callstack.gdb from (1) is as below:
set pagination 0
set $count = 0
while $count < 100
backtrace
continue
set $count = $count + 1
end
detach
quit
man page of pstack https://linux.die.net/man/1/pstack
cat > gdb.run
set pagination 0
backtrace
continue
backtrace
continue
... as many more backtrace + continue's as needed
backtrace
continue
detach
quit
Of course, omit the duplicate newlines, how do you do single newlines in this forum software? :(
gdb -x gdb.run -p $pid
Then just use do
kill -INT $pid ; sleep 0.01
in a loop in another script.
kill -INT is what the OS does when you hit ctrl-C. Exercise for the reader: make the gdb script use a loop with $n iterations.