Coverage Report

Created: 2019-01-18 03:29

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