am 5434bf66: Merge "LP64: Enable debuggerd/libbacktrace/libunwind."
* commit '5434bf6640af7145986d63968846ba7168dab406': LP64: Enable debuggerd/libbacktrace/libunwind.
This commit is contained in:
commit
fe0d5d42e4
11 changed files with 129 additions and 83 deletions
|
|
@ -1,6 +1,6 @@
|
||||||
# Copyright 2005 The Android Open Source Project
|
# Copyright 2005 The Android Open Source Project
|
||||||
|
|
||||||
ifneq ($(filter arm mips x86,$(TARGET_ARCH)),)
|
ifneq ($(filter arm mips x86 x86_64,$(TARGET_ARCH)),)
|
||||||
|
|
||||||
LOCAL_PATH:= $(call my-dir)
|
LOCAL_PATH:= $(call my-dir)
|
||||||
include $(CLEAR_VARS)
|
include $(CLEAR_VARS)
|
||||||
|
|
@ -19,6 +19,7 @@ LOCAL_CFLAGS := \
|
||||||
-Wall \
|
-Wall \
|
||||||
-Wno-array-bounds \
|
-Wno-array-bounds \
|
||||||
-Werror \
|
-Werror \
|
||||||
|
-Wno-unused-parameter \
|
||||||
|
|
||||||
LOCAL_MODULE := debuggerd
|
LOCAL_MODULE := debuggerd
|
||||||
|
|
||||||
|
|
|
||||||
45
debuggerd/tombstone.cpp
Normal file → Executable file
45
debuggerd/tombstone.cpp
Normal file → Executable file
|
|
@ -179,9 +179,9 @@ static void dump_fault_addr(log_t* log, pid_t tid, int sig) {
|
||||||
if (ptrace(PTRACE_GETSIGINFO, tid, 0, &si)){
|
if (ptrace(PTRACE_GETSIGINFO, tid, 0, &si)){
|
||||||
_LOG(log, SCOPE_AT_FAULT, "cannot get siginfo: %s\n", strerror(errno));
|
_LOG(log, SCOPE_AT_FAULT, "cannot get siginfo: %s\n", strerror(errno));
|
||||||
} else if (signal_has_address(sig)) {
|
} else if (signal_has_address(sig)) {
|
||||||
_LOG(log, SCOPE_AT_FAULT, "signal %d (%s), code %d (%s), fault addr %0*" PRIxPTR "\n",
|
_LOG(log, SCOPE_AT_FAULT, "signal %d (%s), code %d (%s), fault addr %" PRIPTR "\n",
|
||||||
sig, get_signame(sig), si.si_code, get_sigcode(sig, si.si_code),
|
sig, get_signame(sig), si.si_code, get_sigcode(sig, si.si_code),
|
||||||
sizeof(uintptr_t)*2, reinterpret_cast<uintptr_t>(si.si_addr));
|
reinterpret_cast<uintptr_t>(si.si_addr));
|
||||||
} else {
|
} else {
|
||||||
_LOG(log, SCOPE_AT_FAULT, "signal %d (%s), code %d (%s), fault addr --------\n",
|
_LOG(log, SCOPE_AT_FAULT, "signal %d (%s), code %d (%s), fault addr --------\n",
|
||||||
sig, get_signame(sig), si.si_code, get_sigcode(sig, si.si_code));
|
sig, get_signame(sig), si.si_code, get_sigcode(sig, si.si_code));
|
||||||
|
|
@ -226,7 +226,7 @@ static void dump_thread_info(log_t* log, pid_t pid, pid_t tid, int scope_flags)
|
||||||
static void dump_stack_segment(
|
static void dump_stack_segment(
|
||||||
Backtrace* backtrace, log_t* log, int scope_flags, uintptr_t* sp, size_t words, int label) {
|
Backtrace* backtrace, log_t* log, int scope_flags, uintptr_t* sp, size_t words, int label) {
|
||||||
for (size_t i = 0; i < words; i++) {
|
for (size_t i = 0; i < words; i++) {
|
||||||
uint32_t stack_content;
|
word_t stack_content;
|
||||||
if (!backtrace->ReadWord(*sp, &stack_content)) {
|
if (!backtrace->ReadWord(*sp, &stack_content)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -243,32 +243,32 @@ static void dump_stack_segment(
|
||||||
if (!func_name.empty()) {
|
if (!func_name.empty()) {
|
||||||
if (!i && label >= 0) {
|
if (!i && label >= 0) {
|
||||||
if (offset) {
|
if (offset) {
|
||||||
_LOG(log, scope_flags, " #%02d %08x %08x %s (%s+%u)\n",
|
_LOG(log, scope_flags, " #%02d %" PRIPTR " %" PRIPTR " %s (%s+%" PRIxPTR "u)\n",
|
||||||
label, *sp, stack_content, map_name, func_name.c_str(), offset);
|
label, *sp, stack_content, map_name, func_name.c_str(), offset);
|
||||||
} else {
|
} else {
|
||||||
_LOG(log, scope_flags, " #%02d %08x %08x %s (%s)\n",
|
_LOG(log, scope_flags, " #%02d %" PRIPTR " %" PRIPTR " %s (%s)\n",
|
||||||
label, *sp, stack_content, map_name, func_name.c_str());
|
label, *sp, stack_content, map_name, func_name.c_str());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (offset) {
|
if (offset) {
|
||||||
_LOG(log, scope_flags, " %08x %08x %s (%s+%u)\n",
|
_LOG(log, scope_flags, " %" PRIPTR " %" PRIPTR " %s (%s+%" PRIxPTR "u)\n",
|
||||||
*sp, stack_content, map_name, func_name.c_str(), offset);
|
*sp, stack_content, map_name, func_name.c_str(), offset);
|
||||||
} else {
|
} else {
|
||||||
_LOG(log, scope_flags, " %08x %08x %s (%s)\n",
|
_LOG(log, scope_flags, " %" PRIPTR " %" PRIPTR " %s (%s)\n",
|
||||||
*sp, stack_content, map_name, func_name.c_str());
|
*sp, stack_content, map_name, func_name.c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (!i && label >= 0) {
|
if (!i && label >= 0) {
|
||||||
_LOG(log, scope_flags, " #%02d %08x %08x %s\n",
|
_LOG(log, scope_flags, " #%02d %" PRIPTR " %" PRIPTR " %s\n",
|
||||||
label, *sp, stack_content, map_name);
|
label, *sp, stack_content, map_name);
|
||||||
} else {
|
} else {
|
||||||
_LOG(log, scope_flags, " %08x %08x %s\n",
|
_LOG(log, scope_flags, " %" PRIPTR " %" PRIPTR " %s\n",
|
||||||
*sp, stack_content, map_name);
|
*sp, stack_content, map_name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
*sp += sizeof(uint32_t);
|
*sp += sizeof(word_t);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -291,7 +291,7 @@ static void dump_stack(Backtrace* backtrace, log_t* log, int scope_flags) {
|
||||||
scope_flags |= SCOPE_SENSITIVE;
|
scope_flags |= SCOPE_SENSITIVE;
|
||||||
|
|
||||||
// Dump a few words before the first frame.
|
// Dump a few words before the first frame.
|
||||||
uintptr_t sp = backtrace->GetFrame(first)->sp - STACK_WORDS * sizeof(uint32_t);
|
word_t sp = backtrace->GetFrame(first)->sp - STACK_WORDS * sizeof(word_t);
|
||||||
dump_stack_segment(backtrace, log, scope_flags, &sp, STACK_WORDS, -1);
|
dump_stack_segment(backtrace, log, scope_flags, &sp, STACK_WORDS, -1);
|
||||||
|
|
||||||
// Dump a few words from all successive frames.
|
// Dump a few words from all successive frames.
|
||||||
|
|
@ -311,7 +311,7 @@ static void dump_stack(Backtrace* backtrace, log_t* log, int scope_flags) {
|
||||||
_LOG(log, scope_flags, " ........ ........\n");
|
_LOG(log, scope_flags, " ........ ........\n");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
size_t words = frame->stack_size / sizeof(uint32_t);
|
size_t words = frame->stack_size / sizeof(word_t);
|
||||||
if (words == 0) {
|
if (words == 0) {
|
||||||
words = 1;
|
words = 1;
|
||||||
} else if (words > STACK_WORDS) {
|
} else if (words > STACK_WORDS) {
|
||||||
|
|
@ -334,7 +334,7 @@ static void dump_backtrace_and_stack(Backtrace* backtrace, log_t* log, int scope
|
||||||
|
|
||||||
static void dump_map(log_t* log, const backtrace_map_t* map, const char* what, int scope_flags) {
|
static void dump_map(log_t* log, const backtrace_map_t* map, const char* what, int scope_flags) {
|
||||||
if (map != NULL) {
|
if (map != NULL) {
|
||||||
_LOG(log, scope_flags, " %08x-%08x %c%c%c %s\n", map->start, map->end,
|
_LOG(log, scope_flags, " %" PRIPTR "-%" PRIPTR " %c%c%c %s\n", map->start, map->end,
|
||||||
(map->flags & PROT_READ) ? 'r' : '-', (map->flags & PROT_WRITE) ? 'w' : '-',
|
(map->flags & PROT_READ) ? 'r' : '-', (map->flags & PROT_WRITE) ? 'w' : '-',
|
||||||
(map->flags & PROT_EXEC) ? 'x' : '-', map->name.c_str());
|
(map->flags & PROT_EXEC) ? 'x' : '-', map->name.c_str());
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -573,24 +573,15 @@ static void dump_abort_message(Backtrace* backtrace, log_t* log, uintptr_t addre
|
||||||
memset(msg, 0, sizeof(msg));
|
memset(msg, 0, sizeof(msg));
|
||||||
char* p = &msg[0];
|
char* p = &msg[0];
|
||||||
while (p < &msg[sizeof(msg)]) {
|
while (p < &msg[sizeof(msg)]) {
|
||||||
uint32_t data;
|
word_t data;
|
||||||
|
size_t len = sizeof(word_t);
|
||||||
if (!backtrace->ReadWord(address, &data)) {
|
if (!backtrace->ReadWord(address, &data)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
address += sizeof(uint32_t);
|
address += sizeof(word_t);
|
||||||
|
|
||||||
if ((*p++ = (data >> 0) & 0xff) == 0) {
|
while (len > 0 && (*p++ = (data >> (sizeof(word_t) - len) * 8) & 0xff) != 0)
|
||||||
break;
|
len--;
|
||||||
}
|
|
||||||
if ((*p++ = (data >> 8) & 0xff) == 0) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if ((*p++ = (data >> 16) & 0xff) == 0) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if ((*p++ = (data >> 24) & 0xff) == 0) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
msg[sizeof(msg) - 1] = '\0';
|
msg[sizeof(msg) - 1] = '\0';
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -14,19 +14,17 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stddef.h>
|
#include "utility.h"
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <unistd.h>
|
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <log/logd.h>
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
#include <sys/ptrace.h>
|
#include <sys/ptrace.h>
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
#include <arpa/inet.h>
|
|
||||||
#include <assert.h>
|
|
||||||
|
|
||||||
#include "utility.h"
|
#include <backtrace/Backtrace.h>
|
||||||
|
#include <log/logd.h>
|
||||||
|
|
||||||
const int sleep_time_usec = 50000; // 0.05 seconds
|
const int sleep_time_usec = 50000; // 0.05 seconds
|
||||||
const int max_total_sleep_usec = 10000000; // 10 seconds
|
const int max_total_sleep_usec = 10000000; // 10 seconds
|
||||||
|
|
@ -34,7 +32,7 @@ const int max_total_sleep_usec = 10000000; // 10 seconds
|
||||||
static int write_to_am(int fd, const char* buf, int len) {
|
static int write_to_am(int fd, const char* buf, int len) {
|
||||||
int to_write = len;
|
int to_write = len;
|
||||||
while (to_write > 0) {
|
while (to_write > 0) {
|
||||||
int written = TEMP_FAILURE_RETRY( write(fd, buf + len - to_write, to_write) );
|
int written = TEMP_FAILURE_RETRY(write(fd, buf + len - to_write, to_write));
|
||||||
if (written < 0) {
|
if (written < 0) {
|
||||||
// hard failure
|
// hard failure
|
||||||
LOG("AM write failure (%d / %s)\n", errno, strerror(errno));
|
LOG("AM write failure (%d / %s)\n", errno, strerror(errno));
|
||||||
|
|
@ -46,34 +44,28 @@ static int write_to_am(int fd, const char* buf, int len) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void _LOG(log_t* log, int scopeFlags, const char* fmt, ...) {
|
void _LOG(log_t* log, int scopeFlags, const char* fmt, ...) {
|
||||||
char buf[512];
|
bool want_tfd_write = log && log->tfd >= 0;
|
||||||
bool want_tfd_write;
|
bool want_log_write = IS_AT_FAULT(scopeFlags) && (!log || !log->quiet);
|
||||||
bool want_log_write;
|
bool want_amfd_write = IS_AT_FAULT(scopeFlags) && !IS_SENSITIVE(scopeFlags) && log && log->amfd >= 0;
|
||||||
bool want_amfd_write;
|
|
||||||
int len = 0;
|
|
||||||
|
|
||||||
|
char buf[512];
|
||||||
va_list ap;
|
va_list ap;
|
||||||
va_start(ap, fmt);
|
va_start(ap, fmt);
|
||||||
|
vsnprintf(buf, sizeof(buf), fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
|
||||||
// where is the information going to go?
|
size_t len = strlen(buf);
|
||||||
want_tfd_write = log && log->tfd >= 0;
|
if (len <= 0) {
|
||||||
want_log_write = IS_AT_FAULT(scopeFlags) && (!log || !log->quiet);
|
return;
|
||||||
want_amfd_write = IS_AT_FAULT(scopeFlags) && !IS_SENSITIVE(scopeFlags) && log && log->amfd >= 0;
|
|
||||||
|
|
||||||
// if we're going to need the literal string, generate it once here
|
|
||||||
if (want_tfd_write || want_amfd_write) {
|
|
||||||
vsnprintf(buf, sizeof(buf), fmt, ap);
|
|
||||||
len = strlen(buf);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (want_tfd_write) {
|
if (want_tfd_write) {
|
||||||
write(log->tfd, buf, len);
|
TEMP_FAILURE_RETRY(write(log->tfd, buf, len));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (want_log_write) {
|
if (want_log_write) {
|
||||||
// whatever goes to logcat also goes to the Activity Manager
|
__android_log_write(ANDROID_LOG_INFO, "DEBUG", buf);
|
||||||
__android_log_vprint(ANDROID_LOG_INFO, "DEBUG", fmt, ap);
|
if (want_amfd_write) {
|
||||||
if (want_amfd_write && len > 0) {
|
|
||||||
int written = write_to_am(log->amfd, buf, len);
|
int written = write_to_am(log->amfd, buf, len);
|
||||||
if (written <= 0) {
|
if (written <= 0) {
|
||||||
// timeout or other failure on write; stop informing the activity manager
|
// timeout or other failure on write; stop informing the activity manager
|
||||||
|
|
@ -81,7 +73,6 @@ void _LOG(log_t* log, int scopeFlags, const char* fmt, ...) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
va_end(ap);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int wait_for_signal(pid_t tid, int* total_sleep_time_usec) {
|
int wait_for_signal(pid_t tid, int* total_sleep_time_usec) {
|
||||||
|
|
|
||||||
|
|
@ -18,9 +18,8 @@
|
||||||
#ifndef _DEBUGGERD_UTILITY_H
|
#ifndef _DEBUGGERD_UTILITY_H
|
||||||
#define _DEBUGGERD_UTILITY_H
|
#define _DEBUGGERD_UTILITY_H
|
||||||
|
|
||||||
#include <inttypes.h>
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stddef.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
/* tombstone file descriptor */
|
/* tombstone file descriptor */
|
||||||
|
|
@ -61,14 +60,6 @@ void _LOG(log_t* log, int scopeFlags, const char *fmt, ...)
|
||||||
#define XLOG2(fmt...) do {} while(0)
|
#define XLOG2(fmt...) do {} while(0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if __LP64__
|
|
||||||
#define PRIPTR "016" PRIxPTR
|
|
||||||
typedef uint64_t word_t;
|
|
||||||
#else
|
|
||||||
#define PRIPTR "08" PRIxPTR
|
|
||||||
typedef uint32_t word_t;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int wait_for_signal(pid_t tid, int* total_sleep_time_usec);
|
int wait_for_signal(pid_t tid, int* total_sleep_time_usec);
|
||||||
void wait_for_stop(pid_t tid, int* total_sleep_time_usec);
|
void wait_for_stop(pid_t tid, int* total_sleep_time_usec);
|
||||||
|
|
||||||
|
|
|
||||||
15
debuggerd/x86_64/crashglue.S
Normal file
15
debuggerd/x86_64/crashglue.S
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
.globl crash1
|
||||||
|
.globl crashnostack
|
||||||
|
|
||||||
|
crash1:
|
||||||
|
movl $0xa5a50000, %eax
|
||||||
|
movl $0xa5a50001, %ebx
|
||||||
|
movl $0xa5a50002, %ecx
|
||||||
|
|
||||||
|
movl $0, %edx
|
||||||
|
jmp *%rdx
|
||||||
|
|
||||||
|
|
||||||
|
crashnostack:
|
||||||
|
movl $0, %ebp
|
||||||
|
jmp *%rbp
|
||||||
51
debuggerd/x86_64/machine.cpp
Executable file
51
debuggerd/x86_64/machine.cpp
Executable file
|
|
@ -0,0 +1,51 @@
|
||||||
|
/*
|
||||||
|
** Copyright 2013, The Android Open Source Project
|
||||||
|
**
|
||||||
|
** Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
** you may not use this file except in compliance with the License.
|
||||||
|
** You may obtain a copy of the License at
|
||||||
|
**
|
||||||
|
** http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
**
|
||||||
|
** Unless required by applicable law or agreed to in writing, software
|
||||||
|
** distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
** See the License for the specific language governing permissions and
|
||||||
|
** limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/ptrace.h>
|
||||||
|
#include <sys/user.h>
|
||||||
|
|
||||||
|
#include "../utility.h"
|
||||||
|
#include "../machine.h"
|
||||||
|
|
||||||
|
void dump_memory_and_code(log_t* log, pid_t tid, int scope_flags) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void dump_registers(log_t* log, pid_t tid, int scope_flags) {
|
||||||
|
struct user_regs_struct r;
|
||||||
|
if (ptrace(PTRACE_GETREGS, tid, 0, &r) == -1) {
|
||||||
|
_LOG(log, scope_flags, "cannot get registers: %s\n", strerror(errno));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_LOG(log, scope_flags, " rax %016lx rbx %016lx rcx %016lx rdx %016lx\n",
|
||||||
|
r.rax, r.rbx, r.rcx, r.rdx);
|
||||||
|
_LOG(log, scope_flags, " rsi %016lx rdi %016lx\n",
|
||||||
|
r.rsi, r.rdi);
|
||||||
|
_LOG(log, scope_flags, " r8 %016lx r9 %016lx r10 %016lx r11 %016lx\n",
|
||||||
|
r.r8, r.r9, r.r10, r.r11);
|
||||||
|
_LOG(log, scope_flags, " r12 %016lx r13 %016lx r14 %016lx r15 %016lx\n",
|
||||||
|
r.r12, r.r13, r.r14, r.r15);
|
||||||
|
_LOG(log, scope_flags, " cs %016lx ss %016lx\n",
|
||||||
|
r.cs, r.ss);
|
||||||
|
_LOG(log, scope_flags, " rip %016lx rbp %016lx rsp %016lx eflags %016lx\n",
|
||||||
|
r.rip, r.rbp, r.rsp, r.eflags);
|
||||||
|
}
|
||||||
|
|
@ -17,6 +17,7 @@
|
||||||
#ifndef _BACKTRACE_BACKTRACE_H
|
#ifndef _BACKTRACE_BACKTRACE_H
|
||||||
#define _BACKTRACE_BACKTRACE_H
|
#define _BACKTRACE_BACKTRACE_H
|
||||||
|
|
||||||
|
#include <inttypes.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
@ -25,6 +26,14 @@
|
||||||
#include <backtrace/backtrace_constants.h>
|
#include <backtrace/backtrace_constants.h>
|
||||||
#include <backtrace/BacktraceMap.h>
|
#include <backtrace/BacktraceMap.h>
|
||||||
|
|
||||||
|
#if __LP64__
|
||||||
|
#define PRIPTR "016" PRIxPTR
|
||||||
|
typedef uint64_t word_t;
|
||||||
|
#else
|
||||||
|
#define PRIPTR "08" PRIxPTR
|
||||||
|
typedef uint32_t word_t;
|
||||||
|
#endif
|
||||||
|
|
||||||
struct backtrace_frame_data_t {
|
struct backtrace_frame_data_t {
|
||||||
size_t num; // The current fame number.
|
size_t num; // The current fame number.
|
||||||
uintptr_t pc; // The absolute pc.
|
uintptr_t pc; // The absolute pc.
|
||||||
|
|
@ -65,7 +74,7 @@ public:
|
||||||
virtual const backtrace_map_t* FindMap(uintptr_t pc);
|
virtual const backtrace_map_t* FindMap(uintptr_t pc);
|
||||||
|
|
||||||
// Read the data at a specific address.
|
// Read the data at a specific address.
|
||||||
virtual bool ReadWord(uintptr_t ptr, uint32_t* out_value) = 0;
|
virtual bool ReadWord(uintptr_t ptr, word_t* out_value) = 0;
|
||||||
|
|
||||||
// Create a string representing the formatted line of backtrace information
|
// Create a string representing the formatted line of backtrace information
|
||||||
// for a single frame.
|
// for a single frame.
|
||||||
|
|
@ -96,7 +105,7 @@ public:
|
||||||
protected:
|
protected:
|
||||||
Backtrace(BacktraceImpl* impl, pid_t pid, BacktraceMap* map);
|
Backtrace(BacktraceImpl* impl, pid_t pid, BacktraceMap* map);
|
||||||
|
|
||||||
virtual bool VerifyReadWordArgs(uintptr_t ptr, uint32_t* out_value);
|
virtual bool VerifyReadWordArgs(uintptr_t ptr, word_t* out_value);
|
||||||
|
|
||||||
bool BuildMap();
|
bool BuildMap();
|
||||||
|
|
||||||
|
|
|
||||||
2
libbacktrace/Android.mk
Normal file → Executable file
2
libbacktrace/Android.mk
Normal file → Executable file
|
|
@ -23,7 +23,7 @@ common_shared_libs := \
|
||||||
liblog \
|
liblog \
|
||||||
|
|
||||||
# To enable using libunwind on each arch, add it to this list.
|
# To enable using libunwind on each arch, add it to this list.
|
||||||
libunwind_architectures := arm arm64 x86
|
libunwind_architectures := arm arm64 x86 x86_64
|
||||||
|
|
||||||
ifeq ($(TARGET_ARCH),$(filter $(TARGET_ARCH),$(libunwind_architectures)))
|
ifeq ($(TARGET_ARCH),$(filter $(TARGET_ARCH),$(libunwind_architectures)))
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -21,8 +21,6 @@
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include <inttypes.h>
|
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include <backtrace/Backtrace.h>
|
#include <backtrace/Backtrace.h>
|
||||||
|
|
@ -81,10 +79,10 @@ std::string Backtrace::GetFunctionName(uintptr_t pc, uintptr_t* offset) {
|
||||||
return func_name;
|
return func_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Backtrace::VerifyReadWordArgs(uintptr_t ptr, uint32_t* out_value) {
|
bool Backtrace::VerifyReadWordArgs(uintptr_t ptr, word_t* out_value) {
|
||||||
if (ptr & 3) {
|
if (ptr & (sizeof(word_t)-1)) {
|
||||||
BACK_LOGW("invalid pointer %p", (void*)ptr);
|
BACK_LOGW("invalid pointer %p", (void*)ptr);
|
||||||
*out_value = (uint32_t)-1;
|
*out_value = (word_t)-1;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -142,18 +140,18 @@ BacktraceCurrent::BacktraceCurrent(
|
||||||
BacktraceCurrent::~BacktraceCurrent() {
|
BacktraceCurrent::~BacktraceCurrent() {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BacktraceCurrent::ReadWord(uintptr_t ptr, uint32_t* out_value) {
|
bool BacktraceCurrent::ReadWord(uintptr_t ptr, word_t* out_value) {
|
||||||
if (!VerifyReadWordArgs(ptr, out_value)) {
|
if (!VerifyReadWordArgs(ptr, out_value)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const backtrace_map_t* map = FindMap(ptr);
|
const backtrace_map_t* map = FindMap(ptr);
|
||||||
if (map && map->flags & PROT_READ) {
|
if (map && map->flags & PROT_READ) {
|
||||||
*out_value = *reinterpret_cast<uint32_t*>(ptr);
|
*out_value = *reinterpret_cast<word_t*>(ptr);
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
BACK_LOGW("pointer %p not in a readable 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);
|
*out_value = static_cast<word_t>(-1);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -170,7 +168,7 @@ BacktracePtrace::BacktracePtrace(
|
||||||
BacktracePtrace::~BacktracePtrace() {
|
BacktracePtrace::~BacktracePtrace() {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BacktracePtrace::ReadWord(uintptr_t ptr, uint32_t* out_value) {
|
bool BacktracePtrace::ReadWord(uintptr_t ptr, word_t* out_value) {
|
||||||
if (!VerifyReadWordArgs(ptr, out_value)) {
|
if (!VerifyReadWordArgs(ptr, out_value)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
@ -183,7 +181,7 @@ bool BacktracePtrace::ReadWord(uintptr_t ptr, uint32_t* out_value) {
|
||||||
// To disambiguate -1 from a valid result, we clear errno beforehand.
|
// To disambiguate -1 from a valid result, we clear errno beforehand.
|
||||||
errno = 0;
|
errno = 0;
|
||||||
*out_value = ptrace(PTRACE_PEEKTEXT, Tid(), reinterpret_cast<void*>(ptr), NULL);
|
*out_value = ptrace(PTRACE_PEEKTEXT, Tid(), reinterpret_cast<void*>(ptr), NULL);
|
||||||
if (*out_value == static_cast<uint32_t>(-1) && errno) {
|
if (*out_value == static_cast<word_t>(-1) && errno) {
|
||||||
BACK_LOGW("invalid pointer %p reading from tid %d, ptrace() strerror(errno)=%s",
|
BACK_LOGW("invalid pointer %p reading from tid %d, ptrace() strerror(errno)=%s",
|
||||||
reinterpret_cast<void*>(ptr), Tid(), strerror(errno));
|
reinterpret_cast<void*>(ptr), Tid(), strerror(errno));
|
||||||
return false;
|
return false;
|
||||||
|
|
|
||||||
4
libbacktrace/BacktraceImpl.h
Normal file → Executable file
4
libbacktrace/BacktraceImpl.h
Normal file → Executable file
|
|
@ -61,7 +61,7 @@ public:
|
||||||
BacktraceCurrent(BacktraceImpl* impl, BacktraceMap* map);
|
BacktraceCurrent(BacktraceImpl* impl, BacktraceMap* map);
|
||||||
virtual ~BacktraceCurrent();
|
virtual ~BacktraceCurrent();
|
||||||
|
|
||||||
bool ReadWord(uintptr_t ptr, uint32_t* out_value);
|
bool ReadWord(uintptr_t ptr, word_t* out_value);
|
||||||
};
|
};
|
||||||
|
|
||||||
class BacktracePtrace : public Backtrace {
|
class BacktracePtrace : public Backtrace {
|
||||||
|
|
@ -69,7 +69,7 @@ public:
|
||||||
BacktracePtrace(BacktraceImpl* impl, pid_t pid, pid_t tid, BacktraceMap* map);
|
BacktracePtrace(BacktraceImpl* impl, pid_t pid, pid_t tid, BacktraceMap* map);
|
||||||
virtual ~BacktracePtrace();
|
virtual ~BacktracePtrace();
|
||||||
|
|
||||||
bool ReadWord(uintptr_t ptr, uint32_t* out_value);
|
bool ReadWord(uintptr_t ptr, word_t* out_value);
|
||||||
};
|
};
|
||||||
|
|
||||||
Backtrace* CreateCurrentObj(BacktraceMap* map);
|
Backtrace* CreateCurrentObj(BacktraceMap* map);
|
||||||
|
|
|
||||||
3
libbacktrace/UnwindCurrent.cpp
Normal file → Executable file
3
libbacktrace/UnwindCurrent.cpp
Normal file → Executable file
|
|
@ -16,6 +16,7 @@
|
||||||
|
|
||||||
#define LOG_TAG "libbacktrace"
|
#define LOG_TAG "libbacktrace"
|
||||||
|
|
||||||
|
#include <sys/ucontext.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
#include <backtrace/Backtrace.h>
|
#include <backtrace/Backtrace.h>
|
||||||
|
|
@ -27,8 +28,6 @@
|
||||||
#include "UnwindCurrent.h"
|
#include "UnwindCurrent.h"
|
||||||
#include "UnwindMap.h"
|
#include "UnwindMap.h"
|
||||||
|
|
||||||
#include <ucontext.h>
|
|
||||||
|
|
||||||
//-------------------------------------------------------------------------
|
//-------------------------------------------------------------------------
|
||||||
// UnwindCurrent functions.
|
// UnwindCurrent functions.
|
||||||
//-------------------------------------------------------------------------
|
//-------------------------------------------------------------------------
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue