blob: 8e9ddb1adb15b944b0c2f4eb99a9f7eb1252ebd1 [file] [log] [blame]
Yabin Cui8f622512015-05-05 19:58:07 -07001/*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "read_elf.h"
Than McIntoshf831e6d2016-02-01 19:50:20 -050018#include "read_apk.h"
Yabin Cui8f622512015-05-05 19:58:07 -070019
20#include <stdio.h>
21#include <string.h>
Than McIntoshf831e6d2016-02-01 19:50:20 -050022#include <sys/stat.h>
23#include <sys/types.h>
Yabin Cui547c60e2015-10-12 16:56:05 -070024
Yabin Cui8f622512015-05-05 19:58:07 -070025#include <algorithm>
Yabin Cui547c60e2015-10-12 16:56:05 -070026#include <limits>
27
Elliott Hughes66dd09e2015-12-04 14:00:57 -080028#include <android-base/file.h>
29#include <android-base/logging.h>
Yabin Cui8f622512015-05-05 19:58:07 -070030
31#pragma clang diagnostic push
32#pragma clang diagnostic ignored "-Wunused-parameter"
33
34#include <llvm/ADT/StringRef.h>
Yabin Cui8f622512015-05-05 19:58:07 -070035#include <llvm/Object/ELFObjectFile.h>
36#include <llvm/Object/ObjectFile.h>
37
38#pragma clang diagnostic pop
39
Yabin Cui9ba4d942020-09-08 16:12:46 -070040#include "JITDebugReader.h"
Yabin Cui8f622512015-05-05 19:58:07 -070041#include "utils.h"
42
Yabin Cuifaa7b922021-01-11 17:35:57 -080043namespace simpleperf {
Yabin Cuia5bdf0a2015-06-22 19:41:39 -070044
Yabin Cuifaa7b922021-01-11 17:35:57 -080045const static char* ELF_NOTE_GNU = "GNU";
46const static int NT_GNU_BUILD_ID = 3;
Yabin Cui02e20332020-03-16 19:38:23 -070047
Yabin Cuidec43c12016-07-29 16:40:40 -070048std::ostream& operator<<(std::ostream& os, const ElfStatus& status) {
49 switch (status) {
50 case ElfStatus::NO_ERROR:
51 os << "No error";
52 break;
53 case ElfStatus::FILE_NOT_FOUND:
54 os << "File not found";
55 break;
56 case ElfStatus::READ_FAILED:
57 os << "Read failed";
58 break;
59 case ElfStatus::FILE_MALFORMED:
60 os << "Malformed file";
61 break;
62 case ElfStatus::NO_SYMBOL_TABLE:
63 os << "No symbol table";
64 break;
65 case ElfStatus::NO_BUILD_ID:
66 os << "No build id";
67 break;
68 case ElfStatus::BUILD_ID_MISMATCH:
69 os << "Build id mismatch";
70 break;
71 case ElfStatus::SECTION_NOT_FOUND:
72 os << "Section not found";
73 break;
74 }
75 return os;
Than McIntoshf831e6d2016-02-01 19:50:20 -050076}
77
Yabin Cui9e43e9f2018-03-09 15:57:13 -080078bool IsValidElfFileMagic(const char* buf, size_t buf_size) {
Yabin Cuidec43c12016-07-29 16:40:40 -070079 static const char elf_magic[] = {0x7f, 'E', 'L', 'F'};
Yabin Cui9e43e9f2018-03-09 15:57:13 -080080 return (buf_size >= 4u && memcmp(buf, elf_magic, 4) == 0);
81}
82
Yabin Cui02e20332020-03-16 19:38:23 -070083ElfStatus IsValidElfFile(int fd, uint64_t file_offset) {
Yabin Cuidec43c12016-07-29 16:40:40 -070084 char buf[4];
Yabin Cui02e20332020-03-16 19:38:23 -070085 if (!android::base::ReadFullyAtOffset(fd, buf, 4, file_offset)) {
Yabin Cuidec43c12016-07-29 16:40:40 -070086 return ElfStatus::READ_FAILED;
87 }
Yabin Cui9e43e9f2018-03-09 15:57:13 -080088 return IsValidElfFileMagic(buf, 4) ? ElfStatus::NO_ERROR : ElfStatus::FILE_MALFORMED;
Yabin Cuidec43c12016-07-29 16:40:40 -070089}
90
Yabin Cuif79a0082016-11-14 11:23:14 -080091bool GetBuildIdFromNoteSection(const char* section, size_t section_size, BuildId* build_id) {
Yabin Cui8f622512015-05-05 19:58:07 -070092 const char* p = section;
93 const char* end = p + section_size;
94 while (p < end) {
Yabin Cuif79a0082016-11-14 11:23:14 -080095 if (p + 12 >= end) {
96 return false;
97 }
98 uint32_t namesz;
99 uint32_t descsz;
100 uint32_t type;
101 MoveFromBinaryFormat(namesz, p);
102 MoveFromBinaryFormat(descsz, p);
103 MoveFromBinaryFormat(type, p);
Yabin Cuia7a0e502016-06-15 11:49:23 -0700104 namesz = Align(namesz, 4);
105 descsz = Align(descsz, 4);
Yabin Cuif79a0082016-11-14 11:23:14 -0800106 if ((type == NT_GNU_BUILD_ID) && (p < end) && (strcmp(p, ELF_NOTE_GNU) == 0)) {
107 const char* desc_start = p + namesz;
108 const char* desc_end = desc_start + descsz;
109 if (desc_start > p && desc_start < desc_end && desc_end <= end) {
110 *build_id = BuildId(p + namesz, descsz);
111 return true;
112 } else {
113 return false;
114 }
Yabin Cui8f622512015-05-05 19:58:07 -0700115 }
116 p += namesz + descsz;
117 }
118 return false;
119}
120
Yabin Cuidec43c12016-07-29 16:40:40 -0700121ElfStatus GetBuildIdFromNoteFile(const std::string& filename, BuildId* build_id) {
Yabin Cui8f622512015-05-05 19:58:07 -0700122 std::string content;
123 if (!android::base::ReadFileToString(filename, &content)) {
Yabin Cuidec43c12016-07-29 16:40:40 -0700124 return ElfStatus::READ_FAILED;
Yabin Cui8f622512015-05-05 19:58:07 -0700125 }
Yabin Cuidec43c12016-07-29 16:40:40 -0700126 if (!GetBuildIdFromNoteSection(content.c_str(), content.size(), build_id)) {
127 return ElfStatus::NO_BUILD_ID;
Yabin Cui8f622512015-05-05 19:58:07 -0700128 }
Yabin Cuidec43c12016-07-29 16:40:40 -0700129 return ElfStatus::NO_ERROR;
Yabin Cui8f622512015-05-05 19:58:07 -0700130}
131
Yabin Cuifaa7b922021-01-11 17:35:57 -0800132bool IsArmMappingSymbol(const char* name) {
133 // Mapping symbols in arm, which are described in "ELF for ARM Architecture" and
134 // "ELF for ARM 64-bit Architecture". The regular expression to match mapping symbol
135 // is ^\$(a|d|t|x)(\..*)?$
136 return name[0] == '$' && strchr("adtx", name[1]) != nullptr &&
137 (name[2] == '\0' || name[2] == '.');
138}
139
140namespace {
141
Yabin Cuidec43c12016-07-29 16:40:40 -0700142struct BinaryWrapper {
Yabin Cui02e20332020-03-16 19:38:23 -0700143 std::unique_ptr<llvm::MemoryBuffer> buffer;
Yabin Cuic0ebc352023-07-20 17:37:35 +0000144 std::unique_ptr<llvm::object::ObjectFile> obj;
Yabin Cuib1a885b2016-02-14 19:18:02 -0800145};
146
Yabin Cuidec43c12016-07-29 16:40:40 -0700147static ElfStatus OpenObjectFile(const std::string& filename, uint64_t file_offset,
148 uint64_t file_size, BinaryWrapper* wrapper) {
Yabin Cui02e20332020-03-16 19:38:23 -0700149 if (!IsRegularFile(filename)) {
150 return ElfStatus::FILE_NOT_FOUND;
151 }
Yabin Cui2a53ff32018-05-21 17:37:00 -0700152 android::base::unique_fd fd = FileHelper::OpenReadOnly(filename);
153 if (fd == -1) {
Yabin Cuidec43c12016-07-29 16:40:40 -0700154 return ElfStatus::READ_FAILED;
Than McIntoshf831e6d2016-02-01 19:50:20 -0500155 }
Yabin Cuib1a885b2016-02-14 19:18:02 -0800156 if (file_size == 0) {
157 file_size = GetFileSize(filename);
158 if (file_size == 0) {
Yabin Cuidec43c12016-07-29 16:40:40 -0700159 return ElfStatus::READ_FAILED;
Yabin Cuib1a885b2016-02-14 19:18:02 -0800160 }
Than McIntoshf831e6d2016-02-01 19:50:20 -0500161 }
Yabin Cui02e20332020-03-16 19:38:23 -0700162 ElfStatus status = IsValidElfFile(fd, file_offset);
163 if (status != ElfStatus::NO_ERROR) {
164 return status;
165 }
Yabin Cui71b424d2023-07-07 22:53:55 +0000166 auto buffer_or_err = llvm::MemoryBuffer::getFileSlice(filename, file_size, file_offset);
Yabin Cuib1a885b2016-02-14 19:18:02 -0800167 if (!buffer_or_err) {
Yabin Cuidec43c12016-07-29 16:40:40 -0700168 return ElfStatus::READ_FAILED;
Than McIntoshf831e6d2016-02-01 19:50:20 -0500169 }
Yabin Cuic0ebc352023-07-20 17:37:35 +0000170 auto obj_or_err =
171 llvm::object::ObjectFile::createObjectFile(buffer_or_err.get()->getMemBufferRef());
172 if (!obj_or_err) {
Yabin Cuidec43c12016-07-29 16:40:40 -0700173 return ElfStatus::READ_FAILED;
Yabin Cuib1a885b2016-02-14 19:18:02 -0800174 }
Yabin Cui02e20332020-03-16 19:38:23 -0700175 wrapper->buffer = std::move(buffer_or_err.get());
Yabin Cuic0ebc352023-07-20 17:37:35 +0000176 wrapper->obj = std::move(obj_or_err.get());
Yabin Cuidec43c12016-07-29 16:40:40 -0700177 return ElfStatus::NO_ERROR;
Than McIntoshf831e6d2016-02-01 19:50:20 -0500178}
179
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800180static ElfStatus OpenObjectFileInMemory(const char* data, size_t size, BinaryWrapper* wrapper) {
181 auto buffer = llvm::MemoryBuffer::getMemBuffer(llvm::StringRef(data, size));
Yabin Cuic0ebc352023-07-20 17:37:35 +0000182 auto obj_or_err = llvm::object::ObjectFile::createObjectFile(buffer->getMemBufferRef());
183 if (!obj_or_err) {
Yabin Cuidec43c12016-07-29 16:40:40 -0700184 return ElfStatus::FILE_MALFORMED;
Yabin Cui05400532016-03-17 21:18:53 -0700185 }
Yabin Cui02e20332020-03-16 19:38:23 -0700186 wrapper->buffer = std::move(buffer);
Yabin Cuic0ebc352023-07-20 17:37:35 +0000187 wrapper->obj = std::move(obj_or_err.get());
Yabin Cuidec43c12016-07-29 16:40:40 -0700188 return ElfStatus::NO_ERROR;
Yabin Cui05400532016-03-17 21:18:53 -0700189}
190
Yabin Cui71b424d2023-07-07 22:53:55 +0000191static inline llvm::Expected<uint32_t> GetSymbolFlags(const llvm::object::ELFSymbolRef& symbol) {
192 return symbol.getFlags();
193}
194
195static inline llvm::Expected<uint64_t> GetSymbolValue(const llvm::object::ELFSymbolRef& symbol) {
196 return symbol.getValue();
197}
198
199static inline llvm::Expected<llvm::StringRef> GetSectionName(
200 const llvm::object::SectionRef& section) {
201 return section.getName();
202}
203
204static inline llvm::Expected<llvm::StringRef> GetSectionContents(
205 const llvm::object::SectionRef& section) {
206 return section.getContents();
207}
208
209template <typename ELFT>
210static inline const llvm::object::ELFFile<ELFT>* GetELFFile(
211 const llvm::object::ELFObjectFile<ELFT>* obj) {
212 return &obj->getELFFile();
213}
214
215template <typename ELFT>
216static inline const typename ELFT::Ehdr& GetELFHeader(const llvm::object::ELFFile<ELFT>* elf) {
217 return elf->getHeader();
218}
219
220template <typename ELFT>
221static inline llvm::Expected<typename ELFT::PhdrRange> GetELFProgramHeaders(
222 const llvm::object::ELFFile<ELFT>* elf) {
223 return elf->program_headers();
224}
225
226template <typename ELFT>
227static inline llvm::Expected<llvm::StringRef> GetELFSectionName(
228 const llvm::object::ELFFile<ELFT>* elf, const typename ELFT::Shdr& section_header) {
229 return elf->getSectionName(section_header);
230}
231
Thiébaud Weksteen4848ee02020-10-23 16:06:59 +0200232void ReadSymbolTable(llvm::object::symbol_iterator sym_begin, llvm::object::symbol_iterator sym_end,
233 const std::function<void(const ElfFileSymbol&)>& callback, bool is_arm,
Yabin Cui81d4c492018-08-09 12:06:10 -0700234 const llvm::object::section_iterator& section_end) {
Yabin Cui05400532016-03-17 21:18:53 -0700235 for (; sym_begin != sym_end; ++sym_begin) {
Yabin Cuiec12ed92015-06-08 10:38:10 -0700236 ElfFileSymbol symbol;
Yabin Cui05400532016-03-17 21:18:53 -0700237 auto symbol_ref = static_cast<const llvm::object::ELFSymbolRef*>(&*sym_begin);
Yabin Cui1b276a32019-11-18 17:23:27 -0800238 // Exclude undefined symbols, otherwise we may wrongly use them as labels in functions.
Yabin Cui71b424d2023-07-07 22:53:55 +0000239 if (auto flags = GetSymbolFlags(*symbol_ref);
240 !flags || (flags.get() & symbol_ref->SF_Undefined)) {
Yabin Cui1b276a32019-11-18 17:23:27 -0800241 continue;
242 }
Pirama Arumuga Nainar0ea82502016-09-16 16:53:25 -0700243 llvm::Expected<llvm::object::section_iterator> section_it_or_err = symbol_ref->getSection();
Yabin Cui05400532016-03-17 21:18:53 -0700244 if (!section_it_or_err) {
Yabin Cuiec12ed92015-06-08 10:38:10 -0700245 continue;
246 }
Yabin Cui81d4c492018-08-09 12:06:10 -0700247 // Symbols in .dynsym section don't have associated section.
248 if (section_it_or_err.get() != section_end) {
Yabin Cui71b424d2023-07-07 22:53:55 +0000249 llvm::Expected<llvm::StringRef> section_name = GetSectionName(*section_it_or_err.get());
250 if (!section_name || section_name.get().empty()) {
Yabin Cui81d4c492018-08-09 12:06:10 -0700251 continue;
252 }
Yabin Cui71b424d2023-07-07 22:53:55 +0000253 if (section_name.get() == ".text") {
Yabin Cui81d4c492018-08-09 12:06:10 -0700254 symbol.is_in_text_section = true;
255 }
256 }
Yabin Cuiec12ed92015-06-08 10:38:10 -0700257
Pirama Arumuga Nainar0ea82502016-09-16 16:53:25 -0700258 llvm::Expected<llvm::StringRef> symbol_name_or_err = symbol_ref->getName();
Yabin Cui05400532016-03-17 21:18:53 -0700259 if (!symbol_name_or_err || symbol_name_or_err.get().empty()) {
260 continue;
261 }
262
263 symbol.name = symbol_name_or_err.get();
Yabin Cui71b424d2023-07-07 22:53:55 +0000264 llvm::Expected<uint64_t> symbol_value = GetSymbolValue(*symbol_ref);
265 if (!symbol_value) {
266 continue;
267 }
268 symbol.vaddr = symbol_value.get();
Yabin Cui547c60e2015-10-12 16:56:05 -0700269 if ((symbol.vaddr & 1) != 0 && is_arm) {
Yabin Cuib3783552015-06-11 11:15:42 -0700270 // Arm sets bit 0 to mark it as thumb code, remove the flag.
Yabin Cui547c60e2015-10-12 16:56:05 -0700271 symbol.vaddr &= ~1;
Yabin Cuib3783552015-06-11 11:15:42 -0700272 }
Yabin Cui05400532016-03-17 21:18:53 -0700273 symbol.len = symbol_ref->getSize();
Pirama Arumuga Nainar0ea82502016-09-16 16:53:25 -0700274 llvm::object::SymbolRef::Type symbol_type = *symbol_ref->getType();
Yabin Cui05400532016-03-17 21:18:53 -0700275 if (symbol_type == llvm::object::SymbolRef::ST_Function) {
Yabin Cuib3783552015-06-11 11:15:42 -0700276 symbol.is_func = true;
Yabin Cui05400532016-03-17 21:18:53 -0700277 } else if (symbol_type == llvm::object::SymbolRef::ST_Unknown) {
Yabin Cuib3783552015-06-11 11:15:42 -0700278 if (symbol.is_in_text_section) {
279 symbol.is_label = true;
Yabin Cui2c17e0d2015-06-11 14:57:21 -0700280 if (is_arm) {
Yabin Cuia5bdf0a2015-06-22 19:41:39 -0700281 // Remove mapping symbols in arm.
282 const char* p = (symbol.name.compare(0, linker_prefix.size(), linker_prefix) == 0)
283 ? symbol.name.c_str() + linker_prefix.size()
284 : symbol.name.c_str();
285 if (IsArmMappingSymbol(p)) {
Yabin Cui2c17e0d2015-06-11 14:57:21 -0700286 symbol.is_label = false;
287 }
Yabin Cuib3783552015-06-11 11:15:42 -0700288 }
289 }
290 }
291
Yabin Cuiec12ed92015-06-08 10:38:10 -0700292 callback(symbol);
293 }
Yabin Cuiec12ed92015-06-08 10:38:10 -0700294}
295
Yabin Cui05400532016-03-17 21:18:53 -0700296template <class ELFT>
Yabin Cui5783fa02016-07-06 18:29:00 -0700297void AddSymbolForPltSection(const llvm::object::ELFObjectFile<ELFT>* elf,
Yabin Cui3e4c5952016-07-26 15:03:27 -0700298 const std::function<void(const ElfFileSymbol&)>& callback) {
Yabin Cui5783fa02016-07-06 18:29:00 -0700299 // We may sample instructions in .plt section if the program
300 // calls functions from shared libraries. Different architectures use
301 // different formats to store .plt section, so it needs a lot of work to match
302 // instructions in .plt section to symbols. As samples in .plt section rarely
303 // happen, and .plt section can hardly be a performance bottleneck, we can
304 // just use a symbol @plt to represent instructions in .plt section.
305 for (auto it = elf->section_begin(); it != elf->section_end(); ++it) {
306 const llvm::object::ELFSectionRef& section_ref = *it;
Yabin Cui71b424d2023-07-07 22:53:55 +0000307 llvm::Expected<llvm::StringRef> section_name = GetSectionName(section_ref);
308 if (!section_name || section_name.get() != ".plt") {
Yabin Cui5783fa02016-07-06 18:29:00 -0700309 continue;
310 }
311 const auto* shdr = elf->getSection(section_ref.getRawDataRefImpl());
312 if (shdr == nullptr) {
313 return;
314 }
315 ElfFileSymbol symbol;
316 symbol.vaddr = shdr->sh_addr;
317 symbol.len = shdr->sh_size;
318 symbol.is_func = true;
319 symbol.is_label = true;
320 symbol.is_in_text_section = true;
321 symbol.name = "@plt";
322 callback(symbol);
323 return;
324 }
325}
326
Yabin Cui5783fa02016-07-06 18:29:00 -0700327template <class ELFT>
Thiébaud Weksteen4848ee02020-10-23 16:06:59 +0200328void CheckSymbolSections(const llvm::object::ELFObjectFile<ELFT>* elf, bool* has_symtab,
329 bool* has_dynsym) {
Yabin Cuie4e13f32017-12-15 11:36:51 -0800330 *has_symtab = false;
331 *has_dynsym = false;
332 for (auto it = elf->section_begin(); it != elf->section_end(); ++it) {
333 const llvm::object::ELFSectionRef& section_ref = *it;
Yabin Cui71b424d2023-07-07 22:53:55 +0000334 llvm::Expected<llvm::StringRef> section_name = GetSectionName(section_ref);
335 if (!section_name) {
Yabin Cuie4e13f32017-12-15 11:36:51 -0800336 continue;
337 }
Yabin Cui71b424d2023-07-07 22:53:55 +0000338 if (section_name.get() == ".dynsym") {
Yabin Cuie4e13f32017-12-15 11:36:51 -0800339 *has_dynsym = true;
Yabin Cui71b424d2023-07-07 22:53:55 +0000340 } else if (section_name.get() == ".symtab") {
Yabin Cuie4e13f32017-12-15 11:36:51 -0800341 *has_symtab = true;
342 }
343 }
344}
345
Yabin Cui02e20332020-03-16 19:38:23 -0700346template <typename T>
347class ElfFileImpl {};
348
349template <typename ELFT>
Yabin Cui3a880452020-06-29 16:37:31 -0700350class ElfFileImpl<llvm::object::ELFObjectFile<ELFT>> : public ElfFile {
Yabin Cui02e20332020-03-16 19:38:23 -0700351 public:
Yabin Cui3a880452020-06-29 16:37:31 -0700352 ElfFileImpl(BinaryWrapper&& wrapper, const llvm::object::ELFObjectFile<ELFT>* elf_obj)
Yabin Cui71b424d2023-07-07 22:53:55 +0000353 : wrapper_(std::move(wrapper)), elf_obj_(elf_obj), elf_(GetELFFile(elf_obj_)) {}
Yabin Cui02e20332020-03-16 19:38:23 -0700354
Yabin Cui71b424d2023-07-07 22:53:55 +0000355 bool Is64Bit() override { return GetELFHeader(elf_).getFileClass() == llvm::ELF::ELFCLASS64; }
Yabin Cui4ad10fb2020-04-01 15:45:48 -0700356
Thiébaud Weksteen4848ee02020-10-23 16:06:59 +0200357 llvm::MemoryBuffer* GetMemoryBuffer() override { return wrapper_.buffer.get(); }
Yabin Cui02e20332020-03-16 19:38:23 -0700358
Yabin Cui4ad10fb2020-04-01 15:45:48 -0700359 std::vector<ElfSegment> GetProgramHeader() override {
Yabin Cui71b424d2023-07-07 22:53:55 +0000360 auto program_headers = GetELFProgramHeaders(elf_);
361 if (!program_headers) {
362 return {};
363 }
364 std::vector<ElfSegment> segments(program_headers.get().size());
365 for (size_t i = 0; i < program_headers.get().size(); i++) {
366 const auto& phdr = program_headers.get()[i];
Yabin Cui4ad10fb2020-04-01 15:45:48 -0700367 segments[i].vaddr = phdr.p_vaddr;
368 segments[i].file_offset = phdr.p_offset;
369 segments[i].file_size = phdr.p_filesz;
370 segments[i].is_executable =
371 (phdr.p_type == llvm::ELF::PT_LOAD) && (phdr.p_flags & llvm::ELF::PF_X);
Yabin Cui4e4cbbc2020-12-14 15:26:19 -0800372 segments[i].is_load = (phdr.p_type == llvm::ELF::PT_LOAD);
Yabin Cui4ad10fb2020-04-01 15:45:48 -0700373 }
374 return segments;
375 }
376
Yabin Cui7078c672020-11-10 16:24:12 -0800377 std::vector<ElfSection> GetSectionHeader() override {
378 auto section_headers_or_err = elf_->sections();
379 if (!section_headers_or_err) {
380 return {};
381 }
382 const auto& section_headers = section_headers_or_err.get();
383 std::vector<ElfSection> sections(section_headers.size());
384 for (size_t i = 0; i < section_headers.size(); i++) {
385 const auto& shdr = section_headers[i];
Yabin Cui71b424d2023-07-07 22:53:55 +0000386 if (auto name = GetELFSectionName(elf_, shdr); name) {
Yabin Cui7078c672020-11-10 16:24:12 -0800387 sections[i].name = name.get();
388 }
389 sections[i].vaddr = shdr.sh_addr;
390 sections[i].file_offset = shdr.sh_offset;
Yabin Cui16f41ff2021-03-23 14:58:25 -0700391 sections[i].size = shdr.sh_size;
Yabin Cui7078c672020-11-10 16:24:12 -0800392 }
393 return sections;
394 }
395
Yabin Cui3a880452020-06-29 16:37:31 -0700396 ElfStatus GetBuildId(BuildId* build_id) override {
397 llvm::StringRef data = elf_obj_->getData();
398 const char* binary_start = data.data();
399 const char* binary_end = data.data() + data.size();
400 for (auto it = elf_obj_->section_begin(); it != elf_obj_->section_end(); ++it) {
401 const llvm::object::ELFSectionRef& section_ref = *it;
402 if (section_ref.getType() == llvm::ELF::SHT_NOTE) {
Yabin Cui71b424d2023-07-07 22:53:55 +0000403 llvm::Expected<llvm::StringRef> content = GetSectionContents(section_ref);
404 if (!content) {
405 return ElfStatus::NO_BUILD_ID;
Yabin Cui3a880452020-06-29 16:37:31 -0700406 }
Yabin Cui71b424d2023-07-07 22:53:55 +0000407 const llvm::StringRef& data = content.get();
Yabin Cui3a880452020-06-29 16:37:31 -0700408 if (data.data() < binary_start || data.data() + data.size() > binary_end) {
409 return ElfStatus::NO_BUILD_ID;
410 }
411 if (GetBuildIdFromNoteSection(data.data(), data.size(), build_id)) {
412 return ElfStatus::NO_ERROR;
413 }
414 }
415 }
416 return ElfStatus::NO_BUILD_ID;
417 }
418
Yabin Cui01947032020-06-30 14:36:46 -0700419 ElfStatus ParseSymbols(const ParseSymbolCallback& callback) override {
Yabin Cui71b424d2023-07-07 22:53:55 +0000420 auto machine = GetELFHeader(elf_).e_machine;
Yabin Cui01947032020-06-30 14:36:46 -0700421 bool is_arm = (machine == llvm::ELF::EM_ARM || machine == llvm::ELF::EM_AARCH64);
422 AddSymbolForPltSection(elf_obj_, callback);
423 // Some applications deliberately ship elf files with broken section tables.
424 // So check the existence of .symtab section and .dynsym section before reading symbols.
425 bool has_symtab;
426 bool has_dynsym;
427 CheckSymbolSections(elf_obj_, &has_symtab, &has_dynsym);
428 if (has_symtab && elf_obj_->symbol_begin() != elf_obj_->symbol_end()) {
429 ReadSymbolTable(elf_obj_->symbol_begin(), elf_obj_->symbol_end(), callback, is_arm,
430 elf_obj_->section_end());
431 return ElfStatus::NO_ERROR;
432 } else if (has_dynsym && elf_obj_->dynamic_symbol_begin()->getRawDataRefImpl() !=
433 llvm::object::DataRefImpl()) {
434 ReadSymbolTable(elf_obj_->dynamic_symbol_begin(), elf_obj_->dynamic_symbol_end(), callback,
435 is_arm, elf_obj_->section_end());
436 }
437 std::string debugdata;
438 ElfStatus result = ReadSection(".gnu_debugdata", &debugdata);
439 if (result == ElfStatus::SECTION_NOT_FOUND) {
440 return ElfStatus::NO_SYMBOL_TABLE;
441 } else if (result == ElfStatus::NO_ERROR) {
442 std::string decompressed_data;
443 if (XzDecompress(debugdata, &decompressed_data)) {
444 auto debugdata_elf =
445 ElfFile::Open(decompressed_data.data(), decompressed_data.size(), &result);
446 if (debugdata_elf) {
447 return debugdata_elf->ParseSymbols(callback);
448 }
449 }
450 }
451 return result;
452 }
453
454 void ParseDynamicSymbols(const ParseSymbolCallback& callback) override {
Yabin Cui71b424d2023-07-07 22:53:55 +0000455 auto machine = GetELFHeader(elf_).e_machine;
Yabin Cui01947032020-06-30 14:36:46 -0700456 bool is_arm = (machine == llvm::ELF::EM_ARM || machine == llvm::ELF::EM_AARCH64);
457 ReadSymbolTable(elf_obj_->dynamic_symbol_begin(), elf_obj_->dynamic_symbol_end(), callback,
458 is_arm, elf_obj_->section_end());
459 }
460
461 ElfStatus ReadSection(const std::string& section_name, std::string* content) override {
462 for (llvm::object::section_iterator it = elf_obj_->section_begin();
463 it != elf_obj_->section_end(); ++it) {
Yabin Cui71b424d2023-07-07 22:53:55 +0000464 llvm::Expected<llvm::StringRef> name = GetSectionName(*it);
465 if (!name || name.get() != section_name) {
Yabin Cui01947032020-06-30 14:36:46 -0700466 continue;
467 }
Yabin Cui71b424d2023-07-07 22:53:55 +0000468 llvm::Expected<llvm::StringRef> data = GetSectionContents(*it);
469 if (!data) {
Yabin Cui01947032020-06-30 14:36:46 -0700470 return ElfStatus::READ_FAILED;
471 }
Yabin Cui71b424d2023-07-07 22:53:55 +0000472 *content = data.get();
Yabin Cui01947032020-06-30 14:36:46 -0700473 return ElfStatus::NO_ERROR;
474 }
475 return ElfStatus::SECTION_NOT_FOUND;
476 }
477
Yabin Cui90c3b302020-07-01 10:09:16 -0700478 uint64_t ReadMinExecutableVaddr(uint64_t* file_offset) {
479 bool has_vaddr = false;
480 uint64_t min_addr = std::numeric_limits<uint64_t>::max();
Yabin Cui71b424d2023-07-07 22:53:55 +0000481 auto program_headers = GetELFProgramHeaders(elf_);
482 if (program_headers) {
483 for (const auto& ph : program_headers.get()) {
484 if ((ph.p_type == llvm::ELF::PT_LOAD) && (ph.p_flags & llvm::ELF::PF_X) &&
485 (ph.p_vaddr < min_addr)) {
486 min_addr = ph.p_vaddr;
487 *file_offset = ph.p_offset;
Yabin Cui90c3b302020-07-01 10:09:16 -0700488 has_vaddr = true;
489 }
490 }
491 }
492 if (!has_vaddr) {
493 // JIT symfiles don't have program headers.
494 min_addr = 0;
495 *file_offset = 0;
496 }
497 return min_addr;
498 }
499
Yabin Cuib60b33c2020-07-15 11:58:41 -0700500 bool VaddrToOff(uint64_t vaddr, uint64_t* file_offset) override {
Yabin Cui71b424d2023-07-07 22:53:55 +0000501 auto program_headers = GetELFProgramHeaders(elf_);
502 if (!program_headers) {
503 return false;
504 }
505 for (const auto& ph : program_headers.get()) {
506 if (ph.p_type == llvm::ELF::PT_LOAD && vaddr >= ph.p_vaddr &&
507 vaddr < ph.p_vaddr + ph.p_filesz) {
508 *file_offset = vaddr - ph.p_vaddr + ph.p_offset;
Yabin Cuib60b33c2020-07-15 11:58:41 -0700509 return true;
510 }
511 }
512 return false;
513 }
514
Yabin Cui02e20332020-03-16 19:38:23 -0700515 private:
516 BinaryWrapper wrapper_;
Yabin Cui3a880452020-06-29 16:37:31 -0700517 const llvm::object::ELFObjectFile<ELFT>* elf_obj_;
Yabin Cui02e20332020-03-16 19:38:23 -0700518 const llvm::object::ELFFile<ELFT>* elf_;
519};
520
Yabin Cui01947032020-06-30 14:36:46 -0700521std::unique_ptr<ElfFile> CreateElfFileImpl(BinaryWrapper&& wrapper, ElfStatus* status) {
Yabin Cuic0ebc352023-07-20 17:37:35 +0000522 if (auto obj = llvm::dyn_cast<llvm::object::ELF32LEObjectFile>(wrapper.obj.get())) {
Yabin Cui01947032020-06-30 14:36:46 -0700523 return std::unique_ptr<ElfFile>(
524 new ElfFileImpl<llvm::object::ELF32LEObjectFile>(std::move(wrapper), obj));
525 }
Yabin Cuic0ebc352023-07-20 17:37:35 +0000526 if (auto obj = llvm::dyn_cast<llvm::object::ELF64LEObjectFile>(wrapper.obj.get())) {
Yabin Cui01947032020-06-30 14:36:46 -0700527 return std::unique_ptr<ElfFile>(
528 new ElfFileImpl<llvm::object::ELF64LEObjectFile>(std::move(wrapper), obj));
529 }
530 *status = ElfStatus::FILE_MALFORMED;
531 return nullptr;
532}
533
Yabin Cui02e20332020-03-16 19:38:23 -0700534} // namespace
535
Yabin Cuib60b33c2020-07-15 11:58:41 -0700536std::unique_ptr<ElfFile> ElfFile::Open(const std::string& filename) {
537 ElfStatus status;
538 auto elf = Open(filename, &status);
539 if (!elf) {
540 LOG(ERROR) << "failed to open " << filename << ": " << status;
541 }
542 return elf;
543}
544
Yabin Cui01947032020-06-30 14:36:46 -0700545std::unique_ptr<ElfFile> ElfFile::Open(const std::string& filename,
546 const BuildId* expected_build_id, ElfStatus* status) {
Yabin Cui02e20332020-03-16 19:38:23 -0700547 BinaryWrapper wrapper;
548 auto tuple = SplitUrlInApk(filename);
549 if (std::get<0>(tuple)) {
550 EmbeddedElf* elf = ApkInspector::FindElfInApkByName(std::get<1>(tuple), std::get<2>(tuple));
551 if (elf == nullptr) {
552 *status = ElfStatus::FILE_NOT_FOUND;
553 } else {
554 *status = OpenObjectFile(elf->filepath(), elf->entry_offset(), elf->entry_size(), &wrapper);
555 }
Yabin Cui9ba4d942020-09-08 16:12:46 -0700556 } else if (JITDebugReader::IsPathInJITSymFile(filename)) {
557 size_t colon_pos = filename.rfind(':');
558 CHECK_NE(colon_pos, std::string::npos);
Yabin Cuie32ed2b2020-07-23 15:30:14 -0700559 // path generated by JITDebugReader: app_jit_cache:<file_start>-<file_end>
560 uint64_t file_start;
561 uint64_t file_end;
562 if (sscanf(filename.data() + colon_pos, ":%" PRIu64 "-%" PRIu64, &file_start, &file_end) != 2) {
563 *status = ElfStatus::FILE_NOT_FOUND;
564 return nullptr;
565 }
566 *status =
567 OpenObjectFile(filename.substr(0, colon_pos), file_start, file_end - file_start, &wrapper);
Yabin Cui02e20332020-03-16 19:38:23 -0700568 } else {
569 *status = OpenObjectFile(filename, 0, 0, &wrapper);
570 }
Yabin Cui01947032020-06-30 14:36:46 -0700571 if (*status != ElfStatus::NO_ERROR) {
572 return nullptr;
Yabin Cui02e20332020-03-16 19:38:23 -0700573 }
Yabin Cui01947032020-06-30 14:36:46 -0700574 auto elf = CreateElfFileImpl(std::move(wrapper), status);
575 if (elf && expected_build_id != nullptr && !expected_build_id->IsEmpty()) {
576 BuildId real_build_id;
577 *status = elf->GetBuildId(&real_build_id);
578 if (*status != ElfStatus::NO_ERROR) {
579 return nullptr;
580 }
581 if (*expected_build_id != real_build_id) {
582 *status = ElfStatus::BUILD_ID_MISMATCH;
583 return nullptr;
584 }
585 }
586 return elf;
587}
588
589std::unique_ptr<ElfFile> ElfFile::Open(const char* data, size_t size, ElfStatus* status) {
590 BinaryWrapper wrapper;
591 *status = OpenObjectFileInMemory(data, size, &wrapper);
592 if (*status != ElfStatus::NO_ERROR) {
593 return nullptr;
594 }
595 return CreateElfFileImpl(std::move(wrapper), status);
Yabin Cui02e20332020-03-16 19:38:23 -0700596}
597
Yabin Cuie55f0322020-05-27 16:26:45 -0700598} // namespace simpleperf
599
Yabin Cuie55f0322020-05-27 16:26:45 -0700600// LLVM libraries uses ncurses library, but that isn't needed by simpleperf.
601// So support a naive implementation to avoid depending on ncurses.
Thiébaud Weksteen4848ee02020-10-23 16:06:59 +0200602__attribute__((weak)) extern "C" int setupterm(char*, int, int*) {
Yabin Cuie55f0322020-05-27 16:26:45 -0700603 return -1;
604}
605
Thiébaud Weksteen4848ee02020-10-23 16:06:59 +0200606__attribute__((weak)) extern "C" struct term* set_curterm(struct term*) {
Yabin Cuie55f0322020-05-27 16:26:45 -0700607 return nullptr;
608}
609
Thiébaud Weksteen4848ee02020-10-23 16:06:59 +0200610__attribute__((weak)) extern "C" int del_curterm(struct term*) {
Yabin Cuie55f0322020-05-27 16:26:45 -0700611 return -1;
612}
613
Thiébaud Weksteen4848ee02020-10-23 16:06:59 +0200614__attribute__((weak)) extern "C" int tigetnum(char*) {
Yabin Cuie55f0322020-05-27 16:26:45 -0700615 return -1;
616}