123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585 |
- /*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- #include "read_elf.h"
- #include "read_apk.h"
- #include <stdio.h>
- #include <string.h>
- #include <sys/stat.h>
- #include <sys/types.h>
- #include <algorithm>
- #include <limits>
- #include <android-base/file.h>
- #include <android-base/logging.h>
- #pragma clang diagnostic push
- #pragma clang diagnostic ignored "-Wunused-parameter"
- #include <llvm/ADT/StringRef.h>
- #include <llvm/Object/Binary.h>
- #include <llvm/Object/ELFObjectFile.h>
- #include <llvm/Object/ObjectFile.h>
- #pragma clang diagnostic pop
- #include "utils.h"
- #define ELF_NOTE_GNU "GNU"
- #define NT_GNU_BUILD_ID 3
- std::ostream& operator<<(std::ostream& os, const ElfStatus& status) {
- switch (status) {
- case ElfStatus::NO_ERROR:
- os << "No error";
- break;
- case ElfStatus::FILE_NOT_FOUND:
- os << "File not found";
- break;
- case ElfStatus::READ_FAILED:
- os << "Read failed";
- break;
- case ElfStatus::FILE_MALFORMED:
- os << "Malformed file";
- break;
- case ElfStatus::NO_SYMBOL_TABLE:
- os << "No symbol table";
- break;
- case ElfStatus::NO_BUILD_ID:
- os << "No build id";
- break;
- case ElfStatus::BUILD_ID_MISMATCH:
- os << "Build id mismatch";
- break;
- case ElfStatus::SECTION_NOT_FOUND:
- os << "Section not found";
- break;
- }
- return os;
- }
- bool IsValidElfFileMagic(const char* buf, size_t buf_size) {
- static const char elf_magic[] = {0x7f, 'E', 'L', 'F'};
- return (buf_size >= 4u && memcmp(buf, elf_magic, 4) == 0);
- }
- ElfStatus IsValidElfFile(int fd) {
- char buf[4];
- if (!android::base::ReadFully(fd, buf, 4)) {
- return ElfStatus::READ_FAILED;
- }
- return IsValidElfFileMagic(buf, 4) ? ElfStatus::NO_ERROR : ElfStatus::FILE_MALFORMED;
- }
- ElfStatus IsValidElfPath(const std::string& filename) {
- if (!IsRegularFile(filename)) {
- return ElfStatus::FILE_NOT_FOUND;
- }
- std::string mode = std::string("rb") + CLOSE_ON_EXEC_MODE;
- FILE* fp = fopen(filename.c_str(), mode.c_str());
- if (fp == nullptr) {
- return ElfStatus::READ_FAILED;
- }
- ElfStatus result = IsValidElfFile(fileno(fp));
- fclose(fp);
- return result;
- }
- bool GetBuildIdFromNoteSection(const char* section, size_t section_size, BuildId* build_id) {
- const char* p = section;
- const char* end = p + section_size;
- while (p < end) {
- if (p + 12 >= end) {
- return false;
- }
- uint32_t namesz;
- uint32_t descsz;
- uint32_t type;
- MoveFromBinaryFormat(namesz, p);
- MoveFromBinaryFormat(descsz, p);
- MoveFromBinaryFormat(type, p);
- namesz = Align(namesz, 4);
- descsz = Align(descsz, 4);
- if ((type == NT_GNU_BUILD_ID) && (p < end) && (strcmp(p, ELF_NOTE_GNU) == 0)) {
- const char* desc_start = p + namesz;
- const char* desc_end = desc_start + descsz;
- if (desc_start > p && desc_start < desc_end && desc_end <= end) {
- *build_id = BuildId(p + namesz, descsz);
- return true;
- } else {
- return false;
- }
- }
- p += namesz + descsz;
- }
- return false;
- }
- ElfStatus GetBuildIdFromNoteFile(const std::string& filename, BuildId* build_id) {
- std::string content;
- if (!android::base::ReadFileToString(filename, &content)) {
- return ElfStatus::READ_FAILED;
- }
- if (!GetBuildIdFromNoteSection(content.c_str(), content.size(), build_id)) {
- return ElfStatus::NO_BUILD_ID;
- }
- return ElfStatus::NO_ERROR;
- }
- template <class ELFT>
- ElfStatus GetBuildIdFromELFFile(const llvm::object::ELFObjectFile<ELFT>* elf, BuildId* build_id) {
- llvm::StringRef data = elf->getData();
- const char* binary_start = data.data();
- const char* binary_end = data.data() + data.size();
- for (auto it = elf->section_begin(); it != elf->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;
- }
- static ElfStatus GetBuildIdFromObjectFile(llvm::object::ObjectFile* obj, BuildId* build_id) {
- if (auto elf = llvm::dyn_cast<llvm::object::ELF32LEObjectFile>(obj)) {
- return GetBuildIdFromELFFile(elf, build_id);
- } else if (auto elf = llvm::dyn_cast<llvm::object::ELF64LEObjectFile>(obj)) {
- return GetBuildIdFromELFFile(elf, build_id);
- }
- return ElfStatus::FILE_MALFORMED;
- }
- struct BinaryWrapper {
- llvm::object::OwningBinary<llvm::object::Binary> binary;
- llvm::object::ObjectFile* obj;
- BinaryWrapper() : obj(nullptr) {
- }
- };
- static ElfStatus OpenObjectFile(const std::string& filename, uint64_t file_offset,
- uint64_t file_size, BinaryWrapper* wrapper) {
- android::base::unique_fd fd = FileHelper::OpenReadOnly(filename);
- if (fd == -1) {
- return ElfStatus::READ_FAILED;
- }
- if (file_size == 0) {
- file_size = GetFileSize(filename);
- if (file_size == 0) {
- return ElfStatus::READ_FAILED;
- }
- }
- auto buffer_or_err = llvm::MemoryBuffer::getOpenFileSlice(fd, filename, file_size, file_offset);
- if (!buffer_or_err) {
- return ElfStatus::READ_FAILED;
- }
- auto binary_or_err = llvm::object::createBinary(buffer_or_err.get()->getMemBufferRef());
- if (!binary_or_err) {
- return ElfStatus::READ_FAILED;
- }
- wrapper->binary = llvm::object::OwningBinary<llvm::object::Binary>(std::move(binary_or_err.get()),
- std::move(buffer_or_err.get()));
- wrapper->obj = llvm::dyn_cast<llvm::object::ObjectFile>(wrapper->binary.getBinary());
- if (wrapper->obj == nullptr) {
- return ElfStatus::FILE_MALFORMED;
- }
- return ElfStatus::NO_ERROR;
- }
- static ElfStatus OpenObjectFileInMemory(const char* data, size_t size, BinaryWrapper* wrapper) {
- auto buffer = llvm::MemoryBuffer::getMemBuffer(llvm::StringRef(data, size));
- auto binary_or_err = llvm::object::createBinary(buffer->getMemBufferRef());
- if (!binary_or_err) {
- return ElfStatus::FILE_MALFORMED;
- }
- wrapper->binary = llvm::object::OwningBinary<llvm::object::Binary>(std::move(binary_or_err.get()),
- std::move(buffer));
- wrapper->obj = llvm::dyn_cast<llvm::object::ObjectFile>(wrapper->binary.getBinary());
- if (wrapper->obj == nullptr) {
- return ElfStatus::FILE_MALFORMED;
- }
- return ElfStatus::NO_ERROR;
- }
- ElfStatus GetBuildIdFromElfFile(const std::string& filename, BuildId* build_id) {
- ElfStatus result = IsValidElfPath(filename);
- if (result != ElfStatus::NO_ERROR) {
- return result;
- }
- 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) {
- for (llvm::object::section_iterator it = elf->section_begin(); it != elf->section_end(); ++it) {
- llvm::StringRef name;
- if (it->getName(name) || name != section_name) {
- continue;
- }
- llvm::StringRef data;
- std::error_code err = it->getContents(data);
- if (err) {
- return ElfStatus::READ_FAILED;
- }
- *content = data;
- return ElfStatus::NO_ERROR;
- }
- return ElfStatus::SECTION_NOT_FOUND;
- }
- bool IsArmMappingSymbol(const char* name) {
- // Mapping symbols in arm, which are described in "ELF for ARM Architecture" and
- // "ELF for ARM 64-bit Architecture". The regular expression to match mapping symbol
- // is ^\$(a|d|t|x)(\..*)?$
- return name[0] == '$' && strchr("adtx", name[1]) != nullptr && (name[2] == '\0' || name[2] == '.');
- }
- void ReadSymbolTable(llvm::object::symbol_iterator sym_begin,
- llvm::object::symbol_iterator sym_end,
- const std::function<void(const ElfFileSymbol&)>& callback,
- bool is_arm,
- const llvm::object::section_iterator& section_end) {
- for (; sym_begin != sym_end; ++sym_begin) {
- ElfFileSymbol symbol;
- auto symbol_ref = static_cast<const llvm::object::ELFSymbolRef*>(&*sym_begin);
- llvm::Expected<llvm::object::section_iterator> section_it_or_err = symbol_ref->getSection();
- if (!section_it_or_err) {
- continue;
- }
- // Symbols in .dynsym section don't have associated section.
- if (section_it_or_err.get() != section_end) {
- llvm::StringRef section_name;
- if (section_it_or_err.get()->getName(section_name) || section_name.empty()) {
- continue;
- }
- if (section_name == ".text") {
- symbol.is_in_text_section = true;
- }
- }
- llvm::Expected<llvm::StringRef> symbol_name_or_err = symbol_ref->getName();
- if (!symbol_name_or_err || symbol_name_or_err.get().empty()) {
- continue;
- }
- symbol.name = symbol_name_or_err.get();
- symbol.vaddr = symbol_ref->getValue();
- if ((symbol.vaddr & 1) != 0 && is_arm) {
- // Arm sets bit 0 to mark it as thumb code, remove the flag.
- symbol.vaddr &= ~1;
- }
- symbol.len = symbol_ref->getSize();
- llvm::object::SymbolRef::Type symbol_type = *symbol_ref->getType();
- if (symbol_type == llvm::object::SymbolRef::ST_Function) {
- symbol.is_func = true;
- } else if (symbol_type == llvm::object::SymbolRef::ST_Unknown) {
- if (symbol.is_in_text_section) {
- symbol.is_label = true;
- if (is_arm) {
- // Remove mapping symbols in arm.
- const char* p = (symbol.name.compare(0, linker_prefix.size(), linker_prefix) == 0)
- ? symbol.name.c_str() + linker_prefix.size()
- : symbol.name.c_str();
- if (IsArmMappingSymbol(p)) {
- symbol.is_label = false;
- }
- }
- }
- }
- callback(symbol);
- }
- }
- template <class ELFT>
- void AddSymbolForPltSection(const llvm::object::ELFObjectFile<ELFT>* elf,
- const std::function<void(const ElfFileSymbol&)>& callback) {
- // We may sample instructions in .plt section if the program
- // calls functions from shared libraries. Different architectures use
- // different formats to store .plt section, so it needs a lot of work to match
- // instructions in .plt section to symbols. As samples in .plt section rarely
- // happen, and .plt section can hardly be a performance bottleneck, we can
- // just use a symbol @plt to represent instructions in .plt section.
- for (auto it = elf->section_begin(); it != elf->section_end(); ++it) {
- const llvm::object::ELFSectionRef& section_ref = *it;
- llvm::StringRef section_name;
- std::error_code err = section_ref.getName(section_name);
- if (err || section_name != ".plt") {
- continue;
- }
- const auto* shdr = elf->getSection(section_ref.getRawDataRefImpl());
- if (shdr == nullptr) {
- return;
- }
- ElfFileSymbol symbol;
- symbol.vaddr = shdr->sh_addr;
- symbol.len = shdr->sh_size;
- symbol.is_func = true;
- symbol.is_label = true;
- symbol.is_in_text_section = true;
- symbol.name = "@plt";
- callback(symbol);
- return;
- }
- }
- template <class ELFT>
- void CheckSymbolSections(const llvm::object::ELFObjectFile<ELFT>* elf,
- bool* has_symtab, bool* has_dynsym) {
- *has_symtab = false;
- *has_dynsym = false;
- for (auto it = elf->section_begin(); it != elf->section_end(); ++it) {
- const llvm::object::ELFSectionRef& section_ref = *it;
- llvm::StringRef section_name;
- std::error_code err = section_ref.getName(section_name);
- if (err) {
- continue;
- }
- if (section_name == ".dynsym") {
- *has_dynsym = true;
- } else if (section_name == ".symtab") {
- *has_symtab = true;
- }
- }
- }
- template <class ELFT>
- ElfStatus ParseSymbolsFromELFFile(const llvm::object::ELFObjectFile<ELFT>* elf,
- const std::function<void(const ElfFileSymbol&)>& callback) {
- auto machine = elf->getELFFile()->getHeader()->e_machine;
- bool is_arm = (machine == llvm::ELF::EM_ARM || machine == llvm::ELF::EM_AARCH64);
- AddSymbolForPltSection(elf, callback);
- // Some applications deliberately ship elf files with broken section tables.
- // So check the existence of .symtab section and .dynsym section before reading symbols.
- bool has_symtab;
- bool has_dynsym;
- CheckSymbolSections(elf, &has_symtab, &has_dynsym);
- if (has_symtab && elf->symbol_begin() != elf->symbol_end()) {
- ReadSymbolTable(elf->symbol_begin(), elf->symbol_end(), callback, is_arm, elf->section_end());
- return ElfStatus::NO_ERROR;
- } else if (has_dynsym &&
- elf->dynamic_symbol_begin()->getRawDataRefImpl() != llvm::object::DataRefImpl()) {
- ReadSymbolTable(elf->dynamic_symbol_begin(), elf->dynamic_symbol_end(), callback, is_arm,
- elf->section_end());
- }
- std::string debugdata;
- ElfStatus result = ReadSectionFromELFFile(elf, ".gnu_debugdata", &debugdata);
- if (result == ElfStatus::SECTION_NOT_FOUND) {
- return ElfStatus::NO_SYMBOL_TABLE;
- } else if (result == ElfStatus::NO_ERROR) {
- std::string decompressed_data;
- if (XzDecompress(debugdata, &decompressed_data)) {
- BinaryWrapper wrapper;
- result = OpenObjectFileInMemory(decompressed_data.data(), decompressed_data.size(),
- &wrapper);
- if (result == ElfStatus::NO_ERROR) {
- if (auto elf = llvm::dyn_cast<llvm::object::ELF32LEObjectFile>(wrapper.obj)) {
- return ParseSymbolsFromELFFile(elf, callback);
- } else if (auto elf = llvm::dyn_cast<llvm::object::ELF64LEObjectFile>(wrapper.obj)) {
- return ParseSymbolsFromELFFile(elf, callback);
- } else {
- return ElfStatus::FILE_MALFORMED;
- }
- }
- }
- }
- return result;
- }
- ElfStatus MatchBuildId(llvm::object::ObjectFile* obj, const BuildId& expected_build_id) {
- if (expected_build_id.IsEmpty()) {
- return ElfStatus::NO_ERROR;
- }
- BuildId real_build_id;
- ElfStatus result = GetBuildIdFromObjectFile(obj, &real_build_id);
- if (result != ElfStatus::NO_ERROR) {
- return result;
- }
- if (expected_build_id != real_build_id) {
- return ElfStatus::BUILD_ID_MISMATCH;
- }
- return ElfStatus::NO_ERROR;
- }
- ElfStatus ParseSymbolsFromElfFile(const std::string& filename,
- const BuildId& expected_build_id,
- const std::function<void(const ElfFileSymbol&)>& callback) {
- ElfStatus result = IsValidElfPath(filename);
- if (result != ElfStatus::NO_ERROR) {
- return result;
- }
- return ParseSymbolsFromEmbeddedElfFile(filename, 0, 0, expected_build_id, callback);
- }
- ElfStatus ParseSymbolsFromEmbeddedElfFile(const std::string& filename, uint64_t file_offset,
- uint32_t file_size, const BuildId& expected_build_id,
- const std::function<void(const ElfFileSymbol&)>& callback) {
- BinaryWrapper wrapper;
- ElfStatus result = OpenObjectFile(filename, file_offset, file_size, &wrapper);
- if (result != ElfStatus::NO_ERROR) {
- return result;
- }
- result = MatchBuildId(wrapper.obj, expected_build_id);
- if (result != ElfStatus::NO_ERROR) {
- return result;
- }
- if (auto elf = llvm::dyn_cast<llvm::object::ELF32LEObjectFile>(wrapper.obj)) {
- return ParseSymbolsFromELFFile(elf, callback);
- } else if (auto elf = llvm::dyn_cast<llvm::object::ELF64LEObjectFile>(wrapper.obj)) {
- return ParseSymbolsFromELFFile(elf, callback);
- }
- return ElfStatus::FILE_MALFORMED;
- }
- ElfStatus ParseSymbolsFromElfFileInMemory(const char* data, size_t size,
- const std::function<void(const ElfFileSymbol&)>& callback) {
- BinaryWrapper wrapper;
- ElfStatus result = OpenObjectFileInMemory(data, size, &wrapper);
- if (result != ElfStatus::NO_ERROR) {
- return result;
- }
- if (auto elf = llvm::dyn_cast<llvm::object::ELF32LEObjectFile>(wrapper.obj)) {
- return ParseSymbolsFromELFFile(elf, callback);
- } else if (auto elf = llvm::dyn_cast<llvm::object::ELF64LEObjectFile>(wrapper.obj)) {
- return ParseSymbolsFromELFFile(elf, callback);
- }
- return ElfStatus::FILE_MALFORMED;
- }
- template <class ELFT>
- ElfStatus ParseDynamicSymbolsFromELFFile(const llvm::object::ELFObjectFile<ELFT>* elf,
- const std::function<void(const ElfFileSymbol&)>& callback) {
- auto machine = elf->getELFFile()->getHeader()->e_machine;
- bool is_arm = (machine == llvm::ELF::EM_ARM || machine == llvm::ELF::EM_AARCH64);
- ReadSymbolTable(elf->dynamic_symbol_begin(), elf->dynamic_symbol_end(), callback, is_arm,
- elf->section_end());
- return ElfStatus::NO_ERROR;
- }
- ElfStatus ParseDynamicSymbolsFromElfFile(const std::string& filename,
- const std::function<void(const ElfFileSymbol&)>& callback) {
- BinaryWrapper wrapper;
- ElfStatus result = OpenObjectFile(filename, 0, 0, &wrapper);
- if (result != ElfStatus::NO_ERROR) {
- return result;
- }
- if (auto elf = llvm::dyn_cast<llvm::object::ELF32LEObjectFile>(wrapper.obj)) {
- return ParseDynamicSymbolsFromELFFile(elf, callback);
- } else if (auto elf = llvm::dyn_cast<llvm::object::ELF64LEObjectFile>(wrapper.obj)) {
- return ParseDynamicSymbolsFromELFFile(elf, callback);
- }
- return ElfStatus::FILE_MALFORMED;
- }
- template <class ELFT>
- ElfStatus ReadMinExecutableVirtualAddress(const llvm::object::ELFFile<ELFT>* elf,
- uint64_t* p_vaddr,
- uint64_t* file_offset) {
- bool has_vaddr = false;
- uint64_t min_addr = std::numeric_limits<uint64_t>::max();
- for (auto it = elf->program_header_begin(); it != elf->program_header_end(); ++it) {
- if ((it->p_type == llvm::ELF::PT_LOAD) && (it->p_flags & llvm::ELF::PF_X)) {
- if (it->p_vaddr < min_addr) {
- min_addr = it->p_vaddr;
- *file_offset = it->p_offset;
- has_vaddr = true;
- }
- }
- }
- if (!has_vaddr) {
- // JIT symfiles don't have program headers.
- min_addr = 0;
- *file_offset = 0;
- }
- *p_vaddr = min_addr;
- return ElfStatus::NO_ERROR;
- }
- ElfStatus ReadMinExecutableVirtualAddressFromElfFile(const std::string& filename,
- const BuildId& expected_build_id,
- uint64_t* min_vaddr,
- uint64_t* file_offset_of_min_vaddr) {
- ElfStatus result = IsValidElfPath(filename);
- if (result != ElfStatus::NO_ERROR) {
- return result;
- }
- return ReadMinExecutableVirtualAddressFromEmbeddedElfFile(filename, 0, 0, expected_build_id,
- min_vaddr, file_offset_of_min_vaddr);
- }
- ElfStatus ReadMinExecutableVirtualAddressFromEmbeddedElfFile(const std::string& filename,
- uint64_t file_offset,
- uint32_t file_size,
- const BuildId& expected_build_id,
- uint64_t* min_vaddr,
- uint64_t* file_offset_of_min_vaddr) {
- BinaryWrapper wrapper;
- ElfStatus result = OpenObjectFile(filename, file_offset, file_size, &wrapper);
- if (result != ElfStatus::NO_ERROR) {
- return result;
- }
- result = MatchBuildId(wrapper.obj, expected_build_id);
- if (result != ElfStatus::NO_ERROR) {
- return result;
- }
- if (auto elf = llvm::dyn_cast<llvm::object::ELF32LEObjectFile>(wrapper.obj)) {
- return ReadMinExecutableVirtualAddress(elf->getELFFile(), min_vaddr, file_offset_of_min_vaddr);
- } else if (auto elf = llvm::dyn_cast<llvm::object::ELF64LEObjectFile>(wrapper.obj)) {
- return ReadMinExecutableVirtualAddress(elf->getELFFile(), min_vaddr, file_offset_of_min_vaddr);
- }
- return ElfStatus::FILE_MALFORMED;
- }
- ElfStatus ReadSectionFromElfFile(const std::string& filename, const std::string& section_name,
- std::string* content) {
- ElfStatus result = IsValidElfPath(filename);
- if (result != ElfStatus::NO_ERROR) {
- return result;
- }
- BinaryWrapper wrapper;
- result = OpenObjectFile(filename, 0, 0, &wrapper);
- if (result != ElfStatus::NO_ERROR) {
- return result;
- }
- if (auto elf = llvm::dyn_cast<llvm::object::ELF32LEObjectFile>(wrapper.obj)) {
- return ReadSectionFromELFFile(elf, section_name, content);
- } else if (auto elf = llvm::dyn_cast<llvm::object::ELF64LEObjectFile>(wrapper.obj)) {
- return ReadSectionFromELFFile(elf, section_name, content);
- } else {
- return ElfStatus::FILE_MALFORMED;
- }
- }
|