2016-07-09 00:10:27 +08:00
|
|
|
//===- Thunks.h --------------------------------------------------------===//
|
|
|
|
//
|
2019-01-19 16:50:56 +08:00
|
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
2016-07-09 00:10:27 +08:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#ifndef LLD_ELF_THUNKS_H
|
|
|
|
#define LLD_ELF_THUNKS_H
|
|
|
|
|
|
|
|
#include "Relocations.h"
|
|
|
|
|
|
|
|
namespace lld {
|
|
|
|
namespace elf {
|
2018-03-30 06:32:13 +08:00
|
|
|
class Defined;
|
2017-11-04 05:21:47 +08:00
|
|
|
class Symbol;
|
2017-03-16 18:40:50 +08:00
|
|
|
class ThunkSection;
|
2016-07-09 00:10:27 +08:00
|
|
|
// Class to describe an instance of a Thunk.
|
|
|
|
// A Thunk is a code-sequence inserted by the linker in between a caller and
|
|
|
|
// the callee. The relocation to the callee is redirected to the Thunk, which
|
|
|
|
// after executing transfers control to the callee. Typical uses of Thunks
|
|
|
|
// include transferring control from non-pi to pi and changing state on
|
|
|
|
// targets like ARM.
|
|
|
|
//
|
2017-11-06 12:35:31 +08:00
|
|
|
// Thunks can be created for Defined, Shared and Undefined Symbols.
|
2017-02-01 18:26:03 +08:00
|
|
|
// Thunks are assigned to synthetic ThunkSections
|
2017-03-16 18:40:50 +08:00
|
|
|
class Thunk {
|
2016-07-09 00:10:27 +08:00
|
|
|
public:
|
2017-11-04 05:21:47 +08:00
|
|
|
Thunk(Symbol &Destination);
|
2016-07-09 00:10:27 +08:00
|
|
|
virtual ~Thunk();
|
|
|
|
|
2018-03-29 05:33:31 +08:00
|
|
|
virtual uint32_t size() = 0;
|
|
|
|
virtual void writeTo(uint8_t *Buf) = 0;
|
2017-02-01 18:26:03 +08:00
|
|
|
|
2018-03-30 06:32:13 +08:00
|
|
|
// All Thunks must define at least one symbol, known as the thunk target
|
|
|
|
// symbol, so that we can redirect relocations to it. The thunk may define
|
|
|
|
// additional symbols, but these are never targets for relocations.
|
2018-03-29 05:33:31 +08:00
|
|
|
virtual void addSymbols(ThunkSection &IS) = 0;
|
2017-02-01 18:26:03 +08:00
|
|
|
|
2018-03-30 06:32:13 +08:00
|
|
|
void setOffset(uint64_t Offset);
|
|
|
|
Defined *addSymbol(StringRef Name, uint8_t Type, uint64_t Value,
|
|
|
|
InputSectionBase &Section);
|
|
|
|
|
2017-02-01 18:26:03 +08:00
|
|
|
// Some Thunks must be placed immediately before their Target as they elide
|
|
|
|
// a branch and fall through to the first Symbol in the Target.
|
2017-02-24 00:49:07 +08:00
|
|
|
virtual InputSection *getTargetInputSection() const { return nullptr; }
|
2016-07-10 06:52:30 +08:00
|
|
|
|
[PPC32] Improve the 32-bit PowerPC port
Many -static/-no-pie/-shared/-pie applications linked against glibc or musl
should work with this patch. This also helps FreeBSD PowerPC64 to migrate
their lib32 (PR40888).
* Fix default image base and max page size.
* Support new-style Secure PLT (see below). Old-style BSS PLT is not
implemented, so it is not suitable for FreeBSD rtld now because it doesn't
support Secure PLT yet.
* Support more initial relocation types:
R_PPC_ADDR32, R_PPC_REL16*, R_PPC_LOCAL24PC, R_PPC_PLTREL24, and R_PPC_GOT16.
The addend of R_PPC_PLTREL24 is special: it decides the call stub PLT type
but it should be ignored for the computation of target symbol VA.
* Support GNU ifunc
* Support .glink used for lazy PLT resolution in glibc
* Add a new thunk type: PPC32PltCallStub that is similar to PPC64PltCallStub.
It is used by R_PPC_REL24 and R_PPC_PLTREL24.
A PLT stub used in -fPIE/-fPIC usually loads an address relative to
.got2+0x8000 (-fpie/-fpic code uses _GLOBAL_OFFSET_TABLE_ relative
addresses).
Two .got2 sections in two object files have different addresses, thus a PLT stub
can't be shared by two object files. To handle this incompatibility,
change the parameters of Thunk::isCompatibleWith to
`const InputSection &, const Relocation &`.
PowerPC psABI specified an old-style .plt (BSS PLT) that is both
writable and executable. Linkers don't make separate RW- and RWE segments,
which causes all initially writable memory (think .data) executable.
This is a big security concern so a new PLT scheme (secure PLT) was developed to
address the security issue.
TLS will be implemented in D62940.
glibc older than ~2012 requires .rela.dyn to include .rela.plt, it can
not handle the DT_RELA+DT_RELASZ == DT_JMPREL case correctly. A hack
(not included in this patch) in LinkerScript.cpp addOrphanSections() to
work around the issue:
if (Config->EMachine == EM_PPC) {
// Older glibc assumes .rela.dyn includes .rela.plt
Add(In.RelaDyn);
if (In.RelaPlt->isLive() && !In.RelaPlt->Parent)
In.RelaDyn->getParent()->addSection(In.RelaPlt);
}
Reviewed By: ruiu
Differential Revision: https://reviews.llvm.org/D62464
llvm-svn: 362721
2019-06-07 01:03:00 +08:00
|
|
|
// To reuse a Thunk the InputSection and the relocation must be compatible
|
|
|
|
// with it.
|
|
|
|
virtual bool isCompatibleWith(const InputSection &,
|
|
|
|
const Relocation &) const {
|
|
|
|
return true;
|
|
|
|
}
|
2017-07-05 17:36:03 +08:00
|
|
|
|
2018-03-30 06:32:13 +08:00
|
|
|
Defined *getThunkTargetSym() const { return Syms[0]; }
|
|
|
|
|
2017-02-01 18:26:03 +08:00
|
|
|
// The alignment requirement for this Thunk, defaults to the size of the
|
|
|
|
// typical code section alignment.
|
2017-11-04 05:21:47 +08:00
|
|
|
Symbol &Destination;
|
2018-03-30 06:32:13 +08:00
|
|
|
llvm::SmallVector<Defined *, 3> Syms;
|
2017-10-27 17:07:10 +08:00
|
|
|
uint64_t Offset = 0;
|
2017-07-18 19:59:19 +08:00
|
|
|
uint32_t Alignment = 4;
|
2016-07-09 00:10:27 +08:00
|
|
|
};
|
|
|
|
|
2017-02-01 18:26:03 +08:00
|
|
|
// For a Relocation to symbol S create a Thunk to be added to a synthetic
|
[PPC32] Improve the 32-bit PowerPC port
Many -static/-no-pie/-shared/-pie applications linked against glibc or musl
should work with this patch. This also helps FreeBSD PowerPC64 to migrate
their lib32 (PR40888).
* Fix default image base and max page size.
* Support new-style Secure PLT (see below). Old-style BSS PLT is not
implemented, so it is not suitable for FreeBSD rtld now because it doesn't
support Secure PLT yet.
* Support more initial relocation types:
R_PPC_ADDR32, R_PPC_REL16*, R_PPC_LOCAL24PC, R_PPC_PLTREL24, and R_PPC_GOT16.
The addend of R_PPC_PLTREL24 is special: it decides the call stub PLT type
but it should be ignored for the computation of target symbol VA.
* Support GNU ifunc
* Support .glink used for lazy PLT resolution in glibc
* Add a new thunk type: PPC32PltCallStub that is similar to PPC64PltCallStub.
It is used by R_PPC_REL24 and R_PPC_PLTREL24.
A PLT stub used in -fPIE/-fPIC usually loads an address relative to
.got2+0x8000 (-fpie/-fpic code uses _GLOBAL_OFFSET_TABLE_ relative
addresses).
Two .got2 sections in two object files have different addresses, thus a PLT stub
can't be shared by two object files. To handle this incompatibility,
change the parameters of Thunk::isCompatibleWith to
`const InputSection &, const Relocation &`.
PowerPC psABI specified an old-style .plt (BSS PLT) that is both
writable and executable. Linkers don't make separate RW- and RWE segments,
which causes all initially writable memory (think .data) executable.
This is a big security concern so a new PLT scheme (secure PLT) was developed to
address the security issue.
TLS will be implemented in D62940.
glibc older than ~2012 requires .rela.dyn to include .rela.plt, it can
not handle the DT_RELA+DT_RELASZ == DT_JMPREL case correctly. A hack
(not included in this patch) in LinkerScript.cpp addOrphanSections() to
work around the issue:
if (Config->EMachine == EM_PPC) {
// Older glibc assumes .rela.dyn includes .rela.plt
Add(In.RelaDyn);
if (In.RelaPlt->isLive() && !In.RelaPlt->Parent)
In.RelaDyn->getParent()->addSection(In.RelaPlt);
}
Reviewed By: ruiu
Differential Revision: https://reviews.llvm.org/D62464
llvm-svn: 362721
2019-06-07 01:03:00 +08:00
|
|
|
// ThunkSection.
|
|
|
|
Thunk *addThunk(const InputSection &IS, Relocation &Rel);
|
2016-07-09 00:10:27 +08:00
|
|
|
|
|
|
|
} // namespace elf
|
|
|
|
} // namespace lld
|
|
|
|
|
|
|
|
#endif
|