1 | //===- Thunks.h --------------------------------------------------------===// |
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_THUNKS_H |
10 | #define LLD_ELF_THUNKS_H |
11 | |
12 | #include "llvm/ADT/SmallVector.h" |
13 | #include "Relocations.h" |
14 | |
15 | namespace lld::elf { |
16 | struct Ctx; |
17 | class Defined; |
18 | class InputFile; |
19 | class Symbol; |
20 | class ThunkSection; |
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 | // |
28 | // Thunks can be created for Defined, Shared and Undefined Symbols. |
29 | // Thunks are assigned to synthetic ThunkSections |
30 | class Thunk { |
31 | public: |
32 | Thunk(Ctx &, Symbol &destination, int64_t addend); |
33 | virtual ~Thunk(); |
34 | |
35 | virtual uint32_t size() = 0; |
36 | virtual void writeTo(uint8_t *buf) = 0; |
37 | |
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. |
41 | virtual void addSymbols(ThunkSection &isec) = 0; |
42 | |
43 | void setOffset(uint64_t offset); |
44 | Defined *addSymbol(StringRef name, uint8_t type, uint64_t value, |
45 | InputSectionBase §ion); |
46 | |
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. |
49 | virtual InputSection *getTargetInputSection() const { return nullptr; } |
50 | |
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 | } |
57 | |
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 | |
63 | Defined *getThunkTargetSym() const { return syms[0]; } |
64 | |
65 | Ctx &ctx; |
66 | Symbol &destination; |
67 | int64_t addend; |
68 | // Alternative target when indirect branch to destination can't be used. |
69 | Symbol *landingPad = nullptr; |
70 | llvm::SmallVector<Defined *, 3> syms; |
71 | uint64_t offset = 0; |
72 | // The alignment requirement for this Thunk, defaults to the size of the |
73 | // typical code section alignment. |
74 | uint32_t alignment = 4; |
75 | }; |
76 | |
77 | // For a Relocation to symbol S create a Thunk to be added to a synthetic |
78 | // ThunkSection. |
79 | std::unique_ptr<Thunk> addThunk(Ctx &, const InputSection &isec, |
80 | Relocation &rel); |
81 | |
82 | // Create a landing pad Thunk for use when indirect branches from Thunks |
83 | // are restricted. |
84 | std::unique_ptr<Thunk> addLandingPadThunk(Ctx &, Symbol &s, int64_t a); |
85 | |
86 | void writePPC32PltCallStub(Ctx &, uint8_t *buf, uint64_t gotPltVA, |
87 | const InputFile *file, int64_t addend); |
88 | void writePPC64LoadAndBranch(Ctx &, uint8_t *buf, int64_t offset); |
89 | |
90 | } // namespace lld::elf |
91 | |
92 | #endif |
93 | |