Peter Smith | fb05cd9 | 2016-07-08 16:10:27 +0000 | [diff] [blame] | 1 | //===- Thunks.h --------------------------------------------------------===// |
| 2 | // |
Chandler Carruth | 2946cd7 | 2019-01-19 08:50:56 +0000 | [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 |
Peter Smith | fb05cd9 | 2016-07-08 16:10:27 +0000 | [diff] [blame] | 6 | // |
| 7 | //===----------------------------------------------------------------------===// |
| 8 | |
| 9 | #ifndef LLD_ELF_THUNKS_H |
| 10 | #define LLD_ELF_THUNKS_H |
| 11 | |
Nikita Popov | d93b678 | 2021-06-03 18:54:23 +0200 | [diff] [blame] | 12 | #include "llvm/ADT/SmallVector.h" |
Peter Smith | fb05cd9 | 2016-07-08 16:10:27 +0000 | [diff] [blame] | 13 | #include "Relocations.h" |
| 14 | |
Nico Weber | 87248ba | 2022-08-10 15:31:58 -0400 | [diff] [blame] | 15 | namespace lld::elf { |
Fangrui Song | cf30e8e1 | 2024-09-29 14:59:57 -0700 | [diff] [blame] | 16 | struct Ctx; |
Peter Collingbourne | c5391ce | 2018-03-29 22:32:13 +0000 | [diff] [blame] | 17 | class Defined; |
Fangrui Song | fb2944b | 2019-12-17 11:23:37 -0800 | [diff] [blame] | 18 | class InputFile; |
Rui Ueyama | f52496e | 2017-11-03 21:21:47 +0000 | [diff] [blame] | 19 | class Symbol; |
George Rimar | 7b82704 | 2017-03-16 10:40:50 +0000 | [diff] [blame] | 20 | class ThunkSection; |
Peter Smith | fb05cd9 | 2016-07-08 16:10:27 +0000 | [diff] [blame] | 21 | // Class to describe an instance of a Thunk. |
| 22 | // A Thunk is a code-sequence inserted by the linker in between a caller and |
| 23 | // the callee. The relocation to the callee is redirected to the Thunk, which |
| 24 | // after executing transfers control to the callee. Typical uses of Thunks |
| 25 | // include transferring control from non-pi to pi and changing state on |
| 26 | // targets like ARM. |
| 27 | // |
Peter Collingbourne | e9a9e0a | 2017-11-06 04:35:31 +0000 | [diff] [blame] | 28 | // Thunks can be created for Defined, Shared and Undefined Symbols. |
Peter Smith | 3a52eb0 | 2017-02-01 10:26:03 +0000 | [diff] [blame] | 29 | // Thunks are assigned to synthetic ThunkSections |
George Rimar | 7b82704 | 2017-03-16 10:40:50 +0000 | [diff] [blame] | 30 | class Thunk { |
Peter Smith | fb05cd9 | 2016-07-08 16:10:27 +0000 | [diff] [blame] | 31 | public: |
Fangrui Song | 04e69ad | 2024-09-29 15:20:01 -0700 | [diff] [blame] | 32 | Thunk(Ctx &, Symbol &destination, int64_t addend); |
Peter Smith | fb05cd9 | 2016-07-08 16:10:27 +0000 | [diff] [blame] | 33 | virtual ~Thunk(); |
| 34 | |
Peter Collingbourne | cebab4a | 2018-03-28 21:33:31 +0000 | [diff] [blame] | 35 | virtual uint32_t size() = 0; |
Rui Ueyama | 3837f42 | 2019-07-10 05:00:37 +0000 | [diff] [blame] | 36 | virtual void writeTo(uint8_t *buf) = 0; |
Rui Ueyama | 3d2bbb1 | 2016-07-09 22:52:30 +0000 | [diff] [blame] | 37 | |
Peter Collingbourne | c5391ce | 2018-03-29 22:32:13 +0000 | [diff] [blame] | 38 | // All Thunks must define at least one symbol, known as the thunk target |
| 39 | // symbol, so that we can redirect relocations to it. The thunk may define |
| 40 | // additional symbols, but these are never targets for relocations. |
Rui Ueyama | 3837f42 | 2019-07-10 05:00:37 +0000 | [diff] [blame] | 41 | virtual void addSymbols(ThunkSection &isec) = 0; |
Peter Smith | 3a52eb0 | 2017-02-01 10:26:03 +0000 | [diff] [blame] | 42 | |
Rui Ueyama | 3837f42 | 2019-07-10 05:00:37 +0000 | [diff] [blame] | 43 | void setOffset(uint64_t offset); |
| 44 | Defined *addSymbol(StringRef name, uint8_t type, uint64_t value, |
| 45 | InputSectionBase §ion); |
Peter Collingbourne | c5391ce | 2018-03-29 22:32:13 +0000 | [diff] [blame] | 46 | |
Peter Smith | 3a52eb0 | 2017-02-01 10:26:03 +0000 | [diff] [blame] | 47 | // Some Thunks must be placed immediately before their Target as they elide |
| 48 | // a branch and fall through to the first Symbol in the Target. |
Rafael Espindola | 774ea7d | 2017-02-23 16:49:07 +0000 | [diff] [blame] | 49 | virtual InputSection *getTargetInputSection() const { return nullptr; } |
Peter Smith | 3a52eb0 | 2017-02-01 10:26:03 +0000 | [diff] [blame] | 50 | |
Fangrui Song | 82442ad | 2019-06-06 17:03:00 +0000 | [diff] [blame] | 51 | // To reuse a Thunk the InputSection and the relocation must be compatible |
| 52 | // with it. |
| 53 | virtual bool isCompatibleWith(const InputSection &, |
| 54 | const Relocation &) const { |
| 55 | return true; |
| 56 | } |
Peter Smith | 7d66e84 | 2017-07-05 09:36:03 +0000 | [diff] [blame] | 57 | |
Peter Smith | c4d9cd8 | 2024-10-01 13:12:29 +0100 | [diff] [blame] | 58 | // Thunks that indirectly branch to targets may need a synthetic landing |
| 59 | // pad generated close to the target. For example AArch64 when BTI is |
| 60 | // enabled. |
| 61 | virtual bool needsSyntheticLandingPad() { return false; } |
| 62 | |
Rui Ueyama | 3837f42 | 2019-07-10 05:00:37 +0000 | [diff] [blame] | 63 | Defined *getThunkTargetSym() const { return syms[0]; } |
Peter Collingbourne | c5391ce | 2018-03-29 22:32:13 +0000 | [diff] [blame] | 64 | |
Fangrui Song | 04e69ad | 2024-09-29 15:20:01 -0700 | [diff] [blame] | 65 | Ctx &ctx; |
Rui Ueyama | 3837f42 | 2019-07-10 05:00:37 +0000 | [diff] [blame] | 66 | Symbol &destination; |
Fangrui Song | bf535ac | 2019-11-23 00:57:54 -0800 | [diff] [blame] | 67 | int64_t addend; |
Peter Smith | c4d9cd8 | 2024-10-01 13:12:29 +0100 | [diff] [blame] | 68 | // Alternative target when indirect branch to destination can't be used. |
| 69 | Symbol *landingPad = nullptr; |
Rui Ueyama | 3837f42 | 2019-07-10 05:00:37 +0000 | [diff] [blame] | 70 | llvm::SmallVector<Defined *, 3> syms; |
| 71 | uint64_t offset = 0; |
Fangrui Song | bf535ac | 2019-11-23 00:57:54 -0800 | [diff] [blame] | 72 | // The alignment requirement for this Thunk, defaults to the size of the |
| 73 | // typical code section alignment. |
Rui Ueyama | 3837f42 | 2019-07-10 05:00:37 +0000 | [diff] [blame] | 74 | uint32_t alignment = 4; |
Peter Smith | fb05cd9 | 2016-07-08 16:10:27 +0000 | [diff] [blame] | 75 | }; |
| 76 | |
Peter Smith | 3a52eb0 | 2017-02-01 10:26:03 +0000 | [diff] [blame] | 77 | // For a Relocation to symbol S create a Thunk to be added to a synthetic |
Fangrui Song | 82442ad | 2019-06-06 17:03:00 +0000 | [diff] [blame] | 78 | // ThunkSection. |
Fangrui Song | 37e3966 | 2024-11-19 23:16:35 -0800 | [diff] [blame] | 79 | std::unique_ptr<Thunk> addThunk(Ctx &, const InputSection &isec, |
| 80 | Relocation &rel); |
Peter Smith | fb05cd9 | 2016-07-08 16:10:27 +0000 | [diff] [blame] | 81 | |
Peter Smith | c4d9cd8 | 2024-10-01 13:12:29 +0100 | [diff] [blame] | 82 | // Create a landing pad Thunk for use when indirect branches from Thunks |
| 83 | // are restricted. |
Fangrui Song | 37e3966 | 2024-11-19 23:16:35 -0800 | [diff] [blame] | 84 | std::unique_ptr<Thunk> addLandingPadThunk(Ctx &, Symbol &s, int64_t a); |
Peter Smith | c4d9cd8 | 2024-10-01 13:12:29 +0100 | [diff] [blame] | 85 | |
Fangrui Song | 04e69ad | 2024-09-29 15:20:01 -0700 | [diff] [blame] | 86 | void writePPC32PltCallStub(Ctx &, uint8_t *buf, uint64_t gotPltVA, |
Fangrui Song | fb2944b | 2019-12-17 11:23:37 -0800 | [diff] [blame] | 87 | const InputFile *file, int64_t addend); |
Fangrui Song | 0dbc85a | 2024-10-13 11:08:06 -0700 | [diff] [blame] | 88 | void writePPC64LoadAndBranch(Ctx &, uint8_t *buf, int64_t offset); |
Fangrui Song | 45acc35 | 2019-12-13 18:30:21 -0800 | [diff] [blame] | 89 | |
Nico Weber | 87248ba | 2022-08-10 15:31:58 -0400 | [diff] [blame] | 90 | } // namespace lld::elf |
Peter Smith | fb05cd9 | 2016-07-08 16:10:27 +0000 | [diff] [blame] | 91 | |
| 92 | #endif |