Skip to content

Commit e1948bf

Browse files
cferris1000Gerrit Code Review
authored and
Gerrit Code Review
committed
Merge "Avoid re-mapping dex file that's in local memory."
2 parents 51abcc5 + 273d3f0 commit e1948bf

File tree

5 files changed

+70
-7
lines changed

5 files changed

+70
-7
lines changed

libunwindstack/DexFile.cpp

+22-2
Original file line numberDiff line numberDiff line change
@@ -50,14 +50,30 @@ static bool HasDexSupport() {
5050

5151
std::unique_ptr<DexFile> DexFile::Create(uint64_t dex_file_offset_in_memory, Memory* memory,
5252
MapInfo* info) {
53+
if (UNLIKELY(!HasDexSupport())) {
54+
return nullptr;
55+
}
56+
57+
size_t max_size = info->end - dex_file_offset_in_memory;
58+
if (memory->IsLocal()) {
59+
size_t size = max_size;
60+
61+
std::string err_msg;
62+
std::unique_ptr<art_api::dex::DexFile> art_dex_file = DexFile::OpenFromMemory(
63+
reinterpret_cast<void const*>(dex_file_offset_in_memory), &size, info->name, &err_msg);
64+
if (art_dex_file != nullptr && size <= max_size) {
65+
return std::unique_ptr<DexFile>(new DexFile(art_dex_file));
66+
}
67+
}
68+
5369
if (!info->name.empty()) {
5470
std::unique_ptr<DexFile> dex_file =
5571
DexFileFromFile::Create(dex_file_offset_in_memory - info->start + info->offset, info->name);
5672
if (dex_file) {
5773
return dex_file;
5874
}
5975
}
60-
return DexFileFromMemory::Create(dex_file_offset_in_memory, memory, info->name);
76+
return DexFileFromMemory::Create(dex_file_offset_in_memory, memory, info->name, max_size);
6177
}
6278

6379
bool DexFile::GetMethodInformation(uint64_t dex_offset, std::string* method_name,
@@ -94,7 +110,8 @@ std::unique_ptr<DexFileFromFile> DexFileFromFile::Create(uint64_t dex_file_offse
94110

95111
std::unique_ptr<DexFileFromMemory> DexFileFromMemory::Create(uint64_t dex_file_offset_in_memory,
96112
Memory* memory,
97-
const std::string& name) {
113+
const std::string& name,
114+
size_t max_size) {
98115
if (UNLIKELY(!HasDexSupport())) {
99116
return nullptr;
100117
}
@@ -105,6 +122,9 @@ std::unique_ptr<DexFileFromMemory> DexFileFromMemory::Create(uint64_t dex_file_o
105122
std::string error_msg;
106123
std::unique_ptr<art_api::dex::DexFile> art_dex_file =
107124
OpenFromMemory(backing_memory.data(), &size, name, &error_msg);
125+
if (size > max_size) {
126+
return nullptr;
127+
}
108128

109129
if (art_dex_file != nullptr) {
110130
return std::unique_ptr<DexFileFromMemory>(

libunwindstack/DexFile.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,8 @@ class DexFileFromFile : public DexFile {
5555
class DexFileFromMemory : public DexFile {
5656
public:
5757
static std::unique_ptr<DexFileFromMemory> Create(uint64_t dex_file_offset_in_memory,
58-
Memory* memory, const std::string& name);
58+
Memory* memory, const std::string& name,
59+
size_t max_size);
5960

6061
private:
6162
DexFileFromMemory(std::unique_ptr<art_api::dex::DexFile>& art_dex_file,

libunwindstack/MemoryLocal.h

+2
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ class MemoryLocal : public Memory {
2828
MemoryLocal() = default;
2929
virtual ~MemoryLocal() = default;
3030

31+
bool IsLocal() const override { return true; }
32+
3133
size_t Read(uint64_t addr, void* dst, size_t size) override;
3234
};
3335

libunwindstack/include/unwindstack/Memory.h

+2
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ class Memory {
4141

4242
virtual void Clear() {}
4343

44+
virtual bool IsLocal() const { return false; }
45+
4446
virtual size_t Read(uint64_t addr, void* dst, size_t size) = 0;
4547

4648
bool ReadFully(uint64_t addr, void* dst, size_t size);

libunwindstack/tests/DexFileTest.cpp

+42-4
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
#include <unordered_map>
2323

24+
#include <MemoryLocal.h>
2425
#include <android-base/file.h>
2526
#include <gtest/gtest.h>
2627
#include <unwindstack/MapInfo.h>
@@ -109,23 +110,23 @@ TEST(DexFileTest, from_memory_fail_too_small_for_header) {
109110

110111
memory.SetMemory(0x1000, kDexData, 10);
111112

112-
EXPECT_TRUE(DexFileFromMemory::Create(0x1000, &memory, "") == nullptr);
113+
EXPECT_TRUE(DexFileFromMemory::Create(0x1000, &memory, "", sizeof(kDexData)) == nullptr);
113114
}
114115

115116
TEST(DexFileTest, from_memory_fail_too_small_for_data) {
116117
MemoryFake memory;
117118

118119
memory.SetMemory(0x1000, kDexData, sizeof(kDexData) - 2);
119120

120-
EXPECT_TRUE(DexFileFromMemory::Create(0x1000, &memory, "") == nullptr);
121+
EXPECT_TRUE(DexFileFromMemory::Create(0x1000, &memory, "", sizeof(kDexData)) == nullptr);
121122
}
122123

123124
TEST(DexFileTest, from_memory_open) {
124125
MemoryFake memory;
125126

126127
memory.SetMemory(0x1000, kDexData, sizeof(kDexData));
127128

128-
EXPECT_TRUE(DexFileFromMemory::Create(0x1000, &memory, "") != nullptr);
129+
EXPECT_TRUE(DexFileFromMemory::Create(0x1000, &memory, "", sizeof(kDexData)) != nullptr);
129130
}
130131

131132
TEST(DexFileTest, from_memory_no_leak) {
@@ -136,7 +137,7 @@ TEST(DexFileTest, from_memory_no_leak) {
136137
size_t first_allocated_bytes = 0;
137138
size_t last_allocated_bytes = 0;
138139
for (size_t i = 0; i < kNumLeakLoops; i++) {
139-
EXPECT_TRUE(DexFileFromMemory::Create(0x1000, &memory, "") != nullptr);
140+
EXPECT_TRUE(DexFileFromMemory::Create(0x1000, &memory, "", sizeof(kDexData)) != nullptr);
140141
ASSERT_NO_FATAL_FAILURE(CheckForLeak(i, &first_allocated_bytes, &last_allocated_bytes));
141142
}
142143
}
@@ -213,6 +214,43 @@ TEST(DexFileTest, create_using_memory_file_is_malformed) {
213214
EXPECT_TRUE(dex_file == nullptr);
214215
}
215216

217+
TEST(DexFileTest, create_using_memory_size_too_small) {
218+
MemoryFake memory;
219+
memory.SetMemory(0x4000, kDexData, sizeof(kDexData));
220+
MapInfo info(nullptr, nullptr, 0x100, sizeof(kDexData) - 2, 0x200, 0x5, "/does/not/exist");
221+
EXPECT_TRUE(DexFile::Create(0x4000, &memory, &info) != nullptr);
222+
}
223+
224+
class MemoryLocalFake : public MemoryLocal {
225+
public:
226+
MemoryLocalFake(size_t memory_size) : backing_(memory_size) {}
227+
virtual ~MemoryLocalFake() = default;
228+
229+
void* Data() { return backing_.data(); }
230+
231+
private:
232+
std::vector<void*> backing_;
233+
};
234+
235+
TEST(DexFileTest, create_using_local_memory) {
236+
MemoryLocalFake memory(sizeof(kDexData));
237+
238+
memcpy(memory.Data(), kDexData, sizeof(kDexData));
239+
uint64_t start = reinterpret_cast<uint64_t>(memory.Data());
240+
MapInfo info(nullptr, nullptr, start, start + 0x1000, 0x200, 0x5, "/does/not/exist");
241+
EXPECT_TRUE(DexFile::Create(start, &memory, &info) != nullptr);
242+
}
243+
244+
TEST(DexFileTest, create_using_local_memory_size_too_small) {
245+
MemoryLocalFake memory(sizeof(kDexData));
246+
247+
memcpy(memory.Data(), kDexData, sizeof(kDexData));
248+
uint64_t start = reinterpret_cast<uint64_t>(memory.Data());
249+
MapInfo info(nullptr, nullptr, start, start + sizeof(kDexData) - 2, 0x200, 0x5,
250+
"/does/not/exist");
251+
EXPECT_TRUE(DexFile::Create(start, &memory, &info) == nullptr);
252+
}
253+
216254
TEST(DexFileTest, get_method) {
217255
MemoryFake memory;
218256
memory.SetMemory(0x4000, kDexData, sizeof(kDexData));

0 commit comments

Comments
 (0)