1 /* 2 * Copyright (C) 2012 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 #ifndef ART_COMPILER_ELF_WRITER_QUICK_H_ 18 #define ART_COMPILER_ELF_WRITER_QUICK_H_ 19 20 #include "elf_utils.h" 21 #include "elf_writer.h" 22 #include "instruction_set.h" 23 24 namespace art { 25 26 class ElfWriterQuick FINAL : public ElfWriter { 27 public: 28 // Write an ELF file. Returns true on success, false on failure. 29 static bool Create(File* file, 30 OatWriter* oat_writer, 31 const std::vector<const DexFile*>& dex_files, 32 const std::string& android_root, 33 bool is_host, 34 const CompilerDriver& driver) 35 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 36 37 protected: 38 bool Write(OatWriter* oat_writer, 39 const std::vector<const DexFile*>& dex_files, 40 const std::string& android_root, 41 bool is_host) 42 OVERRIDE 43 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 44 45 private: ElfWriterQuick(const CompilerDriver & driver,File * elf_file)46 ElfWriterQuick(const CompilerDriver& driver, File* elf_file) 47 : ElfWriter(driver, elf_file) {} ~ElfWriterQuick()48 ~ElfWriterQuick() {} 49 50 class ElfBuilder; 51 void AddDebugSymbols(ElfBuilder& builder, 52 OatWriter* oat_writer, 53 bool debug); 54 void ReservePatchSpace(std::vector<uint8_t>* buffer, bool debug); 55 56 class ElfSectionBuilder { 57 public: ElfSectionBuilder(const std::string & sec_name,Elf32_Word type,Elf32_Word flags,const ElfSectionBuilder * link,Elf32_Word info,Elf32_Word align,Elf32_Word entsize)58 ElfSectionBuilder(const std::string& sec_name, Elf32_Word type, Elf32_Word flags, 59 const ElfSectionBuilder *link, Elf32_Word info, Elf32_Word align, 60 Elf32_Word entsize) 61 : name_(sec_name), link_(link) { 62 memset(§ion_, 0, sizeof(section_)); 63 section_.sh_type = type; 64 section_.sh_flags = flags; 65 section_.sh_info = info; 66 section_.sh_addralign = align; 67 section_.sh_entsize = entsize; 68 } 69 ~ElfSectionBuilder()70 virtual ~ElfSectionBuilder() {} 71 72 Elf32_Shdr section_; 73 Elf32_Word section_index_ = 0; 74 75 protected: 76 const std::string name_; 77 const ElfSectionBuilder* link_; 78 GetLink()79 Elf32_Word GetLink() { 80 return (link_) ? link_->section_index_ : 0; 81 } 82 83 private: 84 friend class ElfBuilder; 85 }; 86 87 class ElfDynamicBuilder : public ElfSectionBuilder { 88 public: 89 void AddDynamicTag(Elf32_Sword tag, Elf32_Word d_un); 90 void AddDynamicTag(Elf32_Sword tag, Elf32_Word offset, ElfSectionBuilder* section); 91 ElfDynamicBuilder(const std::string & sec_name,ElfSectionBuilder * link)92 ElfDynamicBuilder(const std::string& sec_name, ElfSectionBuilder *link) 93 : ElfSectionBuilder(sec_name, SHT_DYNAMIC, SHF_ALLOC | SHF_ALLOC, link, 94 0, kPageSize, sizeof(Elf32_Dyn)) {} ~ElfDynamicBuilder()95 ~ElfDynamicBuilder() {} 96 97 protected: 98 struct ElfDynamicState { 99 ElfSectionBuilder* section_; 100 Elf32_Sword tag_; 101 Elf32_Word off_; 102 }; 103 std::vector<ElfDynamicState> dynamics_; GetSize()104 Elf32_Word GetSize() { 105 // Add 1 for the DT_NULL, 1 for DT_STRSZ, and 1 for DT_SONAME. All of 106 // these must be added when we actually put the file together because 107 // their values are very dependent on state. 108 return dynamics_.size() + 3; 109 } 110 111 // Create the actual dynamic vector. strsz should be the size of the .dynstr 112 // table and soname_off should be the offset of the soname in .dynstr. 113 // Since niether can be found prior to final layout we will wait until here 114 // to add them. 115 std::vector<Elf32_Dyn> GetDynamics(Elf32_Word strsz, Elf32_Word soname_off); 116 117 private: 118 friend class ElfBuilder; 119 }; 120 121 class ElfRawSectionBuilder : public ElfSectionBuilder { 122 public: ElfRawSectionBuilder(const std::string & sec_name,Elf32_Word type,Elf32_Word flags,const ElfSectionBuilder * link,Elf32_Word info,Elf32_Word align,Elf32_Word entsize)123 ElfRawSectionBuilder(const std::string& sec_name, Elf32_Word type, Elf32_Word flags, 124 const ElfSectionBuilder* link, Elf32_Word info, Elf32_Word align, 125 Elf32_Word entsize) 126 : ElfSectionBuilder(sec_name, type, flags, link, info, align, entsize) {} ~ElfRawSectionBuilder()127 ~ElfRawSectionBuilder() {} GetBuffer()128 std::vector<uint8_t>* GetBuffer() { return &buf_; } SetBuffer(std::vector<uint8_t> buf)129 void SetBuffer(std::vector<uint8_t> buf) { buf_ = buf; } 130 131 protected: 132 std::vector<uint8_t> buf_; 133 134 private: 135 friend class ElfBuilder; 136 }; 137 138 class ElfOatSectionBuilder : public ElfSectionBuilder { 139 public: ElfOatSectionBuilder(const std::string & sec_name,Elf32_Word size,Elf32_Word offset,Elf32_Word type,Elf32_Word flags)140 ElfOatSectionBuilder(const std::string& sec_name, Elf32_Word size, Elf32_Word offset, 141 Elf32_Word type, Elf32_Word flags) 142 : ElfSectionBuilder(sec_name, type, flags, NULL, 0, kPageSize, 0), 143 offset_(offset), size_(size) {} ~ElfOatSectionBuilder()144 ~ElfOatSectionBuilder() {} 145 146 protected: 147 // Offset of the content within the file. 148 Elf32_Word offset_; 149 // Size of the content within the file. 150 Elf32_Word size_; 151 152 private: 153 friend class ElfBuilder; 154 }; 155 156 class ElfSymtabBuilder : public ElfSectionBuilder { 157 public: 158 // Add a symbol with given name to this symtab. The symbol refers to 159 // 'relative_addr' within the given section and has the given attributes. 160 void AddSymbol(const std::string& name, 161 const ElfSectionBuilder* section, 162 Elf32_Addr addr, 163 bool is_relative, 164 Elf32_Word size, 165 uint8_t binding, 166 uint8_t type, 167 uint8_t other = 0); 168 ElfSymtabBuilder(const std::string & sec_name,Elf32_Word type,const std::string & str_name,Elf32_Word str_type,bool alloc)169 ElfSymtabBuilder(const std::string& sec_name, Elf32_Word type, 170 const std::string& str_name, Elf32_Word str_type, bool alloc) 171 : ElfSectionBuilder(sec_name, type, ((alloc) ? SHF_ALLOC : 0U), &strtab_, 0, 172 sizeof(Elf32_Word), sizeof(Elf32_Sym)), 173 str_name_(str_name), str_type_(str_type), 174 strtab_(str_name, str_type, ((alloc) ? SHF_ALLOC : 0U), NULL, 0, 1, 1) {} ~ElfSymtabBuilder()175 ~ElfSymtabBuilder() {} 176 177 protected: 178 std::vector<Elf32_Word> GenerateHashContents(); 179 std::string GenerateStrtab(); 180 std::vector<Elf32_Sym> GenerateSymtab(); 181 GetSize()182 Elf32_Word GetSize() { 183 // 1 is for the implicit NULL symbol. 184 return symbols_.size() + 1; 185 } 186 187 struct ElfSymbolState { 188 const std::string name_; 189 const ElfSectionBuilder* section_; 190 Elf32_Addr addr_; 191 Elf32_Word size_; 192 bool is_relative_; 193 uint8_t info_; 194 uint8_t other_; 195 // Used during Write() to temporarially hold name index in the strtab. 196 Elf32_Word name_idx_; 197 }; 198 199 // Information for the strsym for dynstr sections. 200 const std::string str_name_; 201 Elf32_Word str_type_; 202 // The symbols in the same order they will be in the symbol table. 203 std::vector<ElfSymbolState> symbols_; 204 ElfSectionBuilder strtab_; 205 206 private: 207 friend class ElfBuilder; 208 }; 209 210 class ElfBuilder FINAL { 211 public: 212 ElfBuilder(OatWriter* oat_writer, 213 File* elf_file, 214 InstructionSet isa, 215 Elf32_Word rodata_relative_offset, 216 Elf32_Word rodata_size, 217 Elf32_Word text_relative_offset, 218 Elf32_Word text_size, 219 const bool add_symbols, 220 bool debug = false) oat_writer_(oat_writer)221 : oat_writer_(oat_writer), 222 elf_file_(elf_file), 223 add_symbols_(add_symbols), 224 debug_logging_(debug), 225 text_builder_(".text", text_size, text_relative_offset, SHT_PROGBITS, 226 SHF_ALLOC | SHF_EXECINSTR), 227 rodata_builder_(".rodata", rodata_size, rodata_relative_offset, 228 SHT_PROGBITS, SHF_ALLOC), 229 dynsym_builder_(".dynsym", SHT_DYNSYM, ".dynstr", SHT_STRTAB, true), 230 symtab_builder_(".symtab", SHT_SYMTAB, ".strtab", SHT_STRTAB, false), 231 hash_builder_(".hash", SHT_HASH, SHF_ALLOC, &dynsym_builder_, 0, 232 sizeof(Elf32_Word), sizeof(Elf32_Word)), 233 dynamic_builder_(".dynamic", &dynsym_builder_), 234 shstrtab_builder_(".shstrtab", SHT_STRTAB, 0, NULL, 0, 1, 1) { 235 SetupEhdr(); 236 SetupDynamic(); 237 SetupRequiredSymbols(); 238 SetISA(isa); 239 } ~ElfBuilder()240 ~ElfBuilder() {} 241 242 bool Write(); 243 244 // Adds the given raw section to the builder. This will copy it. The caller 245 // is responsible for deallocating their copy. RegisterRawSection(ElfRawSectionBuilder bld)246 void RegisterRawSection(ElfRawSectionBuilder bld) { 247 other_builders_.push_back(bld); 248 } 249 250 private: 251 OatWriter* oat_writer_; 252 File* elf_file_; 253 const bool add_symbols_; 254 const bool debug_logging_; 255 256 bool fatal_error_ = false; 257 258 Elf32_Ehdr elf_header_; 259 260 public: 261 ElfOatSectionBuilder text_builder_; 262 ElfOatSectionBuilder rodata_builder_; 263 ElfSymtabBuilder dynsym_builder_; 264 ElfSymtabBuilder symtab_builder_; 265 ElfSectionBuilder hash_builder_; 266 ElfDynamicBuilder dynamic_builder_; 267 ElfSectionBuilder shstrtab_builder_; 268 std::vector<ElfRawSectionBuilder> other_builders_; 269 270 private: 271 void SetISA(InstructionSet isa); 272 void SetupEhdr(); 273 274 // Sets up a bunch of the required Dynamic Section entries. 275 // Namely it will initialize all the mandatory ones that it can. 276 // Specifically: 277 // DT_HASH 278 // DT_STRTAB 279 // DT_SYMTAB 280 // DT_SYMENT 281 // 282 // Some such as DT_SONAME, DT_STRSZ and DT_NULL will be put in later. 283 void SetupDynamic(); 284 285 // Sets up the basic dynamic symbols that are needed, namely all those we 286 // can know already. 287 // 288 // Specifically adds: 289 // oatdata 290 // oatexec 291 // oatlastword 292 void SetupRequiredSymbols(); 293 void AssignSectionStr(ElfSectionBuilder *builder, std::string* strtab); 294 IncludingDebugSymbols()295 bool IncludingDebugSymbols() { return add_symbols_ && symtab_builder_.GetSize() > 1; } 296 }; 297 298 /* 299 * @brief Generate the DWARF debug_info and debug_abbrev sections 300 * @param oat_writer The Oat file Writer. 301 * @param dbg_info Compilation unit information. 302 * @param dbg_abbrev Abbreviations used to generate dbg_info. 303 * @param dbg_str Debug strings. 304 */ 305 void FillInCFIInformation(OatWriter* oat_writer, std::vector<uint8_t>* dbg_info, 306 std::vector<uint8_t>* dbg_abbrev, std::vector<uint8_t>* dbg_str); 307 308 DISALLOW_IMPLICIT_CONSTRUCTORS(ElfWriterQuick); 309 }; 310 311 } // namespace art 312 313 #endif // ART_COMPILER_ELF_WRITER_QUICK_H_ 314