diff options
-rw-r--r-- | debuggerd/crash_dump.cpp | 4 | ||||
-rw-r--r-- | debuggerd/handler/debuggerd_fallback.cpp | 10 | ||||
-rw-r--r-- | debuggerd/libdebuggerd/backtrace.cpp | 9 | ||||
-rw-r--r-- | debuggerd/libdebuggerd/tombstone.cpp | 10 | ||||
-rw-r--r-- | libbacktrace/BacktraceCurrent.cpp | 12 | ||||
-rw-r--r-- | libbacktrace/UnwindStack.cpp | 9 | ||||
-rw-r--r-- | libunwindstack/Android.bp | 2 | ||||
-rw-r--r-- | libunwindstack/Unwinder.cpp | 52 | ||||
-rw-r--r-- | libunwindstack/include/unwindstack/Arch.h | 47 | ||||
-rw-r--r-- | libunwindstack/include/unwindstack/Elf.h | 11 | ||||
-rw-r--r-- | libunwindstack/include/unwindstack/Error.h | 21 | ||||
-rw-r--r-- | libunwindstack/include/unwindstack/Regs.h | 7 | ||||
-rw-r--r-- | libunwindstack/include/unwindstack/Unwinder.h | 42 | ||||
-rw-r--r-- | libunwindstack/tests/UnwindOfflineTest.cpp | 8 | ||||
-rw-r--r-- | libunwindstack/tests/UnwindTest.cpp | 3 | ||||
-rw-r--r-- | libunwindstack/tests/UnwinderTest.cpp | 21 | ||||
-rw-r--r-- | libunwindstack/tests/VerifyBionicTerminationTest.cpp | 1 | ||||
-rw-r--r-- | libunwindstack/tests/fuzz/UnwinderFuzz.cpp | 2 | ||||
-rw-r--r-- | libunwindstack/tools/unwind.cpp | 5 | ||||
-rw-r--r-- | libunwindstack/tools/unwind_for_offline.cpp | 4 |
20 files changed, 203 insertions, 77 deletions
diff --git a/debuggerd/crash_dump.cpp b/debuggerd/crash_dump.cpp index c52c6f7413..5280121988 100644 --- a/debuggerd/crash_dump.cpp +++ b/debuggerd/crash_dump.cpp @@ -597,8 +597,8 @@ int main(int argc, char** argv) { } // TODO: Use seccomp to lock ourselves down. - unwindstack::UnwinderFromPid unwinder(256, vm_pid); - if (!unwinder.Init(unwindstack::Regs::CurrentArch())) { + unwindstack::UnwinderFromPid unwinder(256, vm_pid, unwindstack::Regs::CurrentArch()); + if (!unwinder.Init()) { LOG(FATAL) << "Failed to init unwinder object."; } diff --git a/debuggerd/handler/debuggerd_fallback.cpp b/debuggerd/handler/debuggerd_fallback.cpp index 9bcbdb36a3..abcb2c4ed5 100644 --- a/debuggerd/handler/debuggerd_fallback.cpp +++ b/debuggerd/handler/debuggerd_fallback.cpp @@ -82,16 +82,12 @@ static void debuggerd_fallback_trace(int output_fd, ucontext_t* ucontext) { thread.pid = getpid(); thread.tid = gettid(); thread.thread_name = get_thread_name(gettid()); - unwindstack::ArchEnum arch = unwindstack::Regs::CurrentArch(); - thread.registers.reset(unwindstack::Regs::CreateFromUcontext(arch, ucontext)); + thread.registers.reset( + unwindstack::Regs::CreateFromUcontext(unwindstack::Regs::CurrentArch(), ucontext)); // TODO: Create this once and store it in a global? unwindstack::UnwinderFromPid unwinder(kMaxFrames, getpid()); - if (unwinder.Init(arch)) { - dump_backtrace_thread(output_fd, &unwinder, thread); - } else { - async_safe_format_log(ANDROID_LOG_ERROR, "libc", "Unable to init unwinder."); - } + dump_backtrace_thread(output_fd, &unwinder, thread); } __linker_disable_fallback_allocator(); } diff --git a/debuggerd/libdebuggerd/backtrace.cpp b/debuggerd/libdebuggerd/backtrace.cpp index f5a873c4d3..c543a83921 100644 --- a/debuggerd/libdebuggerd/backtrace.cpp +++ b/debuggerd/libdebuggerd/backtrace.cpp @@ -18,8 +18,9 @@ #include "libdebuggerd/backtrace.h" -#include <errno.h> #include <dirent.h> +#include <errno.h> +#include <inttypes.h> #include <limits.h> #include <stddef.h> #include <stdio.h> @@ -65,7 +66,11 @@ void dump_backtrace_thread(int output_fd, unwindstack::Unwinder* unwinder, unwinder->SetRegs(thread.registers.get()); unwinder->Unwind(); if (unwinder->NumFrames() == 0) { - _LOG(&log, logtype::THREAD, "Unwind failed: tid = %d", thread.tid); + _LOG(&log, logtype::THREAD, "Unwind failed: tid = %d\n", thread.tid); + 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; } diff --git a/debuggerd/libdebuggerd/tombstone.cpp b/debuggerd/libdebuggerd/tombstone.cpp index e1fe82b6d9..d88c5a93d1 100644 --- a/debuggerd/libdebuggerd/tombstone.cpp +++ b/debuggerd/libdebuggerd/tombstone.cpp @@ -407,7 +407,11 @@ static bool dump_thread(log_t* log, unwindstack::Unwinder* unwinder, const Threa unwinder->SetRegs(regs_copy.get()); unwinder->Unwind(); if (unwinder->NumFrames() == 0) { - _LOG(log, logtype::THREAD, "Failed to unwind"); + _LOG(log, logtype::THREAD, "Failed to unwind\n"); + 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()); + } } else { _LOG(log, logtype::BACKTRACE, "\nbacktrace:\n"); log_backtrace(log, unwinder, " "); @@ -578,8 +582,8 @@ void engrave_tombstone_ucontext(int tombstone_fd, uint64_t abort_msg_address, si .siginfo = siginfo, }; - unwindstack::UnwinderFromPid unwinder(kMaxFrames, pid); - if (!unwinder.Init(unwindstack::Regs::CurrentArch())) { + unwindstack::UnwinderFromPid unwinder(kMaxFrames, pid, unwindstack::Regs::CurrentArch()); + if (!unwinder.Init()) { LOG(FATAL) << "Failed to init unwinder object."; } diff --git a/libbacktrace/BacktraceCurrent.cpp b/libbacktrace/BacktraceCurrent.cpp index 038b59e15c..a5065752d6 100644 --- a/libbacktrace/BacktraceCurrent.cpp +++ b/libbacktrace/BacktraceCurrent.cpp @@ -37,6 +37,12 @@ #include "ThreadEntry.h" bool BacktraceCurrent::ReadWord(uint64_t ptr, word_t* out_value) { +#if defined(__aarch64__) + // Tagged pointer after Android R would lead top byte to have random values + // https://source.android.com/devices/tech/debug/tagged-pointers + ptr &= (1ULL << 56) - 1; +#endif + if (!VerifyReadWordArgs(ptr, out_value)) { return false; } @@ -54,6 +60,12 @@ bool BacktraceCurrent::ReadWord(uint64_t ptr, word_t* out_value) { } size_t BacktraceCurrent::Read(uint64_t addr, uint8_t* buffer, size_t bytes) { +#if defined(__aarch64__) + // Tagged pointer after Android R would lead top byte to have random values + // https://source.android.com/devices/tech/debug/tagged-pointers + addr &= (1ULL << 56) - 1; +#endif + backtrace_map_t map; FillInMap(addr, &map); if (!BacktraceMap::IsValid(map) || !(map.flags & PROT_READ)) { diff --git a/libbacktrace/UnwindStack.cpp b/libbacktrace/UnwindStack.cpp index 624711f797..82ff21c092 100644 --- a/libbacktrace/UnwindStack.cpp +++ b/libbacktrace/UnwindStack.cpp @@ -52,11 +52,11 @@ bool Backtrace::Unwind(unwindstack::Regs* regs, BacktraceMap* back_map, unwinder.SetResolveNames(stack_map->ResolveNames()); stack_map->SetArch(regs->Arch()); if (stack_map->GetJitDebug() != nullptr) { - unwinder.SetJitDebug(stack_map->GetJitDebug(), regs->Arch()); + unwinder.SetJitDebug(stack_map->GetJitDebug()); } #if !defined(NO_LIBDEXFILE_SUPPORT) if (stack_map->GetDexFiles() != nullptr) { - unwinder.SetDexFiles(stack_map->GetDexFiles(), regs->Arch()); + unwinder.SetDexFiles(stack_map->GetDexFiles()); } #endif unwinder.Unwind(skip_names, &stack_map->GetSuffixesToIgnore()); @@ -180,5 +180,10 @@ bool UnwindStackPtrace::Unwind(size_t num_ignore_frames, void* context) { } size_t UnwindStackPtrace::Read(uint64_t addr, uint8_t* buffer, size_t bytes) { +#if defined(__aarch64__) + // Tagged pointer after Android R would lead top byte to have random values + // https://source.android.com/devices/tech/debug/tagged-pointers + addr &= (1ULL << 56) - 1; +#endif return memory_->Read(addr, buffer, bytes); } diff --git a/libunwindstack/Android.bp b/libunwindstack/Android.bp index 8cc780acdf..75a419c848 100644 --- a/libunwindstack/Android.bp +++ b/libunwindstack/Android.bp @@ -131,7 +131,6 @@ cc_library { support_system_process: true, }, defaults: ["libunwindstack_defaults"], - srcs: ["DexFile.cpp"], cflags: ["-DDEXFILE_SUPPORT"], shared_libs: ["libdexfile_support"], @@ -168,6 +167,7 @@ cc_library_static { defaults: ["libunwindstack_defaults"], visibility: [ + "//external/gwp_asan", "//system/core/debuggerd", "//system/core/init", "//system/core/libbacktrace", diff --git a/libunwindstack/Unwinder.cpp b/libunwindstack/Unwinder.cpp index 57806c157c..bcdbde8d9b 100644 --- a/libunwindstack/Unwinder.cpp +++ b/libunwindstack/Unwinder.cpp @@ -27,6 +27,7 @@ #include <android-base/stringprintf.h> #include <android-base/strings.h> +#include <unwindstack/DexFiles.h> #include <unwindstack/Elf.h> #include <unwindstack/JitDebug.h> #include <unwindstack/MapInfo.h> @@ -34,7 +35,7 @@ #include <unwindstack/Memory.h> #include <unwindstack/Unwinder.h> -#include <unwindstack/DexFiles.h> +#include "Check.h" // Use the demangler from libc++. extern "C" char* __cxa_demangle(const char*, char*, size_t*, int* status); @@ -142,14 +143,12 @@ static bool ShouldStop(const std::vector<std::string>* map_suffixes_to_ignore, void Unwinder::Unwind(const std::vector<std::string>* initial_map_names_to_skip, const std::vector<std::string>* map_suffixes_to_ignore) { + CHECK(arch_ != ARCH_UNKNOWN); + ClearErrors(); + frames_.clear(); - warnings_ = WARNING_NONE; - last_error_.code = ERROR_NONE; - last_error_.address = 0; elf_from_memory_not_file_ = false; - ArchEnum arch = regs_->Arch(); - bool return_address_attempt = false; bool adjust_pc = false; for (; frames_.size() < max_frames_;) { @@ -169,7 +168,7 @@ void Unwinder::Unwind(const std::vector<std::string>* initial_map_names_to_skip, if (ShouldStop(map_suffixes_to_ignore, map_info->name)) { break; } - elf = map_info->GetElf(process_memory_, arch); + elf = map_info->GetElf(process_memory_, arch_); // If this elf is memory backed, and there is a valid file, then set // an indicator that we couldn't open the file. if (!elf_from_memory_not_file_ && map_info->memory_backed_elf && !map_info->name.empty() && @@ -183,7 +182,7 @@ void Unwinder::Unwind(const std::vector<std::string>* initial_map_names_to_skip, step_pc = rel_pc; } if (adjust_pc) { - pc_adjustment = GetPcAdjustment(rel_pc, elf, arch); + pc_adjustment = GetPcAdjustment(rel_pc, elf, arch_); } else { pc_adjustment = 0; } @@ -311,7 +310,7 @@ void Unwinder::Unwind(const std::vector<std::string>* initial_map_names_to_skip, std::string Unwinder::FormatFrame(const FrameData& frame) const { std::string data; - if (regs_->Is32Bit()) { + if (ArchIs32Bit(arch_)) { data += android::base::StringPrintf(" #%02zu pc %08" PRIx64, frame.num, frame.rel_pc); } else { data += android::base::StringPrintf(" #%02zu pc %016" PRIx64, frame.num, frame.rel_pc); @@ -362,23 +361,33 @@ std::string Unwinder::FormatFrame(size_t frame_num) const { return FormatFrame(frames_[frame_num]); } -void Unwinder::SetJitDebug(JitDebug* jit_debug, ArchEnum arch) { - jit_debug->SetArch(arch); +void Unwinder::SetJitDebug(JitDebug* jit_debug) { + CHECK(arch_ != ARCH_UNKNOWN); + jit_debug->SetArch(arch_); jit_debug_ = jit_debug; } -void Unwinder::SetDexFiles(DexFiles* dex_files, ArchEnum arch) { - dex_files->SetArch(arch); +void Unwinder::SetDexFiles(DexFiles* dex_files) { + CHECK(arch_ != ARCH_UNKNOWN); + dex_files->SetArch(arch_); dex_files_ = dex_files; } -bool UnwinderFromPid::Init(ArchEnum arch) { +bool UnwinderFromPid::Init() { + CHECK(arch_ != ARCH_UNKNOWN); + if (initted_) { + return true; + } + initted_ = true; + if (pid_ == getpid()) { maps_ptr_.reset(new LocalMaps()); } else { maps_ptr_.reset(new RemoteMaps(pid_)); } if (!maps_ptr_->Parse()) { + ClearErrors(); + last_error_.code = ERROR_INVALID_MAP; return false; } maps_ = maps_ptr_.get(); @@ -387,16 +396,24 @@ bool UnwinderFromPid::Init(ArchEnum arch) { jit_debug_ptr_.reset(new JitDebug(process_memory_)); jit_debug_ = jit_debug_ptr_.get(); - SetJitDebug(jit_debug_, arch); + SetJitDebug(jit_debug_); #if defined(DEXFILE_SUPPORT) dex_files_ptr_.reset(new DexFiles(process_memory_)); dex_files_ = dex_files_ptr_.get(); - SetDexFiles(dex_files_, arch); + SetDexFiles(dex_files_); #endif return true; } +void UnwinderFromPid::Unwind(const std::vector<std::string>* initial_map_names_to_skip, + const std::vector<std::string>* map_suffixes_to_ignore) { + if (!Init()) { + return; + } + Unwinder::Unwind(initial_map_names_to_skip, map_suffixes_to_ignore); +} + FrameData Unwinder::BuildFrameFromPcOnly(uint64_t pc, ArchEnum arch, Maps* maps, JitDebug* jit_debug, std::shared_ptr<Memory> process_memory, @@ -449,8 +466,7 @@ FrameData Unwinder::BuildFrameFromPcOnly(uint64_t pc, ArchEnum arch, Maps* maps, } FrameData Unwinder::BuildFrameFromPcOnly(uint64_t pc) { - return BuildFrameFromPcOnly(pc, regs_ ? regs_->Arch() : ARCH_UNKNOWN, maps_, jit_debug_, - process_memory_, resolve_names_); + return BuildFrameFromPcOnly(pc, arch_, maps_, jit_debug_, process_memory_, resolve_names_); } } // namespace unwindstack diff --git a/libunwindstack/include/unwindstack/Arch.h b/libunwindstack/include/unwindstack/Arch.h new file mode 100644 index 0000000000..7060004192 --- /dev/null +++ b/libunwindstack/include/unwindstack/Arch.h @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2020 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 _LIBUNWINDSTACK_ARCH_H +#define _LIBUNWINDSTACK_ARCH_H + +#include <stddef.h> + +namespace unwindstack { + +enum ArchEnum : uint8_t { + ARCH_UNKNOWN = 0, + ARCH_ARM, + ARCH_ARM64, + ARCH_X86, + ARCH_X86_64, + ARCH_MIPS, + ARCH_MIPS64, +}; + +static inline bool ArchIs32Bit(ArchEnum arch) { + switch (arch) { + case ARCH_ARM: + case ARCH_X86: + case ARCH_MIPS: + return true; + default: + return false; + } +} + +} // namespace unwindstack + +#endif // _LIBUNWINDSTACK_ARCH_H diff --git a/libunwindstack/include/unwindstack/Elf.h b/libunwindstack/include/unwindstack/Elf.h index 472ed925c6..97614b1aa3 100644 --- a/libunwindstack/include/unwindstack/Elf.h +++ b/libunwindstack/include/unwindstack/Elf.h @@ -25,6 +25,7 @@ #include <unordered_map> #include <utility> +#include <unwindstack/Arch.h> #include <unwindstack/ElfInterface.h> #include <unwindstack/Memory.h> @@ -38,16 +39,6 @@ namespace unwindstack { struct MapInfo; class Regs; -enum ArchEnum : uint8_t { - ARCH_UNKNOWN = 0, - ARCH_ARM, - ARCH_ARM64, - ARCH_X86, - ARCH_X86_64, - ARCH_MIPS, - ARCH_MIPS64, -}; - class Elf { public: Elf(Memory* memory) : memory_(memory) {} diff --git a/libunwindstack/include/unwindstack/Error.h b/libunwindstack/include/unwindstack/Error.h index 66fefe76dc..0be4572f42 100644 --- a/libunwindstack/include/unwindstack/Error.h +++ b/libunwindstack/include/unwindstack/Error.h @@ -39,6 +39,27 @@ enum ErrorCode : uint8_t { ERROR_INVALID_ELF, // Unwind in an invalid elf. }; +static inline const char* GetErrorCodeString(ErrorCode error) { + switch (error) { + case ERROR_NONE: + return "None"; + case ERROR_MEMORY_INVALID: + return "Memory Invalid"; + case ERROR_UNWIND_INFO: + return "Unwind Info"; + case ERROR_UNSUPPORTED: + return "Unsupported"; + case ERROR_INVALID_MAP: + return "Invalid Map"; + case ERROR_MAX_FRAMES_EXCEEDED: + return "Maximum Frames Exceeded"; + case ERROR_REPEATED_FRAME: + return "Repeated Frame"; + case ERROR_INVALID_ELF: + return "Invalid Elf"; + } +} + struct ErrorData { ErrorCode code; uint64_t address; // Only valid when code is ERROR_MEMORY_INVALID. diff --git a/libunwindstack/include/unwindstack/Regs.h b/libunwindstack/include/unwindstack/Regs.h index 5f42565676..1a2a70440a 100644 --- a/libunwindstack/include/unwindstack/Regs.h +++ b/libunwindstack/include/unwindstack/Regs.h @@ -24,11 +24,12 @@ #include <string> #include <vector> +#include <unwindstack/Arch.h> + namespace unwindstack { // Forward declarations. class Elf; -enum ArchEnum : uint8_t; class Memory; class Regs { @@ -52,7 +53,7 @@ class Regs { virtual ArchEnum Arch() = 0; - virtual bool Is32Bit() = 0; + bool Is32Bit() { return ArchIs32Bit(Arch()); } virtual void* RawData() = 0; virtual uint64_t pc() = 0; @@ -96,8 +97,6 @@ class RegsImpl : public Regs { : Regs(total_regs, return_loc), regs_(total_regs) {} virtual ~RegsImpl() = default; - bool Is32Bit() override { return sizeof(AddressType) == sizeof(uint32_t); } - inline AddressType& operator[](size_t reg) { return regs_[reg]; } void* RawData() override { return regs_.data(); } diff --git a/libunwindstack/include/unwindstack/Unwinder.h b/libunwindstack/include/unwindstack/Unwinder.h index 3df8aadfdd..b274c4c13d 100644 --- a/libunwindstack/include/unwindstack/Unwinder.h +++ b/libunwindstack/include/unwindstack/Unwinder.h @@ -24,6 +24,7 @@ #include <string> #include <vector> +#include <unwindstack/Arch.h> #include <unwindstack/DexFiles.h> #include <unwindstack/Error.h> #include <unwindstack/JitDebug.h> @@ -35,7 +36,6 @@ namespace unwindstack { // Forward declarations. class Elf; -enum ArchEnum : uint8_t; struct FrameData { size_t num; @@ -64,7 +64,11 @@ struct FrameData { class Unwinder { public: Unwinder(size_t max_frames, Maps* maps, Regs* regs, std::shared_ptr<Memory> process_memory) - : max_frames_(max_frames), maps_(maps), regs_(regs), process_memory_(process_memory) { + : max_frames_(max_frames), + maps_(maps), + regs_(regs), + process_memory_(process_memory), + arch_(regs->Arch()) { frames_.reserve(max_frames); } Unwinder(size_t max_frames, Maps* maps, std::shared_ptr<Memory> process_memory) @@ -74,8 +78,8 @@ class Unwinder { virtual ~Unwinder() = default; - void Unwind(const std::vector<std::string>* initial_map_names_to_skip = nullptr, - const std::vector<std::string>* map_suffixes_to_ignore = nullptr); + virtual void Unwind(const std::vector<std::string>* initial_map_names_to_skip = nullptr, + const std::vector<std::string>* map_suffixes_to_ignore = nullptr); size_t NumFrames() const { return frames_.size(); } @@ -90,9 +94,14 @@ class Unwinder { std::string FormatFrame(size_t frame_num) const; std::string FormatFrame(const FrameData& frame) const; - void SetJitDebug(JitDebug* jit_debug, ArchEnum arch); + void SetArch(ArchEnum arch) { arch_ = arch; }; + + void SetJitDebug(JitDebug* jit_debug); - void SetRegs(Regs* regs) { regs_ = regs; } + void SetRegs(Regs* regs) { + regs_ = regs; + arch_ = regs_ != nullptr ? regs->Arch() : ARCH_UNKNOWN; + } Maps* GetMaps() { return maps_; } std::shared_ptr<Memory>& GetProcessMemory() { return process_memory_; } @@ -107,11 +116,12 @@ class Unwinder { void SetDisplayBuildID(bool display_build_id) { display_build_id_ = display_build_id; } - void SetDexFiles(DexFiles* dex_files, ArchEnum arch); + void SetDexFiles(DexFiles* dex_files); bool elf_from_memory_not_file() { return elf_from_memory_not_file_; } ErrorCode LastErrorCode() { return last_error_.code; } + const char* LastErrorCodeString() { return GetErrorCodeString(last_error_.code); } uint64_t LastErrorAddress() { return last_error_.address; } uint64_t warnings() { return warnings_; } @@ -126,6 +136,15 @@ class Unwinder { protected: Unwinder(size_t max_frames) : max_frames_(max_frames) { frames_.reserve(max_frames); } + Unwinder(size_t max_frames, ArchEnum arch) : max_frames_(max_frames), arch_(arch) { + frames_.reserve(max_frames); + } + + void ClearErrors() { + warnings_ = WARNING_NONE; + last_error_.code = ERROR_NONE; + last_error_.address = 0; + } void FillInDexFrame(); FrameData* FillInFrame(MapInfo* map_info, Elf* elf, uint64_t rel_pc, uint64_t pc_adjustment); @@ -145,20 +164,27 @@ class Unwinder { bool elf_from_memory_not_file_ = false; ErrorData last_error_; uint64_t warnings_; + ArchEnum arch_ = ARCH_UNKNOWN; }; class UnwinderFromPid : public Unwinder { public: UnwinderFromPid(size_t max_frames, pid_t pid) : Unwinder(max_frames), pid_(pid) {} + UnwinderFromPid(size_t max_frames, pid_t pid, ArchEnum arch) + : Unwinder(max_frames, arch), pid_(pid) {} virtual ~UnwinderFromPid() = default; - bool Init(ArchEnum arch); + bool Init(); + + void Unwind(const std::vector<std::string>* initial_map_names_to_skip = nullptr, + const std::vector<std::string>* map_suffixes_to_ignore = nullptr) override; private: pid_t pid_; std::unique_ptr<Maps> maps_ptr_; std::unique_ptr<JitDebug> jit_debug_ptr_; std::unique_ptr<DexFiles> dex_files_ptr_; + bool initted_ = false; }; } // namespace unwindstack diff --git a/libunwindstack/tests/UnwindOfflineTest.cpp b/libunwindstack/tests/UnwindOfflineTest.cpp index c2bd8363c7..0c6f9f8caf 100644 --- a/libunwindstack/tests/UnwindOfflineTest.cpp +++ b/libunwindstack/tests/UnwindOfflineTest.cpp @@ -314,7 +314,7 @@ TEST_F(UnwindOfflineTest, jit_debug_x86) { JitDebug jit_debug(process_memory_); Unwinder unwinder(128, maps_.get(), regs_.get(), process_memory_); - unwinder.SetJitDebug(&jit_debug, regs_->Arch()); + unwinder.SetJitDebug(&jit_debug); unwinder.Unwind(); std::string frame_info(DumpFrames(unwinder)); @@ -616,7 +616,7 @@ TEST_F(UnwindOfflineTest, jit_debug_arm) { JitDebug jit_debug(process_memory_); Unwinder unwinder(128, maps_.get(), regs_.get(), process_memory_); - unwinder.SetJitDebug(&jit_debug, regs_->Arch()); + unwinder.SetJitDebug(&jit_debug); unwinder.Unwind(); std::string frame_info(DumpFrames(unwinder)); @@ -939,7 +939,7 @@ static void OfflineUnwind(void* data) { std::unique_ptr<Regs> regs_copy(leak_data->regs->Clone()); JitDebug jit_debug(leak_data->process_memory); Unwinder unwinder(128, leak_data->maps, regs_copy.get(), leak_data->process_memory); - unwinder.SetJitDebug(&jit_debug, regs_copy->Arch()); + unwinder.SetJitDebug(&jit_debug); unwinder.Unwind(); ASSERT_EQ(76U, unwinder.NumFrames()); } @@ -1062,7 +1062,7 @@ TEST_F(UnwindOfflineTest, art_quick_osr_stub_arm) { JitDebug jit_debug(process_memory_); Unwinder unwinder(128, maps_.get(), regs_.get(), process_memory_); - unwinder.SetJitDebug(&jit_debug, regs_->Arch()); + unwinder.SetJitDebug(&jit_debug); unwinder.Unwind(); std::string frame_info(DumpFrames(unwinder)); diff --git a/libunwindstack/tests/UnwindTest.cpp b/libunwindstack/tests/UnwindTest.cpp index f76a101df2..b11d213f6b 100644 --- a/libunwindstack/tests/UnwindTest.cpp +++ b/libunwindstack/tests/UnwindTest.cpp @@ -170,7 +170,6 @@ extern "C" void InnerFunction(TestTypeEnum test_type) { unwinder.reset(new Unwinder(512, maps.get(), regs.get(), process_memory)); } else { UnwinderFromPid* unwinder_from_pid = new UnwinderFromPid(512, getpid()); - ASSERT_TRUE(unwinder_from_pid->Init(regs->Arch())); unwinder_from_pid->SetRegs(regs.get()); unwinder.reset(unwinder_from_pid); } @@ -283,7 +282,6 @@ TEST_F(UnwindTest, unwind_from_pid_remote) { ASSERT_TRUE(regs.get() != nullptr); UnwinderFromPid unwinder(512, pid); - ASSERT_TRUE(unwinder.Init(regs->Arch())); unwinder.SetRegs(regs.get()); VerifyUnwind(&unwinder, kFunctionOrder); @@ -335,7 +333,6 @@ static void RemoteUnwindFromPid(void* data) { ASSERT_TRUE(regs.get() != nullptr); UnwinderFromPid unwinder(512, *pid); - ASSERT_TRUE(unwinder.Init(regs->Arch())); unwinder.SetRegs(regs.get()); VerifyUnwind(&unwinder, kFunctionOrder); diff --git a/libunwindstack/tests/UnwinderTest.cpp b/libunwindstack/tests/UnwinderTest.cpp index 915f24884f..8bae242d76 100644 --- a/libunwindstack/tests/UnwinderTest.cpp +++ b/libunwindstack/tests/UnwinderTest.cpp @@ -1182,7 +1182,7 @@ TEST_F(UnwinderTest, dex_pc_not_in_map_valid_dex_files) { DexFiles dex_files(process_memory_); Unwinder unwinder(64, maps_.get(), ®s_, process_memory_); - unwinder.SetDexFiles(&dex_files, ARCH_ARM); + unwinder.SetDexFiles(&dex_files); unwinder.Unwind(); EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode()); EXPECT_EQ(WARNING_DEX_PC_NOT_IN_MAP, unwinder.warnings()); @@ -1735,7 +1735,7 @@ TEST_F(UnwinderTest, build_frame_pc_in_jit) { regs.FakeSetArch(ARCH_ARM); JitDebug jit_debug(process_memory_); Unwinder unwinder(10, maps_.get(), ®s, process_memory_); - unwinder.SetJitDebug(&jit_debug, ARCH_ARM); + unwinder.SetJitDebug(&jit_debug); FrameData frame = unwinder.BuildFrameFromPcOnly(0x100310); EXPECT_EQ(0x10030eU, frame.pc); @@ -1751,4 +1751,21 @@ TEST_F(UnwinderTest, build_frame_pc_in_jit) { EXPECT_EQ(0xeU, frame.function_offset); } +TEST_F(UnwinderTest, unwinder_from_pid_init_error) { + UnwinderFromPid unwinder(10, getpid()); + ASSERT_DEATH(unwinder.Init(), ""); +} + +TEST_F(UnwinderTest, set_jit_debug_error) { + Unwinder unwinder(10, maps_.get(), process_memory_); + JitDebug jit_debug(process_memory_); + ASSERT_DEATH(unwinder.SetJitDebug(&jit_debug), ""); +} + +TEST_F(UnwinderTest, set_dex_files_error) { + Unwinder unwinder(10, maps_.get(), process_memory_); + DexFiles dex_files(process_memory_); + ASSERT_DEATH(unwinder.SetDexFiles(&dex_files), ""); +} + } // namespace unwindstack diff --git a/libunwindstack/tests/VerifyBionicTerminationTest.cpp b/libunwindstack/tests/VerifyBionicTerminationTest.cpp index eb2b01d297..3e67dc9407 100644 --- a/libunwindstack/tests/VerifyBionicTerminationTest.cpp +++ b/libunwindstack/tests/VerifyBionicTerminationTest.cpp @@ -94,7 +94,6 @@ TEST(VerifyBionicTermination, local_terminate) { std::unique_ptr<Regs> regs(Regs::CreateFromLocal()); UnwinderFromPid unwinder(512, getpid()); - ASSERT_TRUE(unwinder.Init(regs->Arch())); unwinder.SetRegs(regs.get()); RegsGetLocal(regs.get()); diff --git a/libunwindstack/tests/fuzz/UnwinderFuzz.cpp b/libunwindstack/tests/fuzz/UnwinderFuzz.cpp index 2f4986a198..1600547914 100644 --- a/libunwindstack/tests/fuzz/UnwinderFuzz.cpp +++ b/libunwindstack/tests/fuzz/UnwinderFuzz.cpp @@ -85,7 +85,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { // Create instance Unwinder unwinder(max_frames, maps.get(), regs.get(), memory); - unwinder.SetJitDebug(jit_debug_ptr.get(), arch); + unwinder.SetJitDebug(jit_debug_ptr.get()); unwinder.SetResolveNames(data_provider.ConsumeBool()); // Call unwind PerformUnwind(&data_provider, &unwinder); diff --git a/libunwindstack/tools/unwind.cpp b/libunwindstack/tools/unwind.cpp index 1812e50371..ae45f06bc9 100644 --- a/libunwindstack/tools/unwind.cpp +++ b/libunwindstack/tools/unwind.cpp @@ -90,11 +90,6 @@ void DoUnwind(pid_t pid) { printf("\n"); unwindstack::UnwinderFromPid unwinder(1024, pid); - if (!unwinder.Init(regs->Arch())) { - printf("Failed to init unwinder object.\n"); - return; - } - unwinder.SetRegs(regs); unwinder.Unwind(); diff --git a/libunwindstack/tools/unwind_for_offline.cpp b/libunwindstack/tools/unwind_for_offline.cpp index 64b58a83a2..c44a121bad 100644 --- a/libunwindstack/tools/unwind_for_offline.cpp +++ b/libunwindstack/tools/unwind_for_offline.cpp @@ -248,10 +248,6 @@ int SaveData(pid_t pid) { // Do an unwind so we know how much of the stack to save, and what // elf files are involved. unwindstack::UnwinderFromPid unwinder(1024, pid); - if (!unwinder.Init(regs->Arch())) { - printf("Unable to init unwinder object.\n"); - return 1; - } unwinder.SetRegs(regs); uint64_t sp = regs->sp(); unwinder.Unwind(); |