am 8c58086c
: Merge "More libbacktrace fixes."
* commit '8c58086c54a23d33e915852a1355a171b09679cc': More libbacktrace fixes.
This commit is contained in:
commit
b5c24e096d
8 changed files with 117 additions and 121 deletions
|
@ -25,7 +25,16 @@ class BacktraceImpl;
|
|||
|
||||
class Backtrace {
|
||||
public:
|
||||
Backtrace(BacktraceImpl* impl);
|
||||
// Create the correct Backtrace object based on what is to be unwound.
|
||||
// If pid < 0 or equals the current pid, then the Backtrace object
|
||||
// corresponds to the current process.
|
||||
// If pid < 0 or equals the current pid and tid >= 0, then the Backtrace
|
||||
// object corresponds to a thread in the current process.
|
||||
// If pid >= 0 and tid < 0, then the Backtrace object corresponds to a
|
||||
// different process.
|
||||
// Tracing a thread in a different process is not supported.
|
||||
static Backtrace* Create(pid_t pid, pid_t tid);
|
||||
|
||||
virtual ~Backtrace();
|
||||
|
||||
// Get the current stack trace and store in the backtrace_ structure.
|
||||
|
@ -60,17 +69,9 @@ public:
|
|||
return &backtrace_.frames[frame_num];
|
||||
}
|
||||
|
||||
// Create the correct Backtrace object based on what is to be unwound.
|
||||
// If pid < 0 or equals the current pid, then the Backtrace object
|
||||
// corresponds to the current process.
|
||||
// If pid < 0 or equals the current pid and tid >= 0, then the Backtrace
|
||||
// object corresponds to a thread in the current process.
|
||||
// If pid >= 0 and tid < 0, then the Backtrace object corresponds to a
|
||||
// different process.
|
||||
// Tracing a thread in a different process is not supported.
|
||||
static Backtrace* Create(pid_t pid, pid_t tid);
|
||||
|
||||
protected:
|
||||
Backtrace(BacktraceImpl* impl);
|
||||
|
||||
virtual bool VerifyReadWordArgs(uintptr_t ptr, uint32_t* out_value);
|
||||
|
||||
BacktraceImpl* impl_;
|
||||
|
|
|
@ -72,10 +72,8 @@ bool Backtrace::Unwind(size_t num_ignore_frames) {
|
|||
return impl_->Unwind(num_ignore_frames);
|
||||
}
|
||||
|
||||
__BEGIN_DECLS
|
||||
extern char* __cxa_demangle (const char* mangled, char* buf, size_t* len,
|
||||
int* status);
|
||||
__END_DECLS
|
||||
extern "C" char* __cxa_demangle(const char* mangled, char* buf, size_t* len,
|
||||
int* status);
|
||||
|
||||
std::string Backtrace::GetFunctionName(uintptr_t pc, uintptr_t* offset) {
|
||||
std::string func_name = impl_->GetFunctionNameRaw(pc, offset);
|
||||
|
@ -97,7 +95,7 @@ std::string Backtrace::GetFunctionName(uintptr_t pc, uintptr_t* offset) {
|
|||
|
||||
bool Backtrace::VerifyReadWordArgs(uintptr_t ptr, uint32_t* out_value) {
|
||||
if (ptr & 3) {
|
||||
ALOGW("Backtrace::verifyReadWordArgs: invalid pointer %p", (void*)ptr);
|
||||
BACK_LOGW("invalid pointer %p", (void*)ptr);
|
||||
*out_value = (uint32_t)-1;
|
||||
return false;
|
||||
}
|
||||
|
@ -172,7 +170,7 @@ bool BacktraceCurrent::ReadWord(uintptr_t ptr, uint32_t* out_value) {
|
|||
*out_value = *reinterpret_cast<uint32_t*>(ptr);
|
||||
return true;
|
||||
} else {
|
||||
ALOGW("BacktraceCurrent::readWord: pointer %p not in a readbale map", reinterpret_cast<void*>(ptr));
|
||||
BACK_LOGW("pointer %p not in a readable map", reinterpret_cast<void*>(ptr));
|
||||
*out_value = static_cast<uint32_t>(-1);
|
||||
return false;
|
||||
}
|
||||
|
@ -198,7 +196,7 @@ bool BacktracePtrace::ReadWord(uintptr_t ptr, uint32_t* out_value) {
|
|||
}
|
||||
|
||||
#if defined(__APPLE__)
|
||||
ALOGW("BacktracePtrace::readWord: MacOS does not support reading from another pid.\n");
|
||||
BACK_LOGW("MacOS does not support reading from another pid.");
|
||||
return false;
|
||||
#else
|
||||
// ptrace() returns -1 and sets errno when the operation fails.
|
||||
|
@ -206,8 +204,8 @@ bool BacktracePtrace::ReadWord(uintptr_t ptr, uint32_t* out_value) {
|
|||
errno = 0;
|
||||
*out_value = ptrace(PTRACE_PEEKTEXT, Tid(), reinterpret_cast<void*>(ptr), NULL);
|
||||
if (*out_value == static_cast<uint32_t>(-1) && errno) {
|
||||
ALOGW("BacktracePtrace::readWord: invalid pointer 0x%08x reading from tid %d, "
|
||||
"ptrace() errno=%d", ptr, Tid(), errno);
|
||||
BACK_LOGW("invalid pointer %p reading from tid %d, ptrace() strerror(errno)=%s",
|
||||
reinterpret_cast<void*>(ptr), Tid(), strerror(errno));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
@ -295,11 +293,8 @@ void backtrace_format_frame_data(
|
|||
const backtrace_context_t* context, size_t frame_num, char* buf,
|
||||
size_t buf_size) {
|
||||
if (buf_size == 0 || buf == NULL) {
|
||||
ALOGW("backtrace_format_frame_data: bad call buf %p buf_size %zu\n",
|
||||
buf, buf_size);
|
||||
return;
|
||||
}
|
||||
if (context->data) {
|
||||
BACK_LOGW("bad call buf %p buf_size %zu", buf, buf_size);
|
||||
} else if (context->data) {
|
||||
Backtrace* backtrace = reinterpret_cast<Backtrace*>(context->data);
|
||||
std::string line = backtrace->FormatFrameData(frame_num);
|
||||
if (line.size() > buf_size) {
|
||||
|
|
|
@ -21,6 +21,10 @@
|
|||
|
||||
#include <sys/types.h>
|
||||
|
||||
// Macro to log the function name along with the warning message.
|
||||
#define BACK_LOGW(format, ...) \
|
||||
ALOGW("%s: " format, __PRETTY_FUNCTION__, ##__VA_ARGS__)
|
||||
|
||||
class BacktraceImpl {
|
||||
public:
|
||||
virtual ~BacktraceImpl() { }
|
||||
|
|
|
@ -31,55 +31,55 @@
|
|||
// ThreadEntry implementation.
|
||||
//-------------------------------------------------------------------------
|
||||
static ThreadEntry* g_list = NULL;
|
||||
static pthread_mutex_t g_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
static pthread_mutex_t g_entry_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
static pthread_mutex_t g_sigaction_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
ThreadEntry::ThreadEntry(
|
||||
BacktraceThreadInterface* intf, pid_t pid, pid_t tid, size_t num_ignore_frames)
|
||||
: thread_intf_(intf), pid_(pid), tid_(tid), next_(NULL), prev_(NULL),
|
||||
state_(STATE_WAITING), num_ignore_frames_(num_ignore_frames) {
|
||||
: thread_intf(intf), pid(pid), tid(tid), next(NULL), prev(NULL),
|
||||
state(STATE_WAITING), num_ignore_frames(num_ignore_frames) {
|
||||
}
|
||||
|
||||
ThreadEntry::~ThreadEntry() {
|
||||
pthread_mutex_lock(&g_mutex);
|
||||
pthread_mutex_lock(&g_entry_mutex);
|
||||
if (g_list == this) {
|
||||
g_list = next_;
|
||||
g_list = next;
|
||||
} else {
|
||||
if (next_) {
|
||||
next_->prev_ = prev_;
|
||||
if (next) {
|
||||
next->prev = prev;
|
||||
}
|
||||
prev_->next_ = next_;
|
||||
prev->next = next;
|
||||
}
|
||||
pthread_mutex_unlock(&g_mutex);
|
||||
pthread_mutex_unlock(&g_entry_mutex);
|
||||
|
||||
next_ = NULL;
|
||||
prev_ = NULL;
|
||||
next = NULL;
|
||||
prev = NULL;
|
||||
}
|
||||
|
||||
ThreadEntry* ThreadEntry::AddThreadToUnwind(
|
||||
BacktraceThreadInterface* intf, pid_t pid, pid_t tid, size_t num_ignore_frames) {
|
||||
ThreadEntry* entry = new ThreadEntry(intf, pid, tid, num_ignore_frames);
|
||||
|
||||
pthread_mutex_lock(&g_mutex);
|
||||
pthread_mutex_lock(&g_entry_mutex);
|
||||
ThreadEntry* cur_entry = g_list;
|
||||
while (cur_entry != NULL) {
|
||||
if (cur_entry->Match(pid, tid)) {
|
||||
// There is already an entry for this pid/tid, this is bad.
|
||||
ALOGW("%s::%s(): Entry for pid %d tid %d already exists.\n",
|
||||
__FILE__, __FUNCTION__, pid, tid);
|
||||
BACK_LOGW("Entry for pid %d tid %d already exists.", pid, tid);
|
||||
|
||||
pthread_mutex_unlock(&g_mutex);
|
||||
pthread_mutex_unlock(&g_entry_mutex);
|
||||
return NULL;
|
||||
}
|
||||
cur_entry = cur_entry->next_;
|
||||
cur_entry = cur_entry->next;
|
||||
}
|
||||
|
||||
// Add the entry to the list.
|
||||
entry->next_ = g_list;
|
||||
entry->next = g_list;
|
||||
if (g_list) {
|
||||
g_list->prev_ = entry;
|
||||
g_list->prev = entry;
|
||||
}
|
||||
g_list = entry;
|
||||
pthread_mutex_unlock(&g_mutex);
|
||||
pthread_mutex_unlock(&g_entry_mutex);
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
@ -89,7 +89,7 @@ ThreadEntry* ThreadEntry::AddThreadToUnwind(
|
|||
//-------------------------------------------------------------------------
|
||||
static void SignalHandler(int n __attribute__((unused)), siginfo_t* siginfo,
|
||||
void* sigcontext) {
|
||||
if (pthread_mutex_lock(&g_mutex) == 0) {
|
||||
if (pthread_mutex_lock(&g_entry_mutex) == 0) {
|
||||
pid_t pid = getpid();
|
||||
pid_t tid = gettid();
|
||||
ThreadEntry* cur_entry = g_list;
|
||||
|
@ -97,20 +97,19 @@ static void SignalHandler(int n __attribute__((unused)), siginfo_t* siginfo,
|
|||
if (cur_entry->Match(pid, tid)) {
|
||||
break;
|
||||
}
|
||||
cur_entry = cur_entry->next_;
|
||||
cur_entry = cur_entry->next;
|
||||
}
|
||||
pthread_mutex_unlock(&g_mutex);
|
||||
pthread_mutex_unlock(&g_entry_mutex);
|
||||
if (!cur_entry) {
|
||||
ALOGW("%s::%s(): Unable to find pid %d tid %d information\n",
|
||||
__FILE__, __FUNCTION__, pid, tid);
|
||||
BACK_LOGW("Unable to find pid %d tid %d information", pid, tid);
|
||||
return;
|
||||
}
|
||||
|
||||
if (android_atomic_acquire_cas(STATE_WAITING, STATE_DUMPING, &cur_entry->state_) == 0) {
|
||||
cur_entry->thread_intf_->ThreadUnwind(siginfo, sigcontext,
|
||||
cur_entry->num_ignore_frames_);
|
||||
if (android_atomic_acquire_cas(STATE_WAITING, STATE_DUMPING, &cur_entry->state) == 0) {
|
||||
cur_entry->thread_intf->ThreadUnwind(siginfo, sigcontext,
|
||||
cur_entry->num_ignore_frames);
|
||||
}
|
||||
android_atomic_release_store(STATE_DONE, &cur_entry->state_);
|
||||
android_atomic_release_store(STATE_DONE, &cur_entry->state);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -143,18 +142,18 @@ void BacktraceThread::FinishUnwind() {
|
|||
}
|
||||
|
||||
bool BacktraceThread::TriggerUnwindOnThread(ThreadEntry* entry) {
|
||||
entry->state_ = STATE_WAITING;
|
||||
entry->state = STATE_WAITING;
|
||||
|
||||
if (tgkill(Pid(), Tid(), SIGURG) != 0) {
|
||||
ALOGW("%s::%s(): tgkill failed %s\n", __FILE__, __FUNCTION__, strerror(errno));
|
||||
BACK_LOGW("tgkill failed %s", strerror(errno));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Allow up to a second for the dump to occur.
|
||||
int wait_millis = 1000;
|
||||
// Allow up to ten seconds for the dump to start.
|
||||
int wait_millis = 10000;
|
||||
int32_t state;
|
||||
while (true) {
|
||||
state = android_atomic_acquire_load(&entry->state_);
|
||||
state = android_atomic_acquire_load(&entry->state);
|
||||
if (state != STATE_WAITING) {
|
||||
break;
|
||||
}
|
||||
|
@ -167,24 +166,22 @@ bool BacktraceThread::TriggerUnwindOnThread(ThreadEntry* entry) {
|
|||
|
||||
bool cancelled = false;
|
||||
if (state == STATE_WAITING) {
|
||||
if (android_atomic_acquire_cas(state, STATE_CANCEL, &entry->state_) == 0) {
|
||||
ALOGW("%s::%s(): Cancelled dump of thread %d\n", __FILE__, __FUNCTION__,
|
||||
entry->tid_);
|
||||
if (android_atomic_acquire_cas(state, STATE_CANCEL, &entry->state) == 0) {
|
||||
BACK_LOGW("Cancelled dump of thread %d", entry->tid);
|
||||
state = STATE_CANCEL;
|
||||
cancelled = true;
|
||||
} else {
|
||||
state = android_atomic_acquire_load(&entry->state_);
|
||||
state = android_atomic_acquire_load(&entry->state);
|
||||
}
|
||||
}
|
||||
|
||||
// Wait for at most one minute for the dump to finish.
|
||||
wait_millis = 60000;
|
||||
while (android_atomic_acquire_load(&entry->state_) != STATE_DONE) {
|
||||
// Wait for at most ten seconds for the cancel or dump to finish.
|
||||
wait_millis = 10000;
|
||||
while (android_atomic_acquire_load(&entry->state) != STATE_DONE) {
|
||||
if (wait_millis--) {
|
||||
usleep(1000);
|
||||
} else {
|
||||
ALOGW("%s::%s(): Didn't finish thread unwind in 60 seconds.\n",
|
||||
__FILE__, __FUNCTION__);
|
||||
BACK_LOGW("Didn't finish thread unwind in 60 seconds.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -202,17 +199,24 @@ bool BacktraceThread::Unwind(size_t num_ignore_frames) {
|
|||
return false;
|
||||
}
|
||||
|
||||
// Prevent multiple threads trying to set the trigger action on different
|
||||
// threads at the same time.
|
||||
bool retval = false;
|
||||
struct sigaction act, oldact;
|
||||
memset(&act, 0, sizeof(act));
|
||||
act.sa_sigaction = SignalHandler;
|
||||
act.sa_flags = SA_RESTART | SA_SIGINFO | SA_ONSTACK;
|
||||
sigemptyset(&act.sa_mask);
|
||||
if (sigaction(SIGURG, &act, &oldact) == 0) {
|
||||
retval = TriggerUnwindOnThread(entry);
|
||||
sigaction(SIGURG, &oldact, NULL);
|
||||
if (pthread_mutex_lock(&g_sigaction_mutex) == 0) {
|
||||
struct sigaction act, oldact;
|
||||
memset(&act, 0, sizeof(act));
|
||||
act.sa_sigaction = SignalHandler;
|
||||
act.sa_flags = SA_RESTART | SA_SIGINFO | SA_ONSTACK;
|
||||
sigemptyset(&act.sa_mask);
|
||||
if (sigaction(SIGURG, &act, &oldact) == 0) {
|
||||
retval = TriggerUnwindOnThread(entry);
|
||||
sigaction(SIGURG, &oldact, NULL);
|
||||
} else {
|
||||
BACK_LOGW("sigaction failed %s", strerror(errno));
|
||||
}
|
||||
pthread_mutex_unlock(&g_sigaction_mutex);
|
||||
} else {
|
||||
ALOGW("%s::%s(): sigaction failed %s\n", __FILE__, __FUNCTION__, strerror(errno));
|
||||
BACK_LOGW("unable to acquire sigaction mutex.");
|
||||
}
|
||||
|
||||
if (retval) {
|
||||
|
|
|
@ -32,26 +32,25 @@ typedef enum {
|
|||
|
||||
class BacktraceThreadInterface;
|
||||
|
||||
class ThreadEntry {
|
||||
public:
|
||||
struct ThreadEntry {
|
||||
ThreadEntry(
|
||||
BacktraceThreadInterface* impl, pid_t pid, pid_t tid,
|
||||
size_t num_ignore_frames);
|
||||
~ThreadEntry();
|
||||
|
||||
bool Match(pid_t pid, pid_t tid) { return (pid == pid_ && tid == tid_); }
|
||||
bool Match(pid_t chk_pid, pid_t chk_tid) { return (chk_pid == pid && chk_tid == tid); }
|
||||
|
||||
static ThreadEntry* AddThreadToUnwind(
|
||||
BacktraceThreadInterface* thread_intf, pid_t pid, pid_t tid,
|
||||
size_t num_ignored_frames);
|
||||
|
||||
BacktraceThreadInterface* thread_intf_;
|
||||
pid_t pid_;
|
||||
pid_t tid_;
|
||||
ThreadEntry* next_;
|
||||
ThreadEntry* prev_;
|
||||
int32_t state_;
|
||||
int num_ignore_frames_;
|
||||
BacktraceThreadInterface* thread_intf;
|
||||
pid_t pid;
|
||||
pid_t tid;
|
||||
ThreadEntry* next;
|
||||
ThreadEntry* prev;
|
||||
int32_t state;
|
||||
int num_ignore_frames;
|
||||
};
|
||||
|
||||
// Interface class that does not contain any local storage, only defines
|
||||
|
|
|
@ -37,7 +37,7 @@
|
|||
bool CorkscrewCommon::GenerateFrameData(
|
||||
backtrace_frame_t* cork_frames, ssize_t num_frames) {
|
||||
if (num_frames < 0) {
|
||||
ALOGW("CorkscrewCommon::GenerateFrameData: libcorkscrew unwind failed.\n");
|
||||
BACK_LOGW("libcorkscrew unwind failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -184,7 +184,7 @@ std::string CorkscrewPtrace::GetFunctionNameRaw(uintptr_t pc, uintptr_t* offset)
|
|||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// C++ object createion functions.
|
||||
// C++ object creation functions.
|
||||
//-------------------------------------------------------------------------
|
||||
Backtrace* CreateCurrentObj() {
|
||||
return new BacktraceCurrent(new CorkscrewCurrent());
|
||||
|
|
|
@ -27,9 +27,9 @@
|
|||
|
||||
#include "UnwindCurrent.h"
|
||||
|
||||
// Define the ucontext_t structures needed for each supported arch.
|
||||
#if defined(__arm__)
|
||||
#if !defined(__BIONIC_HAVE_UCONTEXT_T)
|
||||
// The Current version of the Android <signal.h> doesn't define ucontext_t.
|
||||
// The current version of the <signal.h> doesn't define ucontext_t.
|
||||
#include <asm/sigcontext.h> // Ensure 'struct sigcontext' is defined.
|
||||
|
||||
// Machine context at the time a signal was raised.
|
||||
|
@ -40,8 +40,19 @@
|
|||
struct sigcontext uc_mcontext;
|
||||
uint32_t uc_sigmask;
|
||||
} ucontext_t;
|
||||
#endif // !__BIONIC_HAVE_UCONTEXT_T
|
||||
#endif // defined(__arm__)
|
||||
#elif defined(__mips__)
|
||||
typedef struct ucontext {
|
||||
uint32_t sp;
|
||||
uint32_t ra;
|
||||
uint32_t pc;
|
||||
} ucontext_t;
|
||||
#elif defined(__i386__)
|
||||
#include <asm/sigcontext.h>
|
||||
#include <asm/ucontext.h>
|
||||
typedef struct ucontext ucontext_t;
|
||||
#else
|
||||
#error Unsupported architecture.
|
||||
#endif
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// UnwindCurrent functions.
|
||||
|
@ -55,7 +66,7 @@ UnwindCurrent::~UnwindCurrent() {
|
|||
bool UnwindCurrent::Unwind(size_t num_ignore_frames) {
|
||||
int ret = unw_getcontext(&context_);
|
||||
if (ret < 0) {
|
||||
ALOGW("UnwindCurrent::Unwind: unw_getcontext failed %d\n", ret);
|
||||
BACK_LOGW("unw_getcontext failed %d", ret);
|
||||
return false;
|
||||
}
|
||||
return UnwindFromContext(num_ignore_frames, true);
|
||||
|
@ -81,7 +92,7 @@ bool UnwindCurrent::UnwindFromContext(size_t num_ignore_frames, bool resolve) {
|
|||
unw_cursor_t* cursor = new unw_cursor_t;
|
||||
int ret = unw_init_local(cursor, &context_);
|
||||
if (ret < 0) {
|
||||
ALOGW("UnwindCurrent::UnwindWithContext: unw_init_local failed %d\n", ret);
|
||||
BACK_LOGW("unw_init_local failed %d", ret);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -89,13 +100,13 @@ bool UnwindCurrent::UnwindFromContext(size_t num_ignore_frames, bool resolve) {
|
|||
unw_word_t pc;
|
||||
ret = unw_get_reg(cursor, UNW_REG_IP, &pc);
|
||||
if (ret < 0) {
|
||||
ALOGW("UnwindCurrent::UnwindWithContext: Failed to read IP %d\n", ret);
|
||||
BACK_LOGW("Failed to read IP %d", ret);
|
||||
break;
|
||||
}
|
||||
unw_word_t sp;
|
||||
ret = unw_get_reg(cursor, UNW_REG_SP, &sp);
|
||||
if (ret < 0) {
|
||||
ALOGW("UnwindCurrent::UnwindWithContext: Failed to read SP %d\n", ret);
|
||||
BACK_LOGW("Failed to read SP %d", ret);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -142,10 +153,9 @@ bool UnwindCurrent::UnwindFromContext(size_t num_ignore_frames, bool resolve) {
|
|||
|
||||
void UnwindCurrent::ExtractContext(void* sigcontext) {
|
||||
unw_tdep_context_t* context = reinterpret_cast<unw_tdep_context_t*>(&context_);
|
||||
|
||||
#if defined(__arm__)
|
||||
const ucontext_t* uc = reinterpret_cast<const ucontext_t*>(sigcontext);
|
||||
|
||||
#if defined(__arm__)
|
||||
context->regs[0] = uc->uc_mcontext.arm_r0;
|
||||
context->regs[1] = uc->uc_mcontext.arm_r1;
|
||||
context->regs[2] = uc->uc_mcontext.arm_r2;
|
||||
|
@ -162,28 +172,11 @@ void UnwindCurrent::ExtractContext(void* sigcontext) {
|
|||
context->regs[13] = uc->uc_mcontext.arm_sp;
|
||||
context->regs[14] = uc->uc_mcontext.arm_lr;
|
||||
context->regs[15] = uc->uc_mcontext.arm_pc;
|
||||
|
||||
#elif defined(__mips__)
|
||||
|
||||
typedef struct ucontext {
|
||||
uint32_t sp;
|
||||
uint32_t ra;
|
||||
uint32_t pc;
|
||||
} ucontext_t;
|
||||
|
||||
const ucontext_t* uc = (const ucontext_t*)sigcontext;
|
||||
|
||||
context->uc_mcontext.sp = uc->sp;
|
||||
context->uc_mcontext.pc = uc->pc;
|
||||
context->uc_mcontext.ra = uc->ra;
|
||||
#elif defined(__x86__)
|
||||
|
||||
#include <asm/sigcontext.h>
|
||||
#include <asm/ucontext.h>
|
||||
typedef struct ucontext ucontext_t;
|
||||
|
||||
const ucontext_t* uc = (const ucontext_t*)sigcontext;
|
||||
|
||||
#elif defined(__i386__)
|
||||
context->uc_mcontext.gregs[REG_EBP] = uc->uc_mcontext.gregs[REG_EBP];
|
||||
context->uc_mcontext.gregs[REG_ESP] = uc->uc_mcontext.gregs[REG_ESP];
|
||||
context->uc_mcontext.gregs[REG_EIP] = uc->uc_mcontext.gregs[REG_EIP];
|
||||
|
|
|
@ -45,13 +45,13 @@ UnwindPtrace::~UnwindPtrace() {
|
|||
bool UnwindPtrace::Unwind(size_t num_ignore_frames) {
|
||||
addr_space_ = unw_create_addr_space(&_UPT_accessors, 0);
|
||||
if (!addr_space_) {
|
||||
ALOGW("UnwindPtrace::Unwind: unw_create_addr_space failed.\n");
|
||||
BACK_LOGW("unw_create_addr_space failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
upt_info_ = reinterpret_cast<struct UPT_info*>(_UPT_create(backtrace_obj_->Tid()));
|
||||
if (!upt_info_) {
|
||||
ALOGW("UnwindPtrace::Unwind: Failed to create upt info.\n");
|
||||
BACK_LOGW("Failed to create upt info.");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -61,7 +61,7 @@ bool UnwindPtrace::Unwind(size_t num_ignore_frames) {
|
|||
unw_cursor_t cursor;
|
||||
int ret = unw_init_remote(&cursor, addr_space_, upt_info_);
|
||||
if (ret < 0) {
|
||||
ALOGW("UnwindPtrace::Unwind: unw_init_remote failed %d\n", ret);
|
||||
BACK_LOGW("unw_init_remote failed %d", ret);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -69,13 +69,13 @@ bool UnwindPtrace::Unwind(size_t num_ignore_frames) {
|
|||
unw_word_t pc;
|
||||
ret = unw_get_reg(&cursor, UNW_REG_IP, &pc);
|
||||
if (ret < 0) {
|
||||
ALOGW("UnwindPtrace::Unwind: Failed to read IP %d\n", ret);
|
||||
BACK_LOGW("Failed to read IP %d", ret);
|
||||
break;
|
||||
}
|
||||
unw_word_t sp;
|
||||
ret = unw_get_reg(&cursor, UNW_REG_SP, &sp);
|
||||
if (ret < 0) {
|
||||
ALOGW("UnwindPtrace::Unwind: Failed to read SP %d\n", ret);
|
||||
BACK_LOGW("Failed to read SP %d", ret);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue