1 /* 2 * Copyright (C) 2012 The Android Open Source Project 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * * Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * * Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in 12 * the documentation and/or other materials provided with the 13 * distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 18 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 19 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 22 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 25 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29 #pragma once 30 31 /* Declarations related to the ELF program header table and segments. 32 * 33 * The design goal is to provide an API that is as close as possible 34 * to the ELF spec, and does not depend on linker-specific data 35 * structures (e.g. the exact layout of struct soinfo). 36 */ 37 38 #include "linker.h" 39 #include "linker_mapped_file_fragment.h" 40 #include "linker_note_gnu_property.h" 41 42 class ElfReader { 43 public: 44 ElfReader(); 45 46 bool Read(const char* name, int fd, off64_t file_offset, off64_t file_size); 47 bool Load(address_space_params* address_space); 48 name()49 const char* name() const { return name_.c_str(); } phdr_count()50 size_t phdr_count() const { return phdr_num_; } load_start()51 ElfW(Addr) load_start() const { return reinterpret_cast<ElfW(Addr)>(load_start_); } load_size()52 size_t load_size() const { return load_size_; } gap_start()53 ElfW(Addr) gap_start() const { return reinterpret_cast<ElfW(Addr)>(gap_start_); } gap_size()54 size_t gap_size() const { return gap_size_; } load_bias()55 ElfW(Addr) load_bias() const { return load_bias_; } ElfW(Phdr)56 const ElfW(Phdr)* loaded_phdr() const { return loaded_phdr_; } ElfW(Dyn)57 const ElfW(Dyn)* dynamic() const { return dynamic_; } 58 const char* get_string(ElfW(Word) index) const; is_mapped_by_caller()59 bool is_mapped_by_caller() const { return mapped_by_caller_; } entry_point()60 ElfW(Addr) entry_point() const { return header_.e_entry + load_bias_; } 61 62 private: 63 bool ReadElfHeader(); 64 bool VerifyElfHeader(); 65 bool ReadProgramHeaders(); 66 bool ReadSectionHeaders(); 67 bool ReadDynamicSection(); 68 bool ReserveAddressSpace(address_space_params* address_space); 69 bool LoadSegments(); 70 bool FindPhdr(); 71 bool FindGnuPropertySection(); 72 bool CheckPhdr(ElfW(Addr)); 73 bool CheckFileRange(ElfW(Addr) offset, size_t size, size_t alignment); 74 75 bool did_read_; 76 bool did_load_; 77 std::string name_; 78 int fd_; 79 off64_t file_offset_; 80 off64_t file_size_; 81 82 ElfW(Ehdr) header_; 83 size_t phdr_num_; 84 85 MappedFileFragment phdr_fragment_; 86 const ElfW(Phdr)* phdr_table_; 87 88 MappedFileFragment shdr_fragment_; 89 const ElfW(Shdr)* shdr_table_; 90 size_t shdr_num_; 91 92 MappedFileFragment dynamic_fragment_; 93 const ElfW(Dyn)* dynamic_; 94 95 MappedFileFragment strtab_fragment_; 96 const char* strtab_; 97 size_t strtab_size_; 98 99 // First page of reserved address space. 100 void* load_start_; 101 // Size in bytes of reserved address space. 102 size_t load_size_; 103 // First page of inaccessible gap mapping reserved for this DSO. 104 void* gap_start_; 105 // Size in bytes of the gap mapping. 106 size_t gap_size_; 107 // Load bias. 108 ElfW(Addr) load_bias_; 109 110 // Loaded phdr. 111 const ElfW(Phdr)* loaded_phdr_; 112 113 // Is map owned by the caller 114 bool mapped_by_caller_; 115 116 // Only used by AArch64 at the moment. 117 GnuPropertySection note_gnu_property_ __unused; 118 }; 119 120 size_t phdr_table_get_load_size(const ElfW(Phdr)* phdr_table, size_t phdr_count, 121 ElfW(Addr)* min_vaddr = nullptr, ElfW(Addr)* max_vaddr = nullptr); 122 123 size_t phdr_table_get_maximum_alignment(const ElfW(Phdr)* phdr_table, size_t phdr_count); 124 125 int phdr_table_protect_segments(const ElfW(Phdr)* phdr_table, size_t phdr_count, 126 ElfW(Addr) load_bias, const GnuPropertySection* prop = nullptr); 127 128 int phdr_table_unprotect_segments(const ElfW(Phdr)* phdr_table, size_t phdr_count, 129 ElfW(Addr) load_bias); 130 131 int phdr_table_protect_gnu_relro(const ElfW(Phdr)* phdr_table, size_t phdr_count, 132 ElfW(Addr) load_bias); 133 134 int phdr_table_serialize_gnu_relro(const ElfW(Phdr)* phdr_table, size_t phdr_count, 135 ElfW(Addr) load_bias, int fd, size_t* file_offset); 136 137 int phdr_table_map_gnu_relro(const ElfW(Phdr)* phdr_table, size_t phdr_count, 138 ElfW(Addr) load_bias, int fd, size_t* file_offset); 139 140 #if defined(__arm__) 141 int phdr_table_get_arm_exidx(const ElfW(Phdr)* phdr_table, size_t phdr_count, ElfW(Addr) load_bias, 142 ElfW(Addr)** arm_exidx, size_t* arm_exidix_count); 143 #endif 144 145 void phdr_table_get_dynamic_section(const ElfW(Phdr)* phdr_table, size_t phdr_count, 146 ElfW(Addr) load_bias, ElfW(Dyn)** dynamic, 147 ElfW(Word)* dynamic_flags); 148 149 const char* phdr_table_get_interpreter_name(const ElfW(Phdr)* phdr_table, size_t phdr_count, 150 ElfW(Addr) load_bias); 151