1//===- Relocations.h -------------------------------------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#ifndef LLD_ELF_RELOCATIONS_H
10#define LLD_ELF_RELOCATIONS_H
11
12#include "lld/Common/LLVM.h"
13#include "llvm/ADT/DenseMap.h"
14#include <map>
15#include <vector>
16
17namespace lld {
18namespace elf {
19class Symbol;
20class InputSection;
21class InputSectionBase;
22class OutputSection;
23class SectionBase;
24
25// Represents a relocation type, such as R_X86_64_PC32 or R_ARM_THM_CALL.
26using RelType = uint32_t;
27
28// List of target-independent relocation types. Relocations read
29// from files are converted to these types so that the main code
30// doesn't have to know about architecture-specific details.
31enum RelExpr {
32  R_ABS,
33  R_ADDEND,
34  R_DTPREL,
35  R_GOT,
36  R_GOT_OFF,
37  R_GOT_PC,
38  R_GOTONLY_PC,
39  R_GOTPLTONLY_PC,
40  R_GOTPLT,
41  R_GOTPLTREL,
42  R_GOTREL,
43  R_NEG_TLS,
44  R_NONE,
45  R_PC,
46  R_PLT,
47  R_PLT_PC,
48  R_RELAX_GOT_PC,
49  R_RELAX_GOT_PC_NOPIC,
50  R_RELAX_TLS_GD_TO_IE,
51  R_RELAX_TLS_GD_TO_IE_ABS,
52  R_RELAX_TLS_GD_TO_IE_GOT_OFF,
53  R_RELAX_TLS_GD_TO_IE_GOTPLT,
54  R_RELAX_TLS_GD_TO_LE,
55  R_RELAX_TLS_GD_TO_LE_NEG,
56  R_RELAX_TLS_IE_TO_LE,
57  R_RELAX_TLS_LD_TO_LE,
58  R_RELAX_TLS_LD_TO_LE_ABS,
59  R_SIZE,
60  R_TLS,
61  R_TLSDESC,
62  R_TLSDESC_CALL,
63  R_TLSDESC_PC,
64  R_TLSGD_GOT,
65  R_TLSGD_GOTPLT,
66  R_TLSGD_PC,
67  R_TLSIE_HINT,
68  R_TLSLD_GOT,
69  R_TLSLD_GOTPLT,
70  R_TLSLD_GOT_OFF,
71  R_TLSLD_HINT,
72  R_TLSLD_PC,
73
74  // The following is abstract relocation types used for only one target.
75  //
76  // Even though RelExpr is intended to be a target-neutral representation
77  // of a relocation type, there are some relocations whose semantics are
78  // unique to a target. Such relocation are marked with R_<TARGET_NAME>.
79  R_AARCH64_GOT_PAGE_PC,
80  R_AARCH64_PAGE_PC,
81  R_AARCH64_RELAX_TLS_GD_TO_IE_PAGE_PC,
82  R_AARCH64_TLSDESC_PAGE,
83  R_ARM_SBREL,
84  R_MIPS_GOTREL,
85  R_MIPS_GOT_GP,
86  R_MIPS_GOT_GP_PC,
87  R_MIPS_GOT_LOCAL_PAGE,
88  R_MIPS_GOT_OFF,
89  R_MIPS_GOT_OFF32,
90  R_MIPS_TLSGD,
91  R_MIPS_TLSLD,
92  R_PPC32_PLTREL,
93  R_PPC64_CALL,
94  R_PPC64_CALL_PLT,
95  R_PPC64_RELAX_TOC,
96  R_PPC64_TOCBASE,
97  R_RISCV_ADD,
98  R_RISCV_PC_INDIRECT,
99};
100
101// Architecture-neutral representation of relocation.
102struct Relocation {
103  RelExpr expr;
104  RelType type;
105  uint64_t offset;
106  int64_t addend;
107  Symbol *sym;
108};
109
110// This function writes undefined symbol diagnostics to an internal buffer.
111// Call reportUndefinedSymbols() after calling scanRelocations() to emit
112// the diagnostics.
113template <class ELFT> void scanRelocations(InputSectionBase &);
114
115template <class ELFT> void reportUndefinedSymbols();
116
117class ThunkSection;
118class Thunk;
119struct InputSectionDescription;
120
121class ThunkCreator {
122public:
123  // Return true if Thunks have been added to OutputSections
124  bool createThunks(ArrayRef<OutputSection *> outputSections);
125
126  // The number of completed passes of createThunks this permits us
127  // to do one time initialization on Pass 0 and put a limit on the
128  // number of times it can be called to prevent infinite loops.
129  uint32_t pass = 0;
130
131private:
132  void mergeThunks(ArrayRef<OutputSection *> outputSections);
133
134  ThunkSection *getISDThunkSec(OutputSection *os, InputSection *isec,
135                               InputSectionDescription *isd, uint32_t type,
136                               uint64_t src);
137
138  ThunkSection *getISThunkSec(InputSection *isec);
139
140  void createInitialThunkSections(ArrayRef<OutputSection *> outputSections);
141
142  std::pair<Thunk *, bool> getThunk(InputSection *isec, Relocation &rel,
143                                    uint64_t src);
144
145  ThunkSection *addThunkSection(OutputSection *os, InputSectionDescription *,
146                                uint64_t off);
147
148  bool normalizeExistingThunk(Relocation &rel, uint64_t src);
149
150  // Record all the available Thunks for a (Symbol, addend) pair, where Symbol
151  // is represented as a (section, offset) pair. There may be multiple
152  // relocations sharing the same (section, offset + addend) pair. We may revert
153  // a relocation back to its original non-Thunk target, and restore the
154  // original addend, so we cannot fold offset + addend. A nested pair is used
155  // because DenseMapInfo is not specialized for std::tuple.
156  llvm::DenseMap<std::pair<std::pair<SectionBase *, uint64_t>, int64_t>,
157                 std::vector<Thunk *>>
158      thunkedSymbolsBySectionAndAddend;
159  llvm::DenseMap<std::pair<Symbol *, int64_t>, std::vector<Thunk *>>
160      thunkedSymbols;
161
162  // Find a Thunk from the Thunks symbol definition, we can use this to find
163  // the Thunk from a relocation to the Thunks symbol definition.
164  llvm::DenseMap<Symbol *, Thunk *> thunks;
165
166  // Track InputSections that have an inline ThunkSection placed in front
167  // an inline ThunkSection may have control fall through to the section below
168  // so we need to make sure that there is only one of them.
169  // The Mips LA25 Thunk is an example of an inline ThunkSection.
170  llvm::DenseMap<InputSection *, ThunkSection *> thunkedSections;
171};
172
173// Return a int64_t to make sure we get the sign extension out of the way as
174// early as possible.
175template <class ELFT>
176static inline int64_t getAddend(const typename ELFT::Rel &rel) {
177  return 0;
178}
179template <class ELFT>
180static inline int64_t getAddend(const typename ELFT::Rela &rel) {
181  return rel.r_addend;
182}
183} // namespace elf
184} // namespace lld
185
186#endif
187