Home | History | Annotate | Download | only in src
      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 // ELF shared object file updates handler.
      6 //
      7 // Provides functions to pack relocations in the .rel.dyn or .rela.dyn
      8 // sections, and unpack to return the file to its pre-packed state.
      9 //
     10 // SetPadding() causes PackRelocations() to pad .rel.dyn or .rela.dyn with
     11 // NONE-type entries rather than cutting a hole out of the shared object
     12 // file.  This keeps all load addresses and offsets constant, and enables
     13 // easier debugging and testing.
     14 //
     15 // A packed shared object file is shorter than its non-packed original.
     16 // Unpacking a packed file restores the file to its non-packed state.
     17 
     18 #ifndef TOOLS_RELOCATION_PACKER_SRC_ELF_FILE_H_
     19 #define TOOLS_RELOCATION_PACKER_SRC_ELF_FILE_H_
     20 
     21 #include <string.h>
     22 #include <vector>
     23 
     24 #include "elf.h"
     25 #include "libelf.h"
     26 #include "packer.h"
     27 
     28 namespace relocation_packer {
     29 
     30 // An ElfFile reads shared objects, and shuttles relative relocations
     31 // between .rel.dyn or .rela.dyn and .android.rel.dyn or .android.rela.dyn
     32 // sections.
     33 template <typename ELF>
     34 class ElfFile {
     35  public:
     36   explicit ElfFile(int fd)
     37       : fd_(fd), is_padding_relocations_(false), elf_(NULL),
     38         relocations_section_(NULL), dynamic_section_(NULL),
     39         relocations_type_(NONE), has_android_relocations_(false) {}
     40   ~ElfFile() {}
     41 
     42   // Set padding mode.  When padding, PackRelocations() will not shrink
     43   // the .rel.dyn or .rela.dyn section, but instead replace relative with
     44   // NONE-type entries.
     45   // |flag| is true to pad .rel.dyn or .rela.dyn, false to shrink it.
     46   inline void SetPadding(bool flag) { is_padding_relocations_ = flag; }
     47 
     48   // Transfer relative relocations from .rel.dyn or .rela.dyn to a packed
     49   // representation in .android.rel.dyn or .android.rela.dyn.  Returns true
     50   // on success.
     51   bool PackRelocations();
     52 
     53   // Transfer relative relocations from a packed representation in
     54   // .android.rel.dyn or .android.rela.dyn to .rel.dyn or .rela.dyn.  Returns
     55   // true on success.
     56   bool UnpackRelocations();
     57 
     58  private:
     59   enum relocations_type_t {
     60     NONE = 0, REL, RELA
     61   };
     62 
     63   // Load a new ElfFile from a filedescriptor.  If flushing, the file must
     64   // be open for read/write.  Returns true on successful ELF file load.
     65   // |fd| is an open file descriptor for the shared object.
     66   bool Load();
     67 
     68   // Templated packer, helper for PackRelocations().  Rel type is one of
     69   // ELF::Rel or ELF::Rela.
     70   bool PackTypedRelocations(std::vector<typename ELF::Rela>* relocations);
     71 
     72   // Templated unpacker, helper for UnpackRelocations().  Rel type is one of
     73   // ELF::Rel or ELF::Rela.
     74   bool UnpackTypedRelocations(const std::vector<uint8_t>& packed);
     75 
     76   // Write ELF file changes.
     77   void Flush();
     78 
     79   void AdjustRelativeRelocationTargets(typename ELF::Off hole_start,
     80                                        ssize_t hole_size,
     81                                        std::vector<typename ELF::Rela>* relocations);
     82 
     83   static void ResizeSection(Elf* elf, Elf_Scn* section, size_t new_size,
     84                             typename ELF::Word new_sh_type, relocations_type_t relocations_type);
     85 
     86   static void AdjustDynamicSectionForHole(Elf_Scn* dynamic_section,
     87                                           typename ELF::Off hole_start,
     88                                           ssize_t hole_size,
     89                                           relocations_type_t relocations_type);
     90 
     91   static void ConvertRelArrayToRelaVector(const typename ELF::Rel* rel_array, size_t rel_array_size,
     92                                           std::vector<typename ELF::Rela>* rela_vector);
     93 
     94   static void ConvertRelaVectorToRelVector(const std::vector<typename ELF::Rela>& rela_vector,
     95                                            std::vector<typename ELF::Rel>* rel_vector);
     96 
     97 
     98   // File descriptor opened on the shared object.
     99   int fd_;
    100 
    101   // If set, pad rather than shrink .rel.dyn or .rela.dyn.  Primarily for
    102   // debugging, allows packing to be checked without affecting load addresses.
    103   bool is_padding_relocations_;
    104 
    105   // Libelf handle, assigned by Load().
    106   Elf* elf_;
    107 
    108   // Sections that we manipulate, assigned by Load().
    109   Elf_Scn* relocations_section_;
    110   Elf_Scn* dynamic_section_;
    111 
    112   // Relocation type found, assigned by Load().
    113   relocations_type_t relocations_type_;
    114 
    115   // Elf-file has android relocations section
    116   bool has_android_relocations_;
    117 };
    118 
    119 }  // namespace relocation_packer
    120 
    121 #endif  // TOOLS_RELOCATION_PACKER_SRC_ELF_FILE_H_
    122