10b57cec5SDimitry Andric //===- Thunks.h --------------------------------------------------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric 90b57cec5SDimitry Andric #ifndef LLD_ELF_THUNKS_H 100b57cec5SDimitry Andric #define LLD_ELF_THUNKS_H 110b57cec5SDimitry Andric 12fe6060f1SDimitry Andric #include "llvm/ADT/SmallVector.h" 130b57cec5SDimitry Andric #include "Relocations.h" 140b57cec5SDimitry Andric 15*bdd1243dSDimitry Andric namespace lld::elf { 160b57cec5SDimitry Andric class Defined; 17480093f4SDimitry Andric class InputFile; 180b57cec5SDimitry Andric class Symbol; 190b57cec5SDimitry Andric class ThunkSection; 200b57cec5SDimitry Andric // Class to describe an instance of a Thunk. 210b57cec5SDimitry Andric // A Thunk is a code-sequence inserted by the linker in between a caller and 220b57cec5SDimitry Andric // the callee. The relocation to the callee is redirected to the Thunk, which 230b57cec5SDimitry Andric // after executing transfers control to the callee. Typical uses of Thunks 240b57cec5SDimitry Andric // include transferring control from non-pi to pi and changing state on 250b57cec5SDimitry Andric // targets like ARM. 260b57cec5SDimitry Andric // 270b57cec5SDimitry Andric // Thunks can be created for Defined, Shared and Undefined Symbols. 280b57cec5SDimitry Andric // Thunks are assigned to synthetic ThunkSections 290b57cec5SDimitry Andric class Thunk { 300b57cec5SDimitry Andric public: 31480093f4SDimitry Andric Thunk(Symbol &destination, int64_t addend); 320b57cec5SDimitry Andric virtual ~Thunk(); 330b57cec5SDimitry Andric 340b57cec5SDimitry Andric virtual uint32_t size() = 0; 350b57cec5SDimitry Andric virtual void writeTo(uint8_t *buf) = 0; 360b57cec5SDimitry Andric 370b57cec5SDimitry Andric // All Thunks must define at least one symbol, known as the thunk target 380b57cec5SDimitry Andric // symbol, so that we can redirect relocations to it. The thunk may define 390b57cec5SDimitry Andric // additional symbols, but these are never targets for relocations. 400b57cec5SDimitry Andric virtual void addSymbols(ThunkSection &isec) = 0; 410b57cec5SDimitry Andric 420b57cec5SDimitry Andric void setOffset(uint64_t offset); 430b57cec5SDimitry Andric Defined *addSymbol(StringRef name, uint8_t type, uint64_t value, 440b57cec5SDimitry Andric InputSectionBase §ion); 450b57cec5SDimitry Andric 460b57cec5SDimitry Andric // Some Thunks must be placed immediately before their Target as they elide 470b57cec5SDimitry Andric // a branch and fall through to the first Symbol in the Target. getTargetInputSection()480b57cec5SDimitry Andric virtual InputSection *getTargetInputSection() const { return nullptr; } 490b57cec5SDimitry Andric 500b57cec5SDimitry Andric // To reuse a Thunk the InputSection and the relocation must be compatible 510b57cec5SDimitry Andric // with it. isCompatibleWith(const InputSection &,const Relocation &)520b57cec5SDimitry Andric virtual bool isCompatibleWith(const InputSection &, 530b57cec5SDimitry Andric const Relocation &) const { 540b57cec5SDimitry Andric return true; 550b57cec5SDimitry Andric } 560b57cec5SDimitry Andric getThunkTargetSym()570b57cec5SDimitry Andric Defined *getThunkTargetSym() const { return syms[0]; } 580b57cec5SDimitry Andric 590b57cec5SDimitry Andric Symbol &destination; 60480093f4SDimitry Andric int64_t addend; 610b57cec5SDimitry Andric llvm::SmallVector<Defined *, 3> syms; 620b57cec5SDimitry Andric uint64_t offset = 0; 63480093f4SDimitry Andric // The alignment requirement for this Thunk, defaults to the size of the 64480093f4SDimitry Andric // typical code section alignment. 650b57cec5SDimitry Andric uint32_t alignment = 4; 660b57cec5SDimitry Andric }; 670b57cec5SDimitry Andric 680b57cec5SDimitry Andric // For a Relocation to symbol S create a Thunk to be added to a synthetic 690b57cec5SDimitry Andric // ThunkSection. 700b57cec5SDimitry Andric Thunk *addThunk(const InputSection &isec, Relocation &rel); 710b57cec5SDimitry Andric 72480093f4SDimitry Andric void writePPC32PltCallStub(uint8_t *buf, uint64_t gotPltVA, 73480093f4SDimitry Andric const InputFile *file, int64_t addend); 74480093f4SDimitry Andric void writePPC64LoadAndBranch(uint8_t *buf, int64_t offset); 75480093f4SDimitry Andric 76*bdd1243dSDimitry Andric } // namespace lld::elf 770b57cec5SDimitry Andric 780b57cec5SDimitry Andric #endif 79