Loading debuggerd/tombstone.c +9 −4 Original line number Original line Diff line number Diff line Loading @@ -416,7 +416,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); Loading Loading @@ -450,7 +450,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); } } Loading Loading @@ -644,7 +644,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); Loading @@ -656,9 +658,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, 0); dump_logs(log, pid, 0); } } Loading include/backtrace/Backtrace.h +6 −2 Original line number Original line Diff line number Diff line Loading @@ -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(); Loading Loading @@ -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); Loading @@ -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; Loading include/backtrace/backtrace.h +8 −0 Original line number Original line Diff line number Diff line Loading @@ -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); Loading libbacktrace/Backtrace.cpp +30 −18 Original line number Original line Diff line number Diff line Loading @@ -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() { Loading @@ -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; } } Loading Loading @@ -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(); } } Loading @@ -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; } } Loading Loading @@ -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_CURRENT_THREAD || tid == gettid()) { if (tid == BACKTRACE_CURRENT_THREAD || tid == gettid()) { return CreateCurrentObj(); return CreateCurrentObj(map_info); } else { } else { return CreateThreadObj(tid); return CreateThreadObj(tid, map_info); } } } else if (tid == BACKTRACE_CURRENT_THREAD) { } else if (tid == BACKTRACE_CURRENT_THREAD) { 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; } } Loading @@ -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); Loading libbacktrace/Backtrace.h +5 −5 Original line number Original line Diff line number Diff line Loading @@ -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); Loading @@ -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 Loading
debuggerd/tombstone.c +9 −4 Original line number Original line Diff line number Diff line Loading @@ -416,7 +416,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); Loading Loading @@ -450,7 +450,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); } } Loading Loading @@ -644,7 +644,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); Loading @@ -656,9 +658,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, 0); dump_logs(log, pid, 0); } } Loading
include/backtrace/Backtrace.h +6 −2 Original line number Original line Diff line number Diff line Loading @@ -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(); Loading Loading @@ -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); Loading @@ -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; Loading
include/backtrace/backtrace.h +8 −0 Original line number Original line Diff line number Diff line Loading @@ -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); Loading
libbacktrace/Backtrace.cpp +30 −18 Original line number Original line Diff line number Diff line Loading @@ -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() { Loading @@ -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; } } Loading Loading @@ -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(); } } Loading @@ -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; } } Loading Loading @@ -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_CURRENT_THREAD || tid == gettid()) { if (tid == BACKTRACE_CURRENT_THREAD || tid == gettid()) { return CreateCurrentObj(); return CreateCurrentObj(map_info); } else { } else { return CreateThreadObj(tid); return CreateThreadObj(tid, map_info); } } } else if (tid == BACKTRACE_CURRENT_THREAD) { } else if (tid == BACKTRACE_CURRENT_THREAD) { 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; } } Loading @@ -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); Loading
libbacktrace/Backtrace.h +5 −5 Original line number Original line Diff line number Diff line Loading @@ -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); Loading @@ -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