【问题标题】:LLDB Python API SBAddress constructor errorLLDB Python API SBAddress 构造函数错误
【发布时间】:2016-07-07 17:40:23
【问题描述】:

我正在尝试从我拥有的地址值创建一个 SB 值,但我遇到了 SBAddress 构造函数的问题。当我这样做时:

target = lldb.debugger.GetSelectedTarget()
pointer = target.FindFirstType('node_t').GetPointerType()
root = target.CreateValueFromAddress('root', lldb.SBAddress(0x100004058, target), pointer)

然后我运行

root.GetValue()

我得到类似 0x0000000100004041 的东西

我在这里使用 SBAddress 的构造函数有什么问题吗?

【问题讨论】:

    标签: lldb


    【解决方案1】:

    您必须小心指出什么是正确的。 0x100004058 是您要从中创建类型的指针的值,还是该指针的位置?我怀疑是前者……

    位于指针值地址的内存保存一个“node_t”类型的对象。因此,当您想从该内存中创建一个 SBValue 时,您想要的类型是“node_t”而不是“node_t *”。

    但是,如果 0x100004058 是指针的位置,那么在该地址处将值作为指向 node_t 的指针是正确的。

    所以,例如,停在这里:

    * thread #1: tid = 0x4ae2e3, function: take_void , stop reason = breakpoint 1.1
        frame #0: 0x0000000100000f33 pointers`take_void at pointers.c:12
       9    void
       10   take_void(void *input)
       11   {
    -> 12     printf("Got pointer: %p.\n", input);
       13   }
       14       
       15   int
    

    调用自:

       15   int
       16   main()
       17   {
       18     struct Foo my_foo = {111, 222};
       19     take_void (&my_foo);
       20     return 0;
       21   }
    

    然后:

    (lldb) fr v -L
    0x00007fff5fbff658: (void *) input = 0x00007fff5fbff670
    

    第一个地址是输入的位置,所以:

    (lldb) script
    >>> ptr_type = lldb.target.FindFirstType('Foo').GetPointerType()
    >>> root = lldb.target.CreateValueFromAddress("root", lldb.SBAddress(0x00007fff5fbff658, lldb.target), ptr_type)
    >>> root.GetValue()
        '0x00007fff5fbff670'
    

    这是您所期望的。并且:

    >>> root = lldb.target.CreateValueFromAddress("root", lldb.SBAddress(0x00007fff5fbff670, lldb.target), type)
    >>> root.GetValue()
    

    没错,因为结构没有值。并且:

    >>> root.GetChildAtIndex(0).GetValue()
    '111'
    >>> root.GetChildAtIndex(1).GetValue()
    '222'
    

    这些是我在字段中输入的值,这是正确的。并且:

    >>> root = lldb.target.CreateValueFromAddress("root", lldb.SBAddress(0x00007fff5fbff670, lldb.target), ptr_type)
    >>> root.GetValue()
    '0x000000de0000006f'
    

    (这可能是您犯的错误)也很有意义,因为 0xde 是 222 而 0x6f 是 111 并且我使用的是 little-endian 系统...

    【讨论】:

    • 假设我有一个全局变量“root”,我可以通过运行 root = lldb.target.FindFirstGlobalVariable('root') 来获得它,然后我运行 root.GetValue() 这给了我值 0x100004058 和 root.GetType() 给我'node_t *'。现在我想通过使用 lldb.target.CreateValueFromAddress() 创建相同的变量,并从 root.GetType() 获得相同的结果。这就是我遇到问题的地方。
    • 指针的值是指针指向的内存。驻留在该内存中的对象是该指针的指针类型。因此,在您的情况下,当您从“根”对象上的 GetValue 返回的地址创建值时,您要使用的类型是“node_t”而不是“node_t *”。
    • 对。我明白了,谢谢。只想问一个问题。在您给出的上述示例中, root.GetValue() 返回 None 因为结构没有“值”。但实际上它包含两个具有合法价值的孩子。假设我传入了一个有垃圾的无效地址,root.GetValue() 仍然返回 None,它仍然说 root.GetNumChildren() 函数有两个孩子。但是当然,当调用 GetValue() 时,这两个孩子会返回 None。有没有更简单的方法来查找根变量是否实际上包含垃圾?
    • 该值通常很糟糕,因为它不可读。因此,当您在 CreateValueFromAddress 中获取 root 的值时,就会出现内存读取错误。 SBValue::GetError() 会给你那个错误(你应该在每次 make 和 SBValue 时检查这个。SBError 会告诉你创建是成功还是失败,并且有一个包含更多细节的字符串。
    • 好的,在这里我也看到了同样的问题,运行 root.GetChildMemberWithName('data').GetChildAtIndex(0).GetError() 返回存在读取内存错误的事实,但正在运行root.GetError() 只返回“成功”。我特别想知道根变量中的成员字段是否是垃圾。
    【解决方案2】:

    我正在使用SBValue 自己的CreateValueFromAddress 方法。它没有很好地记录,但我已经弄清楚了参数,它们比目标更简单。像这样使用它(不需要特殊的地址函数,只需简单的 + 运算符):

    offset_in_bytes = base_address + some_offset
    some_other_sbvalue.CreateValueFromAddress("name-of-new-value", offset_in_bytes, value_type)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-05-25
      • 2018-11-15
      • 2012-07-01
      • 1970-01-01
      • 2013-03-05
      • 1970-01-01
      • 2021-03-18
      相关资源
      最近更新 更多