2015-09-23 02:19:46 +08:00
|
|
|
//===- Target.h -------------------------------------------------*- C++ -*-===//
|
|
|
|
//
|
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
|
2015-09-23 02:19:46 +08:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#ifndef LLD_ELF_TARGET_H
|
|
|
|
#define LLD_ELF_TARGET_H
|
|
|
|
|
2022-02-08 13:53:34 +08:00
|
|
|
#include "Config.h"
|
2016-04-13 09:40:19 +08:00
|
|
|
#include "InputSection.h"
|
[lld] unified COFF and ELF error handling on new Common/ErrorHandler
Summary:
The COFF linker and the ELF linker have long had similar but separate
Error.h and Error.cpp files to implement error handling. This change
introduces new error handling code in Common/ErrorHandler.h, changes the
COFF and ELF linkers to use it, and removes the old, separate
implementations.
Reviewers: ruiu
Reviewed By: ruiu
Subscribers: smeenai, jyknight, emaste, sdardis, nemanjai, nhaehnle, mgorny, javed.absar, kbarton, fedor.sergeev, llvm-commits
Differential Revision: https://reviews.llvm.org/D39259
llvm-svn: 316624
2017-10-26 06:28:38 +08:00
|
|
|
#include "lld/Common/ErrorHandler.h"
|
2015-11-06 15:43:03 +08:00
|
|
|
#include "llvm/Object/ELF.h"
|
2018-08-07 07:50:26 +08:00
|
|
|
#include "llvm/Support/MathExtras.h"
|
2018-11-15 05:05:20 +08:00
|
|
|
#include <array>
|
2015-09-29 13:34:03 +08:00
|
|
|
|
2015-09-23 02:19:46 +08:00
|
|
|
namespace lld {
|
2017-10-12 06:49:24 +08:00
|
|
|
std::string toString(elf::RelType type);
|
2017-06-17 01:32:43 +08:00
|
|
|
|
2016-02-28 08:25:54 +08:00
|
|
|
namespace elf {
|
2017-11-07 08:04:22 +08:00
|
|
|
class Defined;
|
2016-04-01 05:26:23 +08:00
|
|
|
class InputFile;
|
2017-11-04 05:21:47 +08:00
|
|
|
class Symbol;
|
2015-09-23 02:19:46 +08:00
|
|
|
|
|
|
|
class TargetInfo {
|
|
|
|
public:
|
2017-10-25 01:01:40 +08:00
|
|
|
virtual uint32_t calcEFlags() const { return 0; }
|
[ELF][ARM][AARCH64][MIPS][PPC] Simplify the logic to create R_*_RELATIVE for absolute relocation types in writable sections
Summary:
Our rule to create R_*_RELATIVE for absolute relocation types were
loose. D63121 made it stricter but it failed to create R_*_RELATIVE for
R_ARM_TARGET1 and R_PPC64_TOC. rLLD363236 worked around that by
reinstating the original behavior for ARM and PPC64.
This patch is an attempt to simplify the logic.
Note, in ld.bfd, R_ARM_TARGET2 --target2=abs also creates
R_ARM_RELATIVE. This seems a very uncommon scenario (moreover,
--target2=got-rel is the default), so I do not implement any logic
related to it.
Also, delete R_AARCH64_ABS32 from AArch64::getDynRel. We don't have
working ILP32 support yet. Allowing it would create an incorrect
R_AARCH64_RELATIVE.
For MIPS, the (if SymbolRel, then RelativeRel) code is to keep its
behavior unchanged.
Note, in ppc64-abs64-dyn.s, R_PPC64_TOC gets an incorrect addend because
computeAddend() doesn't compute the correct address. We seem to have the
wrong behavior for a long time. The important thing seems that a dynamic
relocation R_PPC64_TOC should not be created as the dynamic loader will
error R_PPC64_TOC is not supported.
Reviewers: atanasyan, grimar, peter.smith, ruiu, sfertile, espindola
Reviewed By: ruiu
Differential Revision: https://reviews.llvm.org/D63383
llvm-svn: 363928
2019-06-20 22:00:08 +08:00
|
|
|
virtual RelExpr getRelExpr(RelType type, const Symbol &s,
|
|
|
|
const uint8_t *loc) const = 0;
|
|
|
|
virtual RelType getDynRel(RelType type) const { return 0; }
|
2016-01-29 11:51:51 +08:00
|
|
|
virtual void writeGotPltHeader(uint8_t *buf) const {}
|
2018-03-20 01:40:14 +08:00
|
|
|
virtual void writeGotHeader(uint8_t *buf) const {}
|
2017-11-04 05:21:47 +08:00
|
|
|
virtual void writeGotPlt(uint8_t *buf, const Symbol &s) const {};
|
2020-01-10 03:59:28 +08:00
|
|
|
virtual void writeIgotPlt(uint8_t *buf, const Symbol &s) const {}
|
2017-10-12 06:49:24 +08:00
|
|
|
virtual int64_t getImplicitAddend(const uint8_t *buf, RelType type) const;
|
[PPC64] Set the number of relocations processed for R_PPC64_TLS[GL]D to 2
Summary:
R_PPC64_TLSGD and R_PPC64_TLSLD are used as markers on TLS code sequences. After GD-to-IE or GD-to-LE relaxation, the next relocation R_PPC64_REL24 should be skipped to not create a false dependency on __tls_get_addr. When linking statically, the false dependency may cause an "undefined symbol: __tls_get_addr" error.
R_PPC64_GOT_TLSGD16_HA
R_PPC64_GOT_TLSGD16_LO
R_PPC64_TLSGD R_TLSDESC_CALL
R_PPC64_REL24 __tls_get_addr
Reviewers: ruiu, sfertile, syzaara, espindola
Reviewed By: sfertile
Subscribers: emaste, nemanjai, arichardson, kbarton, jsji, llvm-commits, tamur
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D57673
llvm-svn: 353262
2019-02-06 10:00:24 +08:00
|
|
|
virtual int getTlsGdRelaxSkip(RelType type) const { return 1; }
|
2016-01-29 11:00:30 +08:00
|
|
|
|
|
|
|
// If lazy binding is supported, the first entry of the PLT has code
|
|
|
|
// to call the dynamic linker to resolve PLT entries the first time
|
|
|
|
// they are called. This function writes that code.
|
2016-06-17 00:28:50 +08:00
|
|
|
virtual void writePltHeader(uint8_t *buf) const {}
|
2016-01-29 11:00:30 +08:00
|
|
|
|
2019-12-18 05:43:04 +08:00
|
|
|
virtual void writePlt(uint8_t *buf, const Symbol &sym,
|
|
|
|
uint64_t pltEntryAddr) const {}
|
|
|
|
virtual void writeIplt(uint8_t *buf, const Symbol &sym,
|
|
|
|
uint64_t pltEntryAddr) const {
|
|
|
|
// All but PPC32 and PPC64 use the same format for .plt and .iplt entries.
|
|
|
|
writePlt(buf, sym, pltEntryAddr);
|
2019-12-15 06:17:35 +08:00
|
|
|
}
|
2019-12-11 10:05:36 +08:00
|
|
|
virtual void writeIBTPlt(uint8_t *buf, size_t numEntries) const {}
|
2017-12-20 07:59:35 +08:00
|
|
|
virtual void addPltHeaderSymbols(InputSection &isec) const {}
|
|
|
|
virtual void addPltSymbols(InputSection &isec, uint64_t off) const {}
|
2017-10-12 06:49:24 +08:00
|
|
|
|
2016-04-28 22:34:39 +08:00
|
|
|
// Returns true if a relocation only uses the low bits of a value such that
|
2018-04-27 13:50:40 +08:00
|
|
|
// all those bits are in the same page. For example, if the relocation
|
2016-04-28 22:34:39 +08:00
|
|
|
// only uses the low 12 bits in a system with 4k pages. If this is true, the
|
|
|
|
// bits will always have the same value at runtime and we don't have to emit
|
|
|
|
// a dynamic relocation.
|
2017-10-12 06:49:24 +08:00
|
|
|
virtual bool usesOnlyLowPageBits(RelType type) const;
|
2016-01-08 10:41:35 +08:00
|
|
|
|
2016-07-09 00:10:27 +08:00
|
|
|
// Decide whether a Thunk is needed for the relocation from File
|
2017-02-01 18:26:03 +08:00
|
|
|
// targeting S.
|
2017-10-27 17:04:11 +08:00
|
|
|
virtual bool needsThunk(RelExpr expr, RelType relocType,
|
|
|
|
const InputFile *file, uint64_t branchAddr,
|
2019-11-23 16:57:54 +08:00
|
|
|
const Symbol &s, int64_t a) const;
|
2018-07-18 07:16:02 +08:00
|
|
|
|
2018-08-20 17:37:50 +08:00
|
|
|
// On systems with range extensions we place collections of Thunks at
|
|
|
|
// regular spacings that enable the majority of branches reach the Thunks.
|
|
|
|
// a value of 0 means range extension thunks are not supported.
|
|
|
|
virtual uint32_t getThunkSectionSpacing() const { return 0; }
|
|
|
|
|
2018-07-18 07:16:02 +08:00
|
|
|
// The function with a prologue starting at Loc was compiled with
|
|
|
|
// -fsplit-stack and it calls a function compiled without. Adjust the prologue
|
|
|
|
// to do the right thing. See https://gcc.gnu.org/wiki/SplitStacks.
|
2018-10-17 01:13:01 +08:00
|
|
|
// The symbols st_other flags are needed on PowerPC64 for determining the
|
|
|
|
// offset to the split-stack prologue.
|
|
|
|
virtual bool adjustPrologueForCrossSplitStack(uint8_t *loc, uint8_t *end,
|
|
|
|
uint8_t stOther) const;
|
2018-07-18 07:16:02 +08:00
|
|
|
|
2019-07-16 13:50:45 +08:00
|
|
|
// Return true if we can reach dst from src with RelType type.
|
2017-10-27 17:04:11 +08:00
|
|
|
virtual bool inBranchRange(RelType type, uint64_t src,
|
|
|
|
uint64_t dst) const;
|
2017-10-12 06:49:24 +08:00
|
|
|
|
2020-01-23 13:39:16 +08:00
|
|
|
virtual void relocate(uint8_t *loc, const Relocation &rel,
|
|
|
|
uint64_t val) const = 0;
|
|
|
|
void relocateNoSym(uint8_t *loc, RelType type, uint64_t val) const {
|
|
|
|
relocate(loc, Relocation{R_NONE, type, 0, 0, nullptr}, val);
|
|
|
|
}
|
2017-10-12 06:49:24 +08:00
|
|
|
|
2022-07-08 01:16:09 +08:00
|
|
|
// Do a linker relaxation pass and return true if we changed something.
|
|
|
|
virtual bool relaxOnce(int pass) const { return false; }
|
|
|
|
|
2020-04-07 21:48:18 +08:00
|
|
|
virtual void applyJumpInstrMod(uint8_t *loc, JumpModType type,
|
|
|
|
JumpModType val) const {}
|
|
|
|
|
2015-09-23 02:19:46 +08:00
|
|
|
virtual ~TargetInfo();
|
|
|
|
|
2020-04-07 21:48:18 +08:00
|
|
|
// This deletes a jump insn at the end of the section if it is a fall thru to
|
|
|
|
// the next section. Further, if there is a conditional jump and a direct
|
|
|
|
// jump consecutively, it tries to flip the conditional jump to convert the
|
|
|
|
// direct jump into a fall thru and delete it. Returns true if a jump
|
|
|
|
// instruction can be deleted.
|
|
|
|
virtual bool deleteFallThruJmpInsn(InputSection &is, InputFile *file,
|
|
|
|
InputSection *nextIS) const {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2019-05-14 00:01:26 +08:00
|
|
|
unsigned defaultCommonPageSize = 4096;
|
2016-12-08 05:13:27 +08:00
|
|
|
unsigned defaultMaxPageSize = 4096;
|
2015-10-15 15:49:07 +08:00
|
|
|
|
2019-03-29 01:05:09 +08:00
|
|
|
uint64_t getImageBase() const;
|
2015-10-15 15:49:07 +08:00
|
|
|
|
2018-03-19 14:52:51 +08:00
|
|
|
// True if _GLOBAL_OFFSET_TABLE_ is relative to .got.plt, false if .got.
|
2021-09-26 06:06:09 +08:00
|
|
|
bool gotBaseSymInGotPlt = false;
|
[Coding style change] Rename variables so that they start with a lowercase letter
This patch is mechanically generated by clang-llvm-rename tool that I wrote
using Clang Refactoring Engine just for creating this patch. You can see the
source code of the tool at https://reviews.llvm.org/D64123. There's no manual
post-processing; you can generate the same patch by re-running the tool against
lld's code base.
Here is the main discussion thread to change the LLVM coding style:
https://lists.llvm.org/pipermail/llvm-dev/2019-February/130083.html
In the discussion thread, I proposed we use lld as a testbed for variable
naming scheme change, and this patch does that.
I chose to rename variables so that they are in camelCase, just because that
is a minimal change to make variables to start with a lowercase letter.
Note to downstream patch maintainers: if you are maintaining a downstream lld
repo, just rebasing ahead of this commit would cause massive merge conflicts
because this patch essentially changes every line in the lld subdirectory. But
there's a remedy.
clang-llvm-rename tool is a batch tool, so you can rename variables in your
downstream repo with the tool. Given that, here is how to rebase your repo to
a commit after the mass renaming:
1. rebase to the commit just before the mass variable renaming,
2. apply the tool to your downstream repo to mass-rename variables locally, and
3. rebase again to the head.
Most changes made by the tool should be identical for a downstream repo and
for the head, so at the step 3, almost all changes should be merged and
disappear. I'd expect that there would be some lines that you need to merge by
hand, but that shouldn't be too many.
Differential Revision: https://reviews.llvm.org/D64121
llvm-svn: 365595
2019-07-10 13:00:37 +08:00
|
|
|
|
2021-09-26 06:16:44 +08:00
|
|
|
static constexpr RelType noneRel = 0;
|
2017-10-12 06:49:24 +08:00
|
|
|
RelType copyRel;
|
|
|
|
RelType gotRel;
|
|
|
|
RelType pltRel;
|
|
|
|
RelType relativeRel;
|
|
|
|
RelType iRelativeRel;
|
2019-06-11 20:59:30 +08:00
|
|
|
RelType symbolicRel;
|
2017-10-12 06:49:24 +08:00
|
|
|
RelType tlsDescRel;
|
|
|
|
RelType tlsGotRel;
|
|
|
|
RelType tlsModuleIndexRel;
|
|
|
|
RelType tlsOffsetRel;
|
2021-05-17 07:13:00 +08:00
|
|
|
unsigned gotEntrySize = config->wordsize;
|
2016-06-17 07:50:25 +08:00
|
|
|
unsigned pltEntrySize;
|
|
|
|
unsigned pltHeaderSize;
|
2019-12-15 06:17:35 +08:00
|
|
|
unsigned ipltEntrySize;
|
2016-05-10 02:12:15 +08:00
|
|
|
|
|
|
|
// At least on x86_64 positions 1 and 2 are used by the first plt entry
|
|
|
|
// to support lazy loading.
|
2015-11-17 01:44:08 +08:00
|
|
|
unsigned gotPltHeaderEntriesNum = 3;
|
2016-05-10 02:12:15 +08:00
|
|
|
|
2018-03-20 01:40:14 +08:00
|
|
|
// On PPC ELF V2 abi, the first entry in the .got is the .TOC.
|
|
|
|
unsigned gotHeaderEntriesNum = 0;
|
|
|
|
|
2016-07-21 01:58:07 +08:00
|
|
|
bool needsThunks = false;
|
|
|
|
|
2017-04-07 18:36:42 +08:00
|
|
|
// A 4-byte field corresponding to one or more trap instructions, used to pad
|
|
|
|
// executable OutputSections.
|
2018-11-15 16:20:18 +08:00
|
|
|
std::array<uint8_t, 4> trapInstr;
|
2017-04-07 18:36:42 +08:00
|
|
|
|
2020-04-07 21:48:18 +08:00
|
|
|
// Stores the NOP instructions of different sizes for the target and is used
|
|
|
|
// to pad sections that are relaxed.
|
|
|
|
llvm::Optional<std::vector<std::vector<uint8_t>>> nopInstrs;
|
|
|
|
|
2018-10-17 01:13:01 +08:00
|
|
|
// If a target needs to rewrite calls to __morestack to instead call
|
|
|
|
// __morestack_non_split when a split-stack enabled caller calls a
|
|
|
|
// non-split-stack callee this will return true. Otherwise returns false.
|
|
|
|
bool needsMoreStackNonSplit = true;
|
|
|
|
|
2020-11-26 01:00:55 +08:00
|
|
|
virtual RelExpr adjustTlsExpr(RelType type, RelExpr expr) const;
|
2020-11-26 00:43:26 +08:00
|
|
|
virtual RelExpr adjustGotPcExpr(RelType type, int64_t addend,
|
|
|
|
const uint8_t *loc) const;
|
2020-01-23 11:42:54 +08:00
|
|
|
virtual void relaxGot(uint8_t *loc, const Relocation &rel,
|
|
|
|
uint64_t val) const;
|
|
|
|
virtual void relaxTlsGdToIe(uint8_t *loc, const Relocation &rel,
|
|
|
|
uint64_t val) const;
|
|
|
|
virtual void relaxTlsGdToLe(uint8_t *loc, const Relocation &rel,
|
|
|
|
uint64_t val) const;
|
|
|
|
virtual void relaxTlsIeToLe(uint8_t *loc, const Relocation &rel,
|
|
|
|
uint64_t val) const;
|
|
|
|
virtual void relaxTlsLdToLe(uint8_t *loc, const Relocation &rel,
|
|
|
|
uint64_t val) const;
|
2017-10-10 18:09:35 +08:00
|
|
|
|
|
|
|
protected:
|
|
|
|
// On FreeBSD x86_64 the first page cannot be mmaped.
|
2019-10-31 10:17:52 +08:00
|
|
|
// On Linux this is controlled by vm.mmap_min_addr. At least on some x86_64
|
|
|
|
// installs this is set to 65536, so the first 15 pages cannot be used.
|
2017-10-10 18:09:35 +08:00
|
|
|
// Given that, the smallest value that can be used in here is 0x10000.
|
|
|
|
uint64_t defaultImageBase = 0x10000;
|
2015-09-23 02:19:46 +08:00
|
|
|
};
|
|
|
|
|
2017-06-17 04:15:03 +08:00
|
|
|
TargetInfo *getAArch64TargetInfo();
|
|
|
|
TargetInfo *getAMDGPUTargetInfo();
|
|
|
|
TargetInfo *getARMTargetInfo();
|
|
|
|
TargetInfo *getAVRTargetInfo();
|
2018-06-14 02:45:25 +08:00
|
|
|
TargetInfo *getHexagonTargetInfo();
|
2019-01-10 21:43:06 +08:00
|
|
|
TargetInfo *getMSP430TargetInfo();
|
2017-06-17 04:15:03 +08:00
|
|
|
TargetInfo *getPPC64TargetInfo();
|
|
|
|
TargetInfo *getPPCTargetInfo();
|
2018-08-10 01:59:56 +08:00
|
|
|
TargetInfo *getRISCVTargetInfo();
|
2017-06-29 01:05:39 +08:00
|
|
|
TargetInfo *getSPARCV9TargetInfo();
|
2017-06-17 04:15:03 +08:00
|
|
|
TargetInfo *getX86TargetInfo();
|
|
|
|
TargetInfo *getX86_64TargetInfo();
|
|
|
|
template <class ELFT> TargetInfo *getMipsTargetInfo();
|
2017-06-17 01:32:43 +08:00
|
|
|
|
2018-03-21 17:19:34 +08:00
|
|
|
struct ErrorPlace {
|
|
|
|
InputSectionBase *isec;
|
|
|
|
std::string loc;
|
2021-10-29 00:38:45 +08:00
|
|
|
std::string srcLoc;
|
2018-03-21 17:19:34 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
// Returns input section and corresponding source string for the given location.
|
|
|
|
ErrorPlace getErrorPlace(const uint8_t *loc);
|
|
|
|
|
|
|
|
static inline std::string getErrorLocation(const uint8_t *loc) {
|
|
|
|
return getErrorPlace(loc).loc;
|
|
|
|
}
|
2017-06-17 01:32:43 +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
|
|
|
void writePPC32GlinkSection(uint8_t *buf, size_t numEntries);
|
|
|
|
|
2020-01-23 11:42:54 +08:00
|
|
|
bool tryRelaxPPC64TocIndirection(const Relocation &rel, uint8_t *bufLoc);
|
2019-06-07 01:03:10 +08:00
|
|
|
unsigned getPPCDFormOp(unsigned secondaryOp);
|
[PPC64] toc-indirect to toc-relative relaxation
This is based on D54720 by Sean Fertile.
When accessing a global symbol which is not defined in the translation unit,
compilers will generate instructions that load the address from the toc entry.
If the symbol is defined, non-preemptable, and addressable with a 32-bit
signed offset from the toc pointer, the address can be computed
directly. e.g.
addis 3, 2, .LC0@toc@ha # R_PPC64_TOC16_HA
ld 3, .LC0@toc@l(3) # R_PPC64_TOC16_LO_DS, load the address from a .toc entry
ld/lwa 3, 0(3) # load the value from the address
.section .toc,"aw",@progbits
.LC0: .tc var[TC],var
can be relaxed to
addis 3,2,var@toc@ha # this may be relaxed to a nop,
addi 3,3,var@toc@l # then this becomes addi 3,2,var@toc
ld/lwa 3, 0(3) # load the value from the address
We can delete the test ppc64-got-indirect.s as its purpose is covered by
newly added ppc64-toc-relax.s and ppc64-toc-relax-constants.s
Reviewed By: ruiu, sfertile
Differential Revision: https://reviews.llvm.org/D60958
llvm-svn: 360112
2019-05-07 12:26:05 +08:00
|
|
|
|
|
|
|
// In the PowerPC64 Elf V2 abi a function can have 2 entry points. The first
|
|
|
|
// is a global entry point (GEP) which typically is used to initialize the TOC
|
2018-09-20 08:26:47 +08:00
|
|
|
// pointer in general purpose register 2. The second is a local entry
|
|
|
|
// point (LEP) which bypasses the TOC pointer initialization code. The
|
|
|
|
// offset between GEP and LEP is encoded in a function's st_other flags.
|
|
|
|
// This function will return the offset (in bytes) from the global entry-point
|
|
|
|
// to the local entry-point.
|
|
|
|
unsigned getPPC64GlobalEntryToLocalEntryOffset(uint8_t stOther);
|
|
|
|
|
2020-07-21 01:40:41 +08:00
|
|
|
// Write a prefixed instruction, which is a 4-byte prefix followed by a 4-byte
|
|
|
|
// instruction (regardless of endianness). Therefore, the prefix is always in
|
|
|
|
// lower memory than the instruction.
|
|
|
|
void writePrefixedInstruction(uint8_t *loc, uint64_t insn);
|
|
|
|
|
2020-05-15 04:55:20 +08:00
|
|
|
void addPPC64SaveRestore();
|
2015-10-17 05:55:40 +08:00
|
|
|
uint64_t getPPC64TocBase();
|
2016-12-05 22:14:26 +08:00
|
|
|
uint64_t getAArch64Page(uint64_t expr);
|
2022-07-08 01:16:09 +08:00
|
|
|
void riscvFinalizeRelax(int passes);
|
2015-10-17 05:55:40 +08:00
|
|
|
|
2022-01-10 13:20:37 +08:00
|
|
|
class AArch64Relaxer {
|
|
|
|
bool safeToRelaxAdrpLdr = true;
|
|
|
|
|
|
|
|
public:
|
|
|
|
explicit AArch64Relaxer(ArrayRef<Relocation> relocs);
|
|
|
|
|
2022-02-02 14:08:05 +08:00
|
|
|
bool tryRelaxAdrpAdd(const Relocation &adrpRel, const Relocation &addRel,
|
|
|
|
uint64_t secAddr, uint8_t *buf) const;
|
2022-01-10 13:20:37 +08:00
|
|
|
bool tryRelaxAdrpLdr(const Relocation &adrpRel, const Relocation &ldrRel,
|
|
|
|
uint64_t secAddr, uint8_t *buf) const;
|
|
|
|
};
|
|
|
|
|
2019-03-29 01:05:09 +08:00
|
|
|
extern const TargetInfo *target;
|
2017-06-17 04:15:03 +08:00
|
|
|
TargetInfo *getTarget();
|
2017-06-17 01:32:43 +08:00
|
|
|
|
2017-11-07 08:04:22 +08:00
|
|
|
template <class ELFT> bool isMipsPIC(const Defined *sym);
|
|
|
|
|
2020-01-28 09:35:06 +08:00
|
|
|
void reportRangeError(uint8_t *loc, const Relocation &rel, const Twine &v,
|
|
|
|
int64_t min, uint64_t max);
|
2020-09-12 00:31:37 +08:00
|
|
|
void reportRangeError(uint8_t *loc, int64_t v, int n, const Symbol &sym,
|
|
|
|
const Twine &msg);
|
2017-12-12 04:47:21 +08:00
|
|
|
|
2018-03-30 06:40:52 +08:00
|
|
|
// Make sure that V can be represented as an N bit signed integer.
|
2020-01-23 13:39:16 +08:00
|
|
|
inline void checkInt(uint8_t *loc, int64_t v, int n, const Relocation &rel) {
|
2018-08-07 07:50:26 +08:00
|
|
|
if (v != llvm::SignExtend64(v, n))
|
2020-01-23 13:39:16 +08:00
|
|
|
reportRangeError(loc, rel, Twine(v), llvm::minIntN(n), llvm::maxIntN(n));
|
2015-09-23 02:19:46 +08:00
|
|
|
}
|
2017-01-06 18:04:08 +08:00
|
|
|
|
2018-03-30 06:40:52 +08:00
|
|
|
// Make sure that V can be represented as an N bit unsigned integer.
|
2020-01-23 13:39:16 +08:00
|
|
|
inline void checkUInt(uint8_t *loc, uint64_t v, int n, const Relocation &rel) {
|
2018-03-30 06:40:52 +08:00
|
|
|
if ((v >> n) != 0)
|
2020-01-23 13:39:16 +08:00
|
|
|
reportRangeError(loc, rel, Twine(v), 0, llvm::maxUIntN(n));
|
2017-06-17 01:32:43 +08:00
|
|
|
}
|
|
|
|
|
2018-03-30 06:40:52 +08:00
|
|
|
// Make sure that V can be represented as an N bit signed or unsigned integer.
|
2020-01-23 13:39:16 +08:00
|
|
|
inline void checkIntUInt(uint8_t *loc, uint64_t v, int n,
|
|
|
|
const Relocation &rel) {
|
2018-03-30 06:40:52 +08:00
|
|
|
// For the error message we should cast V to a signed integer so that error
|
|
|
|
// messages show a small negative value rather than an extremely large one
|
2018-08-07 07:50:26 +08:00
|
|
|
if (v != (uint64_t)llvm::SignExtend64(v, n) && (v >> n) != 0)
|
2020-01-23 13:39:16 +08:00
|
|
|
reportRangeError(loc, rel, Twine((int64_t)v), llvm::minIntN(n),
|
[ELF][PPC][X86] Use [-2**(n-1), 2**n) to check overflows for R_PPC_ADDR16, R_PPC64_ADDR{16,32}, R_X86_64_{8,16}
Similar to R_AARCH64_ABS32, R_PPC64_ADDR32 can represent either a signed
value or unsigned value, thus we should use `[-2**(n-1), 2**n)` instead of
`[-2**(n-1), 2**(n-1))` to check overflows.
The issue manifests as a bogus linker error when linking the powerpc64le Linux kernel.
The new behavior is compatible with ld.bfd's complain_overflow_bitfield.
The upper bound of the error message is not correct. Fix it as well.
The changes to R_PPC_ADDR16, R_PPC64_ADDR16, R_X86_64_8 and R_X86_64_16 are similar.
Reviewed By: ruiu
Differential Revision: https://reviews.llvm.org/D63690
llvm-svn: 364164
2019-06-24 13:37:20 +08:00
|
|
|
llvm::maxUIntN(n));
|
2017-06-17 01:32:43 +08:00
|
|
|
}
|
|
|
|
|
2020-01-23 13:39:16 +08:00
|
|
|
inline void checkAlignment(uint8_t *loc, uint64_t v, int n,
|
|
|
|
const Relocation &rel) {
|
2017-06-17 01:32:43 +08:00
|
|
|
if ((v & (n - 1)) != 0)
|
|
|
|
error(getErrorLocation(loc) + "improper alignment for relocation " +
|
2020-01-23 13:39:16 +08:00
|
|
|
lld::toString(rel.type) + ": 0x" + llvm::utohexstr(v) +
|
2017-12-08 22:53:14 +08:00
|
|
|
" is not aligned to " + Twine(n) + " bytes");
|
2017-06-17 01:32:43 +08:00
|
|
|
}
|
2018-03-10 02:03:22 +08:00
|
|
|
|
|
|
|
// Endianness-aware read/write.
|
|
|
|
inline uint16_t read16(const void *p) {
|
|
|
|
return llvm::support::endian::read16(p, config->endianness);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline uint32_t read32(const void *p) {
|
|
|
|
return llvm::support::endian::read32(p, config->endianness);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline uint64_t read64(const void *p) {
|
|
|
|
return llvm::support::endian::read64(p, config->endianness);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void write16(void *p, uint16_t v) {
|
|
|
|
llvm::support::endian::write16(p, v, config->endianness);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void write32(void *p, uint32_t v) {
|
|
|
|
llvm::support::endian::write32(p, v, config->endianness);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void write64(void *p, uint64_t v) {
|
|
|
|
llvm::support::endian::write64(p, v, config->endianness);
|
|
|
|
}
|
2017-06-17 01:32:43 +08:00
|
|
|
} // namespace elf
|
2017-07-18 19:55:35 +08:00
|
|
|
} // namespace lld
|
2015-09-23 02:19:46 +08:00
|
|
|
|
2022-02-02 01:47:56 +08:00
|
|
|
#ifdef __clang__
|
|
|
|
#pragma clang diagnostic ignored "-Wgnu-zero-variadic-macro-arguments"
|
|
|
|
#endif
|
|
|
|
#define invokeELFT(f, ...) \
|
|
|
|
switch (config->ekind) { \
|
|
|
|
case ELF32LEKind: \
|
|
|
|
f<ELF32LE>(__VA_ARGS__); \
|
|
|
|
break; \
|
|
|
|
case ELF32BEKind: \
|
|
|
|
f<ELF32BE>(__VA_ARGS__); \
|
|
|
|
break; \
|
|
|
|
case ELF64LEKind: \
|
|
|
|
f<ELF64LE>(__VA_ARGS__); \
|
|
|
|
break; \
|
|
|
|
case ELF64BEKind: \
|
|
|
|
f<ELF64BE>(__VA_ARGS__); \
|
|
|
|
break; \
|
|
|
|
default: \
|
|
|
|
llvm_unreachable("unknown config->ekind"); \
|
|
|
|
}
|
|
|
|
|
2015-09-23 02:19:46 +08:00
|
|
|
#endif
|