使用gdb计算机器指令

时间:2014-02-07 12:37:32

标签: x86 gdb tracing

我需要根据x86机器指令数来估计程序中某些热点的确切起始位置(以便稍后可以在某些模拟器/模拟器中运行)。有没有办法使用gdb来计算执行到断点的机器指令的数量?

当然还有其他选择,我可以使用仿真/二进制检测工具(如Pin),并在计算指令时跟踪运行,但这需要在我工作的每个平台上安装此工具 - 并非总是可行。我需要一些可以在任何linux机器上使用的工具。

使用gdb,我猜也可以在大步幅上运行stepi X作为某种粗粒度搜索,直到我们到达断点,然后以降低分辨率重复,但这将是极其缓慢的。还有另一种方法吗?

3 个答案:

答案 0 :(得分:15)

试试这个:

set pagination off
set $count=0
while ($pc != 0xyourstoppingaddress)
stepi
set $count++
end
print $count

然后去喝杯咖啡。或者是一顿长长的午餐。

答案 1 :(得分:3)

这实际上只是对Mark解决方案可用性的略微改进。

我们可以定义一个函数do_count

define do_count
set $count=0
while ($pc != $arg0)
stepi
set $count=$count+1
end
print $count
end

然后可以重复使用此函数来反复计算步数:

set pagination off
do_count 0xaddress1
do_count 0xaddress2

甚至可以将此定义放入主文件夹中的.gdbinit(在Linux上,在Windows上,它应该被称为gdb.ini),因此它在gdb启动后自动变为可用(使用show user查看函数是否已加载)。

答案 2 :(得分:1)

如果你真的想要一个循环计数(可能是已知IPC的指令计数的近似值),并且你在裸机ARM上运行,你可能能够读取循环计数器,参见例如{{ 3}}

在您的场景中,我会尝试Cycle counter on ARM Cortex M4 (or M3)?来获取已用完的指令数(自GDB 7.0起可用,之后进行了改进):

  1. 开始测量:record btrace(如果前者不可用,则为record full。)
  2. continue执行(直到断点,或使用next或其他命令逐步完成)。
  3. 获取衡量标准:info record
  4. 清除记录的结果:record stop(建议缓冲区的大小有限)。
  5. 示例:

    (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)).
    

    限制:

    • 记录缓冲区的大小有限(对于上面的BTS格式,可以使用set record btrace pt buffer-size <size>增加,有关其他类型,请参阅Process Record and Replay。)
    • 使用record full,并非所有指令都可以捕获。值得注意的是,SSE和AVX指令不受支持,将导致gdb暂停执行。
    • 录制每条指令时会有一些开销(特别是使用完整格式)。虽然它不应该像其他答案中描述的gdb步骤方法一样糟糕(每次都必须通过ptrace)。