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#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
13namespace crazy {
14
15class 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.
20class 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