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.)