Я начну с того, что C может оказаться не лучшим способом сделать это в 2011 году (в зависимости от ваших больших целей).Проверьте этот другой вопрос: Анализ двоичных файлов MIPS: есть ли библиотека Python для анализа двоичных данных? , которая ссылается (например) pydevtools .
При этом, пожалуйста, найдитениже приведен пример использования gaddr2line
(как Solaris произносит addr2line
).
Эта короткая программа просто вызывает функцию foo()
, которая, в свою очередь, вызывает pstack(1)
(в строке 9 через system(3C)
).).В выводе из программы pstack(1)
говорит нам, что адрес в функции foo()
при вызове system()
равен 0x00010724.Наконец, выполнение gaddr2line(1)
по этому адресу говорит нам, что это соответствует строке 9 из foo.c
, и мы прошли полный круг.
/tmp $ cat -n foo.c
1
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <unistd.h>
5
6 int foo() {
7 char buf[64];
8 snprintf(buf, 64, "/bin/pstack %i", getpid());
9 return system(buf);
10 }
11
12 int main(int argc, char *argv[]) {
13 return foo();
14 }
15
/tmp $ gcc -g -o foo foo.c
/tmp $
/tmp $ ./foo
15954: ./foo
ff2cd4d8 waitid (0, 3e53, ffbff668, 3)
ff2bce94 waitpid (3e53, ffbff7bc, 0, 0, ffbff814, ff390140) + 60
ff2afe20 system (ffbff910, ff339bd0, 20000, 1, ff3303d8, ffbff814) + 2ec
00010724 foo (209b8, 1c00, ff335900, 4, ff392a00, ff2b6d6c) + 38
00010748 main (1, ffbffa34, ffbffa3c, 209dc, ff3900c0, 0) + c
00010584 _start (0, 0, 0, 0, 0, 0) + 5c
/tmp $
/tmp $ gaddr2line -e foo 00010724
/tmp/foo.c:9
/tmp $
Далее следует короткий пример использованияwalkcontext(3C)
чтобы пройтись по стеку.Однако, чтобы получить информацию о номере строки отладки, вам нужно запросить соответствующие разделы двоичного файла ELF (?), Используя (например) libdwarf в функции walker()
, но это должно помочь вам начать.
/tmp $ cat -n bar.c
1
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <unistd.h>
5 #include <ucontext.h>
6 #include <dlfcn.h>
7
8 int walker(uintptr_t pc, int sig, void *usrarg) {
9
10 Dl_info dlip;
11
12 if(dladdr((void *)pc, &dlip)) {
13 (void)printf(" %08lx %s %s\n", pc, dlip.dli_fname, dlip.dli_sname);
14 return 0;
15 } else {
16 perror("dladdr()");
17 return -1;
18 }
19
20 }
21
22 int bar() {
23
24 char buf[64];
25 snprintf(buf, 64, "/bin/pstack %i", getpid());
26 system(buf);
27
28 (void)printf("\nprintstack()\n");
29 printstack(0);
30
31 ucontext_t ucp;
32 if(getcontext(&ucp)) {
33 perror("\ngetcontext()");
34 return -1;
35 } else {
36 (void)printf("\nwalkcontext()\n");
37 return walkcontext(&ucp, &walker, NULL);
38 }
39
40 }
41
42 int main(int argc, char *argv[]) {
43 return bar();
44 }
45
/tmp $ gcc -g -o bar bar.c
/tmp $
/tmp $ ./bar
16486: ./bar
ff2cd4d8 waitid (0, 4067, ffbff4b8, 3)
ff2bce94 waitpid (4067, ffbff60c, 0, 0, ffbff664, ff390140) + 60
ff2afe20 system (ffbff928, ff339bd0, 20000, 1, ff3303d8, ffbff664) + 2ec
000108b8 bar (20c70, 1c00, ff335900, 4, ff392a00, ff2b6d6c) + 38
00010968 main (1, ffbffa4c, ffbffa54, 20c94, ff3900c0, 0) + c
00010698 _start (0, 0, 0, 0, 0, 0) + 5c
printstack()
/tmp/bar:bar+0x54
/tmp/bar:main+0xc
/tmp/bar:_start+0x5c
walkcontext()
00010968 /tmp/bar main
00010698 /tmp/bar _start