int backtrace (void **array, int size) { struct layout *current; void *__unbounded top_frame; void *__unbounded top_stack; int cnt = 0; top_frame = FIRST_FRAME_POINTER; top_stack = CURRENT_STACK_FRAME; /* We skip the call to this function, it makes no sense to record it. */ current = BOUNDED_1 ((struct layout *) top_frame); while (cnt < size) { if ((void *) current INNER_THAN top_stack || !((void *) current INNER_THAN 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 = ADVANCE_STACK_FRAME (current->next); } return cnt; }
/* This function is called when a segmentation fault is caught. The system is in an instable state now. This means especially that malloc() might not work anymore. */ static void catch_segfault (int signal, SIGCONTEXT ctx) { struct layout *current; void *__unbounded top_frame; void *__unbounded top_stack; int fd; void **arr; size_t cnt; struct sigaction sa; /* This is the name of the file we are writing to. If none is given or we cannot write to this file write to stderr. */ fd = 2; if (fname != NULL) { fd = open (fname, O_TRUNC | O_WRONLY | O_CREAT, 0666); if (fd == -1) fd = 2; } WRITE_STRING ("*** "); write_strsignal (fd, signal); WRITE_STRING ("\n"); #ifdef REGISTER_DUMP REGISTER_DUMP; #endif WRITE_STRING ("\nBacktrace:\n"); top_frame = GET_FRAME (ctx); top_stack = GET_STACK (ctx); /* First count how many entries we'll have. */ cnt = 1; current = BOUNDED_1 ((struct layout *) top_frame); while (!((void *) current INNER_THAN top_stack || !((void *) current INNER_THAN __libc_stack_end))) { ++cnt; current = ADVANCE_STACK_FRAME (current->next); } arr = alloca (cnt * sizeof (void *)); /* First handle the program counter from the structure. */ arr[0] = GET_PC (ctx); current = BOUNDED_1 ((struct layout *) top_frame); cnt = 1; while (!((void *) current INNER_THAN top_stack || !((void *) current INNER_THAN __libc_stack_end))) { arr[cnt++] = current->return_address; current = ADVANCE_STACK_FRAME (current->next); } /* If the last return address was NULL, assume that it doesn't count. */ if (arr[cnt-1] == NULL) cnt--; /* Now generate nicely formatted output. */ __backtrace_symbols_fd (arr, cnt, fd); /* Pass on the signal (so that a core file is produced). */ sa.sa_handler = SIG_DFL; sigemptyset (&sa.sa_mask); sa.sa_flags = 0; sigaction (signal, &sa, NULL); raise (signal); }