Coverage Report

Created: 2019-07-24 05:18

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/lib/MC/MCWinCOFFStreamer.cpp
Line
Count
Source (jump to first uncovered line)
1
//===- llvm/MC/MCWinCOFFStreamer.cpp --------------------------------------===//
2
//
3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
// See https://llvm.org/LICENSE.txt for license information.
5
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
//
7
//===----------------------------------------------------------------------===//
8
//
9
// This file contains an implementation of a Windows COFF object file streamer.
10
//
11
//===----------------------------------------------------------------------===//
12
13
#include "llvm/ADT/SmallString.h"
14
#include "llvm/ADT/SmallVector.h"
15
#include "llvm/ADT/Triple.h"
16
#include "llvm/ADT/Twine.h"
17
#include "llvm/BinaryFormat/COFF.h"
18
#include "llvm/MC/MCAsmBackend.h"
19
#include "llvm/MC/MCAssembler.h"
20
#include "llvm/MC/MCCodeEmitter.h"
21
#include "llvm/MC/MCContext.h"
22
#include "llvm/MC/MCExpr.h"
23
#include "llvm/MC/MCFixup.h"
24
#include "llvm/MC/MCFragment.h"
25
#include "llvm/MC/MCObjectFileInfo.h"
26
#include "llvm/MC/MCObjectStreamer.h"
27
#include "llvm/MC/MCObjectWriter.h"
28
#include "llvm/MC/MCSection.h"
29
#include "llvm/MC/MCSymbolCOFF.h"
30
#include "llvm/MC/MCWinCOFFStreamer.h"
31
#include "llvm/Support/Casting.h"
32
#include "llvm/Support/ErrorHandling.h"
33
#include "llvm/Support/MathExtras.h"
34
#include "llvm/Support/SMLoc.h"
35
#include "llvm/Support/raw_ostream.h"
36
#include <algorithm>
37
#include <cassert>
38
#include <cstdint>
39
40
using namespace llvm;
41
42
#define DEBUG_TYPE "WinCOFFStreamer"
43
44
MCWinCOFFStreamer::MCWinCOFFStreamer(MCContext &Context,
45
                                     std::unique_ptr<MCAsmBackend> MAB,
46
                                     std::unique_ptr<MCCodeEmitter> CE,
47
                                     std::unique_ptr<MCObjectWriter> OW)
48
    : MCObjectStreamer(Context, std::move(MAB), std::move(OW), std::move(CE)),
49
592
      CurSymbol(nullptr) {}
50
51
void MCWinCOFFStreamer::EmitInstToData(const MCInst &Inst,
52
4.35k
                                       const MCSubtargetInfo &STI) {
53
4.35k
  MCDataFragment *DF = getOrCreateDataFragment();
54
4.35k
55
4.35k
  SmallVector<MCFixup, 4> Fixups;
56
4.35k
  SmallString<256> Code;
57
4.35k
  raw_svector_ostream VecOS(Code);
58
4.35k
  getAssembler().getEmitter().encodeInstruction(Inst, VecOS, Fixups, STI);
59
4.35k
60
4.35k
  // Add the fixups and data.
61
5.07k
  for (unsigned i = 0, e = Fixups.size(); i != e; 
++i722
) {
62
722
    Fixups[i].setOffset(Fixups[i].getOffset() + DF->getContents().size());
63
722
    DF->getFixups().push_back(Fixups[i]);
64
722
  }
65
4.35k
  DF->setHasInstructions(STI);
66
4.35k
  DF->getContents().append(Code.begin(), Code.end());
67
4.35k
}
68
69
592
void MCWinCOFFStreamer::InitSections(bool NoExecStack) {
70
592
  // FIXME: this is identical to the ELF one.
71
592
  // This emulates the same behavior of GNU as. This makes it easier
72
592
  // to compare the output as the major sections are in the same order.
73
592
  SwitchSection(getContext().getObjectFileInfo()->getTextSection());
74
592
  EmitCodeAlignment(4);
75
592
76
592
  SwitchSection(getContext().getObjectFileInfo()->getDataSection());
77
592
  EmitCodeAlignment(4);
78
592
79
592
  SwitchSection(getContext().getObjectFileInfo()->getBSSSection());
80
592
  EmitCodeAlignment(4);
81
592
82
592
  SwitchSection(getContext().getObjectFileInfo()->getTextSection());
83
592
}
84
85
11.9k
void MCWinCOFFStreamer::EmitLabel(MCSymbol *S, SMLoc Loc) {
86
11.9k
  auto *Symbol = cast<MCSymbolCOFF>(S);
87
11.9k
  MCObjectStreamer::EmitLabel(Symbol, Loc);
88
11.9k
}
89
90
0
void MCWinCOFFStreamer::EmitAssemblerFlag(MCAssemblerFlag Flag) {
91
0
  llvm_unreachable("not implemented");
92
0
}
93
94
0
void MCWinCOFFStreamer::EmitThumbFunc(MCSymbol *Func) {
95
0
  llvm_unreachable("not implemented");
96
0
}
97
98
bool MCWinCOFFStreamer::EmitSymbolAttribute(MCSymbol *S,
99
1.46k
                                            MCSymbolAttr Attribute) {
100
1.46k
  auto *Symbol = cast<MCSymbolCOFF>(S);
101
1.46k
  getAssembler().registerSymbol(*Symbol);
102
1.46k
103
1.46k
  switch (Attribute) {
104
1.46k
  
default: return false71
;
105
1.46k
  case MCSA_WeakReference:
106
8
  case MCSA_Weak:
107
8
    Symbol->setIsWeakExternal();
108
8
    Symbol->setExternal(true);
109
8
    break;
110
1.38k
  case MCSA_Global:
111
1.38k
    Symbol->setExternal(true);
112
1.38k
    break;
113
8
  case MCSA_AltEntry:
114
0
    llvm_unreachable("COFF doesn't support the .alt_entry attribute");
115
1.39k
  }
116
1.39k
117
1.39k
  return true;
118
1.39k
}
119
120
0
void MCWinCOFFStreamer::EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) {
121
0
  llvm_unreachable("not implemented");
122
0
}
123
124
875
void MCWinCOFFStreamer::BeginCOFFSymbolDef(MCSymbol const *S) {
125
875
  auto *Symbol = cast<MCSymbolCOFF>(S);
126
875
  if (CurSymbol)
127
2
    Error("starting a new symbol definition without completing the "
128
2
          "previous one");
129
875
  CurSymbol = Symbol;
130
875
}
131
132
873
void MCWinCOFFStreamer::EmitCOFFSymbolStorageClass(int StorageClass) {
133
873
  if (!CurSymbol) {
134
2
    Error("storage class specified outside of symbol definition");
135
2
    return;
136
2
  }
137
871
138
871
  if (StorageClass & ~COFF::SSC_Invalid) {
139
2
    Error("storage class value '" + Twine(StorageClass) +
140
2
               "' out of range");
141
2
    return;
142
2
  }
143
869
144
869
  getAssembler().registerSymbol(*CurSymbol);
145
869
  cast<MCSymbolCOFF>(CurSymbol)->setClass((uint16_t)StorageClass);
146
869
}
147
148
874
void MCWinCOFFStreamer::EmitCOFFSymbolType(int Type) {
149
874
  if (!CurSymbol) {
150
2
    Error("symbol type specified outside of a symbol definition");
151
2
    return;
152
2
  }
153
872
154
872
  if (Type & ~0xffff) {
155
1
    Error("type value '" + Twine(Type) + "' out of range");
156
1
    return;
157
1
  }
158
871
159
871
  getAssembler().registerSymbol(*CurSymbol);
160
871
  cast<MCSymbolCOFF>(CurSymbol)->setType((uint16_t)Type);
161
871
}
162
163
878
void MCWinCOFFStreamer::EndCOFFSymbolDef() {
164
878
  if (!CurSymbol)
165
2
    Error("ending symbol definition without starting one");
166
878
  CurSymbol = nullptr;
167
878
}
168
169
6
void MCWinCOFFStreamer::EmitCOFFSafeSEH(MCSymbol const *Symbol) {
170
6
  // SafeSEH is a feature specific to 32-bit x86.  It does not exist (and is
171
6
  // unnecessary) on all platforms which use table-based exception dispatch.
172
6
  if (getContext().getObjectFileInfo()->getTargetTriple().getArch() !=
173
6
      Triple::x86)
174
0
    return;
175
6
176
6
  const MCSymbolCOFF *CSymbol = cast<MCSymbolCOFF>(Symbol);
177
6
  if (CSymbol->isSafeSEH())
178
0
    return;
179
6
180
6
  MCSection *SXData = getContext().getObjectFileInfo()->getSXDataSection();
181
6
  getAssembler().registerSection(*SXData);
182
6
  if (SXData->getAlignment() < 4)
183
5
    SXData->setAlignment(4);
184
6
185
6
  new MCSymbolIdFragment(Symbol, SXData);
186
6
187
6
  getAssembler().registerSymbol(*Symbol);
188
6
  CSymbol->setIsSafeSEH();
189
6
190
6
  // The Microsoft linker requires that the symbol type of a handler be
191
6
  // function. Go ahead and oblige it here.
192
6
  CSymbol->setType(COFF::IMAGE_SYM_DTYPE_FUNCTION
193
6
                   << COFF::SCT_COMPLEX_TYPE_SHIFT);
194
6
}
195
196
10
void MCWinCOFFStreamer::EmitCOFFSymbolIndex(MCSymbol const *Symbol) {
197
10
  MCSection *Sec = getCurrentSectionOnly();
198
10
  getAssembler().registerSection(*Sec);
199
10
  if (Sec->getAlignment() < 4)
200
7
    Sec->setAlignment(4);
201
10
202
10
  new MCSymbolIdFragment(Symbol, getCurrentSectionOnly());
203
10
204
10
  getAssembler().registerSymbol(*Symbol);
205
10
}
206
207
685
void MCWinCOFFStreamer::EmitCOFFSectionIndex(const MCSymbol *Symbol) {
208
685
  visitUsedSymbol(*Symbol);
209
685
  MCDataFragment *DF = getOrCreateDataFragment();
210
685
  const MCSymbolRefExpr *SRE = MCSymbolRefExpr::create(Symbol, getContext());
211
685
  MCFixup Fixup = MCFixup::create(DF->getContents().size(), SRE, FK_SecRel_2);
212
685
  DF->getFixups().push_back(Fixup);
213
685
  DF->getContents().resize(DF->getContents().size() + 2, 0);
214
685
}
215
216
void MCWinCOFFStreamer::EmitCOFFSecRel32(const MCSymbol *Symbol,
217
903
                                         uint64_t Offset) {
218
903
  visitUsedSymbol(*Symbol);
219
903
  MCDataFragment *DF = getOrCreateDataFragment();
220
903
  // Create Symbol A for the relocation relative reference.
221
903
  const MCExpr *MCE = MCSymbolRefExpr::create(Symbol, getContext());
222
903
  // Add the constant offset, if given.
223
903
  if (Offset)
224
3
    MCE = MCBinaryExpr::createAdd(
225
3
        MCE, MCConstantExpr::create(Offset, getContext()), getContext());
226
903
  // Build the secrel32 relocation.
227
903
  MCFixup Fixup = MCFixup::create(DF->getContents().size(), MCE, FK_SecRel_4);
228
903
  // Record the relocation.
229
903
  DF->getFixups().push_back(Fixup);
230
903
  // Emit 4 bytes (zeros) to the object file.
231
903
  DF->getContents().resize(DF->getContents().size() + 4, 0);
232
903
}
233
234
void MCWinCOFFStreamer::EmitCOFFImgRel32(const MCSymbol *Symbol,
235
32
                                         int64_t Offset) {
236
32
  visitUsedSymbol(*Symbol);
237
32
  MCDataFragment *DF = getOrCreateDataFragment();
238
32
  // Create Symbol A for the relocation relative reference.
239
32
  const MCExpr *MCE = MCSymbolRefExpr::create(
240
32
      Symbol, MCSymbolRefExpr::VK_COFF_IMGREL32, getContext());
241
32
  // Add the constant offset, if given.
242
32
  if (Offset)
243
4
    MCE = MCBinaryExpr::createAdd(
244
4
        MCE, MCConstantExpr::create(Offset, getContext()), getContext());
245
32
  // Build the imgrel relocation.
246
32
  MCFixup Fixup = MCFixup::create(DF->getContents().size(), MCE, FK_Data_4);
247
32
  // Record the relocation.
248
32
  DF->getFixups().push_back(Fixup);
249
32
  // Emit 4 bytes (zeros) to the object file.
250
32
  DF->getContents().resize(DF->getContents().size() + 4, 0);
251
32
}
252
253
void MCWinCOFFStreamer::EmitCommonSymbol(MCSymbol *S, uint64_t Size,
254
22
                                         unsigned ByteAlignment) {
255
22
  auto *Symbol = cast<MCSymbolCOFF>(S);
256
22
257
22
  const Triple &T = getContext().getObjectFileInfo()->getTargetTriple();
258
22
  if (T.isWindowsMSVCEnvironment()) {
259
16
    if (ByteAlignment > 32)
260
0
      report_fatal_error("alignment is limited to 32-bytes");
261
16
262
16
    // Round size up to alignment so that we will honor the alignment request.
263
16
    Size = std::max(Size, static_cast<uint64_t>(ByteAlignment));
264
16
  }
265
22
266
22
  getAssembler().registerSymbol(*Symbol);
267
22
  Symbol->setExternal(true);
268
22
  Symbol->setCommon(Size, ByteAlignment);
269
22
270
22
  if (!T.isWindowsMSVCEnvironment() && 
ByteAlignment > 16
) {
271
5
    SmallString<128> Directive;
272
5
    raw_svector_ostream OS(Directive);
273
5
    const MCObjectFileInfo *MFI = getContext().getObjectFileInfo();
274
5
275
5
    OS << " -aligncomm:\"" << Symbol->getName() << "\","
276
5
       << Log2_32_Ceil(ByteAlignment);
277
5
278
5
    PushSection();
279
5
    SwitchSection(MFI->getDrectveSection());
280
5
    EmitBytes(Directive);
281
5
    PopSection();
282
5
  }
283
22
}
284
285
void MCWinCOFFStreamer::EmitLocalCommonSymbol(MCSymbol *S, uint64_t Size,
286
7
                                              unsigned ByteAlignment) {
287
7
  auto *Symbol = cast<MCSymbolCOFF>(S);
288
7
289
7
  MCSection *Section = getContext().getObjectFileInfo()->getBSSSection();
290
7
  PushSection();
291
7
  SwitchSection(Section);
292
7
  EmitValueToAlignment(ByteAlignment, 0, 1, 0);
293
7
  EmitLabel(Symbol);
294
7
  Symbol->setExternal(false);
295
7
  EmitZeros(Size);
296
7
  PopSection();
297
7
}
298
299
void MCWinCOFFStreamer::EmitZerofill(MCSection *Section, MCSymbol *Symbol,
300
                                     uint64_t Size, unsigned ByteAlignment,
301
0
                                     SMLoc Loc) {
302
0
  llvm_unreachable("not implemented");
303
0
}
304
305
void MCWinCOFFStreamer::EmitTBSSSymbol(MCSection *Section, MCSymbol *Symbol,
306
0
                                       uint64_t Size, unsigned ByteAlignment) {
307
0
  llvm_unreachable("not implemented");
308
0
}
309
310
// TODO: Implement this if you want to emit .comment section in COFF obj files.
311
0
void MCWinCOFFStreamer::EmitIdent(StringRef IdentString) {
312
0
  llvm_unreachable("not implemented");
313
0
}
314
315
0
void MCWinCOFFStreamer::EmitWinEHHandlerData(SMLoc Loc) {
316
0
  llvm_unreachable("not implemented");
317
0
}
318
319
584
void MCWinCOFFStreamer::FinishImpl() {
320
584
  MCObjectStreamer::FinishImpl();
321
584
}
322
323
11
void MCWinCOFFStreamer::Error(const Twine &Msg) const {
324
11
  getContext().reportError(SMLoc(), Msg);
325
11
}