static int thread_callback(Dwfl_Thread *thread, void *userdata) { struct stack_context *c = userdata; pid_t tid; assert(thread); assert(c); if (c->n_thread >= THREADS_MAX) return DWARF_CB_ABORT; if (c->n_thread != 0) fputc('\n', c->f); c->n_frame = 0; tid = dwfl_thread_tid(thread); fprintf(c->f, "Stack trace of thread " PID_FMT ":\n", tid); if (dwfl_thread_getframes(thread, frame_callback, c) < 0) return DWARF_CB_ABORT; c->n_thread ++; return DWARF_CB_OK; }
static int unwind_thread(Dwfl_Thread *thread, void *data) { struct thread_callback_arg *thread_arg = data; char **error_msg = &thread_arg->error_msg; struct sr_core_thread *result = sr_core_thread_new(); if (!result) { set_error("Failed to initialize stacktrace memory"); return DWARF_CB_ABORT; } result->id = (int64_t)dwfl_thread_tid(thread); struct frame_callback_arg frame_arg = { .thread = result, .error_msg = NULL }; int ret = dwfl_thread_getframes(thread, frame_callback, &frame_arg); if (ret == -1) { warn("dwfl_thread_getframes failed for thread id %d: %s", (int)result->id, dwfl_errmsg(-1)); } else if (ret == DWARF_CB_ABORT) { *error_msg = frame_arg.error_msg; goto abort; } else if (ret != 0 && ret != CB_STOP_UNWIND) { *error_msg = sr_strdup("Unknown error in dwfl_thread_getframes"); goto abort; } if (!error_msg && !frame_arg.thread->frames) { set_error("No frames found for thread id %d", (int)result->id); goto abort; } thread_arg->stacktrace->threads = sr_core_thread_append(thread_arg->stacktrace->threads, result); return DWARF_CB_OK; abort: sr_core_thread_free(result); return DWARF_CB_ABORT; }
static int thread_cb(Dwfl_Thread *thread, void *userdata) { int ret; GString **bt = (GString **)userdata; pid_t tid; tid = dwfl_thread_tid(thread); g_string_append_printf(*bt, "\nBacktrace (TID %u):\n", (unsigned int)tid); ret = dwfl_thread_getframes(thread, frame_cb, userdata); switch (ret) { case -1: errorstr = g_strdup_printf("Error while iterating" " through frames for thread" " %u: %s\n", (unsigned int)tid, dwfl_errmsg(-1)); return DWARF_CB_ABORT; case DWARF_CB_ABORT: /* already set the error string in frame_cb */ return DWARF_CB_ABORT; case DWARF_CB_OK: break; default: telem_log(LOG_ERR, "Unrecognized return code\n"); return DWARF_CB_ABORT; } // New threads (if any), will require a fresh frame counter frame_counter = 0; #if 0 g_string_append_printf(*bt, "\nRegisters (TID %u):\nTODO\n", current, (unsigned int)tid); #endif return DWARF_CB_OK; }