Xcode / LLDB: Làm thế nào để lấy thông tin về một ngoại lệ vừa được ném ra?


83

OK, hãy tưởng tượng rằng điểm ngắt của tôi objc_exception_throwvừa được kích hoạt. Tôi đang ngồi ở lời nhắc của trình gỡ lỗi và tôi muốn nhận thêm một số thông tin về đối tượng ngoại lệ. Tôi tìm nó ở đâu?


2
Hãy nhớ rằng, ngoại lệ vừa được nêu ra, mô tả của nó vẫn chưa được in trên bảng điều khiển.
Karoy Lorentey,

Câu trả lời:


162

Đối tượng ngoại lệ được chuyển vào dưới dạng đối số đầu tiên objc_exception_throw. LLDB cung cấp $arg1.. $argnbiến để tham chiếu đến các đối số trong quy ước gọi đúng, giúp việc in chi tiết ngoại lệ trở nên đơn giản:

(lldb) po $arg1
(lldb) po [$arg1 name]
(lldb) po [$arg1 reason]

Đảm bảo chọn objc_exception_throwkhung trong ngăn xếp cuộc gọi trước khi thực hiện các lệnh này. Xem "Gỡ lỗi nâng cao và Trình vệ sinh địa chỉ" trong video phiên WWDC15 để xem phần này được thực hiện trên sân khấu.

Thông tin lỗi thời

Nếu bạn đang sử dụng GDB, cú pháp để tham chiếu đến đối số đầu tiên phụ thuộc vào quy ước gọi của kiến ​​trúc mà bạn đang chạy. Nếu bạn đang gỡ lỗi trên thiết bị iOS thực, con trỏ tới đối tượng đang được đăng ký r0. Để in hoặc gửi tin nhắn, hãy sử dụng cú pháp đơn giản sau:

(gdb) po $r0
(gdb) po [$r0 name]
(gdb) po [$r0 reason]

Trên iPhone Simulator, tất cả các đối số của hàm đều được chuyển vào ngăn xếp, vì vậy cú pháp khủng khiếp hơn đáng kể. Biểu thức ngắn nhất mà tôi có thể xây dựng để đạt được nó là *(id *)($ebp + 8). Để làm cho mọi thứ bớt đau đớn hơn, tôi khuyên bạn nên sử dụng một biến tiện lợi:

(gdb) set $exception = *(id *)($ebp + 8)
(gdb) po $exception
(gdb) po [$exception name]
(gdb) po [$exception reason]

Bạn cũng có thể đặt $exceptiontự động bất cứ khi nào điểm ngắt được kích hoạt bằng cách thêm danh sách lệnh vào objc_exception_throwđiểm ngắt.

(Lưu ý rằng trong tất cả các trường hợp tôi đã kiểm tra, đối tượng ngoại lệ cũng có trong eaxedxđăng ký tại thời điểm điểm ngắt xảy ra. Tuy nhiên, tôi không chắc điều đó sẽ luôn như vậy.)

Thêm từ bình luận bên dưới:

Trong lldb , chọn khung ngăn xếp cho objc_exception_throwvà sau đó nhập lệnh này:

(lldb) po *(id *)($esp + 4)

6
Làm thế nào một người sẽ làm điều này trong lldb? Tôi gặp lỗi "error: tham chiếu đến 'id' là không rõ ràng"
phạm vi

2
bạn có thể cung cấp nguồn của thông tin này không? tôi muốn đọc thêm về nó
João Nunes

3
Hiện nay các công trình sau đây đối với tôi trước khi mở đầu khi breaing trên objc_exception_throw trong LLĐB : po *(id *)($esp + 4).
wbyoung

7
Điều này đã hiệu quả! Tuy nhiên, nó không hoạt động cho đến khi tôi chọn khung ngăn xếp 0 . ( objc_exception_throw).
funroll

7
po $eaxhoạt động đối với tôi trong trình mô phỏng dưới dạng mặt dây chuyền $r0khi ở trên thiết bị.
Monkeydom

10

trên trình mô phỏng mới (iOS 8, 64bit) xcode 6 im bằng cách sử dụng trong khung ngoại lệ: objc_exception_throw

po $rax

ở 32bit:

po $eax

Rax là gì?

Rax là một thanh ghi 64bits thay thế cho eax cũ

Làm thế nào để tìm thấy tất cả các đăng ký?

register read

Nguồn wikipedia


Hmm ... Trong Xcode 6.1, tôi nhận được: (LLĐB) lỗi po $ rax: Không thể hiện thực: không thể đọc giá trị của thanh ghi rax errored ra trong Execute, không thể PrepareToExecuteJITExpression
bradheintz

@bradheintz giả lập hoặc thiết bị? tôi đã thử điều này với 6.0.1
João Nunes

Bạn có thể chỉ cung cấp một liên kết đến nguồn của bạn cho điều đó không? Cảm ơn!
Chris Conover

Tôi vừa viết trong lldb: đăng ký đọc. Sau đó, với thông tin này, chúng ta biết rằng thanh ghi đầu tiên trong khung ngoại lệ giữ thông báo ngoại lệ.
João Nunes

Ok tôi tìm thấy một số tài liệu: rax là một 64bits đăng ký: Trong chế độ dài 64-bit, bạn có thể sử dụng thanh ghi 64-bit (ví dụ rax thay vì eax, RBX thay vì ebx, vv ..)
João Nunes

6

Tại thời điểm viết bài này, bài đăng này là bài đăng hàng đầu trên Google của tôi về: ngoại lệ in lldb . Do đó, tôi đang thêm câu trả lời này vào tài khoản cho lldb và x86_64.

Nỗ lực của tôi để tìm ngoại lệ bằng cách sử dụng po $eaxvới error: Couldn't materialize struct: Couldn't read eax (materialize). Các nỗ lực khác được mô tả trong các tài liệu liên kết từ các câu trả lời trước đó cũng không thành công.

Điều quan trọng là đầu tiên tôi phải nhấp vào objc_exception_throwkhung trong chuỗi chính của mình. lldb không bắt đầu trong khung đó.

Trong tất cả các ví dụ tìm kiếm và làm theo của tôi, mục blog nàymục đầu tiên giải thích mọi thứ theo cách phù hợp với tôi. Nó hiện đại hơn, được đăng vào tháng 8 năm 2012.


1

Nếu bạn có một câu lệnh bắt, hãy đặt một điểm ngắt vào đó và bạn có thể kiểm tra đối tượng ngoại lệ tại điểm đó.

Nếu bạn không có tuyên bố nắm bắt, hãy tiếp tục.

Bạn sẽ nhận được một thông báo trong thiết bị đầu cuối của mình như sau:

Chấm dứt ứng dụng do không có ngoại lệ 'NSInvalidArgumentException', lý do: ' * - [__ NSPlaceholderDictionary initWithObjects: forKeys: count:]: cố gắng chèn đối tượng nil từ các đối tượng [0]'

Tuy nhiên , có thể bạn đang tìm cách kiểm tra nó mà không cần tiếp tục vì bạn sẽ mất dấu vết ngăn xếp đẹp mắt khi ứng dụng bị chấm dứt.

Đối với điều đó, có vẻ như câu trả lời của Fnord là tốt nhất, nhưng tôi đã không thể làm cho nó hoạt động trong LLDB.

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.