// Copyright (c) 2013 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef CRAZY_LINKER_ELF_LOADER_H #define CRAZY_LINKER_ELF_LOADER_H #include "crazy_linker_error.h" #include "crazy_linker_system.h" // For ScopedFileDescriptor #include "elf_traits.h" namespace crazy { // Helper class used to load an ELF binary in memory. // // Note that this doesn't not perform any relocation, the purpose // of this class is strictly to map all loadable segments from the // file to their correct location. // class ElfLoader { public: ElfLoader(); ~ElfLoader(); // Try to load a library at a given address. On failure, this will // update the linker error message and returns false. // // |lib_path| is the full library path, and |wanted_address| should // be the desired load address, or 0 to enable randomization. // // |file_offset| is an offset in the file where the ELF header will // be looked for. // // |wanted_address| is the wanted load address (of the first loadable // segment), or 0 to enable randomization. // // On success, the library's loadable segments will be mapped in // memory with their original protection. However, no further processing // will be performed. // // On failure, returns false and assign an error message to |error|. bool LoadAt(const char* lib_path, off_t file_offset, uintptr_t wanted_address, Error* error); // Only call the following functions after a succesfull LoadAt() call. size_t phdr_count() { return phdr_num_; } ELF::Addr load_start() { return reinterpret_cast(load_start_); } ELF::Addr load_size() { return load_size_; } ELF::Addr load_bias() { return load_bias_; } const ELF::Phdr* loaded_phdr() { return loaded_phdr_; } private: FileDescriptor fd_; const char* path_; ELF::Ehdr header_; size_t phdr_num_; void* phdr_mmap_; // temporary copy of the program header. ELF::Phdr* phdr_table_; ELF::Addr phdr_size_; // and its size. off_t file_offset_; void* wanted_load_address_; void* load_start_; // First page of reserved address space. ELF::Addr load_size_; // Size in bytes of reserved address space. ELF::Addr load_bias_; // load_bias, add this value to all "vaddr" // values in the library to get the corresponding // memory address. const ELF::Phdr* loaded_phdr_; // points to the loaded program header. // Individual steps used by ::LoadAt() bool ReadElfHeader(Error* error); bool ReadProgramHeader(Error* error); bool ReserveAddressSpace(Error* error); bool LoadSegments(Error* error); bool FindPhdr(Error* error); bool CheckPhdr(ELF::Addr, Error* error); }; } // namespace crazy #endif // CRAZY_LINKER_ELF_LOADER_H