Home | History | Annotate | Download | only in MC
      1 //===-- llvm/MC/WinCOFFStreamer.cpp -----------------------------*- C++ -*-===//
      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 Win32 COFF object file streamer.
     11 //
     12 //===----------------------------------------------------------------------===//
     13 
     14 #define DEBUG_TYPE "WinCOFFStreamer"
     15 
     16 #include "llvm/MC/MCObjectStreamer.h"
     17 #include "llvm/MC/MCContext.h"
     18 #include "llvm/MC/MCSection.h"
     19 #include "llvm/MC/MCSymbol.h"
     20 #include "llvm/MC/MCExpr.h"
     21 #include "llvm/MC/MCValue.h"
     22 #include "llvm/MC/MCAssembler.h"
     23 #include "llvm/MC/MCAsmLayout.h"
     24 #include "llvm/MC/MCCodeEmitter.h"
     25 #include "llvm/MC/MCSectionCOFF.h"
     26 #include "llvm/MC/MCWin64EH.h"
     27 #include "llvm/MC/MCAsmBackend.h"
     28 
     29 #include "llvm/Support/COFF.h"
     30 #include "llvm/Support/Debug.h"
     31 #include "llvm/Support/ErrorHandling.h"
     32 #include "llvm/Support/TargetRegistry.h"
     33 #include "llvm/Support/raw_ostream.h"
     34 
     35 using namespace llvm;
     36 
     37 namespace {
     38 class WinCOFFStreamer : public MCObjectStreamer {
     39 public:
     40   MCSymbol const *CurSymbol;
     41 
     42   WinCOFFStreamer(MCContext &Context,
     43                   MCAsmBackend &MAB,
     44                   MCCodeEmitter &CE,
     45                   raw_ostream &OS);
     46 
     47   void AddCommonSymbol(MCSymbol *Symbol, uint64_t Size,
     48                        unsigned ByteAlignment, bool External);
     49 
     50   // MCStreamer interface
     51 
     52   virtual void InitSections();
     53   virtual void EmitLabel(MCSymbol *Symbol);
     54   virtual void EmitAssemblerFlag(MCAssemblerFlag Flag);
     55   virtual void EmitThumbFunc(MCSymbol *Func);
     56   virtual void EmitAssignment(MCSymbol *Symbol, const MCExpr *Value);
     57   virtual void EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute);
     58   virtual void EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue);
     59   virtual void BeginCOFFSymbolDef(MCSymbol const *Symbol);
     60   virtual void EmitCOFFSymbolStorageClass(int StorageClass);
     61   virtual void EmitCOFFSymbolType(int Type);
     62   virtual void EndCOFFSymbolDef();
     63   virtual void EmitCOFFSecRel32(MCSymbol const *Symbol);
     64   virtual void EmitELFSize(MCSymbol *Symbol, const MCExpr *Value);
     65   virtual void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
     66                                 unsigned ByteAlignment);
     67   virtual void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,
     68                                      unsigned ByteAlignment);
     69   virtual void EmitZerofill(const MCSection *Section, MCSymbol *Symbol,
     70                             unsigned Size,unsigned ByteAlignment);
     71   virtual void EmitTBSSSymbol(const MCSection *Section, MCSymbol *Symbol,
     72                               uint64_t Size, unsigned ByteAlignment);
     73   virtual void EmitBytes(StringRef Data, unsigned AddrSpace);
     74   virtual void EmitValueToAlignment(unsigned ByteAlignment, int64_t Value,
     75                                    unsigned ValueSize, unsigned MaxBytesToEmit);
     76   virtual void EmitCodeAlignment(unsigned ByteAlignment,
     77                                  unsigned MaxBytesToEmit);
     78   virtual void EmitFileDirective(StringRef Filename);
     79   virtual void EmitInstruction(const MCInst &Instruction);
     80   virtual void EmitWin64EHHandlerData();
     81   virtual void FinishImpl();
     82 
     83 private:
     84   virtual void EmitInstToFragment(const MCInst &Inst) {
     85     llvm_unreachable("Not used by WinCOFF.");
     86   }
     87   virtual void EmitInstToData(const MCInst &Inst) {
     88     llvm_unreachable("Not used by WinCOFF.");
     89   }
     90 
     91   void SetSection(StringRef Section,
     92                   unsigned Characteristics,
     93                   SectionKind Kind) {
     94     SwitchSection(getContext().getCOFFSection(Section, Characteristics, Kind));
     95   }
     96 
     97   void SetSectionText() {
     98     SetSection(".text",
     99                COFF::IMAGE_SCN_CNT_CODE
    100              | COFF::IMAGE_SCN_MEM_EXECUTE
    101              | COFF::IMAGE_SCN_MEM_READ,
    102                SectionKind::getText());
    103     EmitCodeAlignment(4, 0);
    104   }
    105 
    106   void SetSectionData() {
    107     SetSection(".data",
    108                COFF::IMAGE_SCN_CNT_INITIALIZED_DATA
    109              | COFF::IMAGE_SCN_MEM_READ
    110              | COFF::IMAGE_SCN_MEM_WRITE,
    111                SectionKind::getDataRel());
    112     EmitCodeAlignment(4, 0);
    113   }
    114 
    115   void SetSectionBSS() {
    116     SetSection(".bss",
    117                COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA
    118              | COFF::IMAGE_SCN_MEM_READ
    119              | COFF::IMAGE_SCN_MEM_WRITE,
    120                SectionKind::getBSS());
    121     EmitCodeAlignment(4, 0);
    122   }
    123 
    124 };
    125 } // end anonymous namespace.
    126 
    127 WinCOFFStreamer::WinCOFFStreamer(MCContext &Context,
    128                                  MCAsmBackend &MAB,
    129                                  MCCodeEmitter &CE,
    130                                  raw_ostream &OS)
    131     : MCObjectStreamer(Context, MAB, OS, &CE)
    132     , CurSymbol(NULL) {
    133 }
    134 
    135 void WinCOFFStreamer::AddCommonSymbol(MCSymbol *Symbol, uint64_t Size,
    136                                       unsigned ByteAlignment, bool External) {
    137   assert(!Symbol->isInSection() && "Symbol must not already have a section!");
    138 
    139   std::string SectionName(".bss$linkonce");
    140   SectionName.append(Symbol->getName().begin(), Symbol->getName().end());
    141 
    142   MCSymbolData &SymbolData = getAssembler().getOrCreateSymbolData(*Symbol);
    143 
    144   unsigned Characteristics =
    145     COFF::IMAGE_SCN_LNK_COMDAT |
    146     COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA |
    147     COFF::IMAGE_SCN_MEM_READ |
    148     COFF::IMAGE_SCN_MEM_WRITE;
    149 
    150   int Selection = COFF::IMAGE_COMDAT_SELECT_LARGEST;
    151 
    152   const MCSection *Section = MCStreamer::getContext().getCOFFSection(
    153     SectionName, Characteristics, Selection, SectionKind::getBSS());
    154 
    155   MCSectionData &SectionData = getAssembler().getOrCreateSectionData(*Section);
    156 
    157   if (SectionData.getAlignment() < ByteAlignment)
    158     SectionData.setAlignment(ByteAlignment);
    159 
    160   SymbolData.setExternal(External);
    161 
    162   Symbol->setSection(*Section);
    163 
    164   if (ByteAlignment != 1)
    165       new MCAlignFragment(ByteAlignment, 0, 0, ByteAlignment, &SectionData);
    166 
    167   SymbolData.setFragment(new MCFillFragment(0, 0, Size, &SectionData));
    168 }
    169 
    170 // MCStreamer interface
    171 
    172 void WinCOFFStreamer::InitSections() {
    173   SetSectionText();
    174   SetSectionData();
    175   SetSectionBSS();
    176   SetSectionText();
    177 }
    178 
    179 void WinCOFFStreamer::EmitLabel(MCSymbol *Symbol) {
    180   assert(Symbol->isUndefined() && "Cannot define a symbol twice!");
    181   MCObjectStreamer::EmitLabel(Symbol);
    182 }
    183 
    184 void WinCOFFStreamer::EmitAssemblerFlag(MCAssemblerFlag Flag) {
    185   llvm_unreachable("not implemented");
    186 }
    187 
    188 void WinCOFFStreamer::EmitThumbFunc(MCSymbol *Func) {
    189   llvm_unreachable("not implemented");
    190 }
    191 
    192 void WinCOFFStreamer::EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) {
    193   assert((Symbol->isInSection()
    194          ? Symbol->getSection().getVariant() == MCSection::SV_COFF
    195          : true) && "Got non COFF section in the COFF backend!");
    196   // FIXME: This is all very ugly and depressing. What needs to happen here
    197   // depends on quite a few things that are all part of relaxation, which we
    198   // don't really even do.
    199 
    200   if (Value->getKind() != MCExpr::SymbolRef) {
    201     // TODO: This is exactly the same as MachOStreamer. Consider merging into
    202     // MCObjectStreamer.
    203     getAssembler().getOrCreateSymbolData(*Symbol);
    204     AddValueSymbols(Value);
    205     Symbol->setVariableValue(Value);
    206   } else {
    207     // FIXME: This is a horrible way to do this :(. This should really be
    208     // handled after we are done with the MC* objects and immediately before
    209     // writing out the object file when we know exactly what the symbol should
    210     // look like in the coff symbol table. I'm not doing that now because the
    211     // COFF object writer doesn't have a clearly defined separation between MC
    212     // data structures, the object writers data structures, and the raw, POD,
    213     // data structures that get written to disk.
    214 
    215     // Copy over the aliased data.
    216     MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*Symbol);
    217     const MCSymbolData &RealSD = getAssembler().getOrCreateSymbolData(
    218       dyn_cast<const MCSymbolRefExpr>(Value)->getSymbol());
    219 
    220     // FIXME: This is particularly nasty because it breaks as soon as any data
    221     // members of MCSymbolData change.
    222     SD.CommonAlign     = RealSD.CommonAlign;
    223     SD.CommonSize      = RealSD.CommonSize;
    224     SD.Flags           = RealSD.Flags;
    225     SD.Fragment        = RealSD.Fragment;
    226     SD.Index           = RealSD.Index;
    227     SD.IsExternal      = RealSD.IsExternal;
    228     SD.IsPrivateExtern = RealSD.IsPrivateExtern;
    229     SD.Offset          = RealSD.Offset;
    230     SD.SymbolSize      = RealSD.SymbolSize;
    231   }
    232 }
    233 
    234 void WinCOFFStreamer::EmitSymbolAttribute(MCSymbol *Symbol,
    235                                           MCSymbolAttr Attribute) {
    236   assert(Symbol && "Symbol must be non-null!");
    237   assert((Symbol->isInSection()
    238          ? Symbol->getSection().getVariant() == MCSection::SV_COFF
    239          : true) && "Got non COFF section in the COFF backend!");
    240   switch (Attribute) {
    241   case MCSA_WeakReference:
    242   case MCSA_Weak: {
    243       MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*Symbol);
    244       SD.modifyFlags(COFF::SF_WeakExternal, COFF::SF_WeakExternal);
    245       SD.setExternal(true);
    246     }
    247     break;
    248 
    249   case MCSA_Global:
    250     getAssembler().getOrCreateSymbolData(*Symbol).setExternal(true);
    251     break;
    252 
    253   default:
    254     llvm_unreachable("unsupported attribute");
    255   }
    256 }
    257 
    258 void WinCOFFStreamer::EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) {
    259   llvm_unreachable("not implemented");
    260 }
    261 
    262 void WinCOFFStreamer::BeginCOFFSymbolDef(MCSymbol const *Symbol) {
    263   assert((Symbol->isInSection()
    264          ? Symbol->getSection().getVariant() == MCSection::SV_COFF
    265          : true) && "Got non COFF section in the COFF backend!");
    266   assert(CurSymbol == NULL && "EndCOFFSymbolDef must be called between calls "
    267                               "to BeginCOFFSymbolDef!");
    268   CurSymbol = Symbol;
    269 }
    270 
    271 void WinCOFFStreamer::EmitCOFFSymbolStorageClass(int StorageClass) {
    272   assert(CurSymbol != NULL && "BeginCOFFSymbolDef must be called first!");
    273   assert((StorageClass & ~0xFF) == 0 && "StorageClass must only have data in "
    274                                         "the first byte!");
    275 
    276   getAssembler().getOrCreateSymbolData(*CurSymbol).modifyFlags(
    277     StorageClass << COFF::SF_ClassShift,
    278     COFF::SF_ClassMask);
    279 }
    280 
    281 void WinCOFFStreamer::EmitCOFFSymbolType(int Type) {
    282   assert(CurSymbol != NULL && "BeginCOFFSymbolDef must be called first!");
    283   assert((Type & ~0xFFFF) == 0 && "Type must only have data in the first 2 "
    284                                   "bytes");
    285 
    286   getAssembler().getOrCreateSymbolData(*CurSymbol).modifyFlags(
    287     Type << COFF::SF_TypeShift,
    288     COFF::SF_TypeMask);
    289 }
    290 
    291 void WinCOFFStreamer::EndCOFFSymbolDef() {
    292   assert(CurSymbol != NULL && "BeginCOFFSymbolDef must be called first!");
    293   CurSymbol = NULL;
    294 }
    295 
    296 void WinCOFFStreamer::EmitCOFFSecRel32(MCSymbol const *Symbol)
    297 {
    298   MCDataFragment *DF = getOrCreateDataFragment();
    299 
    300   DF->addFixup(MCFixup::Create(DF->getContents().size(),
    301                                MCSymbolRefExpr::Create (Symbol, getContext ()),
    302                                FK_SecRel_4));
    303   DF->getContents().resize(DF->getContents().size() + 4, 0);
    304 }
    305 
    306 void WinCOFFStreamer::EmitELFSize(MCSymbol *Symbol, const MCExpr *Value) {
    307   llvm_unreachable("not implemented");
    308 }
    309 
    310 void WinCOFFStreamer::EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
    311                                        unsigned ByteAlignment) {
    312   assert((Symbol->isInSection()
    313          ? Symbol->getSection().getVariant() == MCSection::SV_COFF
    314          : true) && "Got non COFF section in the COFF backend!");
    315   AddCommonSymbol(Symbol, Size, ByteAlignment, true);
    316 }
    317 
    318 void WinCOFFStreamer::EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,
    319                                             unsigned ByteAlignment) {
    320   assert((Symbol->isInSection()
    321          ? Symbol->getSection().getVariant() == MCSection::SV_COFF
    322          : true) && "Got non COFF section in the COFF backend!");
    323   AddCommonSymbol(Symbol, Size, ByteAlignment, false);
    324 }
    325 
    326 void WinCOFFStreamer::EmitZerofill(const MCSection *Section, MCSymbol *Symbol,
    327                                    unsigned Size,unsigned ByteAlignment) {
    328   llvm_unreachable("not implemented");
    329 }
    330 
    331 void WinCOFFStreamer::EmitTBSSSymbol(const MCSection *Section, MCSymbol *Symbol,
    332                                      uint64_t Size, unsigned ByteAlignment) {
    333   llvm_unreachable("not implemented");
    334 }
    335 
    336 void WinCOFFStreamer::EmitBytes(StringRef Data, unsigned AddrSpace) {
    337   // TODO: This is copied exactly from the MachOStreamer. Consider merging into
    338   // MCObjectStreamer?
    339   getOrCreateDataFragment()->getContents().append(Data.begin(), Data.end());
    340 }
    341 
    342 void WinCOFFStreamer::EmitValueToAlignment(unsigned ByteAlignment,
    343                                            int64_t Value,
    344                                            unsigned ValueSize,
    345                                            unsigned MaxBytesToEmit) {
    346   // TODO: This is copied exactly from the MachOStreamer. Consider merging into
    347   // MCObjectStreamer?
    348   if (MaxBytesToEmit == 0)
    349     MaxBytesToEmit = ByteAlignment;
    350   new MCAlignFragment(ByteAlignment, Value, ValueSize, MaxBytesToEmit,
    351                       getCurrentSectionData());
    352 
    353   // Update the maximum alignment on the current section if necessary.
    354   if (ByteAlignment > getCurrentSectionData()->getAlignment())
    355     getCurrentSectionData()->setAlignment(ByteAlignment);
    356 }
    357 
    358 void WinCOFFStreamer::EmitCodeAlignment(unsigned ByteAlignment,
    359                                         unsigned MaxBytesToEmit) {
    360   // TODO: This is copied exactly from the MachOStreamer. Consider merging into
    361   // MCObjectStreamer?
    362   if (MaxBytesToEmit == 0)
    363     MaxBytesToEmit = ByteAlignment;
    364   MCAlignFragment *F = new MCAlignFragment(ByteAlignment, 0, 1, MaxBytesToEmit,
    365                                            getCurrentSectionData());
    366   F->setEmitNops(true);
    367 
    368   // Update the maximum alignment on the current section if necessary.
    369   if (ByteAlignment > getCurrentSectionData()->getAlignment())
    370     getCurrentSectionData()->setAlignment(ByteAlignment);
    371 }
    372 
    373 void WinCOFFStreamer::EmitFileDirective(StringRef Filename) {
    374   // Ignore for now, linkers don't care, and proper debug
    375   // info will be a much large effort.
    376 }
    377 
    378 void WinCOFFStreamer::EmitInstruction(const MCInst &Instruction) {
    379   for (unsigned i = 0, e = Instruction.getNumOperands(); i != e; ++i)
    380     if (Instruction.getOperand(i).isExpr())
    381       AddValueSymbols(Instruction.getOperand(i).getExpr());
    382 
    383   getCurrentSectionData()->setHasInstructions(true);
    384 
    385   MCInstFragment *Fragment =
    386     new MCInstFragment(Instruction, getCurrentSectionData());
    387 
    388   raw_svector_ostream VecOS(Fragment->getCode());
    389 
    390   getAssembler().getEmitter().EncodeInstruction(Instruction, VecOS,
    391                                                 Fragment->getFixups());
    392 }
    393 
    394 void WinCOFFStreamer::EmitWin64EHHandlerData() {
    395   MCStreamer::EmitWin64EHHandlerData();
    396 
    397   // We have to emit the unwind info now, because this directive
    398   // actually switches to the .xdata section!
    399   MCWin64EHUnwindEmitter::EmitUnwindInfo(*this, getCurrentW64UnwindInfo());
    400 }
    401 
    402 void WinCOFFStreamer::FinishImpl() {
    403   EmitW64Tables();
    404   MCObjectStreamer::FinishImpl();
    405 }
    406 
    407 namespace llvm
    408 {
    409   MCStreamer *createWinCOFFStreamer(MCContext &Context,
    410                                     MCAsmBackend &MAB,
    411                                     MCCodeEmitter &CE,
    412                                     raw_ostream &OS,
    413                                     bool RelaxAll) {
    414     WinCOFFStreamer *S = new WinCOFFStreamer(Context, MAB, CE, OS);
    415     S->getAssembler().setRelaxAll(RelaxAll);
    416     return S;
    417   }
    418 }
    419