Home | History | Annotate | Download | only in src
      1 // Copyright (c) 2013 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 
     49   size_t phdr_count() { return phdr_num_; }
     50   ELF::Addr load_start() { return reinterpret_cast<ELF::Addr>(load_start_); }
     51   ELF::Addr load_size() { return load_size_; }
     52   ELF::Addr load_bias() { return load_bias_; }
     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