From 3a88045d17646c9e852a1270c0b5123e2ebb7072 Mon Sep 17 00:00:00 2001 From: Yabin Cui Date: Mon, 29 Jun 2020 16:37:31 -0700 Subject: simpleperf: move GetBuildId* functions inside ElfFile class. Bug: 160187327 Test: run simpleperf_unit_test. Change-Id: Idd50cf755f10000e3629ec99a291ee35cf6f4cfd --- simpleperf/dso.cpp | 24 +++++++++------------- simpleperf/read_elf.cpp | 48 +++++++++++++++++++++++++------------------- simpleperf/read_elf.h | 4 +--- simpleperf/read_elf_test.cpp | 18 +++++++++++++---- 4 files changed, 52 insertions(+), 42 deletions(-) diff --git a/simpleperf/dso.cpp b/simpleperf/dso.cpp index 57e65c59..51f63a38 100644 --- a/simpleperf/dso.cpp +++ b/simpleperf/dso.cpp @@ -34,6 +34,8 @@ #include "read_elf.h" #include "utils.h" +using namespace simpleperf; + namespace simpleperf_dso_impl { std::string RemovePathSeparatorSuffix(const std::string& path) { @@ -87,7 +89,9 @@ void DebugElfFileFinder::CollectBuildIdInDir(const std::string& dir) { CollectBuildIdInDir(path); } else { BuildId build_id; - if (GetBuildIdFromElfFile(path, &build_id) == ElfStatus::NO_ERROR) { + ElfStatus status; + auto elf = ElfFile::Open(path, &status); + if (status == ElfStatus::NO_ERROR && elf->GetBuildId(&build_id) == ElfStatus::NO_ERROR) { build_id_to_file_map_[build_id.ToString()] = path; } } @@ -732,18 +736,10 @@ const char* DsoTypeToString(DsoType dso_type) { } bool GetBuildIdFromDsoPath(const std::string& dso_path, BuildId* build_id) { - auto tuple = SplitUrlInApk(dso_path); - ElfStatus result; - if (std::get<0>(tuple)) { - EmbeddedElf* elf = ApkInspector::FindElfInApkByName(std::get<1>(tuple), std::get<2>(tuple)); - if (elf == nullptr) { - result = ElfStatus::FILE_NOT_FOUND; - } else { - result = GetBuildIdFromEmbeddedElfFile(elf->filepath(), elf->entry_offset(), - elf->entry_size(), build_id); - } - } else { - result = GetBuildIdFromElfFile(dso_path, build_id); + ElfStatus status; + auto elf = ElfFile::Open(dso_path, &status); + if (status == ElfStatus::NO_ERROR && elf->GetBuildId(build_id) == ElfStatus::NO_ERROR) { + return true; } - return result == ElfStatus::NO_ERROR; + return false; } diff --git a/simpleperf/read_elf.cpp b/simpleperf/read_elf.cpp index 0f6aa415..65dd5739 100644 --- a/simpleperf/read_elf.cpp +++ b/simpleperf/read_elf.cpp @@ -217,20 +217,6 @@ static ElfStatus OpenObjectFileInMemory(const char* data, size_t size, BinaryWra return ElfStatus::NO_ERROR; } -ElfStatus GetBuildIdFromElfFile(const std::string& filename, BuildId* build_id) { - return GetBuildIdFromEmbeddedElfFile(filename, 0, 0, build_id); -} - -ElfStatus GetBuildIdFromEmbeddedElfFile(const std::string& filename, uint64_t file_offset, - uint32_t file_size, BuildId* build_id) { - BinaryWrapper wrapper; - ElfStatus result = OpenObjectFile(filename, file_offset, file_size, &wrapper); - if (result != ElfStatus::NO_ERROR) { - return result; - } - return GetBuildIdFromObjectFile(wrapper.obj, build_id); -} - template ElfStatus ReadSectionFromELFFile(const llvm::object::ELFObjectFile* elf, const std::string& section_name, std::string* content) { @@ -571,10 +557,10 @@ template class ElfFileImpl {}; template -class ElfFileImpl> : public ElfFile { +class ElfFileImpl> : public ElfFile { public: - ElfFileImpl(BinaryWrapper&& wrapper, const llvm::object::ELFFile* elf) - : wrapper_(std::move(wrapper)), elf_(elf) {} + ElfFileImpl(BinaryWrapper&& wrapper, const llvm::object::ELFObjectFile* elf_obj) + : wrapper_(std::move(wrapper)), elf_obj_(elf_obj), elf_(elf_obj->getELFFile()) {} bool Is64Bit() override { return elf_->getHeader()->getFileClass() == llvm::ELF::ELFCLASS64; @@ -598,8 +584,30 @@ class ElfFileImpl> : public ElfFile { return segments; } + ElfStatus GetBuildId(BuildId* build_id) override { + llvm::StringRef data = elf_obj_->getData(); + const char* binary_start = data.data(); + const char* binary_end = data.data() + data.size(); + for (auto it = elf_obj_->section_begin(); it != elf_obj_->section_end(); ++it) { + const llvm::object::ELFSectionRef& section_ref = *it; + if (section_ref.getType() == llvm::ELF::SHT_NOTE) { + if (it->getContents(data)) { + return ElfStatus::READ_FAILED; + } + if (data.data() < binary_start || data.data() + data.size() > binary_end) { + return ElfStatus::NO_BUILD_ID; + } + if (GetBuildIdFromNoteSection(data.data(), data.size(), build_id)) { + return ElfStatus::NO_ERROR; + } + } + } + return ElfStatus::NO_BUILD_ID; + } + private: BinaryWrapper wrapper_; + const llvm::object::ELFObjectFile* elf_obj_; const llvm::object::ELFFile* elf_; }; @@ -622,14 +630,12 @@ std::unique_ptr ElfFile::Open(const std::string& filename, ElfStatus* s } if (*status == ElfStatus::NO_ERROR) { if (auto obj = llvm::dyn_cast(wrapper.obj)) { - using elf_t = std::decay_tgetELFFile())>; return std::unique_ptr( - new ElfFileImpl(std::move(wrapper), obj->getELFFile())); + new ElfFileImpl(std::move(wrapper), obj)); } if (auto obj = llvm::dyn_cast(wrapper.obj)) { - using elf_t = std::decay_tgetELFFile())>; return std::unique_ptr( - new ElfFileImpl(std::move(wrapper), obj->getELFFile())); + new ElfFileImpl(std::move(wrapper), obj)); } *status = ElfStatus::FILE_MALFORMED; } diff --git a/simpleperf/read_elf.h b/simpleperf/read_elf.h index c859ef40..6e32b5ea 100644 --- a/simpleperf/read_elf.h +++ b/simpleperf/read_elf.h @@ -40,9 +40,6 @@ enum ElfStatus { std::ostream& operator<<(std::ostream& os, const ElfStatus& status); ElfStatus GetBuildIdFromNoteFile(const std::string& filename, BuildId* build_id); -ElfStatus GetBuildIdFromElfFile(const std::string& filename, BuildId* build_id); -ElfStatus GetBuildIdFromEmbeddedElfFile(const std::string& filename, uint64_t file_offset, - uint32_t file_size, BuildId* build_id); // The symbol prefix used to indicate that the symbol belongs to android linker. static const std::string linker_prefix = "__dl_"; @@ -105,6 +102,7 @@ class ElfFile { virtual bool Is64Bit() = 0; virtual llvm::MemoryBuffer* GetMemoryBuffer() = 0; virtual std::vector GetProgramHeader() = 0; + virtual ElfStatus GetBuildId(BuildId* build_id) = 0; protected: ElfFile() {} diff --git a/simpleperf/read_elf_test.cpp b/simpleperf/read_elf_test.cpp index cc5aa52b..6f0db234 100644 --- a/simpleperf/read_elf_test.cpp +++ b/simpleperf/read_elf_test.cpp @@ -23,6 +23,7 @@ #include #include "get_test_data.h" +#include "read_apk.h" #include "test_util.h" #include "utils.h" @@ -63,14 +64,20 @@ TEST(read_elf, GetBuildIdFromNoteSection) { TEST(read_elf, GetBuildIdFromElfFile) { BuildId build_id; - ASSERT_EQ(ElfStatus::NO_ERROR, GetBuildIdFromElfFile(GetTestData(ELF_FILE), &build_id)); + ElfStatus status; + auto elf = ElfFile::Open(GetTestData(ELF_FILE), &status); + ASSERT_EQ(status, ElfStatus::NO_ERROR); + ASSERT_EQ(ElfStatus::NO_ERROR, elf->GetBuildId(&build_id)); ASSERT_EQ(build_id, BuildId(elf_file_build_id)); } TEST(read_elf, GetBuildIdFromEmbeddedElfFile) { BuildId build_id; - ASSERT_EQ(ElfStatus::NO_ERROR, GetBuildIdFromEmbeddedElfFile(GetTestData(APK_FILE), NATIVELIB_OFFSET_IN_APK, - NATIVELIB_SIZE_IN_APK, &build_id)); + ElfStatus status; + std::string path = GetUrlInApk(APK_FILE, NATIVELIB_IN_APK); + auto elf = ElfFile::Open(GetTestData(path), &status); + ASSERT_EQ(status, ElfStatus::NO_ERROR); + ASSERT_EQ(ElfStatus::NO_ERROR, elf->GetBuildId(&build_id)); ASSERT_EQ(build_id, native_lib_build_id); } @@ -167,7 +174,10 @@ TEST(read_elf, read_elf_with_broken_section_table) { ParseSymbolsFromElfFile(elf_path, BuildId(), std::bind(ParseSymbol, std::placeholders::_1, &symbols))); BuildId build_id; - ASSERT_EQ(ElfStatus::NO_BUILD_ID, GetBuildIdFromElfFile(elf_path, &build_id)); + ElfStatus status; + auto elf = ElfFile::Open(elf_path, &status); + ASSERT_EQ(status, ElfStatus::NO_ERROR); + ASSERT_EQ(ElfStatus::NO_BUILD_ID, elf->GetBuildId(&build_id)); uint64_t min_vaddr; uint64_t file_offset_of_min_vaddr; ASSERT_EQ(ElfStatus::NO_ERROR, ReadMinExecutableVirtualAddressFromElfFile( -- cgit v1.2.3