summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Srbecky <dsrbecky@google.com>2021-03-24 13:31:11 +0000
committerGerrit Code Review <noreply-gerritcodereview@google.com>2021-03-24 13:31:11 +0000
commit0f3e4f8b7598269ce67ad80265aa0f4b41b0739f (patch)
treec3976b1ebeaf3b2adfebae4442fa8532e759f493
parentfcdc5f2c4084890c2ca48d981f74c6ff7bac4889 (diff)
parentc966e544b744dbb6154fac87a6602f0ccb91eac2 (diff)
downloadunwinding-0f3e4f8b7598269ce67ad80265aa0f4b41b0739f.tar.gz
Merge "Simplify DexFile implementation."
-rw-r--r--libunwindstack/DexFile.cpp129
-rw-r--r--libunwindstack/DexFile.h58
-rw-r--r--libunwindstack/DexFiles.cpp4
-rw-r--r--libunwindstack/Memory.cpp5
-rw-r--r--libunwindstack/MemoryFileAtOffset.h2
-rw-r--r--libunwindstack/MemoryLocal.h2
-rw-r--r--libunwindstack/include/unwindstack/Memory.h6
-rw-r--r--libunwindstack/tests/DexFileTest.cpp132
-rw-r--r--libunwindstack/tests/DexFilesTest.cpp38
9 files changed, 108 insertions, 268 deletions
diff --git a/libunwindstack/DexFile.cpp b/libunwindstack/DexFile.cpp
index e1007c7..4cb2c93 100644
--- a/libunwindstack/DexFile.cpp
+++ b/libunwindstack/DexFile.cpp
@@ -32,6 +32,7 @@
#include <unwindstack/Memory.h>
#include "DexFile.h"
+#include "MemoryBuffer.h"
namespace unwindstack {
@@ -43,42 +44,47 @@ static bool CheckDexSupport() {
return true;
}
-static bool HasDexSupport() {
- static bool has_dex_support = CheckDexSupport();
- return has_dex_support;
-}
-
-bool DexFile::IsValidPc(uint64_t dex_pc) {
- return base_addr_ <= dex_pc && dex_pc < base_addr_ + size_;
-}
-
-std::unique_ptr<DexFile> DexFile::Create(uint64_t dex_file_offset_in_memory, Memory* memory,
+std::unique_ptr<DexFile> DexFile::Create(uint64_t base_addr, uint64_t file_size, Memory* memory,
MapInfo* info) {
- if (UNLIKELY(!HasDexSupport() || info == nullptr)) {
+ static bool has_dex_support = CheckDexSupport();
+ if (!has_dex_support || file_size == 0) {
return nullptr;
}
- size_t max_size = info->end - dex_file_offset_in_memory;
- if (memory->IsLocal()) {
- size_t size = max_size;
-
- std::string err_msg;
- std::unique_ptr<art_api::dex::DexFile> art_dex_file = DexFile::OpenFromMemory(
- reinterpret_cast<void const*>(dex_file_offset_in_memory), &size, info->name, &err_msg);
- if (art_dex_file != nullptr && size <= max_size) {
- return std::unique_ptr<DexFile>(new DexFile(dex_file_offset_in_memory, size, art_dex_file));
+ // Try to map the file directly from disk.
+ std::unique_ptr<Memory> dex_memory;
+ if (info != nullptr && !info->name.empty()) {
+ if (info->start <= base_addr && base_addr < info->end) {
+ uint64_t offset_in_file = (base_addr - info->start) + info->offset;
+ if (file_size <= info->end - base_addr) {
+ dex_memory = Memory::CreateFileMemory(info->name, offset_in_file, file_size);
+ // On error, the results is null and we fall through to the fallback code-path.
+ }
}
}
- if (!info->name.empty()) {
- std::unique_ptr<DexFile> dex_file =
- DexFileFromFile::Create(dex_file_offset_in_memory,
- dex_file_offset_in_memory - info->start + info->offset, info->name);
- if (dex_file) {
- return dex_file;
+ // Fallback: make copy in local buffer.
+ if (dex_memory.get() == nullptr) {
+ std::unique_ptr<MemoryBuffer> copy(new MemoryBuffer);
+ if (!copy->Resize(file_size)) {
+ return nullptr;
+ }
+ if (!memory->ReadFully(base_addr, copy->GetPtr(0), file_size)) {
+ return nullptr;
}
+ dex_memory = std::move(copy);
}
- return DexFileFromMemory::Create(dex_file_offset_in_memory, memory, info->name, max_size);
+
+ std::string err_msg;
+ size_t actual_size = file_size;
+ const char* location = info != nullptr ? info->name.c_str() : "";
+ std::unique_ptr<art_api::dex::DexFile> dex =
+ art_api::dex::DexFile::OpenFromMemory(dex_memory->GetPtr(), &actual_size, location, &err_msg);
+ if (dex != nullptr) {
+ return std::unique_ptr<DexFile>(
+ new DexFile(std::move(dex_memory), base_addr, file_size, std::move(dex)));
+ }
+ return nullptr;
}
bool DexFile::GetFunctionName(uint64_t dex_pc, SharedString* method_name, uint64_t* method_offset) {
@@ -94,7 +100,7 @@ bool DexFile::GetFunctionName(uint64_t dex_pc, SharedString* method_name, uint64
}
// Lookup the function in the underlying dex file.
- art_api::dex::MethodInfo method_info = GetMethodInfoForOffset(dex_offset, false);
+ art_api::dex::MethodInfo method_info = dex_->GetMethodInfoForOffset(dex_offset, false);
if (method_info.offset == 0) {
return false;
}
@@ -112,71 +118,4 @@ bool DexFile::GetFunctionName(uint64_t dex_pc, SharedString* method_name, uint64
return true;
}
-std::unique_ptr<DexFileFromFile> DexFileFromFile::Create(uint64_t base_addr,
- uint64_t dex_file_offset_in_file,
- const std::string& file) {
- if (UNLIKELY(!HasDexSupport())) {
- return nullptr;
- }
-
- android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(file.c_str(), O_RDONLY | O_CLOEXEC)));
- if (fd == -1) {
- return nullptr;
- }
- struct stat buf;
- if (fstat(fd, &buf) == -1) {
- return nullptr;
- }
- uint64_t end = static_cast<uint64_t>(buf.st_size);
- if (dex_file_offset_in_file >= end) {
- return nullptr;
- }
- uint64_t size = end - dex_file_offset_in_file;
-
- std::string error_msg;
- std::unique_ptr<art_api::dex::DexFile> art_dex_file =
- OpenFromFd(fd, dex_file_offset_in_file, file, &error_msg);
- if (art_dex_file == nullptr) {
- return nullptr;
- }
-
- return std::unique_ptr<DexFileFromFile>(new DexFileFromFile(base_addr, size, art_dex_file));
-}
-
-std::unique_ptr<DexFileFromMemory> DexFileFromMemory::Create(uint64_t dex_file_offset_in_memory,
- Memory* memory,
- const std::string& name,
- size_t max_size) {
- if (UNLIKELY(!HasDexSupport())) {
- return nullptr;
- }
-
- std::vector<uint8_t> backing_memory;
-
- for (size_t size = 0;;) {
- const size_t old_size = size; // The call below may increase the size.
- std::string error_msg;
- std::unique_ptr<art_api::dex::DexFile> art_dex_file =
- OpenFromMemory(backing_memory.data(), &size, name, &error_msg);
- if (size > max_size) {
- return nullptr;
- }
- if (size > old_size) {
- // Read more memory and retry.
- backing_memory.resize(size);
- if (!memory->ReadFully(dex_file_offset_in_memory, backing_memory.data(),
- backing_memory.size())) {
- return nullptr;
- }
- continue;
- }
-
- if (art_dex_file != nullptr) {
- return std::unique_ptr<DexFileFromMemory>(new DexFileFromMemory(
- dex_file_offset_in_memory, size, art_dex_file, std::move(backing_memory)));
- }
- return nullptr;
- }
-}
-
} // namespace unwindstack
diff --git a/libunwindstack/DexFile.h b/libunwindstack/DexFile.h
index 59ad2f6..a80ea94 100644
--- a/libunwindstack/DexFile.h
+++ b/libunwindstack/DexFile.h
@@ -31,57 +31,39 @@
namespace unwindstack {
-class DexFile : protected art_api::dex::DexFile {
+struct MapInfo;
+class Memory;
+
+class DexFile {
struct Info {
uint32_t offset; // Symbol start offset (relative to start of dex file).
SharedString name;
};
public:
- virtual ~DexFile() = default;
-
- bool IsValidPc(uint64_t dex_pc);
+ bool IsValidPc(uint64_t dex_pc) {
+ return base_addr_ <= dex_pc && (dex_pc - base_addr_) < file_size_;
+ }
bool GetFunctionName(uint64_t dex_pc, SharedString* method_name, uint64_t* method_offset);
- static std::unique_ptr<DexFile> Create(uint64_t dex_file_offset_in_memory, Memory* memory,
+ static std::unique_ptr<DexFile> Create(uint64_t base_addr, uint64_t file_size, Memory* memory,
MapInfo* info);
- protected:
- DexFile(uint64_t base_addr, uint64_t size, std::unique_ptr<art_api::dex::DexFile>& art_dex_file)
- : art_api::dex::DexFile(art_dex_file), base_addr_(base_addr), size_(size) {}
-
- uint64_t base_addr_ = 0; // Absolute address where this DEX file is in memory.
- uint64_t size_ = 0; // Size of the dex file.
-
- std::map<uint32_t, Info> symbols_; // Cache of read symbols (keyed by *end* offset).
-};
-
-class DexFileFromFile : public DexFile {
- public:
- static std::unique_ptr<DexFileFromFile> Create(uint64_t base_addr,
- uint64_t dex_file_offset_in_file,
- const std::string& file);
-
private:
- DexFileFromFile(uint64_t base_addr, uint64_t size,
- std::unique_ptr<art_api::dex::DexFile>& art_dex_file)
- : DexFile(base_addr, size, art_dex_file) {}
-};
-
-class DexFileFromMemory : public DexFile {
- public:
- static std::unique_ptr<DexFileFromMemory> Create(uint64_t dex_file_offset_in_memory,
- Memory* memory, const std::string& name,
- size_t max_size);
+ DexFile(std::unique_ptr<Memory>&& memory, uint64_t base_addr, uint64_t file_size,
+ std::unique_ptr<art_api::dex::DexFile>&& dex)
+ : memory_(std::move(memory)),
+ base_addr_(base_addr),
+ file_size_(file_size),
+ dex_(std::move(dex)) {}
+
+ std::unique_ptr<Memory> memory_; // Memory range containing the dex file.
+ uint64_t base_addr_ = 0; // Absolute address where this DEX file is in memory.
+ uint64_t file_size_ = 0; // Total number of bytes in the dex file.
+ std::unique_ptr<art_api::dex::DexFile> dex_; // Loaded underling dex object.
- private:
- DexFileFromMemory(uint64_t base_addr, uint64_t size,
- std::unique_ptr<art_api::dex::DexFile>& art_dex_file,
- std::vector<uint8_t>&& memory)
- : DexFile(base_addr, size, art_dex_file), memory_(std::move(memory)) {}
-
- std::vector<uint8_t> memory_;
+ std::map<uint32_t, Info> symbols_; // Cache of read symbols (keyed by *end* offset).
};
} // namespace unwindstack
diff --git a/libunwindstack/DexFiles.cpp b/libunwindstack/DexFiles.cpp
index 3507cc7..2a3912b 100644
--- a/libunwindstack/DexFiles.cpp
+++ b/libunwindstack/DexFiles.cpp
@@ -28,8 +28,8 @@ namespace unwindstack {
template <>
bool GlobalDebugInterface<DexFile>::Load(Maps* maps, std::shared_ptr<Memory>& memory, uint64_t addr,
- uint64_t, /*out*/ std::unique_ptr<DexFile>& dex) {
- dex = DexFile::Create(addr, memory.get(), maps->Find(addr));
+ uint64_t size, /*out*/ std::unique_ptr<DexFile>& dex) {
+ dex = DexFile::Create(addr, size, memory.get(), maps->Find(addr));
return dex.get() != nullptr;
}
diff --git a/libunwindstack/Memory.cpp b/libunwindstack/Memory.cpp
index 36a9bb5..ca4aac4 100644
--- a/libunwindstack/Memory.cpp
+++ b/libunwindstack/Memory.cpp
@@ -187,10 +187,11 @@ bool Memory::ReadString(uint64_t addr, std::string* dst, size_t max_read) {
return false;
}
-std::unique_ptr<Memory> Memory::CreateFileMemory(const std::string& path, uint64_t offset) {
+std::unique_ptr<Memory> Memory::CreateFileMemory(const std::string& path, uint64_t offset,
+ uint64_t size) {
auto memory = std::make_unique<MemoryFileAtOffset>();
- if (memory->Init(path, offset)) {
+ if (memory->Init(path, offset, size)) {
return memory;
}
diff --git a/libunwindstack/MemoryFileAtOffset.h b/libunwindstack/MemoryFileAtOffset.h
index d136eb4..9949f26 100644
--- a/libunwindstack/MemoryFileAtOffset.h
+++ b/libunwindstack/MemoryFileAtOffset.h
@@ -30,6 +30,8 @@ class MemoryFileAtOffset : public Memory {
bool Init(const std::string& file, uint64_t offset, uint64_t size = UINT64_MAX);
+ uint8_t* GetPtr(size_t addr = 0) override { return addr < size_ ? data_ + addr : nullptr; }
+
size_t Read(uint64_t addr, void* dst, size_t size) override;
size_t Size() { return size_; }
diff --git a/libunwindstack/MemoryLocal.h b/libunwindstack/MemoryLocal.h
index 741f107..a5c7a48 100644
--- a/libunwindstack/MemoryLocal.h
+++ b/libunwindstack/MemoryLocal.h
@@ -28,8 +28,6 @@ class MemoryLocal : public Memory {
MemoryLocal() = default;
virtual ~MemoryLocal() = default;
- bool IsLocal() const override { return true; }
-
size_t Read(uint64_t addr, void* dst, size_t size) override;
long ReadTag(uint64_t addr) override;
};
diff --git a/libunwindstack/include/unwindstack/Memory.h b/libunwindstack/include/unwindstack/Memory.h
index 3d81878..4b33ddb 100644
--- a/libunwindstack/include/unwindstack/Memory.h
+++ b/libunwindstack/include/unwindstack/Memory.h
@@ -35,13 +35,15 @@ class Memory {
static std::shared_ptr<Memory> CreateProcessMemoryCached(pid_t pid);
static std::shared_ptr<Memory> CreateOfflineMemory(const uint8_t* data, uint64_t start,
uint64_t end);
- static std::unique_ptr<Memory> CreateFileMemory(const std::string& path, uint64_t offset);
+ static std::unique_ptr<Memory> CreateFileMemory(const std::string& path, uint64_t offset,
+ uint64_t size = UINT64_MAX);
virtual bool ReadString(uint64_t addr, std::string* dst, size_t max_read);
virtual void Clear() {}
- virtual bool IsLocal() const { return false; }
+ // Get pointer to directly access the data for buffers that support it.
+ virtual uint8_t* GetPtr(size_t /*addr*/ = 0) { return nullptr; }
virtual size_t Read(uint64_t addr, void* dst, size_t size) = 0;
virtual long ReadTag(uint64_t) { return -1; }
diff --git a/libunwindstack/tests/DexFileTest.cpp b/libunwindstack/tests/DexFileTest.cpp
index 6919c65..1dc0db2 100644
--- a/libunwindstack/tests/DexFileTest.cpp
+++ b/libunwindstack/tests/DexFileTest.cpp
@@ -33,47 +33,6 @@
namespace unwindstack {
-TEST(DexFileTest, from_file_open_non_exist) {
- EXPECT_TRUE(DexFileFromFile::Create(0, 0, "/file/does/not/exist") == nullptr);
-}
-
-TEST(DexFileTest, from_file_open_too_small) {
- TemporaryFile tf;
- ASSERT_TRUE(tf.fd != -1);
-
- ASSERT_EQ(size_t{10}, static_cast<size_t>(TEMP_FAILURE_RETRY(write(tf.fd, kDexData, 10))));
-
- // Header too small.
- EXPECT_TRUE(DexFileFromFile::Create(0, 0, tf.path) == nullptr);
-
- // Header correct, file too small.
- ASSERT_EQ(0, lseek(tf.fd, 0, SEEK_SET));
- ASSERT_EQ(sizeof(kDexData) - 1,
- static_cast<size_t>(TEMP_FAILURE_RETRY(write(tf.fd, kDexData, sizeof(kDexData) - 1))));
- EXPECT_TRUE(DexFileFromFile::Create(0, 0, tf.path) == nullptr);
-}
-
-TEST(DexFileTest, from_file_open) {
- TemporaryFile tf;
- ASSERT_TRUE(tf.fd != -1);
-
- ASSERT_EQ(sizeof(kDexData),
- static_cast<size_t>(TEMP_FAILURE_RETRY(write(tf.fd, kDexData, sizeof(kDexData)))));
-
- EXPECT_TRUE(DexFileFromFile::Create(0, 0, tf.path) != nullptr);
-}
-
-TEST(DexFileTest, from_file_open_non_zero_offset) {
- TemporaryFile tf;
- ASSERT_TRUE(tf.fd != -1);
-
- ASSERT_EQ(0x100, lseek(tf.fd, 0x100, SEEK_SET));
- ASSERT_EQ(sizeof(kDexData),
- static_cast<size_t>(TEMP_FAILURE_RETRY(write(tf.fd, kDexData, sizeof(kDexData)))));
-
- EXPECT_TRUE(DexFileFromFile::Create(0, 0x100, tf.path) != nullptr);
-}
-
static constexpr size_t kNumLeakLoops = 5000;
static constexpr size_t kMaxAllowedLeakBytes = 1024;
@@ -100,35 +59,13 @@ TEST(DexFileTest, from_file_no_leak) {
size_t first_allocated_bytes = 0;
size_t last_allocated_bytes = 0;
for (size_t i = 0; i < kNumLeakLoops; i++) {
- EXPECT_TRUE(DexFileFromFile::Create(0, 0, tf.path) != nullptr);
+ MemoryFake memory;
+ MapInfo info(nullptr, nullptr, 0, 0x10000, 0, 0x5, tf.path);
+ EXPECT_TRUE(DexFile::Create(0, sizeof(kDexData), &memory, &info) != nullptr);
ASSERT_NO_FATAL_FAILURE(CheckForLeak(i, &first_allocated_bytes, &last_allocated_bytes));
}
}
-TEST(DexFileTest, from_memory_fail_too_small_for_header) {
- MemoryFake memory;
-
- memory.SetMemory(0x1000, kDexData, 10);
-
- EXPECT_TRUE(DexFileFromMemory::Create(0x1000, &memory, "", sizeof(kDexData)) == nullptr);
-}
-
-TEST(DexFileTest, from_memory_fail_too_small_for_data) {
- MemoryFake memory;
-
- memory.SetMemory(0x1000, kDexData, sizeof(kDexData) - 2);
-
- EXPECT_TRUE(DexFileFromMemory::Create(0x1000, &memory, "", sizeof(kDexData)) == nullptr);
-}
-
-TEST(DexFileTest, from_memory_open) {
- MemoryFake memory;
-
- memory.SetMemory(0x1000, kDexData, sizeof(kDexData));
-
- EXPECT_TRUE(DexFileFromMemory::Create(0x1000, &memory, "", sizeof(kDexData)) != nullptr);
-}
-
TEST(DexFileTest, from_memory_no_leak) {
MemoryFake memory;
@@ -137,7 +74,7 @@ TEST(DexFileTest, from_memory_no_leak) {
size_t first_allocated_bytes = 0;
size_t last_allocated_bytes = 0;
for (size_t i = 0; i < kNumLeakLoops; i++) {
- EXPECT_TRUE(DexFileFromMemory::Create(0x1000, &memory, "", sizeof(kDexData)) != nullptr);
+ EXPECT_TRUE(DexFile::Create(0x1000, sizeof(kDexData), &memory, nullptr) != nullptr);
ASSERT_NO_FATAL_FAILURE(CheckForLeak(i, &first_allocated_bytes, &last_allocated_bytes));
}
}
@@ -152,7 +89,7 @@ TEST(DexFileTest, create_using_file) {
MemoryFake memory;
MapInfo info(nullptr, nullptr, 0, 0x10000, 0, 0x5, tf.path);
- EXPECT_TRUE(DexFile::Create(0x500, &memory, &info) != nullptr);
+ EXPECT_TRUE(DexFile::Create(0x500, sizeof(kDexData), &memory, &info) != nullptr);
}
TEST(DexFileTest, create_using_file_non_zero_start) {
@@ -165,7 +102,7 @@ TEST(DexFileTest, create_using_file_non_zero_start) {
MemoryFake memory;
MapInfo info(nullptr, nullptr, 0x100, 0x10000, 0, 0x5, tf.path);
- EXPECT_TRUE(DexFile::Create(0x600, &memory, &info) != nullptr);
+ EXPECT_TRUE(DexFile::Create(0x600, sizeof(kDexData), &memory, &info) != nullptr);
}
TEST(DexFileTest, create_using_file_non_zero_offset) {
@@ -178,21 +115,21 @@ TEST(DexFileTest, create_using_file_non_zero_offset) {
MemoryFake memory;
MapInfo info(nullptr, nullptr, 0x100, 0x10000, 0x200, 0x5, tf.path);
- EXPECT_TRUE(DexFile::Create(0x400, &memory, &info) != nullptr);
+ EXPECT_TRUE(DexFile::Create(0x400, sizeof(kDexData), &memory, &info) != nullptr);
}
TEST(DexFileTest, create_using_memory_empty_file) {
MemoryFake memory;
memory.SetMemory(0x4000, kDexData, sizeof(kDexData));
MapInfo info(nullptr, nullptr, 0x100, 0x10000, 0x200, 0x5, "");
- EXPECT_TRUE(DexFile::Create(0x4000, &memory, &info) != nullptr);
+ EXPECT_TRUE(DexFile::Create(0x4000, sizeof(kDexData), &memory, &info) != nullptr);
}
TEST(DexFileTest, create_using_memory_file_does_not_exist) {
MemoryFake memory;
memory.SetMemory(0x4000, kDexData, sizeof(kDexData));
MapInfo info(nullptr, nullptr, 0x100, 0x10000, 0x200, 0x5, "/does/not/exist");
- EXPECT_TRUE(DexFile::Create(0x4000, &memory, &info) != nullptr);
+ EXPECT_TRUE(DexFile::Create(0x4000, sizeof(kDexData), &memory, &info) != nullptr);
}
TEST(DexFileTest, create_using_memory_file_is_malformed) {
@@ -205,57 +142,34 @@ TEST(DexFileTest, create_using_memory_file_is_malformed) {
MemoryFake memory;
memory.SetMemory(0x4000, kDexData, sizeof(kDexData));
MapInfo info(nullptr, nullptr, 0x4000, 0x10000, 0x200, 0x5, "/does/not/exist");
- std::unique_ptr<DexFile> dex_file = DexFile::Create(0x4000, &memory, &info);
+ std::unique_ptr<DexFile> dex_file = DexFile::Create(0x4000, sizeof(kDexData), &memory, &info);
ASSERT_TRUE(dex_file != nullptr);
// Check it came from memory by clearing memory and verifying it fails.
memory.Clear();
- dex_file = DexFile::Create(0x4000, &memory, &info);
+ dex_file = DexFile::Create(0x4000, sizeof(kDexData), &memory, &info);
EXPECT_TRUE(dex_file == nullptr);
}
-TEST(DexFileTest, create_using_memory_size_too_small) {
+TEST(DexFileTest, create_using_memory_header_too_small) {
MemoryFake memory;
- memory.SetMemory(0x4000, kDexData, sizeof(kDexData));
- MapInfo info(nullptr, nullptr, 0x100, sizeof(kDexData) - 2, 0x200, 0x5, "/does/not/exist");
- EXPECT_TRUE(DexFile::Create(0x4000, &memory, &info) != nullptr);
+ size_t size = 10;
+ memory.SetMemory(0x4000, kDexData, size);
+ EXPECT_TRUE(DexFile::Create(0x4000, size, &memory, nullptr) == nullptr);
}
-class MemoryLocalFake : public MemoryLocal {
- public:
- MemoryLocalFake(size_t memory_size) : backing_(memory_size) {}
- virtual ~MemoryLocalFake() = default;
-
- void* Data() { return backing_.data(); }
-
- private:
- std::vector<void*> backing_;
-};
-
-TEST(DexFileTest, create_using_local_memory) {
- MemoryLocalFake memory(sizeof(kDexData));
-
- memcpy(memory.Data(), kDexData, sizeof(kDexData));
- uint64_t start = reinterpret_cast<uint64_t>(memory.Data());
- MapInfo info(nullptr, nullptr, start, start + 0x1000, 0x200, 0x5, "/does/not/exist");
- EXPECT_TRUE(DexFile::Create(start, &memory, &info) != nullptr);
-}
-
-TEST(DexFileTest, create_using_local_memory_size_too_small) {
- MemoryLocalFake memory(sizeof(kDexData));
-
- memcpy(memory.Data(), kDexData, sizeof(kDexData));
- uint64_t start = reinterpret_cast<uint64_t>(memory.Data());
- MapInfo info(nullptr, nullptr, start, start + sizeof(kDexData) - 2, 0x200, 0x5,
- "/does/not/exist");
- EXPECT_TRUE(DexFile::Create(start, &memory, &info) == nullptr);
+TEST(DexFileTest, create_using_memory_size_too_small) {
+ MemoryFake memory;
+ size_t size = sizeof(kDexData) - 1;
+ memory.SetMemory(0x4000, kDexData, size);
+ EXPECT_TRUE(DexFile::Create(0x4000, size, &memory, nullptr) == nullptr);
}
TEST(DexFileTest, get_method) {
MemoryFake memory;
memory.SetMemory(0x4000, kDexData, sizeof(kDexData));
MapInfo info(nullptr, nullptr, 0x100, 0x10000, 0x200, 0x5, "");
- std::unique_ptr<DexFile> dex_file(DexFile::Create(0x4000, &memory, &info));
+ std::unique_ptr<DexFile> dex_file(DexFile::Create(0x4000, sizeof(kDexData), &memory, &info));
ASSERT_TRUE(dex_file != nullptr);
SharedString method;
@@ -273,7 +187,7 @@ TEST(DexFileTest, get_method_empty) {
MemoryFake memory;
memory.SetMemory(0x4000, kDexData, sizeof(kDexData));
MapInfo info(nullptr, nullptr, 0x100, 0x10000, 0x200, 0x5, "");
- std::unique_ptr<DexFile> dex_file(DexFile::Create(0x4000, &memory, &info));
+ std::unique_ptr<DexFile> dex_file(DexFile::Create(0x4000, sizeof(kDexData), &memory, &info));
ASSERT_TRUE(dex_file != nullptr);
SharedString method;
@@ -292,7 +206,7 @@ TEST(DexFileTest, get_method_from_cache) {
MemoryFake memory;
MapInfo info(nullptr, nullptr, 0x4000, 0x10000, 0, 0x5, tf.path);
- std::unique_ptr<DexFile> dex_file = DexFile::Create(0x4000, &memory, &info);
+ std::unique_ptr<DexFile> dex_file = DexFile::Create(0x4000, sizeof(kDexData), &memory, &info);
EXPECT_TRUE(dex_file != nullptr);
SharedString method;
diff --git a/libunwindstack/tests/DexFilesTest.cpp b/libunwindstack/tests/DexFilesTest.cpp
index ce3def6..8da32a1 100644
--- a/libunwindstack/tests/DexFilesTest.cpp
+++ b/libunwindstack/tests/DexFilesTest.cpp
@@ -101,8 +101,10 @@ class DexFilesTest : public ::testing::Test {
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 WriteEntry32(uint64_t entry_addr, uint32_t next, uint32_t prev, uint32_t dex_file,
+ uint64_t dex_size);
+ void WriteEntry64(uint64_t entry_addr, uint64_t next, uint64_t prev, uint64_t dex_file,
+ uint64_t dex_size);
void WriteDex(uint64_t dex_file);
static constexpr size_t kMapGlobalNonReadable = 2;
@@ -143,7 +145,7 @@ void DexFilesTest::WriteDescriptor64(uint64_t addr, uint64_t entry) {
}
void DexFilesTest::WriteEntry32(uint64_t entry_addr, uint32_t next, uint32_t prev,
- uint32_t dex_file) {
+ uint32_t dex_file, uint64_t dex_size) {
// Format of the 32 bit DEXFileEntry structure:
// uint32_t next
memory_->SetData32(entry_addr, next);
@@ -153,11 +155,11 @@ void DexFilesTest::WriteEntry32(uint64_t entry_addr, uint32_t next, uint32_t pre
memory_->SetData32(entry_addr + 8, dex_file);
// uint32_t dex_size (present in the struct, but we ignore it)
memory_->SetData32(entry_addr + 12, 0); // Align.
- memory_->SetData64(entry_addr + 16, 0);
+ memory_->SetData64(entry_addr + 16, dex_size);
}
void DexFilesTest::WriteEntry64(uint64_t entry_addr, uint64_t next, uint64_t prev,
- uint64_t dex_file) {
+ uint64_t dex_file, uint64_t dex_size) {
// Format of the 64 bit DEXFileEntry structure:
// uint64_t next
memory_->SetData64(entry_addr, next);
@@ -166,7 +168,7 @@ void DexFilesTest::WriteEntry64(uint64_t entry_addr, uint64_t next, uint64_t pre
// uint64_t dex_file
memory_->SetData64(entry_addr + 16, dex_file);
// uint32_t dex_size (present in the struct, but we ignore it)
- memory_->SetData64(entry_addr + 24, 0);
+ memory_->SetData64(entry_addr + 24, dex_size);
}
void DexFilesTest::WriteDex(uint64_t dex_file) {
@@ -187,7 +189,7 @@ TEST_F(DexFilesTest, get_method_information_32) {
uint64_t method_offset = 0x124;
WriteDescriptor32(0x100800, 0x200000);
- WriteEntry32(0x200000, 0, 0, 0x300000);
+ WriteEntry32(0x200000, 0, 0, 0x300000, sizeof(kDexData));
WriteDex(0x300000);
dex_files_->GetFunctionName(maps_.get(), 0x300100, &method_name, &method_offset);
@@ -202,7 +204,7 @@ TEST_F(DexFilesTest, get_method_information_64) {
uint64_t method_offset = 0x124;
WriteDescriptor64(0x100800, 0x200000);
- WriteEntry64(0x200000, 0, 0, 0x301000);
+ WriteEntry64(0x200000, 0, 0, 0x301000, sizeof(kDexData));
WriteDex(0x301000);
dex_files_->GetFunctionName(maps_.get(), 0x301102, &method_name, &method_offset);
@@ -215,8 +217,8 @@ TEST_F(DexFilesTest, get_method_information_not_first_entry_32) {
uint64_t method_offset = 0x124;
WriteDescriptor32(0x100800, 0x200000);
- WriteEntry32(0x200000, 0x200100, 0, 0x100000);
- WriteEntry32(0x200100, 0, 0x200000, 0x300000);
+ WriteEntry32(0x200000, 0x200100, 0, 0x100000, sizeof(kDexData));
+ WriteEntry32(0x200100, 0, 0x200000, 0x300000, sizeof(kDexData));
WriteDex(0x300000);
dex_files_->GetFunctionName(maps_.get(), 0x300104, &method_name, &method_offset);
@@ -231,8 +233,8 @@ TEST_F(DexFilesTest, get_method_information_not_first_entry_64) {
uint64_t method_offset = 0x124;
WriteDescriptor64(0x100800, 0x200000);
- WriteEntry64(0x200000, 0x200100, 0, 0x100000);
- WriteEntry64(0x200100, 0, 0x200000, 0x300000);
+ WriteEntry64(0x200000, 0x200100, 0, 0x100000, sizeof(kDexData));
+ WriteEntry64(0x200100, 0, 0x200000, 0x300000, sizeof(kDexData));
WriteDex(0x300000);
dex_files_->GetFunctionName(maps_.get(), 0x300106, &method_name, &method_offset);
@@ -245,7 +247,7 @@ TEST_F(DexFilesTest, get_method_information_cached) {
uint64_t method_offset = 0x124;
WriteDescriptor32(0x100800, 0x200000);
- WriteEntry32(0x200000, 0, 0, 0x300000);
+ WriteEntry32(0x200000, 0, 0, 0x300000, sizeof(kDexData));
WriteDex(0x300000);
dex_files_->GetFunctionName(maps_.get(), 0x300100, &method_name, &method_offset);
@@ -264,8 +266,8 @@ TEST_F(DexFilesTest, get_method_information_search_libs) {
uint64_t method_offset = 0x124;
WriteDescriptor32(0x100800, 0x200000);
- WriteEntry32(0x200000, 0x200100, 0, 0x100000);
- WriteEntry32(0x200100, 0, 0x200000, 0x300000);
+ WriteEntry32(0x200000, 0x200100, 0, 0x100000, sizeof(kDexData));
+ WriteEntry32(0x200100, 0, 0x200000, 0x300000, sizeof(kDexData));
WriteDex(0x300000);
// Only search a given named list of libs.
@@ -299,7 +301,7 @@ TEST_F(DexFilesTest, get_method_information_global_skip_zero_32) {
WriteDescriptor32(0xc800, 0);
WriteDescriptor32(0x100800, 0x200000);
- WriteEntry32(0x200000, 0, 0, 0x300000);
+ WriteEntry32(0x200000, 0, 0, 0x300000, sizeof(kDexData));
WriteDex(0x300000);
dex_files_->GetFunctionName(maps_.get(), 0x300100, &method_name, &method_offset);
@@ -326,7 +328,7 @@ TEST_F(DexFilesTest, get_method_information_global_skip_zero_64) {
WriteDescriptor64(0xc800, 0);
WriteDescriptor64(0x100800, 0x200000);
- WriteEntry64(0x200000, 0, 0, 0x300000);
+ WriteEntry64(0x200000, 0, 0, 0x300000, sizeof(kDexData));
WriteDex(0x300000);
dex_files_->GetFunctionName(maps_.get(), 0x300100, &method_name, &method_offset);
@@ -348,7 +350,7 @@ TEST_F(DexFilesTest, get_method_information_with_empty_map) {
uint64_t method_offset = 0x124;
WriteDescriptor32(0x503800, 0x506000);
- WriteEntry32(0x506000, 0, 0, 0x510000);
+ WriteEntry32(0x506000, 0, 0, 0x510000, sizeof(kDexData));
WriteDex(0x510000);
dex_files_->GetFunctionName(maps_.get(), 0x510100, &method_name, &method_offset);