18f6225147c5b6cb2159a7f5cb0dab952ee0759dfYabin Cui/* 28f6225147c5b6cb2159a7f5cb0dab952ee0759dfYabin Cui * Copyright (C) 2015 The Android Open Source Project 38f6225147c5b6cb2159a7f5cb0dab952ee0759dfYabin Cui * 48f6225147c5b6cb2159a7f5cb0dab952ee0759dfYabin Cui * Licensed under the Apache License, Version 2.0 (the "License"); 58f6225147c5b6cb2159a7f5cb0dab952ee0759dfYabin Cui * you may not use this file except in compliance with the License. 68f6225147c5b6cb2159a7f5cb0dab952ee0759dfYabin Cui * You may obtain a copy of the License at 78f6225147c5b6cb2159a7f5cb0dab952ee0759dfYabin Cui * 88f6225147c5b6cb2159a7f5cb0dab952ee0759dfYabin Cui * http://www.apache.org/licenses/LICENSE-2.0 98f6225147c5b6cb2159a7f5cb0dab952ee0759dfYabin Cui * 108f6225147c5b6cb2159a7f5cb0dab952ee0759dfYabin Cui * Unless required by applicable law or agreed to in writing, software 118f6225147c5b6cb2159a7f5cb0dab952ee0759dfYabin Cui * distributed under the License is distributed on an "AS IS" BASIS, 128f6225147c5b6cb2159a7f5cb0dab952ee0759dfYabin Cui * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 138f6225147c5b6cb2159a7f5cb0dab952ee0759dfYabin Cui * See the License for the specific language governing permissions and 148f6225147c5b6cb2159a7f5cb0dab952ee0759dfYabin Cui * limitations under the License. 158f6225147c5b6cb2159a7f5cb0dab952ee0759dfYabin Cui */ 168f6225147c5b6cb2159a7f5cb0dab952ee0759dfYabin Cui 178f6225147c5b6cb2159a7f5cb0dab952ee0759dfYabin Cui#include "read_elf.h" 18f831e6d12ca2298cb34b155a9d91ef002d0482f3Than McIntosh#include "read_apk.h" 198f6225147c5b6cb2159a7f5cb0dab952ee0759dfYabin Cui 208f6225147c5b6cb2159a7f5cb0dab952ee0759dfYabin Cui#include <stdio.h> 218f6225147c5b6cb2159a7f5cb0dab952ee0759dfYabin Cui#include <string.h> 22f831e6d12ca2298cb34b155a9d91ef002d0482f3Than McIntosh#include <sys/stat.h> 23f831e6d12ca2298cb34b155a9d91ef002d0482f3Than McIntosh#include <sys/types.h> 24547c60e4dd29c5788d5948ad348acf33a55d6ed6Yabin Cui 258f6225147c5b6cb2159a7f5cb0dab952ee0759dfYabin Cui#include <algorithm> 26547c60e4dd29c5788d5948ad348acf33a55d6ed6Yabin Cui#include <limits> 27547c60e4dd29c5788d5948ad348acf33a55d6ed6Yabin Cui 2866dd09e8e2407082ce93bf0784de641298131912Elliott Hughes#include <android-base/file.h> 2966dd09e8e2407082ce93bf0784de641298131912Elliott Hughes#include <android-base/logging.h> 308f6225147c5b6cb2159a7f5cb0dab952ee0759dfYabin Cui 318f6225147c5b6cb2159a7f5cb0dab952ee0759dfYabin Cui#pragma clang diagnostic push 328f6225147c5b6cb2159a7f5cb0dab952ee0759dfYabin Cui#pragma clang diagnostic ignored "-Wunused-parameter" 338f6225147c5b6cb2159a7f5cb0dab952ee0759dfYabin Cui 348f6225147c5b6cb2159a7f5cb0dab952ee0759dfYabin Cui#include <llvm/ADT/StringRef.h> 358f6225147c5b6cb2159a7f5cb0dab952ee0759dfYabin Cui#include <llvm/Object/Binary.h> 368f6225147c5b6cb2159a7f5cb0dab952ee0759dfYabin Cui#include <llvm/Object/ELFObjectFile.h> 378f6225147c5b6cb2159a7f5cb0dab952ee0759dfYabin Cui#include <llvm/Object/ObjectFile.h> 388f6225147c5b6cb2159a7f5cb0dab952ee0759dfYabin Cui 398f6225147c5b6cb2159a7f5cb0dab952ee0759dfYabin Cui#pragma clang diagnostic pop 408f6225147c5b6cb2159a7f5cb0dab952ee0759dfYabin Cui 418f6225147c5b6cb2159a7f5cb0dab952ee0759dfYabin Cui#include "utils.h" 428f6225147c5b6cb2159a7f5cb0dab952ee0759dfYabin Cui 43a5bdf0a31dc6e225c10b82840903de49535bf8fbYabin Cui#define ELF_NOTE_GNU "GNU" 44a5bdf0a31dc6e225c10b82840903de49535bf8fbYabin Cui#define NT_GNU_BUILD_ID 3 45a5bdf0a31dc6e225c10b82840903de49535bf8fbYabin Cui 46dec43c18d06415a955b8f32355bca925be901905Yabin Cuistd::ostream& operator<<(std::ostream& os, const ElfStatus& status) { 47dec43c18d06415a955b8f32355bca925be901905Yabin Cui switch (status) { 48dec43c18d06415a955b8f32355bca925be901905Yabin Cui case ElfStatus::NO_ERROR: 49dec43c18d06415a955b8f32355bca925be901905Yabin Cui os << "No error"; 50dec43c18d06415a955b8f32355bca925be901905Yabin Cui break; 51dec43c18d06415a955b8f32355bca925be901905Yabin Cui case ElfStatus::FILE_NOT_FOUND: 52dec43c18d06415a955b8f32355bca925be901905Yabin Cui os << "File not found"; 53dec43c18d06415a955b8f32355bca925be901905Yabin Cui break; 54dec43c18d06415a955b8f32355bca925be901905Yabin Cui case ElfStatus::READ_FAILED: 55dec43c18d06415a955b8f32355bca925be901905Yabin Cui os << "Read failed"; 56dec43c18d06415a955b8f32355bca925be901905Yabin Cui break; 57dec43c18d06415a955b8f32355bca925be901905Yabin Cui case ElfStatus::FILE_MALFORMED: 58dec43c18d06415a955b8f32355bca925be901905Yabin Cui os << "Malformed file"; 59dec43c18d06415a955b8f32355bca925be901905Yabin Cui break; 60dec43c18d06415a955b8f32355bca925be901905Yabin Cui case ElfStatus::NO_SYMBOL_TABLE: 61dec43c18d06415a955b8f32355bca925be901905Yabin Cui os << "No symbol table"; 62dec43c18d06415a955b8f32355bca925be901905Yabin Cui break; 63dec43c18d06415a955b8f32355bca925be901905Yabin Cui case ElfStatus::NO_BUILD_ID: 64dec43c18d06415a955b8f32355bca925be901905Yabin Cui os << "No build id"; 65dec43c18d06415a955b8f32355bca925be901905Yabin Cui break; 66dec43c18d06415a955b8f32355bca925be901905Yabin Cui case ElfStatus::BUILD_ID_MISMATCH: 67dec43c18d06415a955b8f32355bca925be901905Yabin Cui os << "Build id mismatch"; 68dec43c18d06415a955b8f32355bca925be901905Yabin Cui break; 69dec43c18d06415a955b8f32355bca925be901905Yabin Cui case ElfStatus::SECTION_NOT_FOUND: 70dec43c18d06415a955b8f32355bca925be901905Yabin Cui os << "Section not found"; 71dec43c18d06415a955b8f32355bca925be901905Yabin Cui break; 72dec43c18d06415a955b8f32355bca925be901905Yabin Cui } 73dec43c18d06415a955b8f32355bca925be901905Yabin Cui return os; 74dec43c18d06415a955b8f32355bca925be901905Yabin Cui} 75f831e6d12ca2298cb34b155a9d91ef002d0482f3Than McIntosh 76dec43c18d06415a955b8f32355bca925be901905Yabin CuiElfStatus IsValidElfFile(int fd) { 77797116bfb9ad10d858086680c7465d65c399ef6eYabin Cui static const char elf_magic[] = {0x7f, 'E', 'L', 'F'}; 78f831e6d12ca2298cb34b155a9d91ef002d0482f3Than McIntosh char buf[4]; 79dec43c18d06415a955b8f32355bca925be901905Yabin Cui if (!android::base::ReadFully(fd, buf, 4)) { 80dec43c18d06415a955b8f32355bca925be901905Yabin Cui return ElfStatus::READ_FAILED; 81dec43c18d06415a955b8f32355bca925be901905Yabin Cui } 82dec43c18d06415a955b8f32355bca925be901905Yabin Cui if (memcmp(buf, elf_magic, 4) != 0) { 83dec43c18d06415a955b8f32355bca925be901905Yabin Cui return ElfStatus::FILE_MALFORMED; 84dec43c18d06415a955b8f32355bca925be901905Yabin Cui } 85dec43c18d06415a955b8f32355bca925be901905Yabin Cui return ElfStatus::NO_ERROR; 86f831e6d12ca2298cb34b155a9d91ef002d0482f3Than McIntosh} 87f831e6d12ca2298cb34b155a9d91ef002d0482f3Than McIntosh 88dec43c18d06415a955b8f32355bca925be901905Yabin CuiElfStatus IsValidElfPath(const std::string& filename) { 89797116bfb9ad10d858086680c7465d65c399ef6eYabin Cui if (!IsRegularFile(filename)) { 90dec43c18d06415a955b8f32355bca925be901905Yabin Cui return ElfStatus::FILE_NOT_FOUND; 91797116bfb9ad10d858086680c7465d65c399ef6eYabin Cui } 92ffaa912ca48e87d25d516780c15cdd7c50de43dbYabin Cui std::string mode = std::string("rb") + CLOSE_ON_EXEC_MODE; 93ffaa912ca48e87d25d516780c15cdd7c50de43dbYabin Cui FILE* fp = fopen(filename.c_str(), mode.c_str()); 94a5b79fd2c1a255f587859621094c50882ea8c8d1Yabin Cui if (fp == nullptr) { 95dec43c18d06415a955b8f32355bca925be901905Yabin Cui return ElfStatus::READ_FAILED; 96a5b79fd2c1a255f587859621094c50882ea8c8d1Yabin Cui } 97dec43c18d06415a955b8f32355bca925be901905Yabin Cui ElfStatus result = IsValidElfFile(fileno(fp)); 98797116bfb9ad10d858086680c7465d65c399ef6eYabin Cui fclose(fp); 99f831e6d12ca2298cb34b155a9d91ef002d0482f3Than McIntosh return result; 100797116bfb9ad10d858086680c7465d65c399ef6eYabin Cui} 101797116bfb9ad10d858086680c7465d65c399ef6eYabin Cui 102f79a00874d415ba7e7fda01cf2eb76bf06e459a6Yabin Cuibool GetBuildIdFromNoteSection(const char* section, size_t section_size, BuildId* build_id) { 1038f6225147c5b6cb2159a7f5cb0dab952ee0759dfYabin Cui const char* p = section; 1048f6225147c5b6cb2159a7f5cb0dab952ee0759dfYabin Cui const char* end = p + section_size; 1058f6225147c5b6cb2159a7f5cb0dab952ee0759dfYabin Cui while (p < end) { 106f79a00874d415ba7e7fda01cf2eb76bf06e459a6Yabin Cui if (p + 12 >= end) { 107f79a00874d415ba7e7fda01cf2eb76bf06e459a6Yabin Cui return false; 108f79a00874d415ba7e7fda01cf2eb76bf06e459a6Yabin Cui } 109f79a00874d415ba7e7fda01cf2eb76bf06e459a6Yabin Cui uint32_t namesz; 110f79a00874d415ba7e7fda01cf2eb76bf06e459a6Yabin Cui uint32_t descsz; 111f79a00874d415ba7e7fda01cf2eb76bf06e459a6Yabin Cui uint32_t type; 112f79a00874d415ba7e7fda01cf2eb76bf06e459a6Yabin Cui MoveFromBinaryFormat(namesz, p); 113f79a00874d415ba7e7fda01cf2eb76bf06e459a6Yabin Cui MoveFromBinaryFormat(descsz, p); 114f79a00874d415ba7e7fda01cf2eb76bf06e459a6Yabin Cui MoveFromBinaryFormat(type, p); 115a7a0e5076f0107173bc9ee067d13955d0d169f25Yabin Cui namesz = Align(namesz, 4); 116a7a0e5076f0107173bc9ee067d13955d0d169f25Yabin Cui descsz = Align(descsz, 4); 117f79a00874d415ba7e7fda01cf2eb76bf06e459a6Yabin Cui if ((type == NT_GNU_BUILD_ID) && (p < end) && (strcmp(p, ELF_NOTE_GNU) == 0)) { 118f79a00874d415ba7e7fda01cf2eb76bf06e459a6Yabin Cui const char* desc_start = p + namesz; 119f79a00874d415ba7e7fda01cf2eb76bf06e459a6Yabin Cui const char* desc_end = desc_start + descsz; 120f79a00874d415ba7e7fda01cf2eb76bf06e459a6Yabin Cui if (desc_start > p && desc_start < desc_end && desc_end <= end) { 121f79a00874d415ba7e7fda01cf2eb76bf06e459a6Yabin Cui *build_id = BuildId(p + namesz, descsz); 122f79a00874d415ba7e7fda01cf2eb76bf06e459a6Yabin Cui return true; 123f79a00874d415ba7e7fda01cf2eb76bf06e459a6Yabin Cui } else { 124f79a00874d415ba7e7fda01cf2eb76bf06e459a6Yabin Cui return false; 125f79a00874d415ba7e7fda01cf2eb76bf06e459a6Yabin Cui } 1268f6225147c5b6cb2159a7f5cb0dab952ee0759dfYabin Cui } 1278f6225147c5b6cb2159a7f5cb0dab952ee0759dfYabin Cui p += namesz + descsz; 1288f6225147c5b6cb2159a7f5cb0dab952ee0759dfYabin Cui } 1298f6225147c5b6cb2159a7f5cb0dab952ee0759dfYabin Cui return false; 1308f6225147c5b6cb2159a7f5cb0dab952ee0759dfYabin Cui} 1318f6225147c5b6cb2159a7f5cb0dab952ee0759dfYabin Cui 132dec43c18d06415a955b8f32355bca925be901905Yabin CuiElfStatus GetBuildIdFromNoteFile(const std::string& filename, BuildId* build_id) { 1338f6225147c5b6cb2159a7f5cb0dab952ee0759dfYabin Cui std::string content; 1348f6225147c5b6cb2159a7f5cb0dab952ee0759dfYabin Cui if (!android::base::ReadFileToString(filename, &content)) { 135dec43c18d06415a955b8f32355bca925be901905Yabin Cui return ElfStatus::READ_FAILED; 1368f6225147c5b6cb2159a7f5cb0dab952ee0759dfYabin Cui } 137dec43c18d06415a955b8f32355bca925be901905Yabin Cui if (!GetBuildIdFromNoteSection(content.c_str(), content.size(), build_id)) { 138dec43c18d06415a955b8f32355bca925be901905Yabin Cui return ElfStatus::NO_BUILD_ID; 1398f6225147c5b6cb2159a7f5cb0dab952ee0759dfYabin Cui } 140dec43c18d06415a955b8f32355bca925be901905Yabin Cui return ElfStatus::NO_ERROR; 1418f6225147c5b6cb2159a7f5cb0dab952ee0759dfYabin Cui} 1428f6225147c5b6cb2159a7f5cb0dab952ee0759dfYabin Cui 1438f6225147c5b6cb2159a7f5cb0dab952ee0759dfYabin Cuitemplate <class ELFT> 144dec43c18d06415a955b8f32355bca925be901905Yabin CuiElfStatus GetBuildIdFromELFFile(const llvm::object::ELFObjectFile<ELFT>* elf, BuildId* build_id) { 14505400539d15c50a52a388daba2e831b86824cc8eYabin Cui for (auto it = elf->section_begin(); it != elf->section_end(); ++it) { 14605400539d15c50a52a388daba2e831b86824cc8eYabin Cui const llvm::object::ELFSectionRef& section_ref = *it; 14705400539d15c50a52a388daba2e831b86824cc8eYabin Cui if (section_ref.getType() == llvm::ELF::SHT_NOTE) { 14805400539d15c50a52a388daba2e831b86824cc8eYabin Cui llvm::StringRef data; 14905400539d15c50a52a388daba2e831b86824cc8eYabin Cui if (it->getContents(data)) { 150dec43c18d06415a955b8f32355bca925be901905Yabin Cui return ElfStatus::READ_FAILED; 1518f6225147c5b6cb2159a7f5cb0dab952ee0759dfYabin Cui } 152ae56a5fe174cd2decfcac2ea8634cab88d5180faDimitry Ivanov if (GetBuildIdFromNoteSection(data.data(), data.size(), build_id)) { 153dec43c18d06415a955b8f32355bca925be901905Yabin Cui return ElfStatus::NO_ERROR; 1548f6225147c5b6cb2159a7f5cb0dab952ee0759dfYabin Cui } 1558f6225147c5b6cb2159a7f5cb0dab952ee0759dfYabin Cui } 1568f6225147c5b6cb2159a7f5cb0dab952ee0759dfYabin Cui } 157dec43c18d06415a955b8f32355bca925be901905Yabin Cui return ElfStatus::NO_BUILD_ID; 1588f6225147c5b6cb2159a7f5cb0dab952ee0759dfYabin Cui} 1598f6225147c5b6cb2159a7f5cb0dab952ee0759dfYabin Cui 160dec43c18d06415a955b8f32355bca925be901905Yabin Cuistatic ElfStatus GetBuildIdFromObjectFile(llvm::object::ObjectFile* obj, BuildId* build_id) { 161638c558339b7f1ae0ed95f64bcf7dbc5b238ed83Yabin Cui if (auto elf = llvm::dyn_cast<llvm::object::ELF32LEObjectFile>(obj)) { 162dec43c18d06415a955b8f32355bca925be901905Yabin Cui return GetBuildIdFromELFFile(elf, build_id); 163638c558339b7f1ae0ed95f64bcf7dbc5b238ed83Yabin Cui } else if (auto elf = llvm::dyn_cast<llvm::object::ELF64LEObjectFile>(obj)) { 164dec43c18d06415a955b8f32355bca925be901905Yabin Cui return GetBuildIdFromELFFile(elf, build_id); 165638c558339b7f1ae0ed95f64bcf7dbc5b238ed83Yabin Cui } 166dec43c18d06415a955b8f32355bca925be901905Yabin Cui return ElfStatus::FILE_MALFORMED; 167638c558339b7f1ae0ed95f64bcf7dbc5b238ed83Yabin Cui} 168638c558339b7f1ae0ed95f64bcf7dbc5b238ed83Yabin Cui 169dec43c18d06415a955b8f32355bca925be901905Yabin Cuistruct BinaryWrapper { 170b1a885b014540a2f7798b5a35ea0f0ec150d93eeYabin Cui llvm::object::OwningBinary<llvm::object::Binary> binary; 171b1a885b014540a2f7798b5a35ea0f0ec150d93eeYabin Cui llvm::object::ObjectFile* obj; 172b1a885b014540a2f7798b5a35ea0f0ec150d93eeYabin Cui 173dec43c18d06415a955b8f32355bca925be901905Yabin Cui BinaryWrapper() : obj(nullptr) { 174f831e6d12ca2298cb34b155a9d91ef002d0482f3Than McIntosh } 175b1a885b014540a2f7798b5a35ea0f0ec150d93eeYabin Cui}; 176b1a885b014540a2f7798b5a35ea0f0ec150d93eeYabin Cui 177dec43c18d06415a955b8f32355bca925be901905Yabin Cuistatic ElfStatus OpenObjectFile(const std::string& filename, uint64_t file_offset, 178dec43c18d06415a955b8f32355bca925be901905Yabin Cui uint64_t file_size, BinaryWrapper* wrapper) { 179be7ec66eaa4f995bd9068637f7c7d5718173922cYabin Cui FileHelper fhelper = FileHelper::OpenReadOnly(filename); 180b1a885b014540a2f7798b5a35ea0f0ec150d93eeYabin Cui if (!fhelper) { 181dec43c18d06415a955b8f32355bca925be901905Yabin Cui return ElfStatus::READ_FAILED; 182f831e6d12ca2298cb34b155a9d91ef002d0482f3Than McIntosh } 183b1a885b014540a2f7798b5a35ea0f0ec150d93eeYabin Cui if (file_size == 0) { 184b1a885b014540a2f7798b5a35ea0f0ec150d93eeYabin Cui file_size = GetFileSize(filename); 185b1a885b014540a2f7798b5a35ea0f0ec150d93eeYabin Cui if (file_size == 0) { 186dec43c18d06415a955b8f32355bca925be901905Yabin Cui return ElfStatus::READ_FAILED; 187b1a885b014540a2f7798b5a35ea0f0ec150d93eeYabin Cui } 188f831e6d12ca2298cb34b155a9d91ef002d0482f3Than McIntosh } 189b1a885b014540a2f7798b5a35ea0f0ec150d93eeYabin Cui auto buffer_or_err = llvm::MemoryBuffer::getOpenFileSlice(fhelper.fd(), filename, file_size, file_offset); 190b1a885b014540a2f7798b5a35ea0f0ec150d93eeYabin Cui if (!buffer_or_err) { 191dec43c18d06415a955b8f32355bca925be901905Yabin Cui return ElfStatus::READ_FAILED; 192b1a885b014540a2f7798b5a35ea0f0ec150d93eeYabin Cui } 193b1a885b014540a2f7798b5a35ea0f0ec150d93eeYabin Cui auto binary_or_err = llvm::object::createBinary(buffer_or_err.get()->getMemBufferRef()); 194b1a885b014540a2f7798b5a35ea0f0ec150d93eeYabin Cui if (!binary_or_err) { 195dec43c18d06415a955b8f32355bca925be901905Yabin Cui return ElfStatus::READ_FAILED; 196dec43c18d06415a955b8f32355bca925be901905Yabin Cui } 197dec43c18d06415a955b8f32355bca925be901905Yabin Cui wrapper->binary = llvm::object::OwningBinary<llvm::object::Binary>(std::move(binary_or_err.get()), 198dec43c18d06415a955b8f32355bca925be901905Yabin Cui std::move(buffer_or_err.get())); 199dec43c18d06415a955b8f32355bca925be901905Yabin Cui wrapper->obj = llvm::dyn_cast<llvm::object::ObjectFile>(wrapper->binary.getBinary()); 200dec43c18d06415a955b8f32355bca925be901905Yabin Cui if (wrapper->obj == nullptr) { 201dec43c18d06415a955b8f32355bca925be901905Yabin Cui return ElfStatus::FILE_MALFORMED; 202dec43c18d06415a955b8f32355bca925be901905Yabin Cui } 203dec43c18d06415a955b8f32355bca925be901905Yabin Cui return ElfStatus::NO_ERROR; 204f831e6d12ca2298cb34b155a9d91ef002d0482f3Than McIntosh} 205f831e6d12ca2298cb34b155a9d91ef002d0482f3Than McIntosh 206dec43c18d06415a955b8f32355bca925be901905Yabin Cuistatic ElfStatus OpenObjectFileFromString(const std::string& s, BinaryWrapper* wrapper) { 20705400539d15c50a52a388daba2e831b86824cc8eYabin Cui auto buffer = llvm::MemoryBuffer::getMemBuffer(s); 20805400539d15c50a52a388daba2e831b86824cc8eYabin Cui auto binary_or_err = llvm::object::createBinary(buffer->getMemBufferRef()); 20905400539d15c50a52a388daba2e831b86824cc8eYabin Cui if (!binary_or_err) { 210dec43c18d06415a955b8f32355bca925be901905Yabin Cui return ElfStatus::FILE_MALFORMED; 21105400539d15c50a52a388daba2e831b86824cc8eYabin Cui } 212dec43c18d06415a955b8f32355bca925be901905Yabin Cui wrapper->binary = llvm::object::OwningBinary<llvm::object::Binary>(std::move(binary_or_err.get()), 21305400539d15c50a52a388daba2e831b86824cc8eYabin Cui std::move(buffer)); 214dec43c18d06415a955b8f32355bca925be901905Yabin Cui wrapper->obj = llvm::dyn_cast<llvm::object::ObjectFile>(wrapper->binary.getBinary()); 215dec43c18d06415a955b8f32355bca925be901905Yabin Cui if (wrapper->obj == nullptr) { 216dec43c18d06415a955b8f32355bca925be901905Yabin Cui return ElfStatus::FILE_MALFORMED; 21705400539d15c50a52a388daba2e831b86824cc8eYabin Cui } 218dec43c18d06415a955b8f32355bca925be901905Yabin Cui return ElfStatus::NO_ERROR; 21905400539d15c50a52a388daba2e831b86824cc8eYabin Cui} 22005400539d15c50a52a388daba2e831b86824cc8eYabin Cui 221dec43c18d06415a955b8f32355bca925be901905Yabin CuiElfStatus GetBuildIdFromElfFile(const std::string& filename, BuildId* build_id) { 222dec43c18d06415a955b8f32355bca925be901905Yabin Cui ElfStatus result = IsValidElfPath(filename); 223dec43c18d06415a955b8f32355bca925be901905Yabin Cui if (result != ElfStatus::NO_ERROR) { 224dec43c18d06415a955b8f32355bca925be901905Yabin Cui return result; 225797116bfb9ad10d858086680c7465d65c399ef6eYabin Cui } 226dec43c18d06415a955b8f32355bca925be901905Yabin Cui return GetBuildIdFromEmbeddedElfFile(filename, 0, 0, build_id); 227b1a885b014540a2f7798b5a35ea0f0ec150d93eeYabin Cui} 228b1a885b014540a2f7798b5a35ea0f0ec150d93eeYabin Cui 229dec43c18d06415a955b8f32355bca925be901905Yabin CuiElfStatus GetBuildIdFromEmbeddedElfFile(const std::string& filename, uint64_t file_offset, 230dec43c18d06415a955b8f32355bca925be901905Yabin Cui uint32_t file_size, BuildId* build_id) { 231dec43c18d06415a955b8f32355bca925be901905Yabin Cui BinaryWrapper wrapper; 232dec43c18d06415a955b8f32355bca925be901905Yabin Cui ElfStatus result = OpenObjectFile(filename, file_offset, file_size, &wrapper); 233dec43c18d06415a955b8f32355bca925be901905Yabin Cui if (result != ElfStatus::NO_ERROR) { 234dec43c18d06415a955b8f32355bca925be901905Yabin Cui return result; 2358f6225147c5b6cb2159a7f5cb0dab952ee0759dfYabin Cui } 236dec43c18d06415a955b8f32355bca925be901905Yabin Cui return GetBuildIdFromObjectFile(wrapper.obj, build_id); 2378f6225147c5b6cb2159a7f5cb0dab952ee0759dfYabin Cui} 238a5bdf0a31dc6e225c10b82840903de49535bf8fbYabin Cui 23905400539d15c50a52a388daba2e831b86824cc8eYabin Cuitemplate <class ELFT> 240dec43c18d06415a955b8f32355bca925be901905Yabin CuiElfStatus ReadSectionFromELFFile(const llvm::object::ELFObjectFile<ELFT>* elf, const std::string& section_name, 241dec43c18d06415a955b8f32355bca925be901905Yabin Cui std::string* content) { 24205400539d15c50a52a388daba2e831b86824cc8eYabin Cui for (llvm::object::section_iterator it = elf->section_begin(); it != elf->section_end(); ++it) { 24305400539d15c50a52a388daba2e831b86824cc8eYabin Cui llvm::StringRef name; 24405400539d15c50a52a388daba2e831b86824cc8eYabin Cui if (it->getName(name) || name != section_name) { 24505400539d15c50a52a388daba2e831b86824cc8eYabin Cui continue; 24605400539d15c50a52a388daba2e831b86824cc8eYabin Cui } 24705400539d15c50a52a388daba2e831b86824cc8eYabin Cui llvm::StringRef data; 24805400539d15c50a52a388daba2e831b86824cc8eYabin Cui std::error_code err = it->getContents(data); 24905400539d15c50a52a388daba2e831b86824cc8eYabin Cui if (err) { 250dec43c18d06415a955b8f32355bca925be901905Yabin Cui return ElfStatus::READ_FAILED; 25105400539d15c50a52a388daba2e831b86824cc8eYabin Cui } 25205400539d15c50a52a388daba2e831b86824cc8eYabin Cui *content = data; 253dec43c18d06415a955b8f32355bca925be901905Yabin Cui return ElfStatus::NO_ERROR; 25405400539d15c50a52a388daba2e831b86824cc8eYabin Cui } 255dec43c18d06415a955b8f32355bca925be901905Yabin Cui return ElfStatus::SECTION_NOT_FOUND; 25605400539d15c50a52a388daba2e831b86824cc8eYabin Cui} 25705400539d15c50a52a388daba2e831b86824cc8eYabin Cui 258a5bdf0a31dc6e225c10b82840903de49535bf8fbYabin Cuibool IsArmMappingSymbol(const char* name) { 259a5bdf0a31dc6e225c10b82840903de49535bf8fbYabin Cui // Mapping symbols in arm, which are described in "ELF for ARM Architecture" and 260a5bdf0a31dc6e225c10b82840903de49535bf8fbYabin Cui // "ELF for ARM 64-bit Architecture". The regular expression to match mapping symbol 261a5bdf0a31dc6e225c10b82840903de49535bf8fbYabin Cui // is ^\$(a|d|t|x)(\..*)?$ 262a5bdf0a31dc6e225c10b82840903de49535bf8fbYabin Cui return name[0] == '$' && strchr("adtx", name[1]) != nullptr && (name[2] == '\0' || name[2] == '.'); 263a5bdf0a31dc6e225c10b82840903de49535bf8fbYabin Cui} 264a5bdf0a31dc6e225c10b82840903de49535bf8fbYabin Cui 26505400539d15c50a52a388daba2e831b86824cc8eYabin Cuivoid ReadSymbolTable(llvm::object::symbol_iterator sym_begin, 26605400539d15c50a52a388daba2e831b86824cc8eYabin Cui llvm::object::symbol_iterator sym_end, 2673e4c5950f3aafb0bf66544468d98ee3ec26b705cYabin Cui const std::function<void(const ElfFileSymbol&)>& callback, 26805400539d15c50a52a388daba2e831b86824cc8eYabin Cui bool is_arm) { 26905400539d15c50a52a388daba2e831b86824cc8eYabin Cui for (; sym_begin != sym_end; ++sym_begin) { 270ec12ed9010128483993a87d68edc02d3a89d56cfYabin Cui ElfFileSymbol symbol; 27105400539d15c50a52a388daba2e831b86824cc8eYabin Cui auto symbol_ref = static_cast<const llvm::object::ELFSymbolRef*>(&*sym_begin); 2720ea825032cf8f343f82257c7366fe1ea65f04fa9Pirama Arumuga Nainar llvm::Expected<llvm::object::section_iterator> section_it_or_err = symbol_ref->getSection(); 27305400539d15c50a52a388daba2e831b86824cc8eYabin Cui if (!section_it_or_err) { 274ec12ed9010128483993a87d68edc02d3a89d56cfYabin Cui continue; 275ec12ed9010128483993a87d68edc02d3a89d56cfYabin Cui } 27605400539d15c50a52a388daba2e831b86824cc8eYabin Cui 27707cdff03ffb5e69d73979e8c2f8585314751ee17Yabin Cui llvm::StringRef section_name; 27805400539d15c50a52a388daba2e831b86824cc8eYabin Cui if (section_it_or_err.get()->getName(section_name) || section_name.empty()) { 279ec12ed9010128483993a87d68edc02d3a89d56cfYabin Cui continue; 280ec12ed9010128483993a87d68edc02d3a89d56cfYabin Cui } 28105400539d15c50a52a388daba2e831b86824cc8eYabin Cui if (section_name == ".text") { 282ec12ed9010128483993a87d68edc02d3a89d56cfYabin Cui symbol.is_in_text_section = true; 283ec12ed9010128483993a87d68edc02d3a89d56cfYabin Cui } 2840ea825032cf8f343f82257c7366fe1ea65f04fa9Pirama Arumuga Nainar llvm::Expected<llvm::StringRef> symbol_name_or_err = symbol_ref->getName(); 28505400539d15c50a52a388daba2e831b86824cc8eYabin Cui if (!symbol_name_or_err || symbol_name_or_err.get().empty()) { 286ec12ed9010128483993a87d68edc02d3a89d56cfYabin Cui continue; 287ec12ed9010128483993a87d68edc02d3a89d56cfYabin Cui } 28805400539d15c50a52a388daba2e831b86824cc8eYabin Cui 28905400539d15c50a52a388daba2e831b86824cc8eYabin Cui symbol.name = symbol_name_or_err.get(); 29005400539d15c50a52a388daba2e831b86824cc8eYabin Cui symbol.vaddr = symbol_ref->getValue(); 291547c60e4dd29c5788d5948ad348acf33a55d6ed6Yabin Cui if ((symbol.vaddr & 1) != 0 && is_arm) { 292b378355f34b2b585eaf2be262bcd9baae9f3d36aYabin Cui // Arm sets bit 0 to mark it as thumb code, remove the flag. 293547c60e4dd29c5788d5948ad348acf33a55d6ed6Yabin Cui symbol.vaddr &= ~1; 294b378355f34b2b585eaf2be262bcd9baae9f3d36aYabin Cui } 29505400539d15c50a52a388daba2e831b86824cc8eYabin Cui symbol.len = symbol_ref->getSize(); 2960ea825032cf8f343f82257c7366fe1ea65f04fa9Pirama Arumuga Nainar llvm::object::SymbolRef::Type symbol_type = *symbol_ref->getType(); 29705400539d15c50a52a388daba2e831b86824cc8eYabin Cui if (symbol_type == llvm::object::SymbolRef::ST_Function) { 298b378355f34b2b585eaf2be262bcd9baae9f3d36aYabin Cui symbol.is_func = true; 29905400539d15c50a52a388daba2e831b86824cc8eYabin Cui } else if (symbol_type == llvm::object::SymbolRef::ST_Unknown) { 300b378355f34b2b585eaf2be262bcd9baae9f3d36aYabin Cui if (symbol.is_in_text_section) { 301b378355f34b2b585eaf2be262bcd9baae9f3d36aYabin Cui symbol.is_label = true; 3022c17e0db003baeb044bf3e13175f5d00c414c3fcYabin Cui if (is_arm) { 303a5bdf0a31dc6e225c10b82840903de49535bf8fbYabin Cui // Remove mapping symbols in arm. 304a5bdf0a31dc6e225c10b82840903de49535bf8fbYabin Cui const char* p = (symbol.name.compare(0, linker_prefix.size(), linker_prefix) == 0) 305a5bdf0a31dc6e225c10b82840903de49535bf8fbYabin Cui ? symbol.name.c_str() + linker_prefix.size() 306a5bdf0a31dc6e225c10b82840903de49535bf8fbYabin Cui : symbol.name.c_str(); 307a5bdf0a31dc6e225c10b82840903de49535bf8fbYabin Cui if (IsArmMappingSymbol(p)) { 3082c17e0db003baeb044bf3e13175f5d00c414c3fcYabin Cui symbol.is_label = false; 3092c17e0db003baeb044bf3e13175f5d00c414c3fcYabin Cui } 310b378355f34b2b585eaf2be262bcd9baae9f3d36aYabin Cui } 311b378355f34b2b585eaf2be262bcd9baae9f3d36aYabin Cui } 312b378355f34b2b585eaf2be262bcd9baae9f3d36aYabin Cui } 313b378355f34b2b585eaf2be262bcd9baae9f3d36aYabin Cui 314ec12ed9010128483993a87d68edc02d3a89d56cfYabin Cui callback(symbol); 315ec12ed9010128483993a87d68edc02d3a89d56cfYabin Cui } 316ec12ed9010128483993a87d68edc02d3a89d56cfYabin Cui} 317ec12ed9010128483993a87d68edc02d3a89d56cfYabin Cui 31805400539d15c50a52a388daba2e831b86824cc8eYabin Cuitemplate <class ELFT> 3195783fa0c4ac6a3faaa9191c8f8e3f2b9dc2ae2f0Yabin Cuivoid AddSymbolForPltSection(const llvm::object::ELFObjectFile<ELFT>* elf, 3203e4c5950f3aafb0bf66544468d98ee3ec26b705cYabin Cui const std::function<void(const ElfFileSymbol&)>& callback) { 3215783fa0c4ac6a3faaa9191c8f8e3f2b9dc2ae2f0Yabin Cui // We may sample instructions in .plt section if the program 3225783fa0c4ac6a3faaa9191c8f8e3f2b9dc2ae2f0Yabin Cui // calls functions from shared libraries. Different architectures use 3235783fa0c4ac6a3faaa9191c8f8e3f2b9dc2ae2f0Yabin Cui // different formats to store .plt section, so it needs a lot of work to match 3245783fa0c4ac6a3faaa9191c8f8e3f2b9dc2ae2f0Yabin Cui // instructions in .plt section to symbols. As samples in .plt section rarely 3255783fa0c4ac6a3faaa9191c8f8e3f2b9dc2ae2f0Yabin Cui // happen, and .plt section can hardly be a performance bottleneck, we can 3265783fa0c4ac6a3faaa9191c8f8e3f2b9dc2ae2f0Yabin Cui // just use a symbol @plt to represent instructions in .plt section. 3275783fa0c4ac6a3faaa9191c8f8e3f2b9dc2ae2f0Yabin Cui for (auto it = elf->section_begin(); it != elf->section_end(); ++it) { 3285783fa0c4ac6a3faaa9191c8f8e3f2b9dc2ae2f0Yabin Cui const llvm::object::ELFSectionRef& section_ref = *it; 3295783fa0c4ac6a3faaa9191c8f8e3f2b9dc2ae2f0Yabin Cui llvm::StringRef section_name; 3305783fa0c4ac6a3faaa9191c8f8e3f2b9dc2ae2f0Yabin Cui std::error_code err = section_ref.getName(section_name); 3315783fa0c4ac6a3faaa9191c8f8e3f2b9dc2ae2f0Yabin Cui if (err || section_name != ".plt") { 3325783fa0c4ac6a3faaa9191c8f8e3f2b9dc2ae2f0Yabin Cui continue; 3335783fa0c4ac6a3faaa9191c8f8e3f2b9dc2ae2f0Yabin Cui } 3345783fa0c4ac6a3faaa9191c8f8e3f2b9dc2ae2f0Yabin Cui const auto* shdr = elf->getSection(section_ref.getRawDataRefImpl()); 3355783fa0c4ac6a3faaa9191c8f8e3f2b9dc2ae2f0Yabin Cui if (shdr == nullptr) { 3365783fa0c4ac6a3faaa9191c8f8e3f2b9dc2ae2f0Yabin Cui return; 3375783fa0c4ac6a3faaa9191c8f8e3f2b9dc2ae2f0Yabin Cui } 3385783fa0c4ac6a3faaa9191c8f8e3f2b9dc2ae2f0Yabin Cui ElfFileSymbol symbol; 3395783fa0c4ac6a3faaa9191c8f8e3f2b9dc2ae2f0Yabin Cui symbol.vaddr = shdr->sh_addr; 3405783fa0c4ac6a3faaa9191c8f8e3f2b9dc2ae2f0Yabin Cui symbol.len = shdr->sh_size; 3415783fa0c4ac6a3faaa9191c8f8e3f2b9dc2ae2f0Yabin Cui symbol.is_func = true; 3425783fa0c4ac6a3faaa9191c8f8e3f2b9dc2ae2f0Yabin Cui symbol.is_label = true; 3435783fa0c4ac6a3faaa9191c8f8e3f2b9dc2ae2f0Yabin Cui symbol.is_in_text_section = true; 3445783fa0c4ac6a3faaa9191c8f8e3f2b9dc2ae2f0Yabin Cui symbol.name = "@plt"; 3455783fa0c4ac6a3faaa9191c8f8e3f2b9dc2ae2f0Yabin Cui callback(symbol); 3465783fa0c4ac6a3faaa9191c8f8e3f2b9dc2ae2f0Yabin Cui return; 3475783fa0c4ac6a3faaa9191c8f8e3f2b9dc2ae2f0Yabin Cui } 3485783fa0c4ac6a3faaa9191c8f8e3f2b9dc2ae2f0Yabin Cui} 3495783fa0c4ac6a3faaa9191c8f8e3f2b9dc2ae2f0Yabin Cui 3505783fa0c4ac6a3faaa9191c8f8e3f2b9dc2ae2f0Yabin Cuitemplate <class ELFT> 351dec43c18d06415a955b8f32355bca925be901905Yabin CuiElfStatus ParseSymbolsFromELFFile(const llvm::object::ELFObjectFile<ELFT>* elf, 352dec43c18d06415a955b8f32355bca925be901905Yabin Cui const std::function<void(const ElfFileSymbol&)>& callback) { 35305400539d15c50a52a388daba2e831b86824cc8eYabin Cui auto machine = elf->getELFFile()->getHeader()->e_machine; 35405400539d15c50a52a388daba2e831b86824cc8eYabin Cui bool is_arm = (machine == llvm::ELF::EM_ARM || machine == llvm::ELF::EM_AARCH64); 355dec43c18d06415a955b8f32355bca925be901905Yabin Cui AddSymbolForPltSection(elf, callback); 35605400539d15c50a52a388daba2e831b86824cc8eYabin Cui if (elf->symbol_begin() != elf->symbol_end()) { 35705400539d15c50a52a388daba2e831b86824cc8eYabin Cui ReadSymbolTable(elf->symbol_begin(), elf->symbol_end(), callback, is_arm); 358dec43c18d06415a955b8f32355bca925be901905Yabin Cui return ElfStatus::NO_ERROR; 35905400539d15c50a52a388daba2e831b86824cc8eYabin Cui } else if (elf->dynamic_symbol_begin()->getRawDataRefImpl() != llvm::object::DataRefImpl()) { 36005400539d15c50a52a388daba2e831b86824cc8eYabin Cui ReadSymbolTable(elf->dynamic_symbol_begin(), elf->dynamic_symbol_end(), callback, is_arm); 36105400539d15c50a52a388daba2e831b86824cc8eYabin Cui } 36205400539d15c50a52a388daba2e831b86824cc8eYabin Cui std::string debugdata; 363dec43c18d06415a955b8f32355bca925be901905Yabin Cui ElfStatus result = ReadSectionFromELFFile(elf, ".gnu_debugdata", &debugdata); 364dec43c18d06415a955b8f32355bca925be901905Yabin Cui if (result == ElfStatus::SECTION_NOT_FOUND) { 365dec43c18d06415a955b8f32355bca925be901905Yabin Cui return ElfStatus::NO_SYMBOL_TABLE; 366dec43c18d06415a955b8f32355bca925be901905Yabin Cui } else if (result == ElfStatus::NO_ERROR) { 36705400539d15c50a52a388daba2e831b86824cc8eYabin Cui std::string decompressed_data; 36805400539d15c50a52a388daba2e831b86824cc8eYabin Cui if (XzDecompress(debugdata, &decompressed_data)) { 369dec43c18d06415a955b8f32355bca925be901905Yabin Cui BinaryWrapper wrapper; 370dec43c18d06415a955b8f32355bca925be901905Yabin Cui result = OpenObjectFileFromString(decompressed_data, &wrapper); 371dec43c18d06415a955b8f32355bca925be901905Yabin Cui if (result == ElfStatus::NO_ERROR) { 372dec43c18d06415a955b8f32355bca925be901905Yabin Cui if (auto elf = llvm::dyn_cast<llvm::object::ELF32LEObjectFile>(wrapper.obj)) { 373dec43c18d06415a955b8f32355bca925be901905Yabin Cui return ParseSymbolsFromELFFile(elf, callback); 374dec43c18d06415a955b8f32355bca925be901905Yabin Cui } else if (auto elf = llvm::dyn_cast<llvm::object::ELF64LEObjectFile>(wrapper.obj)) { 375dec43c18d06415a955b8f32355bca925be901905Yabin Cui return ParseSymbolsFromELFFile(elf, callback); 376dec43c18d06415a955b8f32355bca925be901905Yabin Cui } else { 377dec43c18d06415a955b8f32355bca925be901905Yabin Cui return ElfStatus::FILE_MALFORMED; 37805400539d15c50a52a388daba2e831b86824cc8eYabin Cui } 37905400539d15c50a52a388daba2e831b86824cc8eYabin Cui } 38005400539d15c50a52a388daba2e831b86824cc8eYabin Cui } 38105400539d15c50a52a388daba2e831b86824cc8eYabin Cui } 382dec43c18d06415a955b8f32355bca925be901905Yabin Cui return result; 38305400539d15c50a52a388daba2e831b86824cc8eYabin Cui} 38405400539d15c50a52a388daba2e831b86824cc8eYabin Cui 385dec43c18d06415a955b8f32355bca925be901905Yabin CuiElfStatus MatchBuildId(llvm::object::ObjectFile* obj, const BuildId& expected_build_id) { 386b1a885b014540a2f7798b5a35ea0f0ec150d93eeYabin Cui if (expected_build_id.IsEmpty()) { 387dec43c18d06415a955b8f32355bca925be901905Yabin Cui return ElfStatus::NO_ERROR; 388ec12ed9010128483993a87d68edc02d3a89d56cfYabin Cui } 389b1a885b014540a2f7798b5a35ea0f0ec150d93eeYabin Cui BuildId real_build_id; 390dec43c18d06415a955b8f32355bca925be901905Yabin Cui ElfStatus result = GetBuildIdFromObjectFile(obj, &real_build_id); 391dec43c18d06415a955b8f32355bca925be901905Yabin Cui if (result != ElfStatus::NO_ERROR) { 392dec43c18d06415a955b8f32355bca925be901905Yabin Cui return result; 393ec12ed9010128483993a87d68edc02d3a89d56cfYabin Cui } 394b1a885b014540a2f7798b5a35ea0f0ec150d93eeYabin Cui if (expected_build_id != real_build_id) { 395dec43c18d06415a955b8f32355bca925be901905Yabin Cui return ElfStatus::BUILD_ID_MISMATCH; 396dec43c18d06415a955b8f32355bca925be901905Yabin Cui } 397dec43c18d06415a955b8f32355bca925be901905Yabin Cui return ElfStatus::NO_ERROR; 398547c60e4dd29c5788d5948ad348acf33a55d6ed6Yabin Cui} 399547c60e4dd29c5788d5948ad348acf33a55d6ed6Yabin Cui 400dec43c18d06415a955b8f32355bca925be901905Yabin CuiElfStatus ParseSymbolsFromElfFile(const std::string& filename, 401dec43c18d06415a955b8f32355bca925be901905Yabin Cui const BuildId& expected_build_id, 402dec43c18d06415a955b8f32355bca925be901905Yabin Cui const std::function<void(const ElfFileSymbol&)>& callback) { 403dec43c18d06415a955b8f32355bca925be901905Yabin Cui ElfStatus result = IsValidElfPath(filename); 404dec43c18d06415a955b8f32355bca925be901905Yabin Cui if (result != ElfStatus::NO_ERROR) { 405dec43c18d06415a955b8f32355bca925be901905Yabin Cui return result; 406797116bfb9ad10d858086680c7465d65c399ef6eYabin Cui } 407b1a885b014540a2f7798b5a35ea0f0ec150d93eeYabin Cui return ParseSymbolsFromEmbeddedElfFile(filename, 0, 0, expected_build_id, callback); 408b1a885b014540a2f7798b5a35ea0f0ec150d93eeYabin Cui} 409b1a885b014540a2f7798b5a35ea0f0ec150d93eeYabin Cui 410dec43c18d06415a955b8f32355bca925be901905Yabin CuiElfStatus ParseSymbolsFromEmbeddedElfFile(const std::string& filename, uint64_t file_offset, 411b1a885b014540a2f7798b5a35ea0f0ec150d93eeYabin Cui uint32_t file_size, const BuildId& expected_build_id, 4123e4c5950f3aafb0bf66544468d98ee3ec26b705cYabin Cui const std::function<void(const ElfFileSymbol&)>& callback) { 413dec43c18d06415a955b8f32355bca925be901905Yabin Cui BinaryWrapper wrapper; 414dec43c18d06415a955b8f32355bca925be901905Yabin Cui ElfStatus result = OpenObjectFile(filename, file_offset, file_size, &wrapper); 415dec43c18d06415a955b8f32355bca925be901905Yabin Cui if (result != ElfStatus::NO_ERROR) { 416dec43c18d06415a955b8f32355bca925be901905Yabin Cui return result; 417dec43c18d06415a955b8f32355bca925be901905Yabin Cui } 418dec43c18d06415a955b8f32355bca925be901905Yabin Cui result = MatchBuildId(wrapper.obj, expected_build_id); 419dec43c18d06415a955b8f32355bca925be901905Yabin Cui if (result != ElfStatus::NO_ERROR) { 420dec43c18d06415a955b8f32355bca925be901905Yabin Cui return result; 421dec43c18d06415a955b8f32355bca925be901905Yabin Cui } 422dec43c18d06415a955b8f32355bca925be901905Yabin Cui if (auto elf = llvm::dyn_cast<llvm::object::ELF32LEObjectFile>(wrapper.obj)) { 423dec43c18d06415a955b8f32355bca925be901905Yabin Cui return ParseSymbolsFromELFFile(elf, callback); 424dec43c18d06415a955b8f32355bca925be901905Yabin Cui } else if (auto elf = llvm::dyn_cast<llvm::object::ELF64LEObjectFile>(wrapper.obj)) { 425dec43c18d06415a955b8f32355bca925be901905Yabin Cui return ParseSymbolsFromELFFile(elf, callback); 426638c558339b7f1ae0ed95f64bcf7dbc5b238ed83Yabin Cui } 427dec43c18d06415a955b8f32355bca925be901905Yabin Cui return ElfStatus::FILE_MALFORMED; 428ec12ed9010128483993a87d68edc02d3a89d56cfYabin Cui} 429547c60e4dd29c5788d5948ad348acf33a55d6ed6Yabin Cui 430547c60e4dd29c5788d5948ad348acf33a55d6ed6Yabin Cuitemplate <class ELFT> 431dec43c18d06415a955b8f32355bca925be901905Yabin CuiElfStatus ReadMinExecutableVirtualAddress(const llvm::object::ELFFile<ELFT>* elf, uint64_t* p_vaddr) { 432547c60e4dd29c5788d5948ad348acf33a55d6ed6Yabin Cui bool has_vaddr = false; 433547c60e4dd29c5788d5948ad348acf33a55d6ed6Yabin Cui uint64_t min_addr = std::numeric_limits<uint64_t>::max(); 43407cdff03ffb5e69d73979e8c2f8585314751ee17Yabin Cui for (auto it = elf->program_header_begin(); it != elf->program_header_end(); ++it) { 435547c60e4dd29c5788d5948ad348acf33a55d6ed6Yabin Cui if ((it->p_type == llvm::ELF::PT_LOAD) && (it->p_flags & llvm::ELF::PF_X)) { 436547c60e4dd29c5788d5948ad348acf33a55d6ed6Yabin Cui if (it->p_vaddr < min_addr) { 437547c60e4dd29c5788d5948ad348acf33a55d6ed6Yabin Cui min_addr = it->p_vaddr; 438547c60e4dd29c5788d5948ad348acf33a55d6ed6Yabin Cui has_vaddr = true; 439547c60e4dd29c5788d5948ad348acf33a55d6ed6Yabin Cui } 440547c60e4dd29c5788d5948ad348acf33a55d6ed6Yabin Cui } 441547c60e4dd29c5788d5948ad348acf33a55d6ed6Yabin Cui } 442dec43c18d06415a955b8f32355bca925be901905Yabin Cui if (!has_vaddr) { 443dec43c18d06415a955b8f32355bca925be901905Yabin Cui return ElfStatus::FILE_MALFORMED; 444547c60e4dd29c5788d5948ad348acf33a55d6ed6Yabin Cui } 445dec43c18d06415a955b8f32355bca925be901905Yabin Cui *p_vaddr = min_addr; 446dec43c18d06415a955b8f32355bca925be901905Yabin Cui return ElfStatus::NO_ERROR; 447547c60e4dd29c5788d5948ad348acf33a55d6ed6Yabin Cui} 448547c60e4dd29c5788d5948ad348acf33a55d6ed6Yabin Cui 449dec43c18d06415a955b8f32355bca925be901905Yabin CuiElfStatus ReadMinExecutableVirtualAddressFromElfFile(const std::string& filename, 450dec43c18d06415a955b8f32355bca925be901905Yabin Cui const BuildId& expected_build_id, 451dec43c18d06415a955b8f32355bca925be901905Yabin Cui uint64_t* min_vaddr) { 452dec43c18d06415a955b8f32355bca925be901905Yabin Cui ElfStatus result = IsValidElfPath(filename); 453dec43c18d06415a955b8f32355bca925be901905Yabin Cui if (result != ElfStatus::NO_ERROR) { 454dec43c18d06415a955b8f32355bca925be901905Yabin Cui return result; 455797116bfb9ad10d858086680c7465d65c399ef6eYabin Cui } 456dec43c18d06415a955b8f32355bca925be901905Yabin Cui BinaryWrapper wrapper; 457dec43c18d06415a955b8f32355bca925be901905Yabin Cui result = OpenObjectFile(filename, 0, 0, &wrapper); 458dec43c18d06415a955b8f32355bca925be901905Yabin Cui if (result != ElfStatus::NO_ERROR) { 459dec43c18d06415a955b8f32355bca925be901905Yabin Cui return result; 460547c60e4dd29c5788d5948ad348acf33a55d6ed6Yabin Cui } 461dec43c18d06415a955b8f32355bca925be901905Yabin Cui result = MatchBuildId(wrapper.obj, expected_build_id); 462dec43c18d06415a955b8f32355bca925be901905Yabin Cui if (result != ElfStatus::NO_ERROR) { 463dec43c18d06415a955b8f32355bca925be901905Yabin Cui return result; 464547c60e4dd29c5788d5948ad348acf33a55d6ed6Yabin Cui } 465547c60e4dd29c5788d5948ad348acf33a55d6ed6Yabin Cui 466dec43c18d06415a955b8f32355bca925be901905Yabin Cui if (auto elf = llvm::dyn_cast<llvm::object::ELF32LEObjectFile>(wrapper.obj)) { 467dec43c18d06415a955b8f32355bca925be901905Yabin Cui return ReadMinExecutableVirtualAddress(elf->getELFFile(), min_vaddr); 468dec43c18d06415a955b8f32355bca925be901905Yabin Cui } else if (auto elf = llvm::dyn_cast<llvm::object::ELF64LEObjectFile>(wrapper.obj)) { 469dec43c18d06415a955b8f32355bca925be901905Yabin Cui return ReadMinExecutableVirtualAddress(elf->getELFFile(), min_vaddr); 470dec43c18d06415a955b8f32355bca925be901905Yabin Cui } else { 471dec43c18d06415a955b8f32355bca925be901905Yabin Cui return ElfStatus::FILE_MALFORMED; 472547c60e4dd29c5788d5948ad348acf33a55d6ed6Yabin Cui } 473547c60e4dd29c5788d5948ad348acf33a55d6ed6Yabin Cui} 474be7ec66eaa4f995bd9068637f7c7d5718173922cYabin Cui 475dec43c18d06415a955b8f32355bca925be901905Yabin CuiElfStatus ReadSectionFromElfFile(const std::string& filename, const std::string& section_name, 476dec43c18d06415a955b8f32355bca925be901905Yabin Cui std::string* content) { 477dec43c18d06415a955b8f32355bca925be901905Yabin Cui ElfStatus result = IsValidElfPath(filename); 478dec43c18d06415a955b8f32355bca925be901905Yabin Cui if (result != ElfStatus::NO_ERROR) { 479dec43c18d06415a955b8f32355bca925be901905Yabin Cui return result; 480dec43c18d06415a955b8f32355bca925be901905Yabin Cui } 481dec43c18d06415a955b8f32355bca925be901905Yabin Cui BinaryWrapper wrapper; 482dec43c18d06415a955b8f32355bca925be901905Yabin Cui result = OpenObjectFile(filename, 0, 0, &wrapper); 483dec43c18d06415a955b8f32355bca925be901905Yabin Cui if (result != ElfStatus::NO_ERROR) { 484dec43c18d06415a955b8f32355bca925be901905Yabin Cui return result; 485dec43c18d06415a955b8f32355bca925be901905Yabin Cui } 486dec43c18d06415a955b8f32355bca925be901905Yabin Cui if (auto elf = llvm::dyn_cast<llvm::object::ELF32LEObjectFile>(wrapper.obj)) { 487dec43c18d06415a955b8f32355bca925be901905Yabin Cui return ReadSectionFromELFFile(elf, section_name, content); 488dec43c18d06415a955b8f32355bca925be901905Yabin Cui } else if (auto elf = llvm::dyn_cast<llvm::object::ELF64LEObjectFile>(wrapper.obj)) { 489dec43c18d06415a955b8f32355bca925be901905Yabin Cui return ReadSectionFromELFFile(elf, section_name, content); 490be7ec66eaa4f995bd9068637f7c7d5718173922cYabin Cui } else { 491dec43c18d06415a955b8f32355bca925be901905Yabin Cui return ElfStatus::FILE_MALFORMED; 492be7ec66eaa4f995bd9068637f7c7d5718173922cYabin Cui } 493be7ec66eaa4f995bd9068637f7c7d5718173922cYabin Cui} 494