LLDB (Swift): Umwandlung der Rohadresse in einen verwendbaren Typ

92

Gibt es einen LLDB-Befehl, der eine Rohadresse in eine verwendbare Swift-Klasse umwandeln kann?

Beispielsweise:

(lldb) po 0x7df67c50 as MKPinAnnotationView

Ich weiß, dass diese Adresse auf eine MKPinAnnotationView verweist, aber ich kann sie nicht in einem Frame auswählen. Ich möchte die Rohadresse jedoch in eine MKPinAnnotationView umwandeln, damit ich ihre Eigenschaften untersuchen kann. Ist das möglich?

jarrodparkes
quelle

Antworten:

151

Unter Xcode 8.2.1 und Swift 3 funktioniert der lldb-Befehl po oder p mit der eingegebenen Variablen nicht. Sie müssen den schnellen Befehl print verwenden , um die Eigenschaften der typisierten Objektinstanz zu untersuchen. (Dank der Antwort von cbowns !) ZB:

expr -l Swift -- import UIKit
expr -l Swift -- let $pin = unsafeBitCast(0x7df67c50, to: MKPinAnnotationView.self)
expr -l Swift -- print($pin.alpha)
Xi Chen
quelle
37
Das sollte wirklich nicht so schwer sein
Departamento B
Dies war ein wenig kontraintuitiv. Ich dachte, ich müsste das nicht (lldb)in meine Konsole eingeben. Aber ohne das hat es nicht funktioniert.
Honig
2
Gibt es eine Möglichkeit, dies in Ziel-c zu tun?
p0lAris
Ich komme immer wieder darauf zurück. Ich sollte wahrscheinlich einen lldb-Alias ​​für expr -l Swift -- ..
Koen
49

Mit der unsafeBitCastFunktion von Swift können Sie eine Adresse in eine Objektinstanz umwandeln:

(lldb) e let $pin = unsafeBitCast(0x7df67c50, MKPinAnnotationView.self)
(lldb) po $pin

Dann können Sie $pinwie gewohnt arbeiten - Zugriffseigenschaften, Aufrufmethoden usw.

Weitere Informationen finden Sie in diesem Artikel: Swift Memory Dumping .

Gregheo
quelle
Für die erste Aussage denke ich, dass Sie den 'Ausdruck' oder 'Ausdruck' vergessen haben. Ansonsten funktioniert es super!
Jarrodparkes
2
Ich erhalte in Xcode 7.2 den Fehler "Fehler: Verwendung des nicht deklarierten Bezeichners 'unsafeBitCast'".
devios1
8
Neben diesem Fehler (@devios) gibt es einen weiteren Fehler in 7.3.1: "Fehler: unbekannter
Typname
3
Beachten Sie, dass Sie je nach Kontext möglicherweise zuerst lldb in den Swift-Modus wechseln müssen (lldb) settings set target.language swift. In einigen Fällen (z. B. wenn Sie außerhalb des Moduls Ihrer App brechen, während Sie einen Typ aus Ihrer App übertragen) müssen Sie dem möglicherweise mit eineme import MyApp
Patrick Pijnappel
25

Das lldb-Format für expressionscheint sich in Xcode 7.3 geändert zu haben. Folgendes hat mich dazu gebracht:

(lldb) expr -l Swift -- import UIKit
(lldb) expr -l Swift -- let $view = unsafeBitCast(0x7fb75d8349c0, UIView.self)
sfaxon
quelle
14

Für benutzerdefinierte Klassen müssen Sie Ihr Projekt importieren

expr -l Swift -- import MyTestProject
expr -l Swift --  let $vc = unsafeBitCast(0x7fad22c066d0, ViewController.self)
expr -l Swift -- print($vc.view)
Afinlayson
quelle
1
Ich erhalte die Fehlermeldung: Kein solches Modul "MyProjectName". Irgendwelche Gedanken, wie man das behebt?
Alexander Stepanishin
@AlexanderStepanishin versuchen, den Thread / Stack-Pfad festzulegen. Beispiel: "MyApp> Thread 1> 12 main"
Juanmi
12

Ab Xcode 8 / Swift 3 hat Folgendes für mich funktioniert. (Dies basiert auf der Antwort von @ sfaxon .)

(lldb) expr -l Swift -- import UIKit
(lldb) expr -l Swift -- let $nav = unsafeBitCast(0x1030ff000, to: UINavigationController.self)
cbowns
quelle
10

Dank all der obigen Antworten funktioniert unsafeBitCast auch gut mit Xcode 8.3.2 / Swift 3 / macOS / Cocoa Application.

Merken Sie sich eine Adresse der aktuellen Instanz

(lldb) p tabView.controlTint
(NSControlTint) $R10 = defaultControlTint

(lldb) p self
(LearningStoryboard.NSTabViewController) $R11 = 0x00006080000e2280 {
.....

Untersuche sie später

(lldb) p unsafeBitCast(0x00006080000e2280, to: NSTabViewController.self).tabView.controlTint
(NSControlTint) $R20 = graphiteControlTint

(lldb) p $R11.tabView.controlTint
(NSControlTint) $R21 = graphiteControlTint

Wenn so etwas passiert

(lldb) p unsafeBitCast(0x00006080000e2280, to: NSTabViewController.self).tabView.controlTint
error: use of undeclared identifier 'to'

(lldb) p $R11.tabView.controlTint 
error: use of undeclared identifier '$R11'

Stellen Sie sicher, dass Sie einen der Stapelrahmen des Swift-Quellcodes anstelle eines Assemblers auswählen.

Dies ist wahrscheinlich der Fall, wenn die Anwendung durch Klicken auf die Schaltfläche Pause angehalten oder mit einer Ausnahme gestoppt wurde. Lassen Sie lldb durch entsprechende Auswahl eines Stapelrahmens auf eine geeignete Programmiersprache schließen.

Tora
quelle
10

Objective-C-Version

po ((MKPinAnnotationView *)0x7df67c50).alpha
steinhart
quelle
1
Das hat bei mir perfekt funktioniert. In meinem Fall war ich in der Debug View HierarchyAnsicht, habe mit der rechten Maustaste auf eine Ansicht geklickt und dann ausgewählt Print description of.... Das gab mir eine Speicheradresse und einen Typ, den ich in den obigen Code einfügen konnte. Gut zu wissen, dass der visuelle Debugger die Konsole in einen Obj-C-Frame versetzt.
Trev14
5

Ich habe länger gebraucht, um herauszufinden, dass ich zugeben möchte. Es ist ähnlich wie @afinlayson Antwort, aber mit besserer Erklärung (ich hoffe!) Und fester Syntax

Wenn Sie die Eigenschaften eines Objekts mit dem Debugger für die Ansichtshierarchie von Xcode überprüfen möchten, funktioniert dies wie folgt: Sie befinden sich standardmäßig im Objektkontext, sodass Sie ihn in den Swift-Kontext wechseln müssen

  1. Importieren Sie zuerst Ihr Projekt (wenn Sie einige der dort definierten Klassen verwenden möchten)

expr -l Swift -- import <YOUR PROJECT NAME>

  1. Verwandeln Sie das Objekt mit seiner Speicheradresse in eine beliebige Klasse

expr -l Swift -- let $vc = unsafeBitCast(0x7fb7c51cb270, to: <YOUR PROJECT NAME>.<YOUR CUSTOM CLASS NAME>.self)

  1. Greifen Sie über das Objekt auf einen beliebigen Wert zu

expr -l Swift -- print($vc.<PROPERTY NAME>)

Beispiel:

expr -l Swift -- import Football

expr -l Swift -- let $vc = unsafeBitCast(0x7fb7c51cb270, to: Football.Ball.self)

expr -l Swift -- print($vc.velocity)

Bartosz Kunat
quelle
5

Die Antwort von @Xi Chen funktioniert perfekt, wenn Ihre LLDB-Sitzung in einem Swift-Kontext gestartet wurde. In einigen Fällen haben Sie jedoch möglicherweise an einem Haltepunkt außerhalb eines Swift-Kontexts angehalten . Zum Beispiel, wenn es sich um einen symbolischen Haltepunkt für die Objective-C-API handelt oder wenn Sie sich im Debug View Hierarchy-Modus befinden (mindestens ab Xcode 11.4).

error: unknown type name 'let'
error: use of undeclared identifier 'unsafeBitCast'

In diesem Fall müssen Sie es mit Objective-C auf die alte Weise tun:

e MKPinAnnotationView *$pin = (MKPinAnnotationView *)0x7df67c50

und jetzt können Sie verwenden, $pinwie Sie würden.

Gobe
quelle
3

poist ein Alias, was bedeutet, dass er überschrieben werden kann. Sie können überschreiben, poindem Sie Hex-Adressen mit objc behandeln:

command regex po
s/(0x[[:xdigit:]]+)/expression -l objc -O -- %1/
s/(.+)/expression -O -- %1/

Um zu sehen, welchen Effekt dies hat, können Sie lldb anweisen, diese Aliase zu erweitern:

(lldb) settings set interpreter.expand-regex-aliases true

Außerdem habe ich https://github.com/kastiglione/swift_po erstellt , das poSwift ersetzt. Es verarbeitet Objektadressen und weist einige weitere Verbesserungen auf.

Dave Lee
quelle
von Ihrem Link expression -l objc -O -- 0x76543210ist nur die Antwort für mich, und es muss nicht die variable Klasse von der Adresse kennen!
tontonCD
2

Der einfachste Weg, schnell 4

expr unsafeBitCast(0x7df67c50, to: MKPinAnnotationView.self)
Kingsley Mitchell
quelle