summaryrefslogtreecommitdiffstats
path: root/third_party/android_crazy_linker/src/src/crazy_linker_elf_relocations.h
blob: edf2f4bffd01e476f60f8e833c428a5c51c2ab01 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CRAZY_LINKER_ELF_RELOCATIONS_H
#define CRAZY_LINKER_ELF_RELOCATIONS_H

#include <string.h>

#include "elf_traits.h"

namespace crazy {

class ElfSymbols;
class ElfView;
class Error;

// An ElfRelocations instance holds information about relocations in a mapped
// ELF binary.
class ElfRelocations {
 public:
  ElfRelocations() { ::memset(this, 0, sizeof(*this)); }
  ~ElfRelocations() {}

  bool Init(const ElfView* view, Error* error);

  // Abstract class used to resolve symbol names into addresses.
  // Callers of ::ApplyAll() should pass the address of a derived class
  // that properly implements the Lookup() method.
  class SymbolResolver {
   public:
    SymbolResolver() {}
    ~SymbolResolver() {}
    virtual void* Lookup(const char* symbol_name) = 0;
  };

  // Apply all relocations to the target mapped ELF binary. Must be called
  // after Init().
  // |symbols| maps to the symbol entries for the target library only.
  // |resolver| can resolve symbols out of the current library.
  // On error, return false and set |error| message.
  bool ApplyAll(const ElfSymbols* symbols,
                SymbolResolver* resolver,
                Error* error);

  // This function is used to adjust relocated addresses in a copy of an
  // existing section of an ELF binary. I.e. |src_addr|...|src_addr + size|
  // must be inside the mapped ELF binary, this function will first copy its
  // content into |dst_addr|...|dst_addr + size|, then adjust all relocated
  // addresses inside the destination section as if it was loaded/mapped
  // at |map_addr|...|map_addr + size|. Only relative relocations are processed,
  // symbolic ones are ignored.
  void CopyAndRelocate(size_t src_addr,
                       size_t dst_addr,
                       size_t map_addr,
                       size_t size);

 private:
  bool ResolveSymbol(unsigned rel_type,
                     unsigned rel_symbol,
                     const ElfSymbols* symbols,
                     SymbolResolver* resolver,
                     ELF::Addr reloc,
                     ELF::Addr* sym_addr,
                     Error* error);
  bool ApplyRelaReloc(const ELF::Rela* rela,
                      ELF::Addr sym_addr,
                      bool resolved,
                      Error* error);
  bool ApplyRelReloc(const ELF::Rel* rel,
                     ELF::Addr sym_addr,
                     bool resolved,
                     Error* error);
  bool ApplyRelaRelocs(const ELF::Rela* relocs,
                       size_t relocs_count,
                       const ElfSymbols* symbols,
                       SymbolResolver* resolver,
                       Error* error);
  bool ApplyRelRelocs(const ELF::Rel* relocs,
                      size_t relocs_count,
                      const ElfSymbols* symbols,
                      SymbolResolver* resolver,
                      Error* error);
  void AdjustRelocation(ELF::Word rel_type,
                        ELF::Addr src_reloc,
                        size_t dst_delta,
                        size_t map_delta);
  void RelocateRela(size_t src_addr,
                    size_t dst_addr,
                    size_t map_addr,
                    size_t size);
  void RelocateRel(size_t src_addr,
                   size_t dst_addr,
                   size_t map_addr,
                   size_t size);

#if defined(__mips__)
  bool RelocateMipsGot(const ElfSymbols* symbols,
                       SymbolResolver* resolver,
                       Error* error);
#endif

  const ELF::Phdr* phdr_;
  size_t phdr_count_;
  size_t load_bias_;

  ELF::Addr relocations_type_;
  ELF::Addr plt_relocations_;
  size_t plt_relocations_size_;
  ELF::Addr* plt_got_;

  ELF::Addr relocations_;
  size_t relocations_size_;

#if defined(__mips__)
  // MIPS-specific relocation fields.
  ELF::Word mips_symtab_count_;
  ELF::Word mips_local_got_count_;
  ELF::Word mips_gotsym_;
#endif

  bool has_text_relocations_;
  bool has_symbolic_;
};

}  // namespace crazy

#endif  // CRAZY_LINKER_ELF_RELOCATIONS_H