diff options
-rw-r--r-- | libbacktrace/UnwindStack.cpp | 1 | ||||
-rw-r--r-- | libbacktrace/UnwindStackMap.cpp | 13 | ||||
-rw-r--r-- | libbacktrace/UnwindStackMap.h | 5 | ||||
-rw-r--r-- | libunwindstack/DexFiles.cpp | 4 | ||||
-rw-r--r-- | libunwindstack/Elf.cpp | 5 | ||||
-rw-r--r-- | libunwindstack/Global.cpp | 9 | ||||
-rw-r--r-- | libunwindstack/JitDebug.cpp | 4 | ||||
-rw-r--r-- | libunwindstack/LocalUnwinder.cpp | 3 | ||||
-rw-r--r-- | libunwindstack/MapInfo.cpp | 6 | ||||
-rw-r--r-- | libunwindstack/Unwinder.cpp | 4 | ||||
-rw-r--r-- | libunwindstack/include/unwindstack/DexFiles.h | 4 | ||||
-rw-r--r-- | libunwindstack/include/unwindstack/Elf.h | 2 | ||||
-rw-r--r-- | libunwindstack/include/unwindstack/Global.h | 9 | ||||
-rw-r--r-- | libunwindstack/include/unwindstack/JitDebug.h | 16 | ||||
-rw-r--r-- | libunwindstack/include/unwindstack/MapInfo.h | 2 | ||||
-rw-r--r-- | libunwindstack/tests/DexFilesTest.cpp | 56 | ||||
-rw-r--r-- | libunwindstack/tests/ElfCacheTest.cpp | 28 | ||||
-rw-r--r-- | libunwindstack/tests/JitDebugTest.cpp | 51 | ||||
-rw-r--r-- | libunwindstack/tests/MapInfoGetElfTest.cpp | 48 |
19 files changed, 164 insertions, 106 deletions
diff --git a/libbacktrace/UnwindStack.cpp b/libbacktrace/UnwindStack.cpp index 4e7f761ff..fe28eba41 100644 --- a/libbacktrace/UnwindStack.cpp +++ b/libbacktrace/UnwindStack.cpp @@ -49,6 +49,7 @@ bool Backtrace::Unwind(unwindstack::Regs* regs, BacktraceMap* back_map, 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()); } diff --git a/libbacktrace/UnwindStackMap.cpp b/libbacktrace/UnwindStackMap.cpp index 52dd44192..9d15af2db 100644 --- a/libbacktrace/UnwindStackMap.cpp +++ b/libbacktrace/UnwindStackMap.cpp @@ -25,6 +25,7 @@ #include <unwindstack/Elf.h> #include <unwindstack/MapInfo.h> #include <unwindstack/Maps.h> +#include <unwindstack/Regs.h> #include "UnwindStackMap.h" @@ -106,7 +107,17 @@ std::string UnwindStackMap::GetFunctionName(uint64_t pc, uint64_t* offset) { return ""; } - unwindstack::Elf* elf = map_info->GetElf(process_memory()); + if (arch_ == unwindstack::ARCH_UNKNOWN) { + if (pid_ == getpid()) { + arch_ = unwindstack::Regs::CurrentArch(); + } else { + // Create a remote regs, to figure out the architecture. + std::unique_ptr<unwindstack::Regs> regs(unwindstack::Regs::RemoteGet(pid_)); + arch_ = regs->Arch(); + } + } + + unwindstack::Elf* elf = map_info->GetElf(process_memory(), arch_); std::string name; uint64_t func_offset; diff --git a/libbacktrace/UnwindStackMap.h b/libbacktrace/UnwindStackMap.h index 039f4a289..e19b60565 100644 --- a/libbacktrace/UnwindStackMap.h +++ b/libbacktrace/UnwindStackMap.h @@ -30,6 +30,7 @@ #if !defined(NO_LIBDEXFILE_SUPPORT) #include <unwindstack/DexFiles.h> #endif +#include <unwindstack/Elf.h> #include <unwindstack/JitDebug.h> #include <unwindstack/Maps.h> @@ -58,6 +59,8 @@ class UnwindStackMap : public BacktraceMap { unwindstack::DexFiles* GetDexFiles() { return dex_files_.get(); } #endif + void SetArch(unwindstack::ArchEnum arch) { arch_ = arch; } + protected: uint64_t GetLoadBias(size_t index) override; @@ -67,6 +70,8 @@ class UnwindStackMap : public BacktraceMap { #if !defined(NO_LIBDEXFILE_SUPPORT) std::unique_ptr<unwindstack::DexFiles> dex_files_; #endif + + unwindstack::ArchEnum arch_ = unwindstack::ARCH_UNKNOWN; }; class UnwindStackOfflineMap : public UnwindStackMap { diff --git a/libunwindstack/DexFiles.cpp b/libunwindstack/DexFiles.cpp index ac55fee99..451a0b90d 100644 --- a/libunwindstack/DexFiles.cpp +++ b/libunwindstack/DexFiles.cpp @@ -54,8 +54,8 @@ DexFiles::~DexFiles() { } } -void DexFiles::SetArch(ArchEnum arch) { - switch (arch) { +void DexFiles::ProcessArch() { + switch (arch()) { case ARCH_ARM: case ARCH_MIPS: case ARCH_X86: diff --git a/libunwindstack/Elf.cpp b/libunwindstack/Elf.cpp index 60ef79625..4d72eadef 100644 --- a/libunwindstack/Elf.cpp +++ b/libunwindstack/Elf.cpp @@ -88,6 +88,11 @@ void Elf::InitGnuDebugdata() { } } +void Elf::Invalidate() { + interface_.reset(nullptr); + valid_ = false; +} + bool Elf::GetSoname(std::string* name) { std::lock_guard<std::mutex> guard(lock_); return valid_ && interface_->GetSoname(name); diff --git a/libunwindstack/Global.cpp b/libunwindstack/Global.cpp index f0ad2b680..7a3de01d2 100644 --- a/libunwindstack/Global.cpp +++ b/libunwindstack/Global.cpp @@ -31,6 +31,13 @@ Global::Global(std::shared_ptr<Memory>& memory) : memory_(memory) {} Global::Global(std::shared_ptr<Memory>& memory, std::vector<std::string>& search_libs) : memory_(memory), search_libs_(search_libs) {} +void Global::SetArch(ArchEnum arch) { + if (arch_ == ARCH_UNKNOWN) { + arch_ = arch; + ProcessArch(); + } +} + uint64_t Global::GetVariableOffset(MapInfo* info, const std::string& variable) { if (!search_libs_.empty()) { bool found = false; @@ -46,7 +53,7 @@ uint64_t Global::GetVariableOffset(MapInfo* info, const std::string& variable) { } } - Elf* elf = info->GetElf(memory_); + Elf* elf = info->GetElf(memory_, arch()); uint64_t ptr; // Find first non-empty list (libraries might be loaded multiple times). if (elf->GetGlobalVariable(variable, &ptr) && ptr != 0) { diff --git a/libunwindstack/JitDebug.cpp b/libunwindstack/JitDebug.cpp index d6af49e29..20bc4b902 100644 --- a/libunwindstack/JitDebug.cpp +++ b/libunwindstack/JitDebug.cpp @@ -141,8 +141,8 @@ uint64_t JitDebug::ReadEntry64(uint64_t* start, uint64_t* size) { return code.next; } -void JitDebug::SetArch(ArchEnum arch) { - switch (arch) { +void JitDebug::ProcessArch() { + switch (arch()) { case ARCH_X86: read_descriptor_func_ = &JitDebug::ReadDescriptor32; read_entry_func_ = &JitDebug::ReadEntry32Pack; diff --git a/libunwindstack/LocalUnwinder.cpp b/libunwindstack/LocalUnwinder.cpp index 31337a9a8..5b2fadf2b 100644 --- a/libunwindstack/LocalUnwinder.cpp +++ b/libunwindstack/LocalUnwinder.cpp @@ -88,6 +88,7 @@ MapInfo* LocalUnwinder::GetMapInfo(uint64_t pc) { bool LocalUnwinder::Unwind(std::vector<LocalFrameData>* frame_info, size_t max_frames) { std::unique_ptr<unwindstack::Regs> regs(unwindstack::Regs::CreateFromLocal()); unwindstack::RegsGetLocal(regs.get()); + ArchEnum arch = regs->Arch(); size_t num_frames = 0; bool adjust_pc = false; @@ -100,7 +101,7 @@ bool LocalUnwinder::Unwind(std::vector<LocalFrameData>* frame_info, size_t max_f break; } - Elf* elf = map_info->GetElf(process_memory_); + Elf* elf = map_info->GetElf(process_memory_, arch); uint64_t rel_pc = elf->GetRelPc(cur_pc, map_info); uint64_t step_pc = rel_pc; uint64_t pc_adjustment; diff --git a/libunwindstack/MapInfo.cpp b/libunwindstack/MapInfo.cpp index 8527797d2..fe32b5e34 100644 --- a/libunwindstack/MapInfo.cpp +++ b/libunwindstack/MapInfo.cpp @@ -146,7 +146,7 @@ Memory* MapInfo::CreateMemory(const std::shared_ptr<Memory>& process_memory) { return nullptr; } -Elf* MapInfo::GetElf(const std::shared_ptr<Memory>& process_memory) { +Elf* MapInfo::GetElf(const std::shared_ptr<Memory>& process_memory, ArchEnum expected_arch) { // Make sure no other thread is trying to add the elf to this map. std::lock_guard<std::mutex> guard(mutex_); @@ -176,6 +176,10 @@ Elf* MapInfo::GetElf(const std::shared_ptr<Memory>& process_memory) { // If the init fails, keep the elf around as an invalid object so we // don't try to reinit the object. elf->Init(); + if (elf->valid() && expected_arch != elf->arch()) { + // Make the elf invalid, mismatch between arch and expected arch. + elf->Invalidate(); + } if (locked) { Elf::CacheAdd(this); diff --git a/libunwindstack/Unwinder.cpp b/libunwindstack/Unwinder.cpp index b8b0ac63f..b3c55494a 100644 --- a/libunwindstack/Unwinder.cpp +++ b/libunwindstack/Unwinder.cpp @@ -135,6 +135,8 @@ void Unwinder::Unwind(const std::vector<std::string>* initial_map_names_to_skip, last_error_.code = ERROR_NONE; last_error_.address = 0; + ArchEnum arch = regs_->Arch(); + bool return_address_attempt = false; bool adjust_pc = false; std::unique_ptr<JitDebug> jit_debug; @@ -155,7 +157,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_); + elf = map_info->GetElf(process_memory_, arch); step_pc = regs_->pc(); rel_pc = elf->GetRelPc(step_pc, map_info); // Everyone except elf data in gdb jit debug maps uses the relative pc. diff --git a/libunwindstack/include/unwindstack/DexFiles.h b/libunwindstack/include/unwindstack/DexFiles.h index c2fde74ef..c202a334d 100644 --- a/libunwindstack/include/unwindstack/DexFiles.h +++ b/libunwindstack/include/unwindstack/DexFiles.h @@ -47,8 +47,6 @@ class DexFiles : public Global { void GetMethodInformation(Maps* maps, MapInfo* info, uint64_t dex_pc, std::string* method_name, uint64_t* method_offset); - void SetArch(ArchEnum arch); - private: void Init(Maps* maps); @@ -64,6 +62,8 @@ class DexFiles : public Global { bool ReadVariableData(uint64_t ptr_offset) override; + void ProcessArch() override; + std::mutex lock_; bool initialized_ = false; std::unordered_map<uint64_t, DexFile*> files_; diff --git a/libunwindstack/include/unwindstack/Elf.h b/libunwindstack/include/unwindstack/Elf.h index 24cabf220..e5b0a89c9 100644 --- a/libunwindstack/include/unwindstack/Elf.h +++ b/libunwindstack/include/unwindstack/Elf.h @@ -57,6 +57,8 @@ class Elf { void InitGnuDebugdata(); + void Invalidate(); + bool GetSoname(std::string* name); bool GetFunctionName(uint64_t addr, std::string* name, uint64_t* func_offset); diff --git a/libunwindstack/include/unwindstack/Global.h b/libunwindstack/include/unwindstack/Global.h index 70e3ddd45..a7e6c15ba 100644 --- a/libunwindstack/include/unwindstack/Global.h +++ b/libunwindstack/include/unwindstack/Global.h @@ -25,6 +25,7 @@ #include <unordered_map> #include <vector> +#include <unwindstack/Elf.h> #include <unwindstack/Memory.h> namespace unwindstack { @@ -39,12 +40,20 @@ class Global { Global(std::shared_ptr<Memory>& memory, std::vector<std::string>& search_libs); virtual ~Global() = default; + void SetArch(ArchEnum arch); + + ArchEnum arch() { return arch_; } + protected: uint64_t GetVariableOffset(MapInfo* info, const std::string& variable); void FindAndReadVariable(Maps* maps, const char* variable); virtual bool ReadVariableData(uint64_t offset) = 0; + virtual void ProcessArch() = 0; + + ArchEnum arch_ = ARCH_UNKNOWN; + std::shared_ptr<Memory> memory_; std::vector<std::string> search_libs_; }; diff --git a/libunwindstack/include/unwindstack/JitDebug.h b/libunwindstack/include/unwindstack/JitDebug.h index ccb473f7e..f64b04f0a 100644 --- a/libunwindstack/include/unwindstack/JitDebug.h +++ b/libunwindstack/include/unwindstack/JitDebug.h @@ -42,17 +42,9 @@ class JitDebug : public Global { Elf* GetElf(Maps* maps, uint64_t pc); - void SetArch(ArchEnum arch); - private: void Init(Maps* maps); - uint64_t entry_addr_ = 0; - bool initialized_ = false; - std::vector<Elf*> elf_list_; - - std::mutex lock_; - uint64_t (JitDebug::*read_descriptor_func_)(uint64_t) = nullptr; uint64_t (JitDebug::*read_entry_func_)(uint64_t*, uint64_t*) = nullptr; @@ -64,6 +56,14 @@ class JitDebug : public Global { uint64_t ReadEntry64(uint64_t* start, uint64_t* size); bool ReadVariableData(uint64_t ptr_offset) override; + + void ProcessArch() override; + + uint64_t entry_addr_ = 0; + bool initialized_ = false; + std::vector<Elf*> elf_list_; + + std::mutex lock_; }; } // namespace unwindstack diff --git a/libunwindstack/include/unwindstack/MapInfo.h b/libunwindstack/include/unwindstack/MapInfo.h index ff634f26e..9c6b55211 100644 --- a/libunwindstack/include/unwindstack/MapInfo.h +++ b/libunwindstack/include/unwindstack/MapInfo.h @@ -72,7 +72,7 @@ struct MapInfo { std::atomic_uint64_t load_bias; // This function guarantees it will never return nullptr. - Elf* GetElf(const std::shared_ptr<Memory>& process_memory); + Elf* GetElf(const std::shared_ptr<Memory>& process_memory, ArchEnum expected_arch); uint64_t GetLoadBias(const std::shared_ptr<Memory>& process_memory); diff --git a/libunwindstack/tests/DexFilesTest.cpp b/libunwindstack/tests/DexFilesTest.cpp index 3ac3ca61b..1ea9e5c03 100644 --- a/libunwindstack/tests/DexFilesTest.cpp +++ b/libunwindstack/tests/DexFilesTest.cpp @@ -36,12 +36,20 @@ namespace unwindstack { class DexFilesTest : public ::testing::Test { protected: - void SetUp() override { - memory_ = new MemoryFake; - process_memory_.reset(memory_); + void CreateFakeElf(MapInfo* map_info) { + MemoryFake* memory = new MemoryFake; + ElfFake* elf = new ElfFake(memory); + elf->FakeSetValid(true); + ElfInterfaceFake* interface = new ElfInterfaceFake(memory); + elf->FakeSetInterface(interface); + + interface->FakeSetGlobalVariable("__dex_debug_descriptor", 0x800); + map_info->elf.reset(elf); + } + void Init(ArchEnum arch) { dex_files_.reset(new DexFiles(process_memory_)); - dex_files_->SetArch(ARCH_ARM); + dex_files_->SetArch(arch); maps_.reset( new BufferMaps("1000-4000 ---s 00000000 00:00 0 /fake/elf\n" @@ -58,35 +66,24 @@ class DexFilesTest : public ::testing::Test { // Global variable in a section that is not readable. MapInfo* map_info = maps_->Get(kMapGlobalNonReadable); ASSERT_TRUE(map_info != nullptr); - MemoryFake* memory = new MemoryFake; - ElfFake* elf = new ElfFake(memory); - elf->FakeSetValid(true); - ElfInterfaceFake* interface = new ElfInterfaceFake(memory); - elf->FakeSetInterface(interface); - interface->FakeSetGlobalVariable("__dex_debug_descriptor", 0x800); - map_info->elf.reset(elf); + CreateFakeElf(map_info); // Global variable not set by default. map_info = maps_->Get(kMapGlobalSetToZero); ASSERT_TRUE(map_info != nullptr); - memory = new MemoryFake; - elf = new ElfFake(memory); - elf->FakeSetValid(true); - interface = new ElfInterfaceFake(memory); - elf->FakeSetInterface(interface); - interface->FakeSetGlobalVariable("__dex_debug_descriptor", 0x800); - map_info->elf.reset(elf); + CreateFakeElf(map_info); // Global variable set in this map. map_info = maps_->Get(kMapGlobal); ASSERT_TRUE(map_info != nullptr); - memory = new MemoryFake; - elf = new ElfFake(memory); - elf->FakeSetValid(true); - interface = new ElfInterfaceFake(memory); - elf->FakeSetInterface(interface); - interface->FakeSetGlobalVariable("__dex_debug_descriptor", 0x800); - map_info->elf.reset(elf); + CreateFakeElf(map_info); + } + + void SetUp() override { + memory_ = new MemoryFake; + process_memory_.reset(memory_); + + Init(ARCH_ARM); } void WriteDescriptor32(uint64_t addr, uint32_t head); @@ -169,11 +166,12 @@ TEST_F(DexFilesTest, get_method_information_32) { } TEST_F(DexFilesTest, get_method_information_64) { + Init(ARCH_ARM64); + std::string method_name = "nothing"; uint64_t method_offset = 0x124; MapInfo* info = maps_->Get(kMapDexFiles); - dex_files_->SetArch(ARCH_ARM64); WriteDescriptor64(0xf800, 0x200000); WriteEntry64(0x200000, 0, 0, 0x301000); WriteDex(0x301000); @@ -199,11 +197,12 @@ TEST_F(DexFilesTest, get_method_information_not_first_entry_32) { } TEST_F(DexFilesTest, get_method_information_not_first_entry_64) { + Init(ARCH_ARM64); + std::string method_name = "nothing"; uint64_t method_offset = 0x124; MapInfo* info = maps_->Get(kMapDexFiles); - dex_files_->SetArch(ARCH_ARM64); WriteDescriptor64(0xf800, 0x200000); WriteEntry64(0x200000, 0x200100, 0, 0x100000); WriteEntry64(0x200100, 0, 0x200000, 0x300000); @@ -297,6 +296,8 @@ TEST_F(DexFilesTest, get_method_information_global_skip_zero_32) { } TEST_F(DexFilesTest, get_method_information_global_skip_zero_64) { + Init(ARCH_ARM64); + std::string method_name = "nothing"; uint64_t method_offset = 0x124; MapInfo* info = maps_->Get(kMapDexFiles); @@ -308,7 +309,6 @@ TEST_F(DexFilesTest, get_method_information_global_skip_zero_64) { WriteEntry64(0x200000, 0, 0, 0x300000); WriteDex(0x300000); - dex_files_->SetArch(ARCH_ARM64); dex_files_->GetMethodInformation(maps_.get(), info, 0x300100, &method_name, &method_offset); EXPECT_EQ("Main.<init>", method_name); EXPECT_EQ(0U, method_offset); diff --git a/libunwindstack/tests/ElfCacheTest.cpp b/libunwindstack/tests/ElfCacheTest.cpp index 8ed697c61..d9acdec70 100644 --- a/libunwindstack/tests/ElfCacheTest.cpp +++ b/libunwindstack/tests/ElfCacheTest.cpp @@ -82,9 +82,9 @@ void ElfCacheTest::VerifySameMap(bool cache_enabled) { MapInfo info1(nullptr, start, end, 0, 0x5, tf.path); MapInfo info2(nullptr, start, end, 0, 0x5, tf.path); - Elf* elf1 = info1.GetElf(memory_); + Elf* elf1 = info1.GetElf(memory_, ARCH_ARM); ASSERT_TRUE(elf1->valid()); - Elf* elf2 = info2.GetElf(memory_); + Elf* elf2 = info2.GetElf(memory_, ARCH_ARM); ASSERT_TRUE(elf2->valid()); if (cache_enabled) { @@ -132,10 +132,10 @@ void ElfCacheTest::VerifyWithinSameMap(bool cache_enabled) { MapInfo info300_1(nullptr, start, end, 0x300, 0x5, tf.path); MapInfo info300_2(nullptr, start, end, 0x300, 0x5, tf.path); - Elf* elf0_1 = info0_1.GetElf(memory_); + Elf* elf0_1 = info0_1.GetElf(memory_, ARCH_ARM); ASSERT_TRUE(elf0_1->valid()); EXPECT_EQ(ARCH_ARM, elf0_1->arch()); - Elf* elf0_2 = info0_2.GetElf(memory_); + Elf* elf0_2 = info0_2.GetElf(memory_, ARCH_ARM); ASSERT_TRUE(elf0_2->valid()); EXPECT_EQ(ARCH_ARM, elf0_2->arch()); EXPECT_EQ(0U, info0_1.elf_offset); @@ -146,10 +146,10 @@ void ElfCacheTest::VerifyWithinSameMap(bool cache_enabled) { EXPECT_NE(elf0_1, elf0_2); } - Elf* elf100_1 = info100_1.GetElf(memory_); + Elf* elf100_1 = info100_1.GetElf(memory_, ARCH_X86); ASSERT_TRUE(elf100_1->valid()); EXPECT_EQ(ARCH_X86, elf100_1->arch()); - Elf* elf100_2 = info100_2.GetElf(memory_); + Elf* elf100_2 = info100_2.GetElf(memory_, ARCH_X86); ASSERT_TRUE(elf100_2->valid()); EXPECT_EQ(ARCH_X86, elf100_2->arch()); EXPECT_EQ(0U, info100_1.elf_offset); @@ -160,10 +160,10 @@ void ElfCacheTest::VerifyWithinSameMap(bool cache_enabled) { EXPECT_NE(elf100_1, elf100_2); } - Elf* elf200_1 = info200_1.GetElf(memory_); + Elf* elf200_1 = info200_1.GetElf(memory_, ARCH_X86_64); ASSERT_TRUE(elf200_1->valid()); EXPECT_EQ(ARCH_X86_64, elf200_1->arch()); - Elf* elf200_2 = info200_2.GetElf(memory_); + Elf* elf200_2 = info200_2.GetElf(memory_, ARCH_X86_64); ASSERT_TRUE(elf200_2->valid()); EXPECT_EQ(ARCH_X86_64, elf200_2->arch()); EXPECT_EQ(0U, info200_1.elf_offset); @@ -174,10 +174,10 @@ void ElfCacheTest::VerifyWithinSameMap(bool cache_enabled) { EXPECT_NE(elf200_1, elf200_2); } - Elf* elf300_1 = info300_1.GetElf(memory_); + Elf* elf300_1 = info300_1.GetElf(memory_, ARCH_ARM); ASSERT_TRUE(elf300_1->valid()); EXPECT_EQ(ARCH_ARM, elf300_1->arch()); - Elf* elf300_2 = info300_2.GetElf(memory_); + Elf* elf300_2 = info300_2.GetElf(memory_, ARCH_ARM); ASSERT_TRUE(elf300_2->valid()); EXPECT_EQ(ARCH_ARM, elf300_2->arch()); EXPECT_EQ(0x300U, info300_1.elf_offset); @@ -222,10 +222,10 @@ void ElfCacheTest::VerifyWithinSameMapNeverReadAtZero(bool cache_enabled) { MapInfo info400_1(nullptr, start, end, 0x400, 0x5, tf.path); MapInfo info400_2(nullptr, start, end, 0x400, 0x5, tf.path); - Elf* elf300_1 = info300_1.GetElf(memory_); + Elf* elf300_1 = info300_1.GetElf(memory_, ARCH_ARM); ASSERT_TRUE(elf300_1->valid()); EXPECT_EQ(ARCH_ARM, elf300_1->arch()); - Elf* elf300_2 = info300_2.GetElf(memory_); + Elf* elf300_2 = info300_2.GetElf(memory_, ARCH_ARM); ASSERT_TRUE(elf300_2->valid()); EXPECT_EQ(ARCH_ARM, elf300_2->arch()); EXPECT_EQ(0x300U, info300_1.elf_offset); @@ -236,10 +236,10 @@ void ElfCacheTest::VerifyWithinSameMapNeverReadAtZero(bool cache_enabled) { EXPECT_NE(elf300_1, elf300_2); } - Elf* elf400_1 = info400_1.GetElf(memory_); + Elf* elf400_1 = info400_1.GetElf(memory_, ARCH_ARM); ASSERT_TRUE(elf400_1->valid()); EXPECT_EQ(ARCH_ARM, elf400_1->arch()); - Elf* elf400_2 = info400_2.GetElf(memory_); + Elf* elf400_2 = info400_2.GetElf(memory_, ARCH_ARM); ASSERT_TRUE(elf400_2->valid()); EXPECT_EQ(ARCH_ARM, elf400_2->arch()); EXPECT_EQ(0x400U, info400_1.elf_offset); diff --git a/libunwindstack/tests/JitDebugTest.cpp b/libunwindstack/tests/JitDebugTest.cpp index 459852632..b1ca111cb 100644 --- a/libunwindstack/tests/JitDebugTest.cpp +++ b/libunwindstack/tests/JitDebugTest.cpp @@ -35,12 +35,19 @@ namespace unwindstack { class JitDebugTest : public ::testing::Test { protected: - void SetUp() override { - memory_ = new MemoryFake; - process_memory_.reset(memory_); + void CreateFakeElf(MapInfo* map_info) { + MemoryFake* memory = new MemoryFake; + ElfFake* elf = new ElfFake(memory); + elf->FakeSetValid(true); + ElfInterfaceFake* interface = new ElfInterfaceFake(memory); + elf->FakeSetInterface(interface); + interface->FakeSetGlobalVariable("__jit_debug_descriptor", 0x800); + map_info->elf.reset(elf); + } + void Init(ArchEnum arch) { jit_debug_.reset(new JitDebug(process_memory_)); - jit_debug_->SetArch(ARCH_ARM); + jit_debug_->SetArch(arch); maps_.reset( new BufferMaps("1000-4000 ---s 00000000 00:00 0 /fake/elf1\n" @@ -57,33 +64,22 @@ class JitDebugTest : public ::testing::Test { MapInfo* map_info = maps_->Get(3); ASSERT_TRUE(map_info != nullptr); - MemoryFake* memory = new MemoryFake; - ElfFake* elf = new ElfFake(memory); - elf->FakeSetValid(true); - ElfInterfaceFake* interface = new ElfInterfaceFake(memory); - elf->FakeSetInterface(interface); - interface->FakeSetGlobalVariable("__jit_debug_descriptor", 0x800); - map_info->elf.reset(elf); + CreateFakeElf(map_info); map_info = maps_->Get(5); ASSERT_TRUE(map_info != nullptr); - memory = new MemoryFake; - elf = new ElfFake(memory); - elf->FakeSetValid(true); - interface = new ElfInterfaceFake(memory); - elf->FakeSetInterface(interface); - interface->FakeSetGlobalVariable("__jit_debug_descriptor", 0x800); - map_info->elf.reset(elf); + CreateFakeElf(map_info); map_info = maps_->Get(7); ASSERT_TRUE(map_info != nullptr); - memory = new MemoryFake; - elf = new ElfFake(memory); - elf->FakeSetValid(true); - interface = new ElfInterfaceFake(memory); - elf->FakeSetInterface(interface); - interface->FakeSetGlobalVariable("__jit_debug_descriptor", 0x800); - map_info->elf.reset(elf); + CreateFakeElf(map_info); + } + + void SetUp() override { + memory_ = new MemoryFake; + process_memory_.reset(memory_); + + Init(ARCH_ARM); } template <typename EhdrType, typename ShdrType> @@ -326,6 +322,8 @@ TEST_F(JitDebugTest, get_multiple_jit_debug_descriptors_valid) { } TEST_F(JitDebugTest, get_elf_x86) { + Init(ARCH_X86); + CreateElf<Elf32_Ehdr, Elf32_Shdr>(0x4000, ELFCLASS32, EM_ARM, 0x1500, 0x200); WriteDescriptor32(0xf800, 0x200000); @@ -343,12 +341,13 @@ TEST_F(JitDebugTest, get_elf_x86) { } TEST_F(JitDebugTest, get_elf_64) { + Init(ARCH_ARM64); + CreateElf<Elf64_Ehdr, Elf64_Shdr>(0x4000, ELFCLASS64, EM_AARCH64, 0x1500, 0x200); WriteDescriptor64(0xf800, 0x200000); WriteEntry64(0x200000, 0, 0, 0x4000, 0x1000); - jit_debug_->SetArch(ARCH_ARM64); Elf* elf = jit_debug_->GetElf(maps_.get(), 0x1500); ASSERT_TRUE(elf != nullptr); diff --git a/libunwindstack/tests/MapInfoGetElfTest.cpp b/libunwindstack/tests/MapInfoGetElfTest.cpp index c6c1c3428..4d7469690 100644 --- a/libunwindstack/tests/MapInfoGetElfTest.cpp +++ b/libunwindstack/tests/MapInfoGetElfTest.cpp @@ -72,7 +72,7 @@ TEST_F(MapInfoGetElfTest, invalid) { MapInfo info(nullptr, 0x1000, 0x2000, 0, PROT_READ, ""); // The map is empty, but this should still create an invalid elf object. - Elf* elf = info.GetElf(process_memory_); + Elf* elf = info.GetElf(process_memory_, ARCH_ARM); ASSERT_TRUE(elf != nullptr); ASSERT_FALSE(elf->valid()); } @@ -84,7 +84,7 @@ TEST_F(MapInfoGetElfTest, valid32) { TestInitEhdr<Elf32_Ehdr>(&ehdr, ELFCLASS32, EM_ARM); memory_->SetMemory(0x3000, &ehdr, sizeof(ehdr)); - Elf* elf = info.GetElf(process_memory_); + Elf* elf = info.GetElf(process_memory_, ARCH_ARM); ASSERT_TRUE(elf != nullptr); ASSERT_TRUE(elf->valid()); EXPECT_EQ(static_cast<uint32_t>(EM_ARM), elf->machine_type()); @@ -98,13 +98,25 @@ TEST_F(MapInfoGetElfTest, valid64) { TestInitEhdr<Elf64_Ehdr>(&ehdr, ELFCLASS64, EM_AARCH64); memory_->SetMemory(0x8000, &ehdr, sizeof(ehdr)); - Elf* elf = info.GetElf(process_memory_); + Elf* elf = info.GetElf(process_memory_, ARCH_ARM64); ASSERT_TRUE(elf != nullptr); ASSERT_TRUE(elf->valid()); EXPECT_EQ(static_cast<uint32_t>(EM_AARCH64), elf->machine_type()); EXPECT_EQ(ELFCLASS64, elf->class_type()); } +TEST_F(MapInfoGetElfTest, invalid_arch_mismatch) { + MapInfo info(nullptr, 0x3000, 0x4000, 0, PROT_READ, ""); + + Elf32_Ehdr ehdr; + TestInitEhdr<Elf32_Ehdr>(&ehdr, ELFCLASS32, EM_ARM); + memory_->SetMemory(0x3000, &ehdr, sizeof(ehdr)); + + Elf* elf = info.GetElf(process_memory_, ARCH_X86); + ASSERT_TRUE(elf != nullptr); + ASSERT_FALSE(elf->valid()); +} + TEST_F(MapInfoGetElfTest, gnu_debugdata_init32) { MapInfo info(nullptr, 0x2000, 0x3000, 0, PROT_READ, ""); @@ -113,7 +125,7 @@ TEST_F(MapInfoGetElfTest, gnu_debugdata_init32) { memory_->SetMemory(0x2000 + offset, ptr, size); }); - Elf* elf = info.GetElf(process_memory_); + Elf* elf = info.GetElf(process_memory_, ARCH_ARM); ASSERT_TRUE(elf != nullptr); ASSERT_TRUE(elf->valid()); EXPECT_EQ(static_cast<uint32_t>(EM_ARM), elf->machine_type()); @@ -129,7 +141,7 @@ TEST_F(MapInfoGetElfTest, gnu_debugdata_init64) { memory_->SetMemory(0x5000 + offset, ptr, size); }); - Elf* elf = info.GetElf(process_memory_); + Elf* elf = info.GetElf(process_memory_, ARCH_ARM64); ASSERT_TRUE(elf != nullptr); ASSERT_TRUE(elf->valid()); EXPECT_EQ(static_cast<uint32_t>(EM_AARCH64), elf->machine_type()); @@ -144,20 +156,20 @@ TEST_F(MapInfoGetElfTest, end_le_start) { TestInitEhdr<Elf32_Ehdr>(&ehdr, ELFCLASS32, EM_ARM); ASSERT_TRUE(android::base::WriteFully(elf_.fd, &ehdr, sizeof(ehdr))); - Elf* elf = info.GetElf(process_memory_); + Elf* elf = info.GetElf(process_memory_, ARCH_ARM); ASSERT_TRUE(elf != nullptr); ASSERT_FALSE(elf->valid()); info.elf.reset(); info.end = 0xfff; - elf = info.GetElf(process_memory_); + elf = info.GetElf(process_memory_, ARCH_ARM); ASSERT_TRUE(elf != nullptr); ASSERT_FALSE(elf->valid()); // Make sure this test is valid. info.elf.reset(); info.end = 0x2000; - elf = info.GetElf(process_memory_); + elf = info.GetElf(process_memory_, ARCH_ARM); ASSERT_TRUE(elf != nullptr); ASSERT_TRUE(elf->valid()); } @@ -174,7 +186,7 @@ TEST_F(MapInfoGetElfTest, file_backed_non_zero_offset_full_file) { memcpy(buffer.data(), &ehdr, sizeof(ehdr)); ASSERT_TRUE(android::base::WriteFully(elf_.fd, buffer.data(), buffer.size())); - Elf* elf = info.GetElf(process_memory_); + Elf* elf = info.GetElf(process_memory_, ARCH_ARM); ASSERT_TRUE(elf != nullptr); ASSERT_TRUE(elf->valid()); ASSERT_TRUE(elf->memory() != nullptr); @@ -203,7 +215,7 @@ TEST_F(MapInfoGetElfTest, file_backed_non_zero_offset_partial_file) { memcpy(&buffer[info.offset], &ehdr, sizeof(ehdr)); ASSERT_TRUE(android::base::WriteFully(elf_.fd, buffer.data(), buffer.size())); - Elf* elf = info.GetElf(process_memory_); + Elf* elf = info.GetElf(process_memory_, ARCH_ARM); ASSERT_TRUE(elf != nullptr); ASSERT_TRUE(elf->valid()); ASSERT_TRUE(elf->memory() != nullptr); @@ -236,7 +248,7 @@ TEST_F(MapInfoGetElfTest, file_backed_non_zero_offset_partial_file_whole_elf32) memcpy(&buffer[info.offset], &ehdr, sizeof(ehdr)); ASSERT_TRUE(android::base::WriteFully(elf_.fd, buffer.data(), buffer.size())); - Elf* elf = info.GetElf(process_memory_); + Elf* elf = info.GetElf(process_memory_, ARCH_ARM); ASSERT_TRUE(elf != nullptr); ASSERT_TRUE(elf->valid()); ASSERT_TRUE(elf->memory() != nullptr); @@ -264,7 +276,7 @@ TEST_F(MapInfoGetElfTest, file_backed_non_zero_offset_partial_file_whole_elf64) memcpy(&buffer[info.offset], &ehdr, sizeof(ehdr)); ASSERT_TRUE(android::base::WriteFully(elf_.fd, buffer.data(), buffer.size())); - Elf* elf = info.GetElf(process_memory_); + Elf* elf = info.GetElf(process_memory_, ARCH_ARM64); ASSERT_TRUE(elf != nullptr); ASSERT_TRUE(elf->valid()); ASSERT_TRUE(elf->memory() != nullptr); @@ -290,13 +302,13 @@ TEST_F(MapInfoGetElfTest, process_memory_not_read_only) { ehdr.e_shnum = 0; memory_->SetMemory(0x9000, &ehdr, sizeof(ehdr)); - Elf* elf = info.GetElf(process_memory_); + Elf* elf = info.GetElf(process_memory_, ARCH_ARM64); ASSERT_TRUE(elf != nullptr); ASSERT_FALSE(elf->valid()); info.elf.reset(); info.flags = PROT_READ; - elf = info.GetElf(process_memory_); + elf = info.GetElf(process_memory_, ARCH_ARM64); ASSERT_TRUE(elf->valid()); } @@ -313,20 +325,20 @@ TEST_F(MapInfoGetElfTest, check_device_maps) { ehdr.e_shnum = 0; memory_->SetMemory(0x7000, &ehdr, sizeof(ehdr)); - Elf* elf = info.GetElf(process_memory_); + Elf* elf = info.GetElf(process_memory_, ARCH_X86_64); ASSERT_TRUE(elf != nullptr); ASSERT_FALSE(elf->valid()); // Set the name to nothing to verify that it still fails. info.elf.reset(); info.name = ""; - elf = info.GetElf(process_memory_); + elf = info.GetElf(process_memory_, ARCH_X86_64); ASSERT_FALSE(elf->valid()); // Change the flags and verify the elf is valid now. info.elf.reset(); info.flags = PROT_READ; - elf = info.GetElf(process_memory_); + elf = info.GetElf(process_memory_, ARCH_X86_64); ASSERT_TRUE(elf->valid()); } @@ -352,7 +364,7 @@ TEST_F(MapInfoGetElfTest, multiple_thread_get_elf) { std::thread* thread = new std::thread([i, this, &wait, &info, &elf_in_threads]() { while (wait) ; - Elf* elf = info.GetElf(process_memory_); + Elf* elf = info.GetElf(process_memory_, ARCH_X86_64); elf_in_threads[i] = elf; }); threads.push_back(thread); |