Coverage Report

Created: 2018-01-17 21:32

/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 final : public TargetInfo {
27
public:
28
  X86_64();
29
  RelExpr getRelExpr(RelType Type, const Symbol &S,
30
                     const uint8_t *Loc) const override;
31
  bool isPicRel(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
713
template <class ELFT> X86_64<ELFT>::X86_64() {
54
713
  GotBaseSymOff = -1;
55
713
  CopyRel = R_X86_64_COPY;
56
713
  GotRel = R_X86_64_GLOB_DAT;
57
713
  PltRel = R_X86_64_JUMP_SLOT;
58
713
  RelativeRel = R_X86_64_RELATIVE;
59
713
  IRelativeRel = R_X86_64_IRELATIVE;
60
713
  TlsGotRel = R_X86_64_TPOFF64;
61
713
  TlsModuleIndexRel = R_X86_64_DTPMOD64;
62
713
  TlsOffsetRel = R_X86_64_DTPOFF64;
63
713
  GotEntrySize = 8;
64
713
  GotPltEntrySize = 8;
65
713
  PltEntrySize = 16;
66
713
  PltHeaderSize = 16;
67
713
  TlsGdRelaxSkip = 2;
68
713
  TrapInstr = 0xcccccccc; // 0xcc = INT3
69
713
70
713
  // Align to the large page size (known as a superpage or huge page).
71
713
  // FreeBSD automatically promotes large, superpage-aligned allocations.
72
713
  DefaultImageBase = 0x200000;
73
713
}
X86_64.cpp:(anonymous namespace)::X86_64<llvm::object::ELFType<(llvm::support::endianness)1, false> >::X86_64()
Line
Count
Source
53
1
template <class ELFT> X86_64<ELFT>::X86_64() {
54
1
  GotBaseSymOff = -1;
55
1
  CopyRel = R_X86_64_COPY;
56
1
  GotRel = R_X86_64_GLOB_DAT;
57
1
  PltRel = R_X86_64_JUMP_SLOT;
58
1
  RelativeRel = R_X86_64_RELATIVE;
59
1
  IRelativeRel = R_X86_64_IRELATIVE;
60
1
  TlsGotRel = R_X86_64_TPOFF64;
61
1
  TlsModuleIndexRel = R_X86_64_DTPMOD64;
62
1
  TlsOffsetRel = R_X86_64_DTPOFF64;
63
1
  GotEntrySize = 8;
64
1
  GotPltEntrySize = 8;
65
1
  PltEntrySize = 16;
66
1
  PltHeaderSize = 16;
67
1
  TlsGdRelaxSkip = 2;
68
1
  TrapInstr = 0xcccccccc; // 0xcc = INT3
69
1
70
1
  // Align to the large page size (known as a superpage or huge page).
71
1
  // FreeBSD automatically promotes large, superpage-aligned allocations.
72
1
  DefaultImageBase = 0x200000;
73
1
}
X86_64.cpp:(anonymous namespace)::X86_64<llvm::object::ELFType<(llvm::support::endianness)1, true> >::X86_64()
Line
Count
Source
53
712
template <class ELFT> X86_64<ELFT>::X86_64() {
54
712
  GotBaseSymOff = -1;
55
712
  CopyRel = R_X86_64_COPY;
56
712
  GotRel = R_X86_64_GLOB_DAT;
57
712
  PltRel = R_X86_64_JUMP_SLOT;
58
712
  RelativeRel = R_X86_64_RELATIVE;
59
712
  IRelativeRel = R_X86_64_IRELATIVE;
60
712
  TlsGotRel = R_X86_64_TPOFF64;
61
712
  TlsModuleIndexRel = R_X86_64_DTPMOD64;
62
712
  TlsOffsetRel = R_X86_64_DTPOFF64;
63
712
  GotEntrySize = 8;
64
712
  GotPltEntrySize = 8;
65
712
  PltEntrySize = 16;
66
712
  PltHeaderSize = 16;
67
712
  TlsGdRelaxSkip = 2;
68
712
  TrapInstr = 0xcccccccc; // 0xcc = INT3
69
712
70
712
  // Align to the large page size (known as a superpage or huge page).
71
712
  // FreeBSD automatically promotes large, superpage-aligned allocations.
72
712
  DefaultImageBase = 0x200000;
73
712
}
74
75
template <class ELFT>
76
RelExpr X86_64<ELFT>::getRelExpr(RelType Type, const Symbol &S,
77
572
                                 const uint8_t *Loc) const {
78
572
  switch (Type) {
79
572
  case R_X86_64_8:
80
209
  case R_X86_64_16:
81
209
  case R_X86_64_32:
82
209
  case R_X86_64_32S:
83
209
  case R_X86_64_64:
84
209
  case R_X86_64_DTPOFF32:
85
209
  case R_X86_64_DTPOFF64:
86
209
    return R_ABS;
87
209
  case R_X86_64_TPOFF32:
88
4
    return R_TLS;
89
209
  case R_X86_64_TLSLD:
90
2
    return R_TLSLD_PC;
91
209
  case R_X86_64_TLSGD:
92
5
    return R_TLSGD_PC;
93
209
  case R_X86_64_SIZE32:
94
12
  case R_X86_64_SIZE64:
95
12
    return R_SIZE;
96
94
  case R_X86_64_PLT32:
97
94
    return R_PLT_PC;
98
188
  case R_X86_64_PC32:
99
188
  case R_X86_64_PC64:
100
188
    return R_PC;
101
188
  case R_X86_64_GOT32:
102
4
  case R_X86_64_GOT64:
103
4
    return R_GOT_FROM_END;
104
51
  case R_X86_64_GOTPCREL:
105
51
  case R_X86_64_GOTPCRELX:
106
51
  case R_X86_64_REX_GOTPCRELX:
107
51
  case R_X86_64_GOTTPOFF:
108
51
    return R_GOT_PC;
109
51
  case R_X86_64_NONE:
110
1
    return R_NONE;
111
51
  default:
112
2
    return R_INVALID;
113
0
  }
114
0
}
Unexecuted instantiation: 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
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
77
572
                                 const uint8_t *Loc) const {
78
572
  switch (Type) {
79
572
  case R_X86_64_8:
80
209
  case R_X86_64_16:
81
209
  case R_X86_64_32:
82
209
  case R_X86_64_32S:
83
209
  case R_X86_64_64:
84
209
  case R_X86_64_DTPOFF32:
85
209
  case R_X86_64_DTPOFF64:
86
209
    return R_ABS;
87
209
  case R_X86_64_TPOFF32:
88
4
    return R_TLS;
89
209
  case R_X86_64_TLSLD:
90
2
    return R_TLSLD_PC;
91
209
  case R_X86_64_TLSGD:
92
5
    return R_TLSGD_PC;
93
209
  case R_X86_64_SIZE32:
94
12
  case R_X86_64_SIZE64:
95
12
    return R_SIZE;
96
94
  case R_X86_64_PLT32:
97
94
    return R_PLT_PC;
98
188
  case R_X86_64_PC32:
99
188
  case R_X86_64_PC64:
100
188
    return R_PC;
101
188
  case R_X86_64_GOT32:
102
4
  case R_X86_64_GOT64:
103
4
    return R_GOT_FROM_END;
104
51
  case R_X86_64_GOTPCREL:
105
51
  case R_X86_64_GOTPCRELX:
106
51
  case R_X86_64_REX_GOTPCRELX:
107
51
  case R_X86_64_GOTTPOFF:
108
51
    return R_GOT_PC;
109
51
  case R_X86_64_NONE:
110
1
    return R_NONE;
111
51
  default:
112
2
    return R_INVALID;
113
0
  }
114
0
}
115
116
65
template <class ELFT> void X86_64<ELFT>::writeGotPltHeader(uint8_t *Buf) const {
117
65
  // The first entry holds the value of _DYNAMIC. It is not clear why that is
118
65
  // required, but it is documented in the psabi and the glibc dynamic linker
119
65
  // seems to use it (note that this is relevant for linking ld.so, not any
120
65
  // other program).
121
65
  write64le(Buf, InX::Dynamic->getVA());
122
65
}
Unexecuted instantiation: X86_64.cpp:(anonymous namespace)::X86_64<llvm::object::ELFType<(llvm::support::endianness)1, false> >::writeGotPltHeader(unsigned char*) const
X86_64.cpp:(anonymous namespace)::X86_64<llvm::object::ELFType<(llvm::support::endianness)1, true> >::writeGotPltHeader(unsigned char*) const
Line
Count
Source
116
65
template <class ELFT> void X86_64<ELFT>::writeGotPltHeader(uint8_t *Buf) const {
117
65
  // The first entry holds the value of _DYNAMIC. It is not clear why that is
118
65
  // required, but it is documented in the psabi and the glibc dynamic linker
119
65
  // seems to use it (note that this is relevant for linking ld.so, not any
120
65
  // other program).
121
65
  write64le(Buf, InX::Dynamic->getVA());
122
65
}
123
124
template <class ELFT>
125
96
void X86_64<ELFT>::writeGotPlt(uint8_t *Buf, const Symbol &S) const {
126
96
  // See comments in X86::writeGotPlt.
127
96
  write32le(Buf, S.getPltVA() + 6);
128
96
}
Unexecuted instantiation: X86_64.cpp:(anonymous namespace)::X86_64<llvm::object::ELFType<(llvm::support::endianness)1, false> >::writeGotPlt(unsigned char*, lld::elf::Symbol const&) const
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
125
96
void X86_64<ELFT>::writeGotPlt(uint8_t *Buf, const Symbol &S) const {
126
96
  // See comments in X86::writeGotPlt.
127
96
  write32le(Buf, S.getPltVA() + 6);
128
96
}
129
130
65
template <class ELFT> void X86_64<ELFT>::writePltHeader(uint8_t *Buf) const {
131
65
  const uint8_t PltData[] = {
132
65
      0xff, 0x35, 0, 0, 0, 0, // pushq GOTPLT+8(%rip)
133
65
      0xff, 0x25, 0, 0, 0, 0, // jmp *GOTPLT+16(%rip)
134
65
      0x0f, 0x1f, 0x40, 0x00, // nop
135
65
  };
136
65
  memcpy(Buf, PltData, sizeof(PltData));
137
65
  uint64_t GotPlt = InX::GotPlt->getVA();
138
65
  uint64_t Plt = InX::Plt->getVA();
139
65
  write32le(Buf + 2, GotPlt - Plt + 2); // GOTPLT+8
140
65
  write32le(Buf + 8, GotPlt - Plt + 4); // GOTPLT+16
141
65
}
Unexecuted instantiation: X86_64.cpp:(anonymous namespace)::X86_64<llvm::object::ELFType<(llvm::support::endianness)1, false> >::writePltHeader(unsigned char*) const
X86_64.cpp:(anonymous namespace)::X86_64<llvm::object::ELFType<(llvm::support::endianness)1, true> >::writePltHeader(unsigned char*) const
Line
Count
Source
130
65
template <class ELFT> void X86_64<ELFT>::writePltHeader(uint8_t *Buf) const {
131
65
  const uint8_t PltData[] = {
132
65
      0xff, 0x35, 0, 0, 0, 0, // pushq GOTPLT+8(%rip)
133
65
      0xff, 0x25, 0, 0, 0, 0, // jmp *GOTPLT+16(%rip)
134
65
      0x0f, 0x1f, 0x40, 0x00, // nop
135
65
  };
136
65
  memcpy(Buf, PltData, sizeof(PltData));
137
65
  uint64_t GotPlt = InX::GotPlt->getVA();
138
65
  uint64_t Plt = InX::Plt->getVA();
139
65
  write32le(Buf + 2, GotPlt - Plt + 2); // GOTPLT+8
140
65
  write32le(Buf + 8, GotPlt - Plt + 4); // GOTPLT+16
141
65
}
142
143
template <class ELFT>
144
void X86_64<ELFT>::writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr,
145
                            uint64_t PltEntryAddr, int32_t Index,
146
96
                            unsigned RelOff) const {
147
96
  const uint8_t Inst[] = {
148
96
      0xff, 0x25, 0, 0, 0, 0, // jmpq *got(%rip)
149
96
      0x68, 0, 0, 0, 0,       // pushq <relocation index>
150
96
      0xe9, 0, 0, 0, 0,       // jmpq plt[0]
151
96
  };
152
96
  memcpy(Buf, Inst, sizeof(Inst));
153
96
154
96
  write32le(Buf + 2, GotPltEntryAddr - PltEntryAddr - 6);
155
96
  write32le(Buf + 7, Index);
156
96
  write32le(Buf + 12, -Index * PltEntrySize - PltHeaderSize - 16);
157
96
}
Unexecuted instantiation: 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
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
146
96
                            unsigned RelOff) const {
147
96
  const uint8_t Inst[] = {
148
96
      0xff, 0x25, 0, 0, 0, 0, // jmpq *got(%rip)
149
96
      0x68, 0, 0, 0, 0,       // pushq <relocation index>
150
96
      0xe9, 0, 0, 0, 0,       // jmpq plt[0]
151
96
  };
152
96
  memcpy(Buf, Inst, sizeof(Inst));
153
96
154
96
  write32le(Buf + 2, GotPltEntryAddr - PltEntryAddr - 6);
155
96
  write32le(Buf + 7, Index);
156
96
  write32le(Buf + 12, -Index * PltEntrySize - PltHeaderSize - 16);
157
96
}
158
159
35
template <class ELFT> bool X86_64<ELFT>::isPicRel(RelType Type) const {
160
35
  return Type != R_X86_64_PC32 && 
Type != R_X86_64_3234
&&
161
35
         
Type != R_X86_64_TPOFF3231
;
162
35
}
Unexecuted instantiation: X86_64.cpp:(anonymous namespace)::X86_64<llvm::object::ELFType<(llvm::support::endianness)1, false> >::isPicRel(unsigned int) const
X86_64.cpp:(anonymous namespace)::X86_64<llvm::object::ELFType<(llvm::support::endianness)1, true> >::isPicRel(unsigned int) const
Line
Count
Source
159
35
template <class ELFT> bool X86_64<ELFT>::isPicRel(RelType Type) const {
160
35
  return Type != R_X86_64_PC32 && 
Type != R_X86_64_3234
&&
161
35
         
Type != R_X86_64_TPOFF3231
;
162
35
}
163
164
template <class ELFT>
165
void X86_64<ELFT>::relaxTlsGdToLe(uint8_t *Loc, RelType Type,
166
2
                                  uint64_t Val) const {
167
2
  // Convert
168
2
  //   .byte 0x66
169
2
  //   leaq x@tlsgd(%rip), %rdi
170
2
  //   .word 0x6666
171
2
  //   rex64
172
2
  //   call __tls_get_addr@plt
173
2
  // to
174
2
  //   mov %fs:0x0,%rax
175
2
  //   lea x@tpoff,%rax
176
2
  const uint8_t Inst[] = {
177
2
      0x64, 0x48, 0x8b, 0x04, 0x25, 0x00, 0x00, 0x00, 0x00, // mov %fs:0x0,%rax
178
2
      0x48, 0x8d, 0x80, 0, 0, 0, 0,                         // lea x@tpoff,%rax
179
2
  };
180
2
  memcpy(Loc - 4, Inst, sizeof(Inst));
181
2
182
2
  // The original code used a pc relative relocation and so we have to
183
2
  // compensate for the -4 in had in the addend.
184
2
  write32le(Loc + 8, Val + 4);
185
2
}
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
166
2
                                  uint64_t Val) const {
167
2
  // Convert
168
2
  //   .byte 0x66
169
2
  //   leaq x@tlsgd(%rip), %rdi
170
2
  //   .word 0x6666
171
2
  //   rex64
172
2
  //   call __tls_get_addr@plt
173
2
  // to
174
2
  //   mov %fs:0x0,%rax
175
2
  //   lea x@tpoff,%rax
176
2
  const uint8_t Inst[] = {
177
2
      0x64, 0x48, 0x8b, 0x04, 0x25, 0x00, 0x00, 0x00, 0x00, // mov %fs:0x0,%rax
178
2
      0x48, 0x8d, 0x80, 0, 0, 0, 0,                         // lea x@tpoff,%rax
179
2
  };
180
2
  memcpy(Loc - 4, Inst, sizeof(Inst));
181
2
182
2
  // The original code used a pc relative relocation and so we have to
183
2
  // compensate for the -4 in had in the addend.
184
2
  write32le(Loc + 8, Val + 4);
185
2
}
186
187
template <class ELFT>
188
void X86_64<ELFT>::relaxTlsGdToIe(uint8_t *Loc, RelType Type,
189
0
                                  uint64_t Val) const {
190
0
  // Convert
191
0
  //   .byte 0x66
192
0
  //   leaq x@tlsgd(%rip), %rdi
193
0
  //   .word 0x6666
194
0
  //   rex64
195
0
  //   call __tls_get_addr@plt
196
0
  // to
197
0
  //   mov %fs:0x0,%rax
198
0
  //   addq x@tpoff,%rax
199
0
  const uint8_t Inst[] = {
200
0
      0x64, 0x48, 0x8b, 0x04, 0x25, 0x00, 0x00, 0x00, 0x00, // mov %fs:0x0,%rax
201
0
      0x48, 0x03, 0x05, 0, 0, 0, 0,                         // addq x@tpoff,%rax
202
0
  };
203
0
  memcpy(Loc - 4, Inst, sizeof(Inst));
204
0
205
0
  // Both code sequences are PC relatives, but since we are moving the constant
206
0
  // forward by 8 bytes we have to subtract the value by 8.
207
0
  write32le(Loc + 8, Val - 8);
208
0
}
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
Unexecuted instantiation: X86_64.cpp:(anonymous namespace)::X86_64<llvm::object::ELFType<(llvm::support::endianness)1, true> >::relaxTlsGdToIe(unsigned char*, unsigned int, unsigned long long) const
209
210
// In some conditions, R_X86_64_GOTTPOFF relocation can be optimized to
211
// R_X86_64_TPOFF32 so that it does not use GOT.
212
template <class ELFT>
213
void X86_64<ELFT>::relaxTlsIeToLe(uint8_t *Loc, RelType Type,
214
1
                                  uint64_t Val) const {
215
1
  uint8_t *Inst = Loc - 3;
216
1
  uint8_t Reg = Loc[-1] >> 3;
217
1
  uint8_t *RegSlot = Loc - 1;
218
1
219
1
  // Note that ADD with RSP or R12 is converted to ADD instead of LEA
220
1
  // because LEA with these registers needs 4 bytes to encode and thus
221
1
  // wouldn't fit the space.
222
1
223
1
  if (memcmp(Inst, "\x48\x03\x25", 3) == 0) {
224
0
    // "addq foo@gottpoff(%rip),%rsp" -> "addq $foo,%rsp"
225
0
    memcpy(Inst, "\x48\x81\xc4", 3);
226
1
  } else if (memcmp(Inst, "\x4c\x03\x25", 3) == 0) {
227
0
    // "addq foo@gottpoff(%rip),%r12" -> "addq $foo,%r12"
228
0
    memcpy(Inst, "\x49\x81\xc4", 3);
229
1
  } else if (memcmp(Inst, "\x4c\x03", 2) == 0) {
230
0
    // "addq foo@gottpoff(%rip),%r[8-15]" -> "leaq foo(%r[8-15]),%r[8-15]"
231
0
    memcpy(Inst, "\x4d\x8d", 2);
232
0
    *RegSlot = 0x80 | (Reg << 3) | Reg;
233
1
  } else if (memcmp(Inst, "\x48\x03", 2) == 0) {
234
0
    // "addq foo@gottpoff(%rip),%reg -> "leaq foo(%reg),%reg"
235
0
    memcpy(Inst, "\x48\x8d", 2);
236
0
    *RegSlot = 0x80 | (Reg << 3) | Reg;
237
1
  } else if (memcmp(Inst, "\x4c\x8b", 2) == 0) {
238
0
    // "movq foo@gottpoff(%rip),%r[8-15]" -> "movq $foo,%r[8-15]"
239
0
    memcpy(Inst, "\x49\xc7", 2);
240
0
    *RegSlot = 0xc0 | Reg;
241
1
  } else if (memcmp(Inst, "\x48\x8b", 2) == 0) {
242
1
    // "movq foo@gottpoff(%rip),%reg" -> "movq $foo,%reg"
243
1
    memcpy(Inst, "\x48\xc7", 2);
244
1
    *RegSlot = 0xc0 | Reg;
245
1
  } else {
246
0
    error(getErrorLocation(Loc - 3) +
247
0
          "R_X86_64_GOTTPOFF must be used in MOVQ or ADDQ instructions only");
248
0
  }
249
1
250
1
  // The original code used a PC relative relocation.
251
1
  // Need to compensate for the -4 it had in the addend.
252
1
  write32le(Loc, Val + 4);
253
1
}
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
214
1
                                  uint64_t Val) const {
215
1
  uint8_t *Inst = Loc - 3;
216
1
  uint8_t Reg = Loc[-1] >> 3;
217
1
  uint8_t *RegSlot = Loc - 1;
218
1
219
1
  // Note that ADD with RSP or R12 is converted to ADD instead of LEA
220
1
  // because LEA with these registers needs 4 bytes to encode and thus
221
1
  // wouldn't fit the space.
222
1
223
1
  if (memcmp(Inst, "\x48\x03\x25", 3) == 0) {
224
0
    // "addq foo@gottpoff(%rip),%rsp" -> "addq $foo,%rsp"
225
0
    memcpy(Inst, "\x48\x81\xc4", 3);
226
1
  } else if (memcmp(Inst, "\x4c\x03\x25", 3) == 0) {
227
0
    // "addq foo@gottpoff(%rip),%r12" -> "addq $foo,%r12"
228
0
    memcpy(Inst, "\x49\x81\xc4", 3);
229
1
  } else if (memcmp(Inst, "\x4c\x03", 2) == 0) {
230
0
    // "addq foo@gottpoff(%rip),%r[8-15]" -> "leaq foo(%r[8-15]),%r[8-15]"
231
0
    memcpy(Inst, "\x4d\x8d", 2);
232
0
    *RegSlot = 0x80 | (Reg << 3) | Reg;
233
1
  } else if (memcmp(Inst, "\x48\x03", 2) == 0) {
234
0
    // "addq foo@gottpoff(%rip),%reg -> "leaq foo(%reg),%reg"
235
0
    memcpy(Inst, "\x48\x8d", 2);
236
0
    *RegSlot = 0x80 | (Reg << 3) | Reg;
237
1
  } else if (memcmp(Inst, "\x4c\x8b", 2) == 0) {
238
0
    // "movq foo@gottpoff(%rip),%r[8-15]" -> "movq $foo,%r[8-15]"
239
0
    memcpy(Inst, "\x49\xc7", 2);
240
0
    *RegSlot = 0xc0 | Reg;
241
1
  } else if (memcmp(Inst, "\x48\x8b", 2) == 0) {
242
1
    // "movq foo@gottpoff(%rip),%reg" -> "movq $foo,%reg"
243
1
    memcpy(Inst, "\x48\xc7", 2);
244
1
    *RegSlot = 0xc0 | Reg;
245
1
  } else {
246
0
    error(getErrorLocation(Loc - 3) +
247
0
          "R_X86_64_GOTTPOFF must be used in MOVQ or ADDQ instructions only");
248
0
  }
249
1
250
1
  // The original code used a PC relative relocation.
251
1
  // Need to compensate for the -4 it had in the addend.
252
1
  write32le(Loc, Val + 4);
253
1
}
254
255
template <class ELFT>
256
void X86_64<ELFT>::relaxTlsLdToLe(uint8_t *Loc, RelType Type,
257
0
                                  uint64_t Val) const {
258
0
  // Convert
259
0
  //   leaq bar@tlsld(%rip), %rdi
260
0
  //   callq __tls_get_addr@PLT
261
0
  //   leaq bar@dtpoff(%rax), %rcx
262
0
  // to
263
0
  //   .word 0x6666
264
0
  //   .byte 0x66
265
0
  //   mov %fs:0,%rax
266
0
  //   leaq bar@tpoff(%rax), %rcx
267
0
  if (Type == R_X86_64_DTPOFF64) {
268
0
    write64le(Loc, Val);
269
0
    return;
270
0
  }
271
0
  if (Type == R_X86_64_DTPOFF32) {
272
0
    write32le(Loc, Val);
273
0
    return;
274
0
  }
275
0
276
0
  const uint8_t Inst[] = {
277
0
      0x66, 0x66,                                           // .word 0x6666
278
0
      0x66,                                                 // .byte 0x66
279
0
      0x64, 0x48, 0x8b, 0x04, 0x25, 0x00, 0x00, 0x00, 0x00, // mov %fs:0,%rax
280
0
  };
281
0
  memcpy(Loc - 3, Inst, sizeof(Inst));
282
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
Unexecuted instantiation: X86_64.cpp:(anonymous namespace)::X86_64<llvm::object::ELFType<(llvm::support::endianness)1, true> >::relaxTlsLdToLe(unsigned char*, unsigned int, unsigned long long) const
283
284
template <class ELFT>
285
499
void X86_64<ELFT>::relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const {
286
499
  switch (Type) {
287
499
  case R_X86_64_8:
288
2
    checkUInt<8>(Loc, Val, Type);
289
2
    *Loc = Val;
290
2
    break;
291
499
  case R_X86_64_16:
292
2
    checkUInt<16>(Loc, Val, Type);
293
2
    write16le(Loc, Val);
294
2
    break;
295
499
  case R_X86_64_32:
296
49
    checkUInt<32>(Loc, Val, Type);
297
49
    write32le(Loc, Val);
298
49
    break;
299
499
  case R_X86_64_32S:
300
358
  case R_X86_64_TPOFF32:
301
358
  case R_X86_64_GOT32:
302
358
  case R_X86_64_GOTPCREL:
303
358
  case R_X86_64_GOTPCRELX:
304
358
  case R_X86_64_REX_GOTPCRELX:
305
358
  case R_X86_64_PC32:
306
358
  case R_X86_64_GOTTPOFF:
307
358
  case R_X86_64_PLT32:
308
358
  case R_X86_64_TLSGD:
309
358
  case R_X86_64_TLSLD:
310
358
  case R_X86_64_DTPOFF32:
311
358
  case R_X86_64_SIZE32:
312
358
    checkInt<32>(Loc, Val, Type);
313
358
    write32le(Loc, Val);
314
358
    break;
315
358
  case R_X86_64_64:
316
86
  case R_X86_64_DTPOFF64:
317
86
  case R_X86_64_GLOB_DAT:
318
86
  case R_X86_64_PC64:
319
86
  case R_X86_64_SIZE64:
320
86
  case R_X86_64_GOT64:
321
86
    write64le(Loc, Val);
322
86
    break;
323
86
  default:
324
2
    error(getErrorLocation(Loc) + "unrecognized reloc " + Twine(Type));
325
499
  }
326
499
}
327
328
template <class ELFT>
329
RelExpr X86_64<ELFT>::adjustRelaxExpr(RelType Type, const uint8_t *Data,
330
29
                                      RelExpr RelExpr) const {
331
29
  if (Type != R_X86_64_GOTPCRELX && 
Type != R_X86_64_REX_GOTPCRELX21
)
332
3
    return RelExpr;
333
26
  const uint8_t Op = Data[-2];
334
26
  const uint8_t ModRm = Data[-1];
335
26
336
26
  // FIXME: When PIC is disabled and foo is defined locally in the
337
26
  // lower 32 bit address space, memory operand in mov can be converted into
338
26
  // immediate operand. Otherwise, mov must be changed to lea. We support only
339
26
  // latter relaxation at this moment.
340
26
  if (Op == 0x8b)
341
9
    return R_RELAX_GOT_PC;
342
17
343
17
  // Relax call and jmp.
344
17
  if (Op == 0xff && 
(8
ModRm == 0x158
||
ModRm == 0x254
))
345
8
    return R_RELAX_GOT_PC;
346
9
347
9
  // Relaxation of test, adc, add, and, cmp, or, sbb, sub, xor.
348
9
  // If PIC then no relaxation is available.
349
9
  // We also don't relax test/binop instructions without REX byte,
350
9
  // they are 32bit operations and not common to have.
351
9
  assert(Type == R_X86_64_REX_GOTPCRELX);
352
9
  return Config->Pic ? RelExpr : 
R_RELAX_GOT_PC_NOPIC0
;
353
9
}
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
330
29
                                      RelExpr RelExpr) const {
331
29
  if (Type != R_X86_64_GOTPCRELX && 
Type != R_X86_64_REX_GOTPCRELX21
)
332
3
    return RelExpr;
333
26
  const uint8_t Op = Data[-2];
334
26
  const uint8_t ModRm = Data[-1];
335
26
336
26
  // FIXME: When PIC is disabled and foo is defined locally in the
337
26
  // lower 32 bit address space, memory operand in mov can be converted into
338
26
  // immediate operand. Otherwise, mov must be changed to lea. We support only
339
26
  // latter relaxation at this moment.
340
26
  if (Op == 0x8b)
341
9
    return R_RELAX_GOT_PC;
342
17
343
17
  // Relax call and jmp.
344
17
  if (Op == 0xff && 
(8
ModRm == 0x158
||
ModRm == 0x254
))
345
8
    return R_RELAX_GOT_PC;
346
9
347
9
  // Relaxation of test, adc, add, and, cmp, or, sbb, sub, xor.
348
9
  // If PIC then no relaxation is available.
349
9
  // We also don't relax test/binop instructions without REX byte,
350
9
  // they are 32bit operations and not common to have.
351
9
  assert(Type == R_X86_64_REX_GOTPCRELX);
352
9
  return Config->Pic ? RelExpr : 
R_RELAX_GOT_PC_NOPIC0
;
353
9
}
354
355
// A subset of relaxations can only be applied for no-PIC. This method
356
// handles such relaxations. Instructions encoding information was taken from:
357
// "Intel 64 and IA-32 Architectures Software Developer's Manual V2"
358
// (http://www.intel.com/content/dam/www/public/us/en/documents/manuals/
359
//    64-ia-32-architectures-software-developer-instruction-set-reference-manual-325383.pdf)
360
template <class ELFT>
361
void X86_64<ELFT>::relaxGotNoPic(uint8_t *Loc, uint64_t Val, uint8_t Op,
362
0
                                 uint8_t ModRm) const {
363
0
  const uint8_t Rex = Loc[-3];
364
0
  // Convert "test %reg, foo@GOTPCREL(%rip)" to "test $foo, %reg".
365
0
  if (Op == 0x85) {
366
0
    // See "TEST-Logical Compare" (4-428 Vol. 2B),
367
0
    // TEST r/m64, r64 uses "full" ModR / M byte (no opcode extension).
368
0
369
0
    // ModR/M byte has form XX YYY ZZZ, where
370
0
    // YYY is MODRM.reg(register 2), ZZZ is MODRM.rm(register 1).
371
0
    // XX has different meanings:
372
0
    // 00: The operand's memory address is in reg1.
373
0
    // 01: The operand's memory address is reg1 + a byte-sized displacement.
374
0
    // 10: The operand's memory address is reg1 + a word-sized displacement.
375
0
    // 11: The operand is reg1 itself.
376
0
    // If an instruction requires only one operand, the unused reg2 field
377
0
    // holds extra opcode bits rather than a register code
378
0
    // 0xC0 == 11 000 000 binary.
379
0
    // 0x38 == 00 111 000 binary.
380
0
    // We transfer reg2 to reg1 here as operand.
381
0
    // See "2.1.3 ModR/M and SIB Bytes" (Vol. 2A 2-3).
382
0
    Loc[-1] = 0xc0 | (ModRm & 0x38) >> 3; // ModR/M byte.
383
0
384
0
    // Change opcode from TEST r/m64, r64 to TEST r/m64, imm32
385
0
    // See "TEST-Logical Compare" (4-428 Vol. 2B).
386
0
    Loc[-2] = 0xf7;
387
0
388
0
    // Move R bit to the B bit in REX byte.
389
0
    // REX byte is encoded as 0100WRXB, where
390
0
    // 0100 is 4bit fixed pattern.
391
0
    // REX.W When 1, a 64-bit operand size is used. Otherwise, when 0, the
392
0
    //   default operand size is used (which is 32-bit for most but not all
393
0
    //   instructions).
394
0
    // REX.R This 1-bit value is an extension to the MODRM.reg field.
395
0
    // REX.X This 1-bit value is an extension to the SIB.index field.
396
0
    // REX.B This 1-bit value is an extension to the MODRM.rm field or the
397
0
    // SIB.base field.
398
0
    // See "2.2.1.2 More on REX Prefix Fields " (2-8 Vol. 2A).
399
0
    Loc[-3] = (Rex & ~0x4) | (Rex & 0x4) >> 2;
400
0
    write32le(Loc, Val);
401
0
    return;
402
0
  }
403
0
404
0
  // If we are here then we need to relax the adc, add, and, cmp, or, sbb, sub
405
0
  // or xor operations.
406
0
407
0
  // Convert "binop foo@GOTPCREL(%rip), %reg" to "binop $foo, %reg".
408
0
  // Logic is close to one for test instruction above, but we also
409
0
  // write opcode extension here, see below for details.
410
0
  Loc[-1] = 0xc0 | (ModRm & 0x38) >> 3 | (Op & 0x3c); // ModR/M byte.
411
0
412
0
  // Primary opcode is 0x81, opcode extension is one of:
413
0
  // 000b = ADD, 001b is OR, 010b is ADC, 011b is SBB,
414
0
  // 100b is AND, 101b is SUB, 110b is XOR, 111b is CMP.
415
0
  // This value was wrote to MODRM.reg in a line above.
416
0
  // See "3.2 INSTRUCTIONS (A-M)" (Vol. 2A 3-15),
417
0
  // "INSTRUCTION SET REFERENCE, N-Z" (Vol. 2B 4-1) for
418
0
  // descriptions about each operation.
419
0
  Loc[-2] = 0x81;
420
0
  Loc[-3] = (Rex & ~0x4) | (Rex & 0x4) >> 2;
421
0
  write32le(Loc, Val);
422
0
}
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
Unexecuted instantiation: 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
423
424
template <class ELFT>
425
17
void X86_64<ELFT>::relaxGot(uint8_t *Loc, uint64_t Val) const {
426
17
  const uint8_t Op = Loc[-2];
427
17
  const uint8_t ModRm = Loc[-1];
428
17
429
17
  // Convert "mov foo@GOTPCREL(%rip),%reg" to "lea foo(%rip),%reg".
430
17
  if (Op == 0x8b) {
431
9
    Loc[-2] = 0x8d;
432
9
    write32le(Loc, Val);
433
9
    return;
434
9
  }
435
8
436
8
  if (Op != 0xff) {
437
0
    // We are relaxing a rip relative to an absolute, so compensate
438
0
    // for the old -4 addend.
439
0
    assert(!Config->Pic);
440
0
    relaxGotNoPic(Loc, Val + 4, Op, ModRm);
441
0
    return;
442
0
  }
443
8
444
8
  // Convert call/jmp instructions.
445
8
  if (ModRm == 0x15) {
446
4
    // ABI says we can convert "call *foo@GOTPCREL(%rip)" to "nop; call foo".
447
4
    // Instead we convert to "addr32 call foo" where addr32 is an instruction
448
4
    // prefix. That makes result expression to be a single instruction.
449
4
    Loc[-2] = 0x67; // addr32 prefix
450
4
    Loc[-1] = 0xe8; // call
451
4
    write32le(Loc, Val);
452
4
    return;
453
4
  }
454
4
455
4
  // Convert "jmp *foo@GOTPCREL(%rip)" to "jmp foo; nop".
456
4
  // jmp doesn't return, so it is fine to use nop here, it is just a stub.
457
4
  assert(ModRm == 0x25);
458
4
  Loc[-2] = 0xe9; // jmp
459
4
  Loc[3] = 0x90;  // nop
460
4
  write32le(Loc - 1, Val + 1);
461
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
425
17
void X86_64<ELFT>::relaxGot(uint8_t *Loc, uint64_t Val) const {
426
17
  const uint8_t Op = Loc[-2];
427
17
  const uint8_t ModRm = Loc[-1];
428
17
429
17
  // Convert "mov foo@GOTPCREL(%rip),%reg" to "lea foo(%rip),%reg".
430
17
  if (Op == 0x8b) {
431
9
    Loc[-2] = 0x8d;
432
9
    write32le(Loc, Val);
433
9
    return;
434
9
  }
435
8
436
8
  if (Op != 0xff) {
437
0
    // We are relaxing a rip relative to an absolute, so compensate
438
0
    // for the old -4 addend.
439
0
    assert(!Config->Pic);
440
0
    relaxGotNoPic(Loc, Val + 4, Op, ModRm);
441
0
    return;
442
0
  }
443
8
444
8
  // Convert call/jmp instructions.
445
8
  if (ModRm == 0x15) {
446
4
    // ABI says we can convert "call *foo@GOTPCREL(%rip)" to "nop; call foo".
447
4
    // Instead we convert to "addr32 call foo" where addr32 is an instruction
448
4
    // prefix. That makes result expression to be a single instruction.
449
4
    Loc[-2] = 0x67; // addr32 prefix
450
4
    Loc[-1] = 0xe8; // call
451
4
    write32le(Loc, Val);
452
4
    return;
453
4
  }
454
4
455
4
  // Convert "jmp *foo@GOTPCREL(%rip)" to "jmp foo; nop".
456
4
  // jmp doesn't return, so it is fine to use nop here, it is just a stub.
457
4
  assert(ModRm == 0x25);
458
4
  Loc[-2] = 0xe9; // jmp
459
4
  Loc[3] = 0x90;  // nop
460
4
  write32le(Loc - 1, Val + 1);
461
4
}
462
463
1
TargetInfo *elf::getX32TargetInfo() {
464
1
  static X86_64<ELF32LE> Target;
465
1
  return &Target;
466
1
}
467
468
712
TargetInfo *elf::getX86_64TargetInfo() {
469
712
  static X86_64<ELF64LE> Target;
470
712
  return &Target;
471
712
}