2012-03-03 40 views
17

Làm thế nào chúng ta có thể liệt kê tất cả các chức năng được gọi trong một ứng dụng. Tôi đã thử sử dụng GDB nhưng danh sách backtrace của nó chỉ tối đa cuộc gọi chức năng chính.Danh sách tất cả các cuộc gọi chức năng được thực hiện trong một ứng dụng

Tôi cần danh sách sâu hơn, tức là danh sách tất cả các hàm được gọi bởi hàm chính và hàm được gọi từ các hàm được gọi và như vậy.

Có cách nào để có được điều này trong gdb? Hoặc bạn có thể cho tôi những gợi ý về cách để có được điều này?

+0

Với bất kỳ công cụ nào: http://stackoverflow.com/questions/311840/tool-to-trace-local-function-calls-in-linux?lq=1 –

+0

Có thể trùng lặp của [Làm cho luồng điều khiển in của GDB của các hàm như chúng được gọi] (http://stackoverflow.com/questions/311948/make-gdb-print-control-flow-of-functions-as-they-are- được gọi là) – jww

+0

https://balau82.wordpress.com/2010/10/06/trace-and-profile-function-calls-with-gcc/ –

Trả lời

17

Làm thế nào chúng ta có thể liệt kê tất cả các chức năng được gọi trong một ứng dụng

Đối với bất kỳ ứng dụng thực tế kích thước, danh sách này sẽ có hàng ngàn mục, mà có lẽ sẽ làm cho nó vô dụng.

Bạn có thể tìm hiểu tất cả các chức năng được xác định (nhưng không nhất thiết phải gọi) trong một ứng dụng có lệnh nm, ví dụ:

nm /path/to/a.out | egrep ' [TW] ' 

Bạn cũng có thể sử dụng GDB để thiết lập một breakpoint trên từng chức năng:

(gdb) set logging on  # collect trace in gdb.txt 
(gdb) set confirm off # you wouldn't want to confirm every one of them 
(gdb) rbreak .   # set a breakpoint on each function 

Khi bạn tiếp tục, bạn sẽ đánh một breakpoint cho mỗi chức năng gọi. Sử dụng các lệnh disablecontinue để tiến lên phía trước. Tôi không tin rằng có một cách dễ dàng để tự động hóa điều đó, trừ khi bạn muốn sử dụng kịch bản Python.

Đã đề cập gprof là một lựa chọn tốt khác.

+0

Lưu ý: điều này cũng sẽ phá vỡ mã chạy trước '_start': http : //stackoverflow.com/questions/31379422/why-is-init-from-glibcs-csu-init-first-c-called-before-start-even-if-start-i –

+0

gdb đã được đặt ở mức 100% cpu kể từ khi tôi nhập lệnh 'rbreak .' –

+0

mà không cần đăng nhập,' thiết lập chiều cao 0' sẽ hữu ích (không có phân trang cho đầu ra) – Blauhirn

9

Bạn muốn có biểu đồ cuộc gọi. Công cụ bạn muốn sử dụng không phải là gdb, là gprof. Bạn biên dịch chương trình của bạn với -pg và sau đó chạy nó. Khi nó chạy một tập tin gmon.out sẽ được tạo ra. Sau đó, bạn xử lý tệp này với gprof và tận hưởng đầu ra.

1

Câu hỏi này có thể cần được giải thích để quyết định giữa 2 câu trả lời hiện tại là gì. Tùy thuộc vào những gì bạn cần:

1) Bạn cần biết số lần mỗi hàm được gọi theo định dạng danh sách/biểu đồ thẳng của các hàm phù hợp với # cuộc gọi. Điều này có thể dẫn đến kết quả không rõ ràng/không thuyết phục nếu mã của bạn không phải là thủ tục (tức là các chức năng gọi các chức năng khác trong cấu trúc nhánh mà không mơ hồ về những gì đang gọi là gì). Đây là chức năng gprof cơ bản yêu cầu biên dịch lại với cờ -pg.

2) Bạn cần danh sách các chức năng theo thứ tự được gọi, điều này phụ thuộc vào chương trình của bạn là tùy chọn tốt nhất/khả thi: a) NẾU chương trình của bạn chạy và chấm dứt mà không có lỗi thời gian chạy, bạn có thể sử dụng gprof vì mục đích này. b) Tùy chọn ELSE ở trên sử dụng dbg với ghi nhật ký và điểm ngắt là tùy chọn còn lại mà tôi đã học khi đọc phần này.

3) Bạn cần biết không chỉ thứ tự mà, ví dụ, đối số chức năng cho mỗi cuộc gọi. Công việc hiện tại của tôi là mô phỏng trong vật lý của vận chuyển hạt, vì vậy điều này sẽ rất hữu ích trong việc theo dõi các kết quả bất thường đến từ đâu ... tức là khi các đối số được truyền xung quanh ý nghĩa dừng.Tôi tưởng tượng một cách để làm điều này là sẽ là một biến thể của những gì có việc làm Nga đã trừ bằng cách sử dụng sau đây:

args

(gdb) thông tin

Logging kết quả của lệnh này với tất cả các điểm break (đặt tại mỗi cuộc gọi hàm) cho các arg của hàm hiện tại.

4

kỷ lục chức năng gọi lịch sử

https://sourceware.org/gdb/onlinedocs/gdb/Process-Record-and-Replay.html

này phải là một phần cứng tuyệt vời tăng tốc khả năng nếu bạn là một trong số ít người (năm 2015) với một CPU có hỗ trợ Intel Processor Tracing (Intel PT, intel_pt trong /proc/cpuinfo).

docs

GDB cho rằng nó có thể sản xuất ra như:

(gdb) list 1, 10 
1 void foo (void) 
2 { 
3 } 
4 
5 void bar (void) 
6 { 
7  ... 
8  foo(); 
9  ... 
10 } 
(gdb) record function-call-history /ilc 
1 bar  inst 1,4  at foo.c:6,8 
2 foo inst 5,10 at foo.c:2,3 
3 bar  inst 11,13 at foo.c:9,10 

Trước khi sử dụng nó, bạn cần phải chạy:

start 
record btrace 

đó là nơi một CPU không có khả năng không thành công với:

Target does not support branch tracing. 

Hỗ trợ CPU được thảo luận thêm tại: How to run record instruction-history and function-call-history in GDB?

chủ đề liên quan:

Đối nhúng, bạn cũng xem xét JTAG và phần cứng hỗ trợ như ARM của DSTREAM, nhưng hỗ trợ x86 dường như không phải là rất tốt: debugging x86 kernel using a hardware debugger

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