diff options
Diffstat (limited to 'libunwindstack')
24 files changed, 311 insertions, 233 deletions
diff --git a/libunwindstack/Android.bp b/libunwindstack/Android.bp index 36449ebb8..9afc9a326 100644 --- a/libunwindstack/Android.bp +++ b/libunwindstack/Android.bp @@ -35,20 +35,13 @@ cc_defaults { }, } -cc_library { - name: "libunwindstack", - vendor_available: true, - recovery_available: true, - vndk: { - enabled: true, - support_system_process: true, - }, +cc_defaults { + name: "libunwindstack_defaults", defaults: ["libunwindstack_flags"], export_include_dirs: ["include"], srcs: [ "ArmExidx.cpp", - "DexFile.cpp", "DexFiles.cpp", "DwarfCfa.cpp", "DwarfEhFrameWithHdr.cpp", @@ -77,7 +70,6 @@ cc_library { ], cflags: [ - "-DDEXFILE_SUPPORT", "-Wexit-time-destructors", ], @@ -89,24 +81,6 @@ cc_library { "-g", ], }, - vendor: { - cflags: ["-UDEXFILE_SUPPORT"], - exclude_srcs: [ - "DexFile.cpp", - ], - exclude_shared_libs: [ - "libdexfile_support", - ], - }, - recovery: { - cflags: ["-UDEXFILE_SUPPORT"], - exclude_srcs: [ - "DexFile.cpp", - ], - exclude_shared_libs: [ - "libdexfile_support", - ], - }, }, arch: { @@ -124,12 +98,56 @@ cc_library { shared_libs: [ "libbase", - "libdexfile_support", "liblog", "liblzma", ], } +cc_library { + name: "libunwindstack", + vendor_available: true, + recovery_available: true, + vndk: { + enabled: true, + support_system_process: true, + }, + defaults: ["libunwindstack_defaults"], + + srcs: ["DexFile.cpp"], + cflags: ["-DDEXFILE_SUPPORT"], + shared_libs: ["libdexfile_support"], + + target: { + vendor: { + cflags: ["-UDEXFILE_SUPPORT"], + exclude_srcs: ["DexFile.cpp"], + exclude_shared_libs: ["libdexfile_support"], + }, + recovery: { + cflags: ["-UDEXFILE_SUPPORT"], + exclude_srcs: ["DexFile.cpp"], + exclude_shared_libs: ["libdexfile_support"], + }, + }, +} + +// Static library without DEX support to avoid dependencies on the ART APEX. +cc_library_static { + name: "libunwindstack_no_dex", + recovery_available: true, + defaults: ["libunwindstack_defaults"], + + visibility: [ + "//system/core/debuggerd", + "//system/core/init", + "//system/core/libbacktrace", + ], + apex_available: [ + "//apex_available:platform", + "com.android.runtime", + ], +} + //------------------------------------------------------------------------- // Unit Tests //------------------------------------------------------------------------- diff --git a/libunwindstack/DexFile.cpp b/libunwindstack/DexFile.cpp index dff7a8b3c..bf63abf1c 100644 --- a/libunwindstack/DexFile.cpp +++ b/libunwindstack/DexFile.cpp @@ -89,7 +89,7 @@ std::unique_ptr<DexFileFromFile> DexFileFromFile::Create(uint64_t dex_file_offse return nullptr; } - return std::unique_ptr<DexFileFromFile>(new DexFileFromFile(std::move(*art_dex_file.release()))); + return std::unique_ptr<DexFileFromFile>(new DexFileFromFile(art_dex_file)); } std::unique_ptr<DexFileFromMemory> DexFileFromMemory::Create(uint64_t dex_file_offset_in_memory, @@ -108,7 +108,7 @@ std::unique_ptr<DexFileFromMemory> DexFileFromMemory::Create(uint64_t dex_file_o if (art_dex_file != nullptr) { return std::unique_ptr<DexFileFromMemory>( - new DexFileFromMemory(std::move(*art_dex_file.release()), std::move(backing_memory))); + new DexFileFromMemory(art_dex_file, std::move(backing_memory))); } if (!error_msg.empty()) { diff --git a/libunwindstack/DexFile.h b/libunwindstack/DexFile.h index ca658e688..4e8369f84 100644 --- a/libunwindstack/DexFile.h +++ b/libunwindstack/DexFile.h @@ -39,7 +39,8 @@ class DexFile : protected art_api::dex::DexFile { MapInfo* info); protected: - DexFile(art_api::dex::DexFile&& art_dex_file) : art_api::dex::DexFile(std::move(art_dex_file)) {} + DexFile(std::unique_ptr<art_api::dex::DexFile>& art_dex_file) + : art_api::dex::DexFile(art_dex_file) {} }; class DexFileFromFile : public DexFile { @@ -48,7 +49,7 @@ class DexFileFromFile : public DexFile { const std::string& file); private: - DexFileFromFile(art_api::dex::DexFile&& art_dex_file) : DexFile(std::move(art_dex_file)) {} + DexFileFromFile(std::unique_ptr<art_api::dex::DexFile>& art_dex_file) : DexFile(art_dex_file) {} }; class DexFileFromMemory : public DexFile { @@ -57,8 +58,9 @@ class DexFileFromMemory : public DexFile { Memory* memory, const std::string& name); private: - DexFileFromMemory(art_api::dex::DexFile&& art_dex_file, std::vector<uint8_t>&& memory) - : DexFile(std::move(art_dex_file)), memory_(std::move(memory)) {} + DexFileFromMemory(std::unique_ptr<art_api::dex::DexFile>& art_dex_file, + std::vector<uint8_t>&& memory) + : DexFile(art_dex_file), memory_(std::move(memory)) {} std::vector<uint8_t> memory_; }; diff --git a/libunwindstack/LocalUnwinder.cpp b/libunwindstack/LocalUnwinder.cpp index 5d8120036..05650fb2e 100644 --- a/libunwindstack/LocalUnwinder.cpp +++ b/libunwindstack/LocalUnwinder.cpp @@ -106,7 +106,7 @@ bool LocalUnwinder::Unwind(std::vector<LocalFrameData>* frame_info, size_t max_f uint64_t step_pc = rel_pc; uint64_t pc_adjustment; if (adjust_pc) { - pc_adjustment = regs->GetPcAdjustment(rel_pc, elf); + pc_adjustment = GetPcAdjustment(rel_pc, elf, arch); } else { pc_adjustment = 0; } diff --git a/libunwindstack/Regs.cpp b/libunwindstack/Regs.cpp index e0a785b3f..03aa6c205 100644 --- a/libunwindstack/Regs.cpp +++ b/libunwindstack/Regs.cpp @@ -121,4 +121,62 @@ Regs* Regs::CreateFromLocal() { return regs; } +uint64_t GetPcAdjustment(uint64_t rel_pc, Elf* elf, ArchEnum arch) { + switch (arch) { + case ARCH_ARM: { + if (!elf->valid()) { + return 2; + } + + uint64_t load_bias = elf->GetLoadBias(); + if (rel_pc < load_bias) { + if (rel_pc < 2) { + return 0; + } + return 2; + } + uint64_t adjusted_rel_pc = rel_pc - load_bias; + if (adjusted_rel_pc < 5) { + if (adjusted_rel_pc < 2) { + return 0; + } + return 2; + } + + if (adjusted_rel_pc & 1) { + // This is a thumb instruction, it could be 2 or 4 bytes. + uint32_t value; + if (!elf->memory()->ReadFully(adjusted_rel_pc - 5, &value, sizeof(value)) || + (value & 0xe000f000) != 0xe000f000) { + return 2; + } + } + return 4; + } + case ARCH_ARM64: { + if (rel_pc < 4) { + return 0; + } + return 4; + } + case ARCH_MIPS: + case ARCH_MIPS64: { + if (rel_pc < 8) { + return 0; + } + // For now, just assume no compact branches + return 8; + } + case ARCH_X86: + case ARCH_X86_64: { + if (rel_pc == 0) { + return 0; + } + return 1; + } + case ARCH_UNKNOWN: + return 0; + } +} + } // namespace unwindstack diff --git a/libunwindstack/RegsArm.cpp b/libunwindstack/RegsArm.cpp index 1b1f7ebbc..1aaa08f56 100644 --- a/libunwindstack/RegsArm.cpp +++ b/libunwindstack/RegsArm.cpp @@ -51,37 +51,6 @@ void RegsArm::set_sp(uint64_t sp) { regs_[ARM_REG_SP] = sp; } -uint64_t RegsArm::GetPcAdjustment(uint64_t rel_pc, Elf* elf) { - if (!elf->valid()) { - return 2; - } - - uint64_t load_bias = elf->GetLoadBias(); - if (rel_pc < load_bias) { - if (rel_pc < 2) { - return 0; - } - return 2; - } - uint64_t adjusted_rel_pc = rel_pc - load_bias; - if (adjusted_rel_pc < 5) { - if (adjusted_rel_pc < 2) { - return 0; - } - return 2; - } - - if (adjusted_rel_pc & 1) { - // This is a thumb instruction, it could be 2 or 4 bytes. - uint32_t value; - if (!elf->memory()->ReadFully(adjusted_rel_pc - 5, &value, sizeof(value)) || - (value & 0xe000f000) != 0xe000f000) { - return 2; - } - } - return 4; -} - bool RegsArm::SetPcFromReturnAddress(Memory*) { uint32_t lr = regs_[ARM_REG_LR]; if (regs_[ARM_REG_PC] == lr) { diff --git a/libunwindstack/RegsArm64.cpp b/libunwindstack/RegsArm64.cpp index 00b336737..5b7431a57 100644 --- a/libunwindstack/RegsArm64.cpp +++ b/libunwindstack/RegsArm64.cpp @@ -52,13 +52,6 @@ void RegsArm64::set_sp(uint64_t sp) { regs_[ARM64_REG_SP] = sp; } -uint64_t RegsArm64::GetPcAdjustment(uint64_t rel_pc, Elf*) { - if (rel_pc < 4) { - return 0; - } - return 4; -} - bool RegsArm64::SetPcFromReturnAddress(Memory*) { uint64_t lr = regs_[ARM64_REG_LR]; if (regs_[ARM64_REG_PC] == lr) { diff --git a/libunwindstack/RegsMips.cpp b/libunwindstack/RegsMips.cpp index ebefe429b..ab8469114 100644 --- a/libunwindstack/RegsMips.cpp +++ b/libunwindstack/RegsMips.cpp @@ -52,14 +52,6 @@ void RegsMips::set_sp(uint64_t sp) { regs_[MIPS_REG_SP] = static_cast<uint32_t>(sp); } -uint64_t RegsMips::GetPcAdjustment(uint64_t rel_pc, Elf*) { - if (rel_pc < 8) { - return 0; - } - // For now, just assume no compact branches - return 8; -} - bool RegsMips::SetPcFromReturnAddress(Memory*) { uint32_t ra = regs_[MIPS_REG_RA]; if (regs_[MIPS_REG_PC] == ra) { diff --git a/libunwindstack/RegsMips64.cpp b/libunwindstack/RegsMips64.cpp index be2fd22f3..7f600d362 100644 --- a/libunwindstack/RegsMips64.cpp +++ b/libunwindstack/RegsMips64.cpp @@ -52,14 +52,6 @@ void RegsMips64::set_sp(uint64_t sp) { regs_[MIPS64_REG_SP] = sp; } -uint64_t RegsMips64::GetPcAdjustment(uint64_t rel_pc, Elf*) { - if (rel_pc < 8) { - return 0; - } - // For now, just assume no compact branches - return 8; -} - bool RegsMips64::SetPcFromReturnAddress(Memory*) { uint64_t ra = regs_[MIPS64_REG_RA]; if (regs_[MIPS64_REG_PC] == ra) { diff --git a/libunwindstack/RegsX86.cpp b/libunwindstack/RegsX86.cpp index 5538fc0be..4d3c246a4 100644 --- a/libunwindstack/RegsX86.cpp +++ b/libunwindstack/RegsX86.cpp @@ -50,13 +50,6 @@ void RegsX86::set_sp(uint64_t sp) { regs_[X86_REG_SP] = static_cast<uint32_t>(sp); } -uint64_t RegsX86::GetPcAdjustment(uint64_t rel_pc, Elf*) { - if (rel_pc == 0) { - return 0; - } - return 1; -} - bool RegsX86::SetPcFromReturnAddress(Memory* process_memory) { // Attempt to get the return address from the top of the stack. uint32_t new_pc; diff --git a/libunwindstack/RegsX86_64.cpp b/libunwindstack/RegsX86_64.cpp index 5b9aa58c4..c9e245d2f 100644 --- a/libunwindstack/RegsX86_64.cpp +++ b/libunwindstack/RegsX86_64.cpp @@ -51,13 +51,6 @@ void RegsX86_64::set_sp(uint64_t sp) { regs_[X86_64_REG_SP] = sp; } -uint64_t RegsX86_64::GetPcAdjustment(uint64_t rel_pc, Elf*) { - if (rel_pc == 0) { - return 0; - } - return 1; -} - bool RegsX86_64::SetPcFromReturnAddress(Memory* process_memory) { // Attempt to get the return address from the top of the stack. uint64_t new_pc; diff --git a/libunwindstack/Unwinder.cpp b/libunwindstack/Unwinder.cpp index 1bb031947..2d867cd5e 100644 --- a/libunwindstack/Unwinder.cpp +++ b/libunwindstack/Unwinder.cpp @@ -181,7 +181,7 @@ void Unwinder::Unwind(const std::vector<std::string>* initial_map_names_to_skip, step_pc = rel_pc; } if (adjust_pc) { - pc_adjustment = regs_->GetPcAdjustment(rel_pc, elf); + pc_adjustment = GetPcAdjustment(rel_pc, elf, arch); } else { pc_adjustment = 0; } @@ -395,4 +395,54 @@ bool UnwinderFromPid::Init(ArchEnum arch) { return true; } +FrameData Unwinder::BuildFrameFromPcOnly(uint64_t pc) { + FrameData frame; + + Maps* maps = GetMaps(); + MapInfo* map_info = maps->Find(pc); + if (!map_info) { + frame.rel_pc = pc; + return frame; + } + + ArchEnum arch = Regs::CurrentArch(); + Elf* elf = map_info->GetElf(GetProcessMemory(), arch); + + uint64_t relative_pc = elf->GetRelPc(pc, map_info); + + uint64_t pc_adjustment = GetPcAdjustment(relative_pc, elf, arch); + relative_pc -= pc_adjustment; + // The debug PC may be different if the PC comes from the JIT. + uint64_t debug_pc = relative_pc; + + // If we don't have a valid ELF file, check the JIT. + if (!elf->valid()) { + JitDebug jit_debug(GetProcessMemory()); + uint64_t jit_pc = pc - pc_adjustment; + Elf* jit_elf = jit_debug.GetElf(maps, jit_pc); + if (jit_elf != nullptr) { + debug_pc = jit_pc; + elf = jit_elf; + } + } + + // Copy all the things we need into the frame for symbolization. + frame.rel_pc = relative_pc; + frame.pc = pc - pc_adjustment; + frame.map_name = map_info->name; + frame.map_elf_start_offset = map_info->elf_start_offset; + frame.map_exact_offset = map_info->offset; + frame.map_start = map_info->start; + frame.map_end = map_info->end; + frame.map_flags = map_info->flags; + frame.map_load_bias = elf->GetLoadBias(); + + if (!resolve_names_ || + !elf->GetFunctionName(relative_pc, &frame.function_name, &frame.function_offset)) { + frame.function_name = ""; + frame.function_offset = 0; + } + return frame; +} + } // namespace unwindstack diff --git a/libunwindstack/include/unwindstack/Regs.h b/libunwindstack/include/unwindstack/Regs.h index 4f761b4ef..a367e6cf1 100644 --- a/libunwindstack/include/unwindstack/Regs.h +++ b/libunwindstack/include/unwindstack/Regs.h @@ -64,8 +64,6 @@ class Regs { uint64_t dex_pc() { return dex_pc_; } void set_dex_pc(uint64_t dex_pc) { dex_pc_ = dex_pc; } - virtual uint64_t GetPcAdjustment(uint64_t rel_pc, Elf* elf) = 0; - virtual bool StepIfSignalHandler(uint64_t elf_offset, Elf* elf, Memory* process_memory) = 0; virtual bool SetPcFromReturnAddress(Memory* process_memory) = 0; @@ -110,6 +108,8 @@ class RegsImpl : public Regs { std::vector<AddressType> regs_; }; +uint64_t GetPcAdjustment(uint64_t rel_pc, Elf* elf, ArchEnum arch); + } // namespace unwindstack #endif // _LIBUNWINDSTACK_REGS_H diff --git a/libunwindstack/include/unwindstack/RegsArm.h b/libunwindstack/include/unwindstack/RegsArm.h index aa029be64..fbb34e7f8 100644 --- a/libunwindstack/include/unwindstack/RegsArm.h +++ b/libunwindstack/include/unwindstack/RegsArm.h @@ -36,8 +36,6 @@ class RegsArm : public RegsImpl<uint32_t> { ArchEnum Arch() override final; - uint64_t GetPcAdjustment(uint64_t rel_pc, Elf* elf) override; - bool SetPcFromReturnAddress(Memory* process_memory) override; bool StepIfSignalHandler(uint64_t elf_offset, Elf* elf, Memory* process_memory) override; diff --git a/libunwindstack/include/unwindstack/RegsArm64.h b/libunwindstack/include/unwindstack/RegsArm64.h index 5cd7e5ba9..2b3ddeb77 100644 --- a/libunwindstack/include/unwindstack/RegsArm64.h +++ b/libunwindstack/include/unwindstack/RegsArm64.h @@ -36,8 +36,6 @@ class RegsArm64 : public RegsImpl<uint64_t> { ArchEnum Arch() override final; - uint64_t GetPcAdjustment(uint64_t rel_pc, Elf* elf) override; - bool SetPcFromReturnAddress(Memory* process_memory) override; bool StepIfSignalHandler(uint64_t elf_offset, Elf* elf, Memory* process_memory) override; diff --git a/libunwindstack/include/unwindstack/RegsMips.h b/libunwindstack/include/unwindstack/RegsMips.h index 8164a1515..dc09b83b8 100644 --- a/libunwindstack/include/unwindstack/RegsMips.h +++ b/libunwindstack/include/unwindstack/RegsMips.h @@ -36,8 +36,6 @@ class RegsMips : public RegsImpl<uint32_t> { ArchEnum Arch() override final; - uint64_t GetPcAdjustment(uint64_t rel_pc, Elf* elf) override; - bool SetPcFromReturnAddress(Memory* process_memory) override; bool StepIfSignalHandler(uint64_t elf_offset, Elf* elf, Memory* process_memory) override; diff --git a/libunwindstack/include/unwindstack/RegsMips64.h b/libunwindstack/include/unwindstack/RegsMips64.h index c98254259..64a80dc0b 100644 --- a/libunwindstack/include/unwindstack/RegsMips64.h +++ b/libunwindstack/include/unwindstack/RegsMips64.h @@ -36,8 +36,6 @@ class RegsMips64 : public RegsImpl<uint64_t> { ArchEnum Arch() override final; - uint64_t GetPcAdjustment(uint64_t rel_pc, Elf* elf) override; - bool SetPcFromReturnAddress(Memory* process_memory) override; bool StepIfSignalHandler(uint64_t elf_offset, Elf* elf, Memory* process_memory) override; diff --git a/libunwindstack/include/unwindstack/RegsX86.h b/libunwindstack/include/unwindstack/RegsX86.h index 2323a4fc0..cfbdda661 100644 --- a/libunwindstack/include/unwindstack/RegsX86.h +++ b/libunwindstack/include/unwindstack/RegsX86.h @@ -37,8 +37,6 @@ class RegsX86 : public RegsImpl<uint32_t> { ArchEnum Arch() override final; - uint64_t GetPcAdjustment(uint64_t rel_pc, Elf* elf) override; - bool SetPcFromReturnAddress(Memory* process_memory) override; bool StepIfSignalHandler(uint64_t elf_offset, Elf* elf, Memory* process_memory) override; diff --git a/libunwindstack/include/unwindstack/RegsX86_64.h b/libunwindstack/include/unwindstack/RegsX86_64.h index 3e919a4f8..a11aef09f 100644 --- a/libunwindstack/include/unwindstack/RegsX86_64.h +++ b/libunwindstack/include/unwindstack/RegsX86_64.h @@ -37,8 +37,6 @@ class RegsX86_64 : public RegsImpl<uint64_t> { ArchEnum Arch() override final; - uint64_t GetPcAdjustment(uint64_t rel_pc, Elf* elf) override; - bool SetPcFromReturnAddress(Memory* process_memory) override; bool StepIfSignalHandler(uint64_t elf_offset, Elf* elf, Memory* process_memory) override; diff --git a/libunwindstack/include/unwindstack/Unwinder.h b/libunwindstack/include/unwindstack/Unwinder.h index 67762c0bd..4d49f236a 100644 --- a/libunwindstack/include/unwindstack/Unwinder.h +++ b/libunwindstack/include/unwindstack/Unwinder.h @@ -114,6 +114,13 @@ class Unwinder { ErrorCode LastErrorCode() { return last_error_.code; } uint64_t LastErrorAddress() { return last_error_.address; } + // Builds a frame for symbolization using the maps from this unwinder. The + // constructed frame contains just enough information to be used to symbolize + // frames collected by frame-pointer unwinding that's done outside of + // libunwindstack. This is used by tombstoned to symbolize frame pointer-based + // stack traces that are collected by tools such as GWP-ASan and MTE. + FrameData BuildFrameFromPcOnly(uint64_t pc); + protected: Unwinder(size_t max_frames) : max_frames_(max_frames) { frames_.reserve(max_frames); } diff --git a/libunwindstack/tests/DexFileTest.cpp b/libunwindstack/tests/DexFileTest.cpp index 1b54da6fb..dc935a36e 100644 --- a/libunwindstack/tests/DexFileTest.cpp +++ b/libunwindstack/tests/DexFileTest.cpp @@ -14,6 +14,7 @@ * limitations under the License. */ +#include <malloc.h> #include <stdint.h> #include <sys/types.h> #include <unistd.h> @@ -72,6 +73,37 @@ TEST(DexFileTest, from_file_open_non_zero_offset) { EXPECT_TRUE(DexFileFromFile::Create(0x100, tf.path) != nullptr); } +static constexpr size_t kNumLeakLoops = 5000; +static constexpr size_t kMaxAllowedLeakBytes = 1024; + +static void CheckForLeak(size_t loop, size_t* first_allocated_bytes, size_t* last_allocated_bytes) { + size_t allocated_bytes = mallinfo().uordblks; + if (*first_allocated_bytes == 0) { + *first_allocated_bytes = allocated_bytes; + } else if (*last_allocated_bytes > *first_allocated_bytes) { + // Check that the total memory did not increase too much over the first loop. + ASSERT_LE(*last_allocated_bytes - *first_allocated_bytes, kMaxAllowedLeakBytes) + << "Failed in loop " << loop << " first_allocated_bytes " << *first_allocated_bytes + << " last_allocated_bytes " << *last_allocated_bytes; + } + *last_allocated_bytes = allocated_bytes; +} + +TEST(DexFileTest, from_file_no_leak) { + TemporaryFile tf; + ASSERT_TRUE(tf.fd != -1); + + ASSERT_EQ(sizeof(kDexData), + static_cast<size_t>(TEMP_FAILURE_RETRY(write(tf.fd, kDexData, sizeof(kDexData))))); + + size_t first_allocated_bytes = 0; + size_t last_allocated_bytes = 0; + for (size_t i = 0; i < kNumLeakLoops; i++) { + EXPECT_TRUE(DexFileFromFile::Create(0, tf.path) != nullptr); + ASSERT_NO_FATAL_FAILURE(CheckForLeak(i, &first_allocated_bytes, &last_allocated_bytes)); + } +} + TEST(DexFileTest, from_memory_fail_too_small_for_header) { MemoryFake memory; @@ -96,6 +128,19 @@ TEST(DexFileTest, from_memory_open) { EXPECT_TRUE(DexFileFromMemory::Create(0x1000, &memory, "") != nullptr); } +TEST(DexFileTest, from_memory_no_leak) { + MemoryFake memory; + + memory.SetMemory(0x1000, kDexData, sizeof(kDexData)); + + size_t first_allocated_bytes = 0; + size_t last_allocated_bytes = 0; + for (size_t i = 0; i < kNumLeakLoops; i++) { + EXPECT_TRUE(DexFileFromMemory::Create(0x1000, &memory, "") != nullptr); + ASSERT_NO_FATAL_FAILURE(CheckForLeak(i, &first_allocated_bytes, &last_allocated_bytes)); + } +} + TEST(DexFileTest, create_using_file) { TemporaryFile tf; ASSERT_TRUE(tf.fd != -1); diff --git a/libunwindstack/tests/RegsFake.h b/libunwindstack/tests/RegsFake.h index 207d46efe..75fc9d02d 100644 --- a/libunwindstack/tests/RegsFake.h +++ b/libunwindstack/tests/RegsFake.h @@ -54,8 +54,6 @@ class RegsFake : public Regs { return fake_arch_ == ARCH_ARM || fake_arch_ == ARCH_X86 || fake_arch_ == ARCH_MIPS; } - uint64_t GetPcAdjustment(uint64_t, Elf*) override { return 2; } - bool StepIfSignalHandler(uint64_t, Elf*, Memory*) override { return false; } void FakeSetArch(ArchEnum arch) { fake_arch_ = arch; } @@ -86,7 +84,6 @@ class RegsImplFake : public RegsImpl<TypeParam> { void set_pc(uint64_t pc) override { fake_pc_ = pc; } void set_sp(uint64_t sp) override { fake_sp_ = sp; } - uint64_t GetPcAdjustment(uint64_t, Elf*) override { return 0; } bool SetPcFromReturnAddress(Memory*) override { return false; } bool StepIfSignalHandler(uint64_t, Elf*, Memory*) override { return false; } diff --git a/libunwindstack/tests/RegsTest.cpp b/libunwindstack/tests/RegsTest.cpp index 0a33e2ff4..e4fc6f070 100644 --- a/libunwindstack/tests/RegsTest.cpp +++ b/libunwindstack/tests/RegsTest.cpp @@ -93,123 +93,104 @@ TEST_F(RegsTest, regs64) { } TEST_F(RegsTest, rel_pc) { - RegsArm64 arm64; - EXPECT_EQ(4U, arm64.GetPcAdjustment(0x10, elf_.get())); - EXPECT_EQ(4U, arm64.GetPcAdjustment(0x4, elf_.get())); - EXPECT_EQ(0U, arm64.GetPcAdjustment(0x3, elf_.get())); - EXPECT_EQ(0U, arm64.GetPcAdjustment(0x2, elf_.get())); - EXPECT_EQ(0U, arm64.GetPcAdjustment(0x1, elf_.get())); - EXPECT_EQ(0U, arm64.GetPcAdjustment(0x0, elf_.get())); - - RegsX86 x86; - EXPECT_EQ(1U, x86.GetPcAdjustment(0x100, elf_.get())); - EXPECT_EQ(1U, x86.GetPcAdjustment(0x2, elf_.get())); - EXPECT_EQ(1U, x86.GetPcAdjustment(0x1, elf_.get())); - EXPECT_EQ(0U, x86.GetPcAdjustment(0x0, elf_.get())); - - RegsX86_64 x86_64; - EXPECT_EQ(1U, x86_64.GetPcAdjustment(0x100, elf_.get())); - EXPECT_EQ(1U, x86_64.GetPcAdjustment(0x2, elf_.get())); - EXPECT_EQ(1U, x86_64.GetPcAdjustment(0x1, elf_.get())); - EXPECT_EQ(0U, x86_64.GetPcAdjustment(0x0, elf_.get())); - - RegsMips mips; - EXPECT_EQ(8U, mips.GetPcAdjustment(0x10, elf_.get())); - EXPECT_EQ(8U, mips.GetPcAdjustment(0x8, elf_.get())); - EXPECT_EQ(0U, mips.GetPcAdjustment(0x7, elf_.get())); - EXPECT_EQ(0U, mips.GetPcAdjustment(0x6, elf_.get())); - EXPECT_EQ(0U, mips.GetPcAdjustment(0x5, elf_.get())); - EXPECT_EQ(0U, mips.GetPcAdjustment(0x4, elf_.get())); - EXPECT_EQ(0U, mips.GetPcAdjustment(0x3, elf_.get())); - EXPECT_EQ(0U, mips.GetPcAdjustment(0x2, elf_.get())); - EXPECT_EQ(0U, mips.GetPcAdjustment(0x1, elf_.get())); - EXPECT_EQ(0U, mips.GetPcAdjustment(0x0, elf_.get())); - - RegsMips64 mips64; - EXPECT_EQ(8U, mips64.GetPcAdjustment(0x10, elf_.get())); - EXPECT_EQ(8U, mips64.GetPcAdjustment(0x8, elf_.get())); - EXPECT_EQ(0U, mips64.GetPcAdjustment(0x7, elf_.get())); - EXPECT_EQ(0U, mips64.GetPcAdjustment(0x6, elf_.get())); - EXPECT_EQ(0U, mips64.GetPcAdjustment(0x5, elf_.get())); - EXPECT_EQ(0U, mips64.GetPcAdjustment(0x4, elf_.get())); - EXPECT_EQ(0U, mips64.GetPcAdjustment(0x3, elf_.get())); - EXPECT_EQ(0U, mips64.GetPcAdjustment(0x2, elf_.get())); - EXPECT_EQ(0U, mips64.GetPcAdjustment(0x1, elf_.get())); - EXPECT_EQ(0U, mips64.GetPcAdjustment(0x0, elf_.get())); + EXPECT_EQ(4U, GetPcAdjustment(0x10, elf_.get(), ARCH_ARM64)); + EXPECT_EQ(4U, GetPcAdjustment(0x4, elf_.get(), ARCH_ARM64)); + EXPECT_EQ(0U, GetPcAdjustment(0x3, elf_.get(), ARCH_ARM64)); + EXPECT_EQ(0U, GetPcAdjustment(0x2, elf_.get(), ARCH_ARM64)); + EXPECT_EQ(0U, GetPcAdjustment(0x1, elf_.get(), ARCH_ARM64)); + EXPECT_EQ(0U, GetPcAdjustment(0x0, elf_.get(), ARCH_ARM64)); + + EXPECT_EQ(1U, GetPcAdjustment(0x100, elf_.get(), ARCH_X86)); + EXPECT_EQ(1U, GetPcAdjustment(0x2, elf_.get(), ARCH_X86)); + EXPECT_EQ(1U, GetPcAdjustment(0x1, elf_.get(), ARCH_X86)); + EXPECT_EQ(0U, GetPcAdjustment(0x0, elf_.get(), ARCH_X86)); + + EXPECT_EQ(1U, GetPcAdjustment(0x100, elf_.get(), ARCH_X86_64)); + EXPECT_EQ(1U, GetPcAdjustment(0x2, elf_.get(), ARCH_X86_64)); + EXPECT_EQ(1U, GetPcAdjustment(0x1, elf_.get(), ARCH_X86_64)); + EXPECT_EQ(0U, GetPcAdjustment(0x0, elf_.get(), ARCH_X86_64)); + + EXPECT_EQ(8U, GetPcAdjustment(0x10, elf_.get(), ARCH_MIPS)); + EXPECT_EQ(8U, GetPcAdjustment(0x8, elf_.get(), ARCH_MIPS)); + EXPECT_EQ(0U, GetPcAdjustment(0x7, elf_.get(), ARCH_MIPS)); + EXPECT_EQ(0U, GetPcAdjustment(0x6, elf_.get(), ARCH_MIPS)); + EXPECT_EQ(0U, GetPcAdjustment(0x5, elf_.get(), ARCH_MIPS)); + EXPECT_EQ(0U, GetPcAdjustment(0x4, elf_.get(), ARCH_MIPS)); + EXPECT_EQ(0U, GetPcAdjustment(0x3, elf_.get(), ARCH_MIPS)); + EXPECT_EQ(0U, GetPcAdjustment(0x2, elf_.get(), ARCH_MIPS)); + EXPECT_EQ(0U, GetPcAdjustment(0x1, elf_.get(), ARCH_MIPS)); + EXPECT_EQ(0U, GetPcAdjustment(0x0, elf_.get(), ARCH_MIPS)); + + EXPECT_EQ(8U, GetPcAdjustment(0x10, elf_.get(), ARCH_MIPS64)); + EXPECT_EQ(8U, GetPcAdjustment(0x8, elf_.get(), ARCH_MIPS64)); + EXPECT_EQ(0U, GetPcAdjustment(0x7, elf_.get(), ARCH_MIPS64)); + EXPECT_EQ(0U, GetPcAdjustment(0x6, elf_.get(), ARCH_MIPS64)); + EXPECT_EQ(0U, GetPcAdjustment(0x5, elf_.get(), ARCH_MIPS64)); + EXPECT_EQ(0U, GetPcAdjustment(0x4, elf_.get(), ARCH_MIPS64)); + EXPECT_EQ(0U, GetPcAdjustment(0x3, elf_.get(), ARCH_MIPS64)); + EXPECT_EQ(0U, GetPcAdjustment(0x2, elf_.get(), ARCH_MIPS64)); + EXPECT_EQ(0U, GetPcAdjustment(0x1, elf_.get(), ARCH_MIPS64)); + EXPECT_EQ(0U, GetPcAdjustment(0x0, elf_.get(), ARCH_MIPS64)); } TEST_F(RegsTest, rel_pc_arm) { - RegsArm arm; - // Check fence posts. elf_->FakeSetLoadBias(0); - EXPECT_EQ(2U, arm.GetPcAdjustment(0x5, elf_.get())); - EXPECT_EQ(2U, arm.GetPcAdjustment(0x4, elf_.get())); - EXPECT_EQ(2U, arm.GetPcAdjustment(0x3, elf_.get())); - EXPECT_EQ(2U, arm.GetPcAdjustment(0x2, elf_.get())); - EXPECT_EQ(0U, arm.GetPcAdjustment(0x1, elf_.get())); - EXPECT_EQ(0U, arm.GetPcAdjustment(0x0, elf_.get())); + EXPECT_EQ(2U, GetPcAdjustment(0x5, elf_.get(), ARCH_ARM)); + EXPECT_EQ(2U, GetPcAdjustment(0x4, elf_.get(), ARCH_ARM)); + EXPECT_EQ(2U, GetPcAdjustment(0x3, elf_.get(), ARCH_ARM)); + EXPECT_EQ(2U, GetPcAdjustment(0x2, elf_.get(), ARCH_ARM)); + EXPECT_EQ(0U, GetPcAdjustment(0x1, elf_.get(), ARCH_ARM)); + EXPECT_EQ(0U, GetPcAdjustment(0x0, elf_.get(), ARCH_ARM)); elf_->FakeSetLoadBias(0x100); - EXPECT_EQ(0U, arm.GetPcAdjustment(0x1, elf_.get())); - EXPECT_EQ(2U, arm.GetPcAdjustment(0x2, elf_.get())); - EXPECT_EQ(2U, arm.GetPcAdjustment(0xff, elf_.get())); - EXPECT_EQ(2U, arm.GetPcAdjustment(0x105, elf_.get())); - EXPECT_EQ(2U, arm.GetPcAdjustment(0x104, elf_.get())); - EXPECT_EQ(2U, arm.GetPcAdjustment(0x103, elf_.get())); - EXPECT_EQ(2U, arm.GetPcAdjustment(0x102, elf_.get())); - EXPECT_EQ(0U, arm.GetPcAdjustment(0x101, elf_.get())); - EXPECT_EQ(0U, arm.GetPcAdjustment(0x100, elf_.get())); + EXPECT_EQ(0U, GetPcAdjustment(0x1, elf_.get(), ARCH_ARM)); + EXPECT_EQ(2U, GetPcAdjustment(0x2, elf_.get(), ARCH_ARM)); + EXPECT_EQ(2U, GetPcAdjustment(0xff, elf_.get(), ARCH_ARM)); + EXPECT_EQ(2U, GetPcAdjustment(0x105, elf_.get(), ARCH_ARM)); + EXPECT_EQ(2U, GetPcAdjustment(0x104, elf_.get(), ARCH_ARM)); + EXPECT_EQ(2U, GetPcAdjustment(0x103, elf_.get(), ARCH_ARM)); + EXPECT_EQ(2U, GetPcAdjustment(0x102, elf_.get(), ARCH_ARM)); + EXPECT_EQ(0U, GetPcAdjustment(0x101, elf_.get(), ARCH_ARM)); + EXPECT_EQ(0U, GetPcAdjustment(0x100, elf_.get(), ARCH_ARM)); // Check thumb instructions handling. elf_->FakeSetLoadBias(0); memory_->SetData32(0x2000, 0); - EXPECT_EQ(2U, arm.GetPcAdjustment(0x2005, elf_.get())); + EXPECT_EQ(2U, GetPcAdjustment(0x2005, elf_.get(), ARCH_ARM)); memory_->SetData32(0x2000, 0xe000f000); - EXPECT_EQ(4U, arm.GetPcAdjustment(0x2005, elf_.get())); + EXPECT_EQ(4U, GetPcAdjustment(0x2005, elf_.get(), ARCH_ARM)); elf_->FakeSetLoadBias(0x400); memory_->SetData32(0x2100, 0); - EXPECT_EQ(2U, arm.GetPcAdjustment(0x2505, elf_.get())); + EXPECT_EQ(2U, GetPcAdjustment(0x2505, elf_.get(), ARCH_ARM)); memory_->SetData32(0x2100, 0xf111f111); - EXPECT_EQ(4U, arm.GetPcAdjustment(0x2505, elf_.get())); + EXPECT_EQ(4U, GetPcAdjustment(0x2505, elf_.get(), ARCH_ARM)); } TEST_F(RegsTest, elf_invalid) { - RegsArm regs_arm; - RegsArm64 regs_arm64; - RegsX86 regs_x86; - RegsX86_64 regs_x86_64; - RegsMips regs_mips; - RegsMips64 regs_mips64; MapInfo map_info(nullptr, nullptr, 0x1000, 0x2000, 0, 0, ""); Elf* invalid_elf = new Elf(nullptr); map_info.elf.reset(invalid_elf); - regs_arm.set_pc(0x1500); - EXPECT_EQ(0x500U, invalid_elf->GetRelPc(regs_arm.pc(), &map_info)); - EXPECT_EQ(2U, regs_arm.GetPcAdjustment(0x500U, invalid_elf)); - EXPECT_EQ(2U, regs_arm.GetPcAdjustment(0x511U, invalid_elf)); + EXPECT_EQ(0x500U, invalid_elf->GetRelPc(0x1500, &map_info)); + EXPECT_EQ(2U, GetPcAdjustment(0x500U, invalid_elf, ARCH_ARM)); + EXPECT_EQ(2U, GetPcAdjustment(0x511U, invalid_elf, ARCH_ARM)); - regs_arm64.set_pc(0x1600); - EXPECT_EQ(0x600U, invalid_elf->GetRelPc(regs_arm64.pc(), &map_info)); - EXPECT_EQ(4U, regs_arm64.GetPcAdjustment(0x600U, invalid_elf)); + EXPECT_EQ(0x600U, invalid_elf->GetRelPc(0x1600, &map_info)); + EXPECT_EQ(4U, GetPcAdjustment(0x600U, invalid_elf, ARCH_ARM64)); - regs_x86.set_pc(0x1700); - EXPECT_EQ(0x700U, invalid_elf->GetRelPc(regs_x86.pc(), &map_info)); - EXPECT_EQ(1U, regs_x86.GetPcAdjustment(0x700U, invalid_elf)); + EXPECT_EQ(0x700U, invalid_elf->GetRelPc(0x1700, &map_info)); + EXPECT_EQ(1U, GetPcAdjustment(0x700U, invalid_elf, ARCH_X86)); - regs_x86_64.set_pc(0x1800); - EXPECT_EQ(0x800U, invalid_elf->GetRelPc(regs_x86_64.pc(), &map_info)); - EXPECT_EQ(1U, regs_x86_64.GetPcAdjustment(0x800U, invalid_elf)); + EXPECT_EQ(0x800U, invalid_elf->GetRelPc(0x1800, &map_info)); + EXPECT_EQ(1U, GetPcAdjustment(0x800U, invalid_elf, ARCH_X86_64)); - regs_mips.set_pc(0x1900); - EXPECT_EQ(0x900U, invalid_elf->GetRelPc(regs_mips.pc(), &map_info)); - EXPECT_EQ(8U, regs_mips.GetPcAdjustment(0x900U, invalid_elf)); + EXPECT_EQ(0x900U, invalid_elf->GetRelPc(0x1900, &map_info)); + EXPECT_EQ(8U, GetPcAdjustment(0x900U, invalid_elf, ARCH_MIPS)); - regs_mips64.set_pc(0x1a00); - EXPECT_EQ(0xa00U, invalid_elf->GetRelPc(regs_mips64.pc(), &map_info)); - EXPECT_EQ(8U, regs_mips64.GetPcAdjustment(0xa00U, invalid_elf)); + EXPECT_EQ(0xa00U, invalid_elf->GetRelPc(0x1a00, &map_info)); + EXPECT_EQ(8U, GetPcAdjustment(0xa00U, invalid_elf, ARCH_MIPS64)); } TEST_F(RegsTest, arm_verify_sp_pc) { diff --git a/libunwindstack/tests/UnwinderTest.cpp b/libunwindstack/tests/UnwinderTest.cpp index ef1950ccc..dd33aa9d7 100644 --- a/libunwindstack/tests/UnwinderTest.cpp +++ b/libunwindstack/tests/UnwinderTest.cpp @@ -161,8 +161,8 @@ TEST_F(UnwinderTest, multiple_frames) { regs_.set_pc(0x1000); regs_.set_sp(0x10000); - ElfInterfaceFake::FakePushStepData(StepData(0x1102, 0x10010, false)); - ElfInterfaceFake::FakePushStepData(StepData(0x1202, 0x10020, false)); + ElfInterfaceFake::FakePushStepData(StepData(0x1104, 0x10010, false)); + ElfInterfaceFake::FakePushStepData(StepData(0x1204, 0x10020, false)); ElfInterfaceFake::FakePushStepData(StepData(0, 0, true)); Unwinder unwinder(64, maps_.get(), ®s_, process_memory_); @@ -225,8 +225,8 @@ TEST_F(UnwinderTest, multiple_frames_dont_resolve_names) { regs_.set_pc(0x1000); regs_.set_sp(0x10000); - ElfInterfaceFake::FakePushStepData(StepData(0x1102, 0x10010, false)); - ElfInterfaceFake::FakePushStepData(StepData(0x1202, 0x10020, false)); + ElfInterfaceFake::FakePushStepData(StepData(0x1104, 0x10010, false)); + ElfInterfaceFake::FakePushStepData(StepData(0x1204, 0x10020, false)); ElfInterfaceFake::FakePushStepData(StepData(0, 0, true)); Unwinder unwinder(64, maps_.get(), ®s_, process_memory_); @@ -445,7 +445,7 @@ TEST_F(UnwinderTest, no_frames_after_finished) { TEST_F(UnwinderTest, max_frames) { for (size_t i = 0; i < 30; i++) { ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame" + std::to_string(i), i)); - ElfInterfaceFake::FakePushStepData(StepData(0x1102 + i * 0x100, 0x10010 + i * 0x10, false)); + ElfInterfaceFake::FakePushStepData(StepData(0x1104 + i * 0x100, 0x10010 + i * 0x10, false)); } regs_.set_pc(0x1000); @@ -484,12 +484,12 @@ TEST_F(UnwinderTest, verify_frames_skipped) { regs_.set_pc(0x20000); regs_.set_sp(0x10000); - ElfInterfaceFake::FakePushStepData(StepData(0x23002, 0x10010, false)); - ElfInterfaceFake::FakePushStepData(StepData(0x23102, 0x10020, false)); - ElfInterfaceFake::FakePushStepData(StepData(0x20002, 0x10030, false)); - ElfInterfaceFake::FakePushStepData(StepData(0x21002, 0x10040, false)); + ElfInterfaceFake::FakePushStepData(StepData(0x23004, 0x10010, false)); + ElfInterfaceFake::FakePushStepData(StepData(0x23104, 0x10020, false)); + ElfInterfaceFake::FakePushStepData(StepData(0x20004, 0x10030, false)); + ElfInterfaceFake::FakePushStepData(StepData(0x21004, 0x10040, false)); ElfInterfaceFake::FakePushStepData(StepData(0x1002, 0x10050, false)); - ElfInterfaceFake::FakePushStepData(StepData(0x21002, 0x10060, false)); + ElfInterfaceFake::FakePushStepData(StepData(0x21004, 0x10060, false)); ElfInterfaceFake::FakePushStepData(StepData(0x23002, 0x10070, false)); ElfInterfaceFake::FakePushStepData(StepData(0, 0, true)); @@ -553,7 +553,7 @@ TEST_F(UnwinderTest, sp_not_in_map) { regs_.set_pc(0x1000); regs_.set_sp(0x63000); - ElfInterfaceFake::FakePushStepData(StepData(0x21002, 0x50020, false)); + ElfInterfaceFake::FakePushStepData(StepData(0x21004, 0x50020, false)); ElfInterfaceFake::FakePushStepData(StepData(0, 0, true)); Unwinder unwinder(64, maps_.get(), ®s_, process_memory_); @@ -670,10 +670,10 @@ TEST_F(UnwinderTest, speculative_frame) { // Fake as if code called a nullptr function. regs_.set_pc(0); regs_.set_sp(0x10000); - regs_.FakeSetReturnAddress(0x1202); + regs_.FakeSetReturnAddress(0x1204); regs_.FakeSetReturnAddressValid(true); - ElfInterfaceFake::FakePushStepData(StepData(0x23102, 0x10020, false)); + ElfInterfaceFake::FakePushStepData(StepData(0x23104, 0x10020, false)); ElfInterfaceFake::FakePushStepData(StepData(0, 0, true)); Unwinder unwinder(64, maps_.get(), ®s_, process_memory_); @@ -789,7 +789,7 @@ TEST_F(UnwinderTest, speculative_frame_not_removed_pc_bad) { // Fake as if code called a nullptr function. regs_.set_pc(0); regs_.set_sp(0x10000); - regs_.FakeSetReturnAddress(0x1202); + regs_.FakeSetReturnAddress(0x1204); regs_.FakeSetReturnAddressValid(true); Unwinder unwinder(64, maps_.get(), ®s_, process_memory_); @@ -858,8 +858,8 @@ TEST_F(UnwinderTest, map_ignore_suffixes) { // Fake as if code called a nullptr function. regs_.set_pc(0x1000); regs_.set_sp(0x10000); - ElfInterfaceFake::FakePushStepData(StepData(0x43402, 0x10010, false)); - ElfInterfaceFake::FakePushStepData(StepData(0x53502, 0x10020, false)); + ElfInterfaceFake::FakePushStepData(StepData(0x43404, 0x10010, false)); + ElfInterfaceFake::FakePushStepData(StepData(0x53504, 0x10020, false)); ElfInterfaceFake::FakePushStepData(StepData(0, 0, true)); Unwinder unwinder(64, maps_.get(), ®s_, process_memory_); @@ -915,11 +915,11 @@ TEST_F(UnwinderTest, sp_pc_do_not_change) { regs_.set_pc(0x1000); regs_.set_sp(0x10000); - ElfInterfaceFake::FakePushStepData(StepData(0x33402, 0x10010, false)); - ElfInterfaceFake::FakePushStepData(StepData(0x33502, 0x10020, false)); - ElfInterfaceFake::FakePushStepData(StepData(0x33502, 0x10020, false)); - ElfInterfaceFake::FakePushStepData(StepData(0x33502, 0x10020, false)); - ElfInterfaceFake::FakePushStepData(StepData(0x33502, 0x10020, false)); + ElfInterfaceFake::FakePushStepData(StepData(0x33404, 0x10010, false)); + ElfInterfaceFake::FakePushStepData(StepData(0x33504, 0x10020, false)); + ElfInterfaceFake::FakePushStepData(StepData(0x33504, 0x10020, false)); + ElfInterfaceFake::FakePushStepData(StepData(0x33504, 0x10020, false)); + ElfInterfaceFake::FakePushStepData(StepData(0x33504, 0x10020, false)); ElfInterfaceFake::FakePushStepData(StepData(0, 0, true)); Unwinder unwinder(64, maps_.get(), ®s_, process_memory_); @@ -1113,7 +1113,7 @@ TEST_F(UnwinderTest, dex_pc_multiple_frames) { regs_.set_pc(0x1000); regs_.set_sp(0x10000); regs_.FakeSetDexPc(0xa3400); - ElfInterfaceFake::FakePushStepData(StepData(0x33402, 0x10010, false)); + ElfInterfaceFake::FakePushStepData(StepData(0x33404, 0x10010, false)); ElfInterfaceFake::FakePushStepData(StepData(0, 0, true)); Unwinder unwinder(64, maps_.get(), ®s_, process_memory_); |