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:
ElfView()22   ElfView() { ::memset(this, 0, sizeof(*this)); }
23 
~ElfView()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 
phdr()43   const ELF::Phdr* phdr() const { return phdr_; }
phdr_count()44   size_t phdr_count() const { return phdr_count_; }
dynamic()45   const ELF::Dyn* dynamic() const { return dynamic_; }
dynamic_count()46   size_t dynamic_count() const { return dynamic_count_; }
dynamic_flags()47   size_t dynamic_flags() const { return dynamic_flags_; }
load_address()48   size_t load_address() const { return load_address_; }
load_size()49   size_t load_size() const { return load_size_; }
load_bias()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:
DynamicIterator(const ElfView * view)63     DynamicIterator(const ElfView* view) {
64       dyn_ = view->dynamic();
65       dyn_limit_ = dyn_ + view->dynamic_count();
66     }
67 
~DynamicIterator()68     ~DynamicIterator() {}
69 
HasNext()70     bool HasNext() const { return dyn_ < dyn_limit_; }
GetNext()71     void GetNext() { dyn_ += 1; }
72 
GetTag()73     ELF::Addr GetTag() const { return dyn_->d_tag; }
74 
GetValue()75     ELF::Addr GetValue() const { return dyn_->d_un.d_val; }
76 
GetValuePointer()77     ELF::Addr* GetValuePointer() const {
78       return const_cast<ELF::Addr*>(&dyn_->d_un.d_ptr);
79     }
80 
GetOffset()81     uintptr_t GetOffset() const { return dyn_->d_un.d_ptr; }
82 
GetAddress(size_t load_bias)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