Backtrace *libdwGetBacktrace(LibdwSession *session) { if (session->cur_bt != NULL) { sysErrorBelch("Already collecting backtrace. Uh oh."); return NULL; } Backtrace *bt = backtraceAlloc(); session->cur_bt = bt; int pid = getpid(); int ret = dwfl_getthread_frames(session->dwfl, pid, getBacktraceFrameCb, session); if (ret == -1) sysErrorBelch("Failed to get stack frames of current process: %s", dwfl_errmsg(dwfl_errno())); session->cur_bt = NULL; return bt; }
void output_right(enum tof type, struct process *proc, struct library_symbol *libsym, struct timedelta *spent) { assert(! options.summary); struct prototype *func = lookup_symbol_prototype(proc, libsym); if (func == NULL) return; if (current_proc != NULL && (current_proc != proc || current_depth != proc->callstack_depth)) { fprintf(options.output, " <unfinished ...>\n"); current_proc = NULL; } if (current_proc != proc) { begin_of_line(proc, type == LT_TOF_FUNCTIONR, 1); #ifdef USE_DEMANGLE current_column += fprintf(options.output, "<... %s resumed> ", options.demangle ? my_demangle(libsym->name) : libsym->name); #else current_column += fprintf(options.output, "<... %s resumed> ", libsym->name); #endif } struct callstack_element *stel = &proc->callstack[proc->callstack_depth - 1]; struct fetch_context *context = stel->fetch_context; /* Fetch & enter into dictionary the retval first, so that * other values can use it in expressions. */ struct value retval; bool own_retval = false; if (context != NULL) { value_init(&retval, proc, NULL, func->return_info, 0); own_retval = true; if (fetch_retval(context, type, proc, func->return_info, &retval) < 0) value_set_type(&retval, NULL, 0); else if (stel->arguments != NULL && val_dict_push_named(stel->arguments, &retval, "retval", 0) == 0) own_retval = false; } if (stel->arguments != NULL) output_params(stel->arguments, stel->out.params_left, val_dict_count(stel->arguments), &stel->out.need_delim); current_column += fprintf(options.output, ") "); tabto(options.align - 1); fprintf(options.output, "= "); if (context != NULL && retval.type != NULL) { struct format_argument_data data = { &retval, stel->arguments }; format_argument_cb(options.output, &data); } if (own_retval) value_destroy(&retval); if (opt_T) { assert(spent != NULL); fprintf(options.output, " <%lu.%06d>", (unsigned long) spent->tm.tv_sec, (int) spent->tm.tv_usec); } fprintf(options.output, "\n"); #if defined(HAVE_LIBUNWIND) if (options.bt_depth > 0 && proc->unwind_priv != NULL && proc->unwind_as != NULL) { unw_cursor_t cursor; arch_addr_t ip, function_offset; struct library *lib = NULL; int unwind_depth = options.bt_depth; char fn_name[100]; const char *lib_name; size_t distance; /* Verify that we can safely cast arch_addr_t* to * unw_word_t*. */ (void)sizeof(char[1 - 2*(sizeof(unw_word_t) != sizeof(arch_addr_t))]); unw_init_remote(&cursor, proc->unwind_as, proc->unwind_priv); while (unwind_depth) { int rc = unw_get_reg(&cursor, UNW_REG_IP, (unw_word_t *) &ip); if (rc < 0) { fprintf(options.output, " > Error: %s\n", unw_strerror(rc)); goto cont; } /* We are looking for the library with the base address * closest to the current ip. */ lib_name = "unmapped_area"; distance = (size_t) -1; lib = proc->libraries; while (lib != NULL) { /* N.B.: Assumes sizeof(size_t) == * sizeof(arch_addr_t). * Keyword: double cast. */ if ((ip >= lib->base) && ((size_t)(ip - lib->base) < distance)) { distance = ip - lib->base; lib_name = lib->pathname; } lib = lib->next; } rc = unw_get_proc_name(&cursor, fn_name, sizeof(fn_name), (unw_word_t *) &function_offset); if (rc == 0 || rc == -UNW_ENOMEM) fprintf(options.output, " > %s(%s+%p) [%p]\n", lib_name, fn_name, function_offset, ip); else fprintf(options.output, " > %s(??\?) [%p]\n", lib_name, ip); cont: if (unw_step(&cursor) <= 0) break; unwind_depth--; } fprintf(options.output, "\n"); } #endif /* defined(HAVE_LIBUNWIND) */ #if defined(HAVE_LIBDW) if (options.bt_depth > 0 && proc->leader->dwfl != NULL) { int frames = options.bt_depth; if (dwfl_getthread_frames(proc->leader->dwfl, proc->pid, frame_callback, &frames) < 0) { // Only print an error if we couldn't show anything. // Otherwise just show there might be more... if (frames == options.bt_depth) fprintf(stderr, "dwfl_getthread_frames tid %d: %s\n", proc->pid, dwfl_errmsg(-1)); else fprintf(options.output, " > [...]\n"); } fprintf(options.output, "\n"); } #endif /* defined(HAVE_LIBDW) */ current_proc = NULL; current_column = 0; }