Rui Ueyama | 0fcdc73 | 2016-05-24 20:24:43 | [diff] [blame] | 1 | //===- Relocations.h -------------------------------------------*- C++ -*-===// |
| 2 | // |
Chandler Carruth | 2946cd7 | 2019-01-19 08:50:56 | [diff] [blame] | 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 |
Rui Ueyama | 0fcdc73 | 2016-05-24 20:24:43 | [diff] [blame] | 6 | // |
| 7 | //===----------------------------------------------------------------------===// |
| 8 | |
| 9 | #ifndef LLD_ELF_RELOCATIONS_H |
| 10 | #define LLD_ELF_RELOCATIONS_H |
| 11 | |
Rui Ueyama | 3f85170 | 2017-10-02 21:00:41 | [diff] [blame] | 12 | #include "lld/Common/LLVM.h" |
Peter Smith | 56abf20 | 2017-04-05 10:30:09 | [diff] [blame] | 13 | #include "llvm/ADT/DenseMap.h" |
serge-sans-paille | 5f290c0 | 2022-01-24 10:57:09 | [diff] [blame] | 14 | #include "llvm/ADT/STLExtras.h" |
Fangrui Song | 0af07c0 | 2024-08-01 17:22:03 | [diff] [blame] | 15 | #include "llvm/Object/ELFTypes.h" |
Peter Smith | 56abf20 | 2017-04-05 10:30:09 | [diff] [blame] | 16 | #include <vector> |
Rui Ueyama | 0fcdc73 | 2016-05-24 20:24:43 | [diff] [blame] | 17 | |
Nico Weber | 87248ba | 2022-08-10 19:31:58 | [diff] [blame] | 18 | namespace lld::elf { |
Fangrui Song | a94060c | 2024-09-28 07:26:23 | [diff] [blame] | 19 | struct Ctx; |
Peter Smith | c4d9cd8 | 2024-10-01 12:12:29 | [diff] [blame] | 20 | class Defined; |
Rui Ueyama | f52496e | 2017-11-03 21:21:47 | [diff] [blame] | 21 | class Symbol; |
Rafael Espindola | 774ea7d | 2017-02-23 16:49:07 | [diff] [blame] | 22 | class InputSection; |
Rafael Espindola | b4c9b81 | 2017-02-23 02:28:28 | [diff] [blame] | 23 | class InputSectionBase; |
Rafael Espindola | 24e6f36 | 2017-02-24 15:07:30 | [diff] [blame] | 24 | class OutputSection; |
pcc | 970d6d2 | 2024-12-05 01:35:05 | [diff] [blame] | 25 | class RelocationBaseSection; |
Peter Collingbourne | 04ff122 | 2018-03-09 17:54:43 | [diff] [blame] | 26 | class SectionBase; |
Rui Ueyama | 0fcdc73 | 2016-05-24 20:24:43 | [diff] [blame] | 27 | |
Rui Ueyama | 67533a2 | 2017-10-11 22:49:24 | [diff] [blame] | 28 | // Represents a relocation type, such as R_X86_64_PC32 or R_ARM_THM_CALL. |
Fangrui Song | c1a6def | 2024-11-17 04:26:33 | [diff] [blame] | 29 | struct RelType { |
| 30 | uint32_t v = 0; |
| 31 | /*implicit*/ constexpr RelType(uint32_t v = 0) : v(v) {} |
| 32 | /*implicit*/ operator uint32_t() const { return v; } |
| 33 | }; |
| 34 | |
Sriraman Tallam | 9431787 | 2020-04-07 13:48:18 | [diff] [blame] | 35 | using JumpModType = uint32_t; |
Rui Ueyama | 67533a2 | 2017-10-11 22:49:24 | [diff] [blame] | 36 | |
Rui Ueyama | 865d986 | 2016-10-21 04:52:11 | [diff] [blame] | 37 | // List of target-independent relocation types. Relocations read |
| 38 | // from files are converted to these types so that the main code |
| 39 | // doesn't have to know about architecture-specific details. |
Rui Ueyama | 0fcdc73 | 2016-05-24 20:24:43 | [diff] [blame] | 40 | enum RelExpr { |
| 41 | R_ABS, |
Alexander Richardson | cfb6093 | 2018-02-16 10:01:17 | [diff] [blame] | 42 | R_ADDEND, |
Fangrui Song | bc4b159 | 2019-04-22 03:10:40 | [diff] [blame] | 43 | R_DTPREL, |
Rui Ueyama | 0fcdc73 | 2016-05-24 20:24:43 | [diff] [blame] | 44 | R_GOT, |
Rui Ueyama | 0fcdc73 | 2016-05-24 20:24:43 | [diff] [blame] | 45 | R_GOT_OFF, |
Rui Ueyama | 0fcdc73 | 2016-05-24 20:24:43 | [diff] [blame] | 46 | R_GOT_PC, |
Fangrui Song | 210949a | 2019-03-25 23:46:19 | [diff] [blame] | 47 | R_GOTONLY_PC, |
| 48 | R_GOTPLTONLY_PC, |
| 49 | R_GOTPLT, |
| 50 | R_GOTPLTREL, |
| 51 | R_GOTREL, |
Ulrich Weigand | fe3406e | 2024-02-13 10:29:21 | [diff] [blame] | 52 | R_GOTPLT_GOTREL, |
| 53 | R_GOTPLT_PC, |
Petr Hosek | b27bb59 | 2017-02-23 06:22:28 | [diff] [blame] | 54 | R_NONE, |
Rui Ueyama | 0fcdc73 | 2016-05-24 20:24:43 | [diff] [blame] | 55 | R_PC, |
| 56 | R_PLT, |
Rui Ueyama | ff524bf | 2017-03-26 04:10:43 | [diff] [blame] | 57 | R_PLT_PC, |
Fangrui Song | ca8105b | 2021-10-25 20:05:17 | [diff] [blame] | 58 | R_PLT_GOTPLT, |
Ulrich Weigand | fe3406e | 2024-02-13 10:29:21 | [diff] [blame] | 59 | R_PLT_GOTREL, |
Fangrui Song | 6611d58 | 2022-07-07 17:16:09 | [diff] [blame] | 60 | R_RELAX_HINT, |
George Rimar | 5c33b91 | 2016-05-25 14:31:37 | [diff] [blame] | 61 | R_RELAX_GOT_PC, |
George Rimar | f10c829 | 2016-06-01 16:45:30 | [diff] [blame] | 62 | R_RELAX_GOT_PC_NOPIC, |
Rui Ueyama | 0fcdc73 | 2016-05-24 20:24:43 | [diff] [blame] | 63 | R_RELAX_TLS_GD_TO_IE, |
Rafael Espindola | e1979ae | 2016-06-04 23:33:31 | [diff] [blame] | 64 | R_RELAX_TLS_GD_TO_IE_ABS, |
Sean Fertile | f60cb34 | 2018-06-26 19:38:18 | [diff] [blame] | 65 | R_RELAX_TLS_GD_TO_IE_GOT_OFF, |
Fangrui Song | e1f3191 | 2019-04-22 02:48:37 | [diff] [blame] | 66 | R_RELAX_TLS_GD_TO_IE_GOTPLT, |
Rui Ueyama | 0fcdc73 | 2016-05-24 20:24:43 | [diff] [blame] | 67 | R_RELAX_TLS_GD_TO_LE, |
Rafael Espindola | 69f5402 | 2016-06-04 23:22:34 | [diff] [blame] | 68 | R_RELAX_TLS_GD_TO_LE_NEG, |
Rui Ueyama | 0fcdc73 | 2016-05-24 20:24:43 | [diff] [blame] | 69 | R_RELAX_TLS_IE_TO_LE, |
| 70 | R_RELAX_TLS_LD_TO_LE, |
Zaara Syeda | 75c348a | 2018-07-09 16:35:51 | [diff] [blame] | 71 | R_RELAX_TLS_LD_TO_LE_ABS, |
Rui Ueyama | 0fcdc73 | 2016-05-24 20:24:43 | [diff] [blame] | 72 | R_SIZE, |
Fangrui Song | 22c1bd5 | 2020-12-18 16:24:42 | [diff] [blame] | 73 | R_TPREL, |
| 74 | R_TPREL_NEG, |
Rafael Espindola | e37d13b | 2016-06-02 19:49:53 | [diff] [blame] | 75 | R_TLSDESC, |
Peter Smith | d648603 | 2016-10-20 09:59:26 | [diff] [blame] | 76 | R_TLSDESC_CALL, |
Fangrui Song | 7193224 | 2019-05-29 02:03:56 | [diff] [blame] | 77 | R_TLSDESC_PC, |
Fangrui Song | e39c138 | 2021-10-29 00:52:03 | [diff] [blame] | 78 | R_TLSDESC_GOTPLT, |
Sean Fertile | ef0f749 | 2018-05-29 14:34:38 | [diff] [blame] | 79 | R_TLSGD_GOT, |
Fangrui Song | 210949a | 2019-03-25 23:46:19 | [diff] [blame] | 80 | R_TLSGD_GOTPLT, |
Rui Ueyama | 0fcdc73 | 2016-05-24 20:24:43 | [diff] [blame] | 81 | R_TLSGD_PC, |
Zaara Syeda | 662d146 | 2018-08-21 15:13:53 | [diff] [blame] | 82 | R_TLSIE_HINT, |
Sean Fertile | 1a8343f | 2018-05-31 18:44:12 | [diff] [blame] | 83 | R_TLSLD_GOT, |
Fangrui Song | 210949a | 2019-03-25 23:46:19 | [diff] [blame] | 84 | R_TLSLD_GOTPLT, |
Zaara Syeda | de54f58 | 2018-06-27 13:55:41 | [diff] [blame] | 85 | R_TLSLD_GOT_OFF, |
Zaara Syeda | 75c348a | 2018-07-09 16:35:51 | [diff] [blame] | 86 | R_TLSLD_HINT, |
Rui Ueyama | 865d986 | 2016-10-21 04:52:11 | [diff] [blame] | 87 | R_TLSLD_PC, |
Rui Ueyama | f69bbbb | 2019-02-14 18:50:59 | [diff] [blame] | 88 | |
| 89 | // The following is abstract relocation types used for only one target. |
| 90 | // |
| 91 | // Even though RelExpr is intended to be a target-neutral representation |
| 92 | // of a relocation type, there are some relocations whose semantics are |
Fangrui Song | 04996a2 | 2024-12-03 17:17:17 | [diff] [blame] | 93 | // unique to a target. Such relocation are marked with RE_<TARGET_NAME>. |
| 94 | RE_AARCH64_GOT_PAGE_PC, |
Daniil Kovalev | 417d2d7 | 2024-12-17 07:23:01 | [diff] [blame] | 95 | RE_AARCH64_AUTH_GOT_PAGE_PC, |
Fangrui Song | 04996a2 | 2024-12-03 17:17:17 | [diff] [blame] | 96 | RE_AARCH64_GOT_PAGE, |
Daniil Kovalev | 417d2d7 | 2024-12-17 07:23:01 | [diff] [blame] | 97 | RE_AARCH64_AUTH_GOT, |
Daniil Kovalev | 1ef5b98 | 2024-12-18 06:41:54 | [diff] [blame] | 98 | RE_AARCH64_AUTH_GOT_PC, |
Fangrui Song | 04996a2 | 2024-12-03 17:17:17 | [diff] [blame] | 99 | RE_AARCH64_PAGE_PC, |
| 100 | RE_AARCH64_RELAX_TLS_GD_TO_IE_PAGE_PC, |
| 101 | RE_AARCH64_TLSDESC_PAGE, |
| 102 | RE_AARCH64_AUTH, |
| 103 | RE_ARM_PCA, |
| 104 | RE_ARM_SBREL, |
| 105 | RE_MIPS_GOTREL, |
| 106 | RE_MIPS_GOT_GP, |
| 107 | RE_MIPS_GOT_GP_PC, |
| 108 | RE_MIPS_GOT_LOCAL_PAGE, |
| 109 | RE_MIPS_GOT_OFF, |
| 110 | RE_MIPS_GOT_OFF32, |
| 111 | RE_MIPS_TLSGD, |
| 112 | RE_MIPS_TLSLD, |
| 113 | RE_PPC32_PLTREL, |
| 114 | RE_PPC64_CALL, |
| 115 | RE_PPC64_CALL_PLT, |
| 116 | RE_PPC64_RELAX_TOC, |
| 117 | RE_PPC64_TOCBASE, |
| 118 | RE_PPC64_RELAX_GOT_PC, |
| 119 | RE_RISCV_ADD, |
| 120 | RE_RISCV_LEB128, |
| 121 | RE_RISCV_PC_INDIRECT, |
WANG Xuerui | 6084ee7 | 2023-07-25 09:03:28 | [diff] [blame] | 122 | // Same as R_PC but with page-aligned semantics. |
Fangrui Song | 04996a2 | 2024-12-03 17:17:17 | [diff] [blame] | 123 | RE_LOONGARCH_PAGE_PC, |
WANG Xuerui | 6084ee7 | 2023-07-25 09:03:28 | [diff] [blame] | 124 | // Same as R_PLT_PC but with page-aligned semantics. |
Fangrui Song | 04996a2 | 2024-12-03 17:17:17 | [diff] [blame] | 125 | RE_LOONGARCH_PLT_PAGE_PC, |
WANG Xuerui | 6084ee7 | 2023-07-25 09:03:28 | [diff] [blame] | 126 | // In addition to having page-aligned semantics, LoongArch GOT relocs are |
| 127 | // also reused for TLS, making the semantics differ from other architectures. |
Fangrui Song | 04996a2 | 2024-12-03 17:17:17 | [diff] [blame] | 128 | RE_LOONGARCH_GOT, |
| 129 | RE_LOONGARCH_GOT_PAGE_PC, |
| 130 | RE_LOONGARCH_TLSGD_PAGE_PC, |
| 131 | RE_LOONGARCH_TLSDESC_PAGE_PC, |
Rui Ueyama | 0fcdc73 | 2016-05-24 20:24:43 | [diff] [blame] | 132 | }; |
| 133 | |
Rui Ueyama | 865d986 | 2016-10-21 04:52:11 | [diff] [blame] | 134 | // Architecture-neutral representation of relocation. |
Rafael Espindola | 664c652 | 2016-09-07 20:37:34 | [diff] [blame] | 135 | struct Relocation { |
Rui Ueyama | 3837f42 | 2019-07-10 05:00:37 | [diff] [blame] | 136 | RelExpr expr; |
| 137 | RelType type; |
| 138 | uint64_t offset; |
| 139 | int64_t addend; |
| 140 | Symbol *sym; |
Rui Ueyama | 0fcdc73 | 2016-05-24 20:24:43 | [diff] [blame] | 141 | }; |
| 142 | |
Sriraman Tallam | 9431787 | 2020-04-07 13:48:18 | [diff] [blame] | 143 | // Manipulate jump instructions with these modifiers. These are used to relax |
| 144 | // jump instruction opcodes at basic block boundaries and are particularly |
| 145 | // useful when basic block sections are enabled. |
| 146 | struct JumpInstrMod { |
Sriraman Tallam | 9431787 | 2020-04-07 13:48:18 | [diff] [blame] | 147 | uint64_t offset; |
Fangrui Song | e90c8c0 | 2021-12-27 06:17:30 | [diff] [blame] | 148 | JumpModType original; |
Sriraman Tallam | 9431787 | 2020-04-07 13:48:18 | [diff] [blame] | 149 | unsigned size; |
| 150 | }; |
| 151 | |
Nico Weber | 2c45043 | 2019-06-20 18:25:57 | [diff] [blame] | 152 | // This function writes undefined symbol diagnostics to an internal buffer. |
| 153 | // Call reportUndefinedSymbols() after calling scanRelocations() to emit |
| 154 | // the diagnostics. |
Fangrui Song | a94060c | 2024-09-28 07:26:23 | [diff] [blame] | 155 | template <class ELFT> void scanRelocations(Ctx &ctx); |
Fangrui Song | 29783f7 | 2024-09-29 02:17:18 | [diff] [blame] | 156 | template <class ELFT> void checkNoCrossRefs(Ctx &ctx); |
Fangrui Song | c490d34 | 2024-09-29 23:15:32 | [diff] [blame] | 157 | void reportUndefinedSymbols(Ctx &); |
Fangrui Song | a94060c | 2024-09-28 07:26:23 | [diff] [blame] | 158 | void postScanRelocations(Ctx &ctx); |
Fangrui Song | 29783f7 | 2024-09-29 02:17:18 | [diff] [blame] | 159 | void addGotEntry(Ctx &ctx, Symbol &sym); |
Rui Ueyama | c98e4d8 | 2016-07-02 08:50:03 | [diff] [blame] | 160 | |
Fangrui Song | 29783f7 | 2024-09-29 02:17:18 | [diff] [blame] | 161 | void hexagonTLSSymbolUpdate(Ctx &ctx); |
Sid Manning | 5a5a075 | 2020-02-10 23:27:53 | [diff] [blame] | 162 | bool hexagonNeedsTLSSymbol(ArrayRef<OutputSection *> outputSections); |
| 163 | |
Peter Smith | 56abf20 | 2017-04-05 10:30:09 | [diff] [blame] | 164 | class ThunkSection; |
| 165 | class Thunk; |
Andrew Ng | 77152a6 | 2020-09-09 09:48:21 | [diff] [blame] | 166 | class InputSectionDescription; |
Peter Smith | 56abf20 | 2017-04-05 10:30:09 | [diff] [blame] | 167 | |
George Rimar | ec84ffc | 2017-05-17 07:10:59 | [diff] [blame] | 168 | class ThunkCreator { |
Peter Smith | 56abf20 | 2017-04-05 10:30:09 | [diff] [blame] | 169 | public: |
Fangrui Song | 37e3966 | 2024-11-20 07:16:35 | [diff] [blame] | 170 | // Thunk may be incomplete. Avoid inline ctor/dtor. |
| 171 | ThunkCreator(Ctx &ctx); |
| 172 | ~ThunkCreator(); |
Peter Smith | 56abf20 | 2017-04-05 10:30:09 | [diff] [blame] | 173 | // Return true if Thunks have been added to OutputSections |
Fangrui Song | 6611d58 | 2022-07-07 17:16:09 | [diff] [blame] | 174 | bool createThunks(uint32_t pass, ArrayRef<OutputSection *> outputSections); |
Peter Smith | 3298027 | 2017-06-16 13:10:08 | [diff] [blame] | 175 | |
Peter Smith | 56abf20 | 2017-04-05 10:30:09 | [diff] [blame] | 176 | private: |
Rui Ueyama | 3837f42 | 2019-07-10 05:00:37 | [diff] [blame] | 177 | void mergeThunks(ArrayRef<OutputSection *> outputSections); |
Peter Smith | 75030b6d | 2017-10-27 09:04:11 | [diff] [blame] | 178 | |
Rui Ueyama | 3837f42 | 2019-07-10 05:00:37 | [diff] [blame] | 179 | ThunkSection *getISDThunkSec(OutputSection *os, InputSection *isec, |
Peter Smith | e35929e | 2021-02-26 13:14:21 | [diff] [blame] | 180 | InputSectionDescription *isd, |
| 181 | const Relocation &rel, uint64_t src); |
Peter Smith | 75030b6d | 2017-10-27 09:04:11 | [diff] [blame] | 182 | |
Rui Ueyama | 3837f42 | 2019-07-10 05:00:37 | [diff] [blame] | 183 | ThunkSection *getISThunkSec(InputSection *isec); |
Peter Smith | 4a8e115 | 2017-10-27 08:56:20 | [diff] [blame] | 184 | |
Rui Ueyama | 3837f42 | 2019-07-10 05:00:37 | [diff] [blame] | 185 | void createInitialThunkSections(ArrayRef<OutputSection *> outputSections); |
Peter Smith | f0c70f8 | 2017-10-27 08:58:28 | [diff] [blame] | 186 | |
Rui Ueyama | 3837f42 | 2019-07-10 05:00:37 | [diff] [blame] | 187 | std::pair<Thunk *, bool> getThunk(InputSection *isec, Relocation &rel, |
| 188 | uint64_t src); |
Peter Smith | f0c70f8 | 2017-10-27 08:58:28 | [diff] [blame] | 189 | |
Peter Smith | c4d9cd8 | 2024-10-01 12:12:29 | [diff] [blame] | 190 | std::pair<Thunk *, bool> getSyntheticLandingPad(Defined &d, int64_t a); |
| 191 | |
Rui Ueyama | 3837f42 | 2019-07-10 05:00:37 | [diff] [blame] | 192 | ThunkSection *addThunkSection(OutputSection *os, InputSectionDescription *, |
| 193 | uint64_t off); |
Peter Smith | f0c70f8 | 2017-10-27 08:58:28 | [diff] [blame] | 194 | |
Rui Ueyama | 3837f42 | 2019-07-10 05:00:37 | [diff] [blame] | 195 | bool normalizeExistingThunk(Relocation &rel, uint64_t src); |
Peter Smith | 6c9df3f | 2017-10-27 09:07:10 | [diff] [blame] | 196 | |
Peter Smith | 098b0d1 | 2024-11-15 18:18:18 | [diff] [blame] | 197 | bool addSyntheticLandingPads(); |
| 198 | |
Fangrui Song | a94060c | 2024-09-28 07:26:23 | [diff] [blame] | 199 | Ctx &ctx; |
| 200 | |
Fangrui Song | bf535ac | 2019-11-23 08:57:54 | [diff] [blame] | 201 | // Record all the available Thunks for a (Symbol, addend) pair, where Symbol |
| 202 | // is represented as a (section, offset) pair. There may be multiple |
| 203 | // relocations sharing the same (section, offset + addend) pair. We may revert |
| 204 | // a relocation back to its original non-Thunk target, and restore the |
| 205 | // original addend, so we cannot fold offset + addend. A nested pair is used |
| 206 | // because DenseMapInfo is not specialized for std::tuple. |
| 207 | llvm::DenseMap<std::pair<std::pair<SectionBase *, uint64_t>, int64_t>, |
Fangrui Song | 37e3966 | 2024-11-20 07:16:35 | [diff] [blame] | 208 | SmallVector<std::unique_ptr<Thunk>, 0>> |
Fangrui Song | bf535ac | 2019-11-23 08:57:54 | [diff] [blame] | 209 | thunkedSymbolsBySectionAndAddend; |
Fangrui Song | 37e3966 | 2024-11-20 07:16:35 | [diff] [blame] | 210 | llvm::DenseMap<std::pair<Symbol *, int64_t>, |
| 211 | SmallVector<std::unique_ptr<Thunk>, 0>> |
Fangrui Song | bf535ac | 2019-11-23 08:57:54 | [diff] [blame] | 212 | thunkedSymbols; |
Peter Smith | 56abf20 | 2017-04-05 10:30:09 | [diff] [blame] | 213 | |
Peter Smith | 3298027 | 2017-06-16 13:10:08 | [diff] [blame] | 214 | // Find a Thunk from the Thunks symbol definition, we can use this to find |
| 215 | // the Thunk from a relocation to the Thunks symbol definition. |
Rui Ueyama | 3837f42 | 2019-07-10 05:00:37 | [diff] [blame] | 216 | llvm::DenseMap<Symbol *, Thunk *> thunks; |
Peter Smith | 3298027 | 2017-06-16 13:10:08 | [diff] [blame] | 217 | |
Peter Smith | fa23764 | 2017-07-05 09:53:33 | [diff] [blame] | 218 | // Track InputSections that have an inline ThunkSection placed in front |
| 219 | // an inline ThunkSection may have control fall through to the section below |
| 220 | // so we need to make sure that there is only one of them. |
Peter Smith | c4d9cd8 | 2024-10-01 12:12:29 | [diff] [blame] | 221 | // The Mips LA25 Thunk is an example of an inline ThunkSection, as is |
| 222 | // the AArch64BTLandingPadThunk. |
Rui Ueyama | 3837f42 | 2019-07-10 05:00:37 | [diff] [blame] | 223 | llvm::DenseMap<InputSection *, ThunkSection *> thunkedSections; |
Fangrui Song | 6611d58 | 2022-07-07 17:16:09 | [diff] [blame] | 224 | |
Peter Smith | c4d9cd8 | 2024-10-01 12:12:29 | [diff] [blame] | 225 | // Record landing pads, generated for a section + offset destination. |
| 226 | // Landling pads are alternative entry points for destinations that need |
| 227 | // to be reached via thunks that use indirect branches. A destination |
| 228 | // needs at most one landing pad as that can be reused by all callers. |
| 229 | llvm::DenseMap<std::pair<std::pair<SectionBase *, uint64_t>, int64_t>, |
Fangrui Song | 37e3966 | 2024-11-20 07:16:35 | [diff] [blame] | 230 | std::unique_ptr<Thunk>> |
Peter Smith | c4d9cd8 | 2024-10-01 12:12:29 | [diff] [blame] | 231 | landingPadsBySectionAndAddend; |
| 232 | |
Peter Smith | 098b0d1 | 2024-11-15 18:18:18 | [diff] [blame] | 233 | // All the nonLandingPad thunks that have been created, in order of creation. |
| 234 | std::vector<Thunk *> allThunks; |
| 235 | |
Fangrui Song | 6611d58 | 2022-07-07 17:16:09 | [diff] [blame] | 236 | // The number of completed passes of createThunks this permits us |
| 237 | // to do one time initialization on Pass 0 and put a limit on the |
| 238 | // number of times it can be called to prevent infinite loops. |
| 239 | uint32_t pass = 0; |
Peter Smith | 56abf20 | 2017-04-05 10:30:09 | [diff] [blame] | 240 | }; |
Rafael Espindola | 0f7ceda | 2016-07-20 17:58:07 | [diff] [blame] | 241 | |
Fangrui Song | 0af07c0 | 2024-08-01 17:22:03 | [diff] [blame] | 242 | // Decode LEB128 without error checking. Only used by performance critical code |
| 243 | // like RelocsCrel. |
| 244 | inline uint64_t readLEB128(const uint8_t *&p, uint64_t leb) { |
| 245 | uint64_t acc = 0, shift = 0, byte; |
| 246 | do { |
| 247 | byte = *p++; |
| 248 | acc |= (byte - 128 * (byte >= leb)) << shift; |
| 249 | shift += 7; |
| 250 | } while (byte >= 128); |
| 251 | return acc; |
| 252 | } |
| 253 | inline uint64_t readULEB128(const uint8_t *&p) { return readLEB128(p, 128); } |
| 254 | inline int64_t readSLEB128(const uint8_t *&p) { return readLEB128(p, 64); } |
| 255 | |
| 256 | // This class implements a CREL iterator that does not allocate extra memory. |
| 257 | template <bool is64> struct RelocsCrel { |
| 258 | using uint = std::conditional_t<is64, uint64_t, uint32_t>; |
| 259 | struct const_iterator { |
| 260 | using iterator_category = std::forward_iterator_tag; |
| 261 | using value_type = llvm::object::Elf_Crel_Impl<is64>; |
| 262 | using difference_type = ptrdiff_t; |
| 263 | using pointer = value_type *; |
| 264 | using reference = const value_type &; |
| 265 | uint32_t count; |
| 266 | uint8_t flagBits, shift; |
| 267 | const uint8_t *p; |
| 268 | llvm::object::Elf_Crel_Impl<is64> crel{}; |
| 269 | const_iterator(size_t hdr, const uint8_t *p) |
| 270 | : count(hdr / 8), flagBits(hdr & 4 ? 3 : 2), shift(hdr % 4), p(p) { |
| 271 | if (count) |
| 272 | step(); |
| 273 | } |
| 274 | void step() { |
| 275 | // See object::decodeCrel. |
| 276 | const uint8_t b = *p++; |
| 277 | crel.r_offset += b >> flagBits << shift; |
| 278 | if (b >= 0x80) |
| 279 | crel.r_offset += |
| 280 | ((readULEB128(p) << (7 - flagBits)) - (0x80 >> flagBits)) << shift; |
| 281 | if (b & 1) |
| 282 | crel.r_symidx += readSLEB128(p); |
| 283 | if (b & 2) |
| 284 | crel.r_type += readSLEB128(p); |
| 285 | if (b & 4 && flagBits == 3) |
| 286 | crel.r_addend += static_cast<uint>(readSLEB128(p)); |
| 287 | } |
| 288 | llvm::object::Elf_Crel_Impl<is64> operator*() const { return crel; }; |
| 289 | const llvm::object::Elf_Crel_Impl<is64> *operator->() const { |
| 290 | return &crel; |
| 291 | } |
| 292 | // For llvm::enumerate. |
| 293 | bool operator==(const const_iterator &r) const { return count == r.count; } |
| 294 | bool operator!=(const const_iterator &r) const { return count != r.count; } |
| 295 | const_iterator &operator++() { |
| 296 | if (--count) |
| 297 | step(); |
| 298 | return *this; |
| 299 | } |
| 300 | // For RelocationScanner::scanOne. |
| 301 | void operator+=(size_t n) { |
| 302 | for (; n; --n) |
| 303 | operator++(); |
| 304 | } |
| 305 | }; |
| 306 | |
| 307 | size_t hdr = 0; |
| 308 | const uint8_t *p = nullptr; |
| 309 | |
| 310 | constexpr RelocsCrel() = default; |
| 311 | RelocsCrel(const uint8_t *p) : hdr(readULEB128(p)) { this->p = p; } |
| 312 | size_t size() const { return hdr / 8; } |
| 313 | const_iterator begin() const { return {hdr, p}; } |
| 314 | const_iterator end() const { return {0, nullptr}; } |
| 315 | }; |
| 316 | |
Fangrui Song | 6efc377 | 2024-07-27 17:55:17 | [diff] [blame] | 317 | template <class RelTy> struct Relocs : ArrayRef<RelTy> { |
| 318 | Relocs() = default; |
| 319 | Relocs(ArrayRef<RelTy> a) : ArrayRef<RelTy>(a) {} |
| 320 | }; |
| 321 | |
Fangrui Song | 0af07c0 | 2024-08-01 17:22:03 | [diff] [blame] | 322 | template <bool is64> |
| 323 | struct Relocs<llvm::object::Elf_Crel_Impl<is64>> : RelocsCrel<is64> { |
| 324 | using RelocsCrel<is64>::RelocsCrel; |
| 325 | }; |
| 326 | |
Rafael Espindola | 7386cea | 2017-02-16 00:12:34 | [diff] [blame] | 327 | // Return a int64_t to make sure we get the sign extension out of the way as |
| 328 | // early as possible. |
Rafael Espindola | 0f7ceda | 2016-07-20 17:58:07 | [diff] [blame] | 329 | template <class ELFT> |
Rui Ueyama | 3837f42 | 2019-07-10 05:00:37 | [diff] [blame] | 330 | static inline int64_t getAddend(const typename ELFT::Rel &rel) { |
Rui Ueyama | c98e4d8 | 2016-07-02 08:50:03 | [diff] [blame] | 331 | return 0; |
| 332 | } |
Rui Ueyama | c98e4d8 | 2016-07-02 08:50:03 | [diff] [blame] | 333 | template <class ELFT> |
Rui Ueyama | 3837f42 | 2019-07-10 05:00:37 | [diff] [blame] | 334 | static inline int64_t getAddend(const typename ELFT::Rela &rel) { |
| 335 | return rel.r_addend; |
Rui Ueyama | c98e4d8 | 2016-07-02 08:50:03 | [diff] [blame] | 336 | } |
Fangrui Song | 0af07c0 | 2024-08-01 17:22:03 | [diff] [blame] | 337 | template <class ELFT> |
| 338 | static inline int64_t getAddend(const typename ELFT::Crel &rel) { |
| 339 | return rel.r_addend; |
| 340 | } |
Fangrui Song | c9b1bd10 | 2021-04-29 15:51:09 | [diff] [blame] | 341 | |
| 342 | template <typename RelTy> |
Fangrui Song | 6efc377 | 2024-07-27 17:55:17 | [diff] [blame] | 343 | inline Relocs<RelTy> sortRels(Relocs<RelTy> rels, |
| 344 | SmallVector<RelTy, 0> &storage) { |
Fangrui Song | c9b1bd10 | 2021-04-29 15:51:09 | [diff] [blame] | 345 | auto cmp = [](const RelTy &a, const RelTy &b) { |
| 346 | return a.r_offset < b.r_offset; |
| 347 | }; |
| 348 | if (!llvm::is_sorted(rels, cmp)) { |
| 349 | storage.assign(rels.begin(), rels.end()); |
| 350 | llvm::stable_sort(storage, cmp); |
Fangrui Song | 6efc377 | 2024-07-27 17:55:17 | [diff] [blame] | 351 | rels = Relocs<RelTy>(storage); |
Fangrui Song | c9b1bd10 | 2021-04-29 15:51:09 | [diff] [blame] | 352 | } |
| 353 | return rels; |
| 354 | } |
Mitch Phillips | ca35a19 | 2023-07-31 15:07:26 | [diff] [blame] | 355 | |
Fangrui Song | 0af07c0 | 2024-08-01 17:22:03 | [diff] [blame] | 356 | template <bool is64> |
| 357 | inline Relocs<llvm::object::Elf_Crel_Impl<is64>> |
| 358 | sortRels(Relocs<llvm::object::Elf_Crel_Impl<is64>> rels, |
| 359 | SmallVector<llvm::object::Elf_Crel_Impl<is64>, 0> &storage) { |
| 360 | return {}; |
| 361 | } |
| 362 | |
pcc | 970d6d2 | 2024-12-05 01:35:05 | [diff] [blame] | 363 | RelocationBaseSection &getIRelativeSection(Ctx &ctx); |
| 364 | |
Mitch Phillips | ca35a19 | 2023-07-31 15:07:26 | [diff] [blame] | 365 | // Returns true if Expr refers a GOT entry. Note that this function returns |
| 366 | // false for TLS variables even though they need GOT, because TLS variables uses |
| 367 | // GOT differently than the regular variables. |
| 368 | bool needsGot(RelExpr expr); |
Nico Weber | 87248ba | 2022-08-10 19:31:58 | [diff] [blame] | 369 | } // namespace lld::elf |
Rui Ueyama | 0fcdc73 | 2016-05-24 20:24:43 | [diff] [blame] | 370 | |
| 371 | #endif |