To begin with, C may not be the best way to do this in 2011 (depending on your larger goals). Look at another question: MIPS binary analysis: is there a Python library for parsing binary data? that are referenced (for example) by pydevtools .
However, the following is an example using gaddr2line (since Solaris addr2line ).
This short program simply calls the foo() function, which in turn calls pstack(1) (on line 9 via system(3C) ). On exit from the program, pstack(1) tells us that the address in the foo() function when calling system() is 0x00010724. Finally, running gaddr2line(1) at this address tells us that this matches line 9 of foo.c , and we got a full circle.
/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 $
Following this, here is a brief example of using walkcontext(3C) to traverse a stack. To get information about the debug number, you will need to request the appropriate sections of the ELF binary (?), Using (for example) libdwarf in walker() , but this should get you started.
/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