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 [[nodiscard]] bool Read(const char* name, int fd, off64_t file_offset, off64_t file_size); 47 [[nodiscard]] 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_; } should_pad_segments()61 bool should_pad_segments() const { return should_pad_segments_; } 62 63 private: 64 [[nodiscard]] bool ReadElfHeader(); 65 [[nodiscard]] bool VerifyElfHeader(); 66 [[nodiscard]] bool ReadProgramHeaders(); 67 [[nodiscard]] bool ReadSectionHeaders(); 68 [[nodiscard]] bool ReadDynamicSection(); 69 [[nodiscard]] bool ReadPadSegmentNote(); 70 [[nodiscard]] bool ReserveAddressSpace(address_space_params* address_space); 71 [[nodiscard]] bool LoadSegments(); 72 [[nodiscard]] bool FindPhdr(); 73 [[nodiscard]] bool FindGnuPropertySection(); 74 [[nodiscard]] bool CheckPhdr(ElfW(Addr)); 75 [[nodiscard]] bool CheckFileRange(ElfW(Addr) offset, size_t size, size_t alignment); 76 77 bool did_read_; 78 bool did_load_; 79 std::string name_; 80 int fd_; 81 off64_t file_offset_; 82 off64_t file_size_; 83 84 ElfW(Ehdr) header_; 85 size_t phdr_num_; 86 87 MappedFileFragment phdr_fragment_; 88 const ElfW(Phdr)* phdr_table_; 89 90 MappedFileFragment shdr_fragment_; 91 const ElfW(Shdr)* shdr_table_; 92 size_t shdr_num_; 93 94 MappedFileFragment dynamic_fragment_; 95 const ElfW(Dyn)* dynamic_; 96 97 MappedFileFragment strtab_fragment_; 98 const char* strtab_; 99 size_t strtab_size_; 100 101 // First page of reserved address space. 102 void* load_start_; 103 // Size in bytes of reserved address space. 104 size_t load_size_; 105 // First page of inaccessible gap mapping reserved for this DSO. 106 void* gap_start_; 107 // Size in bytes of the gap mapping. 108 size_t gap_size_; 109 // Load bias. 110 ElfW(Addr) load_bias_; 111 112 // Loaded phdr. 113 const ElfW(Phdr)* loaded_phdr_; 114 115 // Is map owned by the caller 116 bool mapped_by_caller_; 117 118 // Pad gaps between segments when memory mapping? 119 bool should_pad_segments_ = false; 120 121 // Only used by AArch64 at the moment. 122 GnuPropertySection note_gnu_property_ __unused; 123 }; 124 125 size_t phdr_table_get_load_size(const ElfW(Phdr)* phdr_table, size_t phdr_count, 126 ElfW(Addr)* min_vaddr = nullptr, ElfW(Addr)* max_vaddr = nullptr); 127 128 size_t phdr_table_get_maximum_alignment(const ElfW(Phdr)* phdr_table, size_t phdr_count); 129 130 int phdr_table_protect_segments(const ElfW(Phdr)* phdr_table, size_t phdr_count, 131 ElfW(Addr) load_bias, bool should_pad_segments, 132 const GnuPropertySection* prop = nullptr); 133 134 int phdr_table_unprotect_segments(const ElfW(Phdr)* phdr_table, size_t phdr_count, 135 ElfW(Addr) load_bias, bool should_pad_segments); 136 137 int phdr_table_protect_gnu_relro(const ElfW(Phdr)* phdr_table, size_t phdr_count, 138 ElfW(Addr) load_bias, bool should_pad_segments); 139 140 int phdr_table_serialize_gnu_relro(const ElfW(Phdr)* phdr_table, size_t phdr_count, 141 ElfW(Addr) load_bias, int fd, size_t* file_offset); 142 143 int phdr_table_map_gnu_relro(const ElfW(Phdr)* phdr_table, size_t phdr_count, 144 ElfW(Addr) load_bias, int fd, size_t* file_offset); 145 146 #if defined(__arm__) 147 int phdr_table_get_arm_exidx(const ElfW(Phdr)* phdr_table, size_t phdr_count, ElfW(Addr) load_bias, 148 ElfW(Addr)** arm_exidx, size_t* arm_exidix_count); 149 #endif 150 151 void phdr_table_get_dynamic_section(const ElfW(Phdr)* phdr_table, size_t phdr_count, 152 ElfW(Addr) load_bias, ElfW(Dyn)** dynamic, 153 ElfW(Word)* dynamic_flags); 154 155 const char* phdr_table_get_interpreter_name(const ElfW(Phdr)* phdr_table, size_t phdr_count, 156 ElfW(Addr) load_bias); 157 158 bool page_size_migration_supported(); 159