By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
449,367 Members | 1,733 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 449,367 IT Pros & Developers. It's quick & easy.

Stacktrace code snippet? Like gdb's "bt"

P: n/a
Does anyone know about a code snippet that can be used
to output a backtrace just like gdb's "backtrace" command
does. One that can be called on a segmentation fault.
(without resolving symbol names, just simple list of frames
until the main() stack frame)

Nov 14 '05 #1
Share this Question
Share on Google+
3 Replies


P: n/a
In article <dx*****************@newsb.telia.net>
eiselekd <ei******@gmx.de> wrote:
Does anyone know about a code snippet that can be used
to output a backtrace just like gdb's "backtrace" command
does. One that can be called on a segmentation fault.
(without resolving symbol names, just simple list of frames
until the main() stack frame)


This cannot be done portably. GDB does it with code that includes
special cases -- as in, code written especially for every single
machine architecture for which gdb does it. There is *some*
code-sharing, e.g., via the "bfd" library, but it really, truly
requires that you write new code every time you port gdb to a new
machine. Sometimes that code is simple, but sometimes it is
horribly complex, and requires cooperation with the compiler.
(In particular, on architectures in which there are different
methods for returning from different function classifications,
one might need to look in different registers or stack locations
or similar depending on the return type and/or "leaf-ness" of
any particular function.)

In a few cases (which one might hope are rare), it cannot be done
at all, because by the time you get something like a "segmentation
fault", the system has removed critical information that the program
that encountered the problem would need. (For a debugger to work
at all on these systems, they have to provide a special, outside-the-
"segmentation-fault" communications channel. Systems with no
debugging facilities at all do exist as well, though.)
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (4039.22'N, 11150.29'W) +1 801 277 2603
email: forget about it http://web.torek.net/torek/index.html
Reading email is like searching for food in the garbage, thanks to spammers.
Nov 14 '05 #2

P: n/a
On Sun, 21 Nov 2004 13:56:09 -0500, eiselekd wrote:
Does anyone know about a code snippet that can be used to output a
backtrace just like gdb's "backtrace" command does. One that can be
called on a segmentation fault. (without resolving symbol names, just
simple list of frames until the main() stack frame)


I think this is what you want:

http://samba.org/ftp/unpacked/junkcode/segv_handler/

But of course I'm obligated to point out that this is *nix specific,
is not ansi C, and is therefore offtopic here.
I use some macros that can build error text in a static buffer. The
result looks like this:

src/module.c:365:module_load: foo.so: cannot open shared object file
src/module.c:405:module_load_all:
src/main.c:114:run:

It's part of my personal "toolbelt" of stuff:

http://www.ioplex.com/~miallen/libmb...ref/msgno.html

I think it's ANSI but it doesn't get called automatically on segv and it
uses variadic macros so you only get the stack trace like effect if you're
using a c library that supports them (e.g. glibc does, MS' does not).

Mike
Nov 14 '05 #3

P: n/a
Found it myself:

#include <stdio.h>
#include <stdlib.h>

#define UNW_LOCAL_ONLY
#include <unwind.h>

void *__libc_stack_end;

struct layout
{
struct layout * next;
void * return_address;
};

int
__backtrace (array, size)
void **array;
int size;
{
/* We assume that all the code is generated with frame pointers set. */
register void *ebp __asm__ ("ebp");
register void *esp __asm__ ("esp");
struct layout *current;
int cnt = 0;

/* We skip the call to this function, it makes no sense to record it. */
current = ((struct layout *) ebp);
while (cnt < size)
{
if ((void *) current < esp || (void *) current > __libc_stack_end)
/* This means the address is out of range. Note that for the
toplevel we see a frame pointer with value NULL which clearly is
out of range. */
break;

array[cnt++] = current->return_address;

current = current->next;
}

return cnt;
}

/* _Unwind_Reason_Code Trace_Fn (struct _Unwind_Context *c, void *arg) */
/* { */
/* printf ("Out\n"); */
/* return _URC_NO_REASON; */
/* } */

/* void print_trace (void) { */

/* _Unwind_Reason_Code r = _Unwind_Backtrace(Trace_Fn,0); */

/* /\*{ */

/* unw_getcontext(&uc); */
/* unw_init_local(&cursor, &uc); */
/* while (unw_step(&cursor) > 0) { */
/* unw_get_reg(&cursor, UNW_REG_IP, &ip); */
/* unw_get_reg(&cursor, UNW_REG_SP, &sp); */
/* printf ("ip = %lx, sp = %lx\n", (long) ip, (long) sp); */
/* }*\/ */
/* } */
/* A dummy function to make the backtrace more interesting. */
void
dummy_function2 (void)
{
void *a[10]; int i = 0;
int cnt = __backtrace (&a, 10);
for (i = 0;i < cnt;i++) {
printf("%x\n",a[i]);
}

}

/* A dummy function to make the backtrace more interesting. */
void
dummy_function1 (void)
{
dummy_function2 ();
}

int main ()
{
/* We assume that all the code is generated with frame pointers set. */
register void *ebp __asm__ ("ebp");
register void *esp __asm__ ("esp");
__libc_stack_end = ((struct layout *) ebp);
dummy_function1 ();
return 0;
}



If glibc is present:
-------------------------------------
#include <execinfo.h>
#include <stdio.h>
#include <stdlib.h>

/* Obtain a backtrace and print it to stdout. */
void
print_trace (void)
{
void *array[10];
size_t size;
char **strings;
size_t i;

size = backtrace (array, 10);
strings = backtrace_symbols (array, size);

printf ("Obtained %zd stack frames.\n", size);

for (i = 0; i < size; i++)
printf ("%s\n", strings[i]);

free (strings);
}

/* A dummy function to make the backtrace more interesting. */
void
dummy_function (void)
{
print_trace ();
}

int
main (void)
{
dummy_function ();
return 0;
}
-------------------------------------

Chris Torek <no****@torek.net> wrote in message news:<cn*********@news4.newsguy.com>...
In article <dx*****************@newsb.telia.net>
eiselekd <ei******@gmx.de> wrote:
Does anyone know about a code snippet that can be used
to output a backtrace just like gdb's "backtrace" command
does. One that can be called on a segmentation fault.
(without resolving symbol names, just simple list of frames
until the main() stack frame)


This cannot be done portably. GDB does it with code that includes
special cases -- as in, code written especially for every single
machine architecture for which gdb does it. There is *some*
code-sharing, e.g., via the "bfd" library, but it really, truly
requires that you write new code every time you port gdb to a new
machine. Sometimes that code is simple, but sometimes it is
horribly complex, and requires cooperation with the compiler.
(In particular, on architectures in which there are different
methods for returning from different function classifications,
one might need to look in different registers or stack locations
or similar depending on the return type and/or "leaf-ness" of
any particular function.)

In a few cases (which one might hope are rare), it cannot be done
at all, because by the time you get something like a "segmentation
fault", the system has removed critical information that the program
that encountered the problem would need. (For a debugger to work
at all on these systems, they have to provide a special, outside-the-
"segmentation-fault" communications channel. Systems with no
debugging facilities at all do exist as well, though.)

Nov 14 '05 #4

This discussion thread is closed

Replies have been disabled for this discussion.