2012-10-02 37 views
11

tôi biên soạn mã này với gcc hello.c -o chào O3Biểu tượng __gmon_start__ là gì?

#include <stdio.h> 

int main(void) { 
    printf("Hello world\n"); 
    return 0; 
} 

khi tôi liệt kê các sự định vị tôi nhận được:

[email protected]$ readelf -r hello | grep gmon 
080495a4 00000106 R_386_GLOB_DAT 00000000 __gmon_start__ 
080495b4 00000107 R_386_JUMP_SLOT 00000000 __gmon_start__ 

khi tôi liệt kê những biểu tượng trong tập tin này tôi nhận được :

[email protected]$ readelf -s hello | grep gmon 
    1: 00000000  0 NOTYPE WEAK DEFAULT UND __gmon_start__ 
    48: 00000000  0 NOTYPE WEAK DEFAULT UND __gmon_start__ 

Gmon_start có liên quan gì đến gprof không? Tại sao có một di dời cho biểu tượng đó ngay cả khi tôi không biên dịch/liên kết với -pg hoặc -g? Thư viện nào sẽ giải quyết biểu tượng này?

Trả lời

10

Đã làm một chút googling và thấy điều này từ here:

Chức năng call_gmon_start khởi hệ thống gmon profiling. Hệ thống này được bật khi các tệp nhị phân được biên dịch với cờ -pg, và tạo đầu ra để sử dụng với gprof (1). Trong trường hợp của kịch bản binary call_gmon_start được đặt trực tiếp tiếp tục _start chức năng. Hàm call_gmon_start tìm mục nhập cuối cùng trong Bảng bù trừ toàn cầu (còn được gọi là __gmon_start__) và, nếu không NULL, sẽ chuyển quyền kiểm soát đến địa chỉ được chỉ định. Phần tử __gmon_start__ trỏ đến hàm khởi tạo gmon, bắt đầu ghi thông tin lược tả và đăng ký chức năng dọn dẹp với atexit(). Trong trường hợp của chúng tôi tuy nhiên gmon không được sử dụng, và như vậy __gmon_start__ là NULL.

Vậy ...

  1. Vâng, nó có cái gì để làm với gprof
  2. Tôi không chắc chắn lý do tại sao biểu tượng là nhận được còn lại trong đó. Có lẽ chỉ là một người giữ chỗ cho khi nó được biên soạn cho gprof?

Cập nhật:

Được rồi, vì vậy tôi biên soạn mã của bạn có và không có -pg. Có vẻ như __gmon_start__ được ánh xạ tới một địa chỉ trong chương trình được biên dịch. Vì vậy, với điều đó đang được nói, tôi không nghĩ rằng có một thư viện mà giải quyết biểu tượng đó, nhưng chương trình chính nó.

với -pg:

[email protected]:~$ readelf -r hello 

Relocation section '.rel.dyn' at offset 0x32c contains 1 entries: 
Offset  Info Type   Sym.Value Sym. Name 
08049fec 00000806 R_386_GLOB_DAT 08048460 __gmon_start__ 

Relocation section '.rel.plt' at offset 0x334 contains 6 entries: 
Offset  Info Type   Sym.Value Sym. Name 
0804a000 00000607 R_386_JUMP_SLOT 080483b0 _mcleanup 
0804a004 00000107 R_386_JUMP_SLOT 00000000 __monstartup 
0804a008 00000207 R_386_JUMP_SLOT 00000000 mcount 
0804a00c 00000307 R_386_JUMP_SLOT 00000000 __cxa_atexit 
0804a010 00000407 R_386_JUMP_SLOT 00000000 puts 
0804a014 00000507 R_386_JUMP_SLOT 00000000 __libc_start_main 

objdump của __gmon_start__ mã:

[email protected]:~$ objdump -S hello | grep "460 <__gmon_start__>:" -A 20 

08048460 <__gmon_start__>: 
8048460:  83 ec 1c    sub $0x1c,%esp 
8048463:  a1 20 a0 04 08   mov 0x804a020,%eax 
8048468:  85 c0     test %eax,%eax 
804846a:  75 2a     jne 8048496 <__gmon_start__+0x36> 
804846c:  c7 05 20 a0 04 08 01 movl $0x1,0x804a020 
8048473:  00 00 00 
8048476:  c7 44 24 04 36 86 04 movl $0x8048636,0x4(%esp) 
804847d:  08 
804847e:  c7 04 24 30 84 04 08 movl $0x8048430,(%esp) 
8048485:  e8 36 ff ff ff   call 80483c0 <[email protected]> 
804848a:  c7 04 24 b0 83 04 08 movl $0x80483b0,(%esp) 
8048491:  e8 1a 01 00 00   call 80485b0 <atexit> 
8048496:  83 c4 1c    add $0x1c,%esp 
8048499:  c3      ret  
804849a:  90      nop 
804849b:  90      nop 
804849c:  90      nop 
804849d:  90      nop 

Với __gmon_start__ có mặt trong biên soạn chương trình hello, bạn có thể thấy rằng __monstartup được gọi vào.(monstartup man page)

mà không -pg:

[email protected]:~$ readelf -r hello 

Relocation section '.rel.dyn' at offset 0x290 contains 1 entries: 
Offset  Info Type   Sym.Value Sym. Name 
08049ff0 00000206 R_386_GLOB_DAT 00000000 __gmon_start__ 

Relocation section '.rel.plt' at offset 0x298 contains 3 entries: 
Offset  Info Type   Sym.Value Sym. Name 
0804a000 00000107 R_386_JUMP_SLOT 00000000 puts 
0804a004 00000207 R_386_JUMP_SLOT 00000000 __gmon_start__ 
0804a008 00000307 R_386_JUMP_SLOT 00000000 __libc_start_main 

Bạn có thể thấy ở đây, rằng giá trị biểu tượng của __gmon_start__ được thiết lập để 00000000.

+0

về câu hỏi thứ ba? Tôi có nên xem mục nhập cuối cùng trong GOT là địa chỉ của __gmon_start__ không? Ngoài ra, kiểm tra các nhị phân của "hello" nó chỉ ra rằng có một mục: __gmon_start __ @ plt và một (mục PLT) __gmon_start __ @ plt-0x10> – JohnTortugo

+0

Vậy làm thế nào để bù đắp cho 'gmon_start' được ánh xạ tới một địa chỉ vật lý ? – RouteMapper

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