For example:
dprintf main,"hello\n"
run
Generates the same output as:
break main
commands
silent
printf "hello\n"
continue
end
run
Is there a significant advantage to using dprintf
over commands
, e.g. it is considerably faster (if so why?), or has some different functionality?
I imagine that dprintf could be in theory faster as it could in theory compile and inject code with a mechanism analogous to the compile code
GDB command.
Or is it mostly a convenience command?
Source
In the 7.9.1 source, breakpoint.c:dprintf_command
, which defines dprintf
, calls create_breakpoint
which is also what break_command
calls, so they both seem to use the same underlying mechanism.
The main difference is that dprintf
passes the dprintf_breakpoint_ops
structure, which has different callbacks and gets initialized at initialize_breakpoint_ops
.
dprintf
stores list of command strings much like that of commands
command, depending on the settings. They are:
- set at
update_dprintf_command_list
- which gets called on after a
type == bp_dprintf
check insideinit_breakpoint_sal
- which gets called by
create_breakpoint
.
When a breakpoint is reached:
bpstat_stop_status
gets called and invokesb->ops->after_condition_true (bs);
for the breakpoint reachedafter_condition_true
fordprintf
isdprintf_after_condition_true
bpstat_do_actions_1
runs the commands
Quick benchmark
loop.c
#include <inttypes.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv) {
uintmax_t i, j, period, max;
if (argc > 1) {
max = strtoumax(argv[1], NULL, 10);
} else {
max = 10;
}
if (argc > 2) {
period = strtoumax(argv[2], NULL, 10);
} else {
period = 1;
}
i = 0;
j = 0;
while (1) {
if (period != 0 && i % period == 0) {
printf("%ju\n", j);
j++;
}
i++; /* line 25 */
if (i == max)
break;
}
}
Compile and run:
gcc -ggdb3 -O0 -std=c99 -Wall -Wextra -pedantic -o loop.out loop.c
loop.gdb
b 25
commands
silent
printf "%d\n", i
c
end
Benchmark:
$ time gdb -n -q -batch -ex 'tb 39' -ex run -ex 'compile code printf("hello: %d\n", i)' -ex c -args ./loop.out 10000 0
So we see that both dprintf
and commands
slow things down massively, and that dprintf
is only marginally faster than an equivalent commands
.
I've asked if there's a way to use compile code
to speed things up at: GDB compile code and don't remove injected code after execution
Tested on Ubuntu 22.10, GDB 12.1.