如何从 python LLDB 打印 char ** var

问题描述 投票:0回答:1

我正在尝试使用 python LLDB 库打印出一个 char ** 。 需要明确的是,C 程序中 main 函数中的 char **argv 。 输入的数组中应该有 3 个字符串。

启动 C 程序并立即停止时 主要(int argc,字符**argv) 在 xcode 中,我只需执行 p argv[0] 和 p argv[1] 即可获得要打印的正确参数字符串。

在 python 中,我有一个函数可以打印前 2 个 argv 字符串

def print_argv(argv: lldb.SBValue, target:SBTarget):
    pointer = argv.Dereference()
    summary = pointer.GetSummary().strip('\"')
    print(summary)
    str_len = len(summary)
    next_str_address:int = pointer.GetLoadAddress() + str_len + 1
    pointer_type = pointer.GetType()
    addr = SBAddress(next_str_address, target)
    next_value = target.CreateValueFromAddress("argv", addr, pointer_type)
    summary = next_value.GetSummary().strip('\"')

但是第二个输入不存在。

我尝试了多种不同的方法,但我看不到获得第二根字符串。我尝试使用 argv.GetChildAtIndex ,它适用于 0,但不适用于 1 或 2。我注意到地址按字符串长度偏移,所以我尝试更新指针,再次没有运气。我通过从 C 程序中打印出来来检查输入是否确实存在。

编辑: 以下是如何设置对打印功能的调用

debugger = lldb.SBDebugger.Create()
debugger.SetAsync(False)

target = debugger.CreateTargetWithFileAndArch (str(binary_path), lldb.LLDB_ARCH_DEFAULT)
assert target, "Failed to create target"

target.BreakpointCreateByName ("main", target.GetExecutable().GetFilename())

launch_info = lldb.SBLaunchInfo(str_args)
launch_info.SetWorkingDirectory(os.getcwd())
error = lldb.SBError()
process = target.Launch(launch_info, error)

assert process, "Failed to launch process"
for _ in range(1000):# Putting an upper limit on the number of functions to trace
    state = process.GetState()

    if state == lldb.eStateStopped:
        for thread in process:
            function_name = frame.GetFunctionName()             
            frame = thread.frames[0]
            if function_name in function_names:
                for arg in frame.arguments:
                    if arg.name == "argv":
                        print_argv(arg, 3, target)

    process.Continue()

解决方案: 结果你需要使用 can_create_synthetic==True 。

child = argv.GetChildAtIndex(1, lldb.eNoDynamicValues, True)

python c lldb
1个回答
0
投票

这是一个通用的C vrs。调试器问题,因为 C 允许未指定大小的数组,因此它不会给调试器提供有关如何检查的提示。正如您所发现的,如果您告诉它可以创建“合成子项”来表示元素,那么要解决此问题,lldb 将为您动态自动调整未大小数组的大小。

但是由于您也知道数组的大小(

argc
),因此还有一种更直接且“正确”的方法来执行此操作:

lldb 的 SBType 有一个

SBType::GetArrayType(uint64_t size)
API,它将从任何 C 类型返回给定大小的固定大小数组的类型。因此,实现打印机的简单方法是将
argc
argv
传递给打印函数。正如您所做的那样,从
argv
变量获取指针类型,然后使用指针类型上的
argc
调用创建一个包含
GetArrayType(argc)
元素的数组类型,并使用它代替
CreateValueFromAddress 中的指针类型
.

然后你将得到一个自然具有正确数量的子级的数组,并且你不会冒险意外获取太多元素等。它也没有那么神奇,如果你必须弄清楚这是如何实现的,这很有用经过足够长的时间,你已经忘记了魔法之后,它会再次起作用......

© www.soinside.com 2019 - 2024. All rights reserved.