Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e1948bf7 authored by Christopher Ferris's avatar Christopher Ferris Committed by Gerrit Code Review
Browse files

Merge "Avoid re-mapping dex file that's in local memory."

parents 51abcc56 273d3f08
Loading
Loading
Loading
Loading
+22 −2
Original line number Diff line number Diff line
@@ -50,6 +50,22 @@ static bool HasDexSupport() {

std::unique_ptr<DexFile> DexFile::Create(uint64_t dex_file_offset_in_memory, Memory* memory,
                                         MapInfo* info) {
  if (UNLIKELY(!HasDexSupport())) {
    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(art_dex_file));
    }
  }

  if (!info->name.empty()) {
    std::unique_ptr<DexFile> dex_file =
        DexFileFromFile::Create(dex_file_offset_in_memory - info->start + info->offset, info->name);
@@ -57,7 +73,7 @@ std::unique_ptr<DexFile> DexFile::Create(uint64_t dex_file_offset_in_memory, Mem
      return dex_file;
    }
  }
  return DexFileFromMemory::Create(dex_file_offset_in_memory, memory, info->name);
  return DexFileFromMemory::Create(dex_file_offset_in_memory, memory, info->name, max_size);
}

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

std::unique_ptr<DexFileFromMemory> DexFileFromMemory::Create(uint64_t dex_file_offset_in_memory,
                                                             Memory* memory,
                                                             const std::string& name) {
                                                             const std::string& name,
                                                             size_t max_size) {
  if (UNLIKELY(!HasDexSupport())) {
    return nullptr;
  }
@@ -105,6 +122,9 @@ std::unique_ptr<DexFileFromMemory> DexFileFromMemory::Create(uint64_t dex_file_o
    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 (art_dex_file != nullptr) {
      return std::unique_ptr<DexFileFromMemory>(
+2 −1
Original line number Diff line number Diff line
@@ -55,7 +55,8 @@ class DexFileFromFile : public DexFile {
class DexFileFromMemory : public DexFile {
 public:
  static std::unique_ptr<DexFileFromMemory> Create(uint64_t dex_file_offset_in_memory,
                                                   Memory* memory, const std::string& name);
                                                   Memory* memory, const std::string& name,
                                                   size_t max_size);

 private:
  DexFileFromMemory(std::unique_ptr<art_api::dex::DexFile>& art_dex_file,
+2 −0
Original line number Diff line number Diff line
@@ -28,6 +28,8 @@ 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;
};

+2 −0
Original line number Diff line number Diff line
@@ -41,6 +41,8 @@ class Memory {

  virtual void Clear() {}

  virtual bool IsLocal() const { return false; }

  virtual size_t Read(uint64_t addr, void* dst, size_t size) = 0;

  bool ReadFully(uint64_t addr, void* dst, size_t size);
+42 −4
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@

#include <unordered_map>

#include <MemoryLocal.h>
#include <android-base/file.h>
#include <gtest/gtest.h>
#include <unwindstack/MapInfo.h>
@@ -109,7 +110,7 @@ TEST(DexFileTest, from_memory_fail_too_small_for_header) {

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

  EXPECT_TRUE(DexFileFromMemory::Create(0x1000, &memory, "") == nullptr);
  EXPECT_TRUE(DexFileFromMemory::Create(0x1000, &memory, "", sizeof(kDexData)) == nullptr);
}

TEST(DexFileTest, from_memory_fail_too_small_for_data) {
@@ -117,7 +118,7 @@ TEST(DexFileTest, from_memory_fail_too_small_for_data) {

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

  EXPECT_TRUE(DexFileFromMemory::Create(0x1000, &memory, "") == nullptr);
  EXPECT_TRUE(DexFileFromMemory::Create(0x1000, &memory, "", sizeof(kDexData)) == nullptr);
}

TEST(DexFileTest, from_memory_open) {
@@ -125,7 +126,7 @@ TEST(DexFileTest, from_memory_open) {

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

  EXPECT_TRUE(DexFileFromMemory::Create(0x1000, &memory, "") != nullptr);
  EXPECT_TRUE(DexFileFromMemory::Create(0x1000, &memory, "", sizeof(kDexData)) != nullptr);
}

TEST(DexFileTest, from_memory_no_leak) {
@@ -136,7 +137,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, "") != nullptr);
    EXPECT_TRUE(DexFileFromMemory::Create(0x1000, &memory, "", sizeof(kDexData)) != nullptr);
    ASSERT_NO_FATAL_FAILURE(CheckForLeak(i, &first_allocated_bytes, &last_allocated_bytes));
  }
}
@@ -213,6 +214,43 @@ TEST(DexFileTest, create_using_memory_file_is_malformed) {
  EXPECT_TRUE(dex_file == nullptr);
}

TEST(DexFileTest, create_using_memory_size_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);
}

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, get_method) {
  MemoryFake memory;
  memory.SetMemory(0x4000, kDexData, sizeof(kDexData));