LLDB Python/C++ 绑定在 (PIC) 地址处设置断点

LLDB Python/C++ binding set Breakpoint at (PIC) Addr

我正在尝试在通过对象转储二进制文件获得的地址处设置断点。所以我的主要从 0x0000000100000f10 <_main>:

开始

通过使用示例 here 并替换

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

main_bp = target.BreakpointCreateByAddress(0x0000000100000f10)

我在启动目标后得到 process.state = 10 (== lldb.eStateExited),所以它没有到达我的断点。我认为这是因为二进制文件实际上不在这个位置 (PIC)。

直接使用lldb

$ lldb a.out
(lldb) b *0x0000000100000f10
(lldb) r

它停在了正确的位置。那么如何使用 python 绑定重现 'real' lldb 的行为?

lldb版本:lldb-340.4.110(lldb由Xcode提供)
OS: Mac (Yosemite)
Python 2.7.10

LaunchSimple 似乎没有在 SBLaunchInfo 选项中设置 "lldb.eLaunchFlagDisableASLR" 标志。您还可以通过设置符号 "main" 断点来对此进行测试。我确实遇到了那个断点,但是当我检查断点的地址时,它不是二进制文件中记录的主要符号的地址。那是因为二进制文件在启动时滑动(这就是 ASLR 所做的。)

这对我来说似乎是一个错误,因为默认的 LaunchInfo 选项确实禁用了 ASLR,请将其提交到 lldb.llvm.org 的 bugzilla。

如果我用更完整的启动API:

launch_info = lldb.SBLaunchInfo(None)
launch_info.SetExecutableFile (lldb.SBFileSpec(exe), True)

error = lldb.SBError()
process = target.Launch (launch_info, error)

然后 - 至少对我来说 - 二进制文件不会滑动,我点击了我在主符号地址上设置的地址断点。

请注意,通过预加载地址设置断点仅适用于主可执行文件。大多数库都是从零开始构建的,因此它们必须滑动,否则它们会相互加载。在关闭 ASLR 的情况下,库最终将位于相同的地址 运行-to-运行,但它们会滑动一定数量。

Jonas 还问了如何手动解析运行ning 程序中的地址,您可以按如下方式进行。

首先,术语:二进制文件中同一位置的 "before running" 和 "while running" 地址的 lldb 术语分别是 "file" 和 "load" 地址。 lldb 还会调用程序中的所有可加载二进制文件 "modules"...

因此,如果您有一个数字 (lldb::addr_t) 文件地址,您希望从某个地方在模块中解析它,您可以分两步完成。首先使用SBModule::ResolveFileAddressAPI将文件地址变成SBAddress。您可以使用 SBTarget::FindModule 找到该模块。然后,一旦程序 运行ning 加载了您感兴趣的模块,您就可以使用 SBAddress::GetLoadAddress 获取加载地址,并使用它来设置断点。

这唯一不好的部分是在程序 运行ning 之前你将无法获得加载地址(很明显)所以你必须有另一种方法来停止程序在你点击你想要中断的地址之前。通常你可以做一些事情,比如在 main 上放置一个断点,然后完成这项工作。当然,如果你想用这种方式解析 main 的地址,那你就不走运了。但想必您有比 main 更有趣的东西……

这应该更容易,因为应该有一个 API 来使用上面的 SBAddress 设置地址断点。然后 lldb 可以在加载其底层模块时为您解决它。我已经有一个错误,只是还没有得到它。大多数人在符号或源位置上设置断点,因此地址断点没有得到足够的关注。