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?
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)
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 .
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)
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)
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)
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é.
Version Objective-C
po ((MKPinAnnotationView *)0x7df67c50).alpha
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.
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.
La manière la plus simple, Swift 4
expr unsafeBitCast(0x7df67c50, to: MKPinAnnotationView.self)
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
expr -l Swift -- import <YOUR PROJECT NAME>
expr -l Swift -- let $vc = unsafeBitCast(0x7fb7c51cb270, to: <YOUR PROJECT NAME>.<YOUR CUSTOM CLASS NAME>.self)
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)