Mandalika's scratchpad [ Work blog @Oracle | Stock Market Notes | My Music Compositions ]

Old Posts: 09.04  10.04  11.04  12.04  01.05  02.05  03.05  04.05  05.05  06.05  07.05  08.05  09.05  10.05  11.05  12.05  01.06  02.06  03.06  04.06  05.06  06.06  07.06  08.06  09.06  10.06  11.06  12.06  01.07  02.07  03.07  04.07  05.07  06.07  08.07  09.07  10.07  11.07  12.07  01.08  02.08  03.08  04.08  05.08  06.08  07.08  08.08  09.08  10.08  11.08  12.08  01.09  02.09  03.09  04.09  05.09  06.09  07.09  08.09  09.09  10.09  11.09  12.09  01.10  02.10  03.10  04.10  05.10  06.10  07.10  08.10  09.10  10.10  11.10  12.10  01.11  02.11  03.11  04.11  05.11  07.11  08.11  09.11  10.11  11.11  12.11  01.12  02.12  03.12  04.12  05.12  06.12  07.12  08.12  09.12  10.12  11.12  12.12  01.13  02.13  03.13  04.13  05.13  06.13  07.13  08.13  09.13  10.13  11.13  12.13  01.14  02.14  03.14  04.14  05.14  06.14 


Monday, May 02, 2005
 
C/C++: Printing Stack Trace with printstack() on Solaris

libc on Solaris 9 and later, provides a useful function called printstack, to print a symbolic stack trace to the specified file descriptor. This is useful for reporting errors from an application during run-time.

If the stack trace appears corrupted, or if the stack cannot be read, printstack() returns -1.

Programmatic example:

% more printstack.c
#include <stdio.h>
#include <ucontext.h>

int callee(int file) {
printstack(file);
return (0);
}

int caller() {
int a;
a = callee (fileno(stdout));
return (a);
}

int main() {
caller();
return (0);
}

% cc -o stacktrace stacktrace.c
% ./stacktrace
/tmp/stacktrace:callee+0x18
/tmp/stacktrace:caller+0x22
/tmp/stacktrace:main+0x14
/tmp/stacktrace:0x6d2

The printstack() function uses dladdr1() to obtain symbolic symbol names. As a result, only global symbols are reported as symbol names by printstack().

% CC -o stacktrace stacktrace.c
% ./stacktrace
/tmp/stacktrace:__1cGcallee6Fi_i_+0x18
/tmp/stacktrace:__1cGcaller6F_i_+0x22
/tmp/stacktrace:main+0x14
/tmp/stacktrace:0x91a

The stack trace from a C++ program, will have all the symbols in their mangled form. So as of now, the programmers may need to have their own wrapper functions to print the stack trace in unmangled form.

There has been an RFE (Request For Enhancement) in place against Solaris' libc to print the stack trace in unmangled form, when printstack() has been called from a C++ program. This will be released as a libc patch for Solaris 8, 9 & 10 some time in the near future.

% elfdump -CsN.symtab libc.so | grep printstack
[5275] 0x00052629 0x00000051 FUNC GLOB D 0 .text _printstack
[6332] 0x00052629 0x00000051 FUNC WEAK D 0 .text printstack

Since the object code is automatically linked with libc during the creation of an executable or a dynamic library, the programmer need not specify -lc on the compile line.

Suggested Reading:
Man page of walkcontext or printstack


Comments:
This is very helpful. Can you show an example of how to printstack to a user-defined file or string?
 
which version onwards does solaris have printstack()?

I am using SunOS 5.8 . printstack returns undefined symbol.
 
Tom,

printstack() & walkcontext() interfaces were introduced in Solaris 9.

Sorry for not being very specific (and for the typo too, where I mentioned about an RFE for unmangled stack)
 
Thanks for the prompt clarification.

Am currently working to implement that on 5.7.... I wonder why this was so hard to find on Google??? :-)
 
You can actually look at the implementation for walkstack() and printstack() at opensolaris.org
 
This comment has been removed by a blog administrator.
 
would it not be easier if it would be possible to have the compiler instrument the actual source code to print stack trace on stdout (might be, use a compile time flag)? its quite painful to put entry and exit statements in a huge system. btw does such an option already exist?
 
would it not be easier if it would be possible to have the compiler instrument the actual source code to print stack trace on stdout

Apparently it is not the job of the compiler. It is pretty easy to write a simple tool that does it, ourselves though.

btw does such an option already exist?

No

its quite painful to put entry and exit statements in a huge system

One simple solution is not to touch the existing code at all, but to interpose upon the symbols where you want to have the call stack. Of course the symbols must have "global" (but not "protected") scope. Please have a look at hijacking a function call (interposing) blog post, to learn more about writing an interposer.

Another advantage of this approach is that the application code remains clean -- you can plug-in (preload) the interposer when you need to look at the call stack; and remove it when it is no longer useful.
 
This is really helpful. Keep on sharing such useful tips & tricks in the future too :)
 
Post a Comment

Links to this post:

Create a Link



<< Home


2004-2014 

This page is powered by Blogger. Isn't yours?