Adjust DEX file reading to follow layout changes in ART.
I have changed the root DEX debug descriptor in ART to more closely follow the JIT debug descriptor. Add the appropriate offsets to correctly fetch the linked list head for DEX files. Test: testrunner.py -t 137 Test: libunwindstack_test Change-Id: I90402befc88fec42658f7330d51ee79756a7f872
This commit is contained in:
parent
e1ae2ff9e4
commit
4015ef411a
|
@ -77,7 +77,8 @@ void DexFiles::SetArch(ArchEnum arch) {
|
|||
|
||||
uint64_t DexFiles::ReadEntryPtr32(uint64_t addr) {
|
||||
uint32_t entry;
|
||||
if (!memory_->ReadFully(addr, &entry, sizeof(entry))) {
|
||||
const uint32_t field_offset = 12; // offset of first_entry_ in the descriptor struct.
|
||||
if (!memory_->ReadFully(addr + field_offset, &entry, sizeof(entry))) {
|
||||
return 0;
|
||||
}
|
||||
return entry;
|
||||
|
@ -85,7 +86,8 @@ uint64_t DexFiles::ReadEntryPtr32(uint64_t addr) {
|
|||
|
||||
uint64_t DexFiles::ReadEntryPtr64(uint64_t addr) {
|
||||
uint64_t entry;
|
||||
if (!memory_->ReadFully(addr, &entry, sizeof(entry))) {
|
||||
const uint32_t field_offset = 16; // offset of first_entry_ in the descriptor struct.
|
||||
if (!memory_->ReadFully(addr + field_offset, &entry, sizeof(entry))) {
|
||||
return 0;
|
||||
}
|
||||
return entry;
|
||||
|
@ -122,7 +124,7 @@ void DexFiles::Init(Maps* maps) {
|
|||
initialized_ = true;
|
||||
entry_addr_ = 0;
|
||||
|
||||
const std::string dex_debug_name("__art_debug_dexfiles");
|
||||
const std::string dex_debug_name("__dex_debug_descriptor");
|
||||
for (MapInfo* info : *maps) {
|
||||
if (!(info->flags & PROT_EXEC) || !(info->flags & PROT_READ) || info->offset != 0) {
|
||||
continue;
|
||||
|
|
|
@ -63,7 +63,7 @@ class DexFilesTest : public ::testing::Test {
|
|||
elf->FakeSetValid(true);
|
||||
ElfInterfaceFake* interface = new ElfInterfaceFake(memory);
|
||||
elf->FakeSetInterface(interface);
|
||||
interface->FakeSetGlobalVariable("__art_debug_dexfiles", 0x800);
|
||||
interface->FakeSetGlobalVariable("__dex_debug_descriptor", 0x800);
|
||||
map_info->elf.reset(elf);
|
||||
|
||||
// Global variable not set by default.
|
||||
|
@ -74,7 +74,7 @@ class DexFilesTest : public ::testing::Test {
|
|||
elf->FakeSetValid(true);
|
||||
interface = new ElfInterfaceFake(memory);
|
||||
elf->FakeSetInterface(interface);
|
||||
interface->FakeSetGlobalVariable("__art_debug_dexfiles", 0x800);
|
||||
interface->FakeSetGlobalVariable("__dex_debug_descriptor", 0x800);
|
||||
map_info->elf.reset(elf);
|
||||
|
||||
// Global variable set in this map.
|
||||
|
@ -85,10 +85,12 @@ class DexFilesTest : public ::testing::Test {
|
|||
elf->FakeSetValid(true);
|
||||
interface = new ElfInterfaceFake(memory);
|
||||
elf->FakeSetInterface(interface);
|
||||
interface->FakeSetGlobalVariable("__art_debug_dexfiles", 0x800);
|
||||
interface->FakeSetGlobalVariable("__dex_debug_descriptor", 0x800);
|
||||
map_info->elf.reset(elf);
|
||||
}
|
||||
|
||||
void WriteDescriptor32(uint64_t addr, uint32_t head);
|
||||
void WriteDescriptor64(uint64_t addr, uint64_t head);
|
||||
void WriteEntry32(uint64_t entry_addr, uint32_t next, uint32_t prev, uint32_t dex_file);
|
||||
void WriteEntry64(uint64_t entry_addr, uint64_t next, uint64_t prev, uint64_t dex_file);
|
||||
void WriteDex(uint64_t dex_file);
|
||||
|
@ -105,6 +107,16 @@ class DexFilesTest : public ::testing::Test {
|
|||
std::unique_ptr<BufferMaps> maps_;
|
||||
};
|
||||
|
||||
void DexFilesTest::WriteDescriptor32(uint64_t addr, uint32_t head) {
|
||||
// void* first_entry_
|
||||
memory_->SetData32(addr + 12, head);
|
||||
}
|
||||
|
||||
void DexFilesTest::WriteDescriptor64(uint64_t addr, uint64_t head) {
|
||||
// void* first_entry_
|
||||
memory_->SetData64(addr + 16, head);
|
||||
}
|
||||
|
||||
void DexFilesTest::WriteEntry32(uint64_t entry_addr, uint32_t next, uint32_t prev,
|
||||
uint32_t dex_file) {
|
||||
// Format of the 32 bit DEXFileEntry structure:
|
||||
|
@ -146,7 +158,7 @@ TEST_F(DexFilesTest, get_method_information_32) {
|
|||
uint64_t method_offset = 0x124;
|
||||
MapInfo* info = maps_->Get(kMapDexFiles);
|
||||
|
||||
memory_->SetData32(0xf800, 0x200000);
|
||||
WriteDescriptor32(0xf800, 0x200000);
|
||||
WriteEntry32(0x200000, 0, 0, 0x300000);
|
||||
WriteDex(0x300000);
|
||||
|
||||
|
@ -161,7 +173,7 @@ TEST_F(DexFilesTest, get_method_information_64) {
|
|||
MapInfo* info = maps_->Get(kMapDexFiles);
|
||||
|
||||
dex_files_->SetArch(ARCH_ARM64);
|
||||
memory_->SetData64(0xf800, 0x200000);
|
||||
WriteDescriptor64(0xf800, 0x200000);
|
||||
WriteEntry64(0x200000, 0, 0, 0x301000);
|
||||
WriteDex(0x301000);
|
||||
|
||||
|
@ -175,7 +187,7 @@ TEST_F(DexFilesTest, get_method_information_not_first_entry_32) {
|
|||
uint64_t method_offset = 0x124;
|
||||
MapInfo* info = maps_->Get(kMapDexFiles);
|
||||
|
||||
memory_->SetData32(0xf800, 0x200000);
|
||||
WriteDescriptor32(0xf800, 0x200000);
|
||||
WriteEntry32(0x200000, 0x200100, 0, 0x100000);
|
||||
WriteEntry32(0x200100, 0, 0x200000, 0x300000);
|
||||
WriteDex(0x300000);
|
||||
|
@ -191,7 +203,7 @@ TEST_F(DexFilesTest, get_method_information_not_first_entry_64) {
|
|||
MapInfo* info = maps_->Get(kMapDexFiles);
|
||||
|
||||
dex_files_->SetArch(ARCH_ARM64);
|
||||
memory_->SetData64(0xf800, 0x200000);
|
||||
WriteDescriptor64(0xf800, 0x200000);
|
||||
WriteEntry64(0x200000, 0x200100, 0, 0x100000);
|
||||
WriteEntry64(0x200100, 0, 0x200000, 0x300000);
|
||||
WriteDex(0x300000);
|
||||
|
@ -206,7 +218,7 @@ TEST_F(DexFilesTest, get_method_information_cached) {
|
|||
uint64_t method_offset = 0x124;
|
||||
MapInfo* info = maps_->Get(kMapDexFiles);
|
||||
|
||||
memory_->SetData32(0xf800, 0x200000);
|
||||
WriteDescriptor32(0xf800, 0x200000);
|
||||
WriteEntry32(0x200000, 0, 0, 0x300000);
|
||||
WriteDex(0x300000);
|
||||
|
||||
|
@ -226,7 +238,7 @@ TEST_F(DexFilesTest, get_method_information_search_libs) {
|
|||
uint64_t method_offset = 0x124;
|
||||
MapInfo* info = maps_->Get(kMapDexFiles);
|
||||
|
||||
memory_->SetData32(0xf800, 0x200000);
|
||||
WriteDescriptor32(0xf800, 0x200000);
|
||||
WriteEntry32(0x200000, 0x200100, 0, 0x100000);
|
||||
WriteEntry32(0x200100, 0, 0x200000, 0x300000);
|
||||
WriteDex(0x300000);
|
||||
|
@ -259,9 +271,9 @@ TEST_F(DexFilesTest, get_method_information_global_skip_zero_32) {
|
|||
MapInfo* info = maps_->Get(kMapDexFiles);
|
||||
|
||||
// First global variable found, but value is zero.
|
||||
memory_->SetData32(0xc800, 0);
|
||||
WriteDescriptor32(0xc800, 0);
|
||||
|
||||
memory_->SetData32(0xf800, 0x200000);
|
||||
WriteDescriptor32(0xf800, 0x200000);
|
||||
WriteEntry32(0x200000, 0, 0, 0x300000);
|
||||
WriteDex(0x300000);
|
||||
|
||||
|
@ -274,7 +286,7 @@ TEST_F(DexFilesTest, get_method_information_global_skip_zero_32) {
|
|||
dex_files_->SetArch(ARCH_ARM);
|
||||
method_name = "fail";
|
||||
method_offset = 0x123;
|
||||
memory_->SetData32(0xc800, 0x100000);
|
||||
WriteDescriptor32(0xc800, 0x100000);
|
||||
dex_files_->GetMethodInformation(maps_.get(), info, 0x300100, &method_name, &method_offset);
|
||||
EXPECT_EQ("fail", method_name);
|
||||
EXPECT_EQ(0x123U, method_offset);
|
||||
|
@ -286,9 +298,9 @@ TEST_F(DexFilesTest, get_method_information_global_skip_zero_64) {
|
|||
MapInfo* info = maps_->Get(kMapDexFiles);
|
||||
|
||||
// First global variable found, but value is zero.
|
||||
memory_->SetData64(0xc800, 0);
|
||||
WriteDescriptor64(0xc800, 0);
|
||||
|
||||
memory_->SetData64(0xf800, 0x200000);
|
||||
WriteDescriptor64(0xf800, 0x200000);
|
||||
WriteEntry64(0x200000, 0, 0, 0x300000);
|
||||
WriteDex(0x300000);
|
||||
|
||||
|
@ -302,7 +314,7 @@ TEST_F(DexFilesTest, get_method_information_global_skip_zero_64) {
|
|||
dex_files_->SetArch(ARCH_ARM64);
|
||||
method_name = "fail";
|
||||
method_offset = 0x123;
|
||||
memory_->SetData32(0xc800, 0x100000);
|
||||
WriteDescriptor64(0xc800, 0x100000);
|
||||
dex_files_->GetMethodInformation(maps_.get(), info, 0x300100, &method_name, &method_offset);
|
||||
EXPECT_EQ("fail", method_name);
|
||||
EXPECT_EQ(0x123U, method_offset);
|
||||
|
|
Loading…
Reference in New Issue