为了解决Apple的 lldb (rdar:// 13702081)中的错误,我经常需要按顺序键入两个命令,如下所示:
(lldb) p todo.matA
(vMAT_Array *) $2 = 0x000000010400b5a0
(lldb) po $2.dump
$3 = 0x0000000100503ce0 <vMAT_Int8Array: 0x10400b5a0; size: [9 1]> =
1
1
1
1
1
1
1
1
1
是否可以使用可以为我组合这些步骤的Python库(或其他东西)编写新的 lldb 命令?理想情况下:
(lldb) pmat todo
$3 = 0x0000000100503ce0 <vMAT_Int8Array: 0x10400b5a0; size: [9 1]> =
1
1
1
1
1
1
1
1
1
感谢Jason Molenda,这是一个正在运行的 lldb 命令脚本的输出:
(lldb) pmat Z
$0 = 0x0000000100112920 <vMAT_DoubleArray: 0x101880c20; size: [9 3]> =
7 9 0.848715
3 5 0.993378
0 1 1.11738
4 12 1.2013
11 13 1.20193
6 10 1.29206
14 15 1.53283
8 16 1.53602
2 17 1.68116
我必须非常轻微地调整下面答案中提供的脚本,使用Jason的建议来解决过于复杂的表达式的 lldb 错误。这是我的最终剧本:
# import this into lldb with a command like
# command script import pmat.py
import lldb
import shlex
import optparse
def pmat(debugger, command, result, dict):
# Use the Shell Lexer to properly parse up command options just like a
# shell would
command_args = shlex.split(command)
parser = create_pmat_options()
try:
(options, args) = parser.parse_args(command_args)
except:
return
target = debugger.GetSelectedTarget()
if target:
process = target.GetProcess()
if process:
frame = process.GetSelectedThread().GetSelectedFrame()
if frame:
var = frame.FindVariable(args[0])
if var:
array = var.GetChildMemberWithName("matA")
if array:
id = array.GetValueAsUnsigned (lldb.LLDB_INVALID_ADDRESS)
if id != lldb.LLDB_INVALID_ADDRESS:
debugger.HandleCommand ('po [0x%x dump]' % id)
def create_pmat_options():
usage = "usage: %prog"
description='''Print a dump of a vMAT_Array instance.'''
parser = optparse.OptionParser(description=description, prog='pmat',usage=usage)
return parser
#
# code that runs when this script is imported into LLDB
#
def __lldb_init_module (debugger, dict):
# This initializer is being run from LLDB in the embedded command interpreter
# Make the options so we can generate the help text for the new LLDB
# command line command prior to registering it with LLDB below
# add pmat
parser = create_pmat_options()
pmat.__doc__ = parser.format_help()
# Add any commands contained in this module to LLDB
debugger.HandleCommand('command script add -f %s.pmat pmat' % __name__)
答案 0 :(得分:6)
您可以使用regex命令或通过创建自己的python命令并将其加载到lldb来执行此操作。在这个特定的例子中,正则表达式命令对你没有帮助,因为你会击中你正在击中的同一个crasher。但为了好玩,我会展示两种解决方案。
首先,python。此python代码获取当前所选线程上当前选定的帧。它查找在命令参数上提供名称的变量。它找到一个名为matA
的变量的子项,并在该SBValue对象上运行GetObjectDescription()
。
# import this into lldb with a command like
# command script import pmat.py
import lldb
import shlex
import optparse
def pmat(debugger, command, result, dict):
# Use the Shell Lexer to properly parse up command options just like a
# shell would
command_args = shlex.split(command)
parser = create_pmat_options()
try:
(options, args) = parser.parse_args(command_args)
except:
return
target = debugger.GetSelectedTarget()
if target:
process = target.GetProcess()
if process:
frame = process.GetSelectedThread().GetSelectedFrame()
if frame:
var = frame.FindVariable(args[0])
if var:
child = var.GetChildMemberWithName("matA")
if child:
print child.GetObjectDescription()
def create_pmat_options():
usage = "usage: %prog"
description='''Call po on the child called "matA"'''
parser = optparse.OptionParser(description=description, prog='pmat',usage=usage)
return parser
#
# code that runs when this script is imported into LLDB
#
def __lldb_init_module (debugger, dict):
# This initializer is being run from LLDB in the embedded command interpreter
# Make the options so we can generate the help text for the new LLDB
# command line command prior to registering it with LLDB below
# add pmat
parser = create_pmat_options()
pmat.__doc__ = parser.format_help()
# Add any commands contained in this module to LLDB
debugger.HandleCommand('command script add -f %s.pmat pmat' % __name__)
使用中,
(lldb) br s -p break
Breakpoint 2: where = a.out`main + 31 at a.m:8, address = 0x0000000100000eaf
(lldb) r
Process 18223 launched: '/private/tmp/a.out' (x86_64)
Process 18223 stopped
* thread #1: tid = 0x1f03, 0x0000000100000eaf a.out`main + 31 at a.m:8, stop reason = breakpoint 2.1
#0: 0x0000000100000eaf a.out`main + 31 at a.m:8
5 @autoreleasepool {
6 struct var myobj;
7 myobj.matA = @"hello there";
-> 8 printf ("%s\n", [(id)myobj.matA UTF8String]); // break here
9 }
10 }
(lldb) p myobj
(var) $0 = {
(void *) matA = 0x0000000100001070
}
(lldb) comm scri imp ~/lldb/pmat.py
(lldb) pmat myobj
hello there
(lldb)
如果您想使用command script import
文件,可以将~/.lldbinit
行放在其中。
一旦大致了解调试器的结构,就可以轻松使用Python API。我知道我会根据框架找到变量,所以我查看了SBFrame
对象的帮助
(lldb) script help (lldb.SBFrame)
方法FindVariable
返回SBValue
,然后我查看了lldb.SBValue
帮助页等等。上面的示例python中有很多样板文件 - 你真的在看完成所有工作的4行python。
如果这仍然触发了崩溃你的lldb进程的代码路径,你可以分两部分完成脚本的最后一点 - 获取对象的地址并在该原始地址上运行po。 e.g。
child = var.GetChildMemberWithName("matA")
if child:
id = child.GetValueAsUnsigned (lldb.LLDB_INVALID_ADDRESS)
if id != lldb.LLDB_INVALID_ADDRESS:
debugger.HandleCommand ('po 0x%x' % id)
其次,使用命令regex:
(lldb) br s -p break
Breakpoint 1: where = a.out`main + 31 at a.m:8, address = 0x0000000100000eaf
(lldb) r
Process 18277 launched: '/private/tmp/a.out' (x86_64)
Process 18277 stopped
* thread #1: tid = 0x1f03, 0x0000000100000eaf a.out`main + 31 at a.m:8, stop reason = breakpoint 1.1
#0: 0x0000000100000eaf a.out`main + 31 at a.m:8
5 @autoreleasepool {
6 struct var myobj;
7 myobj.matA = @"hello there";
-> 8 printf ("%s\n", [(id)myobj.matA UTF8String]); // break here
9 }
10 }
(lldb) command regex pmat 's/(.*)/po %1.matA/'
(lldb) pmat myobj
$0 = 0x0000000100001070 hello there
(lldb)
在这个实例中你不能使用更简单的command alias
- 你必须使用正则表达式别名 - 因为你正在调用一个接受原始输入的命令。具体来说,po
实际上是expression
的别名,您需要使用正则表达式命令别名将值替换为这些别名。