Merge "Fix which maps to search for globals."
This commit is contained in:
commit
7cffd15110
12 changed files with 214 additions and 97 deletions
|
|
@ -58,6 +58,7 @@ cc_library {
|
||||||
"Elf.cpp",
|
"Elf.cpp",
|
||||||
"ElfInterface.cpp",
|
"ElfInterface.cpp",
|
||||||
"ElfInterfaceArm.cpp",
|
"ElfInterfaceArm.cpp",
|
||||||
|
"Global.cpp",
|
||||||
"JitDebug.cpp",
|
"JitDebug.cpp",
|
||||||
"Log.cpp",
|
"Log.cpp",
|
||||||
"MapInfo.cpp",
|
"MapInfo.cpp",
|
||||||
|
|
|
||||||
|
|
@ -43,10 +43,10 @@ struct DEXFileEntry64 {
|
||||||
uint64_t dex_file;
|
uint64_t dex_file;
|
||||||
};
|
};
|
||||||
|
|
||||||
DexFiles::DexFiles(std::shared_ptr<Memory>& memory) : memory_(memory) {}
|
DexFiles::DexFiles(std::shared_ptr<Memory>& memory) : Global(memory) {}
|
||||||
|
|
||||||
DexFiles::DexFiles(std::shared_ptr<Memory>& memory, std::vector<std::string>& search_libs)
|
DexFiles::DexFiles(std::shared_ptr<Memory>& memory, std::vector<std::string>& search_libs)
|
||||||
: memory_(memory), search_libs_(search_libs) {}
|
: Global(memory, search_libs) {}
|
||||||
|
|
||||||
DexFiles::~DexFiles() {
|
DexFiles::~DexFiles() {
|
||||||
for (auto& entry : files_) {
|
for (auto& entry : files_) {
|
||||||
|
|
@ -117,6 +117,11 @@ bool DexFiles::ReadEntry64() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool DexFiles::ReadVariableData(uint64_t ptr_offset) {
|
||||||
|
entry_addr_ = (this->*read_entry_ptr_func_)(ptr_offset);
|
||||||
|
return entry_addr_ != 0;
|
||||||
|
}
|
||||||
|
|
||||||
void DexFiles::Init(Maps* maps) {
|
void DexFiles::Init(Maps* maps) {
|
||||||
if (initialized_) {
|
if (initialized_) {
|
||||||
return;
|
return;
|
||||||
|
|
@ -124,36 +129,7 @@ void DexFiles::Init(Maps* maps) {
|
||||||
initialized_ = true;
|
initialized_ = true;
|
||||||
entry_addr_ = 0;
|
entry_addr_ = 0;
|
||||||
|
|
||||||
const std::string dex_debug_name("__dex_debug_descriptor");
|
FindAndReadVariable(maps, "__dex_debug_descriptor");
|
||||||
for (MapInfo* info : *maps) {
|
|
||||||
if (!(info->flags & PROT_READ) || info->offset != 0) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!search_libs_.empty()) {
|
|
||||||
bool found = false;
|
|
||||||
const char* lib = basename(info->name.c_str());
|
|
||||||
for (const std::string& name : search_libs_) {
|
|
||||||
if (name == lib) {
|
|
||||||
found = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!found) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Elf* elf = info->GetElf(memory_, true);
|
|
||||||
uint64_t ptr;
|
|
||||||
// Find first non-empty list (libart might be loaded multiple times).
|
|
||||||
if (elf->GetGlobalVariable(dex_debug_name, &ptr) && ptr != 0) {
|
|
||||||
entry_addr_ = (this->*read_entry_ptr_func_)(ptr + info->start);
|
|
||||||
if (entry_addr_ != 0) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DexFile* DexFiles::GetDexFile(uint64_t dex_file_offset, MapInfo* info) {
|
DexFile* DexFiles::GetDexFile(uint64_t dex_file_offset, MapInfo* info) {
|
||||||
|
|
|
||||||
96
libunwindstack/Global.cpp
Normal file
96
libunwindstack/Global.cpp
Normal file
|
|
@ -0,0 +1,96 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2018 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include <unwindstack/Global.h>
|
||||||
|
#include <unwindstack/MapInfo.h>
|
||||||
|
#include <unwindstack/Maps.h>
|
||||||
|
#include <unwindstack/Memory.h>
|
||||||
|
|
||||||
|
namespace unwindstack {
|
||||||
|
|
||||||
|
Global::Global(std::shared_ptr<Memory>& memory) : memory_(memory) {}
|
||||||
|
Global::Global(std::shared_ptr<Memory>& memory, std::vector<std::string>& search_libs)
|
||||||
|
: memory_(memory), search_libs_(search_libs) {}
|
||||||
|
|
||||||
|
uint64_t Global::GetVariableOffset(MapInfo* info, const std::string& variable) {
|
||||||
|
if (!search_libs_.empty()) {
|
||||||
|
bool found = false;
|
||||||
|
const char* lib = basename(info->name.c_str());
|
||||||
|
for (const std::string& name : search_libs_) {
|
||||||
|
if (name == lib) {
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!found) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Elf* elf = info->GetElf(memory_, true);
|
||||||
|
uint64_t ptr;
|
||||||
|
// Find first non-empty list (libraries might be loaded multiple times).
|
||||||
|
if (elf->GetGlobalVariable(variable, &ptr) && ptr != 0) {
|
||||||
|
return ptr + info->start;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Global::FindAndReadVariable(Maps* maps, const char* var_str) {
|
||||||
|
std::string variable(var_str);
|
||||||
|
// When looking for global variables, do not arbitrarily search every
|
||||||
|
// readable map. Instead look for a specific pattern that must exist.
|
||||||
|
// The pattern should be a readable map, followed by a read-write
|
||||||
|
// map with a non-zero offset.
|
||||||
|
// For example:
|
||||||
|
// f0000-f1000 0 r-- /system/lib/libc.so
|
||||||
|
// f1000-f2000 1000 r-x /system/lib/libc.so
|
||||||
|
// f2000-f3000 2000 rw- /system/lib/libc.so
|
||||||
|
// This also works:
|
||||||
|
// f0000-f2000 0 r-- /system/lib/libc.so
|
||||||
|
// f2000-f3000 2000 rw- /system/lib/libc.so
|
||||||
|
MapInfo* map_start = nullptr;
|
||||||
|
for (MapInfo* info : *maps) {
|
||||||
|
if (map_start != nullptr) {
|
||||||
|
if (map_start->name == info->name) {
|
||||||
|
if (info->offset != 0 &&
|
||||||
|
(info->flags & (PROT_READ | PROT_WRITE)) == (PROT_READ | PROT_WRITE)) {
|
||||||
|
uint64_t ptr = GetVariableOffset(map_start, variable);
|
||||||
|
if (ptr != 0 && ReadVariableData(ptr)) {
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
// Failed to find the global variable, do not bother trying again.
|
||||||
|
map_start = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
map_start = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (map_start == nullptr && (info->flags & PROT_READ) && info->offset == 0 &&
|
||||||
|
!info->name.empty()) {
|
||||||
|
map_start = info;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace unwindstack
|
||||||
|
|
@ -69,10 +69,10 @@ struct JITDescriptor64 {
|
||||||
uint64_t first_entry;
|
uint64_t first_entry;
|
||||||
};
|
};
|
||||||
|
|
||||||
JitDebug::JitDebug(std::shared_ptr<Memory>& memory) : memory_(memory) {}
|
JitDebug::JitDebug(std::shared_ptr<Memory>& memory) : Global(memory) {}
|
||||||
|
|
||||||
JitDebug::JitDebug(std::shared_ptr<Memory>& memory, std::vector<std::string>& search_libs)
|
JitDebug::JitDebug(std::shared_ptr<Memory>& memory, std::vector<std::string>& search_libs)
|
||||||
: memory_(memory), search_libs_(search_libs) {}
|
: Global(memory, search_libs) {}
|
||||||
|
|
||||||
JitDebug::~JitDebug() {
|
JitDebug::~JitDebug() {
|
||||||
for (auto* elf : elf_list_) {
|
for (auto* elf : elf_list_) {
|
||||||
|
|
@ -165,6 +165,11 @@ void JitDebug::SetArch(ArchEnum arch) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool JitDebug::ReadVariableData(uint64_t ptr) {
|
||||||
|
entry_addr_ = (this->*read_descriptor_func_)(ptr);
|
||||||
|
return entry_addr_ != 0;
|
||||||
|
}
|
||||||
|
|
||||||
void JitDebug::Init(Maps* maps) {
|
void JitDebug::Init(Maps* maps) {
|
||||||
if (initialized_) {
|
if (initialized_) {
|
||||||
return;
|
return;
|
||||||
|
|
@ -172,36 +177,7 @@ void JitDebug::Init(Maps* maps) {
|
||||||
// Regardless of what happens below, consider the init finished.
|
// Regardless of what happens below, consider the init finished.
|
||||||
initialized_ = true;
|
initialized_ = true;
|
||||||
|
|
||||||
const std::string descriptor_name("__jit_debug_descriptor");
|
FindAndReadVariable(maps, "__jit_debug_descriptor");
|
||||||
for (MapInfo* info : *maps) {
|
|
||||||
if (!(info->flags & PROT_READ) || info->offset != 0) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!search_libs_.empty()) {
|
|
||||||
bool found = false;
|
|
||||||
const char* lib = basename(info->name.c_str());
|
|
||||||
for (std::string& name : search_libs_) {
|
|
||||||
if (strcmp(name.c_str(), lib) == 0) {
|
|
||||||
found = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!found) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Elf* elf = info->GetElf(memory_, true);
|
|
||||||
uint64_t descriptor_addr;
|
|
||||||
// Find first non-empty entry (libart might be loaded multiple times).
|
|
||||||
if (elf->GetGlobalVariable(descriptor_name, &descriptor_addr) && descriptor_addr != 0) {
|
|
||||||
entry_addr_ = (this->*read_descriptor_func_)(descriptor_addr + info->start);
|
|
||||||
if (entry_addr_ != 0) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Elf* JitDebug::GetElf(Maps* maps, uint64_t pc) {
|
Elf* JitDebug::GetElf(Maps* maps, uint64_t pc) {
|
||||||
|
|
|
||||||
|
|
@ -25,16 +25,18 @@
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include <unwindstack/Global.h>
|
||||||
|
#include <unwindstack/Memory.h>
|
||||||
|
|
||||||
namespace unwindstack {
|
namespace unwindstack {
|
||||||
|
|
||||||
// Forward declarations.
|
// Forward declarations.
|
||||||
class DexFile;
|
class DexFile;
|
||||||
class Maps;
|
class Maps;
|
||||||
struct MapInfo;
|
struct MapInfo;
|
||||||
class Memory;
|
|
||||||
enum ArchEnum : uint8_t;
|
enum ArchEnum : uint8_t;
|
||||||
|
|
||||||
class DexFiles {
|
class DexFiles : public Global {
|
||||||
public:
|
public:
|
||||||
explicit DexFiles(std::shared_ptr<Memory>& memory);
|
explicit DexFiles(std::shared_ptr<Memory>& memory);
|
||||||
DexFiles(std::shared_ptr<Memory>& memory, std::vector<std::string>& search_libs);
|
DexFiles(std::shared_ptr<Memory>& memory, std::vector<std::string>& search_libs);
|
||||||
|
|
@ -60,8 +62,7 @@ class DexFiles {
|
||||||
|
|
||||||
bool ReadEntry64();
|
bool ReadEntry64();
|
||||||
|
|
||||||
std::shared_ptr<Memory> memory_;
|
bool ReadVariableData(uint64_t ptr_offset) override;
|
||||||
std::vector<std::string> search_libs_;
|
|
||||||
|
|
||||||
std::mutex lock_;
|
std::mutex lock_;
|
||||||
bool initialized_ = false;
|
bool initialized_ = false;
|
||||||
|
|
|
||||||
54
libunwindstack/include/unwindstack/Global.h
Normal file
54
libunwindstack/include/unwindstack/Global.h
Normal file
|
|
@ -0,0 +1,54 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2018 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _LIBUNWINDSTACK_GLOBAL_H
|
||||||
|
#define _LIBUNWINDSTACK_GLOBAL_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <mutex>
|
||||||
|
#include <string>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include <unwindstack/Memory.h>
|
||||||
|
|
||||||
|
namespace unwindstack {
|
||||||
|
|
||||||
|
// Forward declarations.
|
||||||
|
class Maps;
|
||||||
|
struct MapInfo;
|
||||||
|
|
||||||
|
class Global {
|
||||||
|
public:
|
||||||
|
explicit Global(std::shared_ptr<Memory>& memory);
|
||||||
|
Global(std::shared_ptr<Memory>& memory, std::vector<std::string>& search_libs);
|
||||||
|
virtual ~Global() = default;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
uint64_t GetVariableOffset(MapInfo* info, const std::string& variable);
|
||||||
|
void FindAndReadVariable(Maps* maps, const char* variable);
|
||||||
|
|
||||||
|
virtual bool ReadVariableData(uint64_t offset) = 0;
|
||||||
|
|
||||||
|
std::shared_ptr<Memory> memory_;
|
||||||
|
std::vector<std::string> search_libs_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace unwindstack
|
||||||
|
|
||||||
|
#endif // _LIBUNWINDSTACK_GLOBAL_H
|
||||||
|
|
@ -24,15 +24,17 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include <unwindstack/Global.h>
|
||||||
|
#include <unwindstack/Memory.h>
|
||||||
|
|
||||||
namespace unwindstack {
|
namespace unwindstack {
|
||||||
|
|
||||||
// Forward declarations.
|
// Forward declarations.
|
||||||
class Elf;
|
class Elf;
|
||||||
class Maps;
|
class Maps;
|
||||||
class Memory;
|
|
||||||
enum ArchEnum : uint8_t;
|
enum ArchEnum : uint8_t;
|
||||||
|
|
||||||
class JitDebug {
|
class JitDebug : public Global {
|
||||||
public:
|
public:
|
||||||
explicit JitDebug(std::shared_ptr<Memory>& memory);
|
explicit JitDebug(std::shared_ptr<Memory>& memory);
|
||||||
JitDebug(std::shared_ptr<Memory>& memory, std::vector<std::string>& search_libs);
|
JitDebug(std::shared_ptr<Memory>& memory, std::vector<std::string>& search_libs);
|
||||||
|
|
@ -45,11 +47,9 @@ class JitDebug {
|
||||||
private:
|
private:
|
||||||
void Init(Maps* maps);
|
void Init(Maps* maps);
|
||||||
|
|
||||||
std::shared_ptr<Memory> memory_;
|
|
||||||
uint64_t entry_addr_ = 0;
|
uint64_t entry_addr_ = 0;
|
||||||
bool initialized_ = false;
|
bool initialized_ = false;
|
||||||
std::vector<Elf*> elf_list_;
|
std::vector<Elf*> elf_list_;
|
||||||
std::vector<std::string> search_libs_;
|
|
||||||
|
|
||||||
std::mutex lock_;
|
std::mutex lock_;
|
||||||
|
|
||||||
|
|
@ -62,6 +62,8 @@ class JitDebug {
|
||||||
uint64_t ReadEntry32Pack(uint64_t* start, uint64_t* size);
|
uint64_t ReadEntry32Pack(uint64_t* start, uint64_t* size);
|
||||||
uint64_t ReadEntry32Pad(uint64_t* start, uint64_t* size);
|
uint64_t ReadEntry32Pad(uint64_t* start, uint64_t* size);
|
||||||
uint64_t ReadEntry64(uint64_t* start, uint64_t* size);
|
uint64_t ReadEntry64(uint64_t* start, uint64_t* size);
|
||||||
|
|
||||||
|
bool ReadVariableData(uint64_t ptr_offset) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace unwindstack
|
} // namespace unwindstack
|
||||||
|
|
|
||||||
|
|
@ -44,15 +44,15 @@ class DexFilesTest : public ::testing::Test {
|
||||||
dex_files_->SetArch(ARCH_ARM);
|
dex_files_->SetArch(ARCH_ARM);
|
||||||
|
|
||||||
maps_.reset(
|
maps_.reset(
|
||||||
new BufferMaps("1000-4000 ---s 00000000 00:00 0\n"
|
new BufferMaps("1000-4000 ---s 00000000 00:00 0 /fake/elf\n"
|
||||||
"4000-6000 r--s 00000000 00:00 0\n"
|
"4000-6000 r--s 00000000 00:00 0 /fake/elf\n"
|
||||||
"6000-8000 -wxs 00000000 00:00 0\n"
|
"6000-8000 -wxs 00000000 00:00 0 /fake/elf\n"
|
||||||
"a000-c000 r--p 00000000 00:00 0\n"
|
"a000-c000 r--p 00000000 00:00 0 /fake/elf2\n"
|
||||||
"c000-f000 rw-p 00000000 00:00 0\n"
|
"c000-f000 rw-p 00001000 00:00 0 /fake/elf2\n"
|
||||||
"f000-11000 r--p 00000000 00:00 0\n"
|
"f000-11000 r--p 00000000 00:00 0 /fake/elf3\n"
|
||||||
"100000-110000 rw-p 0000000 00:00 0\n"
|
"100000-110000 rw-p 0001000 00:00 0 /fake/elf3\n"
|
||||||
"200000-210000 rw-p 0000000 00:00 0\n"
|
"200000-210000 rw-p 0002000 00:00 0 /fake/elf3\n"
|
||||||
"300000-400000 rw-p 0000000 00:00 0\n"));
|
"300000-400000 rw-p 0003000 00:00 0 /fake/elf3\n"));
|
||||||
ASSERT_TRUE(maps_->Parse());
|
ASSERT_TRUE(maps_->Parse());
|
||||||
|
|
||||||
// Global variable in a section that is not readable.
|
// Global variable in a section that is not readable.
|
||||||
|
|
@ -96,8 +96,9 @@ class DexFilesTest : public ::testing::Test {
|
||||||
void WriteDex(uint64_t dex_file);
|
void WriteDex(uint64_t dex_file);
|
||||||
|
|
||||||
static constexpr size_t kMapGlobalNonReadable = 2;
|
static constexpr size_t kMapGlobalNonReadable = 2;
|
||||||
static constexpr size_t kMapGlobalSetToZero = 4;
|
static constexpr size_t kMapGlobalSetToZero = 3;
|
||||||
static constexpr size_t kMapGlobal = 5;
|
static constexpr size_t kMapGlobal = 5;
|
||||||
|
static constexpr size_t kMapGlobalRw = 6;
|
||||||
static constexpr size_t kMapDexFileEntries = 7;
|
static constexpr size_t kMapDexFileEntries = 7;
|
||||||
static constexpr size_t kMapDexFiles = 8;
|
static constexpr size_t kMapDexFiles = 8;
|
||||||
|
|
||||||
|
|
@ -256,6 +257,9 @@ TEST_F(DexFilesTest, get_method_information_search_libs) {
|
||||||
map_info->name = "/system/lib/libart.so";
|
map_info->name = "/system/lib/libart.so";
|
||||||
dex_files_.reset(new DexFiles(process_memory_, libs));
|
dex_files_.reset(new DexFiles(process_memory_, libs));
|
||||||
dex_files_->SetArch(ARCH_ARM);
|
dex_files_->SetArch(ARCH_ARM);
|
||||||
|
// Set the rw map to the same name or this will not scan this entry.
|
||||||
|
map_info = maps_->Get(kMapGlobalRw);
|
||||||
|
map_info->name = "/system/lib/libart.so";
|
||||||
// Make sure that clearing out copy of the libs doesn't affect the
|
// Make sure that clearing out copy of the libs doesn't affect the
|
||||||
// DexFiles object.
|
// DexFiles object.
|
||||||
libs.clear();
|
libs.clear();
|
||||||
|
|
@ -271,7 +275,7 @@ TEST_F(DexFilesTest, get_method_information_global_skip_zero_32) {
|
||||||
MapInfo* info = maps_->Get(kMapDexFiles);
|
MapInfo* info = maps_->Get(kMapDexFiles);
|
||||||
|
|
||||||
// First global variable found, but value is zero.
|
// First global variable found, but value is zero.
|
||||||
WriteDescriptor32(0xc800, 0);
|
WriteDescriptor32(0xa800, 0);
|
||||||
|
|
||||||
WriteDescriptor32(0xf800, 0x200000);
|
WriteDescriptor32(0xf800, 0x200000);
|
||||||
WriteEntry32(0x200000, 0, 0, 0x300000);
|
WriteEntry32(0x200000, 0, 0, 0x300000);
|
||||||
|
|
@ -286,7 +290,7 @@ TEST_F(DexFilesTest, get_method_information_global_skip_zero_32) {
|
||||||
dex_files_->SetArch(ARCH_ARM);
|
dex_files_->SetArch(ARCH_ARM);
|
||||||
method_name = "fail";
|
method_name = "fail";
|
||||||
method_offset = 0x123;
|
method_offset = 0x123;
|
||||||
WriteDescriptor32(0xc800, 0x100000);
|
WriteDescriptor32(0xa800, 0x100000);
|
||||||
dex_files_->GetMethodInformation(maps_.get(), info, 0x300100, &method_name, &method_offset);
|
dex_files_->GetMethodInformation(maps_.get(), info, 0x300100, &method_name, &method_offset);
|
||||||
EXPECT_EQ("fail", method_name);
|
EXPECT_EQ("fail", method_name);
|
||||||
EXPECT_EQ(0x123U, method_offset);
|
EXPECT_EQ(0x123U, method_offset);
|
||||||
|
|
@ -298,7 +302,7 @@ TEST_F(DexFilesTest, get_method_information_global_skip_zero_64) {
|
||||||
MapInfo* info = maps_->Get(kMapDexFiles);
|
MapInfo* info = maps_->Get(kMapDexFiles);
|
||||||
|
|
||||||
// First global variable found, but value is zero.
|
// First global variable found, but value is zero.
|
||||||
WriteDescriptor64(0xc800, 0);
|
WriteDescriptor64(0xa800, 0);
|
||||||
|
|
||||||
WriteDescriptor64(0xf800, 0x200000);
|
WriteDescriptor64(0xf800, 0x200000);
|
||||||
WriteEntry64(0x200000, 0, 0, 0x300000);
|
WriteEntry64(0x200000, 0, 0, 0x300000);
|
||||||
|
|
@ -314,7 +318,7 @@ TEST_F(DexFilesTest, get_method_information_global_skip_zero_64) {
|
||||||
dex_files_->SetArch(ARCH_ARM64);
|
dex_files_->SetArch(ARCH_ARM64);
|
||||||
method_name = "fail";
|
method_name = "fail";
|
||||||
method_offset = 0x123;
|
method_offset = 0x123;
|
||||||
WriteDescriptor64(0xc800, 0x100000);
|
WriteDescriptor64(0xa800, 0x100000);
|
||||||
dex_files_->GetMethodInformation(maps_.get(), info, 0x300100, &method_name, &method_offset);
|
dex_files_->GetMethodInformation(maps_.get(), info, 0x300100, &method_name, &method_offset);
|
||||||
EXPECT_EQ("fail", method_name);
|
EXPECT_EQ("fail", method_name);
|
||||||
EXPECT_EQ(0x123U, method_offset);
|
EXPECT_EQ(0x123U, method_offset);
|
||||||
|
|
|
||||||
|
|
@ -43,15 +43,16 @@ class JitDebugTest : public ::testing::Test {
|
||||||
jit_debug_->SetArch(ARCH_ARM);
|
jit_debug_->SetArch(ARCH_ARM);
|
||||||
|
|
||||||
maps_.reset(
|
maps_.reset(
|
||||||
new BufferMaps("1000-4000 ---s 00000000 00:00 0\n"
|
new BufferMaps("1000-4000 ---s 00000000 00:00 0 /fake/elf1\n"
|
||||||
"4000-6000 r--s 00000000 00:00 0\n"
|
"4000-6000 r--s 00000000 00:00 0 /fake/elf1\n"
|
||||||
"6000-8000 -wxs 00000000 00:00 0\n"
|
"6000-8000 -wxs 00000000 00:00 0 /fake/elf1\n"
|
||||||
"a000-c000 --xp 00000000 00:00 0\n"
|
"a000-c000 --xp 00000000 00:00 0 /fake/elf2\n"
|
||||||
"c000-f000 rw-p 00000000 00:00 0\n"
|
"c000-f000 rw-p 00001000 00:00 0 /fake/elf2\n"
|
||||||
"f000-11000 r--p 00000000 00:00 0\n"
|
"f000-11000 r--p 00000000 00:00 0 /fake/elf3\n"
|
||||||
"12000-14000 r--p 00000000 00:00 0\n"
|
"11000-12000 rw-p 00001000 00:00 0 /fake/elf3\n"
|
||||||
"100000-110000 rw-p 0000000 00:00 0\n"
|
"12000-14000 r--p 00000000 00:00 0 /fake/elf4\n"
|
||||||
"200000-210000 rw-p 0000000 00:00 0\n"));
|
"100000-110000 rw-p 0001000 00:00 0 /fake/elf4\n"
|
||||||
|
"200000-210000 rw-p 0002000 00:00 0 /fake/elf4\n"));
|
||||||
ASSERT_TRUE(maps_->Parse());
|
ASSERT_TRUE(maps_->Parse());
|
||||||
|
|
||||||
MapInfo* map_info = maps_->Get(3);
|
MapInfo* map_info = maps_->Get(3);
|
||||||
|
|
@ -74,7 +75,7 @@ class JitDebugTest : public ::testing::Test {
|
||||||
interface->FakeSetGlobalVariable("__jit_debug_descriptor", 0x800);
|
interface->FakeSetGlobalVariable("__jit_debug_descriptor", 0x800);
|
||||||
map_info->elf.reset(elf);
|
map_info->elf.reset(elf);
|
||||||
|
|
||||||
map_info = maps_->Get(6);
|
map_info = maps_->Get(7);
|
||||||
ASSERT_TRUE(map_info != nullptr);
|
ASSERT_TRUE(map_info != nullptr);
|
||||||
memory = new MemoryFake;
|
memory = new MemoryFake;
|
||||||
elf = new ElfFake(memory);
|
elf = new ElfFake(memory);
|
||||||
|
|
@ -397,6 +398,8 @@ TEST_F(JitDebugTest, get_elf_search_libs) {
|
||||||
// Change the name of the map that includes the value and verify this works.
|
// Change the name of the map that includes the value and verify this works.
|
||||||
MapInfo* map_info = maps_->Get(5);
|
MapInfo* map_info = maps_->Get(5);
|
||||||
map_info->name = "/system/lib/libart.so";
|
map_info->name = "/system/lib/libart.so";
|
||||||
|
map_info = maps_->Get(6);
|
||||||
|
map_info->name = "/system/lib/libart.so";
|
||||||
jit_debug_.reset(new JitDebug(process_memory_, libs));
|
jit_debug_.reset(new JitDebug(process_memory_, libs));
|
||||||
// Make sure that clearing our copy of the libs doesn't affect the
|
// Make sure that clearing our copy of the libs doesn't affect the
|
||||||
// JitDebug object.
|
// JitDebug object.
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
d0250000-d2600000 r-xp 0 00:00 0 <anonymous:d0250000>
|
d0250000-d2600000 r-xp 0 00:00 0 <anonymous:d0250000>
|
||||||
e466e000-e4ae8000 r-xp 0 00:00 0 libart.so
|
e466e000-e4ae8000 r-xp 0 00:00 0 libart.so
|
||||||
|
e4ae8000-e4ae9000 rw-p 1000 00:00 0 libart.so
|
||||||
e7d91000-e7e31000 r-xp 0 00:00 0 libc.so
|
e7d91000-e7e31000 r-xp 0 00:00 0 libc.so
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,9 @@ ab0d3000-ab0d8000 r-xp 0 00:00 0 dalvikvm32
|
||||||
dfe4e000-dfe7b000 r-xp 0 00:00 0 libarttestd.so
|
dfe4e000-dfe7b000 r-xp 0 00:00 0 libarttestd.so
|
||||||
e0447000-e0448000 r-xp 2000 00:00 0 137-cfi.odex
|
e0447000-e0448000 r-xp 2000 00:00 0 137-cfi.odex
|
||||||
e2796000-e4796000 r-xp 0 00:00 0 anonymous:e2796000
|
e2796000-e4796000 r-xp 0 00:00 0 anonymous:e2796000
|
||||||
e648e000-e690f000 r-xp 00000000 00:00 0 libart.so
|
e648e000-e690f000 r-xp 0 00:00 0 libart.so
|
||||||
|
e690f000-e6910000 rw-p 1000 00:00 0 libart.so
|
||||||
ed306000-ed801000 r-xp 0 00:00 0 libartd.so
|
ed306000-ed801000 r-xp 0 00:00 0 libartd.so
|
||||||
|
ed801000-ed802000 rw-p 1000 00:00 0 libartd.so
|
||||||
eda88000-edb23000 r-xp 0 00:00 0 libc.so
|
eda88000-edb23000 r-xp 0 00:00 0 libc.so
|
||||||
ede4e000-ede50000 r-xp 0 00:00 0 anonymous:ede4e000
|
ede4e000-ede50000 r-xp 0 00:00 0 anonymous:ede4e000
|
||||||
|
|
|
||||||
|
|
@ -3,4 +3,5 @@ eb833000-eb8cc000 r-xp 0 00:00 0 libarttestd.so
|
||||||
ec606000-ec607000 r-xp 2000 00:00 0 137-cfi.odex
|
ec606000-ec607000 r-xp 2000 00:00 0 137-cfi.odex
|
||||||
ee74c000-f074c000 r-xp 0 00:00 0 anonymous:ee74c000
|
ee74c000-f074c000 r-xp 0 00:00 0 anonymous:ee74c000
|
||||||
f6be1000-f732b000 r-xp 0 00:00 0 libartd.so
|
f6be1000-f732b000 r-xp 0 00:00 0 libartd.so
|
||||||
|
f732b000-f732c000 rw-p 1000 00:00 0 libartd.so
|
||||||
f734b000-f74fc000 r-xp 0 00:00 0 libc.so
|
f734b000-f74fc000 r-xp 0 00:00 0 libc.so
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue