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:
Christopher Ferris 2018-02-06 14:51:48 -08:00
parent 9d6b55928c
commit e762f1f193
4 changed files with 105 additions and 13 deletions

View File

@ -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) {

View File

@ -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 {

View File

@ -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; }

View File

@ -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_, &regs_, 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_, &regs_, 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;