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_VIEW_H
      6 #define CRAZY_LINKER_ELF_VIEW_H
      7 
      8 #include <string.h>
      9 
     10 #include "crazy_linker_error.h"
     11 #include "elf_traits.h"
     12 
     13 namespace crazy {
     14 
     15 class Error;
     16 
     17 // An ElfView holds information describing a given ELF binary file for
     18 // the crazy linker. This can be used to describe either system or crazy
     19 // libraries.
     20 class ElfView {
     21  public:
     22   ElfView() { ::memset(this, 0, sizeof(*this)); }
     23 
     24   ~ElfView() {}
     25 
     26   // Initialize this ElfView from its load address and a copy of its program
     27   // header table.
     28   // |load_address| is the desired library load address.
     29   // |phdr| is a pointer to the library's program header. Note that this can
     30   // point to any memory location that contains a valid copy of the header.
     31   // I.e. the library does not have to be mapped in the process.
     32   // |phdr_count| number of entries in program header table.
     33   // On failure, return false and set |error| message.
     34   // On success, return true, and sets all fields of the ElfView to the
     35   // appropriate values. Note that functions phdr() or dynamic() will always
     36   // return an address relative to |load_address|, even if the binary was
     37   // not loaded yet in the process.
     38   bool InitUnmapped(ELF::Addr load_address,
     39                     const ELF::Phdr* phdr,
     40                     size_t phdr_count,
     41                     Error* error);
     42 
     43   const ELF::Phdr* phdr() const { return phdr_; }
     44   size_t phdr_count() const { return phdr_count_; }
     45   const ELF::Dyn* dynamic() const { return dynamic_; }
     46   size_t dynamic_count() const { return dynamic_count_; }
     47   size_t dynamic_flags() const { return dynamic_flags_; }
     48   size_t load_address() const { return load_address_; }
     49   size_t load_size() const { return load_size_; }
     50   size_t load_bias() const { return load_bias_; }
     51 
     52   // Helper class to iterate over the dynamic table.
     53   // Usage example:
     54   //     DynamicIterator iter;
     55   //     for ( ; iter.HasNext(); iter.SkipNext()) {
     56   //        if (iter.GetTag() == DT_SOME_TAG) {
     57   //           ... use iter.GetValue()
     58   //           ... or iter.GetAddress(load_address)
     59   //        }
     60   //     }
     61   class DynamicIterator {
     62    public:
     63     DynamicIterator(const ElfView* view) {
     64       dyn_ = view->dynamic();
     65       dyn_limit_ = dyn_ + view->dynamic_count();
     66     }
     67 
     68     ~DynamicIterator() {}
     69 
     70     bool HasNext() const { return dyn_ < dyn_limit_; }
     71     void GetNext() { dyn_ += 1; }
     72 
     73     ELF::Addr GetTag() const { return dyn_->d_tag; }
     74 
     75     ELF::Addr GetValue() const { return dyn_->d_un.d_val; }
     76 
     77     ELF::Addr* GetValuePointer() const {
     78       return const_cast<ELF::Addr*>(&dyn_->d_un.d_ptr);
     79     }
     80 
     81     uintptr_t GetOffset() const { return dyn_->d_un.d_ptr; }
     82 
     83     uintptr_t GetAddress(size_t load_bias) const {
     84       return load_bias + dyn_->d_un.d_ptr;
     85     }
     86 
     87    private:
     88     const ELF::Dyn* dyn_;
     89     const ELF::Dyn* dyn_limit_;
     90   };
     91 
     92   // Ensure the RELRO section is read-only after relocations. Assume the
     93   // ELF binary is mapped.On failure, return false and set |error| message.
     94   bool ProtectRelroSection(Error* error);
     95 
     96  protected:
     97   const ELF::Phdr* phdr_;
     98   size_t phdr_count_;
     99   const ELF::Dyn* dynamic_;
    100   size_t dynamic_count_;
    101   ELF::Word dynamic_flags_;
    102   ELF::Addr load_address_;
    103   size_t load_size_;
    104   size_t load_bias_;
    105 };
    106 
    107 }  // namespace crazy
    108 
    109 #endif  // CRAZY_LINKER_ELF_VIEW_H
    110