web-dev-qa-db-de.com

Array in LLDB anzeigen: Entspricht dem GDB-Operator '@' in Xcode 4.1

Ich möchte eine Reihe von Elementen anzeigen, auf die ein Zeiger zeigt. In GDB kann dies durch Behandeln des Pointed Memory als künstliches Array einer bestimmten Länge unter Verwendung des Operators '@' als geschehen

*pointer @ length

dabei ist length die Anzahl der Elemente, die ich anzeigen möchte.

Die obige Syntax funktioniert in der mit Xcode 4.1 gelieferten LLDB nicht.

Gibt es eine Möglichkeit, wie das oben genannte in LLDB erreicht werden kann?

71
midinastasurazz

Tatsächlich gibt es eine einfache Möglichkeit, dies zu tun, indem Sie den Zeiger auf ein Zeiger-zu-Array umwandeln.

Wenn Sie zum Beispiel ein int* ptr, und Sie möchten es als Array von zehn Ganzzahlen anzeigen, können Sie tun

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

Diese Methode funktioniert ohne Plugins oder spezielle Einstellungen, da sie nur auf Standard-C-Funktionen basiert. Es funktioniert ebenfalls mit anderen Debuggern wie GDB oder CDB, obwohl sie auch spezielle Syntaxen zum Drucken von Arrays haben.

119
Siyuan Ren

Beginnend mit der lldb in Xcode 8.0 gibt es einen neuen eingebauten Parray-Befehl. Sie können also sagen:

(lldb) parray <COUNT> <EXPRESSION>

um den Speicher, auf den das Ergebnis von EXPRESSION zeigt, als Array von COUNT Elementen des Typs zu drucken, auf den der Ausdruck zeigt.

Wenn die Anzahl in einer Variablen gespeichert ist, die im aktuellen Frame verfügbar ist, können Sie Folgendes tun:

(lldb) parray `count_variable` pointer_to_malloced_array

Dies ist eine allgemeine lldb-Funktion. Jedes in Backticks enthaltene Befehlszeilenargument in lldb wird als Ausdruck ausgewertet, der eine Ganzzahl zurückgibt. Anschließend wird das Argument vor der Befehlsausführung durch die Ganzzahl ersetzt.

29
Jim Ingham

Der einzige Weg, den ich gefunden habe, war über ein Python Skriptmodul:

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

Definiere einen Befehl "parray" in lldb:

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

Jetzt können Sie "parray variable Länge" verwenden:

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

Mit Xcode 4.5.1 (das Ihnen jetzt vielleicht hilft oder auch nicht) können Sie dies in der lldb-Konsole tun:

(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]

In diesem Beispiel wird angenommen, dass 'pointer' ein Array von 64 Floats ist: float pointer[64];

15
davidA

Beginnend mit der Antwort von Martin R habe ich es wie folgt verbessert:

  1. Wenn der Zeiger keine einfache Variable ist, z.

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

    Dann schlägt "parray a.at 5" fehl.

    Ich habe das behoben, indem ich "FindVariable" durch "GetValueForVariablePath" ersetzt habe.

  2. Was ist nun, wenn die Elemente in Ihrem Array Aggregate sind, z.

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

    Dann gibt "parray a.at 5" aus: a.at-> x, a.at-> y, a.at [2], a.at [3], a.at [4], da GetChildAtIndex () Mitglieder zurückgibt von Aggregaten.

    Ich habe dies behoben, indem ich "a.at" + "[" + str (i) + "]" in der Schleife aufgelöst habe, anstatt "a.at" aufzulösen und dann die untergeordneten Elemente abzurufen.

  3. Ein optionales Argument "first" (Verwendung: parray [FIRST] COUNT) wurde hinzugefügt. Dies ist nützlich, wenn Sie über eine große Anzahl von Elementen verfügen.

  4. Hat das "Befehlsskript add -f parray.parray parray" bei init ausgeführt

Hier ist meine modifizierte 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')
12
jng

Es scheint noch nicht unterstützt zu werden.

Sie könnten die Speicherlesefunktion (memory read/x) verwenden, wie z

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

um einen Gleitkomma zehnmal von diesem Zeiger aus zu drucken. Dies sollte die gleiche Funktionalität sein wie gdbs @.

12
w-m

Ich habe versucht, einen Kommentar hinzuzufügen, aber das war nicht besonders gut, um eine vollständige Antwort zu veröffentlichen, also habe ich meine eigene Antwort abgegeben. Dies löst das Problem mit "No Value". Sie müssen den aktuellen Frame abrufen, da lldb.frame meines Erachtens zum Zeitpunkt des Modulimports festgelegt ist, sodass er nicht den aktuellen Frame enthält, wenn Sie an einem Haltepunkt anhalten, wenn Sie das Modul aus .lldbinit laden. Die andere Version würde funktionieren, wenn Sie das Skript beim Anhalten am Haltepunkt importieren oder neu laden. Die folgende Version sollte immer funktionieren.

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

Nun, an diesem Punkt können Sie auch Ihre eigene benutzerdefinierte C-Funktion schreiben und sie aufrufen mit:

call (int)myprint(args)
1
Elektraglide

Um Variablen zu untersuchen, können Sie das frame variable Befehl (fr v ist das kürzeste eindeutige Präfix) mit einem -Z Flag, das genau das tut, was Sie wollen:

(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
}

leider unterstützt expression dieses Flag nicht

0
Holger