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:
update_dprintf_command_listtype == bp_dprintf check inside init_breakpoint_salcreate_breakpoint.When a breakpoint is reached:
bpstat_stop_status gets called and invokes b->ops->after_condition_true (bs); for the breakpoint reachedafter_condition_true for dprintf is dprintf_after_condition_truebpstat_do_actions_1 runs the commandsQuick 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.
There are two main differences.
First, dprintf has some additional output modes that can be used to make it work in other ways. See help set dprintf-channel, or the manual, for more information. I think these modes are the reason that dprintf was added as a separate entity; though at the same time they are fairly specialized and unlikely to be of general interest.
More usefully, though, dprintf doesn't interfere with next. If you write a breakpoint and use commands, and then next over such a breakpoint, gdb will forget about the next and act as if you had typed continue. This is a longstanding oddity in the gdb scripting language. dprintf doesn't suffer from this problem. (If you need similar functionality from an ordinary breakpoint, you can do this from Python.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With