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/MC/MCWinCOFFStreamer.h" 14 #include "llvm/ADT/SmallString.h" 15 #include "llvm/ADT/SmallVector.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/MCCodeView.h" 22 #include "llvm/MC/MCContext.h" 23 #include "llvm/MC/MCExpr.h" 24 #include "llvm/MC/MCFixup.h" 25 #include "llvm/MC/MCFragment.h" 26 #include "llvm/MC/MCObjectFileInfo.h" 27 #include "llvm/MC/MCObjectStreamer.h" 28 #include "llvm/MC/MCObjectWriter.h" 29 #include "llvm/MC/MCSectionCOFF.h" 30 #include "llvm/MC/MCSymbolCOFF.h" 31 #include "llvm/MC/MCTargetOptions.h" 32 #include "llvm/MC/MCValue.h" 33 #include "llvm/MC/MCWinCOFFObjectWriter.h" 34 #include "llvm/Support/Casting.h" 35 #include "llvm/Support/ErrorHandling.h" 36 #include "llvm/Support/MathExtras.h" 37 #include "llvm/Support/SMLoc.h" 38 #include "llvm/Support/raw_ostream.h" 39 #include "llvm/TargetParser/Triple.h" 40 #include <algorithm> 41 #include <cstdint> 42 43 using namespace llvm; 44 45 #define DEBUG_TYPE "WinCOFFStreamer" 46 47 /// MCExpr that represents the physical number for the sections that contains 48 /// a symbol. 49 class MCCOFFSectionNumberTargetExpr final : public MCTargetExpr { 50 const MCSymbol &SectionSymbol; 51 const WinCOFFObjectWriter &Writer; 52 53 MCCOFFSectionNumberTargetExpr(const MCSymbol &SectionSymbol_, 54 const WinCOFFObjectWriter &Writer_) 55 : SectionSymbol(SectionSymbol_), Writer(Writer_) {} 56 57 public: 58 static MCCOFFSectionNumberTargetExpr * 59 create(const MCSymbol &SectionSymbol, const WinCOFFObjectWriter &Writer, 60 MCContext &Ctx) { 61 return new (Ctx) MCCOFFSectionNumberTargetExpr(SectionSymbol, Writer); 62 } 63 64 void printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const override { 65 OS << ":secnum:"; 66 SectionSymbol.print(OS, MAI); 67 } 68 69 bool evaluateAsRelocatableImpl(MCValue &Res, const MCAssembler *Asm, 70 const MCFixup *Fixup) const override { 71 auto sectionNumber = Writer.getSectionNumber(SectionSymbol.getSection()); 72 assert(sectionNumber != 0 && 73 "Containing section was not assigned a number"); 74 Res = MCValue::get(sectionNumber); 75 return true; 76 } 77 78 void visitUsedExpr(MCStreamer &Streamer) const override { 79 // Contains no sub-expressions. 80 } 81 82 MCFragment *findAssociatedFragment() const override { 83 return SectionSymbol.getFragment(); 84 } 85 86 void fixELFSymbolsInTLSFixups(MCAssembler &) const override { 87 llvm_unreachable("Not supported for ELF"); 88 } 89 }; 90 91 /// MCExpr that represents the offset to a symbol from the beginning of its 92 /// section. 93 class MCCOFFSectionOffsetTargetExpr final : public MCTargetExpr { 94 const MCSymbol &Symbol; 95 96 MCCOFFSectionOffsetTargetExpr(const MCSymbol &Symbol_) : Symbol(Symbol_) {} 97 98 public: 99 static MCCOFFSectionOffsetTargetExpr *create(const MCSymbol &Symbol, 100 MCContext &Ctx) { 101 return new (Ctx) MCCOFFSectionOffsetTargetExpr(Symbol); 102 } 103 104 void printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const override { 105 OS << ":secoffset:"; 106 Symbol.print(OS, MAI); 107 } 108 109 bool evaluateAsRelocatableImpl(MCValue &Res, const MCAssembler *Asm, 110 const MCFixup *Fixup) const override { 111 uint64_t CallsiteOffset = 0; 112 if (!Asm->getSymbolOffset(Symbol, CallsiteOffset)) { 113 return true; 114 } 115 Res = MCValue::get(CallsiteOffset); 116 return true; 117 } 118 119 void visitUsedExpr(MCStreamer &Streamer) const override { 120 // Contains no sub-expressions. 121 } 122 123 MCFragment *findAssociatedFragment() const override { 124 return Symbol.getFragment(); 125 } 126 127 void fixELFSymbolsInTLSFixups(MCAssembler &) const override { 128 llvm_unreachable("Not supported for ELF"); 129 } 130 }; 131 132 MCWinCOFFStreamer::MCWinCOFFStreamer(MCContext &Context, 133 std::unique_ptr<MCAsmBackend> MAB, 134 std::unique_ptr<MCCodeEmitter> CE, 135 std::unique_ptr<MCObjectWriter> OW) 136 : MCObjectStreamer(Context, std::move(MAB), std::move(OW), std::move(CE)), 137 CurSymbol(nullptr) { 138 auto *TO = Context.getTargetOptions(); 139 if (TO && TO->MCIncrementalLinkerCompatible) 140 getWriter().setIncrementalLinkerCompatible(true); 141 } 142 143 WinCOFFObjectWriter &MCWinCOFFStreamer::getWriter() { 144 return static_cast<WinCOFFObjectWriter &>(getAssembler().getWriter()); 145 } 146 147 void MCWinCOFFStreamer::emitInstToData(const MCInst &Inst, 148 const MCSubtargetInfo &STI) { 149 MCDataFragment *DF = getOrCreateDataFragment(); 150 151 SmallVector<MCFixup, 4> Fixups; 152 SmallString<256> Code; 153 getAssembler().getEmitter().encodeInstruction(Inst, Code, Fixups, STI); 154 155 // Add the fixups and data. 156 for (unsigned i = 0, e = Fixups.size(); i != e; ++i) { 157 Fixups[i].setOffset(Fixups[i].getOffset() + DF->getContents().size()); 158 DF->getFixups().push_back(Fixups[i]); 159 } 160 DF->setHasInstructions(STI); 161 DF->appendContents(Code); 162 } 163 164 void MCWinCOFFStreamer::initSections(bool NoExecStack, 165 const MCSubtargetInfo &STI) { 166 // FIXME: this is identical to the ELF one. 167 // This emulates the same behavior of GNU as. This makes it easier 168 // to compare the output as the major sections are in the same order. 169 switchSection(getContext().getObjectFileInfo()->getTextSection()); 170 emitCodeAlignment(Align(4), &STI); 171 172 switchSection(getContext().getObjectFileInfo()->getDataSection()); 173 emitCodeAlignment(Align(4), &STI); 174 175 switchSection(getContext().getObjectFileInfo()->getBSSSection()); 176 emitCodeAlignment(Align(4), &STI); 177 178 switchSection(getContext().getObjectFileInfo()->getTextSection()); 179 } 180 181 void MCWinCOFFStreamer::changeSection(MCSection *Section, uint32_t Subsection) { 182 changeSectionImpl(Section, Subsection); 183 // Ensure that the first and the second symbols relative to the section are 184 // the section symbol and the COMDAT symbol. 185 getAssembler().registerSymbol(*Section->getBeginSymbol()); 186 if (auto *Sym = cast<MCSectionCOFF>(Section)->getCOMDATSymbol()) 187 getAssembler().registerSymbol(*Sym); 188 } 189 190 void MCWinCOFFStreamer::emitLabel(MCSymbol *S, SMLoc Loc) { 191 auto *Symbol = cast<MCSymbolCOFF>(S); 192 MCObjectStreamer::emitLabel(Symbol, Loc); 193 } 194 195 void MCWinCOFFStreamer::emitAssemblerFlag(MCAssemblerFlag Flag) { 196 // Let the target do whatever target specific stuff it needs to do. 197 getAssembler().getBackend().handleAssemblerFlag(Flag); 198 199 switch (Flag) { 200 // None of these require COFF specific handling. 201 case MCAF_SyntaxUnified: 202 case MCAF_Code16: 203 case MCAF_Code32: 204 case MCAF_Code64: 205 break; 206 case MCAF_SubsectionsViaSymbols: 207 llvm_unreachable("COFF doesn't support .subsections_via_symbols"); 208 } 209 } 210 211 void MCWinCOFFStreamer::emitThumbFunc(MCSymbol *Func) { 212 llvm_unreachable("not implemented"); 213 } 214 215 bool MCWinCOFFStreamer::emitSymbolAttribute(MCSymbol *S, 216 MCSymbolAttr Attribute) { 217 auto *Symbol = cast<MCSymbolCOFF>(S); 218 getAssembler().registerSymbol(*Symbol); 219 220 switch (Attribute) { 221 default: return false; 222 case MCSA_WeakReference: 223 case MCSA_Weak: 224 Symbol->setWeakExternalCharacteristics(COFF::IMAGE_WEAK_EXTERN_SEARCH_ALIAS); 225 Symbol->setExternal(true); 226 break; 227 case MCSA_WeakAntiDep: 228 Symbol->setWeakExternalCharacteristics(COFF::IMAGE_WEAK_EXTERN_ANTI_DEPENDENCY); 229 Symbol->setExternal(true); 230 Symbol->setIsWeakExternal(true); 231 break; 232 case MCSA_Global: 233 Symbol->setExternal(true); 234 break; 235 case MCSA_AltEntry: 236 llvm_unreachable("COFF doesn't support the .alt_entry attribute"); 237 } 238 239 return true; 240 } 241 242 void MCWinCOFFStreamer::emitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) { 243 llvm_unreachable("not implemented"); 244 } 245 246 void MCWinCOFFStreamer::beginCOFFSymbolDef(MCSymbol const *S) { 247 auto *Symbol = cast<MCSymbolCOFF>(S); 248 if (CurSymbol) 249 Error("starting a new symbol definition without completing the " 250 "previous one"); 251 CurSymbol = Symbol; 252 } 253 254 void MCWinCOFFStreamer::emitCOFFSymbolStorageClass(int StorageClass) { 255 if (!CurSymbol) { 256 Error("storage class specified outside of symbol definition"); 257 return; 258 } 259 260 if (StorageClass & ~COFF::SSC_Invalid) { 261 Error("storage class value '" + Twine(StorageClass) + 262 "' out of range"); 263 return; 264 } 265 266 getAssembler().registerSymbol(*CurSymbol); 267 cast<MCSymbolCOFF>(CurSymbol)->setClass((uint16_t)StorageClass); 268 } 269 270 void MCWinCOFFStreamer::emitCOFFSymbolType(int Type) { 271 if (!CurSymbol) { 272 Error("symbol type specified outside of a symbol definition"); 273 return; 274 } 275 276 if (Type & ~0xffff) { 277 Error("type value '" + Twine(Type) + "' out of range"); 278 return; 279 } 280 281 getAssembler().registerSymbol(*CurSymbol); 282 cast<MCSymbolCOFF>(CurSymbol)->setType((uint16_t)Type); 283 } 284 285 void MCWinCOFFStreamer::endCOFFSymbolDef() { 286 if (!CurSymbol) 287 Error("ending symbol definition without starting one"); 288 CurSymbol = nullptr; 289 } 290 291 void MCWinCOFFStreamer::emitCOFFSafeSEH(MCSymbol const *Symbol) { 292 // SafeSEH is a feature specific to 32-bit x86. It does not exist (and is 293 // unnecessary) on all platforms which use table-based exception dispatch. 294 if (getContext().getTargetTriple().getArch() != Triple::x86) 295 return; 296 297 const MCSymbolCOFF *CSymbol = cast<MCSymbolCOFF>(Symbol); 298 if (CSymbol->isSafeSEH()) 299 return; 300 301 MCSection *SXData = getContext().getObjectFileInfo()->getSXDataSection(); 302 changeSection(SXData); 303 SXData->ensureMinAlignment(Align(4)); 304 305 insert(getContext().allocFragment<MCSymbolIdFragment>(Symbol)); 306 getAssembler().registerSymbol(*Symbol); 307 CSymbol->setIsSafeSEH(); 308 309 // The Microsoft linker requires that the symbol type of a handler be 310 // function. Go ahead and oblige it here. 311 CSymbol->setType(COFF::IMAGE_SYM_DTYPE_FUNCTION 312 << COFF::SCT_COMPLEX_TYPE_SHIFT); 313 } 314 315 void MCWinCOFFStreamer::emitCOFFSymbolIndex(MCSymbol const *Symbol) { 316 MCSection *Sec = getCurrentSectionOnly(); 317 Sec->ensureMinAlignment(Align(4)); 318 319 insert(getContext().allocFragment<MCSymbolIdFragment>(Symbol)); 320 getAssembler().registerSymbol(*Symbol); 321 } 322 323 void MCWinCOFFStreamer::emitCOFFSectionIndex(const MCSymbol *Symbol) { 324 visitUsedSymbol(*Symbol); 325 MCDataFragment *DF = getOrCreateDataFragment(); 326 const MCSymbolRefExpr *SRE = MCSymbolRefExpr::create(Symbol, getContext()); 327 MCFixup Fixup = MCFixup::create(DF->getContents().size(), SRE, FK_SecRel_2); 328 DF->getFixups().push_back(Fixup); 329 DF->appendContents(2, 0); 330 } 331 332 void MCWinCOFFStreamer::emitCOFFSecRel32(const MCSymbol *Symbol, 333 uint64_t Offset) { 334 visitUsedSymbol(*Symbol); 335 MCDataFragment *DF = getOrCreateDataFragment(); 336 // Create Symbol A for the relocation relative reference. 337 const MCExpr *MCE = MCSymbolRefExpr::create(Symbol, getContext()); 338 // Add the constant offset, if given. 339 if (Offset) 340 MCE = MCBinaryExpr::createAdd( 341 MCE, MCConstantExpr::create(Offset, getContext()), getContext()); 342 // Build the secrel32 relocation. 343 MCFixup Fixup = MCFixup::create(DF->getContents().size(), MCE, FK_SecRel_4); 344 // Record the relocation. 345 DF->getFixups().push_back(Fixup); 346 // Emit 4 bytes (zeros) to the object file. 347 DF->appendContents(4, 0); 348 } 349 350 void MCWinCOFFStreamer::emitCOFFImgRel32(const MCSymbol *Symbol, 351 int64_t Offset) { 352 visitUsedSymbol(*Symbol); 353 MCDataFragment *DF = getOrCreateDataFragment(); 354 // Create Symbol A for the relocation relative reference. 355 const MCExpr *MCE = MCSymbolRefExpr::create( 356 Symbol, MCSymbolRefExpr::VK_COFF_IMGREL32, getContext()); 357 // Add the constant offset, if given. 358 if (Offset) 359 MCE = MCBinaryExpr::createAdd( 360 MCE, MCConstantExpr::create(Offset, getContext()), getContext()); 361 // Build the imgrel relocation. 362 MCFixup Fixup = MCFixup::create(DF->getContents().size(), MCE, FK_Data_4); 363 // Record the relocation. 364 DF->getFixups().push_back(Fixup); 365 // Emit 4 bytes (zeros) to the object file. 366 DF->appendContents(4, 0); 367 } 368 369 void MCWinCOFFStreamer::emitCOFFSecNumber(MCSymbol const *Symbol) { 370 visitUsedSymbol(*Symbol); 371 MCDataFragment *DF = getOrCreateDataFragment(); 372 // Create Symbol for section number. 373 const MCExpr *MCE = MCCOFFSectionNumberTargetExpr::create( 374 *Symbol, this->getWriter(), getContext()); 375 // Build the relocation. 376 MCFixup Fixup = MCFixup::create(DF->getContents().size(), MCE, FK_Data_4); 377 // Record the relocation. 378 DF->getFixups().push_back(Fixup); 379 // Emit 4 bytes (zeros) to the object file. 380 DF->appendContents(4, 0); 381 } 382 383 void MCWinCOFFStreamer::emitCOFFSecOffset(MCSymbol const *Symbol) { 384 visitUsedSymbol(*Symbol); 385 MCDataFragment *DF = getOrCreateDataFragment(); 386 // Create Symbol for section offset. 387 const MCExpr *MCE = 388 MCCOFFSectionOffsetTargetExpr::create(*Symbol, getContext()); 389 // Build the relocation. 390 MCFixup Fixup = MCFixup::create(DF->getContents().size(), MCE, FK_Data_4); 391 // Record the relocation. 392 DF->getFixups().push_back(Fixup); 393 // Emit 4 bytes (zeros) to the object file. 394 DF->appendContents(4, 0); 395 } 396 397 void MCWinCOFFStreamer::emitCommonSymbol(MCSymbol *S, uint64_t Size, 398 Align ByteAlignment) { 399 auto *Symbol = cast<MCSymbolCOFF>(S); 400 401 const Triple &T = getContext().getTargetTriple(); 402 if (T.isWindowsMSVCEnvironment()) { 403 if (ByteAlignment > 32) 404 report_fatal_error("alignment is limited to 32-bytes"); 405 406 // Round size up to alignment so that we will honor the alignment request. 407 Size = std::max(Size, ByteAlignment.value()); 408 } 409 410 getAssembler().registerSymbol(*Symbol); 411 Symbol->setExternal(true); 412 Symbol->setCommon(Size, ByteAlignment); 413 414 if (!T.isWindowsMSVCEnvironment() && ByteAlignment > 1) { 415 SmallString<128> Directive; 416 raw_svector_ostream OS(Directive); 417 const MCObjectFileInfo *MFI = getContext().getObjectFileInfo(); 418 419 OS << " -aligncomm:\"" << Symbol->getName() << "\"," 420 << Log2_32_Ceil(ByteAlignment.value()); 421 422 pushSection(); 423 switchSection(MFI->getDrectveSection()); 424 emitBytes(Directive); 425 popSection(); 426 } 427 } 428 429 void MCWinCOFFStreamer::emitLocalCommonSymbol(MCSymbol *S, uint64_t Size, 430 Align ByteAlignment) { 431 auto *Symbol = cast<MCSymbolCOFF>(S); 432 433 MCSection *Section = getContext().getObjectFileInfo()->getBSSSection(); 434 pushSection(); 435 switchSection(Section); 436 emitValueToAlignment(ByteAlignment, 0, 1, 0); 437 emitLabel(Symbol); 438 Symbol->setExternal(false); 439 emitZeros(Size); 440 popSection(); 441 } 442 443 void MCWinCOFFStreamer::emitWeakReference(MCSymbol *AliasS, 444 const MCSymbol *Symbol) { 445 auto *Alias = cast<MCSymbolCOFF>(AliasS); 446 emitSymbolAttribute(Alias, MCSA_Weak); 447 448 getAssembler().registerSymbol(*Symbol); 449 Alias->setVariableValue(MCSymbolRefExpr::create( 450 Symbol, MCSymbolRefExpr::VK_WEAKREF, getContext())); 451 } 452 453 void MCWinCOFFStreamer::emitZerofill(MCSection *Section, MCSymbol *Symbol, 454 uint64_t Size, Align ByteAlignment, 455 SMLoc Loc) { 456 llvm_unreachable("not implemented"); 457 } 458 459 void MCWinCOFFStreamer::emitTBSSSymbol(MCSection *Section, MCSymbol *Symbol, 460 uint64_t Size, Align ByteAlignment) { 461 llvm_unreachable("not implemented"); 462 } 463 464 // TODO: Implement this if you want to emit .comment section in COFF obj files. 465 void MCWinCOFFStreamer::emitIdent(StringRef IdentString) { 466 llvm_unreachable("not implemented"); 467 } 468 469 void MCWinCOFFStreamer::emitWinEHHandlerData(SMLoc Loc) { 470 llvm_unreachable("not implemented"); 471 } 472 473 void MCWinCOFFStreamer::emitCGProfileEntry(const MCSymbolRefExpr *From, 474 const MCSymbolRefExpr *To, 475 uint64_t Count) { 476 // Ignore temporary symbols for now. 477 if (!From->getSymbol().isTemporary() && !To->getSymbol().isTemporary()) 478 getWriter().getCGProfile().push_back({From, To, Count}); 479 } 480 481 void MCWinCOFFStreamer::finalizeCGProfileEntry(const MCSymbolRefExpr *&SRE) { 482 const MCSymbol *S = &SRE->getSymbol(); 483 if (getAssembler().registerSymbol(*S)) 484 cast<MCSymbolCOFF>(S)->setExternal(true); 485 } 486 487 void MCWinCOFFStreamer::finishImpl() { 488 getContext().getCVContext().finish(); 489 MCAssembler &Asm = getAssembler(); 490 if (Asm.getWriter().getEmitAddrsigSection()) { 491 // Register the section. 492 switchSection(Asm.getContext().getCOFFSection(".llvm_addrsig", 493 COFF::IMAGE_SCN_LNK_REMOVE)); 494 } 495 if (!Asm.getWriter().getCGProfile().empty()) { 496 for (auto &E : Asm.getWriter().getCGProfile()) { 497 finalizeCGProfileEntry(E.From); 498 finalizeCGProfileEntry(E.To); 499 } 500 switchSection(Asm.getContext().getCOFFSection(".llvm.call-graph-profile", 501 COFF::IMAGE_SCN_LNK_REMOVE)); 502 } 503 504 MCObjectStreamer::finishImpl(); 505 } 506 507 void MCWinCOFFStreamer::Error(const Twine &Msg) const { 508 getContext().reportError(SMLoc(), Msg); 509 } 510