使用 LLDB API 获取使用 ARM-GCC 编译的 elf 文件中表达式的地址

Posted

技术标签:

【中文标题】使用 LLDB API 获取使用 ARM-GCC 编译的 elf 文件中表达式的地址【英文标题】:Using LLDB API to get the address of an expression in an elf file compiled with ARM-GCC 【发布时间】:2021-03-21 00:29:30 【问题描述】:

假设 ARM .elf 文件在 .cpp 文件中具有嵌套结构,我可以使用 LLDB 计算表达式以获取全局结构/数组元素的地址。

lldb my_arm.elf
(lldb) ex &user_data.sub_type[2].i[3]

这给出了预期的结果,

(int *) $1 = 0x200001f0

...类似于 gdb,具有类型、索引和 RAM 中的地址,用于指定的 C/C++ 结构元素。 LLDB 还可以评估像 '&main'、'1+1' 等表达式。

尝试使用 lldb API 中的 EvaluateExpression() 在 python 中做同样的事情,总是会导致 !IsValid()。

import lldb  # this works in python in linux.
dbg = lldb.SBDebugger().Create()
dbg.SetAsync(False)
modspec = lldb.SBModuleSpec()
modspec.SetFileSpec(lldb.SBFileSpec("my_arm.elf"))
modspec.SetSymbolFileSpec(lldb.SBFileSpec("my_arm.elf"))
target.AddModule(modspec)  # target.IsValid() is True.
val=target.EvaluateExpression('&user_data.sub_type[2].i[3]')

这是 lldb 的 Python 外部val.IsValid() 始终为 False,我似乎无法从表达式中获取值。 '&main' 和 '1+1' 等更简单的表达式给出了类似的结果。

如何使用 lldb API 评估 .elf 文件的表达式?

【问题讨论】:

看起来您正在尝试评估没有正在运行的进程的表达式。表达式求值器确实有一个解释器模式,当没有正在运行的进程时它会回退,但这不是表达式求值器的主要模式。如果要查看全局数据target var是首选模式。它还支持子元素和数组访问,但当然不调用函数或做任何需要在目标进程中执行代码的事情。此外,SBValue 有一个 SBError (SBValue.GetError()),它会告诉你表达式失败的原因。 Jim Ingham,是的,我正在尝试在不运行进程的情况下评估表达式。这些表达式通常用于交叉编译的 .elf 文件,因此运行该过程是不可行或不必要的。显然,.elf 文件具有在不运行进程的情况下评估这些表达式的必要信息——lldb 可以做到这一点,但我的努力是弄清楚如何让 API 做同样的事情。感谢您的建议。 【参考方案1】:

如此接近。您的程序的这种简化提供了预期的结果。

import lldb
dbg = lldb.SBDebugger().Create()
target = dbg.CreateTarget("my_arm.elf")
val = target.EvaluateExpression("&user_data.sub_type[2].i[3]")
print("'0', type=1, name=2, value=3, result=4".format(val, val.type, val.name, val.value, val.GetError()))

结果是:

'(int *) $0 = 0x200001f0', type=int *, name=$0, value=0x200001f0, result=success

...这与 gdb 给出的结果相似,但包含更多关于评估的表达式值的信息,并且使用 lldb 库在进程中快速完成。

【讨论】:

以上是关于使用 LLDB API 获取使用 ARM-GCC 编译的 elf 文件中表达式的地址的主要内容,如果未能解决你的问题,请参考以下文章

在 LLDB 中获取有关坏内存地址的信息

LLDB原理与调试实践

Xcode/LLDB:如何获取有关刚刚抛出的异常的信息?

LLDB使用篇(上)

紧急求助!ARM-GCC对于函数指针调用的编译有错误?已经找到原因

快速在 LLDB 中使用 po