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 | class Defined; |
17 | class InputFile; |
18 | class Symbol; |
19 | class ThunkSection; |
20 | // Class to describe an instance of a Thunk. |
21 | // A Thunk is a code-sequence inserted by the linker in between a caller and |
22 | // the callee. The relocation to the callee is redirected to the Thunk, which |
23 | // after executing transfers control to the callee. Typical uses of Thunks |
24 | // include transferring control from non-pi to pi and changing state on |
25 | // targets like ARM. |
26 | // |
27 | // Thunks can be created for Defined, Shared and Undefined Symbols. |
28 | // Thunks are assigned to synthetic ThunkSections |
29 | class Thunk { |
30 | public: |
31 | Thunk(Symbol &destination, int64_t addend); |
32 | virtual ~Thunk(); |
33 | |
34 | virtual uint32_t size() = 0; |
35 | virtual void writeTo(uint8_t *buf) = 0; |
36 | |
37 | // All Thunks must define at least one symbol, known as the thunk target |
38 | // symbol, so that we can redirect relocations to it. The thunk may define |
39 | // additional symbols, but these are never targets for relocations. |
40 | virtual void addSymbols(ThunkSection &isec) = 0; |
41 | |
42 | void setOffset(uint64_t offset); |
43 | Defined *addSymbol(StringRef name, uint8_t type, uint64_t value, |
44 | InputSectionBase §ion); |
45 | |
46 | // Some Thunks must be placed immediately before their Target as they elide |
47 | // a branch and fall through to the first Symbol in the Target. |
48 | virtual InputSection *getTargetInputSection() const { return nullptr; } |
49 | |
50 | // To reuse a Thunk the InputSection and the relocation must be compatible |
51 | // with it. |
52 | virtual bool isCompatibleWith(const InputSection &, |
53 | const Relocation &) const { |
54 | return true; |
55 | } |
56 | |
57 | Defined *getThunkTargetSym() const { return syms[0]; } |
58 | |
59 | Symbol &destination; |
60 | int64_t addend; |
61 | llvm::SmallVector<Defined *, 3> syms; |
62 | uint64_t offset = 0; |
63 | // The alignment requirement for this Thunk, defaults to the size of the |
64 | // typical code section alignment. |
65 | uint32_t alignment = 4; |
66 | }; |
67 | |
68 | // For a Relocation to symbol S create a Thunk to be added to a synthetic |
69 | // ThunkSection. |
70 | Thunk *addThunk(const InputSection &isec, Relocation &rel); |
71 | |
72 | void writePPC32PltCallStub(uint8_t *buf, uint64_t gotPltVA, |
73 | const InputFile *file, int64_t addend); |
74 | void writePPC64LoadAndBranch(uint8_t *buf, int64_t offset); |
75 | |
76 | } // namespace lld::elf |
77 | |
78 | #endif |
79 | |