LCOV - code coverage report
Current view: top level - lib/MC - MCWinCOFFStreamer.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 130 145 89.7 %
Date: 2018-09-23 13:06:45 Functions: 18 25 72.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13