Try this:
set pagination off
set $count = 0
while $pc != 0xyourstoppingaddress
stepi
set $count++
end
print $count
Then go get a cup of coffee. Or a long lunch.
Pregunta
I need to estimate the exact starting location of some hotspot in a program, in terms of x86 machine instruction count (so that it can later be run in some emulator/simulator). Is there a way to use gdb to count the number of machine instructions being executed up to a breakpoint?
There are other alternatives of course, I could use a emulation / binary instrumentation tool (like Pin), and track the run while counting instructions, but that would require installing this tool on every platform I work on - not always possible. I need some tool that's available on pretty much any linux machine.
With gdb, I guess it's also possible to run stepi X
over large strides as some sort of coarse grained search until we hit the breakpoint, then repeat with reduced the resolution, but that would be excruciatingly slow. Is there another way to do this?
Solución
Try this:
set pagination off
set $count = 0
while $pc != 0xyourstoppingaddress
stepi
set $count++
end
print $count
Then go get a cup of coffee. Or a long lunch.
Otros consejos
This is actually only a slight improvement of the usability of Mark's solution.
We can define a function do_count
:
define do_count
set $count=0
while ($pc != $arg0)
stepi
set $count=$count+1
end
print $count
end
and then this function can be reused for counting the number of steps over and over again:
set pagination off
do_count 0xaddress1
do_count 0xaddress2
One can even put this definition into .gdbinit
(on Linux, on Windows it should be called gdb.ini
) in the home-folder, so it becomes available automatically after the start of the gdb (use show user
to see, whether the function was loaded).
If you actually want a cycle count (maybe as an approximation of instruction count with known IPC), and you're running on bare metal ARM, you might be able to read the cycle counter, see for example Cycle counter on ARM Cortex M4 (or M3)?
In your scenario, I would try Process Record and Replay to obtain the elapsed instruction count (available since GDB 7.0 and improved afterwards):
record btrace
(or record full
if the former is not available).continue
execution (until a breakpoint, or use next
or other commands to step through).info record
record stop
(recommended as the buffer is of limited size).Example:
(gdb) record btrace (gdb) frame #0 __sanitizer::InitTlsSize () at .../lib/sanitizer_common/sanitizer_linux_libcdep.cc:220 220 void *get_tls_static_info_ptr = dlsym(RTLD_NEXT, "_dl_get_tls_static_info"); (gdb) info record Active record target: record-btrace Recording format: Branch Trace Store. Buffer size: 64kB. Recorded 0 instructions in 0 functions (0 gaps) for thread 1 (Thread 0xf7c92300 (LWP 20579)). (gdb) next 226 ... (gdb) info record Active record target: record-btrace Recording format: Branch Trace Store. Buffer size: 64kB. Recorded 2859 instructions in 145 functions (0 gaps) for thread 1 (Thread 0xf7c92300 (LWP 20579)).
Limitations:
set record btrace pt buffer-size <size>
for the BTS format above, see the documentation for other types).record full
, not all instructions can be captured. Notably, SSE and AVX instructions are unsupported and will cause gdb to pause execution.