2009-11-23 40 views
16

Tôi đã đặt breakpoint về xuất cảnh, _exit và chương trình của tôi (ứng dụng đa luồng, chạy trên linux 2.6.16.46-0.12 SLES10), là bằng cách nào đó vẫn thoát trong một cách mà tôi không thể xác định vị tríthiết lập điểm ngắt thoát gdb không hoạt động?

 
(gdb) c 
... 
[New Thread 47513671297344 (LWP 15279)] 
[New Thread 47513667103040 (LWP 15280)] 
[New Thread 47513662908736 (LWP 15281)] 

Program exited with code 0177. 
(gdb) 

lối ra các hàm nằm trong libc do đó không có vấn đề về thư viện được tải xuống bị trì hoãn. Bất kỳ ai biết về một số kích hoạt bí ẩn khác cho lối ra mà không thể bị bắt?

CHỈNH SỬA: sự cố hiện chỉ mang tính chất học thuật. Tôi đã thử gỡ lỗi tìm kiếm nhị phân, sao lưu một tập hợp con các thay đổi của tôi (sự cố đã biến mất). Sau khi tôi áp dụng chúng một lần nữa theo thứ tự, tôi không còn có thể repro vấn đề, ngay cả với những thứ khôi phục lại trạng thái ban đầu.

EDIT2: Gần đây, tôi đã tìm thấy một lý do cho loại lỗi này, đây có thể là nguồn gốc cho vấn đề này. Vì lý do lịch sử, sản phẩm của chúng tôi sử dụng cờ liên kết độc ác -Bymymbolic. Trong số các tác dụng phụ của điều này là khi một biểu tượng không xác định nhưng được gọi, trình liên kết thời gian chạy GLIBC sẽ ném bom theo cách này, và bạn thấy nó trong trình gỡ lỗi như một quá trình đã thoát với 0177. Khi trình liên kết thời gian chạy hủy theo cách này, tôi 'd đoán nó làm cho syscall để _exit trực tiếp (thay vì sử dụng thư viện thời gian chạy C exit() hoặc _exit()). Điều đó sẽ phù hợp với thực tế là tôi không thể bắt được điều này với các điểm ngắt xuất cảnh trong trình gỡ rối.

Trả lời

22

Có hai lý do phổ biến cho _exit breakpoint để "bỏ lỡ" - một trong hai GDB không đặt breakpoint ở đúng nơi, hoặc các chương trình biểu diễn (tương đương đạo đức của) syscall(SYS_exit, ...)

info breakdisassemble _exit nói?

Bạn có thể thuyết phục GDB để đặt điểm ngắt chính xác với break *&_exit. Ngoài ra, GDB-7.0 hỗ trợ catch syscall. Một cái gì đó như thế này nên làm việc (giả sử Linux/x86_64; lưu ý rằng trên ix86 những con số sẽ khác nhau) bất kể như thế nào thoát khỏi chương trình:

(gdb) catch syscall 60 
Catchpoint 3 (syscall 'exit' [60]) 
(gdb) catch syscall 231 
Catchpoint 4 (syscall 'exit_group' [231]) 
(gdb) c 

Catchpoint 4 (call to syscall 'exit_group'), 0x00007ffff7912f3d in _exit() from /lib/libc.so.6 

Cập nhật:
bình luận của bạn cho thấy _exit breakpoint được thiết lập một cách chính xác, vì vậy nó có khả năng rằng quá trình của bạn không thực hiện _exit.

Điều đó rời khỏi syscall(SYS_exit, ...) và một khả năng khác (mà tôi đã bỏ lỡ trước đó): tất cả các chủ đề thực hiện pthread_exit. Bạn cũng có thể muốn đặt một điểm ngắt trên pthread_exit (và thực hiện info thread mỗi khi bạn nhấn vào nó - luồng cuối cùng cần làm pthread_exit sẽ khiến quá trình chấm dứt).

Edit:

Cũng đáng chú ý mà bạn có thể sử dụng tên ghi nhớ, chứ không phải là số syscall. Bạn cũng có thể đồng thời thêm nhiều syscalls vào danh sách bắt giữ như vậy:

(gdb) catch syscall exit exit_group 
Catchpoint 2 (syscalls 'exit' [1] 'exit_group' [252]) 
+0

Tôi sẽ cố gắng xây dựng gdb 7 và xem những gì nó hiển thị. các * & cung cấp cho các địa chỉ hướng dẫn tương tự:

 (gdb) b _exit Breakpoint 2 at 0x2aeea040f250 (gdb) b *&_exit Note: breakpoint 2 also set at pc 0x2aeea040f250. Breakpoint 3 at 0x2aeea040f250 
 0x00002aeea040f250 <_exit+0>: mov %fs:0x0,%r9 ... 0x00002aeea040f275 <_exit+37>: syscall 
(Trông giống như một syscall khá chuẩn). Tôi nghĩ rằng tôi đã ít nhất là cô lập sự thay đổi mã dẫn đến lối ra bí ẩn này, chỉ cần không hiểu các chi tiết được nêu ra. –

+2

Sẽ tốt hơn nếu sử dụng 'catch syscall exit' và' catch syscall exit_group' thay vì giá trị số. Trên hệ thống của tôi, ví dụ, 'thoát' là' [1] 'không' [60] '. – Ruslan

+0

Ngoài ra, bạn có thể đặt cả hai cùng lúc với 'catch syscall exit exit_group'. Trong thực tế, chỉnh sửa nó ngay bây giờ ... –

1

Đặt điểm ngắt trên _exit là một ý tưởng hay.

Bạn cũng có thể thử liên kết tĩnh, chỉ để lấy một chồng các biến chứng gdb tiềm ẩn khỏi bảng.

0177 là nghi ngờ giống như tình trạng chờ đợiwait(2) lợi nhuận cho con dừng lại, nhưng gdb được in tình trạng thoát, đó là một điều khác nhau, do đó có thể là một lý lẽ thoát thực sự.

+0

OP cho biết anh ta đã có điểm ngắt trên _exit và thoát. Ngoài ra, 0177 là 127. Bạn đã nhận được bao nhiêu từ 127 đến SIGCHLD trên thế giới? –

+0

Ồ, đã thoát. Nhưng tôi đúng về tình trạng chờ đợi. Tôi rõ ràng là không nói về số hiệu tín hiệu, nhưng trạng thái 'wait (2)' trả về cho một quá trình dừng lại. Hãy nhìn vào điều này: $ grep IFSTOPPED /usr/include/bits/waitstatus.h '#define __WIFSTOPPED (trạng thái) (((trạng thái) & 0xff) == 0x7f)', AND, '0x7f == 0177'. Nhưng tôi đồng ý đó không phải là những gì đang xảy ra ở đây. – DigitalRoss

1

Có thể bạn có một số tham chiếu lười biếng chưa được giải quyết trong một số thư viện được chia sẻ. Tôi có chính xác tình huống tương tự rằng "ai đó ở đâu đó" đã thoát khỏi quá trình và dường như là tài liệu tham khảo chưa được giải quyết.

Kiểm tra quy trình của bạn bằng tùy chọn "ldd -r".

Có vẻ như ld.so hoặc bất cứ điều gì lười biếng giải quyết một số biểu tượng cho chức năng thoát đồng nhất (cần được hủy bỏ IMHO).

tình hình của tôi:

$ ldd ./program 
undefined symbol: XXXX (/usr/lib/libYYY.so) 

$./program 
program: started! 
... 
<program is running regardless of undefined references> 

Bây giờ thoát xuất hiện khi tôi đã viện dẫn một số kịch bản được sử dụng chức năng đó là không xác định. Nó luôn luôn thoát với exitcode = 127 và gdb báo cáo 0177.

+0

Điều đó dường như không phải là trường hợp ở đây. Tôi nhận được không có biểu tượng không xác định trong thực thi của chúng tôi (không xuất cảnh cũng không phải bất cứ điều gì khác). –

Các vấn đề liên quan