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_RELOCATIONS_H
      6 #define CRAZY_LINKER_ELF_RELOCATIONS_H
      7 
      8 #include <string.h>
      9 
     10 #include "elf_traits.h"
     11 
     12 namespace crazy {
     13 
     14 class ElfSymbols;
     15 class ElfView;
     16 class Error;
     17 
     18 // An ElfRelocations instance holds information about relocations in a mapped
     19 // ELF binary.
     20 class ElfRelocations {
     21  public:
     22   ElfRelocations() { ::memset(this, 0, sizeof(*this)); }
     23   ~ElfRelocations() {}
     24 
     25   bool Init(const ElfView* view, Error* error);
     26 
     27   // Abstract class used to resolve symbol names into addresses.
     28   // Callers of ::ApplyAll() should pass the address of a derived class
     29   // that properly implements the Lookup() method.
     30   class SymbolResolver {
     31    public:
     32     SymbolResolver() {}
     33     ~SymbolResolver() {}
     34     virtual void* Lookup(const char* symbol_name) = 0;
     35   };
     36 
     37   // Apply all relocations to the target mapped ELF binary. Must be called
     38   // after Init().
     39   // |symbols| maps to the symbol entries for the target library only.
     40   // |resolver| can resolve symbols out of the current library.
     41   // On error, return false and set |error| message.
     42   bool ApplyAll(const ElfSymbols* symbols,
     43                 SymbolResolver* resolver,
     44                 Error* error);
     45 
     46   // This function is used to adjust relocated addresses in a copy of an
     47   // existing section of an ELF binary. I.e. |src_addr|...|src_addr + size|
     48   // must be inside the mapped ELF binary, this function will first copy its
     49   // content into |dst_addr|...|dst_addr + size|, then adjust all relocated
     50   // addresses inside the destination section as if it was loaded/mapped
     51   // at |map_addr|...|map_addr + size|. Only relative relocations are processed,
     52   // symbolic ones are ignored.
     53   void CopyAndRelocate(size_t src_addr,
     54                        size_t dst_addr,
     55                        size_t map_addr,
     56                        size_t size);
     57 
     58  private:
     59   bool ResolveSymbol(unsigned rel_type,
     60                      unsigned rel_symbol,
     61                      const ElfSymbols* symbols,
     62                      SymbolResolver* resolver,
     63                      ELF::Addr reloc,
     64                      ELF::Addr* sym_addr,
     65                      Error* error);
     66   bool ApplyRelaReloc(const ELF::Rela* rela,
     67                       ELF::Addr sym_addr,
     68                       bool resolved,
     69                       Error* error);
     70   bool ApplyRelReloc(const ELF::Rel* rel,
     71                      ELF::Addr sym_addr,
     72                      bool resolved,
     73                      Error* error);
     74   bool ApplyRelaRelocs(const ELF::Rela* relocs,
     75                        size_t relocs_count,
     76                        const ElfSymbols* symbols,
     77                        SymbolResolver* resolver,
     78                        Error* error);
     79   bool ApplyRelRelocs(const ELF::Rel* relocs,
     80                       size_t relocs_count,
     81                       const ElfSymbols* symbols,
     82                       SymbolResolver* resolver,
     83                       Error* error);
     84   void AdjustRelocation(ELF::Word rel_type,
     85                         ELF::Addr src_reloc,
     86                         size_t dst_delta,
     87                         size_t map_delta);
     88   void RelocateRela(size_t src_addr,
     89                     size_t dst_addr,
     90                     size_t map_addr,
     91                     size_t size);
     92   void RelocateRel(size_t src_addr,
     93                    size_t dst_addr,
     94                    size_t map_addr,
     95                    size_t size);
     96 
     97 #if defined(__mips__)
     98   bool RelocateMipsGot(const ElfSymbols* symbols,
     99                        SymbolResolver* resolver,
    100                        Error* error);
    101 #endif
    102 
    103   const ELF::Phdr* phdr_;
    104   size_t phdr_count_;
    105   size_t load_bias_;
    106 
    107   ELF::Addr relocations_type_;
    108   ELF::Addr plt_relocations_;
    109   size_t plt_relocations_size_;
    110   ELF::Addr* plt_got_;
    111 
    112   ELF::Addr relocations_;
    113   size_t relocations_size_;
    114 
    115 #if defined(__mips__)
    116   // MIPS-specific relocation fields.
    117   ELF::Word mips_symtab_count_;
    118   ELF::Word mips_local_got_count_;
    119   ELF::Word mips_gotsym_;
    120 #endif
    121 
    122   bool has_text_relocations_;
    123   bool has_symbolic_;
    124 };
    125 
    126 }  // namespace crazy
    127 
    128 #endif  // CRAZY_LINKER_ELF_RELOCATIONS_H
    129