1ece8a530Spatrick //===- X86_64.cpp ---------------------------------------------------------===//
2ece8a530Spatrick //
3ece8a530Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4ece8a530Spatrick // See https://llvm.org/LICENSE.txt for license information.
5ece8a530Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6ece8a530Spatrick //
7ece8a530Spatrick //===----------------------------------------------------------------------===//
8ece8a530Spatrick
9bb684c34Spatrick #include "OutputSections.h"
10ece8a530Spatrick #include "Symbols.h"
11ece8a530Spatrick #include "SyntheticSections.h"
12ece8a530Spatrick #include "Target.h"
13ece8a530Spatrick #include "lld/Common/ErrorHandler.h"
1405edf1c1Srobert #include "llvm/BinaryFormat/ELF.h"
15ece8a530Spatrick #include "llvm/Support/Endian.h"
16ece8a530Spatrick
17ece8a530Spatrick using namespace llvm;
18ece8a530Spatrick using namespace llvm::object;
19ece8a530Spatrick using namespace llvm::support::endian;
20ece8a530Spatrick using namespace llvm::ELF;
21bb684c34Spatrick using namespace lld;
22bb684c34Spatrick using namespace lld::elf;
23ece8a530Spatrick
24ece8a530Spatrick namespace {
25ece8a530Spatrick class X86_64 : public TargetInfo {
26ece8a530Spatrick public:
27ece8a530Spatrick X86_64();
28ece8a530Spatrick int getTlsGdRelaxSkip(RelType type) const override;
29ece8a530Spatrick RelExpr getRelExpr(RelType type, const Symbol &s,
30ece8a530Spatrick const uint8_t *loc) const override;
31ece8a530Spatrick RelType getDynRel(RelType type) const override;
32ece8a530Spatrick void writeGotPltHeader(uint8_t *buf) const override;
33ece8a530Spatrick void writeGotPlt(uint8_t *buf, const Symbol &s) const override;
341cf9926bSpatrick void writeIgotPlt(uint8_t *buf, const Symbol &s) const override;
35ece8a530Spatrick void writePltHeader(uint8_t *buf) const override;
36ece8a530Spatrick void writePlt(uint8_t *buf, const Symbol &sym,
37ece8a530Spatrick uint64_t pltEntryAddr) const override;
38bb684c34Spatrick void relocate(uint8_t *loc, const Relocation &rel,
39bb684c34Spatrick uint64_t val) const override;
401cf9926bSpatrick int64_t getImplicitAddend(const uint8_t *buf, RelType type) const override;
41bb684c34Spatrick void applyJumpInstrMod(uint8_t *loc, JumpModType type,
42bb684c34Spatrick unsigned size) const override;
431cf9926bSpatrick RelExpr adjustGotPcExpr(RelType type, int64_t addend,
441cf9926bSpatrick const uint8_t *loc) const override;
4505edf1c1Srobert void relocateAlloc(InputSectionBase &sec, uint8_t *buf) const override;
46ece8a530Spatrick bool adjustPrologueForCrossSplitStack(uint8_t *loc, uint8_t *end,
47ece8a530Spatrick uint8_t stOther) const override;
48bb684c34Spatrick bool deleteFallThruJmpInsn(InputSection &is, InputFile *file,
49bb684c34Spatrick InputSection *nextIS) const override;
50ece8a530Spatrick };
51ece8a530Spatrick } // namespace
52ece8a530Spatrick
53bb684c34Spatrick // This is vector of NOP instructions of sizes from 1 to 8 bytes. The
54bb684c34Spatrick // appropriately sized instructions are used to fill the gaps between sections
55bb684c34Spatrick // which are executed during fall through.
56bb684c34Spatrick static const std::vector<std::vector<uint8_t>> nopInstructions = {
57bb684c34Spatrick {0x90},
58bb684c34Spatrick {0x66, 0x90},
59bb684c34Spatrick {0x0f, 0x1f, 0x00},
60bb684c34Spatrick {0x0f, 0x1f, 0x40, 0x00},
61bb684c34Spatrick {0x0f, 0x1f, 0x44, 0x00, 0x00},
62bb684c34Spatrick {0x66, 0x0f, 0x1f, 0x44, 0x00, 0x00},
63bb684c34Spatrick {0x0F, 0x1F, 0x80, 0x00, 0x00, 0x00, 0x00},
64bb684c34Spatrick {0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00},
65bb684c34Spatrick {0x66, 0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00}};
66bb684c34Spatrick
X86_64()67ece8a530Spatrick X86_64::X86_64() {
68ece8a530Spatrick copyRel = R_X86_64_COPY;
69ece8a530Spatrick gotRel = R_X86_64_GLOB_DAT;
70ece8a530Spatrick pltRel = R_X86_64_JUMP_SLOT;
71ece8a530Spatrick relativeRel = R_X86_64_RELATIVE;
72ece8a530Spatrick iRelativeRel = R_X86_64_IRELATIVE;
73ece8a530Spatrick symbolicRel = R_X86_64_64;
74ece8a530Spatrick tlsDescRel = R_X86_64_TLSDESC;
75ece8a530Spatrick tlsGotRel = R_X86_64_TPOFF64;
76ece8a530Spatrick tlsModuleIndexRel = R_X86_64_DTPMOD64;
77ece8a530Spatrick tlsOffsetRel = R_X86_64_DTPOFF64;
7805edf1c1Srobert gotBaseSymInGotPlt = true;
791cf9926bSpatrick gotEntrySize = 8;
80ece8a530Spatrick pltHeaderSize = 16;
81ece8a530Spatrick pltEntrySize = 16;
82ece8a530Spatrick ipltEntrySize = 16;
83ece8a530Spatrick trapInstr = {0xcc, 0xcc, 0xcc, 0xcc}; // 0xcc = INT3
84bb684c34Spatrick nopInstrs = nopInstructions;
85ece8a530Spatrick
86ece8a530Spatrick // Align to the large page size (known as a superpage or huge page).
87ece8a530Spatrick // FreeBSD automatically promotes large, superpage-aligned allocations.
88ece8a530Spatrick defaultImageBase = 0x200000;
89ece8a530Spatrick }
90ece8a530Spatrick
getTlsGdRelaxSkip(RelType type) const9105edf1c1Srobert int X86_64::getTlsGdRelaxSkip(RelType type) const {
9205edf1c1Srobert // TLSDESC relocations are processed separately. See relaxTlsGdToLe below.
9305edf1c1Srobert return type == R_X86_64_GOTPC32_TLSDESC || type == R_X86_64_TLSDESC_CALL ? 1
9405edf1c1Srobert : 2;
9505edf1c1Srobert }
96ece8a530Spatrick
97bb684c34Spatrick // Opcodes for the different X86_64 jmp instructions.
98bb684c34Spatrick enum JmpInsnOpcode : uint32_t {
99bb684c34Spatrick J_JMP_32,
100bb684c34Spatrick J_JNE_32,
101bb684c34Spatrick J_JE_32,
102bb684c34Spatrick J_JG_32,
103bb684c34Spatrick J_JGE_32,
104bb684c34Spatrick J_JB_32,
105bb684c34Spatrick J_JBE_32,
106bb684c34Spatrick J_JL_32,
107bb684c34Spatrick J_JLE_32,
108bb684c34Spatrick J_JA_32,
109bb684c34Spatrick J_JAE_32,
110bb684c34Spatrick J_UNKNOWN,
111bb684c34Spatrick };
112bb684c34Spatrick
113bb684c34Spatrick // Given the first (optional) and second byte of the insn's opcode, this
114bb684c34Spatrick // returns the corresponding enum value.
getJmpInsnType(const uint8_t * first,const uint8_t * second)115bb684c34Spatrick static JmpInsnOpcode getJmpInsnType(const uint8_t *first,
116bb684c34Spatrick const uint8_t *second) {
117bb684c34Spatrick if (*second == 0xe9)
118bb684c34Spatrick return J_JMP_32;
119bb684c34Spatrick
120bb684c34Spatrick if (first == nullptr)
121bb684c34Spatrick return J_UNKNOWN;
122bb684c34Spatrick
123bb684c34Spatrick if (*first == 0x0f) {
124bb684c34Spatrick switch (*second) {
125bb684c34Spatrick case 0x84:
126bb684c34Spatrick return J_JE_32;
127bb684c34Spatrick case 0x85:
128bb684c34Spatrick return J_JNE_32;
129bb684c34Spatrick case 0x8f:
130bb684c34Spatrick return J_JG_32;
131bb684c34Spatrick case 0x8d:
132bb684c34Spatrick return J_JGE_32;
133bb684c34Spatrick case 0x82:
134bb684c34Spatrick return J_JB_32;
135bb684c34Spatrick case 0x86:
136bb684c34Spatrick return J_JBE_32;
137bb684c34Spatrick case 0x8c:
138bb684c34Spatrick return J_JL_32;
139bb684c34Spatrick case 0x8e:
140bb684c34Spatrick return J_JLE_32;
141bb684c34Spatrick case 0x87:
142bb684c34Spatrick return J_JA_32;
143bb684c34Spatrick case 0x83:
144bb684c34Spatrick return J_JAE_32;
145bb684c34Spatrick }
146bb684c34Spatrick }
147bb684c34Spatrick return J_UNKNOWN;
148bb684c34Spatrick }
149bb684c34Spatrick
150bb684c34Spatrick // Return the relocation index for input section IS with a specific Offset.
151bb684c34Spatrick // Returns the maximum size of the vector if no such relocation is found.
getRelocationWithOffset(const InputSection & is,uint64_t offset)152bb684c34Spatrick static unsigned getRelocationWithOffset(const InputSection &is,
153bb684c34Spatrick uint64_t offset) {
15405edf1c1Srobert unsigned size = is.relocs().size();
155bb684c34Spatrick for (unsigned i = size - 1; i + 1 > 0; --i) {
15605edf1c1Srobert if (is.relocs()[i].offset == offset && is.relocs()[i].expr != R_NONE)
157bb684c34Spatrick return i;
158bb684c34Spatrick }
159bb684c34Spatrick return size;
160bb684c34Spatrick }
161bb684c34Spatrick
162bb684c34Spatrick // Returns true if R corresponds to a relocation used for a jump instruction.
163bb684c34Spatrick // TODO: Once special relocations for relaxable jump instructions are available,
164bb684c34Spatrick // this should be modified to use those relocations.
isRelocationForJmpInsn(Relocation & R)165bb684c34Spatrick static bool isRelocationForJmpInsn(Relocation &R) {
166bb684c34Spatrick return R.type == R_X86_64_PLT32 || R.type == R_X86_64_PC32 ||
167bb684c34Spatrick R.type == R_X86_64_PC8;
168bb684c34Spatrick }
169bb684c34Spatrick
170bb684c34Spatrick // Return true if Relocation R points to the first instruction in the
171bb684c34Spatrick // next section.
172bb684c34Spatrick // TODO: Delete this once psABI reserves a new relocation type for fall thru
173bb684c34Spatrick // jumps.
isFallThruRelocation(InputSection & is,InputFile * file,InputSection * nextIS,Relocation & r)174bb684c34Spatrick static bool isFallThruRelocation(InputSection &is, InputFile *file,
175bb684c34Spatrick InputSection *nextIS, Relocation &r) {
176bb684c34Spatrick if (!isRelocationForJmpInsn(r))
177bb684c34Spatrick return false;
178bb684c34Spatrick
179bb684c34Spatrick uint64_t addrLoc = is.getOutputSection()->addr + is.outSecOff + r.offset;
180bb684c34Spatrick uint64_t targetOffset = InputSectionBase::getRelocTargetVA(
181bb684c34Spatrick file, r.type, r.addend, addrLoc, *r.sym, r.expr);
182bb684c34Spatrick
183bb684c34Spatrick // If this jmp is a fall thru, the target offset is the beginning of the
184bb684c34Spatrick // next section.
185bb684c34Spatrick uint64_t nextSectionOffset =
186bb684c34Spatrick nextIS->getOutputSection()->addr + nextIS->outSecOff;
187bb684c34Spatrick return (addrLoc + 4 + targetOffset) == nextSectionOffset;
188bb684c34Spatrick }
189bb684c34Spatrick
190bb684c34Spatrick // Return the jmp instruction opcode that is the inverse of the given
191bb684c34Spatrick // opcode. For example, JE inverted is JNE.
invertJmpOpcode(const JmpInsnOpcode opcode)192bb684c34Spatrick static JmpInsnOpcode invertJmpOpcode(const JmpInsnOpcode opcode) {
193bb684c34Spatrick switch (opcode) {
194bb684c34Spatrick case J_JE_32:
195bb684c34Spatrick return J_JNE_32;
196bb684c34Spatrick case J_JNE_32:
197bb684c34Spatrick return J_JE_32;
198bb684c34Spatrick case J_JG_32:
199bb684c34Spatrick return J_JLE_32;
200bb684c34Spatrick case J_JGE_32:
201bb684c34Spatrick return J_JL_32;
202bb684c34Spatrick case J_JB_32:
203bb684c34Spatrick return J_JAE_32;
204bb684c34Spatrick case J_JBE_32:
205bb684c34Spatrick return J_JA_32;
206bb684c34Spatrick case J_JL_32:
207bb684c34Spatrick return J_JGE_32;
208bb684c34Spatrick case J_JLE_32:
209bb684c34Spatrick return J_JG_32;
210bb684c34Spatrick case J_JA_32:
211bb684c34Spatrick return J_JBE_32;
212bb684c34Spatrick case J_JAE_32:
213bb684c34Spatrick return J_JB_32;
214bb684c34Spatrick default:
215bb684c34Spatrick return J_UNKNOWN;
216bb684c34Spatrick }
217bb684c34Spatrick }
218bb684c34Spatrick
219bb684c34Spatrick // Deletes direct jump instruction in input sections that jumps to the
220bb684c34Spatrick // following section as it is not required. If there are two consecutive jump
221bb684c34Spatrick // instructions, it checks if they can be flipped and one can be deleted.
222bb684c34Spatrick // For example:
223bb684c34Spatrick // .section .text
224bb684c34Spatrick // a.BB.foo:
225bb684c34Spatrick // ...
226bb684c34Spatrick // 10: jne aa.BB.foo
227bb684c34Spatrick // 16: jmp bar
228bb684c34Spatrick // aa.BB.foo:
229bb684c34Spatrick // ...
230bb684c34Spatrick //
231bb684c34Spatrick // can be converted to:
232bb684c34Spatrick // a.BB.foo:
233bb684c34Spatrick // ...
234bb684c34Spatrick // 10: je bar #jne flipped to je and the jmp is deleted.
235bb684c34Spatrick // aa.BB.foo:
236bb684c34Spatrick // ...
deleteFallThruJmpInsn(InputSection & is,InputFile * file,InputSection * nextIS) const237bb684c34Spatrick bool X86_64::deleteFallThruJmpInsn(InputSection &is, InputFile *file,
238bb684c34Spatrick InputSection *nextIS) const {
239bb684c34Spatrick const unsigned sizeOfDirectJmpInsn = 5;
240bb684c34Spatrick
241bb684c34Spatrick if (nextIS == nullptr)
242bb684c34Spatrick return false;
243bb684c34Spatrick
244bb684c34Spatrick if (is.getSize() < sizeOfDirectJmpInsn)
245bb684c34Spatrick return false;
246bb684c34Spatrick
247bb684c34Spatrick // If this jmp insn can be removed, it is the last insn and the
248bb684c34Spatrick // relocation is 4 bytes before the end.
249bb684c34Spatrick unsigned rIndex = getRelocationWithOffset(is, is.getSize() - 4);
25005edf1c1Srobert if (rIndex == is.relocs().size())
251bb684c34Spatrick return false;
252bb684c34Spatrick
25305edf1c1Srobert Relocation &r = is.relocs()[rIndex];
254bb684c34Spatrick
255bb684c34Spatrick // Check if the relocation corresponds to a direct jmp.
25605edf1c1Srobert const uint8_t *secContents = is.content().data();
257bb684c34Spatrick // If it is not a direct jmp instruction, there is nothing to do here.
258bb684c34Spatrick if (*(secContents + r.offset - 1) != 0xe9)
259bb684c34Spatrick return false;
260bb684c34Spatrick
261bb684c34Spatrick if (isFallThruRelocation(is, file, nextIS, r)) {
262bb684c34Spatrick // This is a fall thru and can be deleted.
263bb684c34Spatrick r.expr = R_NONE;
264bb684c34Spatrick r.offset = 0;
265bb684c34Spatrick is.drop_back(sizeOfDirectJmpInsn);
266bb684c34Spatrick is.nopFiller = true;
267bb684c34Spatrick return true;
268bb684c34Spatrick }
269bb684c34Spatrick
270bb684c34Spatrick // Now, check if flip and delete is possible.
271bb684c34Spatrick const unsigned sizeOfJmpCCInsn = 6;
272bb684c34Spatrick // To flip, there must be at least one JmpCC and one direct jmp.
273bb684c34Spatrick if (is.getSize() < sizeOfDirectJmpInsn + sizeOfJmpCCInsn)
27405edf1c1Srobert return false;
275bb684c34Spatrick
276bb684c34Spatrick unsigned rbIndex =
277bb684c34Spatrick getRelocationWithOffset(is, (is.getSize() - sizeOfDirectJmpInsn - 4));
27805edf1c1Srobert if (rbIndex == is.relocs().size())
27905edf1c1Srobert return false;
280bb684c34Spatrick
28105edf1c1Srobert Relocation &rB = is.relocs()[rbIndex];
282bb684c34Spatrick
283bb684c34Spatrick const uint8_t *jmpInsnB = secContents + rB.offset - 1;
284bb684c34Spatrick JmpInsnOpcode jmpOpcodeB = getJmpInsnType(jmpInsnB - 1, jmpInsnB);
285bb684c34Spatrick if (jmpOpcodeB == J_UNKNOWN)
286bb684c34Spatrick return false;
287bb684c34Spatrick
288bb684c34Spatrick if (!isFallThruRelocation(is, file, nextIS, rB))
289bb684c34Spatrick return false;
290bb684c34Spatrick
291bb684c34Spatrick // jmpCC jumps to the fall thru block, the branch can be flipped and the
292bb684c34Spatrick // jmp can be deleted.
293bb684c34Spatrick JmpInsnOpcode jInvert = invertJmpOpcode(jmpOpcodeB);
294bb684c34Spatrick if (jInvert == J_UNKNOWN)
295bb684c34Spatrick return false;
29605edf1c1Srobert is.jumpInstrMod = make<JumpInstrMod>();
29705edf1c1Srobert *is.jumpInstrMod = {rB.offset - 1, jInvert, 4};
298bb684c34Spatrick // Move R's values to rB except the offset.
299bb684c34Spatrick rB = {r.expr, r.type, rB.offset, r.addend, r.sym};
300bb684c34Spatrick // Cancel R
301bb684c34Spatrick r.expr = R_NONE;
302bb684c34Spatrick r.offset = 0;
303bb684c34Spatrick is.drop_back(sizeOfDirectJmpInsn);
304bb684c34Spatrick is.nopFiller = true;
305bb684c34Spatrick return true;
306bb684c34Spatrick }
307bb684c34Spatrick
getRelExpr(RelType type,const Symbol & s,const uint8_t * loc) const308ece8a530Spatrick RelExpr X86_64::getRelExpr(RelType type, const Symbol &s,
309ece8a530Spatrick const uint8_t *loc) const {
310ece8a530Spatrick switch (type) {
311ece8a530Spatrick case R_X86_64_8:
312ece8a530Spatrick case R_X86_64_16:
313ece8a530Spatrick case R_X86_64_32:
314ece8a530Spatrick case R_X86_64_32S:
315ece8a530Spatrick case R_X86_64_64:
316ece8a530Spatrick return R_ABS;
317ece8a530Spatrick case R_X86_64_DTPOFF32:
318ece8a530Spatrick case R_X86_64_DTPOFF64:
319ece8a530Spatrick return R_DTPREL;
320ece8a530Spatrick case R_X86_64_TPOFF32:
3211cf9926bSpatrick return R_TPREL;
322ece8a530Spatrick case R_X86_64_TLSDESC_CALL:
323ece8a530Spatrick return R_TLSDESC_CALL;
324ece8a530Spatrick case R_X86_64_TLSLD:
325ece8a530Spatrick return R_TLSLD_PC;
326ece8a530Spatrick case R_X86_64_TLSGD:
327ece8a530Spatrick return R_TLSGD_PC;
328ece8a530Spatrick case R_X86_64_SIZE32:
329ece8a530Spatrick case R_X86_64_SIZE64:
330ece8a530Spatrick return R_SIZE;
331ece8a530Spatrick case R_X86_64_PLT32:
332ece8a530Spatrick return R_PLT_PC;
333ece8a530Spatrick case R_X86_64_PC8:
334ece8a530Spatrick case R_X86_64_PC16:
335ece8a530Spatrick case R_X86_64_PC32:
336ece8a530Spatrick case R_X86_64_PC64:
337ece8a530Spatrick return R_PC;
338ece8a530Spatrick case R_X86_64_GOT32:
339ece8a530Spatrick case R_X86_64_GOT64:
340ece8a530Spatrick return R_GOTPLT;
341ece8a530Spatrick case R_X86_64_GOTPC32_TLSDESC:
342ece8a530Spatrick return R_TLSDESC_PC;
343ece8a530Spatrick case R_X86_64_GOTPCREL:
344ece8a530Spatrick case R_X86_64_GOTPCRELX:
345ece8a530Spatrick case R_X86_64_REX_GOTPCRELX:
346ece8a530Spatrick case R_X86_64_GOTTPOFF:
347ece8a530Spatrick return R_GOT_PC;
348ece8a530Spatrick case R_X86_64_GOTOFF64:
349ece8a530Spatrick return R_GOTPLTREL;
35005edf1c1Srobert case R_X86_64_PLTOFF64:
35105edf1c1Srobert return R_PLT_GOTPLT;
352ece8a530Spatrick case R_X86_64_GOTPC32:
353ece8a530Spatrick case R_X86_64_GOTPC64:
354ece8a530Spatrick return R_GOTPLTONLY_PC;
355ece8a530Spatrick case R_X86_64_NONE:
356ece8a530Spatrick return R_NONE;
357ece8a530Spatrick default:
358ece8a530Spatrick error(getErrorLocation(loc) + "unknown relocation (" + Twine(type) +
359ece8a530Spatrick ") against symbol " + toString(s));
360ece8a530Spatrick return R_NONE;
361ece8a530Spatrick }
362ece8a530Spatrick }
363ece8a530Spatrick
writeGotPltHeader(uint8_t * buf) const364ece8a530Spatrick void X86_64::writeGotPltHeader(uint8_t *buf) const {
365ece8a530Spatrick // The first entry holds the value of _DYNAMIC. It is not clear why that is
366ece8a530Spatrick // required, but it is documented in the psabi and the glibc dynamic linker
367ece8a530Spatrick // seems to use it (note that this is relevant for linking ld.so, not any
368ece8a530Spatrick // other program).
369ece8a530Spatrick write64le(buf, mainPart->dynamic->getVA());
370ece8a530Spatrick }
371ece8a530Spatrick
writeGotPlt(uint8_t * buf,const Symbol & s) const372ece8a530Spatrick void X86_64::writeGotPlt(uint8_t *buf, const Symbol &s) const {
373ece8a530Spatrick // See comments in X86::writeGotPlt.
374ece8a530Spatrick write64le(buf, s.getPltVA() + 6);
375ece8a530Spatrick }
376ece8a530Spatrick
writeIgotPlt(uint8_t * buf,const Symbol & s) const3771cf9926bSpatrick void X86_64::writeIgotPlt(uint8_t *buf, const Symbol &s) const {
3781cf9926bSpatrick // An x86 entry is the address of the ifunc resolver function (for -z rel).
3791cf9926bSpatrick if (config->writeAddends)
3801cf9926bSpatrick write64le(buf, s.getVA());
3811cf9926bSpatrick }
3821cf9926bSpatrick
writePltHeader(uint8_t * buf) const383ece8a530Spatrick void X86_64::writePltHeader(uint8_t *buf) const {
384ece8a530Spatrick const uint8_t pltData[] = {
385ece8a530Spatrick 0xff, 0x35, 0, 0, 0, 0, // pushq GOTPLT+8(%rip)
386ece8a530Spatrick 0xff, 0x25, 0, 0, 0, 0, // jmp *GOTPLT+16(%rip)
387ece8a530Spatrick 0x0f, 0x1f, 0x40, 0x00, // nop
388ece8a530Spatrick };
389ece8a530Spatrick memcpy(buf, pltData, sizeof(pltData));
390ece8a530Spatrick uint64_t gotPlt = in.gotPlt->getVA();
391ece8a530Spatrick uint64_t plt = in.ibtPlt ? in.ibtPlt->getVA() : in.plt->getVA();
392ece8a530Spatrick write32le(buf + 2, gotPlt - plt + 2); // GOTPLT+8
393ece8a530Spatrick write32le(buf + 8, gotPlt - plt + 4); // GOTPLT+16
394ece8a530Spatrick }
395ece8a530Spatrick
writePlt(uint8_t * buf,const Symbol & sym,uint64_t pltEntryAddr) const396ece8a530Spatrick void X86_64::writePlt(uint8_t *buf, const Symbol &sym,
397ece8a530Spatrick uint64_t pltEntryAddr) const {
398ece8a530Spatrick const uint8_t inst[] = {
399ece8a530Spatrick 0xff, 0x25, 0, 0, 0, 0, // jmpq *got(%rip)
400ece8a530Spatrick 0x68, 0, 0, 0, 0, // pushq <relocation index>
401ece8a530Spatrick 0xe9, 0, 0, 0, 0, // jmpq plt[0]
402ece8a530Spatrick };
403ece8a530Spatrick memcpy(buf, inst, sizeof(inst));
404ece8a530Spatrick
405ece8a530Spatrick write32le(buf + 2, sym.getGotPltVA() - pltEntryAddr - 6);
40605edf1c1Srobert write32le(buf + 7, sym.getPltIdx());
407ece8a530Spatrick write32le(buf + 12, in.plt->getVA() - pltEntryAddr - 16);
408ece8a530Spatrick }
409ece8a530Spatrick
getDynRel(RelType type) const410ece8a530Spatrick RelType X86_64::getDynRel(RelType type) const {
411ece8a530Spatrick if (type == R_X86_64_64 || type == R_X86_64_PC64 || type == R_X86_64_SIZE32 ||
412ece8a530Spatrick type == R_X86_64_SIZE64)
413ece8a530Spatrick return type;
414ece8a530Spatrick return R_X86_64_NONE;
415ece8a530Spatrick }
416ece8a530Spatrick
relaxTlsGdToLe(uint8_t * loc,const Relocation & rel,uint64_t val)41705edf1c1Srobert static void relaxTlsGdToLe(uint8_t *loc, const Relocation &rel, uint64_t val) {
418bb684c34Spatrick if (rel.type == R_X86_64_TLSGD) {
419ece8a530Spatrick // Convert
420ece8a530Spatrick // .byte 0x66
421ece8a530Spatrick // leaq x@tlsgd(%rip), %rdi
422ece8a530Spatrick // .word 0x6666
423ece8a530Spatrick // rex64
424ece8a530Spatrick // call __tls_get_addr@plt
425ece8a530Spatrick // to the following two instructions.
426ece8a530Spatrick const uint8_t inst[] = {
427ece8a530Spatrick 0x64, 0x48, 0x8b, 0x04, 0x25, 0x00, 0x00,
428ece8a530Spatrick 0x00, 0x00, // mov %fs:0x0,%rax
429ece8a530Spatrick 0x48, 0x8d, 0x80, 0, 0, 0, 0, // lea x@tpoff,%rax
430ece8a530Spatrick };
431ece8a530Spatrick memcpy(loc - 4, inst, sizeof(inst));
432ece8a530Spatrick
433ece8a530Spatrick // The original code used a pc relative relocation and so we have to
434ece8a530Spatrick // compensate for the -4 in had in the addend.
435ece8a530Spatrick write32le(loc + 8, val + 4);
43605edf1c1Srobert } else if (rel.type == R_X86_64_GOTPC32_TLSDESC) {
43705edf1c1Srobert // Convert leaq x@tlsdesc(%rip), %REG to movq $x@tpoff, %REG.
43805edf1c1Srobert if ((loc[-3] & 0xfb) != 0x48 || loc[-2] != 0x8d ||
43905edf1c1Srobert (loc[-1] & 0xc7) != 0x05) {
44005edf1c1Srobert errorOrWarn(getErrorLocation(loc - 3) +
44105edf1c1Srobert "R_X86_64_GOTPC32_TLSDESC must be used "
44205edf1c1Srobert "in leaq x@tlsdesc(%rip), %REG");
443ece8a530Spatrick return;
444ece8a530Spatrick }
44505edf1c1Srobert loc[-3] = 0x48 | ((loc[-3] >> 2) & 1);
446ece8a530Spatrick loc[-2] = 0xc7;
44705edf1c1Srobert loc[-1] = 0xc0 | ((loc[-1] >> 3) & 7);
448ece8a530Spatrick write32le(loc, val + 4);
44905edf1c1Srobert } else {
45005edf1c1Srobert // Convert call *x@tlsdesc(%REG) to xchg ax, ax.
45105edf1c1Srobert assert(rel.type == R_X86_64_TLSDESC_CALL);
45205edf1c1Srobert loc[0] = 0x66;
45305edf1c1Srobert loc[1] = 0x90;
454ece8a530Spatrick }
455ece8a530Spatrick }
456ece8a530Spatrick
relaxTlsGdToIe(uint8_t * loc,const Relocation & rel,uint64_t val)45705edf1c1Srobert static void relaxTlsGdToIe(uint8_t *loc, const Relocation &rel, uint64_t val) {
458bb684c34Spatrick if (rel.type == R_X86_64_TLSGD) {
459ece8a530Spatrick // Convert
460ece8a530Spatrick // .byte 0x66
461ece8a530Spatrick // leaq x@tlsgd(%rip), %rdi
462ece8a530Spatrick // .word 0x6666
463ece8a530Spatrick // rex64
464ece8a530Spatrick // call __tls_get_addr@plt
465ece8a530Spatrick // to the following two instructions.
466ece8a530Spatrick const uint8_t inst[] = {
467ece8a530Spatrick 0x64, 0x48, 0x8b, 0x04, 0x25, 0x00, 0x00,
468ece8a530Spatrick 0x00, 0x00, // mov %fs:0x0,%rax
469ece8a530Spatrick 0x48, 0x03, 0x05, 0, 0, 0, 0, // addq x@gottpoff(%rip),%rax
470ece8a530Spatrick };
471ece8a530Spatrick memcpy(loc - 4, inst, sizeof(inst));
472ece8a530Spatrick
473ece8a530Spatrick // Both code sequences are PC relatives, but since we are moving the
474ece8a530Spatrick // constant forward by 8 bytes we have to subtract the value by 8.
475ece8a530Spatrick write32le(loc + 8, val - 8);
47605edf1c1Srobert } else if (rel.type == R_X86_64_GOTPC32_TLSDESC) {
47705edf1c1Srobert // Convert leaq x@tlsdesc(%rip), %REG to movq x@gottpoff(%rip), %REG.
478bb684c34Spatrick assert(rel.type == R_X86_64_GOTPC32_TLSDESC);
47905edf1c1Srobert if ((loc[-3] & 0xfb) != 0x48 || loc[-2] != 0x8d ||
48005edf1c1Srobert (loc[-1] & 0xc7) != 0x05) {
48105edf1c1Srobert errorOrWarn(getErrorLocation(loc - 3) +
48205edf1c1Srobert "R_X86_64_GOTPC32_TLSDESC must be used "
48305edf1c1Srobert "in leaq x@tlsdesc(%rip), %REG");
484ece8a530Spatrick return;
485ece8a530Spatrick }
486ece8a530Spatrick loc[-2] = 0x8b;
487ece8a530Spatrick write32le(loc, val);
48805edf1c1Srobert } else {
48905edf1c1Srobert // Convert call *x@tlsdesc(%rax) to xchg ax, ax.
49005edf1c1Srobert assert(rel.type == R_X86_64_TLSDESC_CALL);
49105edf1c1Srobert loc[0] = 0x66;
49205edf1c1Srobert loc[1] = 0x90;
493ece8a530Spatrick }
494ece8a530Spatrick }
495ece8a530Spatrick
496ece8a530Spatrick // In some conditions, R_X86_64_GOTTPOFF relocation can be optimized to
497ece8a530Spatrick // R_X86_64_TPOFF32 so that it does not use GOT.
relaxTlsIeToLe(uint8_t * loc,const Relocation &,uint64_t val)49805edf1c1Srobert static void relaxTlsIeToLe(uint8_t *loc, const Relocation &, uint64_t val) {
499ece8a530Spatrick uint8_t *inst = loc - 3;
500ece8a530Spatrick uint8_t reg = loc[-1] >> 3;
501ece8a530Spatrick uint8_t *regSlot = loc - 1;
502ece8a530Spatrick
503ece8a530Spatrick // Note that ADD with RSP or R12 is converted to ADD instead of LEA
504ece8a530Spatrick // because LEA with these registers needs 4 bytes to encode and thus
505ece8a530Spatrick // wouldn't fit the space.
506ece8a530Spatrick
507ece8a530Spatrick if (memcmp(inst, "\x48\x03\x25", 3) == 0) {
508ece8a530Spatrick // "addq foo@gottpoff(%rip),%rsp" -> "addq $foo,%rsp"
509ece8a530Spatrick memcpy(inst, "\x48\x81\xc4", 3);
510ece8a530Spatrick } else if (memcmp(inst, "\x4c\x03\x25", 3) == 0) {
511ece8a530Spatrick // "addq foo@gottpoff(%rip),%r12" -> "addq $foo,%r12"
512ece8a530Spatrick memcpy(inst, "\x49\x81\xc4", 3);
513ece8a530Spatrick } else if (memcmp(inst, "\x4c\x03", 2) == 0) {
514ece8a530Spatrick // "addq foo@gottpoff(%rip),%r[8-15]" -> "leaq foo(%r[8-15]),%r[8-15]"
515ece8a530Spatrick memcpy(inst, "\x4d\x8d", 2);
516ece8a530Spatrick *regSlot = 0x80 | (reg << 3) | reg;
517ece8a530Spatrick } else if (memcmp(inst, "\x48\x03", 2) == 0) {
518ece8a530Spatrick // "addq foo@gottpoff(%rip),%reg -> "leaq foo(%reg),%reg"
519ece8a530Spatrick memcpy(inst, "\x48\x8d", 2);
520ece8a530Spatrick *regSlot = 0x80 | (reg << 3) | reg;
521ece8a530Spatrick } else if (memcmp(inst, "\x4c\x8b", 2) == 0) {
522ece8a530Spatrick // "movq foo@gottpoff(%rip),%r[8-15]" -> "movq $foo,%r[8-15]"
523ece8a530Spatrick memcpy(inst, "\x49\xc7", 2);
524ece8a530Spatrick *regSlot = 0xc0 | reg;
525ece8a530Spatrick } else if (memcmp(inst, "\x48\x8b", 2) == 0) {
526ece8a530Spatrick // "movq foo@gottpoff(%rip),%reg" -> "movq $foo,%reg"
527ece8a530Spatrick memcpy(inst, "\x48\xc7", 2);
528ece8a530Spatrick *regSlot = 0xc0 | reg;
529ece8a530Spatrick } else {
530ece8a530Spatrick error(getErrorLocation(loc - 3) +
531ece8a530Spatrick "R_X86_64_GOTTPOFF must be used in MOVQ or ADDQ instructions only");
532ece8a530Spatrick }
533ece8a530Spatrick
534ece8a530Spatrick // The original code used a PC relative relocation.
535ece8a530Spatrick // Need to compensate for the -4 it had in the addend.
536ece8a530Spatrick write32le(loc, val + 4);
537ece8a530Spatrick }
538ece8a530Spatrick
relaxTlsLdToLe(uint8_t * loc,const Relocation & rel,uint64_t val)53905edf1c1Srobert static void relaxTlsLdToLe(uint8_t *loc, const Relocation &rel, uint64_t val) {
540ece8a530Spatrick const uint8_t inst[] = {
541ece8a530Spatrick 0x66, 0x66, // .word 0x6666
542ece8a530Spatrick 0x66, // .byte 0x66
543ece8a530Spatrick 0x64, 0x48, 0x8b, 0x04, 0x25, 0x00, 0x00, 0x00, 0x00, // mov %fs:0,%rax
544ece8a530Spatrick };
545ece8a530Spatrick
546ece8a530Spatrick if (loc[4] == 0xe8) {
547ece8a530Spatrick // Convert
548ece8a530Spatrick // leaq bar@tlsld(%rip), %rdi # 48 8d 3d <Loc>
549ece8a530Spatrick // callq __tls_get_addr@PLT # e8 <disp32>
550ece8a530Spatrick // leaq bar@dtpoff(%rax), %rcx
551ece8a530Spatrick // to
552ece8a530Spatrick // .word 0x6666
553ece8a530Spatrick // .byte 0x66
554ece8a530Spatrick // mov %fs:0,%rax
555ece8a530Spatrick // leaq bar@tpoff(%rax), %rcx
556ece8a530Spatrick memcpy(loc - 3, inst, sizeof(inst));
557ece8a530Spatrick return;
558ece8a530Spatrick }
559ece8a530Spatrick
560ece8a530Spatrick if (loc[4] == 0xff && loc[5] == 0x15) {
561ece8a530Spatrick // Convert
562ece8a530Spatrick // leaq x@tlsld(%rip),%rdi # 48 8d 3d <Loc>
563ece8a530Spatrick // call *__tls_get_addr@GOTPCREL(%rip) # ff 15 <disp32>
564ece8a530Spatrick // to
565ece8a530Spatrick // .long 0x66666666
566ece8a530Spatrick // movq %fs:0,%rax
567ece8a530Spatrick // See "Table 11.9: LD -> LE Code Transition (LP64)" in
568ece8a530Spatrick // https://raw.githubusercontent.com/wiki/hjl-tools/x86-psABI/x86-64-psABI-1.0.pdf
569ece8a530Spatrick loc[-3] = 0x66;
570ece8a530Spatrick memcpy(loc - 2, inst, sizeof(inst));
571ece8a530Spatrick return;
572ece8a530Spatrick }
573ece8a530Spatrick
574ece8a530Spatrick error(getErrorLocation(loc - 3) +
575ece8a530Spatrick "expected R_X86_64_PLT32 or R_X86_64_GOTPCRELX after R_X86_64_TLSLD");
576ece8a530Spatrick }
577ece8a530Spatrick
578bb684c34Spatrick // A JumpInstrMod at a specific offset indicates that the jump instruction
579bb684c34Spatrick // opcode at that offset must be modified. This is specifically used to relax
580bb684c34Spatrick // jump instructions with basic block sections. This function looks at the
581bb684c34Spatrick // JumpMod and effects the change.
applyJumpInstrMod(uint8_t * loc,JumpModType type,unsigned size) const582bb684c34Spatrick void X86_64::applyJumpInstrMod(uint8_t *loc, JumpModType type,
583bb684c34Spatrick unsigned size) const {
584ece8a530Spatrick switch (type) {
585bb684c34Spatrick case J_JMP_32:
586bb684c34Spatrick if (size == 4)
587bb684c34Spatrick *loc = 0xe9;
588bb684c34Spatrick else
589bb684c34Spatrick *loc = 0xeb;
590bb684c34Spatrick break;
591bb684c34Spatrick case J_JE_32:
592bb684c34Spatrick if (size == 4) {
593bb684c34Spatrick loc[-1] = 0x0f;
594bb684c34Spatrick *loc = 0x84;
595bb684c34Spatrick } else
596bb684c34Spatrick *loc = 0x74;
597bb684c34Spatrick break;
598bb684c34Spatrick case J_JNE_32:
599bb684c34Spatrick if (size == 4) {
600bb684c34Spatrick loc[-1] = 0x0f;
601bb684c34Spatrick *loc = 0x85;
602bb684c34Spatrick } else
603bb684c34Spatrick *loc = 0x75;
604bb684c34Spatrick break;
605bb684c34Spatrick case J_JG_32:
606bb684c34Spatrick if (size == 4) {
607bb684c34Spatrick loc[-1] = 0x0f;
608bb684c34Spatrick *loc = 0x8f;
609bb684c34Spatrick } else
610bb684c34Spatrick *loc = 0x7f;
611bb684c34Spatrick break;
612bb684c34Spatrick case J_JGE_32:
613bb684c34Spatrick if (size == 4) {
614bb684c34Spatrick loc[-1] = 0x0f;
615bb684c34Spatrick *loc = 0x8d;
616bb684c34Spatrick } else
617bb684c34Spatrick *loc = 0x7d;
618bb684c34Spatrick break;
619bb684c34Spatrick case J_JB_32:
620bb684c34Spatrick if (size == 4) {
621bb684c34Spatrick loc[-1] = 0x0f;
622bb684c34Spatrick *loc = 0x82;
623bb684c34Spatrick } else
624bb684c34Spatrick *loc = 0x72;
625bb684c34Spatrick break;
626bb684c34Spatrick case J_JBE_32:
627bb684c34Spatrick if (size == 4) {
628bb684c34Spatrick loc[-1] = 0x0f;
629bb684c34Spatrick *loc = 0x86;
630bb684c34Spatrick } else
631bb684c34Spatrick *loc = 0x76;
632bb684c34Spatrick break;
633bb684c34Spatrick case J_JL_32:
634bb684c34Spatrick if (size == 4) {
635bb684c34Spatrick loc[-1] = 0x0f;
636bb684c34Spatrick *loc = 0x8c;
637bb684c34Spatrick } else
638bb684c34Spatrick *loc = 0x7c;
639bb684c34Spatrick break;
640bb684c34Spatrick case J_JLE_32:
641bb684c34Spatrick if (size == 4) {
642bb684c34Spatrick loc[-1] = 0x0f;
643bb684c34Spatrick *loc = 0x8e;
644bb684c34Spatrick } else
645bb684c34Spatrick *loc = 0x7e;
646bb684c34Spatrick break;
647bb684c34Spatrick case J_JA_32:
648bb684c34Spatrick if (size == 4) {
649bb684c34Spatrick loc[-1] = 0x0f;
650bb684c34Spatrick *loc = 0x87;
651bb684c34Spatrick } else
652bb684c34Spatrick *loc = 0x77;
653bb684c34Spatrick break;
654bb684c34Spatrick case J_JAE_32:
655bb684c34Spatrick if (size == 4) {
656bb684c34Spatrick loc[-1] = 0x0f;
657bb684c34Spatrick *loc = 0x83;
658bb684c34Spatrick } else
659bb684c34Spatrick *loc = 0x73;
660bb684c34Spatrick break;
661bb684c34Spatrick case J_UNKNOWN:
662bb684c34Spatrick llvm_unreachable("Unknown Jump Relocation");
663bb684c34Spatrick }
664bb684c34Spatrick }
665bb684c34Spatrick
getImplicitAddend(const uint8_t * buf,RelType type) const6661cf9926bSpatrick int64_t X86_64::getImplicitAddend(const uint8_t *buf, RelType type) const {
6671cf9926bSpatrick switch (type) {
6681cf9926bSpatrick case R_X86_64_8:
6691cf9926bSpatrick case R_X86_64_PC8:
6701cf9926bSpatrick return SignExtend64<8>(*buf);
6711cf9926bSpatrick case R_X86_64_16:
6721cf9926bSpatrick case R_X86_64_PC16:
6731cf9926bSpatrick return SignExtend64<16>(read16le(buf));
6741cf9926bSpatrick case R_X86_64_32:
6751cf9926bSpatrick case R_X86_64_32S:
6761cf9926bSpatrick case R_X86_64_TPOFF32:
6771cf9926bSpatrick case R_X86_64_GOT32:
6781cf9926bSpatrick case R_X86_64_GOTPC32:
6791cf9926bSpatrick case R_X86_64_GOTPC32_TLSDESC:
6801cf9926bSpatrick case R_X86_64_GOTPCREL:
6811cf9926bSpatrick case R_X86_64_GOTPCRELX:
6821cf9926bSpatrick case R_X86_64_REX_GOTPCRELX:
6831cf9926bSpatrick case R_X86_64_PC32:
6841cf9926bSpatrick case R_X86_64_GOTTPOFF:
6851cf9926bSpatrick case R_X86_64_PLT32:
6861cf9926bSpatrick case R_X86_64_TLSGD:
6871cf9926bSpatrick case R_X86_64_TLSLD:
6881cf9926bSpatrick case R_X86_64_DTPOFF32:
6891cf9926bSpatrick case R_X86_64_SIZE32:
6901cf9926bSpatrick return SignExtend64<32>(read32le(buf));
6911cf9926bSpatrick case R_X86_64_64:
6921cf9926bSpatrick case R_X86_64_TPOFF64:
6931cf9926bSpatrick case R_X86_64_DTPOFF64:
6941cf9926bSpatrick case R_X86_64_DTPMOD64:
6951cf9926bSpatrick case R_X86_64_PC64:
6961cf9926bSpatrick case R_X86_64_SIZE64:
6971cf9926bSpatrick case R_X86_64_GLOB_DAT:
6981cf9926bSpatrick case R_X86_64_GOT64:
6991cf9926bSpatrick case R_X86_64_GOTOFF64:
7001cf9926bSpatrick case R_X86_64_GOTPC64:
70105edf1c1Srobert case R_X86_64_PLTOFF64:
7021cf9926bSpatrick case R_X86_64_IRELATIVE:
7031cf9926bSpatrick case R_X86_64_RELATIVE:
7041cf9926bSpatrick return read64le(buf);
70505edf1c1Srobert case R_X86_64_TLSDESC:
70605edf1c1Srobert return read64le(buf + 8);
7071cf9926bSpatrick case R_X86_64_JUMP_SLOT:
7081cf9926bSpatrick case R_X86_64_NONE:
7091cf9926bSpatrick // These relocations are defined as not having an implicit addend.
7101cf9926bSpatrick return 0;
7111cf9926bSpatrick default:
7121cf9926bSpatrick internalLinkerError(getErrorLocation(buf),
7131cf9926bSpatrick "cannot read addend for relocation " + toString(type));
7141cf9926bSpatrick return 0;
7151cf9926bSpatrick }
7161cf9926bSpatrick }
7171cf9926bSpatrick
71805edf1c1Srobert static void relaxGot(uint8_t *loc, const Relocation &rel, uint64_t val);
71905edf1c1Srobert
relocate(uint8_t * loc,const Relocation & rel,uint64_t val) const720bb684c34Spatrick void X86_64::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const {
721bb684c34Spatrick switch (rel.type) {
722ece8a530Spatrick case R_X86_64_8:
723bb684c34Spatrick checkIntUInt(loc, val, 8, rel);
724ece8a530Spatrick *loc = val;
725ece8a530Spatrick break;
726ece8a530Spatrick case R_X86_64_PC8:
727bb684c34Spatrick checkInt(loc, val, 8, rel);
728ece8a530Spatrick *loc = val;
729ece8a530Spatrick break;
730ece8a530Spatrick case R_X86_64_16:
731bb684c34Spatrick checkIntUInt(loc, val, 16, rel);
732ece8a530Spatrick write16le(loc, val);
733ece8a530Spatrick break;
734ece8a530Spatrick case R_X86_64_PC16:
735bb684c34Spatrick checkInt(loc, val, 16, rel);
736ece8a530Spatrick write16le(loc, val);
737ece8a530Spatrick break;
738ece8a530Spatrick case R_X86_64_32:
739bb684c34Spatrick checkUInt(loc, val, 32, rel);
740ece8a530Spatrick write32le(loc, val);
741ece8a530Spatrick break;
742ece8a530Spatrick case R_X86_64_32S:
743ece8a530Spatrick case R_X86_64_GOT32:
744ece8a530Spatrick case R_X86_64_GOTPC32:
745ece8a530Spatrick case R_X86_64_GOTPCREL:
746ece8a530Spatrick case R_X86_64_PC32:
747ece8a530Spatrick case R_X86_64_PLT32:
748ece8a530Spatrick case R_X86_64_DTPOFF32:
749ece8a530Spatrick case R_X86_64_SIZE32:
750bb684c34Spatrick checkInt(loc, val, 32, rel);
751ece8a530Spatrick write32le(loc, val);
752ece8a530Spatrick break;
753ece8a530Spatrick case R_X86_64_64:
754ece8a530Spatrick case R_X86_64_DTPOFF64:
755ece8a530Spatrick case R_X86_64_PC64:
756ece8a530Spatrick case R_X86_64_SIZE64:
757ece8a530Spatrick case R_X86_64_GOT64:
758ece8a530Spatrick case R_X86_64_GOTOFF64:
759ece8a530Spatrick case R_X86_64_GOTPC64:
76005edf1c1Srobert case R_X86_64_PLTOFF64:
761ece8a530Spatrick write64le(loc, val);
762ece8a530Spatrick break;
76305edf1c1Srobert case R_X86_64_GOTPCRELX:
76405edf1c1Srobert case R_X86_64_REX_GOTPCRELX:
76505edf1c1Srobert if (rel.expr != R_GOT_PC) {
76605edf1c1Srobert relaxGot(loc, rel, val);
76705edf1c1Srobert } else {
76805edf1c1Srobert checkInt(loc, val, 32, rel);
76905edf1c1Srobert write32le(loc, val);
77005edf1c1Srobert }
77105edf1c1Srobert break;
77205edf1c1Srobert case R_X86_64_GOTPC32_TLSDESC:
77305edf1c1Srobert case R_X86_64_TLSDESC_CALL:
77405edf1c1Srobert case R_X86_64_TLSGD:
77505edf1c1Srobert if (rel.expr == R_RELAX_TLS_GD_TO_LE) {
77605edf1c1Srobert relaxTlsGdToLe(loc, rel, val);
77705edf1c1Srobert } else if (rel.expr == R_RELAX_TLS_GD_TO_IE) {
77805edf1c1Srobert relaxTlsGdToIe(loc, rel, val);
77905edf1c1Srobert } else {
78005edf1c1Srobert checkInt(loc, val, 32, rel);
78105edf1c1Srobert write32le(loc, val);
78205edf1c1Srobert }
78305edf1c1Srobert break;
78405edf1c1Srobert case R_X86_64_TLSLD:
78505edf1c1Srobert if (rel.expr == R_RELAX_TLS_LD_TO_LE) {
78605edf1c1Srobert relaxTlsLdToLe(loc, rel, val);
78705edf1c1Srobert } else {
78805edf1c1Srobert checkInt(loc, val, 32, rel);
78905edf1c1Srobert write32le(loc, val);
79005edf1c1Srobert }
79105edf1c1Srobert break;
79205edf1c1Srobert case R_X86_64_GOTTPOFF:
79305edf1c1Srobert if (rel.expr == R_RELAX_TLS_IE_TO_LE) {
79405edf1c1Srobert relaxTlsIeToLe(loc, rel, val);
79505edf1c1Srobert } else {
79605edf1c1Srobert checkInt(loc, val, 32, rel);
79705edf1c1Srobert write32le(loc, val);
79805edf1c1Srobert }
79905edf1c1Srobert break;
80005edf1c1Srobert case R_X86_64_TPOFF32:
80105edf1c1Srobert checkInt(loc, val, 32, rel);
80205edf1c1Srobert write32le(loc, val);
80305edf1c1Srobert break;
80405edf1c1Srobert
80505edf1c1Srobert case R_X86_64_TLSDESC:
80605edf1c1Srobert // The addend is stored in the second 64-bit word.
80705edf1c1Srobert write64le(loc + 8, val);
80805edf1c1Srobert break;
809ece8a530Spatrick default:
810ece8a530Spatrick llvm_unreachable("unknown relocation");
811ece8a530Spatrick }
812ece8a530Spatrick }
813ece8a530Spatrick
adjustGotPcExpr(RelType type,int64_t addend,const uint8_t * loc) const8141cf9926bSpatrick RelExpr X86_64::adjustGotPcExpr(RelType type, int64_t addend,
8151cf9926bSpatrick const uint8_t *loc) const {
8161cf9926bSpatrick // Only R_X86_64_[REX_]GOTPCRELX can be relaxed. GNU as may emit GOTPCRELX
8171cf9926bSpatrick // with addend != -4. Such an instruction does not load the full GOT entry, so
8181cf9926bSpatrick // we cannot relax the relocation. E.g. movl x@GOTPCREL+4(%rip), %rax
8191cf9926bSpatrick // (addend=0) loads the high 32 bits of the GOT entry.
82005edf1c1Srobert if (!config->relax || addend != -4 ||
82105edf1c1Srobert (type != R_X86_64_GOTPCRELX && type != R_X86_64_REX_GOTPCRELX))
8221cf9926bSpatrick return R_GOT_PC;
8231cf9926bSpatrick const uint8_t op = loc[-2];
8241cf9926bSpatrick const uint8_t modRm = loc[-1];
825ece8a530Spatrick
826ece8a530Spatrick // FIXME: When PIC is disabled and foo is defined locally in the
827ece8a530Spatrick // lower 32 bit address space, memory operand in mov can be converted into
828ece8a530Spatrick // immediate operand. Otherwise, mov must be changed to lea. We support only
829ece8a530Spatrick // latter relaxation at this moment.
830ece8a530Spatrick if (op == 0x8b)
831ece8a530Spatrick return R_RELAX_GOT_PC;
832ece8a530Spatrick
833ece8a530Spatrick // Relax call and jmp.
834ece8a530Spatrick if (op == 0xff && (modRm == 0x15 || modRm == 0x25))
835ece8a530Spatrick return R_RELAX_GOT_PC;
836ece8a530Spatrick
8371cf9926bSpatrick // We don't support test/binop instructions without a REX prefix.
8381cf9926bSpatrick if (type == R_X86_64_GOTPCRELX)
8391cf9926bSpatrick return R_GOT_PC;
8401cf9926bSpatrick
841ece8a530Spatrick // Relaxation of test, adc, add, and, cmp, or, sbb, sub, xor.
842ece8a530Spatrick // If PIC then no relaxation is available.
8431cf9926bSpatrick return config->isPic ? R_GOT_PC : R_RELAX_GOT_PC_NOPIC;
844ece8a530Spatrick }
845ece8a530Spatrick
846ece8a530Spatrick // A subset of relaxations can only be applied for no-PIC. This method
847ece8a530Spatrick // handles such relaxations. Instructions encoding information was taken from:
848ece8a530Spatrick // "Intel 64 and IA-32 Architectures Software Developer's Manual V2"
849ece8a530Spatrick // (http://www.intel.com/content/dam/www/public/us/en/documents/manuals/
850ece8a530Spatrick // 64-ia-32-architectures-software-developer-instruction-set-reference-manual-325383.pdf)
relaxGotNoPic(uint8_t * loc,uint64_t val,uint8_t op,uint8_t modRm)851ece8a530Spatrick static void relaxGotNoPic(uint8_t *loc, uint64_t val, uint8_t op,
852ece8a530Spatrick uint8_t modRm) {
853ece8a530Spatrick const uint8_t rex = loc[-3];
854ece8a530Spatrick // Convert "test %reg, foo@GOTPCREL(%rip)" to "test $foo, %reg".
855ece8a530Spatrick if (op == 0x85) {
856ece8a530Spatrick // See "TEST-Logical Compare" (4-428 Vol. 2B),
857ece8a530Spatrick // TEST r/m64, r64 uses "full" ModR / M byte (no opcode extension).
858ece8a530Spatrick
859ece8a530Spatrick // ModR/M byte has form XX YYY ZZZ, where
860ece8a530Spatrick // YYY is MODRM.reg(register 2), ZZZ is MODRM.rm(register 1).
861ece8a530Spatrick // XX has different meanings:
862ece8a530Spatrick // 00: The operand's memory address is in reg1.
863ece8a530Spatrick // 01: The operand's memory address is reg1 + a byte-sized displacement.
864ece8a530Spatrick // 10: The operand's memory address is reg1 + a word-sized displacement.
865ece8a530Spatrick // 11: The operand is reg1 itself.
866ece8a530Spatrick // If an instruction requires only one operand, the unused reg2 field
867ece8a530Spatrick // holds extra opcode bits rather than a register code
868ece8a530Spatrick // 0xC0 == 11 000 000 binary.
869ece8a530Spatrick // 0x38 == 00 111 000 binary.
870ece8a530Spatrick // We transfer reg2 to reg1 here as operand.
871ece8a530Spatrick // See "2.1.3 ModR/M and SIB Bytes" (Vol. 2A 2-3).
872ece8a530Spatrick loc[-1] = 0xc0 | (modRm & 0x38) >> 3; // ModR/M byte.
873ece8a530Spatrick
874ece8a530Spatrick // Change opcode from TEST r/m64, r64 to TEST r/m64, imm32
875ece8a530Spatrick // See "TEST-Logical Compare" (4-428 Vol. 2B).
876ece8a530Spatrick loc[-2] = 0xf7;
877ece8a530Spatrick
878ece8a530Spatrick // Move R bit to the B bit in REX byte.
879ece8a530Spatrick // REX byte is encoded as 0100WRXB, where
880ece8a530Spatrick // 0100 is 4bit fixed pattern.
881ece8a530Spatrick // REX.W When 1, a 64-bit operand size is used. Otherwise, when 0, the
882ece8a530Spatrick // default operand size is used (which is 32-bit for most but not all
883ece8a530Spatrick // instructions).
884ece8a530Spatrick // REX.R This 1-bit value is an extension to the MODRM.reg field.
885ece8a530Spatrick // REX.X This 1-bit value is an extension to the SIB.index field.
886ece8a530Spatrick // REX.B This 1-bit value is an extension to the MODRM.rm field or the
887ece8a530Spatrick // SIB.base field.
888ece8a530Spatrick // See "2.2.1.2 More on REX Prefix Fields " (2-8 Vol. 2A).
889ece8a530Spatrick loc[-3] = (rex & ~0x4) | (rex & 0x4) >> 2;
890ece8a530Spatrick write32le(loc, val);
891ece8a530Spatrick return;
892ece8a530Spatrick }
893ece8a530Spatrick
894ece8a530Spatrick // If we are here then we need to relax the adc, add, and, cmp, or, sbb, sub
895ece8a530Spatrick // or xor operations.
896ece8a530Spatrick
897ece8a530Spatrick // Convert "binop foo@GOTPCREL(%rip), %reg" to "binop $foo, %reg".
898ece8a530Spatrick // Logic is close to one for test instruction above, but we also
899ece8a530Spatrick // write opcode extension here, see below for details.
900ece8a530Spatrick loc[-1] = 0xc0 | (modRm & 0x38) >> 3 | (op & 0x3c); // ModR/M byte.
901ece8a530Spatrick
902ece8a530Spatrick // Primary opcode is 0x81, opcode extension is one of:
903ece8a530Spatrick // 000b = ADD, 001b is OR, 010b is ADC, 011b is SBB,
904ece8a530Spatrick // 100b is AND, 101b is SUB, 110b is XOR, 111b is CMP.
905ece8a530Spatrick // This value was wrote to MODRM.reg in a line above.
906ece8a530Spatrick // See "3.2 INSTRUCTIONS (A-M)" (Vol. 2A 3-15),
907ece8a530Spatrick // "INSTRUCTION SET REFERENCE, N-Z" (Vol. 2B 4-1) for
908ece8a530Spatrick // descriptions about each operation.
909ece8a530Spatrick loc[-2] = 0x81;
910ece8a530Spatrick loc[-3] = (rex & ~0x4) | (rex & 0x4) >> 2;
911ece8a530Spatrick write32le(loc, val);
912ece8a530Spatrick }
913ece8a530Spatrick
relaxGot(uint8_t * loc,const Relocation & rel,uint64_t val)91405edf1c1Srobert static void relaxGot(uint8_t *loc, const Relocation &rel, uint64_t val) {
9151cf9926bSpatrick checkInt(loc, val, 32, rel);
916ece8a530Spatrick const uint8_t op = loc[-2];
917ece8a530Spatrick const uint8_t modRm = loc[-1];
918ece8a530Spatrick
919ece8a530Spatrick // Convert "mov foo@GOTPCREL(%rip),%reg" to "lea foo(%rip),%reg".
920ece8a530Spatrick if (op == 0x8b) {
921ece8a530Spatrick loc[-2] = 0x8d;
922ece8a530Spatrick write32le(loc, val);
923ece8a530Spatrick return;
924ece8a530Spatrick }
925ece8a530Spatrick
926ece8a530Spatrick if (op != 0xff) {
927ece8a530Spatrick // We are relaxing a rip relative to an absolute, so compensate
928ece8a530Spatrick // for the old -4 addend.
929ece8a530Spatrick assert(!config->isPic);
930ece8a530Spatrick relaxGotNoPic(loc, val + 4, op, modRm);
931ece8a530Spatrick return;
932ece8a530Spatrick }
933ece8a530Spatrick
934ece8a530Spatrick // Convert call/jmp instructions.
935ece8a530Spatrick if (modRm == 0x15) {
936ece8a530Spatrick // ABI says we can convert "call *foo@GOTPCREL(%rip)" to "nop; call foo".
937ece8a530Spatrick // Instead we convert to "addr32 call foo" where addr32 is an instruction
938ece8a530Spatrick // prefix. That makes result expression to be a single instruction.
939ece8a530Spatrick loc[-2] = 0x67; // addr32 prefix
940ece8a530Spatrick loc[-1] = 0xe8; // call
941ece8a530Spatrick write32le(loc, val);
942ece8a530Spatrick return;
943ece8a530Spatrick }
944ece8a530Spatrick
945ece8a530Spatrick // Convert "jmp *foo@GOTPCREL(%rip)" to "jmp foo; nop".
946ece8a530Spatrick // jmp doesn't return, so it is fine to use nop here, it is just a stub.
947ece8a530Spatrick assert(modRm == 0x25);
948ece8a530Spatrick loc[-2] = 0xe9; // jmp
949ece8a530Spatrick loc[3] = 0x90; // nop
950ece8a530Spatrick write32le(loc - 1, val + 1);
951ece8a530Spatrick }
952ece8a530Spatrick
953ece8a530Spatrick // A split-stack prologue starts by checking the amount of stack remaining
954ece8a530Spatrick // in one of two ways:
955ece8a530Spatrick // A) Comparing of the stack pointer to a field in the tcb.
956ece8a530Spatrick // B) Or a load of a stack pointer offset with an lea to r10 or r11.
adjustPrologueForCrossSplitStack(uint8_t * loc,uint8_t * end,uint8_t stOther) const957ece8a530Spatrick bool X86_64::adjustPrologueForCrossSplitStack(uint8_t *loc, uint8_t *end,
958ece8a530Spatrick uint8_t stOther) const {
959ece8a530Spatrick if (!config->is64) {
96005edf1c1Srobert error("target doesn't support split stacks");
961ece8a530Spatrick return false;
962ece8a530Spatrick }
963ece8a530Spatrick
964ece8a530Spatrick if (loc + 8 >= end)
965ece8a530Spatrick return false;
966ece8a530Spatrick
967ece8a530Spatrick // Replace "cmp %fs:0x70,%rsp" and subsequent branch
968ece8a530Spatrick // with "stc, nopl 0x0(%rax,%rax,1)"
969ece8a530Spatrick if (memcmp(loc, "\x64\x48\x3b\x24\x25", 5) == 0) {
970ece8a530Spatrick memcpy(loc, "\xf9\x0f\x1f\x84\x00\x00\x00\x00", 8);
971ece8a530Spatrick return true;
972ece8a530Spatrick }
973ece8a530Spatrick
974ece8a530Spatrick // Adjust "lea X(%rsp),%rYY" to lea "(X - 0x4000)(%rsp),%rYY" where rYY could
975ece8a530Spatrick // be r10 or r11. The lea instruction feeds a subsequent compare which checks
976ece8a530Spatrick // if there is X available stack space. Making X larger effectively reserves
977ece8a530Spatrick // that much additional space. The stack grows downward so subtract the value.
978ece8a530Spatrick if (memcmp(loc, "\x4c\x8d\x94\x24", 4) == 0 ||
979ece8a530Spatrick memcmp(loc, "\x4c\x8d\x9c\x24", 4) == 0) {
980ece8a530Spatrick // The offset bytes are encoded four bytes after the start of the
981ece8a530Spatrick // instruction.
982ece8a530Spatrick write32le(loc + 4, read32le(loc + 4) - 0x4000);
983ece8a530Spatrick return true;
984ece8a530Spatrick }
985ece8a530Spatrick return false;
986ece8a530Spatrick }
987ece8a530Spatrick
relocateAlloc(InputSectionBase & sec,uint8_t * buf) const98805edf1c1Srobert void X86_64::relocateAlloc(InputSectionBase &sec, uint8_t *buf) const {
98905edf1c1Srobert uint64_t secAddr = sec.getOutputSection()->addr;
99005edf1c1Srobert if (auto *s = dyn_cast<InputSection>(&sec))
99105edf1c1Srobert secAddr += s->outSecOff;
99205edf1c1Srobert for (const Relocation &rel : sec.relocs()) {
99305edf1c1Srobert if (rel.expr == R_NONE) // See deleteFallThruJmpInsn
99405edf1c1Srobert continue;
99505edf1c1Srobert uint8_t *loc = buf + rel.offset;
99605edf1c1Srobert const uint64_t val =
99705edf1c1Srobert sec.getRelocTargetVA(sec.file, rel.type, rel.addend,
99805edf1c1Srobert secAddr + rel.offset, *rel.sym, rel.expr);
99905edf1c1Srobert relocate(loc, rel, val);
100005edf1c1Srobert }
100105edf1c1Srobert if (sec.jumpInstrMod) {
100205edf1c1Srobert applyJumpInstrMod(buf + sec.jumpInstrMod->offset,
100305edf1c1Srobert sec.jumpInstrMod->original, sec.jumpInstrMod->size);
100405edf1c1Srobert }
100505edf1c1Srobert }
100605edf1c1Srobert
1007ece8a530Spatrick // If Intel Indirect Branch Tracking is enabled, we have to emit special PLT
1008ece8a530Spatrick // entries containing endbr64 instructions. A PLT entry will be split into two
1009ece8a530Spatrick // parts, one in .plt.sec (writePlt), and the other in .plt (writeIBTPlt).
1010ece8a530Spatrick namespace {
1011ece8a530Spatrick class IntelIBT : public X86_64 {
1012ece8a530Spatrick public:
1013ece8a530Spatrick IntelIBT();
1014ece8a530Spatrick void writeGotPlt(uint8_t *buf, const Symbol &s) const override;
1015ece8a530Spatrick void writePlt(uint8_t *buf, const Symbol &sym,
1016ece8a530Spatrick uint64_t pltEntryAddr) const override;
1017ece8a530Spatrick void writeIBTPlt(uint8_t *buf, size_t numEntries) const override;
1018ece8a530Spatrick
1019ece8a530Spatrick static const unsigned IBTPltHeaderSize = 16;
1020ece8a530Spatrick };
1021ece8a530Spatrick } // namespace
1022ece8a530Spatrick
IntelIBT()1023ece8a530Spatrick IntelIBT::IntelIBT() { pltHeaderSize = 0; }
1024ece8a530Spatrick
writeGotPlt(uint8_t * buf,const Symbol & s) const1025ece8a530Spatrick void IntelIBT::writeGotPlt(uint8_t *buf, const Symbol &s) const {
1026ece8a530Spatrick uint64_t va =
102705edf1c1Srobert in.ibtPlt->getVA() + IBTPltHeaderSize + s.getPltIdx() * pltEntrySize;
1028ece8a530Spatrick write64le(buf, va);
1029ece8a530Spatrick }
1030ece8a530Spatrick
writePlt(uint8_t * buf,const Symbol & sym,uint64_t pltEntryAddr) const1031ece8a530Spatrick void IntelIBT::writePlt(uint8_t *buf, const Symbol &sym,
1032ece8a530Spatrick uint64_t pltEntryAddr) const {
1033ece8a530Spatrick const uint8_t Inst[] = {
1034ece8a530Spatrick 0xf3, 0x0f, 0x1e, 0xfa, // endbr64
1035ece8a530Spatrick 0xff, 0x25, 0, 0, 0, 0, // jmpq *got(%rip)
1036ece8a530Spatrick 0x66, 0x0f, 0x1f, 0x44, 0, 0, // nop
1037ece8a530Spatrick };
1038ece8a530Spatrick memcpy(buf, Inst, sizeof(Inst));
1039ece8a530Spatrick write32le(buf + 6, sym.getGotPltVA() - pltEntryAddr - 10);
1040ece8a530Spatrick }
1041ece8a530Spatrick
writeIBTPlt(uint8_t * buf,size_t numEntries) const1042ece8a530Spatrick void IntelIBT::writeIBTPlt(uint8_t *buf, size_t numEntries) const {
1043ece8a530Spatrick writePltHeader(buf);
1044ece8a530Spatrick buf += IBTPltHeaderSize;
1045ece8a530Spatrick
1046ece8a530Spatrick const uint8_t inst[] = {
1047ece8a530Spatrick 0xf3, 0x0f, 0x1e, 0xfa, // endbr64
1048ece8a530Spatrick 0x68, 0, 0, 0, 0, // pushq <relocation index>
1049ece8a530Spatrick 0xe9, 0, 0, 0, 0, // jmpq plt[0]
1050ece8a530Spatrick 0x66, 0x90, // nop
1051ece8a530Spatrick };
1052ece8a530Spatrick
1053ece8a530Spatrick for (size_t i = 0; i < numEntries; ++i) {
1054ece8a530Spatrick memcpy(buf, inst, sizeof(inst));
1055ece8a530Spatrick write32le(buf + 5, i);
1056ece8a530Spatrick write32le(buf + 10, -pltHeaderSize - sizeof(inst) * i - 30);
1057ece8a530Spatrick buf += sizeof(inst);
1058ece8a530Spatrick }
1059ece8a530Spatrick }
1060ece8a530Spatrick
1061ece8a530Spatrick // These nonstandard PLT entries are to migtigate Spectre v2 security
1062ece8a530Spatrick // vulnerability. In order to mitigate Spectre v2, we want to avoid indirect
1063ece8a530Spatrick // branch instructions such as `jmp *GOTPLT(%rip)`. So, in the following PLT
1064ece8a530Spatrick // entries, we use a CALL followed by MOV and RET to do the same thing as an
1065ece8a530Spatrick // indirect jump. That instruction sequence is so-called "retpoline".
1066ece8a530Spatrick //
1067ece8a530Spatrick // We have two types of retpoline PLTs as a size optimization. If `-z now`
1068ece8a530Spatrick // is specified, all dynamic symbols are resolved at load-time. Thus, when
1069ece8a530Spatrick // that option is given, we can omit code for symbol lazy resolution.
1070ece8a530Spatrick namespace {
1071ece8a530Spatrick class Retpoline : public X86_64 {
1072ece8a530Spatrick public:
1073ece8a530Spatrick Retpoline();
1074ece8a530Spatrick void writeGotPlt(uint8_t *buf, const Symbol &s) const override;
1075ece8a530Spatrick void writePltHeader(uint8_t *buf) const override;
1076ece8a530Spatrick void writePlt(uint8_t *buf, const Symbol &sym,
1077ece8a530Spatrick uint64_t pltEntryAddr) const override;
1078ece8a530Spatrick };
1079ece8a530Spatrick
1080ece8a530Spatrick class RetpolineZNow : public X86_64 {
1081ece8a530Spatrick public:
1082ece8a530Spatrick RetpolineZNow();
writeGotPlt(uint8_t * buf,const Symbol & s) const1083ece8a530Spatrick void writeGotPlt(uint8_t *buf, const Symbol &s) const override {}
1084ece8a530Spatrick void writePltHeader(uint8_t *buf) const override;
1085ece8a530Spatrick void writePlt(uint8_t *buf, const Symbol &sym,
1086ece8a530Spatrick uint64_t pltEntryAddr) const override;
1087ece8a530Spatrick };
1088ece8a530Spatrick } // namespace
1089ece8a530Spatrick
Retpoline()1090ece8a530Spatrick Retpoline::Retpoline() {
1091ece8a530Spatrick pltHeaderSize = 48;
1092ece8a530Spatrick pltEntrySize = 32;
1093ece8a530Spatrick ipltEntrySize = 32;
1094ece8a530Spatrick }
1095ece8a530Spatrick
writeGotPlt(uint8_t * buf,const Symbol & s) const1096ece8a530Spatrick void Retpoline::writeGotPlt(uint8_t *buf, const Symbol &s) const {
1097de7c6152Skettenis write64le(buf, s.getPltVA() + 21);
1098ece8a530Spatrick }
1099ece8a530Spatrick
writePltHeader(uint8_t * buf) const1100ece8a530Spatrick void Retpoline::writePltHeader(uint8_t *buf) const {
1101ece8a530Spatrick const uint8_t insn[] = {
1102ece8a530Spatrick 0xff, 0x35, 0, 0, 0, 0, // 0: pushq GOTPLT+8(%rip)
1103ece8a530Spatrick 0x4c, 0x8b, 0x1d, 0, 0, 0, 0, // 6: mov GOTPLT+16(%rip), %r11
1104ece8a530Spatrick 0xe8, 0x0e, 0x00, 0x00, 0x00, // d: callq next
1105ece8a530Spatrick 0xf3, 0x90, // 12: loop: pause
1106ece8a530Spatrick 0x0f, 0xae, 0xe8, // 14: lfence
1107ece8a530Spatrick 0xeb, 0xf9, // 17: jmp loop
1108ece8a530Spatrick 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, // 19: int3; .align 16
1109ece8a530Spatrick 0x4c, 0x89, 0x1c, 0x24, // 20: next: mov %r11, (%rsp)
1110ece8a530Spatrick 0xc3, // 24: ret
1111ece8a530Spatrick 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, // 25: int3; padding
1112ece8a530Spatrick 0xcc, 0xcc, 0xcc, 0xcc, // 2c: int3; padding
1113ece8a530Spatrick };
1114ece8a530Spatrick memcpy(buf, insn, sizeof(insn));
1115ece8a530Spatrick
1116ece8a530Spatrick uint64_t gotPlt = in.gotPlt->getVA();
1117ece8a530Spatrick uint64_t plt = in.plt->getVA();
1118ece8a530Spatrick write32le(buf + 2, gotPlt - plt - 6 + 8);
1119ece8a530Spatrick write32le(buf + 9, gotPlt - plt - 13 + 16);
1120ece8a530Spatrick }
1121ece8a530Spatrick
writePlt(uint8_t * buf,const Symbol & sym,uint64_t pltEntryAddr) const1122ece8a530Spatrick void Retpoline::writePlt(uint8_t *buf, const Symbol &sym,
1123ece8a530Spatrick uint64_t pltEntryAddr) const {
1124ece8a530Spatrick const uint8_t insn[] = {
1125de7c6152Skettenis 0xf3, 0x0f, 0x1e, 0xfa, // 0: endbr64
1126de7c6152Skettenis 0x4c, 0x8b, 0x1d, 0, 0, 0, 0, // 4: mov foo@GOTPLT(%rip), %r11
1127de7c6152Skettenis 0xe8, 0, 0, 0, 0, // b: callq plt+0x20
1128de7c6152Skettenis 0xe9, 0, 0, 0, 0, // 10: jmp plt+0x12
1129de7c6152Skettenis 0x68, 0, 0, 0, 0, // 15: pushq <relocation index>
1130de7c6152Skettenis 0xe9, 0, 0, 0, 0, // 1a: jmp plt+0
1131de7c6152Skettenis 0xcc, // 1f: int3; padding
1132ece8a530Spatrick };
1133ece8a530Spatrick memcpy(buf, insn, sizeof(insn));
1134ece8a530Spatrick
1135ece8a530Spatrick uint64_t off = pltEntryAddr - in.plt->getVA();
1136ece8a530Spatrick
1137de7c6152Skettenis write32le(buf + 7, sym.getGotPltVA() - pltEntryAddr - 11);
1138de7c6152Skettenis write32le(buf + 12, -off - 16 + 32);
1139de7c6152Skettenis write32le(buf + 17, -off - 21 + 18);
114005edf1c1Srobert write32le(buf + 22, sym.getPltIdx());
1141de7c6152Skettenis write32le(buf + 27, -off - 31);
1142ece8a530Spatrick }
1143ece8a530Spatrick
RetpolineZNow()1144ece8a530Spatrick RetpolineZNow::RetpolineZNow() {
1145ece8a530Spatrick pltHeaderSize = 32;
1146ece8a530Spatrick pltEntrySize = 16;
1147ece8a530Spatrick ipltEntrySize = 16;
1148ece8a530Spatrick }
1149ece8a530Spatrick
writePltHeader(uint8_t * buf) const1150ece8a530Spatrick void RetpolineZNow::writePltHeader(uint8_t *buf) const {
1151ece8a530Spatrick const uint8_t insn[] = {
1152ece8a530Spatrick 0xe8, 0x0b, 0x00, 0x00, 0x00, // 0: call next
1153ece8a530Spatrick 0xf3, 0x90, // 5: loop: pause
1154ece8a530Spatrick 0x0f, 0xae, 0xe8, // 7: lfence
1155ece8a530Spatrick 0xeb, 0xf9, // a: jmp loop
1156ece8a530Spatrick 0xcc, 0xcc, 0xcc, 0xcc, // c: int3; .align 16
1157ece8a530Spatrick 0x4c, 0x89, 0x1c, 0x24, // 10: next: mov %r11, (%rsp)
1158ece8a530Spatrick 0xc3, // 14: ret
1159ece8a530Spatrick 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, // 15: int3; padding
1160ece8a530Spatrick 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, // 1a: int3; padding
1161ece8a530Spatrick 0xcc, // 1f: int3; padding
1162ece8a530Spatrick };
1163ece8a530Spatrick memcpy(buf, insn, sizeof(insn));
1164ece8a530Spatrick }
1165ece8a530Spatrick
writePlt(uint8_t * buf,const Symbol & sym,uint64_t pltEntryAddr) const1166ece8a530Spatrick void RetpolineZNow::writePlt(uint8_t *buf, const Symbol &sym,
1167ece8a530Spatrick uint64_t pltEntryAddr) const {
1168ece8a530Spatrick const uint8_t insn[] = {
1169398b5afeSguenther 0xf3, 0x0f, 0x1e, 0xfa, // 0: endbr64
1170398b5afeSguenther 0x4c, 0x8b, 0x1d, 0, 0, 0, 0, // 4: mov foo@GOTPLT(%rip), %r11
1171398b5afeSguenther 0xe9, 0, 0, 0, 0, // b: jmp plt+0
1172ece8a530Spatrick };
1173ece8a530Spatrick memcpy(buf, insn, sizeof(insn));
1174ece8a530Spatrick
1175398b5afeSguenther write32le(buf + 7, sym.getGotPltVA() - pltEntryAddr - 11);
1176398b5afeSguenther write32le(buf + 12, in.plt->getVA() - pltEntryAddr - 16);
1177ece8a530Spatrick }
1178ece8a530Spatrick
getTargetInfo()1179ece8a530Spatrick static TargetInfo *getTargetInfo() {
1180ece8a530Spatrick if (config->zRetpolineplt) {
1181ece8a530Spatrick if (config->zNow) {
1182ece8a530Spatrick static RetpolineZNow t;
1183ece8a530Spatrick return &t;
1184ece8a530Spatrick }
1185ece8a530Spatrick static Retpoline t;
1186ece8a530Spatrick return &t;
1187ece8a530Spatrick }
1188ece8a530Spatrick
1189*293d5193Skettenis #ifdef __OpenBSD__
1190*293d5193Skettenis static IntelIBT t;
1191*293d5193Skettenis return &t;
1192*293d5193Skettenis #else
1193ece8a530Spatrick if (config->andFeatures & GNU_PROPERTY_X86_FEATURE_1_IBT) {
1194ece8a530Spatrick static IntelIBT t;
1195ece8a530Spatrick return &t;
1196ece8a530Spatrick }
1197ece8a530Spatrick
1198ece8a530Spatrick static X86_64 t;
1199ece8a530Spatrick return &t;
1200*293d5193Skettenis #endif
1201ece8a530Spatrick }
1202ece8a530Spatrick
getX86_64TargetInfo()1203bb684c34Spatrick TargetInfo *elf::getX86_64TargetInfo() { return getTargetInfo(); }
1204