LLDB (Swift): Mentransmisikan Alamat Mentah ke Jenis yang Dapat Digunakan

95

Apakah ada perintah LLDB yang dapat mentransmisikan alamat mentah ke dalam kelas Swift yang dapat digunakan?

Sebagai contoh:

(lldb) po 0x7df67c50 as MKPinAnnotationView

Saya tahu bahwa alamat ini menunjuk ke MKPinAnnotationView, tetapi tidak dalam bingkai yang dapat saya pilih. Tapi, saya ingin mentransmisikan alamat mentah ke dalam MKPinAnnotationView sehingga saya bisa memeriksa propertinya. Apakah ini mungkin?

jarrodparkes
sumber

Jawaban:

154

Di bawah Xcode 8.2.1 dan Swift 3, perintah lldb po atau p tidak akan berfungsi dengan variabel yang diketik. Anda perlu menggunakan perintah cepat cetak untuk memeriksa properti contoh objek yang diketik. (Terima kasih atas jawaban cbowns !) Misalnya:

expr -l Swift -- import UIKit
expr -l Swift -- let $pin = unsafeBitCast(0x7df67c50, to: MKPinAnnotationView.self)
expr -l Swift -- print($pin.alpha)
Xi Chen
sumber
42
Ini seharusnya tidak terlalu sulit
Departamento B
Ini agak kontra intuitif. Saya pikir saya tidak perlu mengetik (lldb)di konsol saya. Tapi itu tidak akan berhasil tanpa itu.
Madu
2
Apakah ada cara untuk melakukan ini di objektif-c?
p0lAris
Saya terus membalas ini. Saya mungkin harus membuat alias lldb untuk expr -l Swift -- ..
Koen.
49

Anda dapat menggunakan unsafeBitCastfungsi Swift untuk mentransmisikan alamat ke instance objek:

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

Kemudian Anda bisa bekerja dengan $pin seperti biasa - mengakses properti, metode panggilan, dll.

Lihat artikel ini untuk informasi lebih lanjut: Swift Memory Dumping .

gregheo
sumber
Untuk pernyataan pertama saya pikir Anda lupa 'expr' atau 'ekspresi'. Jika tidak, itu bekerja dengan baik!
jarrodparkes
2
Saya mendapatkan "error: use of undeclared identifier 'unsafeBitCast'" di Xcode 7.2.
devios1
8
Selain kesalahan itu (@devios), ada kesalahan lain yang ditunjukkan di 7.3.1: "error: nama jenis tidak dikenal 'let'"
carlos_ms
3
Perhatikan bahwa tergantung pada konteks Anda mungkin perlu beralih lldb ke mode Swift terlebih dahulu menggunakan (lldb) settings set target.language swift. Selain itu, dalam beberapa kasus (misalnya saat keluar dari modul aplikasi Anda saat mentransmisikan ke suatu jenis dari aplikasi Anda), Anda mungkin perlu mengikutinya dengane import MyApp
Patrick Pijnappel
25

Format lldb expressiontampaknya telah berubah di Xcode 7.3. Hal berikut ini membuat saya mulai:

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

Untuk Kelas Kustom, Anda perlu mengimpor proyek Anda

expr -l Swift -- import MyTestProject
expr -l Swift --  let $vc = unsafeBitCast(0x7fad22c066d0, ViewController.self)
expr -l Swift -- print($vc.view)
afinlayson
sumber
1
Saya mendapatkan kesalahan: tidak ada modul seperti "MyProjectName". Ada pemikiran bagaimana cara memperbaikinya?
Alexander Stepanishin
@AlexanderStepanishin mencoba mengatur jalur utas / tumpukan, Contoh: "MyApp> Utas 1> 12 utama"
Juanmi
12

Pada Xcode 8 / Swift 3, inilah yang berhasil untuk saya. (Ini didasarkan pada jawaban @ sfaxon .)

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

Berkat semua jawaban di atas, unsafeBitCast juga berfungsi dengan baik dengan Aplikasi Xcode 8.3.2 / Swift 3 / macOS / Cocoa.

Hafalkan alamat contoh saat ini

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

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

Nanti, periksalah

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

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

Jika hal seperti ini terjadi

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

pastikan bahwa memilih salah satu bingkai tumpukan kode sumber Swift daripada yang assembler.

Ini mungkin terjadi ketika aplikasi dijeda dengan mengklik tombol Jeda atau dihentikan dengan pengecualian. Dengan memilih frame stack yang sesuai, biarkan lldb menyimpulkan bahasa pemrograman yang tepat.

Tora
sumber
10

Versi Objective-C

po ((MKPinAnnotationView *)0x7df67c50).alpha
rockhard
sumber
1
Ini bekerja dengan sempurna untuk saya. Dalam kasus saya, saya berada dalam Debug View Hierarchytampilan, mengklik kanan pada tampilan, lalu dipilih Print description of.... Itu memberi saya alamat memori dan jenis yang bisa saya masukkan ke kode di atas. Senang mengetahui bahwa debugger visual menempatkan konsol ke dalam bingkai Obj-C.
Trev14
6

Butuh waktu lebih lama bagi saya untuk menyadari bahwa saya ingin mengakuinya. Ini mirip dengan jawaban @afinlayson, tetapi dengan penjelasan yang lebih baik (saya harap!) Dan sintaks yang tetap

Jika Anda ingin memeriksa properti suatu objek menggunakan debugger hierarki tampilan Xcode, ini akan berfungsi: Anda berada dalam konteks objek secara default sehingga Anda harus mengalihkannya ke konteks Swift

  1. Pertama impor proyek Anda (jika Anda ingin menggunakan beberapa kelas yang ditentukan di sana)

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

  1. Transmisikan objek menggunakan alamat memorinya ke kelas apa pun yang Anda inginkan

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

  1. Akses nilai apa pun yang Anda inginkan dari objek

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

Contoh:

expr -l Swift -- import Football

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

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

Bartosz Kunat
sumber
5

Jawaban @Xi Chen berfungsi sempurna saat sesi LLDB Anda dimulai dalam konteks Swift. Namun, dalam beberapa kasus Anda mungkin berhenti di breakpoint di luar konteks Swift; misalnya, saat breakpoint simbolis ke Objective-C API, atau saat dalam mode Debug View Hierarchy (setidaknya pada Xcode 11.4).

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

Dalam hal ini, Anda harus melakukannya dengan cara lama menggunakan Objective-C:

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

dan sekarang Anda dapat menggunakan $pinseperti yang Anda inginkan.

Gobe
sumber
3

poadalah alias, yang artinya dapat diganti. Anda dapat mengganti podengan menangani alamat hex menggunakan objc:

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

Untuk melihat efeknya, Anda dapat memberi tahu lldb untuk memperluas alias ini:

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

Saya juga telah membuat https://github.com/kastiglione/swift_po , yang merupakan pengganti poSwift. Ini menangani alamat objek, dan memiliki beberapa perbaikan lainnya juga.

Dave Lee
sumber
dari tautan Anda, expression -l objc -O -- 0x76543210hanya tanggapan untuk saya, dan tidak perlu mengetahui kelas variabel dari alamat!
tontonCD
2

Cara termudah, cepat 4

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