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