Loading libunwindstack/Global.cpp +18 −20 Original line number Diff line number Diff line Loading @@ -70,12 +70,16 @@ void Global::FindAndReadVariable(Maps* maps, const char* var_str) { // This also works: // f0000-f2000 0 r-- /system/lib/libc.so // f2000-f3000 2000 rw- /system/lib/libc.so MapInfo* map_start = nullptr; // It is also possible to see empty maps after the read-only like so: // f0000-f1000 0 r-- /system/lib/libc.so // f1000-f2000 0 --- // f2000-f3000 1000 r-x /system/lib/libc.so // f3000-f4000 2000 rw- /system/lib/libc.so MapInfo* map_zero = nullptr; for (const auto& info : *maps) { if (map_start != nullptr && map_start->name == info->name) { if (info->offset != 0 && (info->flags & (PROT_READ | PROT_WRITE)) == (PROT_READ | PROT_WRITE)) { Elf* elf = map_start->GetElf(memory_, arch()); if (info->offset != 0 && (info->flags & (PROT_READ | PROT_WRITE)) == (PROT_READ | PROT_WRITE) && map_zero != nullptr && Searchable(info->name) && info->name == map_zero->name) { Elf* elf = map_zero->GetElf(memory_, arch()); uint64_t ptr; if (elf->GetGlobalVariableOffset(variable, &ptr) && ptr != 0) { uint64_t offset_end = info->offset + info->end - info->start; Loading @@ -86,14 +90,8 @@ void Global::FindAndReadVariable(Maps* maps, const char* var_str) { } } } map_start = nullptr; } } else { map_start = nullptr; } if (map_start == nullptr && (info->flags & PROT_READ) && info->offset == 0 && Searchable(info->name)) { map_start = info.get(); } else if (info->offset == 0 && !info->name.empty()) { map_zero = info.get(); } } } Loading libunwindstack/tests/DexFilesTest.cpp +26 −1 Original line number Diff line number Diff line Loading @@ -64,7 +64,11 @@ class DexFilesTest : public ::testing::Test { "f000-11000 r--p 00000000 00:00 0 /fake/elf3\n" "100000-110000 rw-p 00f1000 00:00 0 /fake/elf3\n" "200000-210000 rw-p 0002000 00:00 0 /fake/elf3\n" "300000-400000 rw-p 0003000 00:00 0 /fake/elf3\n")); "300000-400000 rw-p 0003000 00:00 0 /fake/elf3\n" "500000-501000 r--p 0000000 00:00 0 /fake/elf4\n" "501000-502000 ---p 0000000 00:00 0\n" "503000-510000 rw-p 0003000 00:00 0 /fake/elf4\n" "510000-520000 rw-p 0010000 00:00 0 /fake/elf4\n")); ASSERT_TRUE(maps_->Parse()); // Global variable in a section that is not readable. Loading @@ -81,6 +85,11 @@ class DexFilesTest : public ::testing::Test { map_info = maps_->Get(kMapGlobal); ASSERT_TRUE(map_info != nullptr); CreateFakeElf(map_info, 0xf1800, 0xf1000, 0xf1000, 0x10000); // Global variable set in this map, but there is an empty map before rw map. map_info = maps_->Get(kMapGlobalAfterEmpty); ASSERT_TRUE(map_info != nullptr); CreateFakeElf(map_info, 0x3800, 0x3000, 0x3000, 0xd000); } void SetUp() override { Loading @@ -102,6 +111,8 @@ class DexFilesTest : public ::testing::Test { static constexpr size_t kMapGlobalRw = 6; static constexpr size_t kMapDexFileEntries = 7; static constexpr size_t kMapDexFiles = 8; static constexpr size_t kMapGlobalAfterEmpty = 9; static constexpr size_t kMapDexFilesAfterEmpty = 12; std::shared_ptr<Memory> process_memory_; MemoryFake* memory_; Loading Loading @@ -328,4 +339,18 @@ TEST_F(DexFilesTest, get_method_information_global_skip_zero_64) { EXPECT_EQ(0x123U, method_offset); } TEST_F(DexFilesTest, get_method_information_with_empty_map) { std::string method_name = "nothing"; uint64_t method_offset = 0x124; MapInfo* info = maps_->Get(kMapDexFilesAfterEmpty); WriteDescriptor32(0x503800, 0x506000); WriteEntry32(0x506000, 0, 0, 0x510000); WriteDex(0x510000); dex_files_->GetMethodInformation(maps_.get(), info, 0x510100, &method_name, &method_offset); EXPECT_EQ("Main.<init>", method_name); EXPECT_EQ(0U, method_offset); } } // namespace unwindstack Loading
libunwindstack/Global.cpp +18 −20 Original line number Diff line number Diff line Loading @@ -70,12 +70,16 @@ void Global::FindAndReadVariable(Maps* maps, const char* var_str) { // This also works: // f0000-f2000 0 r-- /system/lib/libc.so // f2000-f3000 2000 rw- /system/lib/libc.so MapInfo* map_start = nullptr; // It is also possible to see empty maps after the read-only like so: // f0000-f1000 0 r-- /system/lib/libc.so // f1000-f2000 0 --- // f2000-f3000 1000 r-x /system/lib/libc.so // f3000-f4000 2000 rw- /system/lib/libc.so MapInfo* map_zero = nullptr; for (const auto& info : *maps) { if (map_start != nullptr && map_start->name == info->name) { if (info->offset != 0 && (info->flags & (PROT_READ | PROT_WRITE)) == (PROT_READ | PROT_WRITE)) { Elf* elf = map_start->GetElf(memory_, arch()); if (info->offset != 0 && (info->flags & (PROT_READ | PROT_WRITE)) == (PROT_READ | PROT_WRITE) && map_zero != nullptr && Searchable(info->name) && info->name == map_zero->name) { Elf* elf = map_zero->GetElf(memory_, arch()); uint64_t ptr; if (elf->GetGlobalVariableOffset(variable, &ptr) && ptr != 0) { uint64_t offset_end = info->offset + info->end - info->start; Loading @@ -86,14 +90,8 @@ void Global::FindAndReadVariable(Maps* maps, const char* var_str) { } } } map_start = nullptr; } } else { map_start = nullptr; } if (map_start == nullptr && (info->flags & PROT_READ) && info->offset == 0 && Searchable(info->name)) { map_start = info.get(); } else if (info->offset == 0 && !info->name.empty()) { map_zero = info.get(); } } } Loading
libunwindstack/tests/DexFilesTest.cpp +26 −1 Original line number Diff line number Diff line Loading @@ -64,7 +64,11 @@ class DexFilesTest : public ::testing::Test { "f000-11000 r--p 00000000 00:00 0 /fake/elf3\n" "100000-110000 rw-p 00f1000 00:00 0 /fake/elf3\n" "200000-210000 rw-p 0002000 00:00 0 /fake/elf3\n" "300000-400000 rw-p 0003000 00:00 0 /fake/elf3\n")); "300000-400000 rw-p 0003000 00:00 0 /fake/elf3\n" "500000-501000 r--p 0000000 00:00 0 /fake/elf4\n" "501000-502000 ---p 0000000 00:00 0\n" "503000-510000 rw-p 0003000 00:00 0 /fake/elf4\n" "510000-520000 rw-p 0010000 00:00 0 /fake/elf4\n")); ASSERT_TRUE(maps_->Parse()); // Global variable in a section that is not readable. Loading @@ -81,6 +85,11 @@ class DexFilesTest : public ::testing::Test { map_info = maps_->Get(kMapGlobal); ASSERT_TRUE(map_info != nullptr); CreateFakeElf(map_info, 0xf1800, 0xf1000, 0xf1000, 0x10000); // Global variable set in this map, but there is an empty map before rw map. map_info = maps_->Get(kMapGlobalAfterEmpty); ASSERT_TRUE(map_info != nullptr); CreateFakeElf(map_info, 0x3800, 0x3000, 0x3000, 0xd000); } void SetUp() override { Loading @@ -102,6 +111,8 @@ class DexFilesTest : public ::testing::Test { static constexpr size_t kMapGlobalRw = 6; static constexpr size_t kMapDexFileEntries = 7; static constexpr size_t kMapDexFiles = 8; static constexpr size_t kMapGlobalAfterEmpty = 9; static constexpr size_t kMapDexFilesAfterEmpty = 12; std::shared_ptr<Memory> process_memory_; MemoryFake* memory_; Loading Loading @@ -328,4 +339,18 @@ TEST_F(DexFilesTest, get_method_information_global_skip_zero_64) { EXPECT_EQ(0x123U, method_offset); } TEST_F(DexFilesTest, get_method_information_with_empty_map) { std::string method_name = "nothing"; uint64_t method_offset = 0x124; MapInfo* info = maps_->Get(kMapDexFilesAfterEmpty); WriteDescriptor32(0x503800, 0x506000); WriteEntry32(0x506000, 0, 0, 0x510000); WriteDex(0x510000); dex_files_->GetMethodInformation(maps_.get(), info, 0x510100, &method_name, &method_offset); EXPECT_EQ("Main.<init>", method_name); EXPECT_EQ(0U, method_offset); } } // namespace unwindstack