xref: /aosp_15_r20/external/sandboxed-api/sandboxed_api/sandbox2/util/minielf.cc (revision ec63e07ab9515d95e79c211197c445ef84cefa6a)
1 // Copyright 2019 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "sandboxed_api/sandbox2/util/minielf.h"
16 
17 #include <elf.h>
18 
19 #include <algorithm>
20 #include <cerrno>
21 #include <cstddef>
22 #include <cstdint>
23 #include <cstdio>
24 #include <cstring>
25 #include <string>
26 #include <type_traits>
27 #include <utility>
28 #include <vector>
29 
30 #include "absl/base/internal/endian.h"
31 #include "absl/status/status.h"
32 #include "absl/status/statusor.h"
33 #include "absl/strings/match.h"
34 #include "absl/strings/str_cat.h"
35 #include "absl/strings/string_view.h"
36 #include "sandboxed_api/config.h"
37 #include "sandboxed_api/sandbox2/util.h"
38 #include "sandboxed_api/util/raw_logging.h"
39 #include "sandboxed_api/util/status_macros.h"
40 
41 namespace host_cpu = ::sapi::host_cpu;
42 
43 namespace sandbox2 {
44 
45 using ElfEhdr = std::conditional_t<host_cpu::Is64Bit(), Elf64_Ehdr, Elf32_Ehdr>;
46 using ElfShdr = std::conditional_t<host_cpu::Is64Bit(), Elf64_Shdr, Elf32_Shdr>;
47 using ElfPhdr = std::conditional_t<host_cpu::Is64Bit(), Elf64_Phdr, Elf32_Phdr>;
48 using ElfDyn = std::conditional_t<host_cpu::Is64Bit(), Elf64_Dyn, Elf32_Dyn>;
49 using ElfSym = std::conditional_t<host_cpu::Is64Bit(), Elf64_Sym, Elf32_Sym>;
50 
51 constexpr int kElfHeaderSize = sizeof(ElfEhdr);  // Maximum size for binaries
52 
53 constexpr char kElfMagic[] =
54     "\x7F"
55     "ELF";
56 
57 constexpr int kEiClassOffset = 0x04;
58 constexpr int kEiClass = host_cpu::Is64Bit() ? ELFCLASS64 : ELFCLASS32;
59 
60 constexpr int kEiDataOffset = 0x05;
61 constexpr int kEiDataLittle = 1;  // Little Endian
62 constexpr int kEiDataBig = 2;     // Big Endian
63 
64 constexpr int kEiVersionOffset = 0x06;
65 constexpr int kEvCurrent = 1;  // ELF version
66 
67 namespace {
68 
69 // NOLINTNEXTLINE
CheckedFSeek(FILE * f,long offset,int whence)70 absl::Status CheckedFSeek(FILE* f, long offset, int whence) {
71   if (fseek(f, offset, whence)) {
72     return absl::ErrnoToStatus(errno, "Fseek on ELF failed");
73   }
74   return absl::OkStatus();
75 }
76 
CheckedFRead(void * dst,size_t size,size_t nmemb,FILE * f)77 absl::Status CheckedFRead(void* dst, size_t size, size_t nmemb, FILE* f) {
78   if (std::fread(dst, size, nmemb, f) == nmemb) {
79     return absl::OkStatus();
80   }
81   return absl::ErrnoToStatus(errno, "Reading ELF data failed");
82 }
83 
CheckedRead(std::string * s,FILE * f)84 absl::Status CheckedRead(std::string* s, FILE* f) {
85   return CheckedFRead(&(*s)[0], 1, s->size(), f);
86 }
87 
ReadName(uint32_t offset,absl::string_view strtab)88 absl::string_view ReadName(uint32_t offset, absl::string_view strtab) {
89   auto name = strtab.substr(offset);
90   return name.substr(0, name.find('\0'));
91 }
92 
93 }  //  namespace
94 
95 #define LOAD_MEMBER(data_struct, member, src)                            \
96   Load(&(data_struct).member,                                            \
97        &src[offsetof(std::remove_reference<decltype(data_struct)>::type, \
98                      member)])
99 
100 class ElfParser {
101  public:
102   // Arbitrary cut-off values, so we can parse safely.
103   static constexpr int kMaxProgramHeaderEntries = 500;
104   static constexpr int kMaxSectionHeaderEntries = 500;
105   static constexpr size_t kMaxSectionSize = 500 * 1024 * 1024;
106   static constexpr size_t kMaxStrtabSize = 500 * 1024 * 1024;
107   static constexpr size_t kMaxLibPathSize = 1024;
108   static constexpr int kMaxSymbolEntries = 4 * 1000 * 1000;
109   static constexpr int kMaxDynamicEntries = 10000;
110   static constexpr size_t kMaxInterpreterSize = 1000;
111 
112   static absl::StatusOr<ElfFile> Parse(const std::string& filename,
113                                        uint32_t features);
114 
~ElfParser()115   ~ElfParser() {
116     if (elf_) {
117       std::fclose(elf_);
118     }
119   }
120 
121  private:
122   ElfParser() = default;
123 
124   // Endianess support functions
Load16(const void * src)125   uint16_t Load16(const void* src) {
126     return elf_little_ ? absl::little_endian::Load16(src)
127                        : absl::big_endian::Load16(src);
128   }
Load32(const void * src)129   uint32_t Load32(const void* src) {
130     return elf_little_ ? absl::little_endian::Load32(src)
131                        : absl::big_endian::Load32(src);
132   }
Load64(const void * src)133   uint64_t Load64(const void* src) {
134     return elf_little_ ? absl::little_endian::Load64(src)
135                        : absl::big_endian::Load64(src);
136   }
137 
138   template <size_t N>
Load(unsigned char (* dst)[N],const void * src)139   void Load(unsigned char (*dst)[N], const void* src) {
140     memcpy(dst, src, N);
141   }
142 
143   template <typename IntT>
Load(IntT * dst,const void * src)144   std::enable_if_t<std::is_integral_v<IntT>, void> Load(IntT* dst,
145                                                         const void* src) {
146     switch (sizeof(IntT)) {
147       case 1:
148         *dst = *reinterpret_cast<const char*>(src);
149         break;
150       case 2:
151         *dst = Load16(src);
152         break;
153       case 4:
154         *dst = Load32(src);
155         break;
156       case 8:
157         *dst = Load64(src);
158         break;
159     }
160   }
161 
162   // Reads ELF file size.
163   absl::Status ReadFileSize();
164   // Reads ELF header.
165   absl::Status ReadFileHeader();
166   // Reads a single ELF program header.
167   absl::StatusOr<ElfPhdr> ReadProgramHeader(absl::string_view src);
168   // Reads all ELF program headers.
169   absl::Status ReadProgramHeaders();
170   // Reads a single ELF section header.
171   absl::StatusOr<ElfShdr> ReadSectionHeader(absl::string_view src);
172   // Reads all ELF section headers.
173   absl::Status ReadSectionHeaders();
174   // Reads contents of an ELF section.
175   absl::StatusOr<std::string> ReadSectionContents(int idx);
176   absl::StatusOr<std::string> ReadSectionContents(
177       const ElfShdr& section_header);
178   // Reads all symbols from symtab section.
179   absl::Status ReadSymbolsFromSymtab(const ElfShdr& symtab);
180   // Reads all imported libraries from dynamic section.
181   absl::Status ReadImportedLibrariesFromDynamic(const ElfShdr& dynamic);
182 
183   ElfFile result_;
184   FILE* elf_ = nullptr;
185   size_t file_size_ = 0;
186   bool elf_little_ = false;
187   ElfEhdr file_header_;
188   std::vector<ElfPhdr> program_headers_;
189   std::vector<ElfShdr> section_headers_;
190 
191   int symbol_entries_read = 0;
192   int dynamic_entries_read = 0;
193 };
194 
ReadFileSize()195 absl::Status ElfParser::ReadFileSize() {
196   std::fseek(elf_, 0, SEEK_END);
197   file_size_ = std::ftell(elf_);
198   if (file_size_ < kElfHeaderSize) {
199     return absl::FailedPreconditionError(
200         absl::StrCat("file too small: ", file_size_, " bytes, at least ",
201                      kElfHeaderSize, " bytes expected"));
202   }
203   return absl::OkStatus();
204 }
205 
ReadFileHeader()206 absl::Status ElfParser::ReadFileHeader() {
207   std::string header(kElfHeaderSize, '\0');
208   SAPI_RETURN_IF_ERROR(CheckedFSeek(elf_, 0, SEEK_SET));
209   SAPI_RETURN_IF_ERROR(CheckedRead(&header, elf_));
210 
211   if (!absl::StartsWith(header, kElfMagic)) {
212     return absl::FailedPreconditionError("magic not found, not an ELF");
213   }
214 
215   if (header[kEiClassOffset] != kEiClass) {
216     return absl::FailedPreconditionError("invalid ELF class");
217   }
218   const auto elf_data = header[kEiDataOffset];
219   elf_little_ = elf_data == kEiDataLittle;
220   if (!elf_little_ && elf_data != kEiDataBig) {
221     return absl::FailedPreconditionError("invalid endianness");
222   }
223 
224   if (header[kEiVersionOffset] != kEvCurrent) {
225     return absl::FailedPreconditionError("invalid ELF version");
226   }
227   LOAD_MEMBER(file_header_, e_ident, header.data());
228   LOAD_MEMBER(file_header_, e_type, header.data());
229   LOAD_MEMBER(file_header_, e_machine, header.data());
230   LOAD_MEMBER(file_header_, e_version, header.data());
231   LOAD_MEMBER(file_header_, e_entry, header.data());
232   LOAD_MEMBER(file_header_, e_phoff, header.data());
233   LOAD_MEMBER(file_header_, e_shoff, header.data());
234   LOAD_MEMBER(file_header_, e_flags, header.data());
235   LOAD_MEMBER(file_header_, e_ehsize, header.data());
236   LOAD_MEMBER(file_header_, e_phentsize, header.data());
237   LOAD_MEMBER(file_header_, e_phnum, header.data());
238   LOAD_MEMBER(file_header_, e_shentsize, header.data());
239   LOAD_MEMBER(file_header_, e_shnum, header.data());
240   LOAD_MEMBER(file_header_, e_shstrndx, header.data());
241   return absl::OkStatus();
242 }
243 
ReadSectionHeader(absl::string_view src)244 absl::StatusOr<ElfShdr> ElfParser::ReadSectionHeader(absl::string_view src) {
245   if (src.size() < sizeof(ElfShdr)) {
246     return absl::FailedPreconditionError(
247         absl::StrCat("invalid section header data: got ", src.size(),
248                      " bytes, ", sizeof(ElfShdr), " bytes expected."));
249   }
250   ElfShdr rv;
251   LOAD_MEMBER(rv, sh_name, src.data());
252   LOAD_MEMBER(rv, sh_type, src.data());
253   LOAD_MEMBER(rv, sh_flags, src.data());
254   LOAD_MEMBER(rv, sh_addr, src.data());
255   LOAD_MEMBER(rv, sh_offset, src.data());
256   LOAD_MEMBER(rv, sh_size, src.data());
257   LOAD_MEMBER(rv, sh_link, src.data());
258   LOAD_MEMBER(rv, sh_info, src.data());
259   LOAD_MEMBER(rv, sh_addralign, src.data());
260   LOAD_MEMBER(rv, sh_entsize, src.data());
261   return rv;
262 }
263 
ReadSectionHeaders()264 absl::Status ElfParser::ReadSectionHeaders() {
265   if (file_header_.e_shoff > file_size_) {
266     return absl::FailedPreconditionError(
267         absl::StrCat("invalid section header offset: ", file_header_.e_shoff));
268   }
269   if (file_header_.e_shentsize != sizeof(ElfShdr)) {
270     return absl::FailedPreconditionError(absl::StrCat(
271         "section header entry size incorrect: ", file_header_.e_shentsize,
272         " bytes, ", sizeof(ElfShdr), " expected."));
273   }
274   if (file_header_.e_shnum > kMaxSectionHeaderEntries) {
275     return absl::FailedPreconditionError(
276         absl::StrCat("too many section header entries: ", file_header_.e_shnum,
277                      " limit: ", kMaxSectionHeaderEntries));
278   }
279   std::string headers(file_header_.e_shentsize * file_header_.e_shnum, '\0');
280   SAPI_RETURN_IF_ERROR(CheckedFSeek(elf_, file_header_.e_shoff, SEEK_SET));
281   SAPI_RETURN_IF_ERROR(CheckedRead(&headers, elf_));
282   section_headers_.resize(file_header_.e_shnum);
283   absl::string_view src = headers;
284   for (int i = 0; i < file_header_.e_shnum; ++i) {
285     SAPI_ASSIGN_OR_RETURN(section_headers_[i], ReadSectionHeader(src));
286     src = src.substr(file_header_.e_shentsize);
287   }
288   return absl::OkStatus();
289 }
290 
ReadSectionContents(int idx)291 absl::StatusOr<std::string> ElfParser::ReadSectionContents(int idx) {
292   if (idx < 0 || idx >= section_headers_.size()) {
293     return absl::FailedPreconditionError(
294         absl::StrCat("invalid section header index: ", idx));
295   }
296   return ReadSectionContents(section_headers_.at(idx));
297 }
298 
ReadSectionContents(const ElfShdr & section_header)299 absl::StatusOr<std::string> ElfParser::ReadSectionContents(
300     const ElfShdr& section_header) {
301   auto offset = section_header.sh_offset;
302   if (offset > file_size_) {
303     return absl::FailedPreconditionError(
304         absl::StrCat("invalid section offset: ", offset));
305   }
306   auto size = section_header.sh_size;
307   if (size > kMaxSectionSize) {
308     return absl::FailedPreconditionError(
309         absl::StrCat("section too big: ", size, " limit: ", kMaxSectionSize));
310   }
311   std::string rv(size, '\0');
312   SAPI_RETURN_IF_ERROR(CheckedFSeek(elf_, offset, SEEK_SET));
313   SAPI_RETURN_IF_ERROR(CheckedRead(&rv, elf_));
314   return rv;
315 }
316 
ReadProgramHeader(absl::string_view src)317 absl::StatusOr<ElfPhdr> ElfParser::ReadProgramHeader(absl::string_view src) {
318   if (src.size() < sizeof(ElfPhdr)) {
319     return absl::FailedPreconditionError(
320         absl::StrCat("invalid program header data: got ", src.size(),
321                      " bytes, ", sizeof(ElfPhdr), " bytes expected."));
322   }
323   ElfPhdr rv;
324   LOAD_MEMBER(rv, p_type, src.data());
325   LOAD_MEMBER(rv, p_flags, src.data());
326   LOAD_MEMBER(rv, p_offset, src.data());
327   LOAD_MEMBER(rv, p_vaddr, src.data());
328   LOAD_MEMBER(rv, p_paddr, src.data());
329   LOAD_MEMBER(rv, p_filesz, src.data());
330   LOAD_MEMBER(rv, p_memsz, src.data());
331   LOAD_MEMBER(rv, p_align, src.data());
332   return rv;
333 }
334 
ReadProgramHeaders()335 absl::Status ElfParser::ReadProgramHeaders() {
336   if (file_header_.e_phoff > file_size_) {
337     return absl::FailedPreconditionError(
338         absl::StrCat("invalid program header offset: ", file_header_.e_phoff));
339   }
340   if (file_header_.e_phentsize != sizeof(ElfPhdr)) {
341     return absl::FailedPreconditionError(absl::StrCat(
342         "section header entry size incorrect: ", file_header_.e_phentsize,
343         " bytes, ", sizeof(ElfPhdr), " expected."));
344   }
345   if (file_header_.e_phnum > kMaxProgramHeaderEntries) {
346     return absl::FailedPreconditionError(
347         absl::StrCat("too many program header entries: ", file_header_.e_phnum,
348                      " limit: ", kMaxProgramHeaderEntries));
349   }
350   std::string headers(file_header_.e_phentsize * file_header_.e_phnum, '\0');
351   SAPI_RETURN_IF_ERROR(CheckedFSeek(elf_, file_header_.e_phoff, SEEK_SET));
352   SAPI_RETURN_IF_ERROR(CheckedRead(&headers, elf_));
353   program_headers_.resize(file_header_.e_phnum);
354   absl::string_view src = headers;
355   for (int i = 0; i < file_header_.e_phnum; ++i) {
356     SAPI_ASSIGN_OR_RETURN(program_headers_[i], ReadProgramHeader(src));
357     src = src.substr(file_header_.e_phentsize);
358   }
359   return absl::OkStatus();
360 }
361 
ReadSymbolsFromSymtab(const ElfShdr & symtab)362 absl::Status ElfParser::ReadSymbolsFromSymtab(const ElfShdr& symtab) {
363   if (symtab.sh_type != SHT_SYMTAB) {
364     return absl::FailedPreconditionError("invalid symtab type");
365   }
366   if (symtab.sh_entsize != sizeof(ElfSym)) {
367     return absl::InternalError(
368         absl::StrCat("invalid symbol entry size: ", symtab.sh_entsize));
369   }
370   if ((symtab.sh_size % symtab.sh_entsize) != 0) {
371     return absl::InternalError(
372         absl::StrCat("invalid symbol table size: ", symtab.sh_size));
373   }
374   size_t symbol_entries = symtab.sh_size / symtab.sh_entsize;
375   if (symbol_entries > kMaxSymbolEntries - symbol_entries_read) {
376     return absl::InternalError(
377         absl::StrCat("too many symbols: ", symbol_entries));
378   }
379   symbol_entries_read += symbol_entries;
380   if (symtab.sh_link >= section_headers_.size()) {
381     return absl::InternalError(
382         absl::StrCat("invalid symtab's strtab reference: ", symtab.sh_link));
383   }
384   SAPI_RAW_VLOG(1, "Symbol table with %zu entries found", symbol_entries);
385   SAPI_ASSIGN_OR_RETURN(std::string strtab,
386                         ReadSectionContents(symtab.sh_link));
387   SAPI_ASSIGN_OR_RETURN(std::string symbols, ReadSectionContents(symtab));
388   result_.symbols_.reserve(result_.symbols_.size() + symbol_entries);
389   for (absl::string_view src = symbols; !src.empty();
390        src = src.substr(symtab.sh_entsize)) {
391     ElfSym symbol;
392     LOAD_MEMBER(symbol, st_name, src.data());
393     LOAD_MEMBER(symbol, st_info, src.data());
394     LOAD_MEMBER(symbol, st_other, src.data());
395     LOAD_MEMBER(symbol, st_shndx, src.data());
396     LOAD_MEMBER(symbol, st_value, src.data());
397     LOAD_MEMBER(symbol, st_size, src.data());
398     if (symbol.st_shndx == SHN_UNDEF) {
399       // External symbol, not supported.
400       continue;
401     }
402     if (symbol.st_shndx == SHN_ABS) {
403       // Absolute value, not supported.
404       continue;
405     }
406     if (symbol.st_shndx >= section_headers_.size()) {
407       return absl::FailedPreconditionError(absl::StrCat(
408           "invalid symbol data: section index: ", symbol.st_shndx));
409     }
410     if (symbol.st_name >= strtab.size()) {
411       return absl::FailedPreconditionError(
412           absl::StrCat("invalid name reference: REL", symbol.st_value));
413     }
414     result_.symbols_.push_back(
415         {symbol.st_value, std::string(ReadName(symbol.st_name, strtab))});
416   }
417   return absl::OkStatus();
418 }
419 
ReadImportedLibrariesFromDynamic(const ElfShdr & dynamic)420 absl::Status ElfParser::ReadImportedLibrariesFromDynamic(
421     const ElfShdr& dynamic) {
422   if (dynamic.sh_type != SHT_DYNAMIC) {
423     return absl::FailedPreconditionError("invalid dynamic type");
424   }
425   if (dynamic.sh_entsize != sizeof(ElfDyn)) {
426     return absl::InternalError(
427         absl::StrCat("invalid dynamic entry size: ", dynamic.sh_entsize));
428   }
429   if ((dynamic.sh_size % dynamic.sh_entsize) != 0) {
430     return absl::InternalError(
431         absl::StrCat("invalid dynamic table size: ", dynamic.sh_size));
432   }
433   size_t entries = dynamic.sh_size / dynamic.sh_entsize;
434   if (entries > kMaxDynamicEntries - dynamic_entries_read) {
435     return absl::InternalError(
436         absl::StrCat("too many dynamic entries: ", entries));
437   }
438   dynamic_entries_read += entries;
439   if (dynamic.sh_link >= section_headers_.size()) {
440     return absl::InternalError(
441         absl::StrCat("invalid dynamic's strtab reference: ", dynamic.sh_link));
442   }
443   SAPI_RAW_VLOG(1, "Dynamic section with %zu entries found", entries);
444   // strtab may be shared with symbols and therefore huge
445   const auto& strtab_section = section_headers_.at(dynamic.sh_link);
446   if (strtab_section.sh_offset > file_size_) {
447     return absl::FailedPreconditionError(absl::StrCat(
448         "invalid symtab's strtab section offset: ", strtab_section.sh_offset));
449   }
450   if (strtab_section.sh_size >= kMaxStrtabSize ||
451       strtab_section.sh_size >= file_size_ ||
452       strtab_section.sh_offset >= file_size_ - strtab_section.sh_size) {
453     return absl::FailedPreconditionError(
454         absl::StrCat("symtab's strtab too big: ", strtab_section.sh_size));
455   }
456   auto strtab_end = strtab_section.sh_offset + strtab_section.sh_size;
457   SAPI_ASSIGN_OR_RETURN(std::string dynamic_entries,
458                         ReadSectionContents(dynamic));
459   for (absl::string_view src = dynamic_entries; !src.empty();
460        src = src.substr(dynamic.sh_entsize)) {
461     ElfDyn dyn;
462     LOAD_MEMBER(dyn, d_tag, src.data());
463     LOAD_MEMBER(dyn, d_un.d_val, src.data());
464     if (dyn.d_tag != DT_NEEDED) {
465       continue;
466     }
467     if (dyn.d_un.d_val >= strtab_section.sh_size) {
468       return absl::FailedPreconditionError(
469           absl::StrCat("invalid name reference"));
470     }
471     auto offset = strtab_section.sh_offset + dyn.d_un.d_val;
472     SAPI_RETURN_IF_ERROR(CheckedFSeek(elf_, offset, SEEK_SET));
473     std::string path(
474         std::min(kMaxLibPathSize, static_cast<size_t>(strtab_end - offset)),
475         '\0');
476     size_t size = std::fread(&path[0], 1, path.size(), elf_);
477     path.resize(size);
478     result_.imported_libraries_.push_back(path.substr(0, path.find('\0')));
479   }
480   return absl::OkStatus();
481 }
482 
Parse(const std::string & filename,uint32_t features)483 absl::StatusOr<ElfFile> ElfParser::Parse(const std::string& filename,
484                                          uint32_t features) {
485   ElfParser parser;
486   if (parser.elf_ = std::fopen(filename.c_str(), "r"); !parser.elf_) {
487     return absl::ErrnoToStatus(errno,
488                                absl::StrCat("cannot open file: ", filename));
489   }
490 
491   // Basic sanity check.
492   if (features & ~(ElfFile::kAll)) {
493     return absl::InvalidArgumentError("Unknown feature flags specified");
494   }
495   SAPI_RETURN_IF_ERROR(parser.ReadFileSize());
496   SAPI_RETURN_IF_ERROR(parser.ReadFileHeader());
497   switch (parser.file_header_.e_type) {
498     case ET_EXEC:
499       parser.result_.position_independent_ = false;
500       break;
501     case ET_DYN:
502       parser.result_.position_independent_ = true;
503       break;
504     default:
505       return absl::FailedPreconditionError("not an executable: ");
506   }
507   if (features & ElfFile::kGetInterpreter) {
508     SAPI_RETURN_IF_ERROR(parser.ReadProgramHeaders());
509     std::string interpreter;
510     auto it = std::find_if(
511         parser.program_headers_.begin(), parser.program_headers_.end(),
512         [](const ElfPhdr& hdr) { return hdr.p_type == PT_INTERP; });
513     // No interpreter usually means that the executable was statically linked.
514     if (it != parser.program_headers_.end()) {
515       if (it->p_filesz > kMaxInterpreterSize) {
516         return absl::FailedPreconditionError(
517             absl::StrCat("program interpeter path too long: ", it->p_filesz));
518       }
519       SAPI_RETURN_IF_ERROR(CheckedFSeek(parser.elf_, it->p_offset, SEEK_SET));
520       interpreter.resize(it->p_filesz, '\0');
521       SAPI_RETURN_IF_ERROR(CheckedRead(&interpreter, parser.elf_));
522       auto first_nul = interpreter.find_first_of('\0');
523       if (first_nul != std::string::npos) {
524         interpreter.erase(first_nul);
525       }
526     }
527     parser.result_.interpreter_ = std::move(interpreter);
528   }
529 
530   if (features & (ElfFile::kLoadSymbols | ElfFile::kLoadImportedLibraries)) {
531     SAPI_RETURN_IF_ERROR(parser.ReadSectionHeaders());
532     for (const auto& hdr : parser.section_headers_) {
533       if (hdr.sh_type == SHT_SYMTAB && features & ElfFile::kLoadSymbols) {
534         SAPI_RETURN_IF_ERROR(parser.ReadSymbolsFromSymtab(hdr));
535       }
536       if (hdr.sh_type == SHT_DYNAMIC &&
537           features & ElfFile::kLoadImportedLibraries) {
538         SAPI_RETURN_IF_ERROR(parser.ReadImportedLibrariesFromDynamic(hdr));
539       }
540     }
541   }
542 
543   return std::move(parser.result_);
544 }
545 
ParseFromFile(const std::string & filename,uint32_t features)546 absl::StatusOr<ElfFile> ElfFile::ParseFromFile(const std::string& filename,
547                                                uint32_t features) {
548   return ElfParser::Parse(filename, features);
549 }
550 
551 }  // namespace sandbox2
552