LLDB (Swift): Truyền địa chỉ thô thành loại có thể sử dụng


94

Có lệnh LLDB nào có thể truyền một địa chỉ thô vào một lớp Swift có thể sử dụng được không?

Ví dụ:

(lldb) po 0x7df67c50 as MKPinAnnotationView

Tôi biết rằng địa chỉ này trỏ đến MKPinAnnotationView, nhưng nó không nằm trong khung mà tôi có thể chọn. Tuy nhiên, tôi muốn truyền địa chỉ thô vào một MKPinAnnotationView để tôi có thể kiểm tra các thuộc tính của nó. Điều này có khả thi không?

Câu trả lời:


153

Trong Xcode 8.2.1 và Swift 3, lệnh lldb po hoặc p sẽ không hoạt động với biến đã nhập. Bạn sẽ cần sử dụng lệnh in nhanh để kiểm tra các thuộc tính của cá thể đối tượng đã nhập. (Cảm ơn câu trả lời của cbowns !) VD:

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

39
Điều này thực sự không quá khó
Departamento B

Đây là một chút phản trực quan. Tôi nghĩ rằng tôi không cần phải nhập (lldb)bảng điều khiển của mình. Nhưng nó không hoạt động nếu không có điều đó.
Honey

2
Có cách nào để làm điều này trong mục tiêu-c?
p0lAris

Tôi tiếp tục nhận lại điều này. Tôi có lẽ nên tạo một bí danh lldb cho expr -l Swift -- ..
Koen.

49

Bạn có thể sử dụng unsafeBitCasthàm của Swift để truyền một địa chỉ tới một cá thể đối tượng:

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

Sau đó, bạn có thể làm việc với $pinnhư bình thường - truy cập thuộc tính, phương thức gọi, v.v.

Kiểm tra bài viết này để biết thêm thông tin: Swift Memory Dumping .


Đối với câu lệnh đầu tiên, tôi nghĩ rằng bạn đã quên 'expr' hoặc 'expression'. Nếu không, nó đang hoạt động tuyệt vời!
jarrodparkes

2
Tôi đang gặp phải "lỗi: sử dụng số nhận dạng không được khai báo 'secureBitCast'" trong Xcode 7.2.
defos1

8
Bên cạnh lỗi (@devios) có một lỗi nó cho thấy trong 7.3.1: "Lỗi: Tên kiểu không rõ 'let'"
carlos_ms

3
Lưu ý rằng tùy thuộc vào ngữ cảnh mà bạn có thể cần chuyển lldb sang chế độ Swift trước khi sử dụng (lldb) settings set target.language swift. Ngoài ra, trong một số trường hợp (ví dụ như khi phá vỡ bên ngoài của mô-đun của ứng dụng của bạn trong khi casting cho một loại từ ứng dụng của bạn), bạn có thể cần phải làm theo điều đó với mộte import MyApp
Patrick Pijnappel

25

Định dạng lldb cho expressiondường như đã thay đổi trong Xcode 7.3. Những điều sau đây đã giúp tôi bắt đầu:

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

14

Đối với các Lớp tùy chỉnh, bạn cần nhập dự án của mình

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

1
Tôi gặp lỗi: không có mô-đun nào như vậy "MyProjectName". Bất kỳ suy nghĩ làm thế nào để sửa chữa điều này?
Alexander Stepanishin

@AlexanderStepanishin thử đặt đường dẫn luồng / ngăn xếp, Ví dụ: "MyApp> Luồng 1> 12 chính"
Juanmi

12

Đối với Xcode 8 / Swift 3, đây là những gì phù hợp với tôi. (Điều này dựa trên câu trả lời của @ sfaxon .)

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

10

Nhờ tất cả các câu trả lời ở trên, secureBitCast cũng hoạt động tốt với Ứng dụng Xcode 8.3.2 / Swift 3 / macOS / Cocoa.

Ghi nhớ một địa chỉ của phiên bản hiện tại

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

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

Sau đó, hãy kiểm tra chúng

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

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

Nếu điều gì đó như thế này xảy ra

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

đảm bảo rằng hãy chọn một trong các khung ngăn xếp của mã nguồn Swift thay vì chọn một trong các khung hợp ngữ.

Có khả năng xảy ra khi ứng dụng bị tạm dừng bằng cách nhấp vào nút Tạm dừng hoặc dừng với một ngoại lệ. Bằng cách chọn một khung ngăn xếp cho phù hợp, hãy để lldb suy ra một ngôn ngữ lập trình thích hợp.


10

Phiên bản Objective-C

po ((MKPinAnnotationView *)0x7df67c50).alpha

1
Điều này làm việc hoàn hảo cho tôi. Trong trường hợp của tôi, tôi đang ở trong Debug View Hierarchychế độ xem, nhấp chuột phải vào một chế độ xem, sau đó được chọn Print description of.... Điều đó đã cho tôi một địa chỉ bộ nhớ và loại tôi có thể thả vào đoạn mã trên. Rất vui khi biết rằng trình gỡ lỗi trực quan đặt bảng điều khiển vào khung Obj-C.
Trev 14

6

Tôi mất nhiều thời gian hơn để hiểu rằng tôi muốn thừa nhận. Nó tương tự như câu trả lời @afinlayson, nhưng với lời giải thích tốt hơn (tôi hy vọng!) Và cú pháp cố định

Nếu bạn muốn kiểm tra thuộc tính của một đối tượng bằng trình gỡ lỗi phân cấp chế độ xem của Xcode thì điều này sẽ hoạt động: Bạn đang ở trong ngữ cảnh objc theo mặc định, vì vậy bạn sẽ phải chuyển nó sang ngữ cảnh Swift

  1. Đầu tiên nhập dự án của bạn (nếu bạn muốn sử dụng một số lớp được xác định ở đó)

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

  1. Truyền đối tượng bằng địa chỉ bộ nhớ của nó tới bất kỳ lớp nào bạn muốn

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

  1. Truy cập bất kỳ giá trị nào bạn muốn từ đối tượng

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

Thí dụ:

expr -l Swift -- import Football

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

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


5

Câu trả lời của @Xi Chen hoạt động hoàn hảo khi phiên LLDB của bạn được bắt đầu trong ngữ cảnh Swift. Tuy nhiên, trong một số trường hợp, bạn có thể đã dừng ở một điểm ngắt bên ngoài ngữ cảnh Swift; ví dụ: khi đó là một điểm ngắt biểu tượng đối với API Objective-C hoặc khi ở chế độ Debug View Hierarchy (ít nhất là với Xcode 11.4).

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

Trong trường hợp đó, bạn sẽ cần làm theo cách cũ bằng Objective-C:

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

và bây giờ bạn có thể sử dụng $pinnhư bạn muốn.


3

polà một bí danh, có nghĩa là nó có thể được ghi đè. Bạn có thể ghi đè pobằng cách xử lý các địa chỉ hex bằng objc:

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

Để xem điều này có tác dụng gì, bạn có thể yêu cầu lldb mở rộng các bí danh sau:

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

Ngoài ra, tôi đã tạo https://github.com/kastiglione/swift_po , một trang thay thế pocho Swift. Nó xử lý các địa chỉ đối tượng và cũng có một số cải tiến khác.


từ liên kết của bạn, expression -l objc -O -- 0x76543210chỉ là phản hồi cho tôi, và nó không cần biết lớp biến từ địa chỉ!
tontonCD

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.