2009-06-15 40 views
8

Tôi hiện đang làm việc trên một dự án mà tôi cần theo dõi việc sử dụng một số cuộc gọi hệ thống và chức năng cấp thấp như mmap, brk, sbrk. Cho đến nay, tôi đã làm điều này bằng cách sử dụng hàm interposition: Tôi viết một hàm wrapper có cùng tên với hàm tôi đang thay thế (ví dụ: mmap) và tôi tải nó trong một chương trình bằng cách đặt biến môi trường LD_PRELOAD. Tôi gọi hàm thực thông qua một con trỏ mà tôi tải với dlsym.Chức năng interposition trong Linux mà không cần dlsym

Thật không may, một trong các chức năng tôi muốn bọc, sbrk, được sử dụng nội bộ dlsym, do đó chương trình bị treo khi tôi cố gắng tải biểu tượng. sbrk không phải là cuộc gọi hệ thống trong Linux, vì vậy tôi không thể đơn giản sử dụng syscall để gọi gián tiếp.

Vì vậy, câu hỏi của tôi là, làm thế nào tôi có thể gọi chức năng thư viện từ hàm bao bọc có cùng tên mà không cần sử dụng dlsym? Có bất kỳ thủ thuật biên dịch (bằng cách sử dụng gcc) cho phép tôi tham khảo các chức năng ban đầu?

Trả lời

14

xem tùy chọn của ld --wrap symbol. Từ trang người đàn ông:

- biểu tượng dấu trang Sử dụng hàm bao bọc cho ký hiệu. Bất kỳ tham chiếu nào chưa được xác định sẽ được giải quyết thành "__wrap_symbol". Bất kỳ tham chiếu nào chưa được xác định tới "__real_symbol" sẽ được giải quyết thành ký hiệu.

Điều này có thể được sử dụng để cung cấp trình bao bọc cho chức năng hệ thống. Hàm bao bọc phải được gọi là "__wrap_symbol". Nếu muốn gọi chức năng hệ thống, nó sẽ gọi "__real_symbol".

Dưới đây là một ví dụ nhỏ:

void * 
__wrap_malloc (size_t c) 
{ 
    printf ("malloc called with %zu\n", c); 
    return __real_malloc (c); 
} 

Nếu bạn liên kết mã khác với tập tin này bằng malloc --wrap, sau đó tất cả các cuộc gọi đến "malloc" sẽ gọi chức năng " __wrap_malloc "để thay thế. Cuộc gọi tới "__real_malloc" trong
"__wrap_malloc" sẽ gọi hàm thực sự "malloc".

Bạn có thể muốn cung cấp một "__real_malloc" chức năng như tốt, vì vậy liên kết mà không có sự lựa chọn --wrap sẽ thành công. Nếu bạn làm điều này, bạn không được đặt định nghĩa của "__real_malloc" trong cùng một tệp như "__wrap_malloc"; nếu bạn làm như vậy, bộ kết hợp có thể giải quyết cuộc gọi trước trình liên kết có cơ hội để bọc nó vào "malloc".

Tùy chọn khác là có thể xem nguồn cho ltrace, ít nhiều cũng giống như vậy :-P.

Đây là một ý tưởng.Bạn có thể thay đổi thư viện ed của LD_PRELOAD các mục PLT để trỏ đến mã của bạn. Về mặt kỹ thuật, bạn có thể gọi hàm sbrk() từ mã của bạn một cách tự nhiên.

+0

Điều này thật tuyệt. Tôi đã không bao giờ nghe nói về tùy chọn - wrap, nhưng điều này là chính xác những gì tôi cần. Cảm ơn bạn. –

+0

Để làm rõ, làm các cờ --wrap cần phải được thông qua khi liên kết thực thi hoặc khi liên kết thư viện LD_PRELOAD chứa các trình bao bọc? Ngoài ra, bạn có cân nhắc cung cấp thêm thông tin về việc sửa đổi các mục PLT của tệp thi hành không? –

+0

Trường hợp sử dụng được thiết kế dành cho bạn để liên kết ứng dụng * target * với --wrap. Nó có thể có thể làm cho nó làm việc cho trường hợp LD_PRELOAD là tốt, tôi không chắc chắn, tôi sẽ phải kiểm tra. –

2

Bạn có thể kiểm tra chức năng gọi âm thầm sử dụng các công cụ như:

  • gdb
  • ltrace
  • systemtap

Những công cụ này cho phép một chương trình giám sát thông báo cho bạn khi một hàm được gọi và cho phép bạn thẩm vấn các đối số.

Sự khác biệt chính là:

  • gdb là tương tác, nhưng mạnh mẽ
  • ltrace đơn giản để sử dụng, nhưng bạn chỉ có thể in tên hàm
  • systemtap là không tương tác, nhưng nó có thể rất nhanh và mạnh mẽ.
0

Nếu bạn đang chạy hệ thống lưu trữ với glibc, libc có một số kết thúc nội bộ cho trình liên kết động thời gian chạy mà tôi đã sử dụng một thời gian trước đây. Nếu tôi nhớ chính xác, tôi nghĩ nó được gọi là '__libc_dlsym'. (Để kiểm tra, "$ readelf -s /usr/lib/libc.a | grep dlsym" nên trợ giúp.) Khai báo nó như một hàm được liên kết bên ngoài với cùng các đối số và giá trị trả về mà dlsym có và sử dụng nó để bọc chính dlsym.

0

truss không hoạt động trên hệ thống của bạn không? Nó hoạt động hoàn hảo cho loại điều này ở đây trên Solaris.

+0

Điều đó nghe có vẻ giống 'strace' trong Linux. Điều này làm việc tốt nếu bạn chỉ cần nhận được một danh sách các cuộc gọi đã được thực hiện. Trong dự án này, tôi cần thêm một số chức năng cho trình bao bọc, và tôi nghĩ rằng sự xen kẽ là cách duy nhất để thực hiện điều đó. –

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