1 // Copyright 2014 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef CRAZY_LINKER_ELF_LOADER_H 6 #define CRAZY_LINKER_ELF_LOADER_H 7 8 #include "crazy_linker_error.h" 9 #include "crazy_linker_system.h" // For ScopedFileDescriptor 10 #include "elf_traits.h" 11 12 namespace crazy { 13 14 // Helper class used to load an ELF binary in memory. 15 // 16 // Note that this doesn't not perform any relocation, the purpose 17 // of this class is strictly to map all loadable segments from the 18 // file to their correct location. 19 // 20 class ElfLoader { 21 public: 22 ElfLoader(); 23 ~ElfLoader(); 24 25 // Try to load a library at a given address. On failure, this will 26 // update the linker error message and returns false. 27 // 28 // |lib_path| is the full library path, and |wanted_address| should 29 // be the desired load address, or 0 to enable randomization. 30 // 31 // |file_offset| is an offset in the file where the ELF header will 32 // be looked for. 33 // 34 // |wanted_address| is the wanted load address (of the first loadable 35 // segment), or 0 to enable randomization. 36 // 37 // On success, the library's loadable segments will be mapped in 38 // memory with their original protection. However, no further processing 39 // will be performed. 40 // 41 // On failure, returns false and assign an error message to |error|. 42 bool LoadAt(const char* lib_path, 43 off_t file_offset, 44 uintptr_t wanted_address, 45 Error* error); 46 47 // Only call the following functions after a succesfull LoadAt() call. 48 phdr_count()49 size_t phdr_count() { return phdr_num_; } load_start()50 ELF::Addr load_start() { return reinterpret_cast<ELF::Addr>(load_start_); } load_size()51 ELF::Addr load_size() { return load_size_; } load_bias()52 ELF::Addr load_bias() { return load_bias_; } loaded_phdr()53 const ELF::Phdr* loaded_phdr() { return loaded_phdr_; } 54 55 private: 56 FileDescriptor fd_; 57 const char* path_; 58 59 ELF::Ehdr header_; 60 size_t phdr_num_; 61 62 void* phdr_mmap_; // temporary copy of the program header. 63 ELF::Phdr* phdr_table_; 64 ELF::Addr phdr_size_; // and its size. 65 66 off_t file_offset_; 67 void* wanted_load_address_; 68 void* load_start_; // First page of reserved address space. 69 ELF::Addr load_size_; // Size in bytes of reserved address space. 70 ELF::Addr load_bias_; // load_bias, add this value to all "vaddr" 71 // values in the library to get the corresponding 72 // memory address. 73 74 const ELF::Phdr* loaded_phdr_; // points to the loaded program header. 75 76 // Individual steps used by ::LoadAt() 77 bool ReadElfHeader(Error* error); 78 bool ReadProgramHeader(Error* error); 79 bool ReserveAddressSpace(Error* error); 80 bool LoadSegments(Error* error); 81 bool FindPhdr(Error* error); 82 bool CheckPhdr(ELF::Addr, Error* error); 83 }; 84 85 } // namespace crazy 86 87 #endif // CRAZY_LINKER_ELF_LOADER_H 88