LLDB中的View数组:相当于Xcode 4.1中GDB的'@'运算符

时间:2011-08-15 06:19:27

标签: xcode debugging xcode4 llvm lldb

我想查看指针指向的元素数组。在GDB中,这可以通过使用运算符'@'将指向的内存视为给定长度的人工数组来完成。

*pointer @ length

其中length是我想要查看的元素数量。

上述语法在随Xcode 4.1提供的LLDB中不起作用。

有没有办法在LLDB中完成上述工作?

9 个答案:

答案 0 :(得分:113)

实际上有一种简单的方法可以通过将指针转换为指向数组的指针来实现。

例如,如果您有int* ptr,并且想要将其视为十个整数的数组,则可以执行

p *(int(*)[10])ptr

因为它仅依赖于标准C功能,所以此方法无需任何插件或特殊设置即可运行。它同样适用于其他调试器,如GDB或CDB,即使它们也有专门的打印数组语法。

答案 1 :(得分:27)

从Xcode 8.0中的lldb开始,有一个新的内置parray命令。所以你可以说:

(lldb) parray <COUNT> <EXPRESSION>

EXPRESSION的结果指向的内存打印为表达式所指向类型的COUNT元素数组。

如果计数存储在当前帧中可用的变量中,请记住您可以执行以下操作:

(lldb) parray `count_variable` pointer_to_malloced_array

这是一个普通的lldb特性,在反引号中包围的lldb中的任何命令行参数都被计算为一个返回整数的表达式,然后在命令执行之前整数被替换为参数。

答案 2 :(得分:26)

我发现的唯一方法是通过Python脚本模块:

""" File: parray.py """
import lldb
import shlex

def parray(debugger, command, result, dict):
    args = shlex.split(command)
    va = lldb.frame.FindVariable(args[0])
    for i in range(0, int(args[1])):
        print va.GetChildAtIndex(i, 0, 1)

在lldb中定义命令“parray”:

(lldb) command script import /path/to/parray.py
(lldb) command script add --function parray.parray parray

现在您可以使用“parray 可变长度”:

(lldb) parray a 5
(double) *a = 0
(double) [1] = 0
(double) [2] = 1.14468
(double) [3] = 2.28936
(double) [4] = 3.43404

答案 3 :(得分:15)

使用Xcode 4.5.1(现在可能有或没有帮助),您可以在lldb控制台中执行此操作:

(lldb) type summary add -s "${var[0-63]}" "float *"
(lldb) frame variable pointer
  (float *) pointer = 0x000000010ba92950 [0.0,1.0,2.0,3.0, ... ,63.0]

此示例假定&#39;指针&#39;是一个包含64个浮点数的数组:float pointer[64];

答案 4 :(得分:12)

似乎还没有得到支持。

您可以使用内存读取功能(内存读取/ x),例如

(lldb) memory read -ff -c10 `test`

从该指针打印浮动十次。这应该与gdb的@。

具有相同的功能

答案 5 :(得分:12)

从Martin R回答开始,我改进了如下:

  1. 如果指针不是简单变量,例如:

    struct {
      int* at;
      size_t size;
    } a;
    

    然后“parray a.at 5”失败。

    我通过将“FindVariable”替换为“GetValueForVariablePath”来修复此问题。

  2. 现在,如果数组中的元素是聚合,例如:

    ,该怎么办?
    struct {
      struct { float x; float y; }* at;
      size_t size;
    } a;
    

    然后“par a.at 5”打印:a.at-&gt; x,a.at-&gt; y,a.at [2],a.at [3],a.at [4]因为GetChildAtIndex()返回聚合的成员。

    我通过在循环中解析“a.at”+“[”+ str(i)+“]”而不是解析“a.at”然后检索它的子节点来解决这个问题。

  3. 添加了一个可选的“第一个”参数(用法:parray [FIRST] COUNT),当您拥有大量元素时,它非常有用。

  4. 让它在init执行“命令脚本添加-f parray.parray parray”

  5. 以下是我的修改版本:

    import lldb
    import shlex
    
    def parray(debugger, command, result, dict):
      args = shlex.split(command)
      if len(args) == 2:
        count = int(args[1])
        indices = range(count)
      elif len(args) == 3:
        first = int(args[1]), count = int(args[2])
        indices = range(first, first + count)
      else:
        print 'Usage: parray ARRAY [FIRST] COUNT'
        return
      for i in indices:
        print lldb.frame.GetValueForVariablePath(args[0] + "[" + str(i) + "]")
    
    def __lldb_init_module(debugger, internal_dict):
      debugger.HandleCommand('command script add -f parray.parray parray')
    

答案 6 :(得分:4)

我试图添加评论,但这对于发布完整答案并不是很好,所以我做出了自己的答案。这解决了获得“无价值”的问题。您需要获取当前帧,因为我认为lldb.frame是在模块导入时设置的,因此如果从.lldbinit加载模块,则在断点处停止时它没有当前帧。如果在断点处停止时导入或重新加载脚本,则另一个版本将起作用。以下版本应始终有效。

import lldb
import shlex

@lldb.command('parray', 'command script add -f parray.parray parray')
def parray(debugger, command, result, dict):

    target = debugger.GetSelectedTarget()
    process = target.GetProcess()
    thread = process.GetSelectedThread()
    frame = thread.GetSelectedFrame()

    args = shlex.split(command)
    if len(args) == 2:
        count = int(args[1])
        indices = range(count)
    elif len(args) == 3:
        first = int(args[1])
        count = int(args[2])
        indices = range(first, first + count)
    else:
        print 'Usage: parray ARRAY [FIRST] COUNT'
        return

    for i in indices:
        print frame.GetValueForVariablePath(args[0] + "[" + str(i) + "]")

答案 7 :(得分:1)

那么,您可以编写自己的自定义C函数并使用以下命令调用它:

call (int)myprint(args)

答案 8 :(得分:1)

要检查变量,可以使用带有frame variable标志的fr v命令(-Z是最短的唯一前缀),它完全可以满足您的要求:

(lldb) fr v buffer -Z5
(int64_t *) buffer = 0x000000010950c000 {
  (int64_t) [0] = 0
  (int64_t) [1] = 0
  (int64_t) [2] = 0
  (int64_t) [3] = 0
  (int64_t) [4] = 0
}

很遗憾,expression不支持该标志