Check that dex pc is in a valid map.
Add new unit tests for dex pc being non-zero. Bug: 73004673 Test: Ran unit tests. Test: Ran art 137-cfi test on host for interpreter. Change-Id: I09bbf96d0ed65fc1e5896e4ab2bc67867e3b7fdb
This commit is contained in:
parent
9d6b55928c
commit
e762f1f193
|
@ -54,13 +54,18 @@ void Unwinder::FillInDexFrame() {
|
|||
frame->sp = regs_->sp();
|
||||
|
||||
MapInfo* info = maps_->Find(dex_pc);
|
||||
frame->map_start = info->start;
|
||||
frame->map_end = info->end;
|
||||
frame->map_offset = info->offset;
|
||||
frame->map_load_bias = info->load_bias;
|
||||
frame->map_flags = info->flags;
|
||||
frame->map_name = info->name;
|
||||
frame->rel_pc = dex_pc - info->start;
|
||||
if (info != nullptr) {
|
||||
frame->map_start = info->start;
|
||||
frame->map_end = info->end;
|
||||
frame->map_offset = info->offset;
|
||||
frame->map_load_bias = info->load_bias;
|
||||
frame->map_flags = info->flags;
|
||||
frame->map_name = info->name;
|
||||
frame->rel_pc = dex_pc - info->start;
|
||||
} else {
|
||||
frame->rel_pc = dex_pc;
|
||||
return;
|
||||
}
|
||||
|
||||
#if !defined(NO_LIBDEXFILE_SUPPORT)
|
||||
if (dex_files_ == nullptr) {
|
||||
|
|
|
@ -45,14 +45,14 @@ struct FrameData {
|
|||
uint64_t sp;
|
||||
|
||||
std::string function_name;
|
||||
uint64_t function_offset;
|
||||
uint64_t function_offset = 0;
|
||||
|
||||
std::string map_name;
|
||||
uint64_t map_offset;
|
||||
uint64_t map_start;
|
||||
uint64_t map_end;
|
||||
uint64_t map_load_bias;
|
||||
int map_flags;
|
||||
uint64_t map_offset = 0;
|
||||
uint64_t map_start = 0;
|
||||
uint64_t map_end = 0;
|
||||
uint64_t map_load_bias = 0;
|
||||
int map_flags = 0;
|
||||
};
|
||||
|
||||
class Unwinder {
|
||||
|
|
|
@ -56,6 +56,7 @@ class RegsFake : public Regs {
|
|||
void FakeSetArch(ArchEnum arch) { fake_arch_ = arch; }
|
||||
void FakeSetPc(uint64_t pc) { fake_pc_ = pc; }
|
||||
void FakeSetSp(uint64_t sp) { fake_sp_ = sp; }
|
||||
void FakeSetDexPc(uint64_t dex_pc) { dex_pc_ = dex_pc; }
|
||||
void FakeSetReturnAddress(uint64_t return_address) { fake_return_address_ = return_address; }
|
||||
void FakeSetReturnAddressValid(bool valid) { fake_return_address_valid_ = valid; }
|
||||
|
||||
|
|
|
@ -98,6 +98,10 @@ class UnwinderTest : public ::testing::Test {
|
|||
info = new MapInfo(0x53000, 0x54000, 0, PROT_READ | PROT_WRITE, "/fake/fake.oat");
|
||||
maps_.FakeAddMapInfo(info);
|
||||
|
||||
info = new MapInfo(0xa3000, 0xa4000, 0, PROT_READ | PROT_WRITE | PROT_EXEC, "/fake/fake.vdex");
|
||||
info->load_bias = 0;
|
||||
maps_.FakeAddMapInfo(info);
|
||||
|
||||
process_memory_.reset(new MemoryFake);
|
||||
}
|
||||
|
||||
|
@ -666,6 +670,88 @@ TEST_F(UnwinderTest, sp_pc_do_not_change) {
|
|||
EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags);
|
||||
}
|
||||
|
||||
TEST_F(UnwinderTest, dex_pc_in_map) {
|
||||
ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 0));
|
||||
regs_.FakeSetPc(0x1000);
|
||||
regs_.FakeSetSp(0x10000);
|
||||
regs_.FakeSetDexPc(0xa3400);
|
||||
|
||||
Unwinder unwinder(64, &maps_, ®s_, process_memory_);
|
||||
unwinder.Unwind();
|
||||
EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode());
|
||||
|
||||
ASSERT_EQ(2U, unwinder.NumFrames());
|
||||
|
||||
auto* frame = &unwinder.frames()[0];
|
||||
EXPECT_EQ(0U, frame->num);
|
||||
EXPECT_EQ(0x400U, frame->rel_pc);
|
||||
EXPECT_EQ(0xa3400U, frame->pc);
|
||||
EXPECT_EQ(0x10000U, frame->sp);
|
||||
EXPECT_EQ("", frame->function_name);
|
||||
EXPECT_EQ(0U, frame->function_offset);
|
||||
EXPECT_EQ("/fake/fake.vdex", frame->map_name);
|
||||
EXPECT_EQ(0U, frame->map_offset);
|
||||
EXPECT_EQ(0xa3000U, frame->map_start);
|
||||
EXPECT_EQ(0xa4000U, frame->map_end);
|
||||
EXPECT_EQ(0U, frame->map_load_bias);
|
||||
EXPECT_EQ(PROT_READ | PROT_WRITE | PROT_EXEC, frame->map_flags);
|
||||
|
||||
frame = &unwinder.frames()[1];
|
||||
EXPECT_EQ(1U, frame->num);
|
||||
EXPECT_EQ(0U, frame->rel_pc);
|
||||
EXPECT_EQ(0x1000U, frame->pc);
|
||||
EXPECT_EQ(0x10000U, frame->sp);
|
||||
EXPECT_EQ("Frame0", frame->function_name);
|
||||
EXPECT_EQ(0U, frame->function_offset);
|
||||
EXPECT_EQ("/system/fake/libc.so", frame->map_name);
|
||||
EXPECT_EQ(0U, frame->map_offset);
|
||||
EXPECT_EQ(0x1000U, frame->map_start);
|
||||
EXPECT_EQ(0x8000U, frame->map_end);
|
||||
EXPECT_EQ(0U, frame->map_load_bias);
|
||||
EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags);
|
||||
}
|
||||
|
||||
TEST_F(UnwinderTest, dex_pc_not_in_map) {
|
||||
ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 0));
|
||||
regs_.FakeSetPc(0x1000);
|
||||
regs_.FakeSetSp(0x10000);
|
||||
regs_.FakeSetDexPc(0x50000);
|
||||
|
||||
Unwinder unwinder(64, &maps_, ®s_, process_memory_);
|
||||
unwinder.Unwind();
|
||||
EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode());
|
||||
|
||||
ASSERT_EQ(2U, unwinder.NumFrames());
|
||||
|
||||
auto* frame = &unwinder.frames()[0];
|
||||
EXPECT_EQ(0U, frame->num);
|
||||
EXPECT_EQ(0x50000U, frame->rel_pc);
|
||||
EXPECT_EQ(0x50000U, frame->pc);
|
||||
EXPECT_EQ(0x10000U, frame->sp);
|
||||
EXPECT_EQ("", frame->function_name);
|
||||
EXPECT_EQ(0U, frame->function_offset);
|
||||
EXPECT_EQ("", frame->map_name);
|
||||
EXPECT_EQ(0U, frame->map_offset);
|
||||
EXPECT_EQ(0U, frame->map_start);
|
||||
EXPECT_EQ(0U, frame->map_end);
|
||||
EXPECT_EQ(0U, frame->map_load_bias);
|
||||
EXPECT_EQ(0, frame->map_flags);
|
||||
|
||||
frame = &unwinder.frames()[1];
|
||||
EXPECT_EQ(1U, frame->num);
|
||||
EXPECT_EQ(0U, frame->rel_pc);
|
||||
EXPECT_EQ(0x1000U, frame->pc);
|
||||
EXPECT_EQ(0x10000U, frame->sp);
|
||||
EXPECT_EQ("Frame0", frame->function_name);
|
||||
EXPECT_EQ(0U, frame->function_offset);
|
||||
EXPECT_EQ("/system/fake/libc.so", frame->map_name);
|
||||
EXPECT_EQ(0U, frame->map_offset);
|
||||
EXPECT_EQ(0x1000U, frame->map_start);
|
||||
EXPECT_EQ(0x8000U, frame->map_end);
|
||||
EXPECT_EQ(0U, frame->map_load_bias);
|
||||
EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags);
|
||||
}
|
||||
|
||||
// Verify format frame code.
|
||||
TEST_F(UnwinderTest, format_frame_static) {
|
||||
FrameData frame;
|
||||
|
|
Loading…
Reference in New Issue