blob: 446345b8517f9324eb2ec3068ce17c9f29b4e043 [file] [log] [blame]
Peter Smithfb05cd92016-07-08 16:10:27 +00001//===- Thunks.h --------------------------------------------------------===//
2//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// 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 Smithfb05cd92016-07-08 16:10:27 +00006//
7//===----------------------------------------------------------------------===//
8
9#ifndef LLD_ELF_THUNKS_H
10#define LLD_ELF_THUNKS_H
11
Nikita Popovd93b6782021-06-03 18:54:23 +020012#include "llvm/ADT/SmallVector.h"
Peter Smithfb05cd92016-07-08 16:10:27 +000013#include "Relocations.h"
14
Nico Weber87248ba2022-08-10 15:31:58 -040015namespace lld::elf {
Fangrui Songcf30e8e12024-09-29 14:59:57 -070016struct Ctx;
Peter Collingbournec5391ce2018-03-29 22:32:13 +000017class Defined;
Fangrui Songfb2944b2019-12-17 11:23:37 -080018class InputFile;
Rui Ueyamaf52496e2017-11-03 21:21:47 +000019class Symbol;
George Rimar7b827042017-03-16 10:40:50 +000020class ThunkSection;
Peter Smithfb05cd92016-07-08 16:10:27 +000021// 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 Collingbournee9a9e0a2017-11-06 04:35:31 +000028// Thunks can be created for Defined, Shared and Undefined Symbols.
Peter Smith3a52eb02017-02-01 10:26:03 +000029// Thunks are assigned to synthetic ThunkSections
George Rimar7b827042017-03-16 10:40:50 +000030class Thunk {
Peter Smithfb05cd92016-07-08 16:10:27 +000031public:
Fangrui Song04e69ad2024-09-29 15:20:01 -070032 Thunk(Ctx &, Symbol &destination, int64_t addend);
Peter Smithfb05cd92016-07-08 16:10:27 +000033 virtual ~Thunk();
34
Peter Collingbournecebab4a2018-03-28 21:33:31 +000035 virtual uint32_t size() = 0;
Rui Ueyama3837f422019-07-10 05:00:37 +000036 virtual void writeTo(uint8_t *buf) = 0;
Rui Ueyama3d2bbb12016-07-09 22:52:30 +000037
Peter Collingbournec5391ce2018-03-29 22:32:13 +000038 // 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 Ueyama3837f422019-07-10 05:00:37 +000041 virtual void addSymbols(ThunkSection &isec) = 0;
Peter Smith3a52eb02017-02-01 10:26:03 +000042
Rui Ueyama3837f422019-07-10 05:00:37 +000043 void setOffset(uint64_t offset);
44 Defined *addSymbol(StringRef name, uint8_t type, uint64_t value,
45 InputSectionBase &section);
Peter Collingbournec5391ce2018-03-29 22:32:13 +000046
Peter Smith3a52eb02017-02-01 10:26:03 +000047 // 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 Espindola774ea7d2017-02-23 16:49:07 +000049 virtual InputSection *getTargetInputSection() const { return nullptr; }
Peter Smith3a52eb02017-02-01 10:26:03 +000050
Fangrui Song82442ad2019-06-06 17:03:00 +000051 // 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 Smith7d66e842017-07-05 09:36:03 +000057
Peter Smithc4d9cd82024-10-01 13:12:29 +010058 // 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 Ueyama3837f422019-07-10 05:00:37 +000063 Defined *getThunkTargetSym() const { return syms[0]; }
Peter Collingbournec5391ce2018-03-29 22:32:13 +000064
Fangrui Song04e69ad2024-09-29 15:20:01 -070065 Ctx &ctx;
Rui Ueyama3837f422019-07-10 05:00:37 +000066 Symbol &destination;
Fangrui Songbf535ac2019-11-23 00:57:54 -080067 int64_t addend;
Peter Smithc4d9cd82024-10-01 13:12:29 +010068 // Alternative target when indirect branch to destination can't be used.
69 Symbol *landingPad = nullptr;
Rui Ueyama3837f422019-07-10 05:00:37 +000070 llvm::SmallVector<Defined *, 3> syms;
71 uint64_t offset = 0;
Fangrui Songbf535ac2019-11-23 00:57:54 -080072 // The alignment requirement for this Thunk, defaults to the size of the
73 // typical code section alignment.
Rui Ueyama3837f422019-07-10 05:00:37 +000074 uint32_t alignment = 4;
Peter Smithfb05cd92016-07-08 16:10:27 +000075};
76
Peter Smith3a52eb02017-02-01 10:26:03 +000077// For a Relocation to symbol S create a Thunk to be added to a synthetic
Fangrui Song82442ad2019-06-06 17:03:00 +000078// ThunkSection.
Fangrui Song37e39662024-11-19 23:16:35 -080079std::unique_ptr<Thunk> addThunk(Ctx &, const InputSection &isec,
80 Relocation &rel);
Peter Smithfb05cd92016-07-08 16:10:27 +000081
Peter Smithc4d9cd82024-10-01 13:12:29 +010082// Create a landing pad Thunk for use when indirect branches from Thunks
83// are restricted.
Fangrui Song37e39662024-11-19 23:16:35 -080084std::unique_ptr<Thunk> addLandingPadThunk(Ctx &, Symbol &s, int64_t a);
Peter Smithc4d9cd82024-10-01 13:12:29 +010085
Fangrui Song04e69ad2024-09-29 15:20:01 -070086void writePPC32PltCallStub(Ctx &, uint8_t *buf, uint64_t gotPltVA,
Fangrui Songfb2944b2019-12-17 11:23:37 -080087 const InputFile *file, int64_t addend);
Fangrui Song0dbc85a2024-10-13 11:08:06 -070088void writePPC64LoadAndBranch(Ctx &, uint8_t *buf, int64_t offset);
Fangrui Song45acc352019-12-13 18:30:21 -080089
Nico Weber87248ba2022-08-10 15:31:58 -040090} // namespace lld::elf
Peter Smithfb05cd92016-07-08 16:10:27 +000091
92#endif