C 如何在Solaris上获取回溯(函数和行号)?
我用C编写了一些代码,很高兴地将带有函数名和行号的完整回溯发送到日志文件中 这是通过在LINUX上混合使用回溯、回溯_符号以及dladdr和ADDR2LINE完成的。在Linux上也使用“execinfo.h” 因此,基本上如下所示: 回溯:行位置:C 如何在Solaris上获取回溯(函数和行号)?,c,solaris,stack-trace,traceback,pstack,C,Solaris,Stack Trace,Traceback,Pstack,我用C编写了一些代码,很高兴地将带有函数名和行号的完整回溯发送到日志文件中 这是通过在LINUX上混合使用回溯、回溯_符号以及dladdr和ADDR2LINE完成的。在Linux上也使用“execinfo.h” 因此,基本上如下所示: 回溯:行位置: signalErrorHandler /home/lynton/Desktop/TestThreadLeak/TestThreadLeak/./main.c:211 ?? ??:0 *__GI_raise /build/buildd/eglibc-
signalErrorHandler
/home/lynton/Desktop/TestThreadLeak/TestThreadLeak/./main.c:211
??
??:0
*__GI_raise
/build/buildd/eglibc-2.12.1/signal/../nptl/sysdeps/unix/sysv/linux/raise.c:64
*__GI_abort
/build/buildd/eglibc-2.12.1/stdlib/abort.c:94
__libc_message
/build/buildd/eglibc-2.12.1/libio/../sysdeps/unix/sysv/linux/libc_fatal.c:168
malloc_printerr
/build/buildd/eglibc-2.12.1/malloc/malloc.c:6283
*__GI___libc_free
/build/buildd/eglibc-2.12.1/malloc/malloc.c:3739
threadMainLoop
/home/lynton/Desktop/TestThreadLeak/TestThreadLeak/./main.c:260
start_thread
/build/buildd/eglibc-2.12.1/nptl/pthread_create.c:304
??
/build/buildd/eglibc-2.12.1/misc/../sysdeps/unix/sysv/linux/x86_64/clone.S:114
现在我已经将代码带到Solaris,我发现它不受支持-(
我在Solaris上尝试了pstack方法,得到如下结果:
15871: ./exit_test
----------------- lwp# 1 / thread# 1 --------------------
ffffffff7efdaf48 lwp_wait (2, ffffffff7ffffb9c)
ffffffff7efd34ac _thrp_join (2, 0, 0, 1, 0, ffffffff7ffffb9c) + 38
00000001000012f0 main (1, ffffffff7ffffd28, ffffffff7ffffd38, 100101f68, 100000000, ffffffff7f500200) + 204
0000000100000ba4 _start (0, 0, 0, 0, 0, 0) + 7c
----------------- lwp# 2 / thread# 2 --------------------
ffffffff7efdb210 waitid (0, 3e01, ffffffff7eaf8c30, 3)
ffffffff7efc9cbc waitpid (3e01, ffffffff7eaf8eb0, 0, 0, ffffffff7f100300, 0) + 64
ffffffff7efbcc08 system (ffffffff7eaf9ff0, 1ad8, 1800, 0, ffffffff7f13c000, ffffffff7eaf8f18) + 394
0000000100000fec signalErrorHandler (b, 0, ffffffff7eafbba0, 40000000, 0, 0) + 2bc
ffffffff7efd6fdc __sighndlr (b, 0, ffffffff7eafbba0, 100000d30, 0, 0) + c
ffffffff7efcab70 call_user_handler (ffffffff7f500a00, ffffffff7f500a00, ffffffff7eafbba0, 12, 0, 0) + 3e0
ffffffff7efcad7c sigacthandler (0, 0, ffffffff7eafbba0, ffffffff7f500a00, 0, ffffffff7f13c000) + 68
--- called from signal handler with signal 0 (SIGEXIT) ---
ffffffff7ee0052c memcpy (ffffffff7ffffd28, 1fc000, 0, 0, 100001040, 0) + 30
ffffffff7efd6eb0 _lwp_start (0, 0, 0, 0, 0, 0)
我怎样才能以某种方式使用上面的代码以编程的方式获得行号和函数名呢?我已经看到了一些关于“walkcontext”或“walkstack”的内容……有没有人能给我一些示例代码来获取行号等
另外,我在Linux上使用了ADDR2LINE,它工作得很好……有人能从上面的转储告诉我如何在Solaris上使用它吗?我无法让它工作-(
任何建议都将不胜感激
谢谢
林顿首先,我要说的是,在2011年,C可能不是实现这一目标的最佳方式(取决于你的更大目标) 也就是说,请在下面找到一个使用
gaddr2line
的示例(这就是Solaris的拼写方式addr2line
)
这个简短的程序只调用函数foo()
,它依次调用pstack(1)
(在第9行,通过system(3C)
)。在程序的输出中,pstack(1)
告诉我们调用system()
时,函数foo()
中的地址是0x00010724。最后,运行gaddr2line(1)该地址上的
告诉我们,这对应于foo.c
的第9行,我们已经完成了完整的循环
/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 $
谢谢你的帮助,非常感谢;-)
/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