Coverage Report

Created: 2017-10-03 07:32

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