Coverage Report

Created: 2018-06-25 02:00

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/tools/lld/ELF/Arch/X86_64.cpp
Line
Count
Source
1
//===- X86_64.cpp ---------------------------------------------------------===//
2
//
3
//                             The LLVM Linker
4
//
5
// This file is distributed under the University of Illinois Open Source
6
// License. See LICENSE.TXT for details.
7
//
8
//===----------------------------------------------------------------------===//
9
10
#include "InputFiles.h"
11
#include "Symbols.h"
12
#include "SyntheticSections.h"
13
#include "Target.h"
14
#include "lld/Common/ErrorHandler.h"
15
#include "llvm/Object/ELF.h"
16
#include "llvm/Support/Endian.h"
17
18
using namespace llvm;
19
using namespace llvm::object;
20
using namespace llvm::support::endian;
21
using namespace llvm::ELF;
22
using namespace lld;
23
using namespace lld::elf;
24
25
namespace {
26
template <class ELFT> class X86_64 : public TargetInfo {
27
public:
28
  X86_64();
29
  RelExpr getRelExpr(RelType Type, const Symbol &S,
30
                     const uint8_t *Loc) const override;
31
  RelType getDynRel(RelType Type) const override;
32
  void writeGotPltHeader(uint8_t *Buf) const override;
33
  void writeGotPlt(uint8_t *Buf, const Symbol &S) const override;
34
  void writePltHeader(uint8_t *Buf) const override;
35
  void writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr, uint64_t PltEntryAddr,
36
                int32_t Index, unsigned RelOff) const override;
37
  void relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const override;
38
39
  RelExpr adjustRelaxExpr(RelType Type, const uint8_t *Data,
40
                          RelExpr Expr) const override;
41
  void relaxGot(uint8_t *Loc, uint64_t Val) const override;
42
  void relaxTlsGdToIe(uint8_t *Loc, RelType Type, uint64_t Val) const override;
43
  void relaxTlsGdToLe(uint8_t *Loc, RelType Type, uint64_t Val) const override;
44
  void relaxTlsIeToLe(uint8_t *Loc, RelType Type, uint64_t Val) const override;
45
  void relaxTlsLdToLe(uint8_t *Loc, RelType Type, uint64_t Val) const override;
46
47
private:
48
  void relaxGotNoPic(uint8_t *Loc, uint64_t Val, uint8_t Op,
49
                     uint8_t ModRm) const;
50
};
51
} // namespace
52
53
1.62k
template <class ELFT> X86_64<ELFT>::X86_64() {
54
1.62k
  CopyRel = R_X86_64_COPY;
55
1.62k
  GotRel = R_X86_64_GLOB_DAT;
56
1.62k
  PltRel = R_X86_64_JUMP_SLOT;
57
1.62k
  RelativeRel = R_X86_64_RELATIVE;
58
1.62k
  IRelativeRel = R_X86_64_IRELATIVE;
59
1.62k
  TlsGotRel = R_X86_64_TPOFF64;
60
1.62k
  TlsModuleIndexRel = R_X86_64_DTPMOD64;
61
1.62k
  TlsOffsetRel = R_X86_64_DTPOFF64;
62
1.62k
  GotEntrySize = 8;
63
1.62k
  GotPltEntrySize = 8;
64
1.62k
  PltEntrySize = 16;
65
1.62k
  PltHeaderSize = 16;
66
1.62k
  TlsGdRelaxSkip = 2;
67
1.62k
  TrapInstr = 0xcccccccc; // 0xcc = INT3
68
1.62k
69
1.62k
  // Align to the large page size (known as a superpage or huge page).
70
1.62k
  // FreeBSD automatically promotes large, superpage-aligned allocations.
71
1.62k
  DefaultImageBase = 0x200000;
72
1.62k
}
X86_64.cpp:(anonymous namespace)::X86_64<llvm::object::ELFType<(llvm::support::endianness)1, false> >::X86_64()
Line
Count
Source
53
3
template <class ELFT> X86_64<ELFT>::X86_64() {
54
3
  CopyRel = R_X86_64_COPY;
55
3
  GotRel = R_X86_64_GLOB_DAT;
56
3
  PltRel = R_X86_64_JUMP_SLOT;
57
3
  RelativeRel = R_X86_64_RELATIVE;
58
3
  IRelativeRel = R_X86_64_IRELATIVE;
59
3
  TlsGotRel = R_X86_64_TPOFF64;
60
3
  TlsModuleIndexRel = R_X86_64_DTPMOD64;
61
3
  TlsOffsetRel = R_X86_64_DTPOFF64;
62
3
  GotEntrySize = 8;
63
3
  GotPltEntrySize = 8;
64
3
  PltEntrySize = 16;
65
3
  PltHeaderSize = 16;
66
3
  TlsGdRelaxSkip = 2;
67
3
  TrapInstr = 0xcccccccc; // 0xcc = INT3
68
3
69
3
  // Align to the large page size (known as a superpage or huge page).
70
3
  // FreeBSD automatically promotes large, superpage-aligned allocations.
71
3
  DefaultImageBase = 0x200000;
72
3
}
X86_64.cpp:(anonymous namespace)::X86_64<llvm::object::ELFType<(llvm::support::endianness)1, true> >::X86_64()
Line
Count
Source
53
1.61k
template <class ELFT> X86_64<ELFT>::X86_64() {
54
1.61k
  CopyRel = R_X86_64_COPY;
55
1.61k
  GotRel = R_X86_64_GLOB_DAT;
56
1.61k
  PltRel = R_X86_64_JUMP_SLOT;
57
1.61k
  RelativeRel = R_X86_64_RELATIVE;
58
1.61k
  IRelativeRel = R_X86_64_IRELATIVE;
59
1.61k
  TlsGotRel = R_X86_64_TPOFF64;
60
1.61k
  TlsModuleIndexRel = R_X86_64_DTPMOD64;
61
1.61k
  TlsOffsetRel = R_X86_64_DTPOFF64;
62
1.61k
  GotEntrySize = 8;
63
1.61k
  GotPltEntrySize = 8;
64
1.61k
  PltEntrySize = 16;
65
1.61k
  PltHeaderSize = 16;
66
1.61k
  TlsGdRelaxSkip = 2;
67
1.61k
  TrapInstr = 0xcccccccc; // 0xcc = INT3
68
1.61k
69
1.61k
  // Align to the large page size (known as a superpage or huge page).
70
1.61k
  // FreeBSD automatically promotes large, superpage-aligned allocations.
71
1.61k
  DefaultImageBase = 0x200000;
72
1.61k
}
73
74
template <class ELFT>
75
RelExpr X86_64<ELFT>::getRelExpr(RelType Type, const Symbol &S,
76
1.22k
                                 const uint8_t *Loc) const {
77
1.22k
  switch (Type) {
78
1.22k
  case R_X86_64_8:
79
476
  case R_X86_64_16:
80
476
  case R_X86_64_32:
81
476
  case R_X86_64_32S:
82
476
  case R_X86_64_64:
83
476
  case R_X86_64_DTPOFF32:
84
476
  case R_X86_64_DTPOFF64:
85
476
    return R_ABS;
86
476
  case R_X86_64_TPOFF32:
87
7
    return R_TLS;
88
476
  case R_X86_64_TLSLD:
89
6
    return R_TLSLD_PC;
90
476
  case R_X86_64_TLSGD:
91
17
    return R_TLSGD_PC;
92
476
  case R_X86_64_SIZE32:
93
37
  case R_X86_64_SIZE64:
94
37
    return R_SIZE;
95
341
  case R_X86_64_PLT32:
96
341
    return R_PLT_PC;
97
187
  case R_X86_64_PC32:
98
187
  case R_X86_64_PC64:
99
187
    return R_PC;
100
187
  case R_X86_64_GOT32:
101
4
  case R_X86_64_GOT64:
102
4
    return R_GOT_FROM_END;
103
135
  case R_X86_64_GOTPCREL:
104
135
  case R_X86_64_GOTPCRELX:
105
135
  case R_X86_64_REX_GOTPCRELX:
106
135
  case R_X86_64_GOTTPOFF:
107
135
    return R_GOT_PC;
108
135
  case R_X86_64_GOTOFF64:
109
1
    return R_GOTREL_FROM_END;
110
135
  case R_X86_64_GOTPC32:
111
2
  case R_X86_64_GOTPC64:
112
2
    return R_GOTONLY_PC_FROM_END;
113
5
  case R_X86_64_NONE:
114
5
    return R_NONE;
115
4
  default:
116
4
    return R_INVALID;
117
1.22k
  }
118
1.22k
}
X86_64.cpp:(anonymous namespace)::X86_64<llvm::object::ELFType<(llvm::support::endianness)1, false> >::getRelExpr(unsigned int, lld::elf::Symbol const&, unsigned char const*) const
Line
Count
Source
76
1
                                 const uint8_t *Loc) const {
77
1
  switch (Type) {
78
1
  case R_X86_64_8:
79
0
  case R_X86_64_16:
80
0
  case R_X86_64_32:
81
0
  case R_X86_64_32S:
82
0
  case R_X86_64_64:
83
0
  case R_X86_64_DTPOFF32:
84
0
  case R_X86_64_DTPOFF64:
85
0
    return R_ABS;
86
0
  case R_X86_64_TPOFF32:
87
0
    return R_TLS;
88
0
  case R_X86_64_TLSLD:
89
0
    return R_TLSLD_PC;
90
0
  case R_X86_64_TLSGD:
91
0
    return R_TLSGD_PC;
92
0
  case R_X86_64_SIZE32:
93
0
  case R_X86_64_SIZE64:
94
0
    return R_SIZE;
95
1
  case R_X86_64_PLT32:
96
1
    return R_PLT_PC;
97
0
  case R_X86_64_PC32:
98
0
  case R_X86_64_PC64:
99
0
    return R_PC;
100
0
  case R_X86_64_GOT32:
101
0
  case R_X86_64_GOT64:
102
0
    return R_GOT_FROM_END;
103
0
  case R_X86_64_GOTPCREL:
104
0
  case R_X86_64_GOTPCRELX:
105
0
  case R_X86_64_REX_GOTPCRELX:
106
0
  case R_X86_64_GOTTPOFF:
107
0
    return R_GOT_PC;
108
0
  case R_X86_64_GOTOFF64:
109
0
    return R_GOTREL_FROM_END;
110
0
  case R_X86_64_GOTPC32:
111
0
  case R_X86_64_GOTPC64:
112
0
    return R_GOTONLY_PC_FROM_END;
113
0
  case R_X86_64_NONE:
114
0
    return R_NONE;
115
0
  default:
116
0
    return R_INVALID;
117
1
  }
118
1
}
X86_64.cpp:(anonymous namespace)::X86_64<llvm::object::ELFType<(llvm::support::endianness)1, true> >::getRelExpr(unsigned int, lld::elf::Symbol const&, unsigned char const*) const
Line
Count
Source
76
1.22k
                                 const uint8_t *Loc) const {
77
1.22k
  switch (Type) {
78
1.22k
  case R_X86_64_8:
79
476
  case R_X86_64_16:
80
476
  case R_X86_64_32:
81
476
  case R_X86_64_32S:
82
476
  case R_X86_64_64:
83
476
  case R_X86_64_DTPOFF32:
84
476
  case R_X86_64_DTPOFF64:
85
476
    return R_ABS;
86
476
  case R_X86_64_TPOFF32:
87
7
    return R_TLS;
88
476
  case R_X86_64_TLSLD:
89
6
    return R_TLSLD_PC;
90
476
  case R_X86_64_TLSGD:
91
17
    return R_TLSGD_PC;
92
476
  case R_X86_64_SIZE32:
93
37
  case R_X86_64_SIZE64:
94
37
    return R_SIZE;
95
340
  case R_X86_64_PLT32:
96
340
    return R_PLT_PC;
97
187
  case R_X86_64_PC32:
98
187
  case R_X86_64_PC64:
99
187
    return R_PC;
100
187
  case R_X86_64_GOT32:
101
4
  case R_X86_64_GOT64:
102
4
    return R_GOT_FROM_END;
103
135
  case R_X86_64_GOTPCREL:
104
135
  case R_X86_64_GOTPCRELX:
105
135
  case R_X86_64_REX_GOTPCRELX:
106
135
  case R_X86_64_GOTTPOFF:
107
135
    return R_GOT_PC;
108
135
  case R_X86_64_GOTOFF64:
109
1
    return R_GOTREL_FROM_END;
110
135
  case R_X86_64_GOTPC32:
111
2
  case R_X86_64_GOTPC64:
112
2
    return R_GOTONLY_PC_FROM_END;
113
5
  case R_X86_64_NONE:
114
5
    return R_NONE;
115
4
  default:
116
4
    return R_INVALID;
117
1.22k
  }
118
1.22k
}
119
120
147
template <class ELFT> void X86_64<ELFT>::writeGotPltHeader(uint8_t *Buf) const {
121
147
  // The first entry holds the value of _DYNAMIC. It is not clear why that is
122
147
  // required, but it is documented in the psabi and the glibc dynamic linker
123
147
  // seems to use it (note that this is relevant for linking ld.so, not any
124
147
  // other program).
125
147
  write64le(Buf, InX::Dynamic->getVA());
126
147
}
X86_64.cpp:(anonymous namespace)::X86_64<llvm::object::ELFType<(llvm::support::endianness)1, false> >::writeGotPltHeader(unsigned char*) const
Line
Count
Source
120
1
template <class ELFT> void X86_64<ELFT>::writeGotPltHeader(uint8_t *Buf) const {
121
1
  // The first entry holds the value of _DYNAMIC. It is not clear why that is
122
1
  // required, but it is documented in the psabi and the glibc dynamic linker
123
1
  // seems to use it (note that this is relevant for linking ld.so, not any
124
1
  // other program).
125
1
  write64le(Buf, InX::Dynamic->getVA());
126
1
}
X86_64.cpp:(anonymous namespace)::X86_64<llvm::object::ELFType<(llvm::support::endianness)1, true> >::writeGotPltHeader(unsigned char*) const
Line
Count
Source
120
146
template <class ELFT> void X86_64<ELFT>::writeGotPltHeader(uint8_t *Buf) const {
121
146
  // The first entry holds the value of _DYNAMIC. It is not clear why that is
122
146
  // required, but it is documented in the psabi and the glibc dynamic linker
123
146
  // seems to use it (note that this is relevant for linking ld.so, not any
124
146
  // other program).
125
146
  write64le(Buf, InX::Dynamic->getVA());
126
146
}
127
128
template <class ELFT>
129
163
void X86_64<ELFT>::writeGotPlt(uint8_t *Buf, const Symbol &S) const {
130
163
  // See comments in X86::writeGotPlt.
131
163
  write64le(Buf, S.getPltVA() + 6);
132
163
}
X86_64.cpp:(anonymous namespace)::X86_64<llvm::object::ELFType<(llvm::support::endianness)1, false> >::writeGotPlt(unsigned char*, lld::elf::Symbol const&) const
Line
Count
Source
129
1
void X86_64<ELFT>::writeGotPlt(uint8_t *Buf, const Symbol &S) const {
130
1
  // See comments in X86::writeGotPlt.
131
1
  write64le(Buf, S.getPltVA() + 6);
132
1
}
X86_64.cpp:(anonymous namespace)::X86_64<llvm::object::ELFType<(llvm::support::endianness)1, true> >::writeGotPlt(unsigned char*, lld::elf::Symbol const&) const
Line
Count
Source
129
162
void X86_64<ELFT>::writeGotPlt(uint8_t *Buf, const Symbol &S) const {
130
162
  // See comments in X86::writeGotPlt.
131
162
  write64le(Buf, S.getPltVA() + 6);
132
162
}
133
134
123
template <class ELFT> void X86_64<ELFT>::writePltHeader(uint8_t *Buf) const {
135
123
  const uint8_t PltData[] = {
136
123
      0xff, 0x35, 0, 0, 0, 0, // pushq GOTPLT+8(%rip)
137
123
      0xff, 0x25, 0, 0, 0, 0, // jmp *GOTPLT+16(%rip)
138
123
      0x0f, 0x1f, 0x40, 0x00, // nop
139
123
  };
140
123
  memcpy(Buf, PltData, sizeof(PltData));
141
123
  uint64_t GotPlt = InX::GotPlt->getVA();
142
123
  uint64_t Plt = InX::Plt->getVA();
143
123
  write32le(Buf + 2, GotPlt - Plt + 2); // GOTPLT+8
144
123
  write32le(Buf + 8, GotPlt - Plt + 4); // GOTPLT+16
145
123
}
X86_64.cpp:(anonymous namespace)::X86_64<llvm::object::ELFType<(llvm::support::endianness)1, false> >::writePltHeader(unsigned char*) const
Line
Count
Source
134
1
template <class ELFT> void X86_64<ELFT>::writePltHeader(uint8_t *Buf) const {
135
1
  const uint8_t PltData[] = {
136
1
      0xff, 0x35, 0, 0, 0, 0, // pushq GOTPLT+8(%rip)
137
1
      0xff, 0x25, 0, 0, 0, 0, // jmp *GOTPLT+16(%rip)
138
1
      0x0f, 0x1f, 0x40, 0x00, // nop
139
1
  };
140
1
  memcpy(Buf, PltData, sizeof(PltData));
141
1
  uint64_t GotPlt = InX::GotPlt->getVA();
142
1
  uint64_t Plt = InX::Plt->getVA();
143
1
  write32le(Buf + 2, GotPlt - Plt + 2); // GOTPLT+8
144
1
  write32le(Buf + 8, GotPlt - Plt + 4); // GOTPLT+16
145
1
}
X86_64.cpp:(anonymous namespace)::X86_64<llvm::object::ELFType<(llvm::support::endianness)1, true> >::writePltHeader(unsigned char*) const
Line
Count
Source
134
122
template <class ELFT> void X86_64<ELFT>::writePltHeader(uint8_t *Buf) const {
135
122
  const uint8_t PltData[] = {
136
122
      0xff, 0x35, 0, 0, 0, 0, // pushq GOTPLT+8(%rip)
137
122
      0xff, 0x25, 0, 0, 0, 0, // jmp *GOTPLT+16(%rip)
138
122
      0x0f, 0x1f, 0x40, 0x00, // nop
139
122
  };
140
122
  memcpy(Buf, PltData, sizeof(PltData));
141
122
  uint64_t GotPlt = InX::GotPlt->getVA();
142
122
  uint64_t Plt = InX::Plt->getVA();
143
122
  write32le(Buf + 2, GotPlt - Plt + 2); // GOTPLT+8
144
122
  write32le(Buf + 8, GotPlt - Plt + 4); // GOTPLT+16
145
122
}
146
147
template <class ELFT>
148
void X86_64<ELFT>::writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr,
149
                            uint64_t PltEntryAddr, int32_t Index,
150
163
                            unsigned RelOff) const {
151
163
  const uint8_t Inst[] = {
152
163
      0xff, 0x25, 0, 0, 0, 0, // jmpq *got(%rip)
153
163
      0x68, 0, 0, 0, 0,       // pushq <relocation index>
154
163
      0xe9, 0, 0, 0, 0,       // jmpq plt[0]
155
163
  };
156
163
  memcpy(Buf, Inst, sizeof(Inst));
157
163
158
163
  write32le(Buf + 2, GotPltEntryAddr - PltEntryAddr - 6);
159
163
  write32le(Buf + 7, Index);
160
163
  write32le(Buf + 12, -getPltEntryOffset(Index) - 16);
161
163
}
X86_64.cpp:(anonymous namespace)::X86_64<llvm::object::ELFType<(llvm::support::endianness)1, false> >::writePlt(unsigned char*, unsigned long long, unsigned long long, int, unsigned int) const
Line
Count
Source
150
1
                            unsigned RelOff) const {
151
1
  const uint8_t Inst[] = {
152
1
      0xff, 0x25, 0, 0, 0, 0, // jmpq *got(%rip)
153
1
      0x68, 0, 0, 0, 0,       // pushq <relocation index>
154
1
      0xe9, 0, 0, 0, 0,       // jmpq plt[0]
155
1
  };
156
1
  memcpy(Buf, Inst, sizeof(Inst));
157
1
158
1
  write32le(Buf + 2, GotPltEntryAddr - PltEntryAddr - 6);
159
1
  write32le(Buf + 7, Index);
160
1
  write32le(Buf + 12, -getPltEntryOffset(Index) - 16);
161
1
}
X86_64.cpp:(anonymous namespace)::X86_64<llvm::object::ELFType<(llvm::support::endianness)1, true> >::writePlt(unsigned char*, unsigned long long, unsigned long long, int, unsigned int) const
Line
Count
Source
150
162
                            unsigned RelOff) const {
151
162
  const uint8_t Inst[] = {
152
162
      0xff, 0x25, 0, 0, 0, 0, // jmpq *got(%rip)
153
162
      0x68, 0, 0, 0, 0,       // pushq <relocation index>
154
162
      0xe9, 0, 0, 0, 0,       // jmpq plt[0]
155
162
  };
156
162
  memcpy(Buf, Inst, sizeof(Inst));
157
162
158
162
  write32le(Buf + 2, GotPltEntryAddr - PltEntryAddr - 6);
159
162
  write32le(Buf + 7, Index);
160
162
  write32le(Buf + 12, -getPltEntryOffset(Index) - 16);
161
162
}
162
163
100
template <class ELFT> RelType X86_64<ELFT>::getDynRel(RelType Type) const {
164
100
  if (Type == R_X86_64_64 || 
Type == R_X86_64_PC6429
||
Type == R_X86_64_SIZE3226
||
165
100
      
Type == R_X86_64_SIZE6420
)
166
86
    return Type;
167
14
  return R_X86_64_NONE;
168
14
}
Unexecuted instantiation: X86_64.cpp:(anonymous namespace)::X86_64<llvm::object::ELFType<(llvm::support::endianness)1, false> >::getDynRel(unsigned int) const
X86_64.cpp:(anonymous namespace)::X86_64<llvm::object::ELFType<(llvm::support::endianness)1, true> >::getDynRel(unsigned int) const
Line
Count
Source
163
100
template <class ELFT> RelType X86_64<ELFT>::getDynRel(RelType Type) const {
164
100
  if (Type == R_X86_64_64 || 
Type == R_X86_64_PC6429
||
Type == R_X86_64_SIZE3226
||
165
100
      
Type == R_X86_64_SIZE6420
)
166
86
    return Type;
167
14
  return R_X86_64_NONE;
168
14
}
169
170
template <class ELFT>
171
void X86_64<ELFT>::relaxTlsGdToLe(uint8_t *Loc, RelType Type,
172
7
                                  uint64_t Val) const {
173
7
  // Convert
174
7
  //   .byte 0x66
175
7
  //   leaq x@tlsgd(%rip), %rdi
176
7
  //   .word 0x6666
177
7
  //   rex64
178
7
  //   call __tls_get_addr@plt
179
7
  // to
180
7
  //   mov %fs:0x0,%rax
181
7
  //   lea x@tpoff,%rax
182
7
  const uint8_t Inst[] = {
183
7
      0x64, 0x48, 0x8b, 0x04, 0x25, 0x00, 0x00, 0x00, 0x00, // mov %fs:0x0,%rax
184
7
      0x48, 0x8d, 0x80, 0, 0, 0, 0,                         // lea x@tpoff,%rax
185
7
  };
186
7
  memcpy(Loc - 4, Inst, sizeof(Inst));
187
7
188
7
  // The original code used a pc relative relocation and so we have to
189
7
  // compensate for the -4 in had in the addend.
190
7
  write32le(Loc + 8, Val + 4);
191
7
}
Unexecuted instantiation: X86_64.cpp:(anonymous namespace)::X86_64<llvm::object::ELFType<(llvm::support::endianness)1, false> >::relaxTlsGdToLe(unsigned char*, unsigned int, unsigned long long) const
X86_64.cpp:(anonymous namespace)::X86_64<llvm::object::ELFType<(llvm::support::endianness)1, true> >::relaxTlsGdToLe(unsigned char*, unsigned int, unsigned long long) const
Line
Count
Source
172
7
                                  uint64_t Val) const {
173
7
  // Convert
174
7
  //   .byte 0x66
175
7
  //   leaq x@tlsgd(%rip), %rdi
176
7
  //   .word 0x6666
177
7
  //   rex64
178
7
  //   call __tls_get_addr@plt
179
7
  // to
180
7
  //   mov %fs:0x0,%rax
181
7
  //   lea x@tpoff,%rax
182
7
  const uint8_t Inst[] = {
183
7
      0x64, 0x48, 0x8b, 0x04, 0x25, 0x00, 0x00, 0x00, 0x00, // mov %fs:0x0,%rax
184
7
      0x48, 0x8d, 0x80, 0, 0, 0, 0,                         // lea x@tpoff,%rax
185
7
  };
186
7
  memcpy(Loc - 4, Inst, sizeof(Inst));
187
7
188
7
  // The original code used a pc relative relocation and so we have to
189
7
  // compensate for the -4 in had in the addend.
190
7
  write32le(Loc + 8, Val + 4);
191
7
}
192
193
template <class ELFT>
194
void X86_64<ELFT>::relaxTlsGdToIe(uint8_t *Loc, RelType Type,
195
4
                                  uint64_t Val) const {
196
4
  // Convert
197
4
  //   .byte 0x66
198
4
  //   leaq x@tlsgd(%rip), %rdi
199
4
  //   .word 0x6666
200
4
  //   rex64
201
4
  //   call __tls_get_addr@plt
202
4
  // to
203
4
  //   mov %fs:0x0,%rax
204
4
  //   addq x@tpoff,%rax
205
4
  const uint8_t Inst[] = {
206
4
      0x64, 0x48, 0x8b, 0x04, 0x25, 0x00, 0x00, 0x00, 0x00, // mov %fs:0x0,%rax
207
4
      0x48, 0x03, 0x05, 0, 0, 0, 0,                         // addq x@tpoff,%rax
208
4
  };
209
4
  memcpy(Loc - 4, Inst, sizeof(Inst));
210
4
211
4
  // Both code sequences are PC relatives, but since we are moving the constant
212
4
  // forward by 8 bytes we have to subtract the value by 8.
213
4
  write32le(Loc + 8, Val - 8);
214
4
}
Unexecuted instantiation: X86_64.cpp:(anonymous namespace)::X86_64<llvm::object::ELFType<(llvm::support::endianness)1, false> >::relaxTlsGdToIe(unsigned char*, unsigned int, unsigned long long) const
X86_64.cpp:(anonymous namespace)::X86_64<llvm::object::ELFType<(llvm::support::endianness)1, true> >::relaxTlsGdToIe(unsigned char*, unsigned int, unsigned long long) const
Line
Count
Source
195
4
                                  uint64_t Val) const {
196
4
  // Convert
197
4
  //   .byte 0x66
198
4
  //   leaq x@tlsgd(%rip), %rdi
199
4
  //   .word 0x6666
200
4
  //   rex64
201
4
  //   call __tls_get_addr@plt
202
4
  // to
203
4
  //   mov %fs:0x0,%rax
204
4
  //   addq x@tpoff,%rax
205
4
  const uint8_t Inst[] = {
206
4
      0x64, 0x48, 0x8b, 0x04, 0x25, 0x00, 0x00, 0x00, 0x00, // mov %fs:0x0,%rax
207
4
      0x48, 0x03, 0x05, 0, 0, 0, 0,                         // addq x@tpoff,%rax
208
4
  };
209
4
  memcpy(Loc - 4, Inst, sizeof(Inst));
210
4
211
4
  // Both code sequences are PC relatives, but since we are moving the constant
212
4
  // forward by 8 bytes we have to subtract the value by 8.
213
4
  write32le(Loc + 8, Val - 8);
214
4
}
215
216
// In some conditions, R_X86_64_GOTTPOFF relocation can be optimized to
217
// R_X86_64_TPOFF32 so that it does not use GOT.
218
template <class ELFT>
219
void X86_64<ELFT>::relaxTlsIeToLe(uint8_t *Loc, RelType Type,
220
31
                                  uint64_t Val) const {
221
31
  uint8_t *Inst = Loc - 3;
222
31
  uint8_t Reg = Loc[-1] >> 3;
223
31
  uint8_t *RegSlot = Loc - 1;
224
31
225
31
  // Note that ADD with RSP or R12 is converted to ADD instead of LEA
226
31
  // because LEA with these registers needs 4 bytes to encode and thus
227
31
  // wouldn't fit the space.
228
31
229
31
  if (memcmp(Inst, "\x48\x03\x25", 3) == 0) {
230
4
    // "addq foo@gottpoff(%rip),%rsp" -> "addq $foo,%rsp"
231
4
    memcpy(Inst, "\x48\x81\xc4", 3);
232
27
  } else if (memcmp(Inst, "\x4c\x03\x25", 3) == 0) {
233
4
    // "addq foo@gottpoff(%rip),%r12" -> "addq $foo,%r12"
234
4
    memcpy(Inst, "\x49\x81\xc4", 3);
235
23
  } else if (memcmp(Inst, "\x4c\x03", 2) == 0) {
236
4
    // "addq foo@gottpoff(%rip),%r[8-15]" -> "leaq foo(%r[8-15]),%r[8-15]"
237
4
    memcpy(Inst, "\x4d\x8d", 2);
238
4
    *RegSlot = 0x80 | (Reg << 3) | Reg;
239
19
  } else if (memcmp(Inst, "\x48\x03", 2) == 0) {
240
4
    // "addq foo@gottpoff(%rip),%reg -> "leaq foo(%reg),%reg"
241
4
    memcpy(Inst, "\x48\x8d", 2);
242
4
    *RegSlot = 0x80 | (Reg << 3) | Reg;
243
15
  } else if (memcmp(Inst, "\x4c\x8b", 2) == 0) {
244
4
    // "movq foo@gottpoff(%rip),%r[8-15]" -> "movq $foo,%r[8-15]"
245
4
    memcpy(Inst, "\x49\xc7", 2);
246
4
    *RegSlot = 0xc0 | Reg;
247
11
  } else if (memcmp(Inst, "\x48\x8b", 2) == 0) {
248
9
    // "movq foo@gottpoff(%rip),%reg" -> "movq $foo,%reg"
249
9
    memcpy(Inst, "\x48\xc7", 2);
250
9
    *RegSlot = 0xc0 | Reg;
251
9
  } else {
252
2
    error(getErrorLocation(Loc - 3) +
253
2
          "R_X86_64_GOTTPOFF must be used in MOVQ or ADDQ instructions only");
254
2
  }
255
31
256
31
  // The original code used a PC relative relocation.
257
31
  // Need to compensate for the -4 it had in the addend.
258
31
  write32le(Loc, Val + 4);
259
31
}
Unexecuted instantiation: X86_64.cpp:(anonymous namespace)::X86_64<llvm::object::ELFType<(llvm::support::endianness)1, false> >::relaxTlsIeToLe(unsigned char*, unsigned int, unsigned long long) const
X86_64.cpp:(anonymous namespace)::X86_64<llvm::object::ELFType<(llvm::support::endianness)1, true> >::relaxTlsIeToLe(unsigned char*, unsigned int, unsigned long long) const
Line
Count
Source
220
31
                                  uint64_t Val) const {
221
31
  uint8_t *Inst = Loc - 3;
222
31
  uint8_t Reg = Loc[-1] >> 3;
223
31
  uint8_t *RegSlot = Loc - 1;
224
31
225
31
  // Note that ADD with RSP or R12 is converted to ADD instead of LEA
226
31
  // because LEA with these registers needs 4 bytes to encode and thus
227
31
  // wouldn't fit the space.
228
31
229
31
  if (memcmp(Inst, "\x48\x03\x25", 3) == 0) {
230
4
    // "addq foo@gottpoff(%rip),%rsp" -> "addq $foo,%rsp"
231
4
    memcpy(Inst, "\x48\x81\xc4", 3);
232
27
  } else if (memcmp(Inst, "\x4c\x03\x25", 3) == 0) {
233
4
    // "addq foo@gottpoff(%rip),%r12" -> "addq $foo,%r12"
234
4
    memcpy(Inst, "\x49\x81\xc4", 3);
235
23
  } else if (memcmp(Inst, "\x4c\x03", 2) == 0) {
236
4
    // "addq foo@gottpoff(%rip),%r[8-15]" -> "leaq foo(%r[8-15]),%r[8-15]"
237
4
    memcpy(Inst, "\x4d\x8d", 2);
238
4
    *RegSlot = 0x80 | (Reg << 3) | Reg;
239
19
  } else if (memcmp(Inst, "\x48\x03", 2) == 0) {
240
4
    // "addq foo@gottpoff(%rip),%reg -> "leaq foo(%reg),%reg"
241
4
    memcpy(Inst, "\x48\x8d", 2);
242
4
    *RegSlot = 0x80 | (Reg << 3) | Reg;
243
15
  } else if (memcmp(Inst, "\x4c\x8b", 2) == 0) {
244
4
    // "movq foo@gottpoff(%rip),%r[8-15]" -> "movq $foo,%r[8-15]"
245
4
    memcpy(Inst, "\x49\xc7", 2);
246
4
    *RegSlot = 0xc0 | Reg;
247
11
  } else if (memcmp(Inst, "\x48\x8b", 2) == 0) {
248
9
    // "movq foo@gottpoff(%rip),%reg" -> "movq $foo,%reg"
249
9
    memcpy(Inst, "\x48\xc7", 2);
250
9
    *RegSlot = 0xc0 | Reg;
251
9
  } else {
252
2
    error(getErrorLocation(Loc - 3) +
253
2
          "R_X86_64_GOTTPOFF must be used in MOVQ or ADDQ instructions only");
254
2
  }
255
31
256
31
  // The original code used a PC relative relocation.
257
31
  // Need to compensate for the -4 it had in the addend.
258
31
  write32le(Loc, Val + 4);
259
31
}
260
261
template <class ELFT>
262
void X86_64<ELFT>::relaxTlsLdToLe(uint8_t *Loc, RelType Type,
263
8
                                  uint64_t Val) const {
264
8
  // Convert
265
8
  //   leaq bar@tlsld(%rip), %rdi
266
8
  //   callq __tls_get_addr@PLT
267
8
  //   leaq bar@dtpoff(%rax), %rcx
268
8
  // to
269
8
  //   .word 0x6666
270
8
  //   .byte 0x66
271
8
  //   mov %fs:0,%rax
272
8
  //   leaq bar@tpoff(%rax), %rcx
273
8
  if (Type == R_X86_64_DTPOFF64) {
274
2
    write64le(Loc, Val);
275
2
    return;
276
2
  }
277
6
  if (Type == R_X86_64_DTPOFF32) {
278
3
    write32le(Loc, Val);
279
3
    return;
280
3
  }
281
3
282
3
  const uint8_t Inst[] = {
283
3
      0x66, 0x66,                                           // .word 0x6666
284
3
      0x66,                                                 // .byte 0x66
285
3
      0x64, 0x48, 0x8b, 0x04, 0x25, 0x00, 0x00, 0x00, 0x00, // mov %fs:0,%rax
286
3
  };
287
3
  memcpy(Loc - 3, Inst, sizeof(Inst));
288
3
}
Unexecuted instantiation: X86_64.cpp:(anonymous namespace)::X86_64<llvm::object::ELFType<(llvm::support::endianness)1, false> >::relaxTlsLdToLe(unsigned char*, unsigned int, unsigned long long) const
X86_64.cpp:(anonymous namespace)::X86_64<llvm::object::ELFType<(llvm::support::endianness)1, true> >::relaxTlsLdToLe(unsigned char*, unsigned int, unsigned long long) const
Line
Count
Source
263
8
                                  uint64_t Val) const {
264
8
  // Convert
265
8
  //   leaq bar@tlsld(%rip), %rdi
266
8
  //   callq __tls_get_addr@PLT
267
8
  //   leaq bar@dtpoff(%rax), %rcx
268
8
  // to
269
8
  //   .word 0x6666
270
8
  //   .byte 0x66
271
8
  //   mov %fs:0,%rax
272
8
  //   leaq bar@tpoff(%rax), %rcx
273
8
  if (Type == R_X86_64_DTPOFF64) {
274
2
    write64le(Loc, Val);
275
2
    return;
276
2
  }
277
6
  if (Type == R_X86_64_DTPOFF32) {
278
3
    write32le(Loc, Val);
279
3
    return;
280
3
  }
281
3
282
3
  const uint8_t Inst[] = {
283
3
      0x66, 0x66,                                           // .word 0x6666
284
3
      0x66,                                                 // .byte 0x66
285
3
      0x64, 0x48, 0x8b, 0x04, 0x25, 0x00, 0x00, 0x00, 0x00, // mov %fs:0,%rax
286
3
  };
287
3
  memcpy(Loc - 3, Inst, sizeof(Inst));
288
3
}
289
290
template <class ELFT>
291
983
void X86_64<ELFT>::relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const {
292
983
  switch (Type) {
293
983
  case R_X86_64_8:
294
3
    checkUInt(Loc, Val, 8, Type);
295
3
    *Loc = Val;
296
3
    break;
297
983
  case R_X86_64_16:
298
2
    checkUInt(Loc, Val, 16, Type);
299
2
    write16le(Loc, Val);
300
2
    break;
301
983
  case R_X86_64_32:
302
116
    checkUInt(Loc, Val, 32, Type);
303
116
    write32le(Loc, Val);
304
116
    break;
305
983
  case R_X86_64_32S:
306
661
  case R_X86_64_TPOFF32:
307
661
  case R_X86_64_GOT32:
308
661
  case R_X86_64_GOTPC32:
309
661
  case R_X86_64_GOTPCREL:
310
661
  case R_X86_64_GOTPCRELX:
311
661
  case R_X86_64_REX_GOTPCRELX:
312
661
  case R_X86_64_PC32:
313
661
  case R_X86_64_GOTTPOFF:
314
661
  case R_X86_64_PLT32:
315
661
  case R_X86_64_TLSGD:
316
661
  case R_X86_64_TLSLD:
317
661
  case R_X86_64_DTPOFF32:
318
661
  case R_X86_64_SIZE32:
319
661
    checkInt(Loc, Val, 32, Type);
320
661
    write32le(Loc, Val);
321
661
    break;
322
661
  case R_X86_64_64:
323
199
  case R_X86_64_DTPOFF64:
324
199
  case R_X86_64_GLOB_DAT:
325
199
  case R_X86_64_PC64:
326
199
  case R_X86_64_SIZE64:
327
199
  case R_X86_64_GOT64:
328
199
  case R_X86_64_GOTOFF64:
329
199
  case R_X86_64_GOTPC64:
330
199
    write64le(Loc, Val);
331
199
    break;
332
199
  default:
333
2
    error(getErrorLocation(Loc) + "unrecognized reloc " + Twine(Type));
334
983
  }
335
983
}
X86_64.cpp:(anonymous namespace)::X86_64<llvm::object::ELFType<(llvm::support::endianness)1, false> >::relocateOne(unsigned char*, unsigned int, unsigned long long) const
Line
Count
Source
291
1
void X86_64<ELFT>::relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const {
292
1
  switch (Type) {
293
1
  case R_X86_64_8:
294
0
    checkUInt(Loc, Val, 8, Type);
295
0
    *Loc = Val;
296
0
    break;
297
1
  case R_X86_64_16:
298
0
    checkUInt(Loc, Val, 16, Type);
299
0
    write16le(Loc, Val);
300
0
    break;
301
1
  case R_X86_64_32:
302
0
    checkUInt(Loc, Val, 32, Type);
303
0
    write32le(Loc, Val);
304
0
    break;
305
1
  case R_X86_64_32S:
306
1
  case R_X86_64_TPOFF32:
307
1
  case R_X86_64_GOT32:
308
1
  case R_X86_64_GOTPC32:
309
1
  case R_X86_64_GOTPCREL:
310
1
  case R_X86_64_GOTPCRELX:
311
1
  case R_X86_64_REX_GOTPCRELX:
312
1
  case R_X86_64_PC32:
313
1
  case R_X86_64_GOTTPOFF:
314
1
  case R_X86_64_PLT32:
315
1
  case R_X86_64_TLSGD:
316
1
  case R_X86_64_TLSLD:
317
1
  case R_X86_64_DTPOFF32:
318
1
  case R_X86_64_SIZE32:
319
1
    checkInt(Loc, Val, 32, Type);
320
1
    write32le(Loc, Val);
321
1
    break;
322
1
  case R_X86_64_64:
323
0
  case R_X86_64_DTPOFF64:
324
0
  case R_X86_64_GLOB_DAT:
325
0
  case R_X86_64_PC64:
326
0
  case R_X86_64_SIZE64:
327
0
  case R_X86_64_GOT64:
328
0
  case R_X86_64_GOTOFF64:
329
0
  case R_X86_64_GOTPC64:
330
0
    write64le(Loc, Val);
331
0
    break;
332
0
  default:
333
0
    error(getErrorLocation(Loc) + "unrecognized reloc " + Twine(Type));
334
1
  }
335
1
}
X86_64.cpp:(anonymous namespace)::X86_64<llvm::object::ELFType<(llvm::support::endianness)1, true> >::relocateOne(unsigned char*, unsigned int, unsigned long long) const
Line
Count
Source
291
982
void X86_64<ELFT>::relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const {
292
982
  switch (Type) {
293
982
  case R_X86_64_8:
294
3
    checkUInt(Loc, Val, 8, Type);
295
3
    *Loc = Val;
296
3
    break;
297
982
  case R_X86_64_16:
298
2
    checkUInt(Loc, Val, 16, Type);
299
2
    write16le(Loc, Val);
300
2
    break;
301
982
  case R_X86_64_32:
302
116
    checkUInt(Loc, Val, 32, Type);
303
116
    write32le(Loc, Val);
304
116
    break;
305
982
  case R_X86_64_32S:
306
660
  case R_X86_64_TPOFF32:
307
660
  case R_X86_64_GOT32:
308
660
  case R_X86_64_GOTPC32:
309
660
  case R_X86_64_GOTPCREL:
310
660
  case R_X86_64_GOTPCRELX:
311
660
  case R_X86_64_REX_GOTPCRELX:
312
660
  case R_X86_64_PC32:
313
660
  case R_X86_64_GOTTPOFF:
314
660
  case R_X86_64_PLT32:
315
660
  case R_X86_64_TLSGD:
316
660
  case R_X86_64_TLSLD:
317
660
  case R_X86_64_DTPOFF32:
318
660
  case R_X86_64_SIZE32:
319
660
    checkInt(Loc, Val, 32, Type);
320
660
    write32le(Loc, Val);
321
660
    break;
322
660
  case R_X86_64_64:
323
199
  case R_X86_64_DTPOFF64:
324
199
  case R_X86_64_GLOB_DAT:
325
199
  case R_X86_64_PC64:
326
199
  case R_X86_64_SIZE64:
327
199
  case R_X86_64_GOT64:
328
199
  case R_X86_64_GOTOFF64:
329
199
  case R_X86_64_GOTPC64:
330
199
    write64le(Loc, Val);
331
199
    break;
332
199
  default:
333
2
    error(getErrorLocation(Loc) + "unrecognized reloc " + Twine(Type));
334
982
  }
335
982
}
336
337
template <class ELFT>
338
RelExpr X86_64<ELFT>::adjustRelaxExpr(RelType Type, const uint8_t *Data,
339
58
                                      RelExpr RelExpr) const {
340
58
  if (Type != R_X86_64_GOTPCRELX && 
Type != R_X86_64_REX_GOTPCRELX50
)
341
17
    return RelExpr;
342
41
  const uint8_t Op = Data[-2];
343
41
  const uint8_t ModRm = Data[-1];
344
41
345
41
  // FIXME: When PIC is disabled and foo is defined locally in the
346
41
  // lower 32 bit address space, memory operand in mov can be converted into
347
41
  // immediate operand. Otherwise, mov must be changed to lea. We support only
348
41
  // latter relaxation at this moment.
349
41
  if (Op == 0x8b)
350
15
    return R_RELAX_GOT_PC;
351
26
352
26
  // Relax call and jmp.
353
26
  if (Op == 0xff && 
(8
ModRm == 0x158
||
ModRm == 0x254
))
354
8
    return R_RELAX_GOT_PC;
355
18
356
18
  // Relaxation of test, adc, add, and, cmp, or, sbb, sub, xor.
357
18
  // If PIC then no relaxation is available.
358
18
  // We also don't relax test/binop instructions without REX byte,
359
18
  // they are 32bit operations and not common to have.
360
18
  assert(Type == R_X86_64_REX_GOTPCRELX);
361
18
  return Config->Pic ? 
RelExpr9
:
R_RELAX_GOT_PC_NOPIC9
;
362
18
}
Unexecuted instantiation: X86_64.cpp:(anonymous namespace)::X86_64<llvm::object::ELFType<(llvm::support::endianness)1, false> >::adjustRelaxExpr(unsigned int, unsigned char const*, lld::elf::RelExpr) const
X86_64.cpp:(anonymous namespace)::X86_64<llvm::object::ELFType<(llvm::support::endianness)1, true> >::adjustRelaxExpr(unsigned int, unsigned char const*, lld::elf::RelExpr) const
Line
Count
Source
339
58
                                      RelExpr RelExpr) const {
340
58
  if (Type != R_X86_64_GOTPCRELX && 
Type != R_X86_64_REX_GOTPCRELX50
)
341
17
    return RelExpr;
342
41
  const uint8_t Op = Data[-2];
343
41
  const uint8_t ModRm = Data[-1];
344
41
345
41
  // FIXME: When PIC is disabled and foo is defined locally in the
346
41
  // lower 32 bit address space, memory operand in mov can be converted into
347
41
  // immediate operand. Otherwise, mov must be changed to lea. We support only
348
41
  // latter relaxation at this moment.
349
41
  if (Op == 0x8b)
350
15
    return R_RELAX_GOT_PC;
351
26
352
26
  // Relax call and jmp.
353
26
  if (Op == 0xff && 
(8
ModRm == 0x158
||
ModRm == 0x254
))
354
8
    return R_RELAX_GOT_PC;
355
18
356
18
  // Relaxation of test, adc, add, and, cmp, or, sbb, sub, xor.
357
18
  // If PIC then no relaxation is available.
358
18
  // We also don't relax test/binop instructions without REX byte,
359
18
  // they are 32bit operations and not common to have.
360
18
  assert(Type == R_X86_64_REX_GOTPCRELX);
361
18
  return Config->Pic ? 
RelExpr9
:
R_RELAX_GOT_PC_NOPIC9
;
362
18
}
363
364
// A subset of relaxations can only be applied for no-PIC. This method
365
// handles such relaxations. Instructions encoding information was taken from:
366
// "Intel 64 and IA-32 Architectures Software Developer's Manual V2"
367
// (http://www.intel.com/content/dam/www/public/us/en/documents/manuals/
368
//    64-ia-32-architectures-software-developer-instruction-set-reference-manual-325383.pdf)
369
template <class ELFT>
370
void X86_64<ELFT>::relaxGotNoPic(uint8_t *Loc, uint64_t Val, uint8_t Op,
371
9
                                 uint8_t ModRm) const {
372
9
  const uint8_t Rex = Loc[-3];
373
9
  // Convert "test %reg, foo@GOTPCREL(%rip)" to "test $foo, %reg".
374
9
  if (Op == 0x85) {
375
1
    // See "TEST-Logical Compare" (4-428 Vol. 2B),
376
1
    // TEST r/m64, r64 uses "full" ModR / M byte (no opcode extension).
377
1
378
1
    // ModR/M byte has form XX YYY ZZZ, where
379
1
    // YYY is MODRM.reg(register 2), ZZZ is MODRM.rm(register 1).
380
1
    // XX has different meanings:
381
1
    // 00: The operand's memory address is in reg1.
382
1
    // 01: The operand's memory address is reg1 + a byte-sized displacement.
383
1
    // 10: The operand's memory address is reg1 + a word-sized displacement.
384
1
    // 11: The operand is reg1 itself.
385
1
    // If an instruction requires only one operand, the unused reg2 field
386
1
    // holds extra opcode bits rather than a register code
387
1
    // 0xC0 == 11 000 000 binary.
388
1
    // 0x38 == 00 111 000 binary.
389
1
    // We transfer reg2 to reg1 here as operand.
390
1
    // See "2.1.3 ModR/M and SIB Bytes" (Vol. 2A 2-3).
391
1
    Loc[-1] = 0xc0 | (ModRm & 0x38) >> 3; // ModR/M byte.
392
1
393
1
    // Change opcode from TEST r/m64, r64 to TEST r/m64, imm32
394
1
    // See "TEST-Logical Compare" (4-428 Vol. 2B).
395
1
    Loc[-2] = 0xf7;
396
1
397
1
    // Move R bit to the B bit in REX byte.
398
1
    // REX byte is encoded as 0100WRXB, where
399
1
    // 0100 is 4bit fixed pattern.
400
1
    // REX.W When 1, a 64-bit operand size is used. Otherwise, when 0, the
401
1
    //   default operand size is used (which is 32-bit for most but not all
402
1
    //   instructions).
403
1
    // REX.R This 1-bit value is an extension to the MODRM.reg field.
404
1
    // REX.X This 1-bit value is an extension to the SIB.index field.
405
1
    // REX.B This 1-bit value is an extension to the MODRM.rm field or the
406
1
    // SIB.base field.
407
1
    // See "2.2.1.2 More on REX Prefix Fields " (2-8 Vol. 2A).
408
1
    Loc[-3] = (Rex & ~0x4) | (Rex & 0x4) >> 2;
409
1
    write32le(Loc, Val);
410
1
    return;
411
1
  }
412
8
413
8
  // If we are here then we need to relax the adc, add, and, cmp, or, sbb, sub
414
8
  // or xor operations.
415
8
416
8
  // Convert "binop foo@GOTPCREL(%rip), %reg" to "binop $foo, %reg".
417
8
  // Logic is close to one for test instruction above, but we also
418
8
  // write opcode extension here, see below for details.
419
8
  Loc[-1] = 0xc0 | (ModRm & 0x38) >> 3 | (Op & 0x3c); // ModR/M byte.
420
8
421
8
  // Primary opcode is 0x81, opcode extension is one of:
422
8
  // 000b = ADD, 001b is OR, 010b is ADC, 011b is SBB,
423
8
  // 100b is AND, 101b is SUB, 110b is XOR, 111b is CMP.
424
8
  // This value was wrote to MODRM.reg in a line above.
425
8
  // See "3.2 INSTRUCTIONS (A-M)" (Vol. 2A 3-15),
426
8
  // "INSTRUCTION SET REFERENCE, N-Z" (Vol. 2B 4-1) for
427
8
  // descriptions about each operation.
428
8
  Loc[-2] = 0x81;
429
8
  Loc[-3] = (Rex & ~0x4) | (Rex & 0x4) >> 2;
430
8
  write32le(Loc, Val);
431
8
}
Unexecuted instantiation: X86_64.cpp:(anonymous namespace)::X86_64<llvm::object::ELFType<(llvm::support::endianness)1, false> >::relaxGotNoPic(unsigned char*, unsigned long long, unsigned char, unsigned char) const
X86_64.cpp:(anonymous namespace)::X86_64<llvm::object::ELFType<(llvm::support::endianness)1, true> >::relaxGotNoPic(unsigned char*, unsigned long long, unsigned char, unsigned char) const
Line
Count
Source
371
9
                                 uint8_t ModRm) const {
372
9
  const uint8_t Rex = Loc[-3];
373
9
  // Convert "test %reg, foo@GOTPCREL(%rip)" to "test $foo, %reg".
374
9
  if (Op == 0x85) {
375
1
    // See "TEST-Logical Compare" (4-428 Vol. 2B),
376
1
    // TEST r/m64, r64 uses "full" ModR / M byte (no opcode extension).
377
1
378
1
    // ModR/M byte has form XX YYY ZZZ, where
379
1
    // YYY is MODRM.reg(register 2), ZZZ is MODRM.rm(register 1).
380
1
    // XX has different meanings:
381
1
    // 00: The operand's memory address is in reg1.
382
1
    // 01: The operand's memory address is reg1 + a byte-sized displacement.
383
1
    // 10: The operand's memory address is reg1 + a word-sized displacement.
384
1
    // 11: The operand is reg1 itself.
385
1
    // If an instruction requires only one operand, the unused reg2 field
386
1
    // holds extra opcode bits rather than a register code
387
1
    // 0xC0 == 11 000 000 binary.
388
1
    // 0x38 == 00 111 000 binary.
389
1
    // We transfer reg2 to reg1 here as operand.
390
1
    // See "2.1.3 ModR/M and SIB Bytes" (Vol. 2A 2-3).
391
1
    Loc[-1] = 0xc0 | (ModRm & 0x38) >> 3; // ModR/M byte.
392
1
393
1
    // Change opcode from TEST r/m64, r64 to TEST r/m64, imm32
394
1
    // See "TEST-Logical Compare" (4-428 Vol. 2B).
395
1
    Loc[-2] = 0xf7;
396
1
397
1
    // Move R bit to the B bit in REX byte.
398
1
    // REX byte is encoded as 0100WRXB, where
399
1
    // 0100 is 4bit fixed pattern.
400
1
    // REX.W When 1, a 64-bit operand size is used. Otherwise, when 0, the
401
1
    //   default operand size is used (which is 32-bit for most but not all
402
1
    //   instructions).
403
1
    // REX.R This 1-bit value is an extension to the MODRM.reg field.
404
1
    // REX.X This 1-bit value is an extension to the SIB.index field.
405
1
    // REX.B This 1-bit value is an extension to the MODRM.rm field or the
406
1
    // SIB.base field.
407
1
    // See "2.2.1.2 More on REX Prefix Fields " (2-8 Vol. 2A).
408
1
    Loc[-3] = (Rex & ~0x4) | (Rex & 0x4) >> 2;
409
1
    write32le(Loc, Val);
410
1
    return;
411
1
  }
412
8
413
8
  // If we are here then we need to relax the adc, add, and, cmp, or, sbb, sub
414
8
  // or xor operations.
415
8
416
8
  // Convert "binop foo@GOTPCREL(%rip), %reg" to "binop $foo, %reg".
417
8
  // Logic is close to one for test instruction above, but we also
418
8
  // write opcode extension here, see below for details.
419
8
  Loc[-1] = 0xc0 | (ModRm & 0x38) >> 3 | (Op & 0x3c); // ModR/M byte.
420
8
421
8
  // Primary opcode is 0x81, opcode extension is one of:
422
8
  // 000b = ADD, 001b is OR, 010b is ADC, 011b is SBB,
423
8
  // 100b is AND, 101b is SUB, 110b is XOR, 111b is CMP.
424
8
  // This value was wrote to MODRM.reg in a line above.
425
8
  // See "3.2 INSTRUCTIONS (A-M)" (Vol. 2A 3-15),
426
8
  // "INSTRUCTION SET REFERENCE, N-Z" (Vol. 2B 4-1) for
427
8
  // descriptions about each operation.
428
8
  Loc[-2] = 0x81;
429
8
  Loc[-3] = (Rex & ~0x4) | (Rex & 0x4) >> 2;
430
8
  write32le(Loc, Val);
431
8
}
432
433
template <class ELFT>
434
32
void X86_64<ELFT>::relaxGot(uint8_t *Loc, uint64_t Val) const {
435
32
  const uint8_t Op = Loc[-2];
436
32
  const uint8_t ModRm = Loc[-1];
437
32
438
32
  // Convert "mov foo@GOTPCREL(%rip),%reg" to "lea foo(%rip),%reg".
439
32
  if (Op == 0x8b) {
440
15
    Loc[-2] = 0x8d;
441
15
    write32le(Loc, Val);
442
15
    return;
443
15
  }
444
17
445
17
  if (Op != 0xff) {
446
9
    // We are relaxing a rip relative to an absolute, so compensate
447
9
    // for the old -4 addend.
448
9
    assert(!Config->Pic);
449
9
    relaxGotNoPic(Loc, Val + 4, Op, ModRm);
450
9
    return;
451
9
  }
452
8
453
8
  // Convert call/jmp instructions.
454
8
  if (ModRm == 0x15) {
455
4
    // ABI says we can convert "call *foo@GOTPCREL(%rip)" to "nop; call foo".
456
4
    // Instead we convert to "addr32 call foo" where addr32 is an instruction
457
4
    // prefix. That makes result expression to be a single instruction.
458
4
    Loc[-2] = 0x67; // addr32 prefix
459
4
    Loc[-1] = 0xe8; // call
460
4
    write32le(Loc, Val);
461
4
    return;
462
4
  }
463
4
464
4
  // Convert "jmp *foo@GOTPCREL(%rip)" to "jmp foo; nop".
465
4
  // jmp doesn't return, so it is fine to use nop here, it is just a stub.
466
4
  assert(ModRm == 0x25);
467
4
  Loc[-2] = 0xe9; // jmp
468
4
  Loc[3] = 0x90;  // nop
469
4
  write32le(Loc - 1, Val + 1);
470
4
}
Unexecuted instantiation: X86_64.cpp:(anonymous namespace)::X86_64<llvm::object::ELFType<(llvm::support::endianness)1, false> >::relaxGot(unsigned char*, unsigned long long) const
X86_64.cpp:(anonymous namespace)::X86_64<llvm::object::ELFType<(llvm::support::endianness)1, true> >::relaxGot(unsigned char*, unsigned long long) const
Line
Count
Source
434
32
void X86_64<ELFT>::relaxGot(uint8_t *Loc, uint64_t Val) const {
435
32
  const uint8_t Op = Loc[-2];
436
32
  const uint8_t ModRm = Loc[-1];
437
32
438
32
  // Convert "mov foo@GOTPCREL(%rip),%reg" to "lea foo(%rip),%reg".
439
32
  if (Op == 0x8b) {
440
15
    Loc[-2] = 0x8d;
441
15
    write32le(Loc, Val);
442
15
    return;
443
15
  }
444
17
445
17
  if (Op != 0xff) {
446
9
    // We are relaxing a rip relative to an absolute, so compensate
447
9
    // for the old -4 addend.
448
9
    assert(!Config->Pic);
449
9
    relaxGotNoPic(Loc, Val + 4, Op, ModRm);
450
9
    return;
451
9
  }
452
8
453
8
  // Convert call/jmp instructions.
454
8
  if (ModRm == 0x15) {
455
4
    // ABI says we can convert "call *foo@GOTPCREL(%rip)" to "nop; call foo".
456
4
    // Instead we convert to "addr32 call foo" where addr32 is an instruction
457
4
    // prefix. That makes result expression to be a single instruction.
458
4
    Loc[-2] = 0x67; // addr32 prefix
459
4
    Loc[-1] = 0xe8; // call
460
4
    write32le(Loc, Val);
461
4
    return;
462
4
  }
463
4
464
4
  // Convert "jmp *foo@GOTPCREL(%rip)" to "jmp foo; nop".
465
4
  // jmp doesn't return, so it is fine to use nop here, it is just a stub.
466
4
  assert(ModRm == 0x25);
467
4
  Loc[-2] = 0xe9; // jmp
468
4
  Loc[3] = 0x90;  // nop
469
4
  write32le(Loc - 1, Val + 1);
470
4
}
471
472
// These nonstandard PLT entries are to migtigate Spectre v2 security
473
// vulnerability. In order to mitigate Spectre v2, we want to avoid indirect
474
// branch instructions such as `jmp *GOTPLT(%rip)`. So, in the following PLT
475
// entries, we use a CALL followed by MOV and RET to do the same thing as an
476
// indirect jump. That instruction sequence is so-called "retpoline".
477
//
478
// We have two types of retpoline PLTs as a size optimization. If `-z now`
479
// is specified, all dynamic symbols are resolved at load-time. Thus, when
480
// that option is given, we can omit code for symbol lazy resolution.
481
namespace {
482
template <class ELFT> class Retpoline : public X86_64<ELFT> {
483
public:
484
  Retpoline();
485
  void writeGotPlt(uint8_t *Buf, const Symbol &S) const override;
486
  void writePltHeader(uint8_t *Buf) const override;
487
  void writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr, uint64_t PltEntryAddr,
488
                int32_t Index, unsigned RelOff) const override;
489
};
490
491
template <class ELFT> class RetpolineZNow : public X86_64<ELFT> {
492
public:
493
  RetpolineZNow();
494
4
  void writeGotPlt(uint8_t *Buf, const Symbol &S) const override {}
Unexecuted instantiation: X86_64.cpp:(anonymous namespace)::RetpolineZNow<llvm::object::ELFType<(llvm::support::endianness)1, false> >::writeGotPlt(unsigned char*, lld::elf::Symbol const&) const
X86_64.cpp:(anonymous namespace)::RetpolineZNow<llvm::object::ELFType<(llvm::support::endianness)1, true> >::writeGotPlt(unsigned char*, lld::elf::Symbol const&) const
Line
Count
Source
494
4
  void writeGotPlt(uint8_t *Buf, const Symbol &S) const override {}
495
  void writePltHeader(uint8_t *Buf) const override;
496
  void writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr, uint64_t PltEntryAddr,
497
                int32_t Index, unsigned RelOff) const override;
498
};
499
} // namespace
500
501
3
template <class ELFT> Retpoline<ELFT>::Retpoline() {
502
3
  TargetInfo::PltHeaderSize = 48;
503
3
  TargetInfo::PltEntrySize = 32;
504
3
}
Unexecuted instantiation: X86_64.cpp:(anonymous namespace)::Retpoline<llvm::object::ELFType<(llvm::support::endianness)1, false> >::Retpoline()
X86_64.cpp:(anonymous namespace)::Retpoline<llvm::object::ELFType<(llvm::support::endianness)1, true> >::Retpoline()
Line
Count
Source
501
3
template <class ELFT> Retpoline<ELFT>::Retpoline() {
502
3
  TargetInfo::PltHeaderSize = 48;
503
3
  TargetInfo::PltEntrySize = 32;
504
3
}
505
506
template <class ELFT>
507
5
void Retpoline<ELFT>::writeGotPlt(uint8_t *Buf, const Symbol &S) const {
508
5
  write64le(Buf, S.getPltVA() + 17);
509
5
}
Unexecuted instantiation: X86_64.cpp:(anonymous namespace)::Retpoline<llvm::object::ELFType<(llvm::support::endianness)1, false> >::writeGotPlt(unsigned char*, lld::elf::Symbol const&) const
X86_64.cpp:(anonymous namespace)::Retpoline<llvm::object::ELFType<(llvm::support::endianness)1, true> >::writeGotPlt(unsigned char*, lld::elf::Symbol const&) const
Line
Count
Source
507
5
void Retpoline<ELFT>::writeGotPlt(uint8_t *Buf, const Symbol &S) const {
508
5
  write64le(Buf, S.getPltVA() + 17);
509
5
}
510
511
3
template <class ELFT> void Retpoline<ELFT>::writePltHeader(uint8_t *Buf) const {
512
3
  const uint8_t Insn[] = {
513
3
      0xff, 0x35, 0,    0,    0,    0,          // 0:    pushq GOTPLT+8(%rip)
514
3
      0x4c, 0x8b, 0x1d, 0,    0,    0,    0,    // 6:    mov GOTPLT+16(%rip), %r11
515
3
      0xe8, 0x0e, 0x00, 0x00, 0x00,             // d:    callq next
516
3
      0xf3, 0x90,                               // 12: loop: pause
517
3
      0x0f, 0xae, 0xe8,                         // 14:   lfence
518
3
      0xeb, 0xf9,                               // 17:   jmp loop
519
3
      0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, // 19:   int3; .align 16
520
3
      0x4c, 0x89, 0x1c, 0x24,                   // 20: next: mov %r11, (%rsp)
521
3
      0xc3,                                     // 24:   ret
522
3
      0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, // 25:   int3; padding
523
3
      0xcc, 0xcc, 0xcc, 0xcc,                   // 2c:   int3; padding
524
3
  };
525
3
  memcpy(Buf, Insn, sizeof(Insn));
526
3
527
3
  uint64_t GotPlt = InX::GotPlt->getVA();
528
3
  uint64_t Plt = InX::Plt->getVA();
529
3
  write32le(Buf + 2, GotPlt - Plt - 6 + 8);
530
3
  write32le(Buf + 9, GotPlt - Plt - 13 + 16);
531
3
}
Unexecuted instantiation: X86_64.cpp:(anonymous namespace)::Retpoline<llvm::object::ELFType<(llvm::support::endianness)1, false> >::writePltHeader(unsigned char*) const
X86_64.cpp:(anonymous namespace)::Retpoline<llvm::object::ELFType<(llvm::support::endianness)1, true> >::writePltHeader(unsigned char*) const
Line
Count
Source
511
3
template <class ELFT> void Retpoline<ELFT>::writePltHeader(uint8_t *Buf) const {
512
3
  const uint8_t Insn[] = {
513
3
      0xff, 0x35, 0,    0,    0,    0,          // 0:    pushq GOTPLT+8(%rip)
514
3
      0x4c, 0x8b, 0x1d, 0,    0,    0,    0,    // 6:    mov GOTPLT+16(%rip), %r11
515
3
      0xe8, 0x0e, 0x00, 0x00, 0x00,             // d:    callq next
516
3
      0xf3, 0x90,                               // 12: loop: pause
517
3
      0x0f, 0xae, 0xe8,                         // 14:   lfence
518
3
      0xeb, 0xf9,                               // 17:   jmp loop
519
3
      0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, // 19:   int3; .align 16
520
3
      0x4c, 0x89, 0x1c, 0x24,                   // 20: next: mov %r11, (%rsp)
521
3
      0xc3,                                     // 24:   ret
522
3
      0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, // 25:   int3; padding
523
3
      0xcc, 0xcc, 0xcc, 0xcc,                   // 2c:   int3; padding
524
3
  };
525
3
  memcpy(Buf, Insn, sizeof(Insn));
526
3
527
3
  uint64_t GotPlt = InX::GotPlt->getVA();
528
3
  uint64_t Plt = InX::Plt->getVA();
529
3
  write32le(Buf + 2, GotPlt - Plt - 6 + 8);
530
3
  write32le(Buf + 9, GotPlt - Plt - 13 + 16);
531
3
}
532
533
template <class ELFT>
534
void Retpoline<ELFT>::writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr,
535
                               uint64_t PltEntryAddr, int32_t Index,
536
5
                               unsigned RelOff) const {
537
5
  const uint8_t Insn[] = {
538
5
      0x4c, 0x8b, 0x1d, 0, 0, 0, 0, // 0:  mov foo@GOTPLT(%rip), %r11
539
5
      0xe8, 0,    0,    0,    0,    // 7:  callq plt+0x20
540
5
      0xe9, 0,    0,    0,    0,    // c:  jmp plt+0x12
541
5
      0x68, 0,    0,    0,    0,    // 11: pushq <relocation index>
542
5
      0xe9, 0,    0,    0,    0,    // 16: jmp plt+0
543
5
      0xcc, 0xcc, 0xcc, 0xcc, 0xcc, // 1b: int3; padding
544
5
  };
545
5
  memcpy(Buf, Insn, sizeof(Insn));
546
5
547
5
  uint64_t Off = TargetInfo::getPltEntryOffset(Index);
548
5
549
5
  write32le(Buf + 3, GotPltEntryAddr - PltEntryAddr - 7);
550
5
  write32le(Buf + 8, -Off - 12 + 32);
551
5
  write32le(Buf + 13, -Off - 17 + 18);
552
5
  write32le(Buf + 18, Index);
553
5
  write32le(Buf + 23, -Off - 27);
554
5
}
Unexecuted instantiation: X86_64.cpp:(anonymous namespace)::Retpoline<llvm::object::ELFType<(llvm::support::endianness)1, false> >::writePlt(unsigned char*, unsigned long long, unsigned long long, int, unsigned int) const
X86_64.cpp:(anonymous namespace)::Retpoline<llvm::object::ELFType<(llvm::support::endianness)1, true> >::writePlt(unsigned char*, unsigned long long, unsigned long long, int, unsigned int) const
Line
Count
Source
536
5
                               unsigned RelOff) const {
537
5
  const uint8_t Insn[] = {
538
5
      0x4c, 0x8b, 0x1d, 0, 0, 0, 0, // 0:  mov foo@GOTPLT(%rip), %r11
539
5
      0xe8, 0,    0,    0,    0,    // 7:  callq plt+0x20
540
5
      0xe9, 0,    0,    0,    0,    // c:  jmp plt+0x12
541
5
      0x68, 0,    0,    0,    0,    // 11: pushq <relocation index>
542
5
      0xe9, 0,    0,    0,    0,    // 16: jmp plt+0
543
5
      0xcc, 0xcc, 0xcc, 0xcc, 0xcc, // 1b: int3; padding
544
5
  };
545
5
  memcpy(Buf, Insn, sizeof(Insn));
546
5
547
5
  uint64_t Off = TargetInfo::getPltEntryOffset(Index);
548
5
549
5
  write32le(Buf + 3, GotPltEntryAddr - PltEntryAddr - 7);
550
5
  write32le(Buf + 8, -Off - 12 + 32);
551
5
  write32le(Buf + 13, -Off - 17 + 18);
552
5
  write32le(Buf + 18, Index);
553
5
  write32le(Buf + 23, -Off - 27);
554
5
}
555
556
2
template <class ELFT> RetpolineZNow<ELFT>::RetpolineZNow() {
557
2
  TargetInfo::PltHeaderSize = 32;
558
2
  TargetInfo::PltEntrySize = 16;
559
2
}
Unexecuted instantiation: X86_64.cpp:(anonymous namespace)::RetpolineZNow<llvm::object::ELFType<(llvm::support::endianness)1, false> >::RetpolineZNow()
X86_64.cpp:(anonymous namespace)::RetpolineZNow<llvm::object::ELFType<(llvm::support::endianness)1, true> >::RetpolineZNow()
Line
Count
Source
556
2
template <class ELFT> RetpolineZNow<ELFT>::RetpolineZNow() {
557
2
  TargetInfo::PltHeaderSize = 32;
558
2
  TargetInfo::PltEntrySize = 16;
559
2
}
560
561
template <class ELFT>
562
2
void RetpolineZNow<ELFT>::writePltHeader(uint8_t *Buf) const {
563
2
  const uint8_t Insn[] = {
564
2
      0xe8, 0x0b, 0x00, 0x00, 0x00, // 0:    call next
565
2
      0xf3, 0x90,                   // 5:  loop: pause
566
2
      0x0f, 0xae, 0xe8,             // 7:    lfence
567
2
      0xeb, 0xf9,                   // a:    jmp loop
568
2
      0xcc, 0xcc, 0xcc, 0xcc,       // c:    int3; .align 16
569
2
      0x4c, 0x89, 0x1c, 0x24,       // 10: next: mov %r11, (%rsp)
570
2
      0xc3,                         // 14:   ret
571
2
      0xcc, 0xcc, 0xcc, 0xcc, 0xcc, // 15:   int3; padding
572
2
      0xcc, 0xcc, 0xcc, 0xcc, 0xcc, // 1a:   int3; padding
573
2
      0xcc,                         // 1f:   int3; padding
574
2
  };
575
2
  memcpy(Buf, Insn, sizeof(Insn));
576
2
}
Unexecuted instantiation: X86_64.cpp:(anonymous namespace)::RetpolineZNow<llvm::object::ELFType<(llvm::support::endianness)1, false> >::writePltHeader(unsigned char*) const
X86_64.cpp:(anonymous namespace)::RetpolineZNow<llvm::object::ELFType<(llvm::support::endianness)1, true> >::writePltHeader(unsigned char*) const
Line
Count
Source
562
2
void RetpolineZNow<ELFT>::writePltHeader(uint8_t *Buf) const {
563
2
  const uint8_t Insn[] = {
564
2
      0xe8, 0x0b, 0x00, 0x00, 0x00, // 0:    call next
565
2
      0xf3, 0x90,                   // 5:  loop: pause
566
2
      0x0f, 0xae, 0xe8,             // 7:    lfence
567
2
      0xeb, 0xf9,                   // a:    jmp loop
568
2
      0xcc, 0xcc, 0xcc, 0xcc,       // c:    int3; .align 16
569
2
      0x4c, 0x89, 0x1c, 0x24,       // 10: next: mov %r11, (%rsp)
570
2
      0xc3,                         // 14:   ret
571
2
      0xcc, 0xcc, 0xcc, 0xcc, 0xcc, // 15:   int3; padding
572
2
      0xcc, 0xcc, 0xcc, 0xcc, 0xcc, // 1a:   int3; padding
573
2
      0xcc,                         // 1f:   int3; padding
574
2
  };
575
2
  memcpy(Buf, Insn, sizeof(Insn));
576
2
}
577
578
template <class ELFT>
579
void RetpolineZNow<ELFT>::writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr,
580
                                   uint64_t PltEntryAddr, int32_t Index,
581
4
                                   unsigned RelOff) const {
582
4
  const uint8_t Insn[] = {
583
4
      0x4c, 0x8b, 0x1d, 0,    0, 0, 0, // mov foo@GOTPLT(%rip), %r11
584
4
      0xe9, 0,    0,    0,    0,       // jmp plt+0
585
4
      0xcc, 0xcc, 0xcc, 0xcc,          // int3; padding
586
4
  };
587
4
  memcpy(Buf, Insn, sizeof(Insn));
588
4
589
4
  write32le(Buf + 3, GotPltEntryAddr - PltEntryAddr - 7);
590
4
  write32le(Buf + 8, -TargetInfo::getPltEntryOffset(Index) - 12);
591
4
}
Unexecuted instantiation: X86_64.cpp:(anonymous namespace)::RetpolineZNow<llvm::object::ELFType<(llvm::support::endianness)1, false> >::writePlt(unsigned char*, unsigned long long, unsigned long long, int, unsigned int) const
X86_64.cpp:(anonymous namespace)::RetpolineZNow<llvm::object::ELFType<(llvm::support::endianness)1, true> >::writePlt(unsigned char*, unsigned long long, unsigned long long, int, unsigned int) const
Line
Count
Source
581
4
                                   unsigned RelOff) const {
582
4
  const uint8_t Insn[] = {
583
4
      0x4c, 0x8b, 0x1d, 0,    0, 0, 0, // mov foo@GOTPLT(%rip), %r11
584
4
      0xe9, 0,    0,    0,    0,       // jmp plt+0
585
4
      0xcc, 0xcc, 0xcc, 0xcc,          // int3; padding
586
4
  };
587
4
  memcpy(Buf, Insn, sizeof(Insn));
588
4
589
4
  write32le(Buf + 3, GotPltEntryAddr - PltEntryAddr - 7);
590
4
  write32le(Buf + 8, -TargetInfo::getPltEntryOffset(Index) - 12);
591
4
}
592
593
1.62k
template <class ELFT> static TargetInfo *getTargetInfo() {
594
1.62k
  if (Config->ZRetpolineplt) {
595
5
    if (Config->ZNow) {
596
2
      static RetpolineZNow<ELFT> T;
597
2
      return &T;
598
2
    }
599
3
    static Retpoline<ELFT> T;
600
3
    return &T;
601
3
  }
602
1.61k
603
1.61k
  static X86_64<ELFT> T;
604
1.61k
  return &T;
605
1.61k
}
X86_64.cpp:lld::elf::TargetInfo* getTargetInfo<llvm::object::ELFType<(llvm::support::endianness)1, false> >()
Line
Count
Source
593
3
template <class ELFT> static TargetInfo *getTargetInfo() {
594
3
  if (Config->ZRetpolineplt) {
595
0
    if (Config->ZNow) {
596
0
      static RetpolineZNow<ELFT> T;
597
0
      return &T;
598
0
    }
599
0
    static Retpoline<ELFT> T;
600
0
    return &T;
601
0
  }
602
3
603
3
  static X86_64<ELFT> T;
604
3
  return &T;
605
3
}
X86_64.cpp:lld::elf::TargetInfo* getTargetInfo<llvm::object::ELFType<(llvm::support::endianness)1, true> >()
Line
Count
Source
593
1.61k
template <class ELFT> static TargetInfo *getTargetInfo() {
594
1.61k
  if (Config->ZRetpolineplt) {
595
5
    if (Config->ZNow) {
596
2
      static RetpolineZNow<ELFT> T;
597
2
      return &T;
598
2
    }
599
3
    static Retpoline<ELFT> T;
600
3
    return &T;
601
3
  }
602
1.61k
603
1.61k
  static X86_64<ELFT> T;
604
1.61k
  return &T;
605
1.61k
}
606
607
3
TargetInfo *elf::getX32TargetInfo() { return getTargetInfo<ELF32LE>(); }
608
1.61k
TargetInfo *elf::getX86_64TargetInfo() { return getTargetInfo<ELF64LE>(); }