Merge "Change all uintptr_t to uint64_t in API."
am: e20b4a48fe
Change-Id: Id0bb2e33e87a6889ded796fc29fdb6a273d4c5ff
This commit is contained in:
commit
b5ca867bd5
|
@ -40,16 +40,16 @@ int open_tombstone(std::string* path);
|
|||
/* Creates a tombstone file and writes the crash dump to it. */
|
||||
void engrave_tombstone(int tombstone_fd, BacktraceMap* map, const OpenFilesList* open_files,
|
||||
pid_t pid, pid_t tid, const std::string& process_name,
|
||||
const std::map<pid_t, std::string>& threads, uintptr_t abort_msg_address,
|
||||
const std::map<pid_t, std::string>& threads, uint64_t abort_msg_address,
|
||||
std::string* amfd_data);
|
||||
|
||||
void engrave_tombstone_ucontext(int tombstone_fd, uintptr_t abort_msg_address, siginfo_t* siginfo,
|
||||
void engrave_tombstone_ucontext(int tombstone_fd, uint64_t abort_msg_address, siginfo_t* siginfo,
|
||||
ucontext_t* ucontext);
|
||||
|
||||
void engrave_tombstone(android::base::unique_fd output_fd, BacktraceMap* map,
|
||||
unwindstack::Memory* process_memory,
|
||||
const std::map<pid_t, ThreadInfo>& thread_info, pid_t target_thread,
|
||||
uintptr_t abort_msg_address, OpenFilesList* open_files,
|
||||
uint64_t abort_msg_address, OpenFilesList* open_files,
|
||||
std::string* amfd_data);
|
||||
|
||||
#endif // _DEBUGGERD_TOMBSTONE_H
|
||||
|
|
|
@ -68,7 +68,7 @@ namespace unwindstack {
|
|||
class Memory;
|
||||
}
|
||||
|
||||
void dump_memory(log_t* log, unwindstack::Memory* backtrace, uintptr_t addr, const char* fmt, ...);
|
||||
void dump_memory(log_t* log, unwindstack::Memory* backtrace, uint64_t addr, const char* fmt, ...);
|
||||
|
||||
void read_with_default(const char* path, char* buf, size_t len, const char* default_value);
|
||||
|
||||
|
|
|
@ -437,9 +437,9 @@ TEST_F(TombstoneTest, multiple_maps_fault_address_after) {
|
|||
map_mock_->AddMap(map);
|
||||
|
||||
#if defined(__LP64__)
|
||||
uintptr_t addr = 0x12345a534040UL;
|
||||
uint64_t addr = 0x12345a534040UL;
|
||||
#else
|
||||
uintptr_t addr = 0xf534040UL;
|
||||
uint64_t addr = 0xf534040UL;
|
||||
#endif
|
||||
dump_all_maps(&log_, map_mock_.get(), nullptr, addr);
|
||||
|
||||
|
|
|
@ -127,7 +127,7 @@ static void dump_thread_info(log_t* log, const ThreadInfo& thread_info) {
|
|||
}
|
||||
|
||||
static void dump_stack_segment(log_t* log, BacktraceMap* backtrace_map, Memory* process_memory,
|
||||
uintptr_t* sp, size_t words, int label) {
|
||||
uint64_t* sp, size_t words, int label) {
|
||||
// Read the data all at once.
|
||||
word_t stack_data[words];
|
||||
|
||||
|
@ -144,18 +144,18 @@ static void dump_stack_segment(log_t* log, BacktraceMap* backtrace_map, Memory*
|
|||
} else {
|
||||
line += " ";
|
||||
}
|
||||
line += StringPrintf("%" PRIPTR " %" PRIPTR, *sp, stack_data[i]);
|
||||
line += StringPrintf("%" PRIPTR " %" PRIxPTR, *sp, stack_data[i]);
|
||||
|
||||
backtrace_map_t map;
|
||||
backtrace_map->FillIn(stack_data[i], &map);
|
||||
if (BacktraceMap::IsValid(map) && !map.name.empty()) {
|
||||
line += " " + map.name;
|
||||
uintptr_t offset = 0;
|
||||
uint64_t offset = 0;
|
||||
std::string func_name = backtrace_map->GetFunctionName(stack_data[i], &offset);
|
||||
if (!func_name.empty()) {
|
||||
line += " (" + func_name;
|
||||
if (offset) {
|
||||
line += StringPrintf("+%" PRIuPTR, offset);
|
||||
line += StringPrintf("+%" PRIu64, offset);
|
||||
}
|
||||
line += ')';
|
||||
}
|
||||
|
@ -185,7 +185,7 @@ static void dump_stack(log_t* log, BacktraceMap* backtrace_map, Memory* process_
|
|||
first--;
|
||||
|
||||
// Dump a few words before the first frame.
|
||||
word_t sp = frames[first].sp - STACK_WORDS * sizeof(word_t);
|
||||
uint64_t sp = frames[first].sp - STACK_WORDS * sizeof(word_t);
|
||||
dump_stack_segment(log, backtrace_map, process_memory, &sp, STACK_WORDS, -1);
|
||||
|
||||
// Dump a few words from all successive frames.
|
||||
|
@ -213,19 +213,19 @@ static void dump_stack(log_t* log, BacktraceMap* backtrace_map, Memory* process_
|
|||
}
|
||||
}
|
||||
|
||||
static std::string get_addr_string(uintptr_t addr) {
|
||||
static std::string get_addr_string(uint64_t addr) {
|
||||
std::string addr_str;
|
||||
#if defined(__LP64__)
|
||||
addr_str = StringPrintf("%08x'%08x",
|
||||
static_cast<uint32_t>(addr >> 32),
|
||||
static_cast<uint32_t>(addr & 0xffffffff));
|
||||
#else
|
||||
addr_str = StringPrintf("%08x", addr);
|
||||
addr_str = StringPrintf("%08x", static_cast<uint32_t>(addr));
|
||||
#endif
|
||||
return addr_str;
|
||||
}
|
||||
|
||||
static void dump_abort_message(log_t* log, Memory* process_memory, uintptr_t address) {
|
||||
static void dump_abort_message(log_t* log, Memory* process_memory, uint64_t address) {
|
||||
if (address == 0) {
|
||||
return;
|
||||
}
|
||||
|
@ -251,7 +251,7 @@ static void dump_abort_message(log_t* log, Memory* process_memory, uintptr_t add
|
|||
_LOG(log, logtype::HEADER, "Abort message: '%s'\n", msg);
|
||||
}
|
||||
|
||||
static void dump_all_maps(log_t* log, BacktraceMap* map, Memory* process_memory, uintptr_t addr) {
|
||||
static void dump_all_maps(log_t* log, BacktraceMap* map, Memory* process_memory, uint64_t addr) {
|
||||
bool print_fault_address_marker = addr;
|
||||
|
||||
ScopedBacktraceMapIteratorLock lock(map);
|
||||
|
@ -301,7 +301,7 @@ static void dump_all_maps(log_t* log, BacktraceMap* map, Memory* process_memory,
|
|||
} else {
|
||||
line += '-';
|
||||
}
|
||||
line += StringPrintf(" %8" PRIxPTR " %8" PRIxPTR, entry->offset, entry->end - entry->start);
|
||||
line += StringPrintf(" %8" PRIx64 " %8" PRIx64, entry->offset, entry->end - entry->start);
|
||||
bool space_needed = true;
|
||||
if (entry->name.length() > 0) {
|
||||
space_needed = false;
|
||||
|
@ -315,7 +315,7 @@ static void dump_all_maps(log_t* log, BacktraceMap* map, Memory* process_memory,
|
|||
if (space_needed) {
|
||||
line += ' ';
|
||||
}
|
||||
line += StringPrintf(" (load bias 0x%" PRIxPTR ")", entry->load_bias);
|
||||
line += StringPrintf(" (load bias 0x%" PRIx64 ")", entry->load_bias);
|
||||
}
|
||||
_LOG(log, logtype::MAPS, "%s\n", line.c_str());
|
||||
}
|
||||
|
@ -335,9 +335,9 @@ static void print_register_row(log_t* log,
|
|||
const std::vector<std::pair<std::string, uint64_t>>& registers) {
|
||||
std::string output;
|
||||
for (auto& [name, value] : registers) {
|
||||
output += android::base::StringPrintf(" %-3s %0*" PRIxPTR, name.c_str(),
|
||||
output += android::base::StringPrintf(" %-3s %0*" PRIx64, name.c_str(),
|
||||
static_cast<int>(2 * sizeof(void*)),
|
||||
static_cast<uintptr_t>(value));
|
||||
static_cast<uint64_t>(value));
|
||||
}
|
||||
|
||||
_LOG(log, logtype::REGISTERS, " %s\n", output.c_str());
|
||||
|
@ -389,7 +389,7 @@ void dump_memory_and_code(log_t* log, Memory* memory, Regs* regs) {
|
|||
}
|
||||
|
||||
static bool dump_thread(log_t* log, BacktraceMap* map, Memory* process_memory,
|
||||
const ThreadInfo& thread_info, uintptr_t abort_msg_address,
|
||||
const ThreadInfo& thread_info, uint64_t abort_msg_address,
|
||||
bool primary_thread) {
|
||||
UNUSED(process_memory);
|
||||
log->current_tid = thread_info.tid;
|
||||
|
@ -425,10 +425,10 @@ static bool dump_thread(log_t* log, BacktraceMap* map, Memory* process_memory,
|
|||
if (primary_thread) {
|
||||
dump_memory_and_code(log, process_memory, thread_info.registers.get());
|
||||
if (map) {
|
||||
uintptr_t addr = 0;
|
||||
uint64_t addr = 0;
|
||||
siginfo_t* si = thread_info.siginfo;
|
||||
if (signal_has_si_addr(si->si_signo, si->si_code)) {
|
||||
addr = reinterpret_cast<uintptr_t>(si->si_addr);
|
||||
addr = reinterpret_cast<uint64_t>(si->si_addr);
|
||||
}
|
||||
dump_all_maps(log, map, process_memory, addr);
|
||||
}
|
||||
|
@ -572,7 +572,7 @@ static void dump_logs(log_t* log, pid_t pid, unsigned int tail) {
|
|||
dump_log_file(log, pid, "main", tail);
|
||||
}
|
||||
|
||||
void engrave_tombstone_ucontext(int tombstone_fd, uintptr_t abort_msg_address, siginfo_t* siginfo,
|
||||
void engrave_tombstone_ucontext(int tombstone_fd, uint64_t abort_msg_address, siginfo_t* siginfo,
|
||||
ucontext_t* ucontext) {
|
||||
pid_t pid = getpid();
|
||||
pid_t tid = gettid();
|
||||
|
@ -614,7 +614,7 @@ void engrave_tombstone_ucontext(int tombstone_fd, uintptr_t abort_msg_address, s
|
|||
|
||||
void engrave_tombstone(unique_fd output_fd, BacktraceMap* map, Memory* process_memory,
|
||||
const std::map<pid_t, ThreadInfo>& threads, pid_t target_thread,
|
||||
uintptr_t abort_msg_address, OpenFilesList* open_files,
|
||||
uint64_t abort_msg_address, OpenFilesList* open_files,
|
||||
std::string* amfd_data) {
|
||||
// don't copy log messages to tombstone unless this is a dev device
|
||||
bool want_logs = android::base::GetBoolProperty("ro.debuggable", false);
|
||||
|
|
|
@ -124,7 +124,7 @@ void _LOG(log_t* log, enum logtype ltype, const char* fmt, ...) {
|
|||
#define MEMORY_BYTES_TO_DUMP 256
|
||||
#define MEMORY_BYTES_PER_LINE 16
|
||||
|
||||
void dump_memory(log_t* log, unwindstack::Memory* memory, uintptr_t addr, const char* fmt, ...) {
|
||||
void dump_memory(log_t* log, unwindstack::Memory* memory, uint64_t addr, const char* fmt, ...) {
|
||||
std::string log_msg;
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
|
@ -159,7 +159,7 @@ void dump_memory(log_t* log, unwindstack::Memory* memory, uintptr_t addr, const
|
|||
bytes &= ~(sizeof(uintptr_t) - 1);
|
||||
}
|
||||
|
||||
uintptr_t start = 0;
|
||||
uint64_t start = 0;
|
||||
bool skip_2nd_read = false;
|
||||
if (bytes == 0) {
|
||||
// In this case, we might want to try another read at the beginning of
|
||||
|
@ -206,7 +206,7 @@ void dump_memory(log_t* log, unwindstack::Memory* memory, uintptr_t addr, const
|
|||
std::string ascii;
|
||||
for (size_t i = 0; i < MEMORY_BYTES_PER_LINE / sizeof(uintptr_t); i++) {
|
||||
if (current >= start && current + sizeof(uintptr_t) <= total_bytes) {
|
||||
android::base::StringAppendF(&logline, " %" PRIPTR, *data_ptr);
|
||||
android::base::StringAppendF(&logline, " %" PRIPTR, static_cast<uint64_t>(*data_ptr));
|
||||
|
||||
// Fill out the ascii string from the data.
|
||||
uint8_t* ptr = reinterpret_cast<uint8_t*>(data_ptr);
|
||||
|
|
|
@ -50,9 +50,6 @@ libbacktrace_sources = [
|
|||
"BacktracePtrace.cpp",
|
||||
"thread_utils.c",
|
||||
"ThreadEntry.cpp",
|
||||
"UnwindCurrent.cpp",
|
||||
"UnwindMap.cpp",
|
||||
"UnwindPtrace.cpp",
|
||||
"UnwindStack.cpp",
|
||||
"UnwindStackMap.cpp",
|
||||
]
|
||||
|
|
|
@ -30,8 +30,6 @@
|
|||
#include <demangle.h>
|
||||
|
||||
#include "BacktraceLog.h"
|
||||
#include "UnwindCurrent.h"
|
||||
#include "UnwindPtrace.h"
|
||||
#include "UnwindStack.h"
|
||||
#include "thread_utils.h"
|
||||
|
||||
|
@ -55,7 +53,7 @@ Backtrace::~Backtrace() {
|
|||
}
|
||||
}
|
||||
|
||||
std::string Backtrace::GetFunctionName(uintptr_t pc, uintptr_t* offset, const backtrace_map_t* map) {
|
||||
std::string Backtrace::GetFunctionName(uint64_t pc, uint64_t* offset, const backtrace_map_t* map) {
|
||||
backtrace_map_t map_value;
|
||||
if (map == nullptr) {
|
||||
FillInMap(pc, &map_value);
|
||||
|
@ -68,7 +66,7 @@ std::string Backtrace::GetFunctionName(uintptr_t pc, uintptr_t* offset, const ba
|
|||
return demangle(GetFunctionNameRaw(pc, offset).c_str());
|
||||
}
|
||||
|
||||
bool Backtrace::VerifyReadWordArgs(uintptr_t ptr, word_t* out_value) {
|
||||
bool Backtrace::VerifyReadWordArgs(uint64_t ptr, word_t* out_value) {
|
||||
if (ptr & (sizeof(word_t)-1)) {
|
||||
BACK_LOGW("invalid pointer %p", reinterpret_cast<void*>(ptr));
|
||||
*out_value = static_cast<word_t>(-1);
|
||||
|
@ -105,12 +103,12 @@ std::string Backtrace::FormatFrameData(const backtrace_frame_data_t* frame) {
|
|||
// Special handling for non-zero offset maps, we need to print that
|
||||
// information.
|
||||
if (frame->map.offset != 0) {
|
||||
line += " (offset " + StringPrintf("0x%" PRIxPTR, frame->map.offset) + ")";
|
||||
line += " (offset " + StringPrintf("0x%" PRIx64, frame->map.offset) + ")";
|
||||
}
|
||||
if (!frame->func_name.empty()) {
|
||||
line += " (" + frame->func_name;
|
||||
if (frame->func_offset) {
|
||||
line += StringPrintf("+%" PRIuPTR, frame->func_offset);
|
||||
line += StringPrintf("+%" PRIu64, frame->func_offset);
|
||||
}
|
||||
line += ')';
|
||||
}
|
||||
|
@ -118,7 +116,7 @@ std::string Backtrace::FormatFrameData(const backtrace_frame_data_t* frame) {
|
|||
return line;
|
||||
}
|
||||
|
||||
void Backtrace::FillInMap(uintptr_t pc, backtrace_map_t* map) {
|
||||
void Backtrace::FillInMap(uint64_t pc, backtrace_map_t* map) {
|
||||
if (map_ != nullptr) {
|
||||
map_->FillIn(pc, map);
|
||||
}
|
||||
|
|
|
@ -36,7 +36,7 @@
|
|||
#include "ThreadEntry.h"
|
||||
#include "thread_utils.h"
|
||||
|
||||
bool BacktraceCurrent::ReadWord(uintptr_t ptr, word_t* out_value) {
|
||||
bool BacktraceCurrent::ReadWord(uint64_t ptr, word_t* out_value) {
|
||||
if (!VerifyReadWordArgs(ptr, out_value)) {
|
||||
return false;
|
||||
}
|
||||
|
@ -53,7 +53,7 @@ bool BacktraceCurrent::ReadWord(uintptr_t ptr, word_t* out_value) {
|
|||
}
|
||||
}
|
||||
|
||||
size_t BacktraceCurrent::Read(uintptr_t addr, uint8_t* buffer, size_t bytes) {
|
||||
size_t BacktraceCurrent::Read(uint64_t addr, uint8_t* buffer, size_t bytes) {
|
||||
backtrace_map_t map;
|
||||
FillInMap(addr, &map);
|
||||
if (!BacktraceMap::IsValid(map) || !(map.flags & PROT_READ)) {
|
||||
|
|
|
@ -40,9 +40,9 @@ class BacktraceCurrent : public Backtrace {
|
|||
BacktraceCurrent(pid_t pid, pid_t tid, BacktraceMap* map) : Backtrace(pid, tid, map) {}
|
||||
virtual ~BacktraceCurrent() {}
|
||||
|
||||
size_t Read(uintptr_t addr, uint8_t* buffer, size_t bytes) override;
|
||||
size_t Read(uint64_t addr, uint8_t* buffer, size_t bytes) override;
|
||||
|
||||
bool ReadWord(uintptr_t ptr, word_t* out_value) override;
|
||||
bool ReadWord(uint64_t ptr, word_t* out_value) override;
|
||||
|
||||
bool Unwind(size_t num_ignore_frames, ucontext_t* ucontext) override;
|
||||
|
||||
|
|
|
@ -38,7 +38,7 @@ BacktraceMap::BacktraceMap(pid_t pid) : pid_(pid) {
|
|||
BacktraceMap::~BacktraceMap() {
|
||||
}
|
||||
|
||||
void BacktraceMap::FillIn(uintptr_t addr, backtrace_map_t* map) {
|
||||
void BacktraceMap::FillIn(uint64_t addr, backtrace_map_t* map) {
|
||||
ScopedBacktraceMapIteratorLock lock(this);
|
||||
for (auto it = begin(); it != end(); ++it) {
|
||||
const backtrace_map_t* entry = *it;
|
||||
|
|
|
@ -57,7 +57,7 @@ struct EhFrame {
|
|||
uint64_t hdr_vaddr;
|
||||
uint64_t vaddr;
|
||||
uint64_t fde_table_offset;
|
||||
uintptr_t min_func_vaddr;
|
||||
uint64_t min_func_vaddr;
|
||||
std::vector<uint8_t> hdr_data;
|
||||
std::vector<uint8_t> data;
|
||||
};
|
||||
|
@ -221,8 +221,8 @@ bool BacktraceOffline::Unwind(size_t num_ignore_frames, ucontext_t* context) {
|
|||
frames_.resize(num_frames + 1);
|
||||
backtrace_frame_data_t* frame = &frames_[num_frames];
|
||||
frame->num = num_frames;
|
||||
frame->pc = static_cast<uintptr_t>(pc);
|
||||
frame->sp = static_cast<uintptr_t>(sp);
|
||||
frame->pc = static_cast<uint64_t>(pc);
|
||||
frame->sp = static_cast<uint64_t>(sp);
|
||||
frame->stack_size = 0;
|
||||
|
||||
if (num_frames > 0) {
|
||||
|
@ -253,12 +253,12 @@ bool BacktraceOffline::Unwind(size_t num_ignore_frames, ucontext_t* context) {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool BacktraceOffline::ReadWord(uintptr_t ptr, word_t* out_value) {
|
||||
bool BacktraceOffline::ReadWord(uint64_t ptr, word_t* out_value) {
|
||||
size_t bytes_read = Read(ptr, reinterpret_cast<uint8_t*>(out_value), sizeof(word_t));
|
||||
return bytes_read == sizeof(word_t);
|
||||
}
|
||||
|
||||
size_t BacktraceOffline::Read(uintptr_t addr, uint8_t* buffer, size_t bytes) {
|
||||
size_t BacktraceOffline::Read(uint64_t addr, uint8_t* buffer, size_t bytes) {
|
||||
// Normally, libunwind needs stack information and call frame information to do remote unwinding.
|
||||
// If call frame information is stored in .debug_frame, libunwind can read it from file
|
||||
// by itself. If call frame information is stored in .eh_frame, we need to provide data in
|
||||
|
@ -386,9 +386,8 @@ bool BacktraceOffline::FindProcInfo(unw_addr_space_t addr_space, uint64_t ip,
|
|||
proc_info->start_ip = *it;
|
||||
proc_info->format = UNW_INFO_FORMAT_ARM_EXIDX;
|
||||
proc_info->unwind_info = reinterpret_cast<void*>(
|
||||
static_cast<uintptr_t>(index * sizeof(ArmIdxEntry) +
|
||||
debug_frame->arm_exidx.exidx_vaddr +
|
||||
debug_frame->min_vaddr));
|
||||
static_cast<uint64_t>(index * sizeof(ArmIdxEntry) + debug_frame->arm_exidx.exidx_vaddr +
|
||||
debug_frame->min_vaddr));
|
||||
eh_frame_hdr_space_.Clear();
|
||||
eh_frame_space_.Clear();
|
||||
// Prepare arm_exidx space and arm_extab space.
|
||||
|
@ -595,7 +594,7 @@ bool BacktraceOffline::ReadReg(size_t reg, uint64_t* value) {
|
|||
return result;
|
||||
}
|
||||
|
||||
std::string BacktraceOffline::GetFunctionNameRaw(uintptr_t, uintptr_t* offset) {
|
||||
std::string BacktraceOffline::GetFunctionNameRaw(uint64_t, uint64_t* offset) {
|
||||
// We don't have enough information to support this. And it is expensive.
|
||||
*offset = 0;
|
||||
return "";
|
||||
|
|
|
@ -57,9 +57,9 @@ class BacktraceOffline : public Backtrace {
|
|||
|
||||
bool Unwind(size_t num_ignore_frames, ucontext_t* context) override;
|
||||
|
||||
bool ReadWord(uintptr_t ptr, word_t* out_value) override;
|
||||
bool ReadWord(uint64_t ptr, word_t* out_value) override;
|
||||
|
||||
size_t Read(uintptr_t addr, uint8_t* buffer, size_t bytes) override;
|
||||
size_t Read(uint64_t addr, uint8_t* buffer, size_t bytes) override;
|
||||
|
||||
bool FindProcInfo(unw_addr_space_t addr_space, uint64_t ip, unw_proc_info_t* proc_info,
|
||||
int need_unwind_info);
|
||||
|
@ -67,7 +67,7 @@ class BacktraceOffline : public Backtrace {
|
|||
bool ReadReg(size_t reg_index, uint64_t* value);
|
||||
|
||||
protected:
|
||||
std::string GetFunctionNameRaw(uintptr_t pc, uintptr_t* offset) override;
|
||||
std::string GetFunctionNameRaw(uint64_t pc, uint64_t* offset) override;
|
||||
DebugFrameInfo* GetDebugFrameInFile(const std::string& filename);
|
||||
|
||||
bool cache_file_;
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
#include "thread_utils.h"
|
||||
|
||||
#if !defined(__APPLE__)
|
||||
static bool PtraceRead(pid_t tid, uintptr_t addr, word_t* out_value) {
|
||||
static bool PtraceRead(pid_t tid, uint64_t addr, word_t* out_value) {
|
||||
// ptrace() returns -1 and sets errno when the operation fails.
|
||||
// To disambiguate -1 from a valid result, we clear errno beforehand.
|
||||
errno = 0;
|
||||
|
@ -43,7 +43,7 @@ static bool PtraceRead(pid_t tid, uintptr_t addr, word_t* out_value) {
|
|||
}
|
||||
#endif
|
||||
|
||||
bool BacktracePtrace::ReadWord(uintptr_t ptr, word_t* out_value) {
|
||||
bool BacktracePtrace::ReadWord(uint64_t ptr, word_t* out_value) {
|
||||
#if defined(__APPLE__)
|
||||
BACK_LOGW("MacOS does not support reading from another pid.");
|
||||
return false;
|
||||
|
@ -62,7 +62,7 @@ bool BacktracePtrace::ReadWord(uintptr_t ptr, word_t* out_value) {
|
|||
#endif
|
||||
}
|
||||
|
||||
size_t BacktracePtrace::Read(uintptr_t addr, uint8_t* buffer, size_t bytes) {
|
||||
size_t BacktracePtrace::Read(uint64_t addr, uint8_t* buffer, size_t bytes) {
|
||||
#if defined(__APPLE__)
|
||||
BACK_LOGW("MacOS does not support reading from another pid.");
|
||||
return 0;
|
||||
|
|
|
@ -29,9 +29,9 @@ class BacktracePtrace : public Backtrace {
|
|||
BacktracePtrace(pid_t pid, pid_t tid, BacktraceMap* map) : Backtrace(pid, tid, map) {}
|
||||
virtual ~BacktracePtrace() {}
|
||||
|
||||
size_t Read(uintptr_t addr, uint8_t* buffer, size_t bytes) override;
|
||||
size_t Read(uint64_t addr, uint8_t* buffer, size_t bytes) override;
|
||||
|
||||
bool ReadWord(uintptr_t ptr, word_t* out_value) override;
|
||||
bool ReadWord(uint64_t ptr, word_t* out_value) override;
|
||||
};
|
||||
|
||||
#endif // _LIBBACKTRACE_BACKTRACE_PTRACE_H
|
||||
|
|
|
@ -1,165 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 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 <stdint.h>
|
||||
#include <ucontext.h>
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#define UNW_LOCAL_ONLY
|
||||
#include <libunwind.h>
|
||||
|
||||
#include <android-base/logging.h>
|
||||
#include <backtrace/Backtrace.h>
|
||||
|
||||
#include "BacktraceLog.h"
|
||||
#include "UnwindCurrent.h"
|
||||
|
||||
std::string UnwindCurrent::GetFunctionNameRaw(uintptr_t pc, uintptr_t* offset) {
|
||||
if (!initialized_) {
|
||||
// If init local is not called, then trying to get a function name will
|
||||
// fail, so try to initialize first.
|
||||
std::unique_ptr<unw_cursor_t> cursor(new unw_cursor_t);
|
||||
if (unw_init_local(cursor.get(), &context_) < 0) {
|
||||
return "";
|
||||
}
|
||||
initialized_ = true;
|
||||
}
|
||||
|
||||
*offset = 0;
|
||||
char buf[512];
|
||||
unw_word_t value;
|
||||
if (unw_get_proc_name_by_ip(unw_local_addr_space, pc, buf, sizeof(buf),
|
||||
&value, &context_) >= 0 && buf[0] != '\0') {
|
||||
*offset = static_cast<uintptr_t>(value);
|
||||
return buf;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
void UnwindCurrent::GetUnwContextFromUcontext(const ucontext_t* ucontext) {
|
||||
unw_tdep_context_t* unw_context = reinterpret_cast<unw_tdep_context_t*>(&context_);
|
||||
|
||||
#if defined(__arm__)
|
||||
unw_context->regs[0] = ucontext->uc_mcontext.arm_r0;
|
||||
unw_context->regs[1] = ucontext->uc_mcontext.arm_r1;
|
||||
unw_context->regs[2] = ucontext->uc_mcontext.arm_r2;
|
||||
unw_context->regs[3] = ucontext->uc_mcontext.arm_r3;
|
||||
unw_context->regs[4] = ucontext->uc_mcontext.arm_r4;
|
||||
unw_context->regs[5] = ucontext->uc_mcontext.arm_r5;
|
||||
unw_context->regs[6] = ucontext->uc_mcontext.arm_r6;
|
||||
unw_context->regs[7] = ucontext->uc_mcontext.arm_r7;
|
||||
unw_context->regs[8] = ucontext->uc_mcontext.arm_r8;
|
||||
unw_context->regs[9] = ucontext->uc_mcontext.arm_r9;
|
||||
unw_context->regs[10] = ucontext->uc_mcontext.arm_r10;
|
||||
unw_context->regs[11] = ucontext->uc_mcontext.arm_fp;
|
||||
unw_context->regs[12] = ucontext->uc_mcontext.arm_ip;
|
||||
unw_context->regs[13] = ucontext->uc_mcontext.arm_sp;
|
||||
unw_context->regs[14] = ucontext->uc_mcontext.arm_lr;
|
||||
unw_context->regs[15] = ucontext->uc_mcontext.arm_pc;
|
||||
#else
|
||||
unw_context->uc_mcontext = ucontext->uc_mcontext;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool UnwindCurrent::UnwindFromContext(size_t num_ignore_frames, ucontext_t* ucontext) {
|
||||
if (ucontext == nullptr) {
|
||||
int ret = unw_getcontext(&context_);
|
||||
if (ret < 0) {
|
||||
BACK_LOGW("unw_getcontext failed %d", ret);
|
||||
error_.error_code = BACKTRACE_UNWIND_ERROR_SETUP_FAILED;
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
GetUnwContextFromUcontext(ucontext);
|
||||
}
|
||||
|
||||
// The cursor structure is pretty large, do not put it on the stack.
|
||||
std::unique_ptr<unw_cursor_t> cursor(new unw_cursor_t);
|
||||
int ret = unw_init_local(cursor.get(), &context_);
|
||||
if (ret < 0) {
|
||||
BACK_LOGW("unw_init_local failed %d", ret);
|
||||
error_.error_code = BACKTRACE_UNWIND_ERROR_SETUP_FAILED;
|
||||
return false;
|
||||
}
|
||||
initialized_ = true;
|
||||
|
||||
size_t num_frames = 0;
|
||||
do {
|
||||
unw_word_t pc;
|
||||
ret = unw_get_reg(cursor.get(), UNW_REG_IP, &pc);
|
||||
if (ret < 0) {
|
||||
BACK_LOGW("Failed to read IP %d", ret);
|
||||
break;
|
||||
}
|
||||
unw_word_t sp;
|
||||
ret = unw_get_reg(cursor.get(), UNW_REG_SP, &sp);
|
||||
if (ret < 0) {
|
||||
BACK_LOGW("Failed to read SP %d", ret);
|
||||
break;
|
||||
}
|
||||
|
||||
frames_.resize(num_frames+1);
|
||||
backtrace_frame_data_t* frame = &frames_.at(num_frames);
|
||||
frame->num = num_frames;
|
||||
frame->pc = static_cast<uintptr_t>(pc);
|
||||
frame->sp = static_cast<uintptr_t>(sp);
|
||||
frame->stack_size = 0;
|
||||
|
||||
FillInMap(frame->pc, &frame->map);
|
||||
// Check to see if we should skip this frame because it's coming
|
||||
// from within the library, and we are doing a local unwind.
|
||||
if (ucontext != nullptr || num_frames != 0 || !DiscardFrame(*frame)) {
|
||||
if (num_ignore_frames == 0) {
|
||||
// GetFunctionName is an expensive call, only do it if we are
|
||||
// keeping the frame.
|
||||
frame->func_name = GetFunctionName(frame->pc, &frame->func_offset, &frame->map);
|
||||
if (num_frames > 0) {
|
||||
// Set the stack size for the previous frame.
|
||||
backtrace_frame_data_t* prev = &frames_.at(num_frames-1);
|
||||
prev->stack_size = frame->sp - prev->sp;
|
||||
}
|
||||
if (BacktraceMap::IsValid(frame->map)) {
|
||||
frame->rel_pc = frame->pc - frame->map.start + frame->map.load_bias;
|
||||
} else {
|
||||
frame->rel_pc = frame->pc;
|
||||
}
|
||||
num_frames++;
|
||||
} else {
|
||||
num_ignore_frames--;
|
||||
// Set the number of frames to zero to remove the frame added
|
||||
// above. By definition, if we still have frames to ignore
|
||||
// there should only be one frame in the vector.
|
||||
CHECK(num_frames == 0);
|
||||
frames_.resize(0);
|
||||
}
|
||||
}
|
||||
// If the pc is in a device map, then don't try to step.
|
||||
if (frame->map.flags & PROT_DEVICE_MAP) {
|
||||
break;
|
||||
}
|
||||
// Verify the sp is not in a device map too.
|
||||
backtrace_map_t map;
|
||||
FillInMap(frame->sp, &map);
|
||||
if (map.flags & PROT_DEVICE_MAP) {
|
||||
break;
|
||||
}
|
||||
ret = unw_step (cursor.get());
|
||||
} while (ret > 0 && num_frames < MAX_BACKTRACE_FRAMES);
|
||||
|
||||
return true;
|
||||
}
|
|
@ -1,51 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 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.
|
||||
*/
|
||||
|
||||
#ifndef _LIBBACKTRACE_UNWIND_CURRENT_H
|
||||
#define _LIBBACKTRACE_UNWIND_CURRENT_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
#include <ucontext.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <backtrace/Backtrace.h>
|
||||
#include <backtrace/BacktraceMap.h>
|
||||
|
||||
#include "BacktraceCurrent.h"
|
||||
|
||||
#define UNW_LOCAL_ONLY
|
||||
#include <libunwind.h>
|
||||
|
||||
class UnwindCurrent : public BacktraceCurrent {
|
||||
public:
|
||||
UnwindCurrent(pid_t pid, pid_t tid, BacktraceMap* map) : BacktraceCurrent(pid, tid, map) {}
|
||||
virtual ~UnwindCurrent() {}
|
||||
|
||||
std::string GetFunctionNameRaw(uintptr_t pc, uintptr_t* offset) override;
|
||||
|
||||
private:
|
||||
void GetUnwContextFromUcontext(const ucontext_t* ucontext);
|
||||
|
||||
bool UnwindFromContext(size_t num_ignore_frames, ucontext_t* ucontext) override;
|
||||
|
||||
unw_context_t context_;
|
||||
|
||||
bool initialized_ = false;
|
||||
};
|
||||
|
||||
#endif // _LIBBACKTRACE_UNWIND_CURRENT_H
|
|
@ -134,7 +134,7 @@ bool UnwindMapLocal::Build() {
|
|||
return (map_created_ = (unw_map_local_create() == 0)) && GenerateMap();;
|
||||
}
|
||||
|
||||
void UnwindMapLocal::FillIn(uintptr_t addr, backtrace_map_t* map) {
|
||||
void UnwindMapLocal::FillIn(uint64_t addr, backtrace_map_t* map) {
|
||||
BacktraceMap::FillIn(addr, map);
|
||||
if (!IsValid(*map)) {
|
||||
// Check to see if the underlying map changed and regenerate the map
|
||||
|
|
|
@ -55,7 +55,7 @@ class UnwindMapLocal : public UnwindMap {
|
|||
|
||||
bool Build() override;
|
||||
|
||||
void FillIn(uintptr_t addr, backtrace_map_t* map) override;
|
||||
void FillIn(uint64_t addr, backtrace_map_t* map) override;
|
||||
|
||||
void LockIterator() override { pthread_rwlock_rdlock(&map_lock_); }
|
||||
void UnlockIterator() override { pthread_rwlock_unlock(&map_lock_); }
|
||||
|
|
|
@ -1,186 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 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 <stdint.h>
|
||||
#include <sys/types.h>
|
||||
#include <ucontext.h>
|
||||
|
||||
#include <libunwind.h>
|
||||
#include <libunwind-ptrace.h>
|
||||
|
||||
#include <backtrace/Backtrace.h>
|
||||
#include <backtrace/BacktraceMap.h>
|
||||
|
||||
#include "BacktraceLog.h"
|
||||
#include "UnwindMap.h"
|
||||
#include "UnwindPtrace.h"
|
||||
|
||||
UnwindPtrace::UnwindPtrace(pid_t pid, pid_t tid, BacktraceMap* map)
|
||||
: BacktracePtrace(pid, tid, map), addr_space_(nullptr), upt_info_(nullptr) {
|
||||
}
|
||||
|
||||
UnwindPtrace::~UnwindPtrace() {
|
||||
if (upt_info_) {
|
||||
_UPT_destroy(upt_info_);
|
||||
upt_info_ = nullptr;
|
||||
}
|
||||
|
||||
if (addr_space_) {
|
||||
// Remove the map from the address space before destroying it.
|
||||
// It will be freed in the UnwindMap destructor.
|
||||
unw_map_set(addr_space_, nullptr);
|
||||
|
||||
unw_destroy_addr_space(addr_space_);
|
||||
addr_space_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
bool UnwindPtrace::Init() {
|
||||
if (upt_info_) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (addr_space_) {
|
||||
// If somehow the addr_space_ gets initialized but upt_info_ doesn't,
|
||||
// then that indicates there is some kind of failure.
|
||||
return false;
|
||||
}
|
||||
|
||||
addr_space_ = unw_create_addr_space(&_UPT_accessors, 0);
|
||||
if (!addr_space_) {
|
||||
BACK_LOGW("unw_create_addr_space failed.");
|
||||
error_.error_code = BACKTRACE_UNWIND_ERROR_SETUP_FAILED;
|
||||
return false;
|
||||
}
|
||||
|
||||
UnwindMap* map = static_cast<UnwindMap*>(GetMap());
|
||||
unw_map_set(addr_space_, map->GetMapCursor());
|
||||
|
||||
upt_info_ = reinterpret_cast<struct UPT_info*>(_UPT_create(Tid()));
|
||||
if (!upt_info_) {
|
||||
BACK_LOGW("Failed to create upt info.");
|
||||
error_.error_code = BACKTRACE_UNWIND_ERROR_SETUP_FAILED;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool UnwindPtrace::Unwind(size_t num_ignore_frames, ucontext_t* ucontext) {
|
||||
if (GetMap() == nullptr) {
|
||||
// Without a map object, we can't do anything.
|
||||
error_.error_code = BACKTRACE_UNWIND_ERROR_MAP_MISSING;
|
||||
return false;
|
||||
}
|
||||
|
||||
error_.error_code = BACKTRACE_UNWIND_NO_ERROR;
|
||||
|
||||
if (ucontext) {
|
||||
BACK_LOGW("Unwinding from a specified context not supported yet.");
|
||||
error_.error_code = BACKTRACE_UNWIND_ERROR_UNSUPPORTED_OPERATION;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!Init()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
unw_cursor_t cursor;
|
||||
int ret = unw_init_remote(&cursor, addr_space_, upt_info_);
|
||||
if (ret < 0) {
|
||||
BACK_LOGW("unw_init_remote failed %d", ret);
|
||||
error_.error_code = BACKTRACE_UNWIND_ERROR_SETUP_FAILED;
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t num_frames = 0;
|
||||
do {
|
||||
unw_word_t pc;
|
||||
ret = unw_get_reg(&cursor, UNW_REG_IP, &pc);
|
||||
if (ret < 0) {
|
||||
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) {
|
||||
BACK_LOGW("Failed to read SP %d", ret);
|
||||
break;
|
||||
}
|
||||
|
||||
if (num_ignore_frames == 0) {
|
||||
frames_.resize(num_frames+1);
|
||||
backtrace_frame_data_t* frame = &frames_.at(num_frames);
|
||||
frame->num = num_frames;
|
||||
frame->pc = static_cast<uintptr_t>(pc);
|
||||
frame->sp = static_cast<uintptr_t>(sp);
|
||||
frame->stack_size = 0;
|
||||
|
||||
if (num_frames > 0) {
|
||||
backtrace_frame_data_t* prev = &frames_.at(num_frames-1);
|
||||
prev->stack_size = frame->sp - prev->sp;
|
||||
}
|
||||
|
||||
FillInMap(frame->pc, &frame->map);
|
||||
if (BacktraceMap::IsValid(frame->map)) {
|
||||
frame->rel_pc = frame->pc - frame->map.start + frame->map.load_bias;
|
||||
} else {
|
||||
frame->rel_pc = frame->pc;
|
||||
}
|
||||
|
||||
frame->func_name = GetFunctionName(frame->pc, &frame->func_offset, &frame->map);
|
||||
|
||||
num_frames++;
|
||||
// If the pc is in a device map, then don't try to step.
|
||||
if (frame->map.flags & PROT_DEVICE_MAP) {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
// If the pc is in a device map, then don't try to step.
|
||||
backtrace_map_t map;
|
||||
FillInMap(pc, &map);
|
||||
if (map.flags & PROT_DEVICE_MAP) {
|
||||
break;
|
||||
}
|
||||
num_ignore_frames--;
|
||||
}
|
||||
// Verify the sp is not in a device map.
|
||||
backtrace_map_t map;
|
||||
FillInMap(sp, &map);
|
||||
if (map.flags & PROT_DEVICE_MAP) {
|
||||
break;
|
||||
}
|
||||
ret = unw_step (&cursor);
|
||||
} while (ret > 0 && num_frames < MAX_BACKTRACE_FRAMES);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string UnwindPtrace::GetFunctionNameRaw(uintptr_t pc, uintptr_t* offset) {
|
||||
if (!Init()) {
|
||||
return "";
|
||||
}
|
||||
|
||||
*offset = 0;
|
||||
char buf[512];
|
||||
unw_word_t value;
|
||||
if (unw_get_proc_name_by_ip(addr_space_, pc, buf, sizeof(buf), &value,
|
||||
upt_info_) >= 0 && buf[0] != '\0') {
|
||||
*offset = static_cast<uintptr_t>(value);
|
||||
return buf;
|
||||
}
|
||||
return "";
|
||||
}
|
|
@ -1,48 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 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.
|
||||
*/
|
||||
|
||||
#ifndef _LIBBACKTRACE_UNWIND_PTRACE_H
|
||||
#define _LIBBACKTRACE_UNWIND_PTRACE_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
#ifdef UNW_LOCAL_ONLY
|
||||
#undef UNW_LOCAL_ONLY
|
||||
#endif
|
||||
#include <libunwind.h>
|
||||
|
||||
#include "BacktracePtrace.h"
|
||||
|
||||
class UnwindPtrace : public BacktracePtrace {
|
||||
public:
|
||||
UnwindPtrace(pid_t pid, pid_t tid, BacktraceMap* map);
|
||||
virtual ~UnwindPtrace();
|
||||
|
||||
bool Unwind(size_t num_ignore_frames, ucontext_t* ucontext) override;
|
||||
|
||||
std::string GetFunctionNameRaw(uintptr_t pc, uintptr_t* offset) override;
|
||||
|
||||
private:
|
||||
bool Init();
|
||||
|
||||
unw_addr_space_t addr_space_;
|
||||
struct UPT_info* upt_info_;
|
||||
};
|
||||
|
||||
#endif // _LIBBACKTRACE_UNWIND_PTRACE_H
|
|
@ -89,7 +89,7 @@ bool Backtrace::Unwind(unwindstack::Regs* regs, BacktraceMap* back_map,
|
|||
UnwindStackCurrent::UnwindStackCurrent(pid_t pid, pid_t tid, BacktraceMap* map)
|
||||
: BacktraceCurrent(pid, tid, map) {}
|
||||
|
||||
std::string UnwindStackCurrent::GetFunctionNameRaw(uintptr_t pc, uintptr_t* offset) {
|
||||
std::string UnwindStackCurrent::GetFunctionNameRaw(uint64_t pc, uint64_t* offset) {
|
||||
return GetMap()->GetFunctionName(pc, offset);
|
||||
}
|
||||
|
||||
|
@ -112,7 +112,7 @@ bool UnwindStackCurrent::UnwindFromContext(size_t num_ignore_frames, ucontext_t*
|
|||
UnwindStackPtrace::UnwindStackPtrace(pid_t pid, pid_t tid, BacktraceMap* map)
|
||||
: BacktracePtrace(pid, tid, map), memory_(pid) {}
|
||||
|
||||
std::string UnwindStackPtrace::GetFunctionNameRaw(uintptr_t pc, uintptr_t* offset) {
|
||||
std::string UnwindStackPtrace::GetFunctionNameRaw(uint64_t pc, uint64_t* offset) {
|
||||
return GetMap()->GetFunctionName(pc, offset);
|
||||
}
|
||||
|
||||
|
@ -128,6 +128,6 @@ bool UnwindStackPtrace::Unwind(size_t num_ignore_frames, ucontext_t* context) {
|
|||
return Backtrace::Unwind(regs.get(), GetMap(), &frames_, num_ignore_frames, nullptr);
|
||||
}
|
||||
|
||||
size_t UnwindStackPtrace::Read(uintptr_t addr, uint8_t* buffer, size_t bytes) {
|
||||
size_t UnwindStackPtrace::Read(uint64_t addr, uint8_t* buffer, size_t bytes) {
|
||||
return memory_.Read(addr, buffer, bytes);
|
||||
}
|
||||
|
|
|
@ -32,7 +32,7 @@ class UnwindStackCurrent : public BacktraceCurrent {
|
|||
UnwindStackCurrent(pid_t pid, pid_t tid, BacktraceMap* map);
|
||||
virtual ~UnwindStackCurrent() = default;
|
||||
|
||||
std::string GetFunctionNameRaw(uintptr_t pc, uintptr_t* offset) override;
|
||||
std::string GetFunctionNameRaw(uint64_t pc, uint64_t* offset) override;
|
||||
|
||||
bool UnwindFromContext(size_t num_ignore_frames, ucontext_t* ucontext) override;
|
||||
};
|
||||
|
@ -44,9 +44,9 @@ class UnwindStackPtrace : public BacktracePtrace {
|
|||
|
||||
bool Unwind(size_t num_ignore_frames, ucontext_t* context) override;
|
||||
|
||||
std::string GetFunctionNameRaw(uintptr_t pc, uintptr_t* offset);
|
||||
std::string GetFunctionNameRaw(uint64_t pc, uint64_t* offset);
|
||||
|
||||
size_t Read(uintptr_t addr, uint8_t* buffer, size_t bytes) override;
|
||||
size_t Read(uint64_t addr, uint8_t* buffer, size_t bytes) override;
|
||||
|
||||
private:
|
||||
unwindstack::MemoryRemote memory_;
|
||||
|
|
|
@ -57,7 +57,7 @@ bool UnwindStackMap::Build() {
|
|||
map.end = map_info->end;
|
||||
map.offset = map_info->offset;
|
||||
// Set to -1 so that it is demand loaded.
|
||||
map.load_bias = static_cast<uintptr_t>(-1);
|
||||
map.load_bias = static_cast<uint64_t>(-1);
|
||||
map.flags = map_info->flags;
|
||||
map.name = map_info->name;
|
||||
|
||||
|
@ -67,9 +67,9 @@ bool UnwindStackMap::Build() {
|
|||
return true;
|
||||
}
|
||||
|
||||
void UnwindStackMap::FillIn(uintptr_t addr, backtrace_map_t* map) {
|
||||
void UnwindStackMap::FillIn(uint64_t addr, backtrace_map_t* map) {
|
||||
BacktraceMap::FillIn(addr, map);
|
||||
if (map->load_bias != static_cast<uintptr_t>(-1)) {
|
||||
if (map->load_bias != static_cast<uint64_t>(-1)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -93,7 +93,7 @@ uint64_t UnwindStackMap::GetLoadBias(size_t index) {
|
|||
return map_info->GetLoadBias(process_memory_);
|
||||
}
|
||||
|
||||
std::string UnwindStackMap::GetFunctionName(uintptr_t pc, uintptr_t* offset) {
|
||||
std::string UnwindStackMap::GetFunctionName(uint64_t pc, uint64_t* offset) {
|
||||
*offset = 0;
|
||||
unwindstack::Maps* maps = stack_maps();
|
||||
|
||||
|
|
|
@ -33,9 +33,9 @@ class UnwindStackMap : public BacktraceMap {
|
|||
|
||||
bool Build() override;
|
||||
|
||||
void FillIn(uintptr_t addr, backtrace_map_t* map) override;
|
||||
void FillIn(uint64_t addr, backtrace_map_t* map) override;
|
||||
|
||||
virtual std::string GetFunctionName(uintptr_t pc, uintptr_t* offset) override;
|
||||
virtual std::string GetFunctionName(uint64_t pc, uint64_t* offset) override;
|
||||
virtual std::shared_ptr<unwindstack::Memory> GetProcessMemory() override final;
|
||||
|
||||
unwindstack::Maps* stack_maps() { return stack_maps_.get(); }
|
||||
|
|
|
@ -75,20 +75,20 @@ static ucontext_t GetUContextFromUnwContext(const unw_context_t& unw_context) {
|
|||
|
||||
struct FunctionSymbol {
|
||||
std::string name;
|
||||
uintptr_t start;
|
||||
uintptr_t end;
|
||||
uint64_t start;
|
||||
uint64_t end;
|
||||
};
|
||||
|
||||
static std::vector<FunctionSymbol> GetFunctionSymbols() {
|
||||
std::vector<FunctionSymbol> symbols = {
|
||||
{"unknown_start", 0, 0},
|
||||
{"test_level_one", reinterpret_cast<uintptr_t>(&test_level_one), 0},
|
||||
{"test_level_two", reinterpret_cast<uintptr_t>(&test_level_two), 0},
|
||||
{"test_level_three", reinterpret_cast<uintptr_t>(&test_level_three), 0},
|
||||
{"test_level_four", reinterpret_cast<uintptr_t>(&test_level_four), 0},
|
||||
{"test_recursive_call", reinterpret_cast<uintptr_t>(&test_recursive_call), 0},
|
||||
{"test_get_context_and_wait", reinterpret_cast<uintptr_t>(&test_get_context_and_wait), 0},
|
||||
{"unknown_end", static_cast<uintptr_t>(-1), static_cast<uintptr_t>(-1)},
|
||||
{"test_level_one", reinterpret_cast<uint64_t>(&test_level_one), 0},
|
||||
{"test_level_two", reinterpret_cast<uint64_t>(&test_level_two), 0},
|
||||
{"test_level_three", reinterpret_cast<uint64_t>(&test_level_three), 0},
|
||||
{"test_level_four", reinterpret_cast<uint64_t>(&test_level_four), 0},
|
||||
{"test_recursive_call", reinterpret_cast<uint64_t>(&test_recursive_call), 0},
|
||||
{"test_get_context_and_wait", reinterpret_cast<uint64_t>(&test_get_context_and_wait), 0},
|
||||
{"unknown_end", static_cast<uint64_t>(-1), static_cast<uint64_t>(-1)},
|
||||
};
|
||||
std::sort(
|
||||
symbols.begin(), symbols.end(),
|
||||
|
@ -141,7 +141,7 @@ TEST(libbacktrace, DISABLED_generate_offline_testdata) {
|
|||
const size_t stack_size = 16 * 1024;
|
||||
void* stack = mmap(NULL, stack_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
|
||||
ASSERT_NE(MAP_FAILED, stack);
|
||||
uintptr_t stack_addr = reinterpret_cast<uintptr_t>(stack);
|
||||
uint64_t stack_addr = reinterpret_cast<uint64_t>(stack);
|
||||
pthread_attr_t attr;
|
||||
ASSERT_EQ(0, pthread_attr_init(&attr));
|
||||
ASSERT_EQ(0, pthread_attr_setstack(&attr, reinterpret_cast<void*>(stack), stack_size));
|
||||
|
@ -174,8 +174,8 @@ TEST(libbacktrace, DISABLED_generate_offline_testdata) {
|
|||
for (auto it = map->begin(); it != map->end(); ++it) {
|
||||
const backtrace_map_t* entry = *it;
|
||||
testdata +=
|
||||
android::base::StringPrintf("map: start: %" PRIxPTR " end: %" PRIxPTR " offset: %" PRIxPTR
|
||||
" load_bias: %" PRIxPTR " flags: %d name: %s\n",
|
||||
android::base::StringPrintf("map: start: %" PRIx64 " end: %" PRIx64 " offset: %" PRIx64
|
||||
" load_bias: %" PRIx64 " flags: %d name: %s\n",
|
||||
entry->start, entry->end, entry->offset, entry->load_bias,
|
||||
entry->flags, entry->name.c_str());
|
||||
}
|
||||
|
@ -194,9 +194,9 @@ TEST(libbacktrace, DISABLED_generate_offline_testdata) {
|
|||
// 5. Dump function symbols
|
||||
std::vector<FunctionSymbol> function_symbols = GetFunctionSymbols();
|
||||
for (const auto& symbol : function_symbols) {
|
||||
testdata += android::base::StringPrintf(
|
||||
"function: start: %" PRIxPTR " end: %" PRIxPTR" name: %s\n",
|
||||
symbol.start, symbol.end, symbol.name.c_str());
|
||||
testdata +=
|
||||
android::base::StringPrintf("function: start: %" PRIx64 " end: %" PRIx64 " name: %s\n",
|
||||
symbol.start, symbol.end, symbol.name.c_str());
|
||||
}
|
||||
|
||||
ASSERT_TRUE(android::base::WriteStringToFile(testdata, "offline_testdata"));
|
||||
|
@ -204,7 +204,7 @@ TEST(libbacktrace, DISABLED_generate_offline_testdata) {
|
|||
|
||||
// Return the name of the function which matches the address. Although we don't know the
|
||||
// exact end of each function, it is accurate enough for the tests.
|
||||
static std::string FunctionNameForAddress(uintptr_t addr,
|
||||
static std::string FunctionNameForAddress(uint64_t addr,
|
||||
const std::vector<FunctionSymbol>& symbols) {
|
||||
for (auto& symbol : symbols) {
|
||||
if (addr >= symbol.start && addr < symbol.end) {
|
||||
|
@ -240,7 +240,7 @@ bool ReadOfflineTestData(const std::string offline_testdata_path, OfflineTestDat
|
|||
backtrace_map_t& map = testdata->maps.back();
|
||||
int pos;
|
||||
sscanf(line.c_str(),
|
||||
"map: start: %" SCNxPTR " end: %" SCNxPTR " offset: %" SCNxPTR " load_bias: %" SCNxPTR
|
||||
"map: start: %" SCNx64 " end: %" SCNx64 " offset: %" SCNx64 " load_bias: %" SCNx64
|
||||
" flags: %d name: %n",
|
||||
&map.start, &map.end, &map.offset, &map.load_bias, &map.flags, &pos);
|
||||
map.name = android::base::Trim(line.substr(pos));
|
||||
|
@ -302,9 +302,8 @@ bool ReadOfflineTestData(const std::string offline_testdata_path, OfflineTestDat
|
|||
testdata->symbols.resize(testdata->symbols.size() + 1);
|
||||
FunctionSymbol& symbol = testdata->symbols.back();
|
||||
int pos;
|
||||
sscanf(line.c_str(),
|
||||
"function: start: %" SCNxPTR " end: %" SCNxPTR " name: %n",
|
||||
&symbol.start, &symbol.end, &pos);
|
||||
sscanf(line.c_str(), "function: start: %" SCNx64 " end: %" SCNx64 " name: %n", &symbol.start,
|
||||
&symbol.end, &pos);
|
||||
symbol.name = line.substr(pos);
|
||||
}
|
||||
}
|
||||
|
@ -342,7 +341,7 @@ static void BacktraceOfflineTest(const char* arch, const std::string& testlib_na
|
|||
ASSERT_TRUE(backtrace->Unwind(0, &ucontext));
|
||||
|
||||
// Collect pc values of the call stack frames.
|
||||
std::vector<uintptr_t> pc_values;
|
||||
std::vector<uint64_t> pc_values;
|
||||
for (size_t i = 0; i < backtrace->NumFrames(); ++i) {
|
||||
pc_values.push_back(backtrace->GetFrame(i)->pc);
|
||||
}
|
||||
|
@ -420,7 +419,7 @@ static void LibUnwindingTest(const std::string& arch, const std::string& testdat
|
|||
|
||||
ASSERT_EQ(testdata.symbols.size(), backtrace->NumFrames());
|
||||
for (size_t i = 0; i < backtrace->NumFrames(); ++i) {
|
||||
uintptr_t vaddr_in_file =
|
||||
uint64_t vaddr_in_file =
|
||||
backtrace->GetFrame(i)->pc - testdata.maps[0].start + testdata.maps[0].load_bias;
|
||||
std::string name = FunctionNameForAddress(vaddr_in_file, testdata.symbols);
|
||||
ASSERT_EQ(name, testdata.symbols[i].name);
|
||||
|
|
|
@ -745,8 +745,8 @@ TEST(libbacktrace, fillin_erases) {
|
|||
delete back_map;
|
||||
|
||||
ASSERT_FALSE(BacktraceMap::IsValid(map));
|
||||
ASSERT_EQ(static_cast<uintptr_t>(0), map.start);
|
||||
ASSERT_EQ(static_cast<uintptr_t>(0), map.end);
|
||||
ASSERT_EQ(static_cast<uint64_t>(0), map.start);
|
||||
ASSERT_EQ(static_cast<uint64_t>(0), map.end);
|
||||
ASSERT_EQ(0, map.flags);
|
||||
ASSERT_EQ("", map.name);
|
||||
}
|
||||
|
@ -851,8 +851,8 @@ TEST(libbacktrace, format_test) {
|
|||
}
|
||||
|
||||
struct map_test_t {
|
||||
uintptr_t start;
|
||||
uintptr_t end;
|
||||
uint64_t start;
|
||||
uint64_t end;
|
||||
};
|
||||
|
||||
static bool map_sort(map_test_t i, map_test_t j) { return i.start < j.start; }
|
||||
|
@ -863,7 +863,7 @@ static std::string GetTestMapsAsString(const std::vector<map_test_t>& maps) {
|
|||
}
|
||||
std::string map_txt;
|
||||
for (auto map : maps) {
|
||||
map_txt += android::base::StringPrintf("%" PRIxPTR "-%" PRIxPTR "\n", map.start, map.end);
|
||||
map_txt += android::base::StringPrintf("%" PRIx64 "-%" PRIx64 "\n", map.start, map.end);
|
||||
}
|
||||
return map_txt;
|
||||
}
|
||||
|
@ -875,7 +875,7 @@ static std::string GetMapsAsString(BacktraceMap* maps) {
|
|||
std::string map_txt;
|
||||
for (const backtrace_map_t* map : *maps) {
|
||||
map_txt += android::base::StringPrintf(
|
||||
"%" PRIxPTR "-%" PRIxPTR " flags: 0x%x offset: 0x%" PRIxPTR " load_bias: 0x%" PRIxPTR,
|
||||
"%" PRIx64 "-%" PRIx64 " flags: 0x%x offset: 0x%" PRIx64 " load_bias: 0x%" PRIx64,
|
||||
map->start, map->end, map->flags, map->offset, map->load_bias);
|
||||
if (!map->name.empty()) {
|
||||
map_txt += ' ' + map->name;
|
||||
|
@ -894,7 +894,7 @@ static void VerifyMap(pid_t pid) {
|
|||
std::vector<map_test_t> test_maps;
|
||||
while (fgets(buffer, sizeof(buffer), map_file)) {
|
||||
map_test_t map;
|
||||
ASSERT_EQ(2, sscanf(buffer, "%" SCNxPTR "-%" SCNxPTR " ", &map.start, &map.end));
|
||||
ASSERT_EQ(2, sscanf(buffer, "%" SCNx64 "-%" SCNx64 " ", &map.start, &map.end));
|
||||
test_maps.push_back(map);
|
||||
}
|
||||
fclose(map_file);
|
||||
|
@ -984,7 +984,7 @@ static void* ThreadReadTest(void* data) {
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
static void RunReadTest(Backtrace* backtrace, uintptr_t read_addr) {
|
||||
static void RunReadTest(Backtrace* backtrace, uint64_t read_addr) {
|
||||
size_t pagesize = static_cast<size_t>(sysconf(_SC_PAGE_SIZE));
|
||||
|
||||
// Create a page of data to use to do quick compares.
|
||||
|
@ -1035,15 +1035,15 @@ TEST(libbacktrace, thread_read) {
|
|||
std::unique_ptr<Backtrace> backtrace(Backtrace::Create(getpid(), thread_data.tid));
|
||||
ASSERT_TRUE(backtrace.get() != nullptr);
|
||||
|
||||
RunReadTest(backtrace.get(), reinterpret_cast<uintptr_t>(thread_data.data));
|
||||
RunReadTest(backtrace.get(), reinterpret_cast<uint64_t>(thread_data.data));
|
||||
|
||||
android_atomic_acquire_store(0, &thread_data.state);
|
||||
|
||||
ASSERT_TRUE(WaitForNonZero(&thread_data.state, 10));
|
||||
}
|
||||
|
||||
volatile uintptr_t g_ready = 0;
|
||||
volatile uintptr_t g_addr = 0;
|
||||
volatile uint64_t g_ready = 0;
|
||||
volatile uint64_t g_addr = 0;
|
||||
|
||||
static void ForkedReadTest() {
|
||||
// Create two map pages.
|
||||
|
@ -1063,7 +1063,7 @@ static void ForkedReadTest() {
|
|||
// Set up a simple pattern in memory.
|
||||
InitMemory(memory, pagesize);
|
||||
|
||||
g_addr = reinterpret_cast<uintptr_t>(memory);
|
||||
g_addr = reinterpret_cast<uint64_t>(memory);
|
||||
g_ready = 1;
|
||||
|
||||
while (1) {
|
||||
|
@ -1089,17 +1089,15 @@ TEST(libbacktrace, process_read) {
|
|||
std::unique_ptr<Backtrace> backtrace(Backtrace::Create(pid, pid));
|
||||
ASSERT_TRUE(backtrace.get() != nullptr);
|
||||
|
||||
uintptr_t read_addr;
|
||||
size_t bytes_read = backtrace->Read(reinterpret_cast<uintptr_t>(&g_ready),
|
||||
reinterpret_cast<uint8_t*>(&read_addr),
|
||||
sizeof(uintptr_t));
|
||||
ASSERT_EQ(sizeof(uintptr_t), bytes_read);
|
||||
uint64_t read_addr;
|
||||
size_t bytes_read = backtrace->Read(reinterpret_cast<uint64_t>(&g_ready),
|
||||
reinterpret_cast<uint8_t*>(&read_addr), sizeof(uint64_t));
|
||||
ASSERT_EQ(sizeof(uint64_t), bytes_read);
|
||||
if (read_addr) {
|
||||
// The forked process is ready to be read.
|
||||
bytes_read = backtrace->Read(reinterpret_cast<uintptr_t>(&g_addr),
|
||||
reinterpret_cast<uint8_t*>(&read_addr),
|
||||
sizeof(uintptr_t));
|
||||
ASSERT_EQ(sizeof(uintptr_t), bytes_read);
|
||||
bytes_read = backtrace->Read(reinterpret_cast<uint64_t>(&g_addr),
|
||||
reinterpret_cast<uint8_t*>(&read_addr), sizeof(uint64_t));
|
||||
ASSERT_EQ(sizeof(uint64_t), bytes_read);
|
||||
|
||||
RunReadTest(backtrace.get(), read_addr);
|
||||
|
||||
|
@ -1173,7 +1171,7 @@ TEST(libbacktrace, check_unreadable_elf_local) {
|
|||
|
||||
struct stat buf;
|
||||
ASSERT_TRUE(stat(tmp_so_name, &buf) != -1);
|
||||
uintptr_t map_size = buf.st_size;
|
||||
uint64_t map_size = buf.st_size;
|
||||
|
||||
int fd = open(tmp_so_name, O_RDONLY);
|
||||
ASSERT_TRUE(fd != -1);
|
||||
|
@ -1192,11 +1190,10 @@ TEST(libbacktrace, check_unreadable_elf_local) {
|
|||
backtrace->Unwind(0);
|
||||
|
||||
// Loop through the entire map, and get every function we can find.
|
||||
map_size += reinterpret_cast<uintptr_t>(map);
|
||||
map_size += reinterpret_cast<uint64_t>(map);
|
||||
std::string last_func;
|
||||
for (uintptr_t read_addr = reinterpret_cast<uintptr_t>(map);
|
||||
read_addr < map_size; read_addr += 4) {
|
||||
uintptr_t offset;
|
||||
for (uint64_t read_addr = reinterpret_cast<uint64_t>(map); read_addr < map_size; read_addr += 4) {
|
||||
uint64_t offset;
|
||||
std::string func_name = backtrace->GetFunctionName(read_addr, &offset);
|
||||
if (!func_name.empty() && last_func != func_name) {
|
||||
found_functions.push_back(func_name);
|
||||
|
@ -1204,7 +1201,7 @@ TEST(libbacktrace, check_unreadable_elf_local) {
|
|||
last_func = func_name;
|
||||
}
|
||||
|
||||
ASSERT_TRUE(munmap(map, map_size - reinterpret_cast<uintptr_t>(map)) == 0);
|
||||
ASSERT_TRUE(munmap(map, map_size - reinterpret_cast<uint64_t>(map)) == 0);
|
||||
|
||||
VerifyFunctionsFound(found_functions);
|
||||
}
|
||||
|
@ -1217,7 +1214,7 @@ TEST(libbacktrace, check_unreadable_elf_remote) {
|
|||
|
||||
struct stat buf;
|
||||
ASSERT_TRUE(stat(tmp_so_name, &buf) != -1);
|
||||
uintptr_t map_size = buf.st_size;
|
||||
uint64_t map_size = buf.st_size;
|
||||
|
||||
pid_t pid;
|
||||
if ((pid = fork()) == 0) {
|
||||
|
@ -1240,7 +1237,7 @@ TEST(libbacktrace, check_unreadable_elf_remote) {
|
|||
exit(0);
|
||||
}
|
||||
|
||||
g_addr = reinterpret_cast<uintptr_t>(map);
|
||||
g_addr = reinterpret_cast<uint64_t>(map);
|
||||
g_ready = 1;
|
||||
while (true) {
|
||||
usleep(US_PER_MSEC);
|
||||
|
@ -1260,10 +1257,14 @@ TEST(libbacktrace, check_unreadable_elf_remote) {
|
|||
std::unique_ptr<Backtrace> backtrace(Backtrace::Create(pid, BACKTRACE_CURRENT_THREAD));
|
||||
ASSERT_TRUE(backtrace.get() != nullptr);
|
||||
|
||||
uintptr_t read_addr;
|
||||
ASSERT_EQ(sizeof(uintptr_t), backtrace->Read(reinterpret_cast<uintptr_t>(&g_ready), reinterpret_cast<uint8_t*>(&read_addr), sizeof(uintptr_t)));
|
||||
uint64_t read_addr;
|
||||
ASSERT_EQ(sizeof(uint64_t),
|
||||
backtrace->Read(reinterpret_cast<uint64_t>(&g_ready),
|
||||
reinterpret_cast<uint8_t*>(&read_addr), sizeof(uint64_t)));
|
||||
if (read_addr) {
|
||||
ASSERT_EQ(sizeof(uintptr_t), backtrace->Read(reinterpret_cast<uintptr_t>(&g_addr), reinterpret_cast<uint8_t*>(&read_addr), sizeof(uintptr_t)));
|
||||
ASSERT_EQ(sizeof(uint64_t),
|
||||
backtrace->Read(reinterpret_cast<uint64_t>(&g_addr),
|
||||
reinterpret_cast<uint8_t*>(&read_addr), sizeof(uint64_t)));
|
||||
|
||||
// Needed before GetFunctionName will work.
|
||||
backtrace->Unwind(0);
|
||||
|
@ -1272,7 +1273,7 @@ TEST(libbacktrace, check_unreadable_elf_remote) {
|
|||
map_size += read_addr;
|
||||
std::string last_func;
|
||||
for (; read_addr < map_size; read_addr += 4) {
|
||||
uintptr_t offset;
|
||||
uint64_t offset;
|
||||
std::string func_name = backtrace->GetFunctionName(read_addr, &offset);
|
||||
if (!func_name.empty() && last_func != func_name) {
|
||||
found_functions.push_back(func_name);
|
||||
|
@ -1295,7 +1296,7 @@ TEST(libbacktrace, check_unreadable_elf_remote) {
|
|||
VerifyFunctionsFound(found_functions);
|
||||
}
|
||||
|
||||
static bool FindFuncFrameInBacktrace(Backtrace* backtrace, uintptr_t test_func, size_t* frame_num) {
|
||||
static bool FindFuncFrameInBacktrace(Backtrace* backtrace, uint64_t test_func, size_t* frame_num) {
|
||||
backtrace_map_t map;
|
||||
backtrace->FillInMap(test_func, &map);
|
||||
if (!BacktraceMap::IsValid(map)) {
|
||||
|
@ -1314,7 +1315,7 @@ static bool FindFuncFrameInBacktrace(Backtrace* backtrace, uintptr_t test_func,
|
|||
return false;
|
||||
}
|
||||
|
||||
static void VerifyUnreadableElfFrame(Backtrace* backtrace, uintptr_t test_func, size_t frame_num) {
|
||||
static void VerifyUnreadableElfFrame(Backtrace* backtrace, uint64_t test_func, size_t frame_num) {
|
||||
ASSERT_LT(backtrace->NumFrames(), static_cast<size_t>(MAX_BACKTRACE_FRAMES))
|
||||
<< DumpFrames(backtrace);
|
||||
|
||||
|
@ -1322,11 +1323,12 @@ static void VerifyUnreadableElfFrame(Backtrace* backtrace, uintptr_t test_func,
|
|||
// Make sure that there is at least one more frame above the test func call.
|
||||
ASSERT_LT(frame_num, backtrace->NumFrames()) << DumpFrames(backtrace);
|
||||
|
||||
uintptr_t diff = backtrace->GetFrame(frame_num)->pc - test_func;
|
||||
uint64_t diff = backtrace->GetFrame(frame_num)->pc - test_func;
|
||||
ASSERT_LT(diff, 200U) << DumpFrames(backtrace);
|
||||
}
|
||||
|
||||
static void VerifyUnreadableElfBacktrace(uintptr_t test_func) {
|
||||
static void VerifyUnreadableElfBacktrace(void* func) {
|
||||
uint64_t test_func = reinterpret_cast<uint64_t>(func);
|
||||
std::unique_ptr<Backtrace> backtrace(Backtrace::Create(BACKTRACE_CURRENT_PROCESS,
|
||||
BACKTRACE_CURRENT_THREAD));
|
||||
ASSERT_TRUE(backtrace.get() != nullptr);
|
||||
|
@ -1339,7 +1341,7 @@ static void VerifyUnreadableElfBacktrace(uintptr_t test_func) {
|
|||
VerifyUnreadableElfFrame(backtrace.get(), test_func, frame_num);
|
||||
}
|
||||
|
||||
typedef int (*test_func_t)(int, int, int, int, void (*)(uintptr_t), uintptr_t);
|
||||
typedef int (*test_func_t)(int, int, int, int, void (*)(void*), void*);
|
||||
|
||||
TEST(libbacktrace, unwind_through_unreadable_elf_local) {
|
||||
const char* tmp_so_name = CopySharedLibrary();
|
||||
|
@ -1352,8 +1354,8 @@ TEST(libbacktrace, unwind_through_unreadable_elf_local) {
|
|||
test_func = reinterpret_cast<test_func_t>(dlsym(lib_handle, "test_level_one"));
|
||||
ASSERT_TRUE(test_func != nullptr);
|
||||
|
||||
ASSERT_NE(test_func(1, 2, 3, 4, VerifyUnreadableElfBacktrace,
|
||||
reinterpret_cast<uintptr_t>(test_func)), 0);
|
||||
ASSERT_NE(test_func(1, 2, 3, 4, VerifyUnreadableElfBacktrace, reinterpret_cast<void*>(test_func)),
|
||||
0);
|
||||
|
||||
ASSERT_TRUE(dlclose(lib_handle) == 0);
|
||||
}
|
||||
|
@ -1391,10 +1393,9 @@ TEST(libbacktrace, unwind_through_unreadable_elf_remote) {
|
|||
ASSERT_EQ(BACKTRACE_UNWIND_NO_ERROR, backtrace->GetError().error_code);
|
||||
|
||||
size_t frame_num;
|
||||
if (FindFuncFrameInBacktrace(backtrace.get(),
|
||||
reinterpret_cast<uintptr_t>(test_func), &frame_num)) {
|
||||
|
||||
VerifyUnreadableElfFrame(backtrace.get(), reinterpret_cast<uintptr_t>(test_func), frame_num);
|
||||
if (FindFuncFrameInBacktrace(backtrace.get(), reinterpret_cast<uint64_t>(test_func),
|
||||
&frame_num)) {
|
||||
VerifyUnreadableElfFrame(backtrace.get(), reinterpret_cast<uint64_t>(test_func), frame_num);
|
||||
done = true;
|
||||
}
|
||||
|
||||
|
@ -1426,8 +1427,8 @@ TEST(libbacktrace, local_get_function_name_before_unwind) {
|
|||
ASSERT_TRUE(backtrace.get() != nullptr);
|
||||
|
||||
// Verify that trying to get a function name before doing an unwind works.
|
||||
uintptr_t cur_func_offset = reinterpret_cast<uintptr_t>(&test_level_one) + 1;
|
||||
size_t offset;
|
||||
uint64_t cur_func_offset = reinterpret_cast<uint64_t>(&test_level_one) + 1;
|
||||
uint64_t offset;
|
||||
ASSERT_NE(std::string(""), backtrace->GetFunctionName(cur_func_offset, &offset));
|
||||
}
|
||||
|
||||
|
@ -1439,14 +1440,14 @@ TEST(libbacktrace, remote_get_function_name_before_unwind) {
|
|||
std::unique_ptr<Backtrace> backtrace(Backtrace::Create(pid, pid));
|
||||
|
||||
// Verify that trying to get a function name before doing an unwind works.
|
||||
uintptr_t cur_func_offset = reinterpret_cast<uintptr_t>(&test_level_one) + 1;
|
||||
size_t offset;
|
||||
uint64_t cur_func_offset = reinterpret_cast<uint64_t>(&test_level_one) + 1;
|
||||
uint64_t offset;
|
||||
ASSERT_NE(std::string(""), backtrace->GetFunctionName(cur_func_offset, &offset));
|
||||
|
||||
FinishRemoteProcess(pid);
|
||||
}
|
||||
|
||||
static void SetUcontextSp(uintptr_t sp, ucontext_t* ucontext) {
|
||||
static void SetUcontextSp(uint64_t sp, ucontext_t* ucontext) {
|
||||
#if defined(__arm__)
|
||||
ucontext->uc_mcontext.arm_sp = sp;
|
||||
#elif defined(__aarch64__)
|
||||
|
@ -1462,7 +1463,7 @@ static void SetUcontextSp(uintptr_t sp, ucontext_t* ucontext) {
|
|||
#endif
|
||||
}
|
||||
|
||||
static void SetUcontextPc(uintptr_t pc, ucontext_t* ucontext) {
|
||||
static void SetUcontextPc(uint64_t pc, ucontext_t* ucontext) {
|
||||
#if defined(__arm__)
|
||||
ucontext->uc_mcontext.arm_pc = pc;
|
||||
#elif defined(__aarch64__)
|
||||
|
@ -1478,7 +1479,7 @@ static void SetUcontextPc(uintptr_t pc, ucontext_t* ucontext) {
|
|||
#endif
|
||||
}
|
||||
|
||||
static void SetUcontextLr(uintptr_t lr, ucontext_t* ucontext) {
|
||||
static void SetUcontextLr(uint64_t lr, ucontext_t* ucontext) {
|
||||
#if defined(__arm__)
|
||||
ucontext->uc_mcontext.arm_lr = lr;
|
||||
#elif defined(__aarch64__)
|
||||
|
@ -1513,7 +1514,7 @@ static void SetupDeviceMap(void** device_map) {
|
|||
}
|
||||
|
||||
static void UnwindFromDevice(Backtrace* backtrace, void* device_map) {
|
||||
uintptr_t device_map_uint = reinterpret_cast<uintptr_t>(device_map);
|
||||
uint64_t device_map_uint = reinterpret_cast<uint64_t>(device_map);
|
||||
|
||||
backtrace_map_t map;
|
||||
backtrace->FillInMap(device_map_uint, &map);
|
||||
|
@ -1521,12 +1522,12 @@ static void UnwindFromDevice(Backtrace* backtrace, void* device_map) {
|
|||
ASSERT_EQ(PROT_DEVICE_MAP, map.flags & PROT_DEVICE_MAP);
|
||||
|
||||
// Quick sanity checks.
|
||||
size_t offset;
|
||||
uint64_t offset;
|
||||
ASSERT_EQ(std::string(""), backtrace->GetFunctionName(device_map_uint, &offset));
|
||||
ASSERT_EQ(std::string(""), backtrace->GetFunctionName(device_map_uint, &offset, &map));
|
||||
ASSERT_EQ(std::string(""), backtrace->GetFunctionName(0, &offset));
|
||||
|
||||
uintptr_t cur_func_offset = reinterpret_cast<uintptr_t>(&test_level_one) + 1;
|
||||
uint64_t cur_func_offset = reinterpret_cast<uint64_t>(&test_level_one) + 1;
|
||||
// Now verify the device map flag actually causes the function name to be empty.
|
||||
backtrace->FillInMap(cur_func_offset, &map);
|
||||
ASSERT_TRUE((map.flags & PROT_DEVICE_MAP) == 0);
|
||||
|
@ -1539,7 +1540,7 @@ static void UnwindFromDevice(Backtrace* backtrace, void* device_map) {
|
|||
// Create a context that has the pc in the device map, but the sp
|
||||
// in a non-device map.
|
||||
memset(&ucontext, 0, sizeof(ucontext));
|
||||
SetUcontextSp(reinterpret_cast<uintptr_t>(&ucontext), &ucontext);
|
||||
SetUcontextSp(reinterpret_cast<uint64_t>(&ucontext), &ucontext);
|
||||
SetUcontextPc(device_map_uint, &ucontext);
|
||||
SetUcontextLr(cur_func_offset, &ucontext);
|
||||
|
||||
|
@ -1549,7 +1550,7 @@ static void UnwindFromDevice(Backtrace* backtrace, void* device_map) {
|
|||
ASSERT_EQ(1U, backtrace->NumFrames());
|
||||
const backtrace_frame_data_t* frame = backtrace->GetFrame(0);
|
||||
ASSERT_EQ(device_map_uint, frame->pc);
|
||||
ASSERT_EQ(reinterpret_cast<uintptr_t>(&ucontext), frame->sp);
|
||||
ASSERT_EQ(reinterpret_cast<uint64_t>(&ucontext), frame->sp);
|
||||
|
||||
// Check what happens when skipping the first frame.
|
||||
ASSERT_TRUE(backtrace->Unwind(1, &ucontext));
|
||||
|
@ -1669,7 +1670,7 @@ static void UnwindThroughSignal(bool use_action, create_func_t create_func,
|
|||
std::unique_ptr<BacktraceMap> map(map_create_func(pid, false));
|
||||
std::unique_ptr<Backtrace> backtrace(create_func(pid, pid, map.get()));
|
||||
|
||||
size_t bytes_read = backtrace->Read(reinterpret_cast<uintptr_t>(const_cast<int*>(&value)),
|
||||
size_t bytes_read = backtrace->Read(reinterpret_cast<uint64_t>(const_cast<int*>(&value)),
|
||||
reinterpret_cast<uint8_t*>(&read_value), sizeof(read_value));
|
||||
ASSERT_EQ(sizeof(read_value), bytes_read);
|
||||
|
||||
|
|
|
@ -26,11 +26,11 @@
|
|||
#include <backtrace/backtrace_constants.h>
|
||||
#include <backtrace/BacktraceMap.h>
|
||||
|
||||
#if __LP64__
|
||||
#define PRIPTR "016" PRIxPTR
|
||||
#if defined(__LP64__)
|
||||
#define PRIPTR "016" PRIx64
|
||||
typedef uint64_t word_t;
|
||||
#else
|
||||
#define PRIPTR "08" PRIxPTR
|
||||
#define PRIPTR "08" PRIx64
|
||||
typedef uint32_t word_t;
|
||||
#endif
|
||||
|
||||
|
@ -77,14 +77,15 @@ struct BacktraceUnwindError {
|
|||
|
||||
struct backtrace_frame_data_t {
|
||||
size_t num; // The current fame number.
|
||||
uintptr_t pc; // The absolute pc.
|
||||
uintptr_t rel_pc; // The relative pc.
|
||||
uintptr_t sp; // The top of the stack.
|
||||
uint64_t pc; // The absolute pc.
|
||||
uint64_t rel_pc; // The relative pc.
|
||||
uint64_t sp; // The top of the stack.
|
||||
size_t stack_size; // The size of the stack, zero indicate an unknown stack size.
|
||||
uint64_t dex_pc; // If non-zero, the Dex PC for the ART interpreter.
|
||||
backtrace_map_t map; // The map associated with the given pc.
|
||||
std::string func_name; // The function name associated with this pc, NULL if not found.
|
||||
uintptr_t func_offset; // pc relative to the start of the function, only valid if func_name is not NULL.
|
||||
uint64_t func_offset; // pc relative to the start of the function, only valid if func_name is not
|
||||
// NULL.
|
||||
};
|
||||
|
||||
#if defined(__APPLE__)
|
||||
|
@ -139,20 +140,20 @@ public:
|
|||
// Get the function name and offset into the function given the pc.
|
||||
// If the string is empty, then no valid function name was found,
|
||||
// or the pc is not in any valid map.
|
||||
virtual std::string GetFunctionName(uintptr_t pc, uintptr_t* offset,
|
||||
virtual std::string GetFunctionName(uint64_t pc, uint64_t* offset,
|
||||
const backtrace_map_t* map = NULL);
|
||||
|
||||
// Fill in the map data associated with the given pc.
|
||||
virtual void FillInMap(uintptr_t pc, backtrace_map_t* map);
|
||||
virtual void FillInMap(uint64_t pc, backtrace_map_t* map);
|
||||
|
||||
// Read the data at a specific address.
|
||||
virtual bool ReadWord(uintptr_t ptr, word_t* out_value) = 0;
|
||||
virtual bool ReadWord(uint64_t ptr, word_t* out_value) = 0;
|
||||
|
||||
// Read arbitrary data from a specific address. If a read request would
|
||||
// span from one map to another, this call only reads up until the end
|
||||
// of the current map.
|
||||
// Returns the total number of bytes actually read.
|
||||
virtual size_t Read(uintptr_t addr, uint8_t* buffer, size_t bytes) = 0;
|
||||
virtual size_t Read(uint64_t addr, uint8_t* buffer, size_t bytes) = 0;
|
||||
|
||||
// Create a string representing the formatted line of backtrace information
|
||||
// for a single frame.
|
||||
|
@ -189,9 +190,9 @@ protected:
|
|||
|
||||
// The name returned is not demangled, GetFunctionName() takes care of
|
||||
// demangling the name.
|
||||
virtual std::string GetFunctionNameRaw(uintptr_t pc, uintptr_t* offset) = 0;
|
||||
virtual std::string GetFunctionNameRaw(uint64_t pc, uint64_t* offset) = 0;
|
||||
|
||||
virtual bool VerifyReadWordArgs(uintptr_t ptr, word_t* out_value);
|
||||
virtual bool VerifyReadWordArgs(uint64_t ptr, word_t* out_value);
|
||||
|
||||
bool BuildMap();
|
||||
|
||||
|
|
|
@ -39,10 +39,10 @@
|
|||
static constexpr int PROT_DEVICE_MAP = 0x8000;
|
||||
|
||||
struct backtrace_map_t {
|
||||
uintptr_t start = 0;
|
||||
uintptr_t end = 0;
|
||||
uintptr_t offset = 0;
|
||||
uintptr_t load_bias = 0;
|
||||
uint64_t start = 0;
|
||||
uint64_t end = 0;
|
||||
uint64_t offset = 0;
|
||||
uint64_t load_bias = 0;
|
||||
int flags = 0;
|
||||
std::string name;
|
||||
};
|
||||
|
@ -91,7 +91,7 @@ public:
|
|||
return nullptr;
|
||||
}
|
||||
backtrace_map_t* map = &map_->maps_[index_];
|
||||
if (map->load_bias == static_cast<uintptr_t>(-1)) {
|
||||
if (map->load_bias == static_cast<uint64_t>(-1)) {
|
||||
map->load_bias = map_->GetLoadBias(index_);
|
||||
}
|
||||
return map;
|
||||
|
@ -106,15 +106,15 @@ public:
|
|||
iterator end() { return iterator(this, maps_.size()); }
|
||||
|
||||
// Fill in the map data structure for the given address.
|
||||
virtual void FillIn(uintptr_t addr, backtrace_map_t* map);
|
||||
virtual void FillIn(uint64_t addr, backtrace_map_t* map);
|
||||
|
||||
// Only supported with the new unwinder.
|
||||
virtual std::string GetFunctionName(uintptr_t /*pc*/, uintptr_t* /*offset*/) { return ""; }
|
||||
virtual std::string GetFunctionName(uint64_t /*pc*/, uint64_t* /*offset*/) { return ""; }
|
||||
virtual std::shared_ptr<unwindstack::Memory> GetProcessMemory() { return nullptr; }
|
||||
|
||||
// The flags returned are the same flags as used by the mmap call.
|
||||
// The values are PROT_*.
|
||||
int GetFlags(uintptr_t pc) {
|
||||
int GetFlags(uint64_t pc) {
|
||||
backtrace_map_t map;
|
||||
FillIn(pc, &map);
|
||||
if (IsValid(map)) {
|
||||
|
@ -123,9 +123,9 @@ public:
|
|||
return PROT_NONE;
|
||||
}
|
||||
|
||||
bool IsReadable(uintptr_t pc) { return GetFlags(pc) & PROT_READ; }
|
||||
bool IsWritable(uintptr_t pc) { return GetFlags(pc) & PROT_WRITE; }
|
||||
bool IsExecutable(uintptr_t pc) { return GetFlags(pc) & PROT_EXEC; }
|
||||
bool IsReadable(uint64_t pc) { return GetFlags(pc) & PROT_READ; }
|
||||
bool IsWritable(uint64_t pc) { return GetFlags(pc) & PROT_WRITE; }
|
||||
bool IsExecutable(uint64_t pc) { return GetFlags(pc) & PROT_EXEC; }
|
||||
|
||||
// In order to use the iterators on this object, a caller must
|
||||
// call the LockIterator and UnlockIterator function to guarantee
|
||||
|
|
Loading…
Reference in New Issue