* commit 'f1f150d0e6e27588d0b15a53e7fac4984bf6ccd8': Refactor to share map_info amongst threads.
This commit is contained in:
commit
5ca7d87fe4
10 changed files with 75 additions and 44 deletions
|
|
@ -415,7 +415,7 @@ static void dump_thread(const backtrace_context_t* context, log_t* log,
|
||||||
|
|
||||||
/* Return true if some thread is not detached cleanly */
|
/* Return true if some thread is not detached cleanly */
|
||||||
static bool dump_sibling_thread_report(
|
static bool dump_sibling_thread_report(
|
||||||
log_t* log, pid_t pid, pid_t tid, int* total_sleep_time_usec) {
|
log_t* log, pid_t pid, pid_t tid, int* total_sleep_time_usec, backtrace_map_info_t* map_info) {
|
||||||
char task_path[64];
|
char task_path[64];
|
||||||
snprintf(task_path, sizeof(task_path), "/proc/%d/task", pid);
|
snprintf(task_path, sizeof(task_path), "/proc/%d/task", pid);
|
||||||
|
|
||||||
|
|
@ -449,7 +449,7 @@ static bool dump_sibling_thread_report(
|
||||||
_LOG(log, 0, "--- --- --- --- --- --- --- --- --- --- --- --- --- --- --- ---\n");
|
_LOG(log, 0, "--- --- --- --- --- --- --- --- --- --- --- --- --- --- --- ---\n");
|
||||||
dump_thread_info(log, pid, new_tid, 0);
|
dump_thread_info(log, pid, new_tid, 0);
|
||||||
backtrace_context_t new_context;
|
backtrace_context_t new_context;
|
||||||
if (backtrace_create_context(&new_context, pid, new_tid, 0)) {
|
if (backtrace_create_context_with_map(&new_context, pid, new_tid, 0, map_info)) {
|
||||||
dump_thread(&new_context, log, 0, total_sleep_time_usec);
|
dump_thread(&new_context, log, 0, total_sleep_time_usec);
|
||||||
backtrace_destroy_context(&new_context);
|
backtrace_destroy_context(&new_context);
|
||||||
}
|
}
|
||||||
|
|
@ -676,7 +676,9 @@ static bool dump_crash(log_t* log, pid_t pid, pid_t tid, int signal, uintptr_t a
|
||||||
}
|
}
|
||||||
|
|
||||||
backtrace_context_t context;
|
backtrace_context_t context;
|
||||||
if (backtrace_create_context(&context, pid, tid, 0)) {
|
/* Gather the map info once for all this process' threads. */
|
||||||
|
backtrace_map_info_t* map_info = backtrace_create_map_info_list(pid);
|
||||||
|
if (backtrace_create_context_with_map(&context, pid, tid, 0, map_info)) {
|
||||||
dump_abort_message(&context, log, abort_msg_address);
|
dump_abort_message(&context, log, abort_msg_address);
|
||||||
dump_thread(&context, log, SCOPE_AT_FAULT, total_sleep_time_usec);
|
dump_thread(&context, log, SCOPE_AT_FAULT, total_sleep_time_usec);
|
||||||
backtrace_destroy_context(&context);
|
backtrace_destroy_context(&context);
|
||||||
|
|
@ -688,9 +690,12 @@ static bool dump_crash(log_t* log, pid_t pid, pid_t tid, int signal, uintptr_t a
|
||||||
|
|
||||||
bool detach_failed = false;
|
bool detach_failed = false;
|
||||||
if (dump_sibling_threads) {
|
if (dump_sibling_threads) {
|
||||||
detach_failed = dump_sibling_thread_report(log, pid, tid, total_sleep_time_usec);
|
detach_failed = dump_sibling_thread_report(log, pid, tid, total_sleep_time_usec, map_info);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Destroy the previously created map info. */
|
||||||
|
backtrace_destroy_map_info_list(map_info);
|
||||||
|
|
||||||
if (want_logs) {
|
if (want_logs) {
|
||||||
dump_logs(log, pid, false);
|
dump_logs(log, pid, false);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,9 @@ public:
|
||||||
// If pid >= 0 and tid < 0, then the Backtrace object corresponds to a
|
// If pid >= 0 and tid < 0, then the Backtrace object corresponds to a
|
||||||
// different process.
|
// different process.
|
||||||
// Tracing a thread in a different process is not supported.
|
// Tracing a thread in a different process is not supported.
|
||||||
static Backtrace* Create(pid_t pid, pid_t tid);
|
// If map_info is NULL, then create the map and manage it internally.
|
||||||
|
// If map_info is not NULL, the map is still owned by the caller.
|
||||||
|
static Backtrace* Create(pid_t pid, pid_t tid, backtrace_map_info_t* map_info = NULL);
|
||||||
|
|
||||||
virtual ~Backtrace();
|
virtual ~Backtrace();
|
||||||
|
|
||||||
|
|
@ -70,7 +72,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Backtrace(BacktraceImpl* impl);
|
Backtrace(BacktraceImpl* impl, pid_t pid, backtrace_map_info_t* map_info);
|
||||||
|
|
||||||
virtual bool VerifyReadWordArgs(uintptr_t ptr, uint32_t* out_value);
|
virtual bool VerifyReadWordArgs(uintptr_t ptr, uint32_t* out_value);
|
||||||
|
|
||||||
|
|
@ -78,6 +80,8 @@ protected:
|
||||||
|
|
||||||
backtrace_map_info_t* map_info_;
|
backtrace_map_info_t* map_info_;
|
||||||
|
|
||||||
|
bool map_info_requires_delete_;
|
||||||
|
|
||||||
backtrace_t backtrace_;
|
backtrace_t backtrace_;
|
||||||
|
|
||||||
friend class BacktraceImpl;
|
friend class BacktraceImpl;
|
||||||
|
|
|
||||||
|
|
@ -73,6 +73,14 @@ typedef struct {
|
||||||
bool backtrace_create_context(
|
bool backtrace_create_context(
|
||||||
backtrace_context_t* context, pid_t pid, pid_t tid, size_t num_ignore_frames);
|
backtrace_context_t* context, pid_t pid, pid_t tid, size_t num_ignore_frames);
|
||||||
|
|
||||||
|
/* The same as backtrace_create_context, except that it is assumed that
|
||||||
|
* the pid map has already been acquired and the caller will handle freeing
|
||||||
|
* the map data.
|
||||||
|
*/
|
||||||
|
bool backtrace_create_context_with_map(
|
||||||
|
backtrace_context_t* context, pid_t pid, pid_t tid, size_t num_ignore_frames,
|
||||||
|
backtrace_map_info_t* map_info);
|
||||||
|
|
||||||
/* Gather the backtrace data for a pthread instead of a process. */
|
/* Gather the backtrace data for a pthread instead of a process. */
|
||||||
bool backtrace_create_thread_context(
|
bool backtrace_create_thread_context(
|
||||||
backtrace_context_t* context, pid_t tid, size_t num_ignore_frames);
|
backtrace_context_t* context, pid_t tid, size_t num_ignore_frames);
|
||||||
|
|
|
||||||
|
|
@ -42,11 +42,18 @@ backtrace_t* BacktraceImpl::GetBacktraceData() {
|
||||||
//-------------------------------------------------------------------------
|
//-------------------------------------------------------------------------
|
||||||
// Backtrace functions.
|
// Backtrace functions.
|
||||||
//-------------------------------------------------------------------------
|
//-------------------------------------------------------------------------
|
||||||
Backtrace::Backtrace(BacktraceImpl* impl) : impl_(impl), map_info_(NULL) {
|
Backtrace::Backtrace(BacktraceImpl* impl, pid_t pid, backtrace_map_info_t* map_info)
|
||||||
|
: impl_(impl), map_info_(map_info), map_info_requires_delete_(false) {
|
||||||
impl_->SetParent(this);
|
impl_->SetParent(this);
|
||||||
backtrace_.num_frames = 0;
|
backtrace_.num_frames = 0;
|
||||||
backtrace_.pid = -1;
|
backtrace_.pid = pid;
|
||||||
backtrace_.tid = -1;
|
backtrace_.tid = -1;
|
||||||
|
|
||||||
|
if (map_info_ == NULL) {
|
||||||
|
// Create the map and manage it internally.
|
||||||
|
map_info_ = backtrace_create_map_info_list(pid);
|
||||||
|
map_info_requires_delete_ = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Backtrace::~Backtrace() {
|
Backtrace::~Backtrace() {
|
||||||
|
|
@ -57,7 +64,7 @@ Backtrace::~Backtrace() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (map_info_) {
|
if (map_info_ && map_info_requires_delete_) {
|
||||||
backtrace_destroy_map_info_list(map_info_);
|
backtrace_destroy_map_info_list(map_info_);
|
||||||
map_info_ = NULL;
|
map_info_ = NULL;
|
||||||
}
|
}
|
||||||
|
|
@ -151,8 +158,8 @@ std::string Backtrace::FormatFrameData(size_t frame_num) {
|
||||||
//-------------------------------------------------------------------------
|
//-------------------------------------------------------------------------
|
||||||
// BacktraceCurrent functions.
|
// BacktraceCurrent functions.
|
||||||
//-------------------------------------------------------------------------
|
//-------------------------------------------------------------------------
|
||||||
BacktraceCurrent::BacktraceCurrent(BacktraceImpl* impl) : Backtrace(impl) {
|
BacktraceCurrent::BacktraceCurrent(
|
||||||
map_info_ = backtrace_create_map_info_list(-1);
|
BacktraceImpl* impl, backtrace_map_info_t *map_info) : Backtrace(impl, getpid(), map_info) {
|
||||||
|
|
||||||
backtrace_.pid = getpid();
|
backtrace_.pid = getpid();
|
||||||
}
|
}
|
||||||
|
|
@ -179,11 +186,9 @@ bool BacktraceCurrent::ReadWord(uintptr_t ptr, uint32_t* out_value) {
|
||||||
//-------------------------------------------------------------------------
|
//-------------------------------------------------------------------------
|
||||||
// BacktracePtrace functions.
|
// BacktracePtrace functions.
|
||||||
//-------------------------------------------------------------------------
|
//-------------------------------------------------------------------------
|
||||||
BacktracePtrace::BacktracePtrace(BacktraceImpl* impl, pid_t pid, pid_t tid)
|
BacktracePtrace::BacktracePtrace(
|
||||||
: Backtrace(impl) {
|
BacktraceImpl* impl, pid_t pid, pid_t tid, backtrace_map_info_t* map_info)
|
||||||
map_info_ = backtrace_create_map_info_list(tid);
|
: Backtrace(impl, pid, map_info) {
|
||||||
|
|
||||||
backtrace_.pid = pid;
|
|
||||||
backtrace_.tid = tid;
|
backtrace_.tid = tid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -212,26 +217,27 @@ bool BacktracePtrace::ReadWord(uintptr_t ptr, uint32_t* out_value) {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
Backtrace* Backtrace::Create(pid_t pid, pid_t tid) {
|
Backtrace* Backtrace::Create(pid_t pid, pid_t tid, backtrace_map_info_t* map_info) {
|
||||||
if (pid == BACKTRACE_CURRENT_PROCESS || pid == getpid()) {
|
if (pid == BACKTRACE_CURRENT_PROCESS || pid == getpid()) {
|
||||||
if (tid == BACKTRACE_NO_TID || tid == gettid()) {
|
if (tid == BACKTRACE_NO_TID || tid == gettid()) {
|
||||||
return CreateCurrentObj();
|
return CreateCurrentObj(map_info);
|
||||||
} else {
|
} else {
|
||||||
return CreateThreadObj(tid);
|
return CreateThreadObj(tid, map_info);
|
||||||
}
|
}
|
||||||
} else if (tid == BACKTRACE_NO_TID) {
|
} else if (tid == BACKTRACE_NO_TID) {
|
||||||
return CreatePtraceObj(pid, pid);
|
return CreatePtraceObj(pid, pid, map_info);
|
||||||
} else {
|
} else {
|
||||||
return CreatePtraceObj(pid, tid);
|
return CreatePtraceObj(pid, tid, map_info);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//-------------------------------------------------------------------------
|
//-------------------------------------------------------------------------
|
||||||
// Common interface functions.
|
// Common interface functions.
|
||||||
//-------------------------------------------------------------------------
|
//-------------------------------------------------------------------------
|
||||||
bool backtrace_create_context(
|
bool backtrace_create_context_with_map(
|
||||||
backtrace_context_t* context, pid_t pid, pid_t tid, size_t num_ignore_frames) {
|
backtrace_context_t* context, pid_t pid, pid_t tid, size_t num_ignore_frames,
|
||||||
Backtrace* backtrace = Backtrace::Create(pid, tid);
|
backtrace_map_info_t* map_info) {
|
||||||
|
Backtrace* backtrace = Backtrace::Create(pid, tid, map_info);
|
||||||
if (!backtrace) {
|
if (!backtrace) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
@ -245,6 +251,12 @@ bool backtrace_create_context(
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool backtrace_create_context(
|
||||||
|
backtrace_context_t* context, pid_t pid, pid_t tid, size_t num_ignore_frames) {
|
||||||
|
return backtrace_create_context_with_map(context, pid, tid, num_ignore_frames, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void backtrace_destroy_context(backtrace_context_t* context) {
|
void backtrace_destroy_context(backtrace_context_t* context) {
|
||||||
if (context->data) {
|
if (context->data) {
|
||||||
Backtrace* backtrace = reinterpret_cast<Backtrace*>(context->data);
|
Backtrace* backtrace = reinterpret_cast<Backtrace*>(context->data);
|
||||||
|
|
|
||||||
|
|
@ -45,7 +45,7 @@ protected:
|
||||||
|
|
||||||
class BacktraceCurrent : public Backtrace {
|
class BacktraceCurrent : public Backtrace {
|
||||||
public:
|
public:
|
||||||
BacktraceCurrent(BacktraceImpl* impl);
|
BacktraceCurrent(BacktraceImpl* impl, backtrace_map_info_t* map_info);
|
||||||
virtual ~BacktraceCurrent();
|
virtual ~BacktraceCurrent();
|
||||||
|
|
||||||
bool ReadWord(uintptr_t ptr, uint32_t* out_value);
|
bool ReadWord(uintptr_t ptr, uint32_t* out_value);
|
||||||
|
|
@ -53,14 +53,14 @@ public:
|
||||||
|
|
||||||
class BacktracePtrace : public Backtrace {
|
class BacktracePtrace : public Backtrace {
|
||||||
public:
|
public:
|
||||||
BacktracePtrace(BacktraceImpl* impl, pid_t pid, pid_t tid);
|
BacktracePtrace(BacktraceImpl* impl, pid_t pid, pid_t tid, backtrace_map_info_t* map_info);
|
||||||
virtual ~BacktracePtrace();
|
virtual ~BacktracePtrace();
|
||||||
|
|
||||||
bool ReadWord(uintptr_t ptr, uint32_t* out_value);
|
bool ReadWord(uintptr_t ptr, uint32_t* out_value);
|
||||||
};
|
};
|
||||||
|
|
||||||
Backtrace* CreateCurrentObj();
|
Backtrace* CreateCurrentObj(backtrace_map_info_t* map_info);
|
||||||
Backtrace* CreatePtraceObj(pid_t pid, pid_t tid);
|
Backtrace* CreatePtraceObj(pid_t pid, pid_t tid, backtrace_map_info_t* map_info);
|
||||||
Backtrace* CreateThreadObj(pid_t tid);
|
Backtrace* CreateThreadObj(pid_t tid, backtrace_map_info_t* map_info);
|
||||||
|
|
||||||
#endif // _LIBBACKTRACE_BACKTRACE_H
|
#endif // _LIBBACKTRACE_BACKTRACE_H
|
||||||
|
|
|
||||||
|
|
@ -114,8 +114,9 @@ static void SignalHandler(int n __attribute__((unused)), siginfo_t* siginfo,
|
||||||
}
|
}
|
||||||
|
|
||||||
BacktraceThread::BacktraceThread(
|
BacktraceThread::BacktraceThread(
|
||||||
BacktraceImpl* impl, BacktraceThreadInterface* thread_intf, pid_t tid)
|
BacktraceImpl* impl, BacktraceThreadInterface* thread_intf, pid_t tid,
|
||||||
: BacktraceCurrent(impl), thread_intf_(thread_intf) {
|
backtrace_map_info_t* map_info)
|
||||||
|
: BacktraceCurrent(impl, map_info), thread_intf_(thread_intf) {
|
||||||
backtrace_.tid = tid;
|
backtrace_.tid = tid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -71,7 +71,8 @@ public:
|
||||||
// the compiler to catch if an implementation does not properly
|
// the compiler to catch if an implementation does not properly
|
||||||
// subclass both.
|
// subclass both.
|
||||||
BacktraceThread(
|
BacktraceThread(
|
||||||
BacktraceImpl* impl, BacktraceThreadInterface* thread_intf, pid_t tid);
|
BacktraceImpl* impl, BacktraceThreadInterface* thread_intf, pid_t tid,
|
||||||
|
backtrace_map_info_t* map_info);
|
||||||
virtual ~BacktraceThread();
|
virtual ~BacktraceThread();
|
||||||
|
|
||||||
virtual bool Unwind(size_t num_ignore_frames);
|
virtual bool Unwind(size_t num_ignore_frames);
|
||||||
|
|
|
||||||
|
|
@ -204,15 +204,15 @@ std::string CorkscrewPtrace::GetFunctionNameRaw(uintptr_t pc, uintptr_t* offset)
|
||||||
//-------------------------------------------------------------------------
|
//-------------------------------------------------------------------------
|
||||||
// C++ object creation functions.
|
// C++ object creation functions.
|
||||||
//-------------------------------------------------------------------------
|
//-------------------------------------------------------------------------
|
||||||
Backtrace* CreateCurrentObj() {
|
Backtrace* CreateCurrentObj(backtrace_map_info_t* map_info) {
|
||||||
return new BacktraceCurrent(new CorkscrewCurrent());
|
return new BacktraceCurrent(new CorkscrewCurrent(), map_info);
|
||||||
}
|
}
|
||||||
|
|
||||||
Backtrace* CreatePtraceObj(pid_t pid, pid_t tid) {
|
Backtrace* CreatePtraceObj(pid_t pid, pid_t tid, backtrace_map_info_t* map_info) {
|
||||||
return new BacktracePtrace(new CorkscrewPtrace(), pid, tid);
|
return new BacktracePtrace(new CorkscrewPtrace(), pid, tid, map_info);
|
||||||
}
|
}
|
||||||
|
|
||||||
Backtrace* CreateThreadObj(pid_t tid) {
|
Backtrace* CreateThreadObj(pid_t tid, backtrace_map_info_t* map_info) {
|
||||||
CorkscrewThread* thread_obj = new CorkscrewThread();
|
CorkscrewThread* thread_obj = new CorkscrewThread();
|
||||||
return new BacktraceThread(thread_obj, thread_obj, tid);
|
return new BacktraceThread(thread_obj, thread_obj, tid, map_info);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -194,11 +194,11 @@ void UnwindThread::ThreadUnwind(
|
||||||
//-------------------------------------------------------------------------
|
//-------------------------------------------------------------------------
|
||||||
// C++ object creation function.
|
// C++ object creation function.
|
||||||
//-------------------------------------------------------------------------
|
//-------------------------------------------------------------------------
|
||||||
Backtrace* CreateCurrentObj() {
|
Backtrace* CreateCurrentObj(backtrace_map_info_t* map_info) {
|
||||||
return new BacktraceCurrent(new UnwindCurrent());
|
return new BacktraceCurrent(new UnwindCurrent(), map_info);
|
||||||
}
|
}
|
||||||
|
|
||||||
Backtrace* CreateThreadObj(pid_t tid) {
|
Backtrace* CreateThreadObj(pid_t tid, backtrace_map_info_t* map_info) {
|
||||||
UnwindThread* thread_obj = new UnwindThread();
|
UnwindThread* thread_obj = new UnwindThread();
|
||||||
return new BacktraceThread(thread_obj, thread_obj, tid);
|
return new BacktraceThread(thread_obj, thread_obj, tid, map_info);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -131,6 +131,6 @@ std::string UnwindPtrace::GetFunctionNameRaw(uintptr_t pc, uintptr_t* offset) {
|
||||||
//-------------------------------------------------------------------------
|
//-------------------------------------------------------------------------
|
||||||
// C++ object creation function.
|
// C++ object creation function.
|
||||||
//-------------------------------------------------------------------------
|
//-------------------------------------------------------------------------
|
||||||
Backtrace* CreatePtraceObj(pid_t pid, pid_t tid) {
|
Backtrace* CreatePtraceObj(pid_t pid, pid_t tid, backtrace_map_info_t* map_info) {
|
||||||
return new BacktracePtrace(new UnwindPtrace(), pid, tid);
|
return new BacktracePtrace(new UnwindPtrace(), pid, tid, map_info);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue