summaryrefslogtreecommitdiffstats
path: root/debuggerd/tombstone.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'debuggerd/tombstone.cpp')
-rw-r--r--debuggerd/tombstone.cpp181
1 files changed, 100 insertions, 81 deletions
diff --git a/debuggerd/tombstone.cpp b/debuggerd/tombstone.cpp
index 0c1b80f..094ab48 100644
--- a/debuggerd/tombstone.cpp
+++ b/debuggerd/tombstone.cpp
@@ -16,6 +16,7 @@
#define LOG_TAG "DEBUG"
+#include <arpa/inet.h>
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
@@ -33,6 +34,7 @@
#include <private/android_filesystem_config.h>
+#include <base/stringprintf.h>
#include <cutils/properties.h>
#include <log/log.h>
#include <log/logger.h>
@@ -45,9 +47,12 @@
#include <UniquePtr.h>
+#include <string>
+
+#include "backtrace.h"
+#include "elf_utils.h"
#include "machine.h"
#include "tombstone.h"
-#include "backtrace.h"
#define STACK_WORDS 16
@@ -233,48 +238,36 @@ static void dump_thread_info(log_t* log, pid_t pid, pid_t tid) {
static void dump_stack_segment(
Backtrace* backtrace, log_t* log, uintptr_t* sp, size_t words, int label) {
+ // Read the data all at once.
+ word_t stack_data[words];
+ size_t bytes_read = backtrace->Read(*sp, reinterpret_cast<uint8_t*>(&stack_data[0]), sizeof(word_t) * words);
+ words = bytes_read / sizeof(word_t);
+ std::string line;
for (size_t i = 0; i < words; i++) {
- word_t stack_content;
- if (!backtrace->ReadWord(*sp, &stack_content)) {
- break;
- }
-
- const backtrace_map_t* map = backtrace->FindMap(stack_content);
- const char* map_name;
- if (!map) {
- map_name = "";
+ line = " ";
+ if (i == 0 && label >= 0) {
+ // Print the label once.
+ line += android::base::StringPrintf("#%02d ", label);
} else {
- map_name = map->name.c_str();
+ line += " ";
}
- uintptr_t offset = 0;
- std::string func_name(backtrace->GetFunctionName(stack_content, &offset));
- if (!func_name.empty()) {
- if (!i && label >= 0) {
+ line += android::base::StringPrintf("%" PRIPTR " %" PRIPTR, *sp, stack_data[i]);
+
+ backtrace_map_t map;
+ backtrace->FillInMap(stack_data[i], &map);
+ if (BacktraceMap::IsValid(map) && !map.name.empty()) {
+ line += " " + map.name;
+ uintptr_t offset = 0;
+ std::string func_name(backtrace->GetFunctionName(stack_data[i], &offset));
+ if (!func_name.empty()) {
+ line += " (" + func_name;
if (offset) {
- _LOG(log, logtype::STACK, " #%02d %" PRIPTR " %" PRIPTR " %s (%s+%" PRIuPTR ")\n",
- label, *sp, stack_content, map_name, func_name.c_str(), offset);
- } else {
- _LOG(log, logtype::STACK, " #%02d %" PRIPTR " %" PRIPTR " %s (%s)\n",
- label, *sp, stack_content, map_name, func_name.c_str());
+ line += android::base::StringPrintf("+%" PRIuPTR, offset);
}
- } else {
- if (offset) {
- _LOG(log, logtype::STACK, " %" PRIPTR " %" PRIPTR " %s (%s+%" PRIuPTR ")\n",
- *sp, stack_content, map_name, func_name.c_str(), offset);
- } else {
- _LOG(log, logtype::STACK, " %" PRIPTR " %" PRIPTR " %s (%s)\n",
- *sp, stack_content, map_name, func_name.c_str());
- }
- }
- } else {
- if (!i && label >= 0) {
- _LOG(log, logtype::STACK, " #%02d %" PRIPTR " %" PRIPTR " %s\n",
- label, *sp, stack_content, map_name);
- } else {
- _LOG(log, logtype::STACK, " %" PRIPTR " %" PRIPTR " %s\n",
- *sp, stack_content, map_name);
+ line += ')';
}
}
+ _LOG(log, logtype::STACK, "%s\n", line.c_str());
*sp += sizeof(word_t);
}
@@ -325,61 +318,83 @@ static void dump_stack(Backtrace* backtrace, log_t* log) {
}
}
-static void dump_backtrace_and_stack(Backtrace* backtrace, log_t* log) {
- if (backtrace->NumFrames()) {
- _LOG(log, logtype::BACKTRACE, "\nbacktrace:\n");
- dump_backtrace_to_log(backtrace, log, " ");
-
- _LOG(log, logtype::STACK, "\nstack:\n");
- dump_stack(backtrace, log);
- }
-}
-
-static void dump_map(log_t* log, const backtrace_map_t* map, bool fault_addr) {
- _LOG(log, logtype::MAPS, "%s%" PRIPTR "-%" PRIPTR " %c%c%c %7" PRIdPTR " %s\n",
- (fault_addr? "--->" : " "), map->start, map->end - 1,
- (map->flags & PROT_READ) ? 'r' : '-', (map->flags & PROT_WRITE) ? 'w' : '-',
- (map->flags & PROT_EXEC) ? 'x' : '-',
- (map->end - map->start), map->name.c_str());
-}
-
-static void dump_nearby_maps(BacktraceMap* map, log_t* log, pid_t tid) {
+static void dump_all_maps(Backtrace* backtrace, BacktraceMap* map, log_t* log, pid_t tid) {
+ bool print_fault_address_marker = false;
+ uintptr_t addr = 0;
siginfo_t si;
memset(&si, 0, sizeof(si));
if (ptrace(PTRACE_GETSIGINFO, tid, 0, &si)) {
- _LOG(log, logtype::MAPS, "cannot get siginfo for %d: %s\n", tid, strerror(errno));
- return;
+ _LOG(log, logtype::ERROR, "cannot get siginfo for %d: %s\n", tid, strerror(errno));
+ } else {
+ print_fault_address_marker = signal_has_si_addr(si.si_signo);
+ addr = reinterpret_cast<uintptr_t>(si.si_addr);
}
- bool has_fault_address = signal_has_si_addr(si.si_signo);
- uintptr_t addr = reinterpret_cast<uintptr_t>(si.si_addr);
-
- _LOG(log, logtype::MAPS, "\nmemory map: %s\n", has_fault_address ? "(fault address prefixed with --->)" : "");
-
- if (has_fault_address && (addr < map->begin()->start)) {
- _LOG(log, logtype::MAPS, "--->Fault address falls at %" PRIPTR " before any mapped regions\n", addr);
+ _LOG(log, logtype::MAPS, "\n");
+ if (!print_fault_address_marker) {
+ _LOG(log, logtype::MAPS, "memory map:\n");
+ } else {
+ _LOG(log, logtype::MAPS, "memory map: (fault address prefixed with --->)\n");
+ if (map->begin() != map->end() && addr < map->begin()->start) {
+ _LOG(log, logtype::MAPS, "--->Fault address falls at %" PRIPTR " before any mapped regions\n",
+ addr);
+ print_fault_address_marker = false;
+ }
}
- BacktraceMap::const_iterator prev = map->begin();
+ std::string line;
for (BacktraceMap::const_iterator it = map->begin(); it != map->end(); ++it) {
- if (addr >= (*prev).end && addr < (*it).start) {
- _LOG(log, logtype::MAPS, "--->Fault address falls at %" PRIPTR " between mapped regions\n", addr);
+ line = " ";
+ if (print_fault_address_marker) {
+ if (addr < it->start) {
+ _LOG(log, logtype::MAPS, "--->Fault address falls at %" PRIPTR " between mapped regions\n",
+ addr);
+ print_fault_address_marker = false;
+ } else if (addr >= it->start && addr < it->end) {
+ line = "--->";
+ print_fault_address_marker = false;
+ }
+ }
+ line += android::base::StringPrintf("%" PRIPTR "-%" PRIPTR " ", it->start, it->end - 1);
+ if (it->flags & PROT_READ) {
+ line += 'r';
+ } else {
+ line += '-';
+ }
+ if (it->flags & PROT_WRITE) {
+ line += 'w';
+ } else {
+ line += '-';
}
- prev = it;
- bool in_map = has_fault_address && (addr >= (*it).start) && (addr < (*it).end);
- dump_map(log, &*it, in_map);
+ if (it->flags & PROT_EXEC) {
+ line += 'x';
+ } else {
+ line += '-';
+ }
+ line += android::base::StringPrintf(" %8" PRIxPTR, it->end - it->start);
+ if (it->name.length() > 0) {
+ line += " " + it->name;
+ std::string build_id;
+ if ((it->flags & PROT_READ) && elf_get_build_id(backtrace, it->start, &build_id)) {
+ line += " (BuildId: " + build_id + ")";
+ }
+ }
+ _LOG(log, logtype::MAPS, "%s\n", line.c_str());
}
- if (has_fault_address && (addr >= (*prev).end)) {
- _LOG(log, logtype::MAPS, "--->Fault address falls at %" PRIPTR " after any mapped regions\n", addr);
+ if (print_fault_address_marker) {
+ _LOG(log, logtype::MAPS, "--->Fault address falls at %" PRIPTR " after any mapped regions\n",
+ addr);
}
}
-static void dump_thread(Backtrace* backtrace, log_t* log) {
- dump_registers(log, backtrace->Tid());
- dump_backtrace_and_stack(backtrace, log);
+static void dump_backtrace_and_stack(Backtrace* backtrace, log_t* log) {
+ if (backtrace->NumFrames()) {
+ _LOG(log, logtype::BACKTRACE, "\nbacktrace:\n");
+ dump_backtrace_to_log(backtrace, log, " ");
- dump_memory_and_code(log, backtrace->Tid());
- dump_nearby_maps(backtrace->GetMap(), log, backtrace->Tid());
+ _LOG(log, logtype::STACK, "\nstack:\n");
+ dump_stack(backtrace, log);
+ }
}
// Return true if some thread is not detached cleanly
@@ -425,9 +440,10 @@ static bool dump_sibling_thread_report(
_LOG(log, logtype::THREAD, "--- --- --- --- --- --- --- --- --- --- --- --- --- --- --- ---\n");
dump_thread_info(log, pid, new_tid);
+ dump_registers(log, new_tid);
UniquePtr<Backtrace> backtrace(Backtrace::Create(pid, new_tid, map));
if (backtrace->Unwind(0)) {
- dump_thread(backtrace.get(), log);
+ dump_backtrace_and_stack(backtrace.get(), log);
}
log->current_tid = log->crashed_tid;
@@ -458,7 +474,7 @@ static void dump_log_file(
}
logger_list = android_logger_list_open(
- android_name_to_log_id(filename), O_RDONLY | O_NONBLOCK, tail, pid);
+ android_name_to_log_id(filename), ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK, tail, pid);
if (!logger_list) {
ALOGE("Unable to open %s: %s\n", filename, strerror(errno));
@@ -626,10 +642,13 @@ static bool dump_crash(log_t* log, pid_t pid, pid_t tid, int signal, int si_code
UniquePtr<BacktraceMap> map(BacktraceMap::Create(pid));
UniquePtr<Backtrace> backtrace(Backtrace::Create(pid, tid, map.get()));
+ dump_abort_message(backtrace.get(), log, abort_msg_address);
+ dump_registers(log, tid);
if (backtrace->Unwind(0)) {
- dump_abort_message(backtrace.get(), log, abort_msg_address);
- dump_thread(backtrace.get(), log);
+ dump_backtrace_and_stack(backtrace.get(), log);
}
+ dump_memory_and_code(log, tid);
+ dump_all_maps(backtrace.get(), map.get(), log, tid);
if (want_logs) {
dump_logs(log, pid, 5);