LLDB (Swift): ส่งที่อยู่ดิบเป็นประเภทที่ใช้งานได้


95

มีคำสั่ง LLDB ที่สามารถส่งที่อยู่ดิบลงในคลาส Swift ที่ใช้งานได้หรือไม่

ตัวอย่างเช่น:

(lldb) po 0x7df67c50 as MKPinAnnotationView

ฉันรู้ว่าที่อยู่นี้ชี้ไปที่ MKPinAnnotationView แต่ไม่ได้อยู่ในกรอบที่ฉันสามารถเลือกได้ แต่ฉันต้องการส่งที่อยู่ดิบลงใน MKPinAnnotationView เพื่อที่ฉันจะได้ตรวจสอบคุณสมบัติของมัน เป็นไปได้หรือไม่

คำตอบ:


154

ภายใต้ Xcode 8.2.1 และ Swift 3 คำสั่ง lldb poหรือpจะไม่ทำงานกับตัวแปรที่พิมพ์ คุณจะต้องใช้การพิมพ์คำสั่ง swift เพื่อตรวจสอบคุณสมบัติของอินสแตนซ์อ็อบเจ็กต์ที่พิมพ์ (ขอบคุณคำตอบของ cbowns !) เช่น:

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

42
นี่ไม่น่าจะยากขนาดนี้
Departamento B

นี่เป็นเพียงการตอบโต้เล็กน้อย ฉันคิดว่าฉันไม่จำเป็นต้องพิมพ์(lldb)ในคอนโซลของฉัน แต่มันไม่ได้ผลหากไม่มีสิ่งนั้น
น้ำผึ้ง

2
มีวิธีทำใน objective-c หรือไม่?
p0lAris

ฉันกลับมาที่นี่เรื่อย ๆ ฉันน่าจะสร้างนามแฝง lldb สำหรับexpr -l Swift -- ..
Koen.

49

คุณสามารถใช้unsafeBitCastฟังก์ชันของ Swift เพื่อส่งที่อยู่ไปยังอินสแตนซ์วัตถุ:

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

จากนั้นคุณสามารถใช้งานได้$pinตามปกติ - คุณสมบัติการเข้าถึงวิธีการโทร ฯลฯ

ตรวจสอบบทความนี้สำหรับข้อมูลเพิ่มเติม: สวิฟท์หน่วยความจำการทุ่มตลาด


สำหรับคำสั่งแรกฉันคิดว่าคุณลืม 'expr' หรือ 'expression' มิฉะนั้นจะทำงานได้ดี!
jarrodparkes

2
ฉันได้รับ "ข้อผิดพลาด: การใช้ตัวระบุที่ไม่ได้ประกาศ" unsafeBitCast "" ใน Xcode 7.2
devios1

8
นอกจากข้อผิดพลาดนั้น (@devios) ยังมีข้อผิดพลาดอีกอย่างที่แสดงใน 7.3.1: "error: Unknown type name" let ""
carlos_ms

3
โปรดทราบว่าขึ้นอยู่กับบริบทที่คุณอาจต้องสลับไปที่โหมด lldb (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)

15

สำหรับคลาสที่กำหนดเองคุณต้องนำเข้าโครงการของคุณ

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

1
ฉันได้รับข้อผิดพลาด: ไม่มีโมดูลดังกล่าว "MyProjectName" มีความคิดอย่างไรที่จะแก้ไขปัญหานี้?
Alexander Stepanishin

@AlexanderStepanishin ลองตั้งค่าเส้นทางเธรด / สแต็กตัวอย่าง: "MyApp> เธรด 1> 12 main"
Juanmi

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 อย่างไรก็ตามในบางกรณีคุณอาจหยุดอยู่ในเบรกพอยต์นอกบริบท Swift ตัวอย่างเช่นเมื่อเป็นจุดพักเชิงสัญลักษณ์ของ Objective-C API หรือเมื่ออยู่ในโหมด Debug View Hierarchy (อย่างน้อยที่สุดใน 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

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.