简体   繁体   English

LLDB 中的视图数组:相当于 Xcode 4.1 中 GDB 的“@”运算符

[英]View array in LLDB: equivalent of GDB's '@' operator in Xcode 4.1

I would like to view an array of elements pointed to by a pointer.我想查看一个指针指向的元素数组。 In GDB this can be done by treating the pointed memory as an artificial array of a given length using the operator '@' as在 GDB 中,这可以通过使用运算符“@”将指向的 memory 视为给定长度的人工数组来完成

*pointer @ length

where length is the number of elements I want to view.其中length是我要查看的元素数。

The above syntax does not work in LLDB supplied with Xcode 4.1.上述语法在 Xcode 4.1 提供的 LLDB 中不起作用。

Is there any way how to accomplish the above in LLDB?有什么方法可以在 LLDB 中完成上述操作?

There are two ways to do this in lldb.在 lldb 中有两种方法可以做到这一点。

Most commonly, you use the parray lldb command which takes a COUNT and an EXPRESSION ;最常见的是,您使用带有COUNTEXPRESSIONparray lldb 命令; EXPRESSION is evaluated and should result in a pointer to memory. EXPRESSION被评估并且应该导致指向 memory 的指针。 lldb will then print COUNT items of that type at that address.然后 lldb 将在该地址打印该类型的COUNT个项目。 eg例如

parray 10 ptr

where ptr is of type int * .其中ptr的类型为int *

Alternatively, it can be done by casting the pointer to a pointer-to-array.或者,可以通过将指针转换为指向数组的指针来完成。

For example, if you have a int* ptr , and you want to view it as an array of ten integers, you can do例如,如果您有一个int* ptr ,并且您想将其视为一个由十个整数组成的数组,您可以这样做

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

Because it relies only on standard C features, this method works without any plugins or special settings.因为它仅依赖于标准 C 功能,所以此方法无需任何插件或特殊设置即可工作。 It likewise works with other debuggers like GDB or CDB, even though they also have specialized syntaxes for printing arrays.它同样适用于 GDB 或 CDB 等其他调试器,尽管它们也具有用于打印 arrays 的专用语法。

Starting with the lldb in Xcode 8.0, there is a new built-in parray command.从 Xcode 8.0 中的 lldb 开始,有一个新的内置 parray 命令。 So you can say:所以你可以说:

(lldb) parray <COUNT> <EXPRESSION>

to print the memory pointed to by the result of the EXPRESSION as an array of COUNT elements of the type pointed to by the expression.EXPRESSION的结果指向的 memory 打印为表达式指向的类型的COUNT元素数组。

If the count is stored in a variable available in the current frame, then remember you can do:如果计数存储在当前帧中可用的变量中,请记住您可以执行以下操作:

(lldb) parray `count_variable` pointer_to_malloced_array

That's a general lldb feature, any command-line argument in lldb surrounded in backticks gets evaluated as an expression that returns an integer, and then the integer gets substituted for the argument before command execution.这是一个通用的 lldb 功能,在 lldb 中用反引号括起来的任何命令行参数都会被评估为返回 integer 的表达式,然后在命令执行之前 integer 被替换为参数。

The only way I found was via a Python scripting module:我发现的唯一方法是通过 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)

Define a command "parray" in lldb:在 lldb 中定义一个命令“parray”:

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

Now you can use "parray variable length ":现在您可以使用“数组变长”:

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

With Xcode 4.5.1 (which may or may not help you now), you can do this in the lldb console:使用 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]

This example assumes that 'pointer' is an array of 64 floats: float pointer[64];这个例子假设'pointer'是一个有64个浮点数的数组: float pointer[64];

Starting with Martin R answer I improved it as follow:从 Martin R 答案开始,我对其进行了如下改进:

  1. If the pointer is not a simple variable, eg:如果指针不是一个简单的变量,例如:

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

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

    I fixed this by replacing "FindVariable" with "GetValueForVariablePath".我通过用“GetValueForVariablePath”替换“FindVariable”来解决这个问题。

  2. Now what if the elements in your array are aggregates, eg:现在,如果您的数组中的元素是聚合的,例如:

     struct { struct { float x; float y; }* at; size_t size; } a;

    Then "parray a.at 5" prints: a.at->x, a.at->y, a.at[2], a.at[3], a.at[4] because GetChildAtIndex() returns members of aggregates.然后 "parray a.at 5" 打印: a.at->x, a.at->y, a.at[2], a.at[3], a.at[4] 因为 GetChildAtIndex() 返回成员的聚合体。

    I fixed this by resolving "a.at" + "[" + str(i) + "]" inside the loop instead of resolving "a.at" and then retrieving its children.我通过在循环内解析“a.at”+“[”+str(i)+“]”而不是解析“a.at”然后检索它的孩子来解决这个问题。

  3. Added an optional "first" argument (Usage: parray [FIRST] COUNT), which is useful when you have a huge number of elements.添加了一个可选的“第一个”参数(用法:parray [FIRST] COUNT),这在您拥有大量元素时很有用。

  4. Made it do the "command script add -f parray.parray parray" at init让它在初始化时执行“命令脚本添加 -f parray.parray parray”

Here is my modified version:这是我的修改版本:

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')

It doesn't seem to be supported yet.好像还不支持。

You could use the memory read function (memory read / x), like您可以使用 memory 读取 function(内存读取 / x),例如

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

to print a float ten times from that pointer.从该指针打印十次浮点数。 This should be the same functionality as gdb's @.这应该与 gdb 的 @ 功能相同。

I tried to add a comment but that wasn't great for posting a full answer so I made my own answer.我尝试添加评论,但这对于发布完整答案并不好,所以我做出了自己的答案。 This solves the problem with getting "No Value".这解决了获得“无价值”的问题。 You need to get the current frame as I believe lldb.frame is set at module import time so it doesn't have the current frame when you stop at a breakpoint if you load the module from.lldbinit.您需要获取当前帧,因为我相信 lldb.frame 是在模块导入时设置的,因此如果您从.lldbinit 加载模块,当您在断点处停止时它没有当前帧。 The other version would work if you import or reloaded the script when you stopped at the breakpoint.如果您在断点处停止时导入或重新加载脚本,则另一个版本将起作用。 The version below should always work.下面的版本应该总是有效的。

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) + "]")

To inspect variables you can use the frame variable command ( fr v is the shortest unique prefix) which has a -Z flag which does exactly what you want:要检查变量,您可以使用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
}

unfortunately expression does not support that flag不幸的是, expression不支持该标志

Well at that point, you may as well write your own custom C function and invoke it with:那么此时,您不妨编写自己的自定义 C function 并调用它:

call (int)myprint(args)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM