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.