web-dev-qa-db-fra.com

LLDB (Swift): Cast de l'adresse brute en type utilisable

Existe-t-il une commande LLDB qui peut convertir une adresse brute en une classe utilisable Swift?

Par exemple:

(lldb) po 0x7df67c50 as MKPinAnnotationView

Je sais que cette adresse pointe vers un MKPinAnnotationView, mais ce n'est pas dans un cadre que je peux sélectionner. Mais, je veux convertir l'adresse brute dans un MKPinAnnotationView afin que je puisse examiner ses propriétés. Est-ce possible?

75
jarrodparkes

Sous Xcode 8.2.1 et Swift 3, la commande lldb po ou p ne fonctionnera pas avec la variable saisie. Vous devrez utiliser la commande Swift print pour examiner les propriétés de l'instance d'objet typé. (Merci à réponse de cbowns !) Par exemple:

(lldb) expr -l Swift -- import UIKit
(lldb) expr -l Swift -- let $pin = unsafeBitCast(0x7df67c50, to: MKPinAnnotationView.self)
(lldb) expr -l Swift -- print($pin.alpha)
112
Xi Chen

Vous pouvez utiliser la fonction unsafeBitCast de Swift pour convertir une adresse en une instance d'objet:

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

Ensuite, vous pouvez travailler avec $pin comme d'habitude - accès aux propriétés, aux méthodes d'appel, etc.

Consultez cet article pour plus d'informations: Swift Memory Dumping .

43
gregheo

Le format lldb pour expression semble avoir changé dans Xcode 7.3. Ce qui suit m'a permis de commencer:

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

Depuis Xcode 8/Swift 3, voici ce qui a fonctionné pour moi. (Ceci est basé sur @ réponse de sfaxon .)

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

Pour les cours personnalisés, vous devez importer votre projet

expr -l Swift -- import MyTestProject
expr -l Swift --  let $vc = unsafeBitCast(0x7fad22c066d0, ViewController.self)
expr -l Swift -- print($vc.view)
11
afinlayson

Grâce à toutes les réponses ci-dessus, unsafeBitCast fonctionne également bien avec Xcode 8.3.2/Swift 3/macOS/Cocoa Application.

Mémorisez une adresse de l'instance actuelle

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

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

Plus tard, examinez-les

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

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

Si quelque chose comme ça arrive

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

assurez-vous que choisissez l'un des cadres de pile du code source Swift plutôt que l'assembleur.

Cela peut se produire lorsque l'application a été suspendue en cliquant sur un bouton Pause ou arrêtée avec une exception. En choisissant un cadre de pile en conséquence, laissez lldb inférer un langage de programmation approprié.

9
Tora

Version Objective-C

po ((MKPinAnnotationView *)0x7df67c50).alpha
6
rockhard

La réponse de @Xi Chen fonctionne parfaitement lorsque votre session LLDB a été lancée dans un contexte Swift. Cependant, dans certains cas, vous pourriez vous être arrêté dans un point d'arrêt extérieur a Swift context; par exemple, lorsqu'il s'agit d'un point d'arrêt symbolique vers l'API Objective-C.

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

Dans ce cas, vous devrez le faire à l'ancienne en utilisant Objective-C:

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

et maintenant vous pouvez utiliser $pin comme vous le feriez.

4
Gobe

po est un alias, ce qui signifie qu'il peut être remplacé. Vous pouvez remplacer po en gérant les adresses hexadécimales en utilisant objc:

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

Pour voir quel effet cela a, vous pouvez demander à lldb de développer ces alias:

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

J'ai également créé https://github.com/kastiglione/Swift_po , qui est un substitut po pour Swift. Il gère les adresses des objets et propose également quelques autres améliorations.

2
Dave Lee

La manière la plus simple, Swift 4

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

Il m'a fallu plus de temps pour comprendre que j'aimerais l'admettre. C'est similaire à la réponse @afinlayson, mais avec une meilleure explication (j'espère!) Et une syntaxe fixe

Si vous souhaitez vérifier les propriétés d'un objet à l'aide du débogueur de hiérarchie de vues de Xcode, cela fonctionnera: vous êtes dans le contexte objc par défaut, vous devrez donc le basculer sur Swift

  1. Importez d'abord votre projet (si vous souhaitez utiliser certaines des classes qui y sont définies)

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

  1. Diffusez un objet en utilisant son adresse mémoire dans la classe de votre choix

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

  1. Accédez à n'importe quelle valeur de votre choix depuis l'objet

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

Exemple:

expr -l Swift -- import Football

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

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

1
Bartosz Kunat