我想解决的问题是我想动态计算给定其地址的指令的长度(来自GDB内)和set
该长度作为变量值的长度。挑战在于我不希望在控制台上打印任何无关的输出(例如反汇编指令等)。
我的正常做法是x/2i ADDR
,然后减去这两个地址。我想自动实现同样的事情;但是,我不想在控制台上打印任何东西。如果我可以禁用控制台输出,那么我可以通过x/2i ADDR
执行此操作,然后执行$_ - ADDR
。
我还没有找到一种方法来禁用GDB中的命令输出。如果你知道这样的话请告诉我!但是,我发现了interpreter-exec
和GDB / MI。快速测试表明,x/2i
可以在GDB / MI上运行,并且由MI解释器计算的$_
的值与控制台解释器共享。不幸的是,这种方法也会产生很多输出。
有没有人知道如何计算指令的长度而不显示任何内容,或者如何禁用interpreter-exec
的输出,从而让我实现目标?谢谢。
答案 0 :(得分:5)
我会给出一个可以说更清洁,更具可扩展性的解决方案,而不是真的更短。它实现$instn_length()
作为新的GDB便利功能。
将此保存到 instn-length.py
import gdb
def instn_length(addr_expr):
t = gdb.execute('x/2i ' + addr_expr, to_string=True)
return long(gdb.parse_and_eval('$_')) - long(gdb.parse_and_eval(addr_expr))
class InstnLength(gdb.Function):
def __init__(self):
super(InstnLength, self).__init__('instn_length')
def invoke(self, addr):
return instn_length(str(long(addr)))
InstnLength()
然后运行
$ gdb -q -x instn-length.py /bin/true
Reading symbols from /usr/bin/true...Reading symbols from /usr/lib/debug/usr/bin/true.debug...done.
done.
(gdb) start
Temporary breakpoint 1 at 0x4014c0: file true.c, line 59.
Starting program: /usr/bin/true
Temporary breakpoint 1, main (argc=1, argv=0x7fffffffde28) at true.c:59
59 if (argc == 2)
(gdb) p $instn_length($pc)
$1 = 3
(gdb) disassemble /r $pc, $pc + 4
Dump of assembler code from 0x4014c0 to 0x4014c4:
instn_length()的另一种实现是在GDB 7.6 +中使用 gdb.Architecture.disassemble()方法:
def instn_length(addr_expr):
addr = long(gdb.parse_and_eval(addr_expr))
arch = gdb.selected_frame().architecture()
return arch.disassemble(addr)[0]['length']
答案 1 :(得分:1)
我找到了合适的解决方案;但是,较短的解决方案将是优选的。此解决方案将日志记录文件设置为/dev/null
,如果存在则设置为覆盖,然后暂时将控制台输出重定向到日志文件。
define get-in-length
set logging file /dev/null
set logging overwrite on
set logging redirect on
set logging on
x/2i $arg0
set logging off
set logging redirect off
set logging overwrite off
set $_in_length = ((unsigned long) $_) - ((unsigned long) $arg0)
end
此解决方案受到另一个问题答案的启发:How to get my program name in GDB when writting a "define" script?。