Add indicator that an elf is memory backed.
Modify the unwinder library to indicate that at least one of the stack
frames contains an elf file that is unreadable.
Modify debuggerd to display a note about the unreadable frame and a possible
way to fix it.
Bug: 129769339
Test: New unit tests pass.
Test: Ran an app that crashes and has an unreadable file and verified the
Test: message is displayed. Then setenforce 0 and verify the message is
Test: not displayed.
Change-Id: Ibc4fe1d117e9b5840290454e90914ddc698d3cc2
Merged-In: Ibc4fe1d117e9b5840290454e90914ddc698d3cc2
(cherry picked from commit 4ae266ccbddbd0a6529248ecd1b324feab261c0d)
diff --git a/libunwindstack/tests/MapInfoCreateMemoryTest.cpp b/libunwindstack/tests/MapInfoCreateMemoryTest.cpp
index 2ddadef..6be8bdc 100644
--- a/libunwindstack/tests/MapInfoCreateMemoryTest.cpp
+++ b/libunwindstack/tests/MapInfoCreateMemoryTest.cpp
@@ -108,6 +108,7 @@
info.end = 0x101;
memory.reset(info.CreateMemory(process_memory_));
ASSERT_TRUE(memory.get() != nullptr);
+ EXPECT_FALSE(info.memory_backed_elf);
}
// Verify that if the offset is non-zero but there is no elf at the offset,
@@ -117,6 +118,7 @@
std::unique_ptr<Memory> memory(info.CreateMemory(process_memory_));
ASSERT_TRUE(memory.get() != nullptr);
+ EXPECT_FALSE(info.memory_backed_elf);
ASSERT_EQ(0x100U, info.elf_offset);
EXPECT_EQ(0x100U, info.elf_start_offset);
@@ -140,32 +142,40 @@
// offset to zero.
info.elf_offset = 0;
info.elf_start_offset = 0;
+ info.memory_backed_elf = false;
memory.reset(info.CreateMemory(process_memory_));
ASSERT_TRUE(memory.get() != nullptr);
+ EXPECT_FALSE(info.memory_backed_elf);
ASSERT_EQ(0x100U, info.elf_offset);
EXPECT_EQ(0x100U, info.elf_start_offset);
prev_info.offset = 0;
info.elf_offset = 0;
info.elf_start_offset = 0;
+ info.memory_backed_elf = false;
memory.reset(info.CreateMemory(process_memory_));
ASSERT_TRUE(memory.get() != nullptr);
+ EXPECT_FALSE(info.memory_backed_elf);
ASSERT_EQ(0x100U, info.elf_offset);
EXPECT_EQ(0x100U, info.elf_start_offset);
prev_info.flags = PROT_READ;
info.elf_offset = 0;
info.elf_start_offset = 0;
+ info.memory_backed_elf = false;
memory.reset(info.CreateMemory(process_memory_));
ASSERT_TRUE(memory.get() != nullptr);
+ EXPECT_FALSE(info.memory_backed_elf);
ASSERT_EQ(0x100U, info.elf_offset);
EXPECT_EQ(0x100U, info.elf_start_offset);
prev_info.name = info.name;
info.elf_offset = 0;
info.elf_start_offset = 0;
+ info.memory_backed_elf = false;
memory.reset(info.CreateMemory(process_memory_));
ASSERT_TRUE(memory.get() != nullptr);
+ EXPECT_FALSE(info.memory_backed_elf);
ASSERT_EQ(0x100U, info.elf_offset);
EXPECT_EQ(0U, info.elf_start_offset);
}
@@ -177,6 +187,7 @@
std::unique_ptr<Memory> memory(info.CreateMemory(process_memory_));
ASSERT_TRUE(memory.get() != nullptr);
+ EXPECT_FALSE(info.memory_backed_elf);
ASSERT_EQ(0U, info.elf_offset);
EXPECT_EQ(0x1000U, info.elf_start_offset);
@@ -201,6 +212,7 @@
std::unique_ptr<Memory> memory(info.CreateMemory(process_memory_));
ASSERT_TRUE(memory.get() != nullptr);
+ EXPECT_FALSE(info.memory_backed_elf);
ASSERT_EQ(0U, info.elf_offset);
EXPECT_EQ(0x1000U, info.elf_start_offset);
@@ -218,6 +230,7 @@
std::unique_ptr<Memory> memory(info.CreateMemory(process_memory_));
ASSERT_TRUE(memory.get() != nullptr);
+ EXPECT_FALSE(info.memory_backed_elf);
ASSERT_EQ(0U, info.elf_offset);
EXPECT_EQ(0x2000U, info.elf_start_offset);
@@ -259,6 +272,7 @@
std::unique_ptr<Memory> memory(info.CreateMemory(process_memory_));
ASSERT_TRUE(memory.get() != nullptr);
+ EXPECT_TRUE(info.memory_backed_elf);
memset(buffer.data(), 0, buffer.size());
ASSERT_TRUE(memory->ReadFully(0, buffer.data(), buffer.size()));
@@ -290,6 +304,7 @@
std::unique_ptr<Memory> mem(map_info->CreateMemory(process_memory_));
ASSERT_TRUE(mem.get() != nullptr);
+ EXPECT_TRUE(map_info->memory_backed_elf);
EXPECT_EQ(0x4000UL, map_info->elf_offset);
EXPECT_EQ(0x4000UL, map_info->offset);
EXPECT_EQ(0U, map_info->elf_start_offset);
@@ -336,6 +351,7 @@
std::unique_ptr<Memory> mem(map_info->CreateMemory(process_memory_));
ASSERT_TRUE(mem.get() != nullptr);
+ EXPECT_TRUE(map_info->memory_backed_elf);
EXPECT_EQ(0x1000UL, map_info->elf_offset);
EXPECT_EQ(0xb000UL, map_info->offset);
EXPECT_EQ(0xa000UL, map_info->elf_start_offset);
@@ -374,6 +390,7 @@
// extend over the executable segment.
std::unique_ptr<Memory> memory(map_info->CreateMemory(process_memory_));
ASSERT_TRUE(memory.get() != nullptr);
+ EXPECT_FALSE(map_info->memory_backed_elf);
std::vector<uint8_t> buffer(0x100);
EXPECT_EQ(0x2000U, map_info->offset);
EXPECT_EQ(0U, map_info->elf_offset);
@@ -388,7 +405,9 @@
ASSERT_EQ(0x1000, lseek(elf_at_1000_.fd, 0x1000, SEEK_SET));
ASSERT_TRUE(android::base::WriteFully(elf_at_1000_.fd, &ehdr, sizeof(ehdr)));
+ map_info->memory_backed_elf = false;
memory.reset(map_info->CreateMemory(process_memory_));
+ EXPECT_FALSE(map_info->memory_backed_elf);
EXPECT_EQ(0x2000U, map_info->offset);
EXPECT_EQ(0x1000U, map_info->elf_offset);
EXPECT_EQ(0x1000U, map_info->elf_start_offset);
diff --git a/libunwindstack/tests/UnwinderTest.cpp b/libunwindstack/tests/UnwinderTest.cpp
index 48e038e..f635021 100644
--- a/libunwindstack/tests/UnwinderTest.cpp
+++ b/libunwindstack/tests/UnwinderTest.cpp
@@ -108,6 +108,24 @@
const auto& info2 = *--maps_->end();
info2->elf_offset = 0x8000;
+ elf = new ElfFake(new MemoryFake);
+ elf->FakeSetInterface(new ElfInterfaceFake(nullptr));
+ AddMapInfo(0xc0000, 0xc1000, 0, PROT_READ | PROT_WRITE | PROT_EXEC, "/fake/unreadable.so", elf);
+ const auto& info3 = *--maps_->end();
+ info3->memory_backed_elf = true;
+
+ elf = new ElfFake(new MemoryFake);
+ elf->FakeSetInterface(new ElfInterfaceFake(nullptr));
+ AddMapInfo(0xc1000, 0xc2000, 0, PROT_READ | PROT_WRITE | PROT_EXEC, "[vdso]", elf);
+ const auto& info4 = *--maps_->end();
+ info4->memory_backed_elf = true;
+
+ elf = new ElfFake(new MemoryFake);
+ elf->FakeSetInterface(new ElfInterfaceFake(nullptr));
+ AddMapInfo(0xc2000, 0xc3000, 0, PROT_READ | PROT_WRITE | PROT_EXEC, "", elf);
+ const auto& info5 = *--maps_->end();
+ info5->memory_backed_elf = true;
+
process_memory_.reset(new MemoryFake);
}
@@ -140,6 +158,7 @@
Unwinder unwinder(64, maps_.get(), ®s_, process_memory_);
unwinder.Unwind();
EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode());
+ EXPECT_FALSE(unwinder.elf_from_memory_not_file());
ASSERT_EQ(3U, unwinder.NumFrames());
@@ -204,6 +223,7 @@
unwinder.SetResolveNames(false);
unwinder.Unwind();
EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode());
+ EXPECT_FALSE(unwinder.elf_from_memory_not_file());
ASSERT_EQ(3U, unwinder.NumFrames());
@@ -263,6 +283,7 @@
Unwinder unwinder(64, maps_.get(), ®s_, process_memory_);
unwinder.Unwind();
EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode());
+ EXPECT_FALSE(unwinder.elf_from_memory_not_file());
ASSERT_EQ(1U, unwinder.NumFrames());
@@ -292,6 +313,7 @@
Unwinder unwinder(64, maps_.get(), ®s_, process_memory_);
unwinder.Unwind();
EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode());
+ EXPECT_FALSE(unwinder.elf_from_memory_not_file());
ASSERT_EQ(1U, unwinder.NumFrames());
@@ -321,6 +343,7 @@
Unwinder unwinder(64, maps_.get(), ®s_, process_memory_);
unwinder.Unwind();
EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode());
+ EXPECT_FALSE(unwinder.elf_from_memory_not_file());
ASSERT_EQ(1U, unwinder.NumFrames());
@@ -351,6 +374,7 @@
unwinder.SetEmbeddedSoname(false);
unwinder.Unwind();
EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode());
+ EXPECT_FALSE(unwinder.elf_from_memory_not_file());
ASSERT_EQ(1U, unwinder.NumFrames());
@@ -387,6 +411,7 @@
Unwinder unwinder(64, maps_.get(), ®s_, process_memory_);
unwinder.Unwind();
EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode());
+ EXPECT_FALSE(unwinder.elf_from_memory_not_file());
ASSERT_EQ(1U, unwinder.NumFrames());
@@ -419,6 +444,7 @@
Unwinder unwinder(20, maps_.get(), ®s_, process_memory_);
unwinder.Unwind();
EXPECT_EQ(ERROR_MAX_FRAMES_EXCEEDED, unwinder.LastErrorCode());
+ EXPECT_FALSE(unwinder.elf_from_memory_not_file());
ASSERT_EQ(20U, unwinder.NumFrames());
@@ -461,6 +487,7 @@
std::vector<std::string> skip_libs{"libunwind.so", "libanother.so"};
unwinder.Unwind(&skip_libs);
EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode());
+ EXPECT_FALSE(unwinder.elf_from_memory_not_file());
ASSERT_EQ(3U, unwinder.NumFrames());
@@ -522,6 +549,7 @@
Unwinder unwinder(64, maps_.get(), ®s_, process_memory_);
unwinder.Unwind();
EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode());
+ EXPECT_FALSE(unwinder.elf_from_memory_not_file());
ASSERT_EQ(2U, unwinder.NumFrames());
@@ -569,6 +597,7 @@
Unwinder unwinder(64, maps_.get(), ®s_, process_memory_);
unwinder.Unwind();
EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode());
+ EXPECT_FALSE(unwinder.elf_from_memory_not_file());
ASSERT_EQ(1U, unwinder.NumFrames());
}
@@ -588,6 +617,7 @@
Unwinder unwinder(64, maps_.get(), ®s_, process_memory_);
unwinder.Unwind();
EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode());
+ EXPECT_FALSE(unwinder.elf_from_memory_not_file());
ASSERT_EQ(1U, unwinder.NumFrames());
}
@@ -602,6 +632,7 @@
Unwinder unwinder(64, maps_.get(), ®s_, process_memory_);
unwinder.Unwind();
EXPECT_EQ(ERROR_INVALID_MAP, unwinder.LastErrorCode());
+ EXPECT_FALSE(unwinder.elf_from_memory_not_file());
ASSERT_EQ(1U, unwinder.NumFrames());
@@ -638,6 +669,7 @@
Unwinder unwinder(64, maps_.get(), ®s_, process_memory_);
unwinder.Unwind();
EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode());
+ EXPECT_FALSE(unwinder.elf_from_memory_not_file());
ASSERT_EQ(3U, unwinder.NumFrames());
@@ -703,6 +735,7 @@
Unwinder unwinder(64, maps_.get(), ®s_, process_memory_);
unwinder.Unwind();
EXPECT_EQ(ERROR_INVALID_MAP, unwinder.LastErrorCode());
+ EXPECT_FALSE(unwinder.elf_from_memory_not_file());
ASSERT_EQ(2U, unwinder.NumFrames());
@@ -752,6 +785,7 @@
Unwinder unwinder(64, maps_.get(), ®s_, process_memory_);
unwinder.Unwind();
EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode());
+ EXPECT_FALSE(unwinder.elf_from_memory_not_file());
ASSERT_EQ(2U, unwinder.NumFrames());
@@ -799,6 +833,7 @@
std::vector<std::string> skip_names{"libanother.so"};
unwinder.Unwind(&skip_names);
EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode());
+ EXPECT_FALSE(unwinder.elf_from_memory_not_file());
ASSERT_EQ(0U, unwinder.NumFrames());
}
@@ -821,6 +856,7 @@
std::vector<std::string> suffixes{"oat"};
unwinder.Unwind(nullptr, &suffixes);
EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode());
+ EXPECT_FALSE(unwinder.elf_from_memory_not_file());
ASSERT_EQ(2U, unwinder.NumFrames());
// Make sure the elf was not initialized.
@@ -879,6 +915,7 @@
Unwinder unwinder(64, maps_.get(), ®s_, process_memory_);
unwinder.Unwind();
EXPECT_EQ(ERROR_REPEATED_FRAME, unwinder.LastErrorCode());
+ EXPECT_FALSE(unwinder.elf_from_memory_not_file());
ASSERT_EQ(3U, unwinder.NumFrames());
@@ -937,6 +974,7 @@
Unwinder unwinder(64, maps_.get(), ®s_, process_memory_);
unwinder.Unwind();
EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode());
+ EXPECT_FALSE(unwinder.elf_from_memory_not_file());
ASSERT_EQ(2U, unwinder.NumFrames());
@@ -980,6 +1018,7 @@
Unwinder unwinder(64, maps_.get(), ®s_, process_memory_);
unwinder.Unwind();
EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode());
+ EXPECT_FALSE(unwinder.elf_from_memory_not_file());
ASSERT_EQ(2U, unwinder.NumFrames());
@@ -1026,6 +1065,7 @@
Unwinder unwinder(64, maps_.get(), ®s_, process_memory_);
unwinder.Unwind();
EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode());
+ EXPECT_FALSE(unwinder.elf_from_memory_not_file());
ASSERT_EQ(3U, unwinder.NumFrames());
@@ -1084,6 +1124,7 @@
Unwinder unwinder(1, maps_.get(), ®s_, process_memory_);
unwinder.Unwind();
EXPECT_EQ(ERROR_MAX_FRAMES_EXCEEDED, unwinder.LastErrorCode());
+ EXPECT_FALSE(unwinder.elf_from_memory_not_file());
ASSERT_EQ(1U, unwinder.NumFrames());
@@ -1103,6 +1144,96 @@
EXPECT_EQ(PROT_READ | PROT_WRITE | PROT_EXEC, frame->map_flags);
}
+TEST_F(UnwinderTest, elf_from_memory_not_file) {
+ ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 0));
+
+ regs_.set_pc(0xc0050);
+ regs_.set_sp(0x10000);
+ ElfInterfaceFake::FakePushStepData(StepData(0, 0, true));
+
+ Unwinder unwinder(64, maps_.get(), ®s_, process_memory_);
+ unwinder.Unwind();
+ EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode());
+ EXPECT_TRUE(unwinder.elf_from_memory_not_file());
+
+ ASSERT_EQ(1U, unwinder.NumFrames());
+
+ auto* frame = &unwinder.frames()[0];
+ EXPECT_EQ(0U, frame->num);
+ EXPECT_EQ(0x50U, frame->rel_pc);
+ EXPECT_EQ(0xc0050U, frame->pc);
+ EXPECT_EQ(0x10000U, frame->sp);
+ EXPECT_EQ("Frame0", frame->function_name);
+ EXPECT_EQ(0U, frame->function_offset);
+ EXPECT_EQ("/fake/unreadable.so", frame->map_name);
+ EXPECT_EQ(0U, frame->map_elf_start_offset);
+ EXPECT_EQ(0U, frame->map_exact_offset);
+ EXPECT_EQ(0xc0000U, frame->map_start);
+ EXPECT_EQ(0xc1000U, frame->map_end);
+ EXPECT_EQ(0U, frame->map_load_bias);
+ EXPECT_EQ(PROT_READ | PROT_WRITE | PROT_EXEC, frame->map_flags);
+}
+
+TEST_F(UnwinderTest, elf_from_memory_but_no_valid_file_with_bracket) {
+ ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 0));
+
+ regs_.set_pc(0xc1050);
+ regs_.set_sp(0x10000);
+ ElfInterfaceFake::FakePushStepData(StepData(0, 0, true));
+
+ Unwinder unwinder(64, maps_.get(), ®s_, process_memory_);
+ unwinder.Unwind();
+ EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode());
+ EXPECT_FALSE(unwinder.elf_from_memory_not_file());
+
+ ASSERT_EQ(1U, unwinder.NumFrames());
+
+ auto* frame = &unwinder.frames()[0];
+ EXPECT_EQ(0U, frame->num);
+ EXPECT_EQ(0x50U, frame->rel_pc);
+ EXPECT_EQ(0xc1050U, frame->pc);
+ EXPECT_EQ(0x10000U, frame->sp);
+ EXPECT_EQ("Frame0", frame->function_name);
+ EXPECT_EQ(0U, frame->function_offset);
+ EXPECT_EQ("[vdso]", frame->map_name);
+ EXPECT_EQ(0U, frame->map_elf_start_offset);
+ EXPECT_EQ(0U, frame->map_exact_offset);
+ EXPECT_EQ(0xc1000U, frame->map_start);
+ EXPECT_EQ(0xc2000U, frame->map_end);
+ EXPECT_EQ(0U, frame->map_load_bias);
+ EXPECT_EQ(PROT_READ | PROT_WRITE | PROT_EXEC, frame->map_flags);
+}
+
+TEST_F(UnwinderTest, elf_from_memory_but_empty_filename) {
+ ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 0));
+
+ regs_.set_pc(0xc2050);
+ regs_.set_sp(0x10000);
+ ElfInterfaceFake::FakePushStepData(StepData(0, 0, true));
+
+ Unwinder unwinder(64, maps_.get(), ®s_, process_memory_);
+ unwinder.Unwind();
+ EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode());
+ EXPECT_FALSE(unwinder.elf_from_memory_not_file());
+
+ ASSERT_EQ(1U, unwinder.NumFrames());
+
+ auto* frame = &unwinder.frames()[0];
+ EXPECT_EQ(0U, frame->num);
+ EXPECT_EQ(0x50U, frame->rel_pc);
+ EXPECT_EQ(0xc2050U, frame->pc);
+ EXPECT_EQ(0x10000U, frame->sp);
+ EXPECT_EQ("Frame0", frame->function_name);
+ EXPECT_EQ(0U, frame->function_offset);
+ EXPECT_EQ("", frame->map_name);
+ EXPECT_EQ(0U, frame->map_elf_start_offset);
+ EXPECT_EQ(0U, frame->map_exact_offset);
+ EXPECT_EQ(0xc2000U, frame->map_start);
+ EXPECT_EQ(0xc3000U, frame->map_end);
+ EXPECT_EQ(0U, frame->map_load_bias);
+ EXPECT_EQ(PROT_READ | PROT_WRITE | PROT_EXEC, frame->map_flags);
+}
+
// Verify format frame code.
TEST_F(UnwinderTest, format_frame) {
RegsFake regs_arm(10);