summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--simpleperf/dso.cpp24
-rw-r--r--simpleperf/read_elf.cpp48
-rw-r--r--simpleperf/read_elf.h4
-rw-r--r--simpleperf/read_elf_test.cpp18
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 <class ELFT>
ElfStatus ReadSectionFromELFFile(const llvm::object::ELFObjectFile<ELFT>* elf, const std::string& section_name,
std::string* content) {
@@ -571,10 +557,10 @@ template <typename T>
class ElfFileImpl {};
template <typename ELFT>
-class ElfFileImpl<llvm::object::ELFFile<ELFT>> : public ElfFile {
+class ElfFileImpl<llvm::object::ELFObjectFile<ELFT>> : public ElfFile {
public:
- ElfFileImpl(BinaryWrapper&& wrapper, const llvm::object::ELFFile<ELFT>* elf)
- : wrapper_(std::move(wrapper)), elf_(elf) {}
+ ElfFileImpl(BinaryWrapper&& wrapper, const llvm::object::ELFObjectFile<ELFT>* 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<llvm::object::ELFFile<ELFT>> : 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<ELFT>* elf_obj_;
const llvm::object::ELFFile<ELFT>* elf_;
};
@@ -622,14 +630,12 @@ std::unique_ptr<ElfFile> ElfFile::Open(const std::string& filename, ElfStatus* s
}
if (*status == ElfStatus::NO_ERROR) {
if (auto obj = llvm::dyn_cast<llvm::object::ELF32LEObjectFile>(wrapper.obj)) {
- using elf_t = std::decay_t<decltype(*obj->getELFFile())>;
return std::unique_ptr<ElfFile>(
- new ElfFileImpl<elf_t>(std::move(wrapper), obj->getELFFile()));
+ new ElfFileImpl<llvm::object::ELF32LEObjectFile>(std::move(wrapper), obj));
}
if (auto obj = llvm::dyn_cast<llvm::object::ELF64LEObjectFile>(wrapper.obj)) {
- using elf_t = std::decay_t<decltype(*obj->getELFFile())>;
return std::unique_ptr<ElfFile>(
- new ElfFileImpl<elf_t>(std::move(wrapper), obj->getELFFile()));
+ new ElfFileImpl<llvm::object::ELF64LEObjectFile>(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<ElfSegment> 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 <android-base/file.h>
#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(