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

Commit cacf5bf6 authored by Martin Stjernholm's avatar Martin Stjernholm
Browse files

Revert "Use libdexfile external API in libunwindstack."

This reverts commit 444e23d2.

The rest of the topic doesn't need to be reverted.

Reason for revert: Breaks renderscript on marlin and sailfish.

Test: Manual repro of http://b/121110092#comment1 on reported branch
Test: "atest CtsRenderscriptTestCases" on that branch
Test: mmma system/core/{libunwindstack,libbacktrace}, run host gtests
Test: Make image, flash, and reboot device.
Bug: 121110092, 119632407
Change-Id: If1976b19ce386c95bc5bd4fd6d523745c167de18
parent 8fd4435d
Loading
Loading
Loading
Loading
+2 −21
Original line number Original line Diff line number Diff line
@@ -116,21 +116,14 @@ cc_library_static {
        "libdebuggerd",
        "libdebuggerd",
        "libbacktrace",
        "libbacktrace",
        "libunwindstack",
        "libunwindstack",
        "libdexfile",  // libunwindstack dependency
        "libdexfile",
        "libdexfile_external",  // libunwindstack dependency
        "libdexfile_support",  // libunwindstack dependency
        "liblzma",
        "liblzma",
        "libcutils",
        "libcutils",
    ],
    ],
    target: {
    target: {
        recovery: {
        recovery: {
            cflags: ["-DNO_LIBDEXFILE_SUPPORT"],
            cflags: ["-DNO_LIBDEXFILE_SUPPORT"],
            exclude_static_libs: [
            exclude_static_libs: ["libdexfile"],
                "libartbase",
                "libdexfile",
                "libdexfile_external",
                "libdexfile_support",
            ],
        },
        },
    },
    },


@@ -177,22 +170,12 @@ cc_library_static {


    static_libs: [
    static_libs: [
        "libbacktrace",
        "libbacktrace",
        "libdexfile_external",  // libunwindstack dependency
        "libdexfile_support",  // libunwindstack dependency
        "libunwindstack",
        "libunwindstack",
        "liblzma",
        "liblzma",
        "libbase",
        "libbase",
        "libcutils",
        "libcutils",
        "liblog",
        "liblog",
    ],
    ],
    target: {
        recovery: {
            exclude_static_libs: [
                "libdexfile_external",
                "libdexfile_support",
            ],
        },
    },
}
}


cc_test {
cc_test {
@@ -233,8 +216,6 @@ cc_test {


    static_libs: [
    static_libs: [
        "libdebuggerd",
        "libdebuggerd",
        "libdexfile_external",  // libunwindstack dependency
        "libdexfile_support",  // libunwindstack dependency
        "libunwindstack",
        "libunwindstack",
    ],
    ],


+3 −11
Original line number Original line Diff line number Diff line
@@ -94,10 +94,7 @@ cc_library {
                "DexFile.cpp",
                "DexFile.cpp",
                "DexFiles.cpp",
                "DexFiles.cpp",
            ],
            ],
            exclude_shared_libs: [
            exclude_shared_libs: ["libdexfile"],
                "libdexfile_external",
                "libdexfile_support",
            ],
        },
        },
        recovery: {
        recovery: {
            cflags: ["-DNO_LIBDEXFILE_SUPPORT"],
            cflags: ["-DNO_LIBDEXFILE_SUPPORT"],
@@ -105,10 +102,7 @@ cc_library {
                "DexFile.cpp",
                "DexFile.cpp",
                "DexFiles.cpp",
                "DexFiles.cpp",
            ],
            ],
            exclude_shared_libs: [
            exclude_shared_libs: ["libdexfile"],
                "libdexfile_external",
                "libdexfile_support",
            ],
        },
        },
    },
    },


@@ -133,8 +127,7 @@ cc_library {


    shared_libs: [
    shared_libs: [
        "libbase",
        "libbase",
        "libdexfile_external",
        "libdexfile",
        "libdexfile_support",
        "liblog",
        "liblog",
        "liblzma",
        "liblzma",
    ],
    ],
@@ -222,7 +215,6 @@ cc_test {
        "liblzma",
        "liblzma",
        "libunwindstack",
        "libunwindstack",
        "libdexfile",
        "libdexfile",
        "libdexfile_support",
    ],
    ],


    static_libs: [
    static_libs: [
+146 −42
Original line number Original line Diff line number Diff line
@@ -23,7 +23,13 @@
#include <memory>
#include <memory>


#include <android-base/unique_fd.h>
#include <android-base/unique_fd.h>
#include <art_api/ext_dex_file.h>

#include <dex/class_accessor-inl.h>
#include <dex/code_item_accessors-inl.h>
#include <dex/compact_dex_file.h>
#include <dex/dex_file-inl.h>
#include <dex/dex_file_loader.h>
#include <dex/standard_dex_file.h>


#include <unwindstack/MapInfo.h>
#include <unwindstack/MapInfo.h>
#include <unwindstack/Memory.h>
#include <unwindstack/Memory.h>
@@ -32,71 +38,169 @@


namespace unwindstack {
namespace unwindstack {


std::unique_ptr<DexFile> DexFile::Create(uint64_t dex_file_offset_in_memory, Memory* memory,
DexFile* DexFile::Create(uint64_t dex_file_offset_in_memory, Memory* memory, MapInfo* info) {
                                         MapInfo* info) {
  if (!info->name.empty()) {
  if (!info->name.empty()) {
    std::unique_ptr<DexFile> dex_file =
    std::unique_ptr<DexFileFromFile> dex_file(new DexFileFromFile);
        DexFileFromFile::Create(dex_file_offset_in_memory - info->start + info->offset, info->name);
    if (dex_file->Open(dex_file_offset_in_memory - info->start + info->offset, info->name)) {
    if (dex_file) {
      return dex_file.release();
      return dex_file;
    }
  }

  std::unique_ptr<DexFileFromMemory> dex_file(new DexFileFromMemory);
  if (dex_file->Open(dex_file_offset_in_memory, memory)) {
    return dex_file.release();
  }
  return nullptr;
}
}

DexFileFromFile::~DexFileFromFile() {
  if (size_ != 0) {
    munmap(mapped_memory_, size_);
  }
  }
  return DexFileFromMemory::Create(dex_file_offset_in_memory, memory, info->name);
}
}


bool DexFile::GetMethodInformation(uint64_t dex_offset, std::string* method_name,
bool DexFile::GetMethodInformation(uint64_t dex_offset, std::string* method_name,
                                   uint64_t* method_offset) {
                                   uint64_t* method_offset) {
  art_api::dex::MethodInfo method_info = GetMethodInfoForOffset(dex_offset);
  if (dex_file_ == nullptr) {
  if (method_info.offset == 0) {
    return false;
    return false;
  }
  }
  *method_name = method_info.name;

  *method_offset = dex_offset - method_info.offset;
  if (!dex_file_->IsInDataSection(dex_file_->Begin() + dex_offset)) {
    return false;  // The DEX offset is not within the bytecode of this dex file.
  }

  if (dex_file_->IsCompactDexFile()) {
    // The data section of compact dex files might be shared.
    // Check the subrange unique to this compact dex.
    const auto& cdex_header = dex_file_->AsCompactDexFile()->GetHeader();
    uint32_t begin = cdex_header.data_off_ + cdex_header.OwnedDataBegin();
    uint32_t end = cdex_header.data_off_ + cdex_header.OwnedDataEnd();
    if (dex_offset < begin || dex_offset >= end) {
      return false;  // The DEX offset is not within the bytecode of this dex file.
    }
  }

  // The method data is cached in a std::map indexed by method end offset and
  // contains the start offset and the method member index.
  // Only cache the method data as it is searched. Do not read the entire
  // set of method data into the cache at once.
  // This is done because many unwinds only find a single frame with dex file
  // info, so reading the entire method data is wasteful. However, still cache
  // the data so that anything doing multiple unwinds will have this data
  // cached for future use.

  // First look in the method cache.
  auto entry = method_cache_.upper_bound(dex_offset);
  if (entry != method_cache_.end() && dex_offset >= entry->second.first) {
    *method_name = dex_file_->PrettyMethod(entry->second.second, false);
    *method_offset = dex_offset - entry->second.first;
    return true;
  }

  // Check the methods we haven't cached.
  for (; class_def_index_ < dex_file_->NumClassDefs(); class_def_index_++) {
    art::ClassAccessor accessor(*dex_file_, dex_file_->GetClassDef(class_def_index_));

    for (const art::ClassAccessor::Method& method : accessor.GetMethods()) {
      art::CodeItemInstructionAccessor code = method.GetInstructions();
      if (!code.HasCodeItem()) {
        continue;
      }
      uint32_t offset = reinterpret_cast<const uint8_t*>(code.Insns()) - dex_file_->Begin();
      uint32_t offset_end = offset + code.InsnsSizeInBytes();
      uint32_t member_index = method.GetIndex();
      method_cache_[offset_end] = std::make_pair(offset, member_index);
      if (offset <= dex_offset && dex_offset < offset_end) {
        *method_name = dex_file_->PrettyMethod(member_index, false);
        *method_offset = dex_offset - offset;
        return true;
        return true;
      }
      }
    }
  }
  return false;
}


std::unique_ptr<DexFileFromFile> DexFileFromFile::Create(uint64_t dex_file_offset_in_file,
bool DexFileFromFile::Open(uint64_t dex_file_offset_in_file, const std::string& file) {
                                                         const std::string& file) {
  android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(file.c_str(), O_RDONLY | O_CLOEXEC)));
  android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(file.c_str(), O_RDONLY | O_CLOEXEC)));
  if (fd == -1) {
  if (fd == -1) {
    return nullptr;
    return false;
  }
  struct stat buf;
  if (fstat(fd, &buf) == -1) {
    return false;
  }
  uint64_t length;
  if (buf.st_size < 0 ||
      __builtin_add_overflow(dex_file_offset_in_file, sizeof(art::DexFile::Header), &length) ||
      static_cast<uint64_t>(buf.st_size) < length) {
    return false;
  }
  }


  std::string error_msg;
  mapped_memory_ = mmap(nullptr, buf.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
  std::unique_ptr<art_api::dex::DexFile> art_dex_file =
  if (mapped_memory_ == MAP_FAILED) {
      OpenFromFd(fd, dex_file_offset_in_file, file, &error_msg);
    return false;
  if (art_dex_file == nullptr) {
    return nullptr;
  }
  }
  size_ = buf.st_size;

  uint8_t* memory = reinterpret_cast<uint8_t*>(mapped_memory_);


  return std::unique_ptr<DexFileFromFile>(new DexFileFromFile(std::move(*art_dex_file.release())));
  art::DexFile::Header* header =
      reinterpret_cast<art::DexFile::Header*>(&memory[dex_file_offset_in_file]);
  if (!art::StandardDexFile::IsMagicValid(header->magic_) &&
      !art::CompactDexFile::IsMagicValid(header->magic_)) {
    return false;
  }
  }


std::unique_ptr<DexFileFromMemory> DexFileFromMemory::Create(uint64_t dex_file_offset_in_memory,
  if (__builtin_add_overflow(dex_file_offset_in_file, header->file_size_, &length) ||
                                                             Memory* memory,
      static_cast<uint64_t>(buf.st_size) < length) {
                                                             const std::string& name) {
    return false;
  std::vector<uint8_t> backing_memory;
  }


  for (size_t size = 0;;) {
  art::DexFileLoader loader;
  std::string error_msg;
  std::string error_msg;
    std::unique_ptr<art_api::dex::DexFile> art_dex_file =
  auto dex = loader.Open(&memory[dex_file_offset_in_file], header->file_size_, "", 0, nullptr,
        OpenFromMemory(backing_memory.data(), &size, name, &error_msg);
                         false, false, &error_msg);

  dex_file_.reset(dex.release());
    if (art_dex_file != nullptr) {
  return dex_file_ != nullptr;
      return std::unique_ptr<DexFileFromMemory>(
          new DexFileFromMemory(std::move(*art_dex_file.release()), std::move(backing_memory)));
}
}


    if (!error_msg.empty()) {
bool DexFileFromMemory::Open(uint64_t dex_file_offset_in_memory, Memory* memory) {
      return nullptr;
  memory_.resize(sizeof(art::DexFile::Header));
  if (!memory->ReadFully(dex_file_offset_in_memory, memory_.data(), memory_.size())) {
    return false;
  }
  }


    backing_memory.resize(size);
  art::DexFile::Header* header = reinterpret_cast<art::DexFile::Header*>(memory_.data());
    if (!memory->ReadFully(dex_file_offset_in_memory, backing_memory.data(),
  uint32_t file_size = header->file_size_;
                           backing_memory.size())) {
  if (art::CompactDexFile::IsMagicValid(header->magic_)) {
      return nullptr;
    // Compact dex file store data section separately so that it can be shared.
    // Therefore we need to extend the read memory range to include it.
    // TODO: This might be wasteful as we might read data in between as well.
    //       In practice, this should be fine, as such sharing only happens on disk.
    uint32_t computed_file_size;
    if (__builtin_add_overflow(header->data_off_, header->data_size_, &computed_file_size)) {
      return false;
    }
    if (computed_file_size > file_size) {
      file_size = computed_file_size;
    }
  } else if (!art::StandardDexFile::IsMagicValid(header->magic_)) {
    return false;
  }
  }

  memory_.resize(file_size);
  if (!memory->ReadFully(dex_file_offset_in_memory, memory_.data(), memory_.size())) {
    return false;
  }
  }

  header = reinterpret_cast<art::DexFile::Header*>(memory_.data());

  art::DexFileLoader loader;
  std::string error_msg;
  auto dex =
      loader.Open(memory_.data(), header->file_size_, "", 0, nullptr, false, false, &error_msg);
  dex_file_.reset(dex.release());
  return dex_file_ != nullptr;
}
}


}  // namespace unwindstack
}  // namespace unwindstack
+20 −13
Original line number Original line Diff line number Diff line
@@ -25,41 +25,48 @@
#include <utility>
#include <utility>
#include <vector>
#include <vector>


#include <art_api/ext_dex_file.h>
#include <dex/dex_file-inl.h>


namespace unwindstack {
namespace unwindstack {


class DexFile : protected art_api::dex::DexFile {
class DexFile {
 public:
 public:
  DexFile() = default;
  virtual ~DexFile() = default;
  virtual ~DexFile() = default;


  bool GetMethodInformation(uint64_t dex_offset, std::string* method_name, uint64_t* method_offset);
  bool GetMethodInformation(uint64_t dex_offset, std::string* method_name, uint64_t* method_offset);


  static std::unique_ptr<DexFile> Create(uint64_t dex_file_offset_in_memory, Memory* memory,
  static DexFile* Create(uint64_t dex_file_offset_in_memory, Memory* memory, MapInfo* info);
                                         MapInfo* info);


 protected:
 protected:
  DexFile(art_api::dex::DexFile&& art_dex_file) : art_api::dex::DexFile(std::move(art_dex_file)) {}
  void Init();

  std::unique_ptr<const art::DexFile> dex_file_;
  std::map<uint32_t, std::pair<uint64_t, uint32_t>> method_cache_;  // dex offset to method index.

  uint32_t class_def_index_ = 0;
};
};


class DexFileFromFile : public DexFile {
class DexFileFromFile : public DexFile {
 public:
 public:
  static std::unique_ptr<DexFileFromFile> Create(uint64_t dex_file_offset_in_file,
  DexFileFromFile() = default;
                                                 const std::string& file);
  virtual ~DexFileFromFile();

  bool Open(uint64_t dex_file_offset_in_file, const std::string& name);


 private:
 private:
  DexFileFromFile(art_api::dex::DexFile&& art_dex_file) : DexFile(std::move(art_dex_file)) {}
  void* mapped_memory_ = nullptr;
  size_t size_ = 0;
};
};


class DexFileFromMemory : public DexFile {
class DexFileFromMemory : public DexFile {
 public:
 public:
  static std::unique_ptr<DexFileFromMemory> Create(uint64_t dex_file_offset_in_memory,
  DexFileFromMemory() = default;
                                                   Memory* memory, const std::string& name);
  virtual ~DexFileFromMemory() = default;


 private:
  bool Open(uint64_t dex_file_offset_in_memory, Memory* memory);
  DexFileFromMemory(art_api::dex::DexFile&& art_dex_file, std::vector<uint8_t>&& memory)
      : DexFile(std::move(art_dex_file)), memory_(std::move(memory)) {}


 private:
  std::vector<uint8_t> memory_;
  std::vector<uint8_t> memory_;
};
};


+8 −5
Original line number Original line Diff line number Diff line
@@ -48,7 +48,11 @@ 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)
    : Global(memory, search_libs) {}
    : Global(memory, search_libs) {}


DexFiles::~DexFiles() {}
DexFiles::~DexFiles() {
  for (auto& entry : files_) {
    delete entry.second;
  }
}


void DexFiles::ProcessArch() {
void DexFiles::ProcessArch() {
  switch (arch()) {
  switch (arch()) {
@@ -133,11 +137,10 @@ DexFile* DexFiles::GetDexFile(uint64_t dex_file_offset, MapInfo* info) {
  DexFile* dex_file;
  DexFile* dex_file;
  auto entry = files_.find(dex_file_offset);
  auto entry = files_.find(dex_file_offset);
  if (entry == files_.end()) {
  if (entry == files_.end()) {
    std::unique_ptr<DexFile> new_dex_file = DexFile::Create(dex_file_offset, memory_.get(), info);
    dex_file = DexFile::Create(dex_file_offset, memory_.get(), info);
    dex_file = new_dex_file.get();
    files_[dex_file_offset] = dex_file;
    files_[dex_file_offset] = std::move(new_dex_file);
  } else {
  } else {
    dex_file = entry->second.get();
    dex_file = entry->second;
  }
  }
  return dex_file;
  return dex_file;
}
}
Loading