123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261 |
- /*
- * Copyright (C) 2017 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.
- */
- #define _GNU_SOURCE 1
- #include <stdint.h>
- #include <stdlib.h>
- #include <string.h>
- #include <memory>
- #include <set>
- #include <string>
- #include <backtrace/Backtrace.h>
- #include <demangle.h>
- #include <unwindstack/Elf.h>
- #include <unwindstack/MapInfo.h>
- #include <unwindstack/Maps.h>
- #include <unwindstack/Memory.h>
- #include <unwindstack/Regs.h>
- #include <unwindstack/RegsGetLocal.h>
- #if !defined(NO_LIBDEXFILE_SUPPORT)
- #include <unwindstack/DexFiles.h>
- #endif
- #include <unwindstack/Unwinder.h>
- #include "BacktraceLog.h"
- #include "UnwindStack.h"
- #include "UnwindStackMap.h"
- bool Backtrace::Unwind(unwindstack::Regs* regs, BacktraceMap* back_map,
- std::vector<backtrace_frame_data_t>* frames, size_t num_ignore_frames,
- std::vector<std::string>* skip_names, BacktraceUnwindError* error) {
- UnwindStackMap* stack_map = reinterpret_cast<UnwindStackMap*>(back_map);
- auto process_memory = stack_map->process_memory();
- unwindstack::Unwinder unwinder(MAX_BACKTRACE_FRAMES + num_ignore_frames, stack_map->stack_maps(),
- regs, stack_map->process_memory());
- unwinder.SetResolveNames(stack_map->ResolveNames());
- stack_map->SetArch(regs->Arch());
- if (stack_map->GetJitDebug() != nullptr) {
- unwinder.SetJitDebug(stack_map->GetJitDebug(), regs->Arch());
- }
- #if !defined(NO_LIBDEXFILE_SUPPORT)
- if (stack_map->GetDexFiles() != nullptr) {
- unwinder.SetDexFiles(stack_map->GetDexFiles(), regs->Arch());
- }
- #endif
- unwinder.Unwind(skip_names, &stack_map->GetSuffixesToIgnore());
- if (error != nullptr) {
- switch (unwinder.LastErrorCode()) {
- case unwindstack::ERROR_NONE:
- error->error_code = BACKTRACE_UNWIND_NO_ERROR;
- break;
- case unwindstack::ERROR_MEMORY_INVALID:
- error->error_code = BACKTRACE_UNWIND_ERROR_ACCESS_MEM_FAILED;
- error->error_info.addr = unwinder.LastErrorAddress();
- break;
- case unwindstack::ERROR_UNWIND_INFO:
- error->error_code = BACKTRACE_UNWIND_ERROR_UNWIND_INFO;
- break;
- case unwindstack::ERROR_UNSUPPORTED:
- error->error_code = BACKTRACE_UNWIND_ERROR_UNSUPPORTED_OPERATION;
- break;
- case unwindstack::ERROR_INVALID_MAP:
- error->error_code = BACKTRACE_UNWIND_ERROR_MAP_MISSING;
- break;
- case unwindstack::ERROR_MAX_FRAMES_EXCEEDED:
- error->error_code = BACKTRACE_UNWIND_ERROR_EXCEED_MAX_FRAMES_LIMIT;
- break;
- case unwindstack::ERROR_REPEATED_FRAME:
- error->error_code = BACKTRACE_UNWIND_ERROR_REPEATED_FRAME;
- break;
- case unwindstack::ERROR_INVALID_ELF:
- error->error_code = BACKTRACE_UNWIND_ERROR_INVALID_ELF;
- break;
- }
- }
- if (num_ignore_frames >= unwinder.NumFrames()) {
- frames->resize(0);
- return true;
- }
- auto unwinder_frames = unwinder.frames();
- frames->resize(unwinder.NumFrames() - num_ignore_frames);
- size_t cur_frame = 0;
- for (size_t i = num_ignore_frames; i < unwinder.NumFrames(); i++) {
- auto frame = &unwinder_frames[i];
- backtrace_frame_data_t* back_frame = &frames->at(cur_frame);
- back_frame->num = cur_frame++;
- back_frame->rel_pc = frame->rel_pc;
- back_frame->pc = frame->pc;
- back_frame->sp = frame->sp;
- back_frame->func_name = demangle(frame->function_name.c_str());
- back_frame->func_offset = frame->function_offset;
- back_frame->map.name = frame->map_name;
- back_frame->map.start = frame->map_start;
- back_frame->map.end = frame->map_end;
- back_frame->map.offset = frame->map_elf_start_offset;
- back_frame->map.load_bias = frame->map_load_bias;
- back_frame->map.flags = frame->map_flags;
- }
- return true;
- }
- bool Backtrace::UnwindOffline(unwindstack::Regs* regs, BacktraceMap* back_map,
- const backtrace_stackinfo_t& stack,
- std::vector<backtrace_frame_data_t>* frames,
- BacktraceUnwindError* error) {
- UnwindStackOfflineMap* offline_map = reinterpret_cast<UnwindStackOfflineMap*>(back_map);
- // Create the process memory from the stack data since this will almost
- // always be different each unwind.
- if (!offline_map->CreateProcessMemory(stack)) {
- if (error != nullptr) {
- error->error_code = BACKTRACE_UNWIND_ERROR_SETUP_FAILED;
- }
- return false;
- }
- return Backtrace::Unwind(regs, back_map, frames, 0U, nullptr, error);
- }
- UnwindStackCurrent::UnwindStackCurrent(pid_t pid, pid_t tid, BacktraceMap* map)
- : BacktraceCurrent(pid, tid, map) {}
- std::string UnwindStackCurrent::GetFunctionNameRaw(uint64_t pc, uint64_t* offset) {
- return GetMap()->GetFunctionName(pc, offset);
- }
- bool UnwindStackCurrent::UnwindFromContext(size_t num_ignore_frames, void* ucontext) {
- std::unique_ptr<unwindstack::Regs> regs;
- if (ucontext == nullptr) {
- regs.reset(unwindstack::Regs::CreateFromLocal());
- // Fill in the registers from this function. Do it here to avoid
- // one extra function call appearing in the unwind.
- unwindstack::RegsGetLocal(regs.get());
- } else {
- regs.reset(unwindstack::Regs::CreateFromUcontext(unwindstack::Regs::CurrentArch(), ucontext));
- }
- std::vector<std::string> skip_names{"libunwindstack.so", "libbacktrace.so"};
- if (!skip_frames_) {
- skip_names.clear();
- }
- return Backtrace::Unwind(regs.get(), GetMap(), &frames_, num_ignore_frames, &skip_names, &error_);
- }
- UnwindStackPtrace::UnwindStackPtrace(pid_t pid, pid_t tid, BacktraceMap* map)
- : BacktracePtrace(pid, tid, map), memory_(pid) {}
- std::string UnwindStackPtrace::GetFunctionNameRaw(uint64_t pc, uint64_t* offset) {
- return GetMap()->GetFunctionName(pc, offset);
- }
- bool UnwindStackPtrace::Unwind(size_t num_ignore_frames, void* context) {
- std::unique_ptr<unwindstack::Regs> regs;
- if (context == nullptr) {
- regs.reset(unwindstack::Regs::RemoteGet(Tid()));
- } else {
- regs.reset(unwindstack::Regs::CreateFromUcontext(unwindstack::Regs::CurrentArch(), context));
- }
- return Backtrace::Unwind(regs.get(), GetMap(), &frames_, num_ignore_frames, nullptr, &error_);
- }
- size_t UnwindStackPtrace::Read(uint64_t addr, uint8_t* buffer, size_t bytes) {
- return memory_.Read(addr, buffer, bytes);
- }
- UnwindStackOffline::UnwindStackOffline(ArchEnum arch, pid_t pid, pid_t tid, BacktraceMap* map,
- bool map_shared)
- : Backtrace(pid, tid, map), arch_(arch) {
- map_shared_ = map_shared;
- }
- bool UnwindStackOffline::Unwind(size_t num_ignore_frames, void* ucontext) {
- if (ucontext == nullptr) {
- return false;
- }
- unwindstack::ArchEnum arch;
- switch (arch_) {
- case ARCH_ARM:
- arch = unwindstack::ARCH_ARM;
- break;
- case ARCH_ARM64:
- arch = unwindstack::ARCH_ARM64;
- break;
- case ARCH_X86:
- arch = unwindstack::ARCH_X86;
- break;
- case ARCH_X86_64:
- arch = unwindstack::ARCH_X86_64;
- break;
- default:
- return false;
- }
- std::unique_ptr<unwindstack::Regs> regs(unwindstack::Regs::CreateFromUcontext(arch, ucontext));
- return Backtrace::Unwind(regs.get(), GetMap(), &frames_, num_ignore_frames, nullptr, &error_);
- }
- std::string UnwindStackOffline::GetFunctionNameRaw(uint64_t, uint64_t*) {
- return "";
- }
- size_t UnwindStackOffline::Read(uint64_t, uint8_t*, size_t) {
- return 0;
- }
- bool UnwindStackOffline::ReadWord(uint64_t, word_t*) {
- return false;
- }
- Backtrace* Backtrace::CreateOffline(ArchEnum arch, pid_t pid, pid_t tid,
- const std::vector<backtrace_map_t>& maps,
- const backtrace_stackinfo_t& stack) {
- std::unique_ptr<UnwindStackOfflineMap> map(
- reinterpret_cast<UnwindStackOfflineMap*>(BacktraceMap::CreateOffline(pid, maps)));
- if (map.get() == nullptr || !map->CreateProcessMemory(stack)) {
- return nullptr;
- }
- return new UnwindStackOffline(arch, pid, tid, map.release(), false);
- }
- Backtrace* Backtrace::CreateOffline(ArchEnum arch, pid_t pid, pid_t tid, BacktraceMap* map) {
- if (map == nullptr) {
- return nullptr;
- }
- return new UnwindStackOffline(arch, pid, tid, map, true);
- }
- void Backtrace::SetGlobalElfCache(bool enable) {
- unwindstack::Elf::SetCachingEnabled(enable);
- }
|