LLDB (Swift): Передавання необробленої адреси у придатний для використання тип


93

Чи існує команда LLDB, яка може передати необроблену адресу в придатний для використання клас Swift?

Наприклад:

(lldb) po 0x7df67c50 as MKPinAnnotationView

Я знаю, що ця адреса вказує на MKPinAnnotationView, але я не в кадрі, який я можу вибрати. Але я хочу передати необроблену адресу в MKPinAnnotationView, щоб я міг вивчити її властивості. Чи можливо це?

Відповіді:


152

У Xcode 8.2.1 та Swift 3 команда lldb po або p не працюватиме із введеною змінною. Вам потрібно буде скористатися командою швидкого друку для вивчення властивостей набраного екземпляра об’єкта. (Завдяки відповіді cbowns !) Наприклад:

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

38
Це насправді не повинно бути настільки важко
Департамент Б

Це було трохи протилежним інтуїтивним. Я думав, що мені не потрібно вводити (lldb)в консолі. Але без цього не вийшло.
Мед

2
Чи є спосіб зробити це в object-c?
p0lAris

Я постійно повертаюся до цього. Ймовірно, мені слід створити псевдонім lldb для expr -l Swift -- ..
Koen.

49

Ви можете використовувати unsafeBitCastфункцію Swift, щоб прив’язати адресу до екземпляра об’єкта:

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

Тоді ви зможете працювати $pinяк завжди - властивості доступу, методи виклику тощо.

Ознайомтесь із цією статтею, щоб отримати додаткову інформацію: Швидкий демпінг пам'яті .


Для першого твердження, я думаю, ви забули "вираження" або "вираз". В іншому випадку це чудово працює!
jarrodparkes

2
Я отримую "помилку: використання незадекларованого ідентифікатора 'unsafeBitCast'" у Xcode 7.2.
devios1

8
Окрім цієї помилки (@devios) є ще одна помилка, яку вона показує в 7.3.1: "помилка: невідоме ім'я типу 'let'"
carlos_ms

3
Зауважте, що залежно від контексту вам може знадобитися переключити lldb у режим Swift спочатку (lldb) settings set target.language swift. Крім того, в деяких випадках (наприклад, під час виходу за межі модуля вашого додатка під час трансляції на тип із вашої програми), можливо, вам доведеться дотримуватися цього за допомогоюe import MyApp
Patrick Pijnappel

25

Формат lldb для, expressionсхоже, змінився в Xcode 7.3. Мене почало наступне:

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

14

Для користувацьких класів потрібно імпортувати ваш проект

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

1
Я отримую помилку: такого модуля "MyProjectName" немає. Будь-які думки, як це виправити?
Олександр Степанишин

@AlexanderStepanishin спробуйте встановити шлях потоку / стека, Приклад: "MyApp> Thread 1> 12 main"
Хуанмі

12

Що стосується Xcode 8 / Swift 3, ось що мені вдалося. (Це базується на відповіді @ sfaxon .)

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

10

Завдяки всім наведеним вище відповідям, unsafeBitCast також добре працює з Xcode 8.3.2 / Swift 3 / macOS / Cocoa Application.

Запам’ятайте адресу поточного екземпляра

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

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

Пізніше вивчіть їх

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

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

Якщо щось подібне трапиться

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

переконайтеся, що обрали один із кадрів стеку вихідного коду Swift, а не асемблер.

Ймовірно, це трапиться, коли програму було призупинено натисканням кнопки Пауза або зупинено за винятком. Вибравши відповідним чином фрейм стека, дозвольте lldb зробити правильну мову програмування.


10

Версія Objective-C

po ((MKPinAnnotationView *)0x7df67c50).alpha

1
Для мене це чудово працювало. У моєму випадку я був у Debug View Hierarchyподанні, клацнув правою кнопкою миші на поданні, потім вибраний Print description of.... Це дало мені адресу пам’яті та тип, який я міг би ввести до коду вище. Приємно знати, що візуальний налагоджувач розміщує консоль у кадрі Obj-C.
Trev14,

6

Мені знадобилося більше часу, щоб зрозуміти, що я хотів би визнати. Це схоже на відповідь @afinlayson, але з кращим поясненням (сподіваюся!) Та фіксованим синтаксисом

Якщо ви хочете перевірити властивості об’єктів за допомогою налагоджувача ієрархії подання Xcode, це буде працювати: Ви за замовчуванням перебуваєте в контексті objc, тому вам доведеться перемкнути його на контекст Swift

  1. Спочатку імпортуйте свій проект (якщо ви хочете використовувати деякі класи, визначені там)

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

  1. Передайте об'єкт, використовуючи адресу його пам'яті, до будь-якого класу, який ви хочете

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

  1. Отримайте доступ до будь-якого значення, яке ви хочете від об’єкта

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

Приклад:

expr -l Swift -- import Football

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

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


5

Відповідь @Xi Chen чудово працює, коли ваш сеанс LLDB розпочинався у швидкому контексті. Однак у деяких випадках ви могли зупинитися в точці зупинки поза контекстом Swift; наприклад, коли це символічна точка зупинки для Objective-C API, або коли вона знаходиться в режимі ієрархії перегляду налагодження (принаймні станом на Xcode 11.4).

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

У цьому випадку вам потрібно буде зробити це по-старому, використовуючи Objective-C:

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

і тепер ви можете використовувати $pinяк би.


3

poє псевдонімом, що означає, що його можна замінити. Ви можете замінити po, обробляючи шістнадцяткові адреси, використовуючи objc:

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

Щоб побачити, який ефект це має, ви можете сказати lldb розгорнути ці псевдоніми:

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

Також я створив https://github.com/kastiglione/swift_po , який замінює poSwift. Він обробляє адреси об’єктів і має ще кілька вдосконалень.


за вашим посиланням, expression -l objc -O -- 0x76543210це просто відповідь для мене, і йому не потрібно знати клас змінних з адреси!
tontonCD

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.