am 5434bf66: Merge "LP64: Enable debuggerd/libbacktrace/libunwind."

* commit '5434bf6640af7145986d63968846ba7168dab406':
  LP64: Enable debuggerd/libbacktrace/libunwind.
This commit is contained in:
Elliott Hughes 2014-01-31 22:09:29 +00:00 committed by Android Git Automerger
commit fe0d5d42e4
11 changed files with 129 additions and 83 deletions

View file

@ -1,6 +1,6 @@
# 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)
include $(CLEAR_VARS)
@ -19,6 +19,7 @@ LOCAL_CFLAGS := \
-Wall \
-Wno-array-bounds \
-Werror \
-Wno-unused-parameter \
LOCAL_MODULE := debuggerd

45
debuggerd/tombstone.cpp Normal file → Executable file
View 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)){
_LOG(log, SCOPE_AT_FAULT, "cannot get siginfo: %s\n", strerror(errno));
} 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),
sizeof(uintptr_t)*2, reinterpret_cast<uintptr_t>(si.si_addr));
reinterpret_cast<uintptr_t>(si.si_addr));
} else {
_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));
@ -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(
Backtrace* backtrace, log_t* log, int scope_flags, uintptr_t* sp, size_t words, int label) {
for (size_t i = 0; i < words; i++) {
uint32_t stack_content;
word_t stack_content;
if (!backtrace->ReadWord(*sp, &stack_content)) {
break;
}
@ -243,32 +243,32 @@ static void dump_stack_segment(
if (!func_name.empty()) {
if (!i && label >= 0) {
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);
} 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());
}
} else {
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);
} 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());
}
}
} else {
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);
} else {
_LOG(log, scope_flags, " %08x %08x %s\n",
_LOG(log, scope_flags, " %" PRIPTR " %" PRIPTR " %s\n",
*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;
// 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 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");
}
} else {
size_t words = frame->stack_size / sizeof(uint32_t);
size_t words = frame->stack_size / sizeof(word_t);
if (words == 0) {
words = 1;
} 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) {
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_EXEC) ? 'x' : '-', map->name.c_str());
} else {
@ -573,24 +573,15 @@ static void dump_abort_message(Backtrace* backtrace, log_t* log, uintptr_t addre
memset(msg, 0, sizeof(msg));
char* p = &msg[0];
while (p < &msg[sizeof(msg)]) {
uint32_t data;
word_t data;
size_t len = sizeof(word_t);
if (!backtrace->ReadWord(address, &data)) {
break;
}
address += sizeof(uint32_t);
address += sizeof(word_t);
if ((*p++ = (data >> 0) & 0xff) == 0) {
break;
}
if ((*p++ = (data >> 8) & 0xff) == 0) {
break;
}
if ((*p++ = (data >> 16) & 0xff) == 0) {
break;
}
if ((*p++ = (data >> 24) & 0xff) == 0) {
break;
}
while (len > 0 && (*p++ = (data >> (sizeof(word_t) - len) * 8) & 0xff) != 0)
len--;
}
msg[sizeof(msg) - 1] = '\0';

View file

@ -14,19 +14,17 @@
* limitations under the License.
*/
#include <stddef.h>
#include <stdio.h>
#include <string.h>
#include "utility.h"
#include <errno.h>
#include <unistd.h>
#include <signal.h>
#include <log/logd.h>
#include <string.h>
#include <unistd.h>
#include <sys/ptrace.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 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) {
int to_write = len;
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) {
// hard failure
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, ...) {
char buf[512];
bool want_tfd_write;
bool want_log_write;
bool want_amfd_write;
int len = 0;
bool want_tfd_write = log && log->tfd >= 0;
bool want_log_write = IS_AT_FAULT(scopeFlags) && (!log || !log->quiet);
bool want_amfd_write = IS_AT_FAULT(scopeFlags) && !IS_SENSITIVE(scopeFlags) && log && log->amfd >= 0;
char buf[512];
va_list ap;
va_start(ap, fmt);
vsnprintf(buf, sizeof(buf), fmt, ap);
va_end(ap);
// where is the information going to go?
want_tfd_write = log && log->tfd >= 0;
want_log_write = IS_AT_FAULT(scopeFlags) && (!log || !log->quiet);
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);
size_t len = strlen(buf);
if (len <= 0) {
return;
}
if (want_tfd_write) {
write(log->tfd, buf, len);
TEMP_FAILURE_RETRY(write(log->tfd, buf, len));
}
if (want_log_write) {
// whatever goes to logcat also goes to the Activity Manager
__android_log_vprint(ANDROID_LOG_INFO, "DEBUG", fmt, ap);
if (want_amfd_write && len > 0) {
__android_log_write(ANDROID_LOG_INFO, "DEBUG", buf);
if (want_amfd_write) {
int written = write_to_am(log->amfd, buf, len);
if (written <= 0) {
// 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) {

View file

@ -18,9 +18,8 @@
#ifndef _DEBUGGERD_UTILITY_H
#define _DEBUGGERD_UTILITY_H
#include <inttypes.h>
#include <stdbool.h>
#include <stddef.h>
#include <sys/types.h>
typedef struct {
/* tombstone file descriptor */
@ -61,14 +60,6 @@ void _LOG(log_t* log, int scopeFlags, const char *fmt, ...)
#define XLOG2(fmt...) do {} while(0)
#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);
void wait_for_stop(pid_t tid, int* total_sleep_time_usec);

View 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
View 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);
}

View file

@ -17,6 +17,7 @@
#ifndef _BACKTRACE_BACKTRACE_H
#define _BACKTRACE_BACKTRACE_H
#include <inttypes.h>
#include <stdint.h>
#include <string>
@ -25,6 +26,14 @@
#include <backtrace/backtrace_constants.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 {
size_t num; // The current fame number.
uintptr_t pc; // The absolute pc.
@ -65,7 +74,7 @@ public:
virtual const backtrace_map_t* FindMap(uintptr_t pc);
// 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
// for a single frame.
@ -96,7 +105,7 @@ public:
protected:
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();

2
libbacktrace/Android.mk Normal file → Executable file
View file

@ -23,7 +23,7 @@ common_shared_libs := \
liblog \
# 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)))

View file

@ -21,8 +21,6 @@
#include <sys/types.h>
#include <unistd.h>
#include <inttypes.h>
#include <string>
#include <backtrace/Backtrace.h>
@ -81,10 +79,10 @@ std::string Backtrace::GetFunctionName(uintptr_t pc, uintptr_t* offset) {
return func_name;
}
bool Backtrace::VerifyReadWordArgs(uintptr_t ptr, uint32_t* out_value) {
if (ptr & 3) {
bool Backtrace::VerifyReadWordArgs(uintptr_t ptr, word_t* out_value) {
if (ptr & (sizeof(word_t)-1)) {
BACK_LOGW("invalid pointer %p", (void*)ptr);
*out_value = (uint32_t)-1;
*out_value = (word_t)-1;
return false;
}
return true;
@ -142,18 +140,18 @@ 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)) {
return false;
}
const backtrace_map_t* map = FindMap(ptr);
if (map && map->flags & PROT_READ) {
*out_value = *reinterpret_cast<uint32_t*>(ptr);
*out_value = *reinterpret_cast<word_t*>(ptr);
return true;
} else {
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;
}
}
@ -170,7 +168,7 @@ 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)) {
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.
errno = 0;
*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",
reinterpret_cast<void*>(ptr), Tid(), strerror(errno));
return false;

4
libbacktrace/BacktraceImpl.h Normal file → Executable file
View file

@ -61,7 +61,7 @@ public:
BacktraceCurrent(BacktraceImpl* impl, BacktraceMap* map);
virtual ~BacktraceCurrent();
bool ReadWord(uintptr_t ptr, uint32_t* out_value);
bool ReadWord(uintptr_t ptr, word_t* out_value);
};
class BacktracePtrace : public Backtrace {
@ -69,7 +69,7 @@ public:
BacktracePtrace(BacktraceImpl* impl, pid_t pid, pid_t tid, BacktraceMap* map);
virtual ~BacktracePtrace();
bool ReadWord(uintptr_t ptr, uint32_t* out_value);
bool ReadWord(uintptr_t ptr, word_t* out_value);
};
Backtrace* CreateCurrentObj(BacktraceMap* map);

3
libbacktrace/UnwindCurrent.cpp Normal file → Executable file
View file

@ -16,6 +16,7 @@
#define LOG_TAG "libbacktrace"
#include <sys/ucontext.h>
#include <sys/types.h>
#include <backtrace/Backtrace.h>
@ -27,8 +28,6 @@
#include "UnwindCurrent.h"
#include "UnwindMap.h"
#include <ucontext.h>
//-------------------------------------------------------------------------
// UnwindCurrent functions.
//-------------------------------------------------------------------------