2012-02-09 21 views
6

Tôi cần in dấu vết ngăn xếp từ trình xử lý tín hiệu của ứng dụng C++ mutli-luồng C++ chạy trên Linux. Mặc dù tôi đã tìm thấy một số ví dụ mã, nhưng không có mã nào trong số đó biên dịch được. Điểm chặn của tôi là nhận được địa chỉ của người gọi (điểm mà tín hiệu được tạo ra) từ cấu trúc ucontext_t. Tất cả thông tin tôi có thể tìm thấy, trỏ tới thanh ghi EIP dưới dạng ucontext.gregs [REG_EIP] hoặc ucontext.eip. Có vẻ như cả hai đều là x86. Tôi cần mã tuân thủ 64 bit cho cả CPU Intel và AMD. Ai có thể giúp được không?In dấu vết ngăn xếp từ trình xử lý tín hiệu

+0

Nó sẽ không làm tôi ngạc nhiên nếu nó không thể làm được. Bạn đã thử làm nó trên 32bit chưa? Ngoài ra, mà distro? –

+0

Trong 64 bit, thanh ghi là RIP. Khá chắc chắn nó sẽ ở trong một nơi nào đó. –

+0

Đó là Red Hat 4.1.2-50. Không thể là ứng dụng 32 bit khi chúng tôi làm việc với các vùng bộ nhớ lớn lên đến 60+ GB – GMichael

Trả lời

1

Cách thông thường nhận được một vết đống là để lấy địa chỉ của một biến địa phương, sau đó thêm một số con số kỳ diệu với nó, tùy thuộc vào cách trình biên dịch tạo ra mã (có thể phụ thuộc vào các tùy chọn tối ưu hóa sử dụng để biên dịch mã) và làm việc trở lại từ đó. Tất cả các hệ thống rất phụ thuộc, nhưng có thể làm được nếu bạn biết những gì bạn đang làm.

Việc này có hoạt động trong trình xử lý tín hiệu hay không là một câu hỏi khác. Tôi không biết về nền tảng mà bạn mô tả, nhưng rất nhiều hệ thống cài đặt ngăn xếp riêng biệt cho bộ xử lý tín hiệu , không có liên kết quay lại ngăn xếp bị gián đoạn trong bộ nhớ người dùng có thể truy cập.

+0

Bạn có nghĩa là không có liên kết quay lại ngăn xếp bị gián đoạn không? –

+0

@wood_brian Không có trong bộ nhớ có thể truy cập của người dùng. (Hệ điều hành rõ ràng giữ thông tin theo một cách nào đó.) –

+0

Bạn đã viết bị gián đoạn tĩnh. Tôi nghĩ bạn có nghĩa là ngăn xếp bị gián đoạn. –

4

có chức năng glibc backtrace. Trang người dùng liệt kê ví dụ về cuộc gọi:

#define SIZE 100 
void myfunc3(void) { 
     int j, nptrs; 

     void *buffer[100]; 
     char **strings; 

     nptrs = backtrace(buffer, SIZE); 
     printf("backtrace() returned %d addresses\n", nptrs); 

     /* The call backtrace_symbols_fd(buffer, nptrs, STDOUT_FILENO) 
      would produce similar output to the following: */ 

     strings = backtrace_symbols(buffer, nptrs); 
     if (strings == NULL) { 
      perror("backtrace_symbols"); 
      exit(EXIT_FAILURE); 
     } 

     for (j = 0; j < nptrs; j++) 
      printf("%s\n", strings[j]); 

     free(strings); 
    } 

Xem trang hướng dẫn để biết thêm ngữ cảnh.

thật khó để biết liệu điều này có thực sự được đảm bảo để hoạt động từ trình xử lý tín hiệu hay không, vì posix chỉ liệt kê một vài hàm reentrant được đảm bảo hoạt động. Hãy nhớ rằng: một trình xử lý tín hiệu có thể được gọi trong khi phần còn lại của tiến trình của bạn nằm ngay giữa cuộc gọi malloc.

My đoán là, điều này thường hoạt động, nhưng đôi khi có thể không thành công. Để gỡ lỗi này có thể là đủ tốt.

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