read_elf.cpp 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585
  1. /*
  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. #include "read_elf.h"
  17. #include "read_apk.h"
  18. #include <stdio.h>
  19. #include <string.h>
  20. #include <sys/stat.h>
  21. #include <sys/types.h>
  22. #include <algorithm>
  23. #include <limits>
  24. #include <android-base/file.h>
  25. #include <android-base/logging.h>
  26. #pragma clang diagnostic push
  27. #pragma clang diagnostic ignored "-Wunused-parameter"
  28. #include <llvm/ADT/StringRef.h>
  29. #include <llvm/Object/Binary.h>
  30. #include <llvm/Object/ELFObjectFile.h>
  31. #include <llvm/Object/ObjectFile.h>
  32. #pragma clang diagnostic pop
  33. #include "utils.h"
  34. #define ELF_NOTE_GNU "GNU"
  35. #define NT_GNU_BUILD_ID 3
  36. std::ostream& operator<<(std::ostream& os, const ElfStatus& status) {
  37. switch (status) {
  38. case ElfStatus::NO_ERROR:
  39. os << "No error";
  40. break;
  41. case ElfStatus::FILE_NOT_FOUND:
  42. os << "File not found";
  43. break;
  44. case ElfStatus::READ_FAILED:
  45. os << "Read failed";
  46. break;
  47. case ElfStatus::FILE_MALFORMED:
  48. os << "Malformed file";
  49. break;
  50. case ElfStatus::NO_SYMBOL_TABLE:
  51. os << "No symbol table";
  52. break;
  53. case ElfStatus::NO_BUILD_ID:
  54. os << "No build id";
  55. break;
  56. case ElfStatus::BUILD_ID_MISMATCH:
  57. os << "Build id mismatch";
  58. break;
  59. case ElfStatus::SECTION_NOT_FOUND:
  60. os << "Section not found";
  61. break;
  62. }
  63. return os;
  64. }
  65. bool IsValidElfFileMagic(const char* buf, size_t buf_size) {
  66. static const char elf_magic[] = {0x7f, 'E', 'L', 'F'};
  67. return (buf_size >= 4u && memcmp(buf, elf_magic, 4) == 0);
  68. }
  69. ElfStatus IsValidElfFile(int fd) {
  70. char buf[4];
  71. if (!android::base::ReadFully(fd, buf, 4)) {
  72. return ElfStatus::READ_FAILED;
  73. }
  74. return IsValidElfFileMagic(buf, 4) ? ElfStatus::NO_ERROR : ElfStatus::FILE_MALFORMED;
  75. }
  76. ElfStatus IsValidElfPath(const std::string& filename) {
  77. if (!IsRegularFile(filename)) {
  78. return ElfStatus::FILE_NOT_FOUND;
  79. }
  80. std::string mode = std::string("rb") + CLOSE_ON_EXEC_MODE;
  81. FILE* fp = fopen(filename.c_str(), mode.c_str());
  82. if (fp == nullptr) {
  83. return ElfStatus::READ_FAILED;
  84. }
  85. ElfStatus result = IsValidElfFile(fileno(fp));
  86. fclose(fp);
  87. return result;
  88. }
  89. bool GetBuildIdFromNoteSection(const char* section, size_t section_size, BuildId* build_id) {
  90. const char* p = section;
  91. const char* end = p + section_size;
  92. while (p < end) {
  93. if (p + 12 >= end) {
  94. return false;
  95. }
  96. uint32_t namesz;
  97. uint32_t descsz;
  98. uint32_t type;
  99. MoveFromBinaryFormat(namesz, p);
  100. MoveFromBinaryFormat(descsz, p);
  101. MoveFromBinaryFormat(type, p);
  102. namesz = Align(namesz, 4);
  103. descsz = Align(descsz, 4);
  104. if ((type == NT_GNU_BUILD_ID) && (p < end) && (strcmp(p, ELF_NOTE_GNU) == 0)) {
  105. const char* desc_start = p + namesz;
  106. const char* desc_end = desc_start + descsz;
  107. if (desc_start > p && desc_start < desc_end && desc_end <= end) {
  108. *build_id = BuildId(p + namesz, descsz);
  109. return true;
  110. } else {
  111. return false;
  112. }
  113. }
  114. p += namesz + descsz;
  115. }
  116. return false;
  117. }
  118. ElfStatus GetBuildIdFromNoteFile(const std::string& filename, BuildId* build_id) {
  119. std::string content;
  120. if (!android::base::ReadFileToString(filename, &content)) {
  121. return ElfStatus::READ_FAILED;
  122. }
  123. if (!GetBuildIdFromNoteSection(content.c_str(), content.size(), build_id)) {
  124. return ElfStatus::NO_BUILD_ID;
  125. }
  126. return ElfStatus::NO_ERROR;
  127. }
  128. template <class ELFT>
  129. ElfStatus GetBuildIdFromELFFile(const llvm::object::ELFObjectFile<ELFT>* elf, BuildId* build_id) {
  130. llvm::StringRef data = elf->getData();
  131. const char* binary_start = data.data();
  132. const char* binary_end = data.data() + data.size();
  133. for (auto it = elf->section_begin(); it != elf->section_end(); ++it) {
  134. const llvm::object::ELFSectionRef& section_ref = *it;
  135. if (section_ref.getType() == llvm::ELF::SHT_NOTE) {
  136. if (it->getContents(data)) {
  137. return ElfStatus::READ_FAILED;
  138. }
  139. if (data.data() < binary_start || data.data() + data.size() > binary_end) {
  140. return ElfStatus::NO_BUILD_ID;
  141. }
  142. if (GetBuildIdFromNoteSection(data.data(), data.size(), build_id)) {
  143. return ElfStatus::NO_ERROR;
  144. }
  145. }
  146. }
  147. return ElfStatus::NO_BUILD_ID;
  148. }
  149. static ElfStatus GetBuildIdFromObjectFile(llvm::object::ObjectFile* obj, BuildId* build_id) {
  150. if (auto elf = llvm::dyn_cast<llvm::object::ELF32LEObjectFile>(obj)) {
  151. return GetBuildIdFromELFFile(elf, build_id);
  152. } else if (auto elf = llvm::dyn_cast<llvm::object::ELF64LEObjectFile>(obj)) {
  153. return GetBuildIdFromELFFile(elf, build_id);
  154. }
  155. return ElfStatus::FILE_MALFORMED;
  156. }
  157. struct BinaryWrapper {
  158. llvm::object::OwningBinary<llvm::object::Binary> binary;
  159. llvm::object::ObjectFile* obj;
  160. BinaryWrapper() : obj(nullptr) {
  161. }
  162. };
  163. static ElfStatus OpenObjectFile(const std::string& filename, uint64_t file_offset,
  164. uint64_t file_size, BinaryWrapper* wrapper) {
  165. android::base::unique_fd fd = FileHelper::OpenReadOnly(filename);
  166. if (fd == -1) {
  167. return ElfStatus::READ_FAILED;
  168. }
  169. if (file_size == 0) {
  170. file_size = GetFileSize(filename);
  171. if (file_size == 0) {
  172. return ElfStatus::READ_FAILED;
  173. }
  174. }
  175. auto buffer_or_err = llvm::MemoryBuffer::getOpenFileSlice(fd, filename, file_size, file_offset);
  176. if (!buffer_or_err) {
  177. return ElfStatus::READ_FAILED;
  178. }
  179. auto binary_or_err = llvm::object::createBinary(buffer_or_err.get()->getMemBufferRef());
  180. if (!binary_or_err) {
  181. return ElfStatus::READ_FAILED;
  182. }
  183. wrapper->binary = llvm::object::OwningBinary<llvm::object::Binary>(std::move(binary_or_err.get()),
  184. std::move(buffer_or_err.get()));
  185. wrapper->obj = llvm::dyn_cast<llvm::object::ObjectFile>(wrapper->binary.getBinary());
  186. if (wrapper->obj == nullptr) {
  187. return ElfStatus::FILE_MALFORMED;
  188. }
  189. return ElfStatus::NO_ERROR;
  190. }
  191. static ElfStatus OpenObjectFileInMemory(const char* data, size_t size, BinaryWrapper* wrapper) {
  192. auto buffer = llvm::MemoryBuffer::getMemBuffer(llvm::StringRef(data, size));
  193. auto binary_or_err = llvm::object::createBinary(buffer->getMemBufferRef());
  194. if (!binary_or_err) {
  195. return ElfStatus::FILE_MALFORMED;
  196. }
  197. wrapper->binary = llvm::object::OwningBinary<llvm::object::Binary>(std::move(binary_or_err.get()),
  198. std::move(buffer));
  199. wrapper->obj = llvm::dyn_cast<llvm::object::ObjectFile>(wrapper->binary.getBinary());
  200. if (wrapper->obj == nullptr) {
  201. return ElfStatus::FILE_MALFORMED;
  202. }
  203. return ElfStatus::NO_ERROR;
  204. }
  205. ElfStatus GetBuildIdFromElfFile(const std::string& filename, BuildId* build_id) {
  206. ElfStatus result = IsValidElfPath(filename);
  207. if (result != ElfStatus::NO_ERROR) {
  208. return result;
  209. }
  210. return GetBuildIdFromEmbeddedElfFile(filename, 0, 0, build_id);
  211. }
  212. ElfStatus GetBuildIdFromEmbeddedElfFile(const std::string& filename, uint64_t file_offset,
  213. uint32_t file_size, BuildId* build_id) {
  214. BinaryWrapper wrapper;
  215. ElfStatus result = OpenObjectFile(filename, file_offset, file_size, &wrapper);
  216. if (result != ElfStatus::NO_ERROR) {
  217. return result;
  218. }
  219. return GetBuildIdFromObjectFile(wrapper.obj, build_id);
  220. }
  221. template <class ELFT>
  222. ElfStatus ReadSectionFromELFFile(const llvm::object::ELFObjectFile<ELFT>* elf, const std::string& section_name,
  223. std::string* content) {
  224. for (llvm::object::section_iterator it = elf->section_begin(); it != elf->section_end(); ++it) {
  225. llvm::StringRef name;
  226. if (it->getName(name) || name != section_name) {
  227. continue;
  228. }
  229. llvm::StringRef data;
  230. std::error_code err = it->getContents(data);
  231. if (err) {
  232. return ElfStatus::READ_FAILED;
  233. }
  234. *content = data;
  235. return ElfStatus::NO_ERROR;
  236. }
  237. return ElfStatus::SECTION_NOT_FOUND;
  238. }
  239. bool IsArmMappingSymbol(const char* name) {
  240. // Mapping symbols in arm, which are described in "ELF for ARM Architecture" and
  241. // "ELF for ARM 64-bit Architecture". The regular expression to match mapping symbol
  242. // is ^\$(a|d|t|x)(\..*)?$
  243. return name[0] == '$' && strchr("adtx", name[1]) != nullptr && (name[2] == '\0' || name[2] == '.');
  244. }
  245. void ReadSymbolTable(llvm::object::symbol_iterator sym_begin,
  246. llvm::object::symbol_iterator sym_end,
  247. const std::function<void(const ElfFileSymbol&)>& callback,
  248. bool is_arm,
  249. const llvm::object::section_iterator& section_end) {
  250. for (; sym_begin != sym_end; ++sym_begin) {
  251. ElfFileSymbol symbol;
  252. auto symbol_ref = static_cast<const llvm::object::ELFSymbolRef*>(&*sym_begin);
  253. llvm::Expected<llvm::object::section_iterator> section_it_or_err = symbol_ref->getSection();
  254. if (!section_it_or_err) {
  255. continue;
  256. }
  257. // Symbols in .dynsym section don't have associated section.
  258. if (section_it_or_err.get() != section_end) {
  259. llvm::StringRef section_name;
  260. if (section_it_or_err.get()->getName(section_name) || section_name.empty()) {
  261. continue;
  262. }
  263. if (section_name == ".text") {
  264. symbol.is_in_text_section = true;
  265. }
  266. }
  267. llvm::Expected<llvm::StringRef> symbol_name_or_err = symbol_ref->getName();
  268. if (!symbol_name_or_err || symbol_name_or_err.get().empty()) {
  269. continue;
  270. }
  271. symbol.name = symbol_name_or_err.get();
  272. symbol.vaddr = symbol_ref->getValue();
  273. if ((symbol.vaddr & 1) != 0 && is_arm) {
  274. // Arm sets bit 0 to mark it as thumb code, remove the flag.
  275. symbol.vaddr &= ~1;
  276. }
  277. symbol.len = symbol_ref->getSize();
  278. llvm::object::SymbolRef::Type symbol_type = *symbol_ref->getType();
  279. if (symbol_type == llvm::object::SymbolRef::ST_Function) {
  280. symbol.is_func = true;
  281. } else if (symbol_type == llvm::object::SymbolRef::ST_Unknown) {
  282. if (symbol.is_in_text_section) {
  283. symbol.is_label = true;
  284. if (is_arm) {
  285. // Remove mapping symbols in arm.
  286. const char* p = (symbol.name.compare(0, linker_prefix.size(), linker_prefix) == 0)
  287. ? symbol.name.c_str() + linker_prefix.size()
  288. : symbol.name.c_str();
  289. if (IsArmMappingSymbol(p)) {
  290. symbol.is_label = false;
  291. }
  292. }
  293. }
  294. }
  295. callback(symbol);
  296. }
  297. }
  298. template <class ELFT>
  299. void AddSymbolForPltSection(const llvm::object::ELFObjectFile<ELFT>* elf,
  300. const std::function<void(const ElfFileSymbol&)>& callback) {
  301. // We may sample instructions in .plt section if the program
  302. // calls functions from shared libraries. Different architectures use
  303. // different formats to store .plt section, so it needs a lot of work to match
  304. // instructions in .plt section to symbols. As samples in .plt section rarely
  305. // happen, and .plt section can hardly be a performance bottleneck, we can
  306. // just use a symbol @plt to represent instructions in .plt section.
  307. for (auto it = elf->section_begin(); it != elf->section_end(); ++it) {
  308. const llvm::object::ELFSectionRef& section_ref = *it;
  309. llvm::StringRef section_name;
  310. std::error_code err = section_ref.getName(section_name);
  311. if (err || section_name != ".plt") {
  312. continue;
  313. }
  314. const auto* shdr = elf->getSection(section_ref.getRawDataRefImpl());
  315. if (shdr == nullptr) {
  316. return;
  317. }
  318. ElfFileSymbol symbol;
  319. symbol.vaddr = shdr->sh_addr;
  320. symbol.len = shdr->sh_size;
  321. symbol.is_func = true;
  322. symbol.is_label = true;
  323. symbol.is_in_text_section = true;
  324. symbol.name = "@plt";
  325. callback(symbol);
  326. return;
  327. }
  328. }
  329. template <class ELFT>
  330. void CheckSymbolSections(const llvm::object::ELFObjectFile<ELFT>* elf,
  331. bool* has_symtab, bool* has_dynsym) {
  332. *has_symtab = false;
  333. *has_dynsym = false;
  334. for (auto it = elf->section_begin(); it != elf->section_end(); ++it) {
  335. const llvm::object::ELFSectionRef& section_ref = *it;
  336. llvm::StringRef section_name;
  337. std::error_code err = section_ref.getName(section_name);
  338. if (err) {
  339. continue;
  340. }
  341. if (section_name == ".dynsym") {
  342. *has_dynsym = true;
  343. } else if (section_name == ".symtab") {
  344. *has_symtab = true;
  345. }
  346. }
  347. }
  348. template <class ELFT>
  349. ElfStatus ParseSymbolsFromELFFile(const llvm::object::ELFObjectFile<ELFT>* elf,
  350. const std::function<void(const ElfFileSymbol&)>& callback) {
  351. auto machine = elf->getELFFile()->getHeader()->e_machine;
  352. bool is_arm = (machine == llvm::ELF::EM_ARM || machine == llvm::ELF::EM_AARCH64);
  353. AddSymbolForPltSection(elf, callback);
  354. // Some applications deliberately ship elf files with broken section tables.
  355. // So check the existence of .symtab section and .dynsym section before reading symbols.
  356. bool has_symtab;
  357. bool has_dynsym;
  358. CheckSymbolSections(elf, &has_symtab, &has_dynsym);
  359. if (has_symtab && elf->symbol_begin() != elf->symbol_end()) {
  360. ReadSymbolTable(elf->symbol_begin(), elf->symbol_end(), callback, is_arm, elf->section_end());
  361. return ElfStatus::NO_ERROR;
  362. } else if (has_dynsym &&
  363. elf->dynamic_symbol_begin()->getRawDataRefImpl() != llvm::object::DataRefImpl()) {
  364. ReadSymbolTable(elf->dynamic_symbol_begin(), elf->dynamic_symbol_end(), callback, is_arm,
  365. elf->section_end());
  366. }
  367. std::string debugdata;
  368. ElfStatus result = ReadSectionFromELFFile(elf, ".gnu_debugdata", &debugdata);
  369. if (result == ElfStatus::SECTION_NOT_FOUND) {
  370. return ElfStatus::NO_SYMBOL_TABLE;
  371. } else if (result == ElfStatus::NO_ERROR) {
  372. std::string decompressed_data;
  373. if (XzDecompress(debugdata, &decompressed_data)) {
  374. BinaryWrapper wrapper;
  375. result = OpenObjectFileInMemory(decompressed_data.data(), decompressed_data.size(),
  376. &wrapper);
  377. if (result == ElfStatus::NO_ERROR) {
  378. if (auto elf = llvm::dyn_cast<llvm::object::ELF32LEObjectFile>(wrapper.obj)) {
  379. return ParseSymbolsFromELFFile(elf, callback);
  380. } else if (auto elf = llvm::dyn_cast<llvm::object::ELF64LEObjectFile>(wrapper.obj)) {
  381. return ParseSymbolsFromELFFile(elf, callback);
  382. } else {
  383. return ElfStatus::FILE_MALFORMED;
  384. }
  385. }
  386. }
  387. }
  388. return result;
  389. }
  390. ElfStatus MatchBuildId(llvm::object::ObjectFile* obj, const BuildId& expected_build_id) {
  391. if (expected_build_id.IsEmpty()) {
  392. return ElfStatus::NO_ERROR;
  393. }
  394. BuildId real_build_id;
  395. ElfStatus result = GetBuildIdFromObjectFile(obj, &real_build_id);
  396. if (result != ElfStatus::NO_ERROR) {
  397. return result;
  398. }
  399. if (expected_build_id != real_build_id) {
  400. return ElfStatus::BUILD_ID_MISMATCH;
  401. }
  402. return ElfStatus::NO_ERROR;
  403. }
  404. ElfStatus ParseSymbolsFromElfFile(const std::string& filename,
  405. const BuildId& expected_build_id,
  406. const std::function<void(const ElfFileSymbol&)>& callback) {
  407. ElfStatus result = IsValidElfPath(filename);
  408. if (result != ElfStatus::NO_ERROR) {
  409. return result;
  410. }
  411. return ParseSymbolsFromEmbeddedElfFile(filename, 0, 0, expected_build_id, callback);
  412. }
  413. ElfStatus ParseSymbolsFromEmbeddedElfFile(const std::string& filename, uint64_t file_offset,
  414. uint32_t file_size, const BuildId& expected_build_id,
  415. const std::function<void(const ElfFileSymbol&)>& callback) {
  416. BinaryWrapper wrapper;
  417. ElfStatus result = OpenObjectFile(filename, file_offset, file_size, &wrapper);
  418. if (result != ElfStatus::NO_ERROR) {
  419. return result;
  420. }
  421. result = MatchBuildId(wrapper.obj, expected_build_id);
  422. if (result != ElfStatus::NO_ERROR) {
  423. return result;
  424. }
  425. if (auto elf = llvm::dyn_cast<llvm::object::ELF32LEObjectFile>(wrapper.obj)) {
  426. return ParseSymbolsFromELFFile(elf, callback);
  427. } else if (auto elf = llvm::dyn_cast<llvm::object::ELF64LEObjectFile>(wrapper.obj)) {
  428. return ParseSymbolsFromELFFile(elf, callback);
  429. }
  430. return ElfStatus::FILE_MALFORMED;
  431. }
  432. ElfStatus ParseSymbolsFromElfFileInMemory(const char* data, size_t size,
  433. const std::function<void(const ElfFileSymbol&)>& callback) {
  434. BinaryWrapper wrapper;
  435. ElfStatus result = OpenObjectFileInMemory(data, size, &wrapper);
  436. if (result != ElfStatus::NO_ERROR) {
  437. return result;
  438. }
  439. if (auto elf = llvm::dyn_cast<llvm::object::ELF32LEObjectFile>(wrapper.obj)) {
  440. return ParseSymbolsFromELFFile(elf, callback);
  441. } else if (auto elf = llvm::dyn_cast<llvm::object::ELF64LEObjectFile>(wrapper.obj)) {
  442. return ParseSymbolsFromELFFile(elf, callback);
  443. }
  444. return ElfStatus::FILE_MALFORMED;
  445. }
  446. template <class ELFT>
  447. ElfStatus ParseDynamicSymbolsFromELFFile(const llvm::object::ELFObjectFile<ELFT>* elf,
  448. const std::function<void(const ElfFileSymbol&)>& callback) {
  449. auto machine = elf->getELFFile()->getHeader()->e_machine;
  450. bool is_arm = (machine == llvm::ELF::EM_ARM || machine == llvm::ELF::EM_AARCH64);
  451. ReadSymbolTable(elf->dynamic_symbol_begin(), elf->dynamic_symbol_end(), callback, is_arm,
  452. elf->section_end());
  453. return ElfStatus::NO_ERROR;
  454. }
  455. ElfStatus ParseDynamicSymbolsFromElfFile(const std::string& filename,
  456. const std::function<void(const ElfFileSymbol&)>& callback) {
  457. BinaryWrapper wrapper;
  458. ElfStatus result = OpenObjectFile(filename, 0, 0, &wrapper);
  459. if (result != ElfStatus::NO_ERROR) {
  460. return result;
  461. }
  462. if (auto elf = llvm::dyn_cast<llvm::object::ELF32LEObjectFile>(wrapper.obj)) {
  463. return ParseDynamicSymbolsFromELFFile(elf, callback);
  464. } else if (auto elf = llvm::dyn_cast<llvm::object::ELF64LEObjectFile>(wrapper.obj)) {
  465. return ParseDynamicSymbolsFromELFFile(elf, callback);
  466. }
  467. return ElfStatus::FILE_MALFORMED;
  468. }
  469. template <class ELFT>
  470. ElfStatus ReadMinExecutableVirtualAddress(const llvm::object::ELFFile<ELFT>* elf,
  471. uint64_t* p_vaddr,
  472. uint64_t* file_offset) {
  473. bool has_vaddr = false;
  474. uint64_t min_addr = std::numeric_limits<uint64_t>::max();
  475. for (auto it = elf->program_header_begin(); it != elf->program_header_end(); ++it) {
  476. if ((it->p_type == llvm::ELF::PT_LOAD) && (it->p_flags & llvm::ELF::PF_X)) {
  477. if (it->p_vaddr < min_addr) {
  478. min_addr = it->p_vaddr;
  479. *file_offset = it->p_offset;
  480. has_vaddr = true;
  481. }
  482. }
  483. }
  484. if (!has_vaddr) {
  485. // JIT symfiles don't have program headers.
  486. min_addr = 0;
  487. *file_offset = 0;
  488. }
  489. *p_vaddr = min_addr;
  490. return ElfStatus::NO_ERROR;
  491. }
  492. ElfStatus ReadMinExecutableVirtualAddressFromElfFile(const std::string& filename,
  493. const BuildId& expected_build_id,
  494. uint64_t* min_vaddr,
  495. uint64_t* file_offset_of_min_vaddr) {
  496. ElfStatus result = IsValidElfPath(filename);
  497. if (result != ElfStatus::NO_ERROR) {
  498. return result;
  499. }
  500. return ReadMinExecutableVirtualAddressFromEmbeddedElfFile(filename, 0, 0, expected_build_id,
  501. min_vaddr, file_offset_of_min_vaddr);
  502. }
  503. ElfStatus ReadMinExecutableVirtualAddressFromEmbeddedElfFile(const std::string& filename,
  504. uint64_t file_offset,
  505. uint32_t file_size,
  506. const BuildId& expected_build_id,
  507. uint64_t* min_vaddr,
  508. uint64_t* file_offset_of_min_vaddr) {
  509. BinaryWrapper wrapper;
  510. ElfStatus result = OpenObjectFile(filename, file_offset, file_size, &wrapper);
  511. if (result != ElfStatus::NO_ERROR) {
  512. return result;
  513. }
  514. result = MatchBuildId(wrapper.obj, expected_build_id);
  515. if (result != ElfStatus::NO_ERROR) {
  516. return result;
  517. }
  518. if (auto elf = llvm::dyn_cast<llvm::object::ELF32LEObjectFile>(wrapper.obj)) {
  519. return ReadMinExecutableVirtualAddress(elf->getELFFile(), min_vaddr, file_offset_of_min_vaddr);
  520. } else if (auto elf = llvm::dyn_cast<llvm::object::ELF64LEObjectFile>(wrapper.obj)) {
  521. return ReadMinExecutableVirtualAddress(elf->getELFFile(), min_vaddr, file_offset_of_min_vaddr);
  522. }
  523. return ElfStatus::FILE_MALFORMED;
  524. }
  525. ElfStatus ReadSectionFromElfFile(const std::string& filename, const std::string& section_name,
  526. std::string* content) {
  527. ElfStatus result = IsValidElfPath(filename);
  528. if (result != ElfStatus::NO_ERROR) {
  529. return result;
  530. }
  531. BinaryWrapper wrapper;
  532. result = OpenObjectFile(filename, 0, 0, &wrapper);
  533. if (result != ElfStatus::NO_ERROR) {
  534. return result;
  535. }
  536. if (auto elf = llvm::dyn_cast<llvm::object::ELF32LEObjectFile>(wrapper.obj)) {
  537. return ReadSectionFromELFFile(elf, section_name, content);
  538. } else if (auto elf = llvm::dyn_cast<llvm::object::ELF64LEObjectFile>(wrapper.obj)) {
  539. return ReadSectionFromELFFile(elf, section_name, content);
  540. } else {
  541. return ElfStatus::FILE_MALFORMED;
  542. }
  543. }