Merge "Use the new AndroidUnwinder object."
This commit is contained in:
commit
f26a9504db
13 changed files with 104 additions and 116 deletions
|
|
@ -51,12 +51,9 @@
|
||||||
#define ATRACE_TAG ATRACE_TAG_BIONIC
|
#define ATRACE_TAG ATRACE_TAG_BIONIC
|
||||||
#include <utils/Trace.h>
|
#include <utils/Trace.h>
|
||||||
|
|
||||||
#include <unwindstack/DexFiles.h>
|
#include <unwindstack/AndroidUnwinder.h>
|
||||||
#include <unwindstack/JitDebug.h>
|
#include <unwindstack/Error.h>
|
||||||
#include <unwindstack/Maps.h>
|
|
||||||
#include <unwindstack/Memory.h>
|
|
||||||
#include <unwindstack/Regs.h>
|
#include <unwindstack/Regs.h>
|
||||||
#include <unwindstack/Unwinder.h>
|
|
||||||
|
|
||||||
#include "libdebuggerd/backtrace.h"
|
#include "libdebuggerd/backtrace.h"
|
||||||
#include "libdebuggerd/tombstone.h"
|
#include "libdebuggerd/tombstone.h"
|
||||||
|
|
@ -623,9 +620,12 @@ int main(int argc, char** argv) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Use seccomp to lock ourselves down.
|
// TODO: Use seccomp to lock ourselves down.
|
||||||
unwindstack::UnwinderFromPid unwinder(256, vm_pid, unwindstack::Regs::CurrentArch());
|
|
||||||
if (!unwinder.Init()) {
|
unwindstack::AndroidRemoteUnwinder unwinder(vm_pid, unwindstack::Regs::CurrentArch());
|
||||||
LOG(FATAL) << "Failed to init unwinder object.";
|
unwindstack::ErrorData error_data;
|
||||||
|
if (!unwinder.Initialize(error_data)) {
|
||||||
|
LOG(FATAL) << "Failed to initialize unwinder object: "
|
||||||
|
<< unwindstack::GetErrorCodeString(error_data.code);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string amfd_data;
|
std::string amfd_data;
|
||||||
|
|
|
||||||
|
|
@ -31,12 +31,9 @@
|
||||||
#include <android-base/unique_fd.h>
|
#include <android-base/unique_fd.h>
|
||||||
#include <async_safe/log.h>
|
#include <async_safe/log.h>
|
||||||
#include <bionic/reserved_signals.h>
|
#include <bionic/reserved_signals.h>
|
||||||
#include <unwindstack/DexFiles.h>
|
#include <unwindstack/AndroidUnwinder.h>
|
||||||
#include <unwindstack/JitDebug.h>
|
|
||||||
#include <unwindstack/Maps.h>
|
|
||||||
#include <unwindstack/Memory.h>
|
#include <unwindstack/Memory.h>
|
||||||
#include <unwindstack/Regs.h>
|
#include <unwindstack/Regs.h>
|
||||||
#include <unwindstack/Unwinder.h>
|
|
||||||
|
|
||||||
#include "debuggerd/handler.h"
|
#include "debuggerd/handler.h"
|
||||||
#include "handler/fallback.h"
|
#include "handler/fallback.h"
|
||||||
|
|
@ -75,11 +72,11 @@ static void debuggerd_fallback_trace(int output_fd, ucontext_t* ucontext) {
|
||||||
|
|
||||||
// Do not use the thread cache here because it will call pthread_key_create
|
// Do not use the thread cache here because it will call pthread_key_create
|
||||||
// which doesn't work in linker code. See b/189803009.
|
// which doesn't work in linker code. See b/189803009.
|
||||||
// Use a normal cached object because the process is stopped, and there
|
// Use a normal cached object because the thread is stopped, and there
|
||||||
// is no chance of data changing between reads.
|
// is no chance of data changing between reads.
|
||||||
auto process_memory = unwindstack::Memory::CreateProcessMemoryCached(getpid());
|
auto process_memory = unwindstack::Memory::CreateProcessMemoryCached(getpid());
|
||||||
// TODO: Create this once and store it in a global?
|
// TODO: Create this once and store it in a global?
|
||||||
unwindstack::UnwinderFromPid unwinder(kMaxFrames, getpid(), process_memory);
|
unwindstack::AndroidLocalUnwinder unwinder(process_memory);
|
||||||
dump_backtrace_thread(output_fd, &unwinder, thread);
|
dump_backtrace_thread(output_fd, &unwinder, thread);
|
||||||
}
|
}
|
||||||
__linker_disable_fallback_allocator();
|
__linker_disable_fallback_allocator();
|
||||||
|
|
|
||||||
|
|
@ -37,6 +37,7 @@
|
||||||
#include <android-base/strings.h>
|
#include <android-base/strings.h>
|
||||||
#include <android-base/unique_fd.h>
|
#include <android-base/unique_fd.h>
|
||||||
#include <log/log.h>
|
#include <log/log.h>
|
||||||
|
#include <unwindstack/AndroidUnwinder.h>
|
||||||
#include <unwindstack/Unwinder.h>
|
#include <unwindstack/Unwinder.h>
|
||||||
|
|
||||||
#include "libdebuggerd/types.h"
|
#include "libdebuggerd/types.h"
|
||||||
|
|
@ -57,7 +58,7 @@ static void dump_process_footer(log_t* log, pid_t pid) {
|
||||||
_LOG(log, logtype::BACKTRACE, "\n----- end %d -----\n", pid);
|
_LOG(log, logtype::BACKTRACE, "\n----- end %d -----\n", pid);
|
||||||
}
|
}
|
||||||
|
|
||||||
void dump_backtrace_thread(int output_fd, unwindstack::Unwinder* unwinder,
|
void dump_backtrace_thread(int output_fd, unwindstack::AndroidUnwinder* unwinder,
|
||||||
const ThreadInfo& thread) {
|
const ThreadInfo& thread) {
|
||||||
log_t log;
|
log_t log;
|
||||||
log.tfd = output_fd;
|
log.tfd = output_fd;
|
||||||
|
|
@ -65,21 +66,17 @@ void dump_backtrace_thread(int output_fd, unwindstack::Unwinder* unwinder,
|
||||||
|
|
||||||
_LOG(&log, logtype::BACKTRACE, "\n\"%s\" sysTid=%d\n", thread.thread_name.c_str(), thread.tid);
|
_LOG(&log, logtype::BACKTRACE, "\n\"%s\" sysTid=%d\n", thread.thread_name.c_str(), thread.tid);
|
||||||
|
|
||||||
unwinder->SetRegs(thread.registers.get());
|
unwindstack::AndroidUnwinderData data;
|
||||||
unwinder->Unwind();
|
if (!unwinder->Unwind(thread.registers.get(), data)) {
|
||||||
if (unwinder->NumFrames() == 0) {
|
_LOG(&log, logtype::THREAD, "Unwind failed: tid = %d: Error %s\n", thread.tid,
|
||||||
_LOG(&log, logtype::THREAD, "Unwind failed: tid = %d\n", thread.tid);
|
data.GetErrorString().c_str());
|
||||||
if (unwinder->LastErrorCode() != unwindstack::ERROR_NONE) {
|
|
||||||
_LOG(&log, logtype::THREAD, " Error code: %s\n", unwinder->LastErrorCodeString());
|
|
||||||
_LOG(&log, logtype::THREAD, " Error address: 0x%" PRIx64 "\n", unwinder->LastErrorAddress());
|
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
log_backtrace(&log, unwinder, " ");
|
log_backtrace(&log, unwinder, data, " ");
|
||||||
}
|
}
|
||||||
|
|
||||||
void dump_backtrace(android::base::unique_fd output_fd, unwindstack::Unwinder* unwinder,
|
void dump_backtrace(android::base::unique_fd output_fd, unwindstack::AndroidUnwinder* unwinder,
|
||||||
const std::map<pid_t, ThreadInfo>& thread_info, pid_t target_thread) {
|
const std::map<pid_t, ThreadInfo>& thread_info, pid_t target_thread) {
|
||||||
log_t log;
|
log_t log;
|
||||||
log.tfd = output_fd.get();
|
log.tfd = output_fd.get();
|
||||||
|
|
|
||||||
|
|
@ -21,9 +21,8 @@
|
||||||
#include "gwp_asan/common.h"
|
#include "gwp_asan/common.h"
|
||||||
#include "gwp_asan/crash_handler.h"
|
#include "gwp_asan/crash_handler.h"
|
||||||
|
|
||||||
#include <unwindstack/Maps.h>
|
#include <unwindstack/AndroidUnwinder.h>
|
||||||
#include <unwindstack/Memory.h>
|
#include <unwindstack/Memory.h>
|
||||||
#include <unwindstack/Regs.h>
|
|
||||||
#include <unwindstack/Unwinder.h>
|
#include <unwindstack/Unwinder.h>
|
||||||
|
|
||||||
#include "tombstone.pb.h"
|
#include "tombstone.pb.h"
|
||||||
|
|
@ -106,7 +105,8 @@ bool GwpAsanCrashData::CrashIsMine() const {
|
||||||
|
|
||||||
constexpr size_t kMaxTraceLength = gwp_asan::AllocationMetadata::kMaxTraceLengthToCollect;
|
constexpr size_t kMaxTraceLength = gwp_asan::AllocationMetadata::kMaxTraceLengthToCollect;
|
||||||
|
|
||||||
void GwpAsanCrashData::AddCauseProtos(Tombstone* tombstone, unwindstack::Unwinder* unwinder) const {
|
void GwpAsanCrashData::AddCauseProtos(Tombstone* tombstone,
|
||||||
|
unwindstack::AndroidUnwinder* unwinder) const {
|
||||||
if (!CrashIsMine()) {
|
if (!CrashIsMine()) {
|
||||||
ALOGE("Internal Error: AddCauseProtos() on a non-GWP-ASan crash.");
|
ALOGE("Internal Error: AddCauseProtos() on a non-GWP-ASan crash.");
|
||||||
return;
|
return;
|
||||||
|
|
@ -140,7 +140,6 @@ void GwpAsanCrashData::AddCauseProtos(Tombstone* tombstone, unwindstack::Unwinde
|
||||||
|
|
||||||
heap_object->set_address(__gwp_asan_get_allocation_address(responsible_allocation_));
|
heap_object->set_address(__gwp_asan_get_allocation_address(responsible_allocation_));
|
||||||
heap_object->set_size(__gwp_asan_get_allocation_size(responsible_allocation_));
|
heap_object->set_size(__gwp_asan_get_allocation_size(responsible_allocation_));
|
||||||
unwinder->SetDisplayBuildID(true);
|
|
||||||
|
|
||||||
std::unique_ptr<uintptr_t[]> frames(new uintptr_t[kMaxTraceLength]);
|
std::unique_ptr<uintptr_t[]> frames(new uintptr_t[kMaxTraceLength]);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -30,16 +30,16 @@
|
||||||
|
|
||||||
// Forward delcaration
|
// Forward delcaration
|
||||||
namespace unwindstack {
|
namespace unwindstack {
|
||||||
class Unwinder;
|
class AndroidUnwinder;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dumps a backtrace using a format similar to what Dalvik uses so that the result
|
// Dumps a backtrace using a format similar to what Dalvik uses so that the result
|
||||||
// can be intermixed in a bug report.
|
// can be intermixed in a bug report.
|
||||||
void dump_backtrace(android::base::unique_fd output_fd, unwindstack::Unwinder* unwinder,
|
void dump_backtrace(android::base::unique_fd output_fd, unwindstack::AndroidUnwinder* unwinder,
|
||||||
const std::map<pid_t, ThreadInfo>& thread_info, pid_t target_thread);
|
const std::map<pid_t, ThreadInfo>& thread_info, pid_t target_thread);
|
||||||
|
|
||||||
void dump_backtrace_header(int output_fd);
|
void dump_backtrace_header(int output_fd);
|
||||||
void dump_backtrace_thread(int output_fd, unwindstack::Unwinder* unwinder,
|
void dump_backtrace_thread(int output_fd, unwindstack::AndroidUnwinder* unwinder,
|
||||||
const ThreadInfo& thread);
|
const ThreadInfo& thread);
|
||||||
void dump_backtrace_footer(int output_fd);
|
void dump_backtrace_footer(int output_fd);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -26,9 +26,15 @@
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
#include "utility.h"
|
#include "utility.h"
|
||||||
|
|
||||||
|
// Forward delcarations
|
||||||
class Cause;
|
class Cause;
|
||||||
class Tombstone;
|
class Tombstone;
|
||||||
|
|
||||||
|
namespace unwindstack {
|
||||||
|
class AndroidUnwinder;
|
||||||
|
class Memory;
|
||||||
|
} // namespace unwindstack
|
||||||
|
|
||||||
class GwpAsanCrashData {
|
class GwpAsanCrashData {
|
||||||
public:
|
public:
|
||||||
GwpAsanCrashData() = delete;
|
GwpAsanCrashData() = delete;
|
||||||
|
|
@ -52,7 +58,7 @@ class GwpAsanCrashData {
|
||||||
// allocator crash state.
|
// allocator crash state.
|
||||||
uintptr_t GetFaultAddress() const;
|
uintptr_t GetFaultAddress() const;
|
||||||
|
|
||||||
void AddCauseProtos(Tombstone* tombstone, unwindstack::Unwinder* unwinder) const;
|
void AddCauseProtos(Tombstone* tombstone, unwindstack::AndroidUnwinder* unwinder) const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// Is GWP-ASan responsible for this crash.
|
// Is GWP-ASan responsible for this crash.
|
||||||
|
|
|
||||||
|
|
@ -23,9 +23,15 @@
|
||||||
|
|
||||||
#include "scudo/interface.h"
|
#include "scudo/interface.h"
|
||||||
|
|
||||||
|
// Forward delcarations
|
||||||
class Cause;
|
class Cause;
|
||||||
class Tombstone;
|
class Tombstone;
|
||||||
|
|
||||||
|
namespace unwindstack {
|
||||||
|
class AndroidUnwinder;
|
||||||
|
class Memory;
|
||||||
|
} // namespace unwindstack
|
||||||
|
|
||||||
class ScudoCrashData {
|
class ScudoCrashData {
|
||||||
public:
|
public:
|
||||||
ScudoCrashData() = delete;
|
ScudoCrashData() = delete;
|
||||||
|
|
@ -34,12 +40,12 @@ class ScudoCrashData {
|
||||||
|
|
||||||
bool CrashIsMine() const;
|
bool CrashIsMine() const;
|
||||||
|
|
||||||
void AddCauseProtos(Tombstone* tombstone, unwindstack::Unwinder* unwinder) const;
|
void AddCauseProtos(Tombstone* tombstone, unwindstack::AndroidUnwinder* unwinder) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
scudo_error_info error_info_ = {};
|
scudo_error_info error_info_ = {};
|
||||||
uintptr_t untagged_fault_addr_;
|
uintptr_t untagged_fault_addr_;
|
||||||
|
|
||||||
void FillInCause(Cause* cause, const scudo_error_report* report,
|
void FillInCause(Cause* cause, const scudo_error_report* report,
|
||||||
unwindstack::Unwinder* unwinder) const;
|
unwindstack::AndroidUnwinder* unwinder) const;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,7 @@ class Tombstone;
|
||||||
|
|
||||||
namespace unwindstack {
|
namespace unwindstack {
|
||||||
struct FrameData;
|
struct FrameData;
|
||||||
class Unwinder;
|
class AndroidUnwinder;
|
||||||
}
|
}
|
||||||
|
|
||||||
// The maximum number of frames to save when unwinding.
|
// The maximum number of frames to save when unwinding.
|
||||||
|
|
@ -51,7 +51,7 @@ int open_tombstone(std::string* path);
|
||||||
|
|
||||||
/* Creates a tombstone file and writes the crash dump to it. */
|
/* Creates a tombstone file and writes the crash dump to it. */
|
||||||
void engrave_tombstone(android::base::unique_fd output_fd, android::base::unique_fd proto_fd,
|
void engrave_tombstone(android::base::unique_fd output_fd, android::base::unique_fd proto_fd,
|
||||||
unwindstack::Unwinder* unwinder,
|
unwindstack::AndroidUnwinder* unwinder,
|
||||||
const std::map<pid_t, ThreadInfo>& thread_info, pid_t target_thread,
|
const std::map<pid_t, ThreadInfo>& thread_info, pid_t target_thread,
|
||||||
const ProcessInfo& process_info, OpenFilesList* open_files,
|
const ProcessInfo& process_info, OpenFilesList* open_files,
|
||||||
std::string* amfd_data);
|
std::string* amfd_data);
|
||||||
|
|
@ -59,7 +59,7 @@ void engrave_tombstone(android::base::unique_fd output_fd, android::base::unique
|
||||||
void engrave_tombstone_ucontext(int tombstone_fd, int proto_fd, uint64_t abort_msg_address,
|
void engrave_tombstone_ucontext(int tombstone_fd, int proto_fd, uint64_t abort_msg_address,
|
||||||
siginfo_t* siginfo, ucontext_t* ucontext);
|
siginfo_t* siginfo, ucontext_t* ucontext);
|
||||||
|
|
||||||
void engrave_tombstone_proto(Tombstone* tombstone, unwindstack::Unwinder* unwinder,
|
void engrave_tombstone_proto(Tombstone* tombstone, unwindstack::AndroidUnwinder* unwinder,
|
||||||
const std::map<pid_t, ThreadInfo>& threads, pid_t target_thread,
|
const std::map<pid_t, ThreadInfo>& threads, pid_t target_thread,
|
||||||
const ProcessInfo& process_info, const OpenFilesList* open_files);
|
const ProcessInfo& process_info, const OpenFilesList* open_files);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -73,11 +73,13 @@ void _LOG(log_t* log, logtype ltype, const char* fmt, ...) __attribute__((format
|
||||||
void _VLOG(log_t* log, logtype ltype, const char* fmt, va_list ap);
|
void _VLOG(log_t* log, logtype ltype, const char* fmt, va_list ap);
|
||||||
|
|
||||||
namespace unwindstack {
|
namespace unwindstack {
|
||||||
class Unwinder;
|
class AndroidUnwinder;
|
||||||
class Memory;
|
class Memory;
|
||||||
|
struct AndroidUnwinderData;
|
||||||
}
|
}
|
||||||
|
|
||||||
void log_backtrace(log_t* log, unwindstack::Unwinder* unwinder, const char* prefix);
|
void log_backtrace(log_t* log, unwindstack::AndroidUnwinder* unwinder,
|
||||||
|
unwindstack::AndroidUnwinderData& data, const char* prefix);
|
||||||
|
|
||||||
ssize_t dump_memory(void* out, size_t len, uint8_t* tags, size_t tags_len, uint64_t* addr,
|
ssize_t dump_memory(void* out, size_t len, uint8_t* tags, size_t tags_len, uint64_t* addr,
|
||||||
unwindstack::Memory* memory);
|
unwindstack::Memory* memory);
|
||||||
|
|
|
||||||
|
|
@ -17,8 +17,8 @@
|
||||||
#include "libdebuggerd/scudo.h"
|
#include "libdebuggerd/scudo.h"
|
||||||
#include "libdebuggerd/tombstone.h"
|
#include "libdebuggerd/tombstone.h"
|
||||||
|
|
||||||
|
#include "unwindstack/AndroidUnwinder.h"
|
||||||
#include "unwindstack/Memory.h"
|
#include "unwindstack/Memory.h"
|
||||||
#include "unwindstack/Unwinder.h"
|
|
||||||
|
|
||||||
#include <android-base/macros.h>
|
#include <android-base/macros.h>
|
||||||
#include <bionic/macros.h>
|
#include <bionic/macros.h>
|
||||||
|
|
@ -80,7 +80,7 @@ bool ScudoCrashData::CrashIsMine() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScudoCrashData::FillInCause(Cause* cause, const scudo_error_report* report,
|
void ScudoCrashData::FillInCause(Cause* cause, const scudo_error_report* report,
|
||||||
unwindstack::Unwinder* unwinder) const {
|
unwindstack::AndroidUnwinder* unwinder) const {
|
||||||
MemoryError* memory_error = cause->mutable_memory_error();
|
MemoryError* memory_error = cause->mutable_memory_error();
|
||||||
HeapObject* heap_object = memory_error->mutable_heap();
|
HeapObject* heap_object = memory_error->mutable_heap();
|
||||||
|
|
||||||
|
|
@ -102,7 +102,6 @@ void ScudoCrashData::FillInCause(Cause* cause, const scudo_error_report* report,
|
||||||
|
|
||||||
heap_object->set_address(report->allocation_address);
|
heap_object->set_address(report->allocation_address);
|
||||||
heap_object->set_size(report->allocation_size);
|
heap_object->set_size(report->allocation_size);
|
||||||
unwinder->SetDisplayBuildID(true);
|
|
||||||
|
|
||||||
heap_object->set_allocation_tid(report->allocation_tid);
|
heap_object->set_allocation_tid(report->allocation_tid);
|
||||||
for (size_t i = 0; i < arraysize(report->allocation_trace) && report->allocation_trace[i]; ++i) {
|
for (size_t i = 0; i < arraysize(report->allocation_trace) && report->allocation_trace[i]; ++i) {
|
||||||
|
|
@ -123,7 +122,8 @@ void ScudoCrashData::FillInCause(Cause* cause, const scudo_error_report* report,
|
||||||
set_human_readable_cause(cause, untagged_fault_addr_);
|
set_human_readable_cause(cause, untagged_fault_addr_);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScudoCrashData::AddCauseProtos(Tombstone* tombstone, unwindstack::Unwinder* unwinder) const {
|
void ScudoCrashData::AddCauseProtos(Tombstone* tombstone,
|
||||||
|
unwindstack::AndroidUnwinder* unwinder) const {
|
||||||
size_t report_num = 0;
|
size_t report_num = 0;
|
||||||
while (report_num < sizeof(error_info_.reports) / sizeof(error_info_.reports[0]) &&
|
while (report_num < sizeof(error_info_.reports) / sizeof(error_info_.reports[0]) &&
|
||||||
error_info_.reports[report_num].error_type != UNKNOWN) {
|
error_info_.reports[report_num].error_type != UNKNOWN) {
|
||||||
|
|
|
||||||
|
|
@ -36,9 +36,9 @@
|
||||||
#include <async_safe/log.h>
|
#include <async_safe/log.h>
|
||||||
#include <log/log.h>
|
#include <log/log.h>
|
||||||
#include <private/android_filesystem_config.h>
|
#include <private/android_filesystem_config.h>
|
||||||
#include <unwindstack/Memory.h>
|
#include <unwindstack/AndroidUnwinder.h>
|
||||||
|
#include <unwindstack/Error.h>
|
||||||
#include <unwindstack/Regs.h>
|
#include <unwindstack/Regs.h>
|
||||||
#include <unwindstack/Unwinder.h>
|
|
||||||
|
|
||||||
#include "libdebuggerd/backtrace.h"
|
#include "libdebuggerd/backtrace.h"
|
||||||
#include "libdebuggerd/open_files_list.h"
|
#include "libdebuggerd/open_files_list.h"
|
||||||
|
|
@ -101,12 +101,16 @@ void engrave_tombstone_ucontext(int tombstone_fd, int proto_fd, uint64_t abort_m
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto process_memory =
|
// Do not use the thread cache here because it will call pthread_key_create
|
||||||
unwindstack::Memory::CreateProcessMemoryCached(getpid());
|
// which doesn't work in linker code. See b/189803009.
|
||||||
unwindstack::UnwinderFromPid unwinder(kMaxFrames, pid, unwindstack::Regs::CurrentArch(), nullptr,
|
// Use a normal cached object because the thread is stopped, and there
|
||||||
process_memory);
|
// is no chance of data changing between reads.
|
||||||
if (!unwinder.Init()) {
|
auto process_memory = unwindstack::Memory::CreateProcessMemoryCached(getpid());
|
||||||
async_safe_format_log(ANDROID_LOG_ERROR, LOG_TAG, "failed to init unwinder object");
|
unwindstack::AndroidLocalUnwinder unwinder(process_memory);
|
||||||
|
unwindstack::ErrorData error;
|
||||||
|
if (!unwinder.Initialize(error)) {
|
||||||
|
async_safe_format_log(ANDROID_LOG_ERROR, LOG_TAG, "failed to init unwinder object: %s",
|
||||||
|
unwindstack::GetErrorCodeString(error.code));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -116,7 +120,8 @@ void engrave_tombstone_ucontext(int tombstone_fd, int proto_fd, uint64_t abort_m
|
||||||
process_info, nullptr, nullptr);
|
process_info, nullptr, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void engrave_tombstone(unique_fd output_fd, unique_fd proto_fd, unwindstack::Unwinder* unwinder,
|
void engrave_tombstone(unique_fd output_fd, unique_fd proto_fd,
|
||||||
|
unwindstack::AndroidUnwinder* unwinder,
|
||||||
const std::map<pid_t, ThreadInfo>& threads, pid_t target_thread,
|
const std::map<pid_t, ThreadInfo>& threads, pid_t target_thread,
|
||||||
const ProcessInfo& process_info, OpenFilesList* open_files,
|
const ProcessInfo& process_info, OpenFilesList* open_files,
|
||||||
std::string* amfd_data) {
|
std::string* amfd_data) {
|
||||||
|
|
|
||||||
|
|
@ -56,10 +56,11 @@
|
||||||
#include <private/android_filesystem_config.h>
|
#include <private/android_filesystem_config.h>
|
||||||
|
|
||||||
#include <procinfo/process.h>
|
#include <procinfo/process.h>
|
||||||
|
#include <unwindstack/AndroidUnwinder.h>
|
||||||
|
#include <unwindstack/Error.h>
|
||||||
|
#include <unwindstack/MapInfo.h>
|
||||||
#include <unwindstack/Maps.h>
|
#include <unwindstack/Maps.h>
|
||||||
#include <unwindstack/Memory.h>
|
|
||||||
#include <unwindstack/Regs.h>
|
#include <unwindstack/Regs.h>
|
||||||
#include <unwindstack/Unwinder.h>
|
|
||||||
|
|
||||||
#include "libdebuggerd/open_files_list.h"
|
#include "libdebuggerd/open_files_list.h"
|
||||||
#include "libdebuggerd/utility.h"
|
#include "libdebuggerd/utility.h"
|
||||||
|
|
@ -189,7 +190,7 @@ void set_human_readable_cause(Cause* cause, uint64_t fault_addr) {
|
||||||
error_type_str, diff, byte_suffix, location_str, heap_object.size(), heap_object.address()));
|
error_type_str, diff, byte_suffix, location_str, heap_object.size(), heap_object.address()));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dump_probable_cause(Tombstone* tombstone, unwindstack::Unwinder* unwinder,
|
static void dump_probable_cause(Tombstone* tombstone, unwindstack::AndroidUnwinder* unwinder,
|
||||||
const ProcessInfo& process_info, const ThreadInfo& main_thread) {
|
const ProcessInfo& process_info, const ThreadInfo& main_thread) {
|
||||||
#if defined(USE_SCUDO)
|
#if defined(USE_SCUDO)
|
||||||
ScudoCrashData scudo_crash_data(unwinder->GetProcessMemory().get(), process_info);
|
ScudoCrashData scudo_crash_data(unwinder->GetProcessMemory().get(), process_info);
|
||||||
|
|
@ -245,9 +246,9 @@ static void dump_probable_cause(Tombstone* tombstone, unwindstack::Unwinder* unw
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dump_abort_message(Tombstone* tombstone, unwindstack::Unwinder* unwinder,
|
static void dump_abort_message(Tombstone* tombstone,
|
||||||
|
std::shared_ptr<unwindstack::Memory>& process_memory,
|
||||||
const ProcessInfo& process_info) {
|
const ProcessInfo& process_info) {
|
||||||
std::shared_ptr<unwindstack::Memory> process_memory = unwinder->GetProcessMemory();
|
|
||||||
uintptr_t address = process_info.abort_msg_address;
|
uintptr_t address = process_info.abort_msg_address;
|
||||||
if (address == 0) {
|
if (address == 0) {
|
||||||
return;
|
return;
|
||||||
|
|
@ -348,7 +349,7 @@ void fill_in_backtrace_frame(BacktraceFrame* f, const unwindstack::FrameData& fr
|
||||||
f->set_build_id(frame.map_info->GetPrintableBuildID());
|
f->set_build_id(frame.map_info->GetPrintableBuildID());
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dump_registers(unwindstack::Unwinder* unwinder,
|
static void dump_registers(unwindstack::AndroidUnwinder* unwinder,
|
||||||
const std::unique_ptr<unwindstack::Regs>& regs, Thread& thread,
|
const std::unique_ptr<unwindstack::Regs>& regs, Thread& thread,
|
||||||
bool memory_dump) {
|
bool memory_dump) {
|
||||||
if (regs == nullptr) {
|
if (regs == nullptr) {
|
||||||
|
|
@ -402,27 +403,9 @@ static void dump_registers(unwindstack::Unwinder* unwinder,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
static void log_unwinder_error(unwindstack::Unwinder* unwinder) {
|
static void dump_thread_backtrace(std::vector<unwindstack::FrameData>& frames, Thread& thread) {
|
||||||
if (unwinder->LastErrorCode() == unwindstack::ERROR_NONE) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
async_safe_format_log(ANDROID_LOG_ERROR, LOG_TAG, " error code: %s",
|
|
||||||
unwinder->LastErrorCodeString());
|
|
||||||
async_safe_format_log(ANDROID_LOG_ERROR, LOG_TAG, " error address: 0x%" PRIx64,
|
|
||||||
unwinder->LastErrorAddress());
|
|
||||||
}
|
|
||||||
|
|
||||||
static void dump_thread_backtrace(unwindstack::Unwinder* unwinder, Thread& thread) {
|
|
||||||
if (unwinder->NumFrames() == 0) {
|
|
||||||
async_safe_format_log(ANDROID_LOG_ERROR, LOG_TAG, "failed to unwind");
|
|
||||||
log_unwinder_error(unwinder);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
unwinder->SetDisplayBuildID(true);
|
|
||||||
std::set<std::string> unreadable_elf_files;
|
std::set<std::string> unreadable_elf_files;
|
||||||
for (const auto& frame : unwinder->frames()) {
|
for (const auto& frame : frames) {
|
||||||
BacktraceFrame* f = thread.add_current_backtrace();
|
BacktraceFrame* f = thread.add_current_backtrace();
|
||||||
fill_in_backtrace_frame(f, frame);
|
fill_in_backtrace_frame(f, frame);
|
||||||
if (frame.map_info != nullptr && frame.map_info->ElfFileNotReadable()) {
|
if (frame.map_info != nullptr && frame.map_info->ElfFileNotReadable()) {
|
||||||
|
|
@ -446,7 +429,7 @@ static void dump_thread_backtrace(unwindstack::Unwinder* unwinder, Thread& threa
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dump_thread(Tombstone* tombstone, unwindstack::Unwinder* unwinder,
|
static void dump_thread(Tombstone* tombstone, unwindstack::AndroidUnwinder* unwinder,
|
||||||
const ThreadInfo& thread_info, bool memory_dump = false) {
|
const ThreadInfo& thread_info, bool memory_dump = false) {
|
||||||
Thread thread;
|
Thread thread;
|
||||||
|
|
||||||
|
|
@ -455,36 +438,29 @@ static void dump_thread(Tombstone* tombstone, unwindstack::Unwinder* unwinder,
|
||||||
thread.set_tagged_addr_ctrl(thread_info.tagged_addr_ctrl);
|
thread.set_tagged_addr_ctrl(thread_info.tagged_addr_ctrl);
|
||||||
thread.set_pac_enabled_keys(thread_info.pac_enabled_keys);
|
thread.set_pac_enabled_keys(thread_info.pac_enabled_keys);
|
||||||
|
|
||||||
if (thread_info.pid == getpid() && thread_info.pid != thread_info.tid) {
|
unwindstack::AndroidUnwinderData data;
|
||||||
// Fallback path for non-main thread, doing unwind from running process.
|
// Indicate we want a copy of the initial registers.
|
||||||
unwindstack::ThreadUnwinder thread_unwinder(kMaxFrames, unwinder->GetMaps());
|
data.saved_initial_regs = std::make_optional<std::unique_ptr<unwindstack::Regs>>();
|
||||||
if (!thread_unwinder.Init()) {
|
bool unwind_ret;
|
||||||
async_safe_format_log(ANDROID_LOG_ERROR, LOG_TAG,
|
if (thread_info.registers != nullptr) {
|
||||||
"Unable to initialize ThreadUnwinder object.");
|
unwind_ret = unwinder->Unwind(thread_info.registers.get(), data);
|
||||||
log_unwinder_error(&thread_unwinder);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::unique_ptr<unwindstack::Regs> initial_regs;
|
|
||||||
thread_unwinder.UnwindWithSignal(BIONIC_SIGNAL_BACKTRACE, thread_info.tid, &initial_regs);
|
|
||||||
dump_registers(&thread_unwinder, initial_regs, thread, memory_dump);
|
|
||||||
dump_thread_backtrace(&thread_unwinder, thread);
|
|
||||||
} else {
|
} else {
|
||||||
dump_registers(unwinder, thread_info.registers, thread, memory_dump);
|
unwind_ret = unwinder->Unwind(thread_info.tid, data);
|
||||||
std::unique_ptr<unwindstack::Regs> regs_copy(thread_info.registers->Clone());
|
|
||||||
unwinder->SetRegs(regs_copy.get());
|
|
||||||
unwinder->Unwind();
|
|
||||||
dump_thread_backtrace(unwinder, thread);
|
|
||||||
}
|
}
|
||||||
|
if (!unwind_ret) {
|
||||||
|
async_safe_format_log(ANDROID_LOG_ERROR, LOG_TAG, "Unwind failed for tid %d: Error %s",
|
||||||
|
thread_info.tid, data.GetErrorString().c_str());
|
||||||
|
} else {
|
||||||
|
dump_thread_backtrace(data.frames, thread);
|
||||||
|
}
|
||||||
|
dump_registers(unwinder, *data.saved_initial_regs, thread, memory_dump);
|
||||||
|
|
||||||
auto& threads = *tombstone->mutable_threads();
|
auto& threads = *tombstone->mutable_threads();
|
||||||
threads[thread_info.tid] = thread;
|
threads[thread_info.tid] = thread;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dump_mappings(Tombstone* tombstone, unwindstack::Unwinder* unwinder) {
|
static void dump_mappings(Tombstone* tombstone, unwindstack::Maps* maps,
|
||||||
unwindstack::Maps* maps = unwinder->GetMaps();
|
std::shared_ptr<unwindstack::Memory>& process_memory) {
|
||||||
std::shared_ptr<unwindstack::Memory> process_memory = unwinder->GetProcessMemory();
|
|
||||||
|
|
||||||
for (const auto& map_info : *maps) {
|
for (const auto& map_info : *maps) {
|
||||||
auto* map = tombstone->add_memory_mappings();
|
auto* map = tombstone->add_memory_mappings();
|
||||||
map->set_begin_address(map_info->start());
|
map->set_begin_address(map_info->start());
|
||||||
|
|
@ -593,7 +569,8 @@ static void dump_logcat(Tombstone* tombstone, pid_t pid) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dump_tags_around_fault_addr(Signal* signal, const Tombstone& tombstone,
|
static void dump_tags_around_fault_addr(Signal* signal, const Tombstone& tombstone,
|
||||||
unwindstack::Unwinder* unwinder, uintptr_t fault_addr) {
|
std::shared_ptr<unwindstack::Memory>& process_memory,
|
||||||
|
uintptr_t fault_addr) {
|
||||||
if (tombstone.arch() != Architecture::ARM64) return;
|
if (tombstone.arch() != Architecture::ARM64) return;
|
||||||
|
|
||||||
fault_addr = untag_address(fault_addr);
|
fault_addr = untag_address(fault_addr);
|
||||||
|
|
@ -604,8 +581,6 @@ static void dump_tags_around_fault_addr(Signal* signal, const Tombstone& tombsto
|
||||||
// a valid address for us to dump tags from.
|
// a valid address for us to dump tags from.
|
||||||
if (fault_addr < kBytesToRead / 2) return;
|
if (fault_addr < kBytesToRead / 2) return;
|
||||||
|
|
||||||
unwindstack::Memory* memory = unwinder->GetProcessMemory().get();
|
|
||||||
|
|
||||||
constexpr uintptr_t kRowStartMask = ~(kNumTagColumns * kTagGranuleSize - 1);
|
constexpr uintptr_t kRowStartMask = ~(kNumTagColumns * kTagGranuleSize - 1);
|
||||||
size_t start_address = (fault_addr & kRowStartMask) - kBytesToRead / 2;
|
size_t start_address = (fault_addr & kRowStartMask) - kBytesToRead / 2;
|
||||||
MemoryDump tag_dump;
|
MemoryDump tag_dump;
|
||||||
|
|
@ -614,7 +589,7 @@ static void dump_tags_around_fault_addr(Signal* signal, const Tombstone& tombsto
|
||||||
// Attempt to read the first tag. If reading fails, this likely indicates the
|
// Attempt to read the first tag. If reading fails, this likely indicates the
|
||||||
// lowest touched page is inaccessible or not marked with PROT_MTE.
|
// lowest touched page is inaccessible or not marked with PROT_MTE.
|
||||||
// Fast-forward over pages until one has tags, or we exhaust the search range.
|
// Fast-forward over pages until one has tags, or we exhaust the search range.
|
||||||
while (memory->ReadTag(start_address) < 0) {
|
while (process_memory->ReadTag(start_address) < 0) {
|
||||||
size_t page_size = sysconf(_SC_PAGE_SIZE);
|
size_t page_size = sysconf(_SC_PAGE_SIZE);
|
||||||
size_t bytes_to_next_page = page_size - (start_address % page_size);
|
size_t bytes_to_next_page = page_size - (start_address % page_size);
|
||||||
if (bytes_to_next_page >= granules_to_read * kTagGranuleSize) return;
|
if (bytes_to_next_page >= granules_to_read * kTagGranuleSize) return;
|
||||||
|
|
@ -626,7 +601,7 @@ static void dump_tags_around_fault_addr(Signal* signal, const Tombstone& tombsto
|
||||||
std::string* mte_tags = tag_dump.mutable_arm_mte_metadata()->mutable_memory_tags();
|
std::string* mte_tags = tag_dump.mutable_arm_mte_metadata()->mutable_memory_tags();
|
||||||
|
|
||||||
for (size_t i = 0; i < granules_to_read; ++i) {
|
for (size_t i = 0; i < granules_to_read; ++i) {
|
||||||
long tag = memory->ReadTag(start_address + i * kTagGranuleSize);
|
long tag = process_memory->ReadTag(start_address + i * kTagGranuleSize);
|
||||||
if (tag < 0) break;
|
if (tag < 0) break;
|
||||||
mte_tags->push_back(static_cast<uint8_t>(tag));
|
mte_tags->push_back(static_cast<uint8_t>(tag));
|
||||||
}
|
}
|
||||||
|
|
@ -636,7 +611,7 @@ static void dump_tags_around_fault_addr(Signal* signal, const Tombstone& tombsto
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void engrave_tombstone_proto(Tombstone* tombstone, unwindstack::Unwinder* unwinder,
|
void engrave_tombstone_proto(Tombstone* tombstone, unwindstack::AndroidUnwinder* unwinder,
|
||||||
const std::map<pid_t, ThreadInfo>& threads, pid_t target_thread,
|
const std::map<pid_t, ThreadInfo>& threads, pid_t target_thread,
|
||||||
const ProcessInfo& process_info, const OpenFilesList* open_files) {
|
const ProcessInfo& process_info, const OpenFilesList* open_files) {
|
||||||
Tombstone result;
|
Tombstone result;
|
||||||
|
|
@ -691,12 +666,12 @@ void engrave_tombstone_proto(Tombstone* tombstone, unwindstack::Unwinder* unwind
|
||||||
sig.set_has_fault_address(true);
|
sig.set_has_fault_address(true);
|
||||||
uintptr_t fault_addr = process_info.maybe_tagged_fault_address;
|
uintptr_t fault_addr = process_info.maybe_tagged_fault_address;
|
||||||
sig.set_fault_address(fault_addr);
|
sig.set_fault_address(fault_addr);
|
||||||
dump_tags_around_fault_addr(&sig, result, unwinder, fault_addr);
|
dump_tags_around_fault_addr(&sig, result, unwinder->GetProcessMemory(), fault_addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
*result.mutable_signal_info() = sig;
|
*result.mutable_signal_info() = sig;
|
||||||
|
|
||||||
dump_abort_message(&result, unwinder, process_info);
|
dump_abort_message(&result, unwinder->GetProcessMemory(), process_info);
|
||||||
|
|
||||||
// Dump the main thread, but save the memory around the registers.
|
// Dump the main thread, but save the memory around the registers.
|
||||||
dump_thread(&result, unwinder, main_thread, /* memory_dump */ true);
|
dump_thread(&result, unwinder, main_thread, /* memory_dump */ true);
|
||||||
|
|
@ -709,7 +684,7 @@ void engrave_tombstone_proto(Tombstone* tombstone, unwindstack::Unwinder* unwind
|
||||||
|
|
||||||
dump_probable_cause(&result, unwinder, process_info, main_thread);
|
dump_probable_cause(&result, unwinder, process_info, main_thread);
|
||||||
|
|
||||||
dump_mappings(&result, unwinder);
|
dump_mappings(&result, unwinder->GetMaps(), unwinder->GetProcessMemory());
|
||||||
|
|
||||||
// Only dump logs on debuggable devices.
|
// Only dump logs on debuggable devices.
|
||||||
if (android::base::GetBoolProperty("ro.debuggable", false)) {
|
if (android::base::GetBoolProperty("ro.debuggable", false)) {
|
||||||
|
|
|
||||||
|
|
@ -39,6 +39,7 @@
|
||||||
#include <bionic/reserved_signals.h>
|
#include <bionic/reserved_signals.h>
|
||||||
#include <debuggerd/handler.h>
|
#include <debuggerd/handler.h>
|
||||||
#include <log/log.h>
|
#include <log/log.h>
|
||||||
|
#include <unwindstack/AndroidUnwinder.h>
|
||||||
#include <unwindstack/Memory.h>
|
#include <unwindstack/Memory.h>
|
||||||
#include <unwindstack/Unwinder.h>
|
#include <unwindstack/Unwinder.h>
|
||||||
|
|
||||||
|
|
@ -483,10 +484,10 @@ std::string describe_pac_enabled_keys(long value) {
|
||||||
return describe_end(value, desc);
|
return describe_end(value, desc);
|
||||||
}
|
}
|
||||||
|
|
||||||
void log_backtrace(log_t* log, unwindstack::Unwinder* unwinder, const char* prefix) {
|
void log_backtrace(log_t* log, unwindstack::AndroidUnwinder* unwinder,
|
||||||
|
unwindstack::AndroidUnwinderData& data, const char* prefix) {
|
||||||
std::set<std::string> unreadable_elf_files;
|
std::set<std::string> unreadable_elf_files;
|
||||||
unwinder->SetDisplayBuildID(true);
|
for (const auto& frame : data.frames) {
|
||||||
for (const auto& frame : unwinder->frames()) {
|
|
||||||
if (frame.map_info != nullptr && frame.map_info->ElfFileNotReadable()) {
|
if (frame.map_info != nullptr && frame.map_info->ElfFileNotReadable()) {
|
||||||
unreadable_elf_files.emplace(frame.map_info->name());
|
unreadable_elf_files.emplace(frame.map_info->name());
|
||||||
}
|
}
|
||||||
|
|
@ -509,7 +510,7 @@ void log_backtrace(log_t* log, unwindstack::Unwinder* unwinder, const char* pref
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const auto& frame : unwinder->frames()) {
|
for (const auto& frame : data.frames) {
|
||||||
_LOG(log, logtype::BACKTRACE, "%s%s\n", prefix, unwinder->FormatFrame(frame).c_str());
|
_LOG(log, logtype::BACKTRACE, "%s%s\n", prefix, unwinder->FormatFrame(frame).c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue