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