【问题标题】:LLDB Show trap opcodes in memory dumpLLDB 在内存转储中显示陷阱操作码
【发布时间】:2020-04-03 03:08:13
【问题描述】:

我想知道 LLDB 的内存转储器是否可以在我刚刚设置了一个断点的位置查看陷阱操作码? 正如我所见,LLDB 足够聪明,可以用原始操作码隐藏陷阱操作码:

(lldb) memory read --format instruction --count 5 0x00000076619b5478
->  0x76619b5478: 0xf9401668   ldr    x8, [x19, #0x28]
    0x76619b547c: 0xf9400289   ldr    x9, [x20]
    0x76619b5480: 0xeb09011f   cmp    x8, x9
    0x76619b5484: 0x540000e1   b.ne   0x76619b54a0              ; <+200>
    0x76619b5488: 0xa95d7bf3   ldp    x19, x30, [sp, #0x1d0]
(lldb) breakpoint set --address 0x76619b5488
Breakpoint 3: where = libface_detector_v2_jni.so`___lldb_unnamed_symbol20247$$libface_detector_v2_jni.so + 176, address = 0x00000076619b5488
(lldb) memory read --format instruction --count 5 0x00000076619b5478
->  0x76619b5478: 0xf9401668   ldr    x8, [x19, #0x28]
    0x76619b547c: 0xf9400289   ldr    x9, [x20]
    0x76619b5480: 0xeb09011f   cmp    x8, x9
    0x76619b5484: 0x540000e1   b.ne   0x76619b54a0              ; <+200>
    0x76619b5488: 0xa95d7bf3   ldp    x19, x30, [sp, #0x1d0]

在这里,我在0x76619b5488 设置了一个休息点,但 dumper 仍然在那个地方显示原始指令。 help memory read 没有关于如何看到陷阱操作码的提示。

有什么想法吗?

附:它是一个与 Android SDK 捆绑在一起的 LLDB,声称版本:7.0.0。目标是 Android Aarch64。

【问题讨论】:

    标签: linux android-ndk gdb llvm lldb


    【解决方案1】:

    在这里我在 0x76619b5488 处设置了一个中断,但转储程序仍然在该位置显示原始指令。

    这是非常典型的调试器:他们不想让您与他们插入的断点指令混淆,因此向您显示内存的原始内容。

    在 x86 上,执行任何其他操作都会使指令流不同步(因为指令是可变长度的),因此显示插入断点的 实际 指令会产生完全的垃圾。

    如何看到陷阱操作码

    您可以复制(拍摄快照)内存区域(例如 1 个函数的内存价值),并在该函数上有断点时将其与当前内容进行比较。他们不会匹配。这是程序可以检测到它正在被调试的方式之一。

    然后您可以要求 LLDB 反汇编复制的区域(对于插入断点后获取的副本),您将看到您希望观察的断点(但相对于 IP 的偏移量将指向错误的位置)。

    我不知道实现这一目标的更简单方法。

    【讨论】:

    • 他/她不能检查内存并查看断点吗?像x/16b 0x76619b5470 这样的东西。或者调试器会知道提供熟值吗?
    • @jww 我不了解 LLDB,但 GDB 提供“熟”值。我希望 LLDB 也会这样做——通常这是在低级“读取内存”例程中实现的,它知道如何从 coreRAMremote 读取实际内存(取决于正在使用哪个后端) 并“煮”它以删除断点。 examinedisassemble 然后都使用这个低级的read_mem 并且不需要担心底层细节。
    • @EmployedRussian 聪明的把戏!令人惊讶的是,expression -- printf("%x\n", *((unsigned*)&lt;patched_location_addr&gt;)) 也能够打印陷阱字节。可能评估引擎允许直接读取,从而绕过您一直在谈论的调试器的内存访问子系统。是否应该将其视为错误...
    • 上次我处理它时,gdb 在停止时删除所有断点,并在继续时重新插入它们。这可能就是您在上面显示的表达式中看不到陷阱的原因。当有很多很多断点时,我们想让 lldb 变得更快,所以 lldb 不这样做,它会留下陷阱。由于表达式访问进程的实际内存 - 然后它们将看到这些陷阱。 IMO,不必在每一站都处理陷阱的好处非常值得这个小怪异。
    • “cooking”发生在内存由 debugserver 或 lldb 提供时,程序的内存中仍有陷阱。由于表达式实际上是在目标程序中运行的(例如 printf 就像语句是源代码的一部分一样运行),如果您没有删除陷阱,那么在表达式中运行的代码将看到它们。这实际上很有用 - 如果您想调试带有奇怪输入的函数,请在其中设置断点,然后使用 expr -i 0 -- 调用该函数,然后调试代码。所以我们真的不能用这种方式对你隐藏陷阱。
    猜你喜欢
    • 2014-02-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-03
    • 2011-10-07
    • 1970-01-01
    • 2012-10-22
    • 2010-11-19
    相关资源
    最近更新 更多