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/MCStreamer.h" 17 #include "llvm/MC/MCAsmBackend.h" 18 #include "llvm/MC/MCAsmLayout.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/MCObjectStreamer.h" 24 #include "llvm/MC/MCSection.h" 25 #include "llvm/MC/MCSectionCOFF.h" 26 #include "llvm/MC/MCSymbol.h" 27 #include "llvm/MC/MCValue.h" 28 #include "llvm/MC/MCWin64EH.h" 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 InitToTextSection(); 54 virtual void EmitLabel(MCSymbol *Symbol); 55 virtual void EmitDebugLabel(MCSymbol *Symbol); 56 virtual void EmitAssemblerFlag(MCAssemblerFlag Flag); 57 virtual void EmitThumbFunc(MCSymbol *Func); 58 virtual void EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute); 59 virtual void EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue); 60 virtual void BeginCOFFSymbolDef(MCSymbol const *Symbol); 61 virtual void EmitCOFFSymbolStorageClass(int StorageClass); 62 virtual void EmitCOFFSymbolType(int Type); 63 virtual void EndCOFFSymbolDef(); 64 virtual void EmitCOFFSecRel32(MCSymbol const *Symbol); 65 virtual void EmitELFSize(MCSymbol *Symbol, const MCExpr *Value); 66 virtual void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, 67 unsigned ByteAlignment); 68 virtual void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size, 69 unsigned ByteAlignment); 70 virtual void EmitZerofill(const MCSection *Section, MCSymbol *Symbol, 71 uint64_t Size,unsigned ByteAlignment); 72 virtual void EmitTBSSSymbol(const MCSection *Section, MCSymbol *Symbol, 73 uint64_t Size, unsigned ByteAlignment); 74 virtual void EmitFileDirective(StringRef Filename); 75 virtual void EmitWin64EHHandlerData(); 76 virtual void FinishImpl(); 77 78 static bool classof(const MCStreamer *S) { 79 return S->getKind() == SK_WinCOFFStreamer; 80 } 81 82 private: 83 virtual void EmitInstToData(const MCInst &Inst) { 84 MCDataFragment *DF = getOrCreateDataFragment(); 85 86 SmallVector<MCFixup, 4> Fixups; 87 SmallString<256> Code; 88 raw_svector_ostream VecOS(Code); 89 getAssembler().getEmitter().EncodeInstruction(Inst, VecOS, Fixups); 90 VecOS.flush(); 91 92 // Add the fixups and data. 93 for (unsigned i = 0, e = Fixups.size(); i != e; ++i) { 94 Fixups[i].setOffset(Fixups[i].getOffset() + DF->getContents().size()); 95 DF->getFixups().push_back(Fixups[i]); 96 } 97 DF->getContents().append(Code.begin(), Code.end()); 98 } 99 100 void SetSection(StringRef Section, 101 unsigned Characteristics, 102 SectionKind Kind) { 103 SwitchSection(getContext().getCOFFSection(Section, Characteristics, Kind)); 104 } 105 106 void SetSectionText() { 107 SetSection(".text", 108 COFF::IMAGE_SCN_CNT_CODE 109 | COFF::IMAGE_SCN_MEM_EXECUTE 110 | COFF::IMAGE_SCN_MEM_READ, 111 SectionKind::getText()); 112 EmitCodeAlignment(4, 0); 113 } 114 115 void SetSectionData() { 116 SetSection(".data", 117 COFF::IMAGE_SCN_CNT_INITIALIZED_DATA 118 | COFF::IMAGE_SCN_MEM_READ 119 | COFF::IMAGE_SCN_MEM_WRITE, 120 SectionKind::getDataRel()); 121 EmitCodeAlignment(4, 0); 122 } 123 124 void SetSectionBSS() { 125 SetSection(".bss", 126 COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA 127 | COFF::IMAGE_SCN_MEM_READ 128 | COFF::IMAGE_SCN_MEM_WRITE, 129 SectionKind::getBSS()); 130 EmitCodeAlignment(4, 0); 131 } 132 }; 133 } // end anonymous namespace. 134 135 WinCOFFStreamer::WinCOFFStreamer(MCContext &Context, MCAsmBackend &MAB, 136 MCCodeEmitter &CE, raw_ostream &OS) 137 : MCObjectStreamer(SK_WinCOFFStreamer, Context, MAB, OS, &CE), 138 CurSymbol(NULL) {} 139 140 void WinCOFFStreamer::AddCommonSymbol(MCSymbol *Symbol, uint64_t Size, 141 unsigned ByteAlignment, bool External) { 142 assert(!Symbol->isInSection() && "Symbol must not already have a section!"); 143 144 std::string SectionName(".bss$linkonce"); 145 SectionName.append(Symbol->getName().begin(), Symbol->getName().end()); 146 147 MCSymbolData &SymbolData = getAssembler().getOrCreateSymbolData(*Symbol); 148 149 unsigned Characteristics = 150 COFF::IMAGE_SCN_LNK_COMDAT | 151 COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA | 152 COFF::IMAGE_SCN_MEM_READ | 153 COFF::IMAGE_SCN_MEM_WRITE; 154 155 int Selection = COFF::IMAGE_COMDAT_SELECT_LARGEST; 156 157 const MCSection *Section = MCStreamer::getContext().getCOFFSection( 158 SectionName, Characteristics, Selection, SectionKind::getBSS()); 159 160 MCSectionData &SectionData = getAssembler().getOrCreateSectionData(*Section); 161 162 if (SectionData.getAlignment() < ByteAlignment) 163 SectionData.setAlignment(ByteAlignment); 164 165 SymbolData.setExternal(External); 166 167 Symbol->setSection(*Section); 168 169 if (ByteAlignment != 1) 170 new MCAlignFragment(ByteAlignment, 0, 0, ByteAlignment, &SectionData); 171 172 SymbolData.setFragment(new MCFillFragment(0, 0, Size, &SectionData)); 173 } 174 175 // MCStreamer interface 176 177 void WinCOFFStreamer::InitToTextSection() { 178 SetSectionText(); 179 } 180 181 void WinCOFFStreamer::InitSections() { 182 SetSectionText(); 183 SetSectionData(); 184 SetSectionBSS(); 185 SetSectionText(); 186 } 187 188 void WinCOFFStreamer::EmitLabel(MCSymbol *Symbol) { 189 assert(Symbol->isUndefined() && "Cannot define a symbol twice!"); 190 MCObjectStreamer::EmitLabel(Symbol); 191 } 192 193 void WinCOFFStreamer::EmitDebugLabel(MCSymbol *Symbol) { 194 EmitLabel(Symbol); 195 } 196 void WinCOFFStreamer::EmitAssemblerFlag(MCAssemblerFlag Flag) { 197 llvm_unreachable("not implemented"); 198 } 199 200 void WinCOFFStreamer::EmitThumbFunc(MCSymbol *Func) { 201 llvm_unreachable("not implemented"); 202 } 203 204 void WinCOFFStreamer::EmitSymbolAttribute(MCSymbol *Symbol, 205 MCSymbolAttr Attribute) { 206 assert(Symbol && "Symbol must be non-null!"); 207 assert((Symbol->isInSection() 208 ? Symbol->getSection().getVariant() == MCSection::SV_COFF 209 : true) && "Got non COFF section in the COFF backend!"); 210 switch (Attribute) { 211 case MCSA_WeakReference: 212 case MCSA_Weak: { 213 MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*Symbol); 214 SD.modifyFlags(COFF::SF_WeakExternal, COFF::SF_WeakExternal); 215 SD.setExternal(true); 216 } 217 break; 218 219 case MCSA_Global: 220 getAssembler().getOrCreateSymbolData(*Symbol).setExternal(true); 221 break; 222 223 default: 224 llvm_unreachable("unsupported attribute"); 225 } 226 } 227 228 void WinCOFFStreamer::EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) { 229 llvm_unreachable("not implemented"); 230 } 231 232 void WinCOFFStreamer::BeginCOFFSymbolDef(MCSymbol const *Symbol) { 233 assert((Symbol->isInSection() 234 ? Symbol->getSection().getVariant() == MCSection::SV_COFF 235 : true) && "Got non COFF section in the COFF backend!"); 236 assert(CurSymbol == NULL && "EndCOFFSymbolDef must be called between calls " 237 "to BeginCOFFSymbolDef!"); 238 CurSymbol = Symbol; 239 } 240 241 void WinCOFFStreamer::EmitCOFFSymbolStorageClass(int StorageClass) { 242 assert(CurSymbol != NULL && "BeginCOFFSymbolDef must be called first!"); 243 assert((StorageClass & ~0xFF) == 0 && "StorageClass must only have data in " 244 "the first byte!"); 245 246 getAssembler().getOrCreateSymbolData(*CurSymbol).modifyFlags( 247 StorageClass << COFF::SF_ClassShift, 248 COFF::SF_ClassMask); 249 } 250 251 void WinCOFFStreamer::EmitCOFFSymbolType(int Type) { 252 assert(CurSymbol != NULL && "BeginCOFFSymbolDef must be called first!"); 253 assert((Type & ~0xFFFF) == 0 && "Type must only have data in the first 2 " 254 "bytes"); 255 256 getAssembler().getOrCreateSymbolData(*CurSymbol).modifyFlags( 257 Type << COFF::SF_TypeShift, 258 COFF::SF_TypeMask); 259 } 260 261 void WinCOFFStreamer::EndCOFFSymbolDef() { 262 assert(CurSymbol != NULL && "BeginCOFFSymbolDef must be called first!"); 263 CurSymbol = NULL; 264 } 265 266 void WinCOFFStreamer::EmitCOFFSecRel32(MCSymbol const *Symbol) 267 { 268 MCDataFragment *DF = getOrCreateDataFragment(); 269 270 DF->getFixups().push_back( 271 MCFixup::Create(DF->getContents().size(), 272 MCSymbolRefExpr::Create (Symbol, getContext ()), 273 FK_SecRel_4)); 274 DF->getContents().resize(DF->getContents().size() + 4, 0); 275 } 276 277 void WinCOFFStreamer::EmitELFSize(MCSymbol *Symbol, const MCExpr *Value) { 278 llvm_unreachable("not implemented"); 279 } 280 281 void WinCOFFStreamer::EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, 282 unsigned ByteAlignment) { 283 assert((Symbol->isInSection() 284 ? Symbol->getSection().getVariant() == MCSection::SV_COFF 285 : true) && "Got non COFF section in the COFF backend!"); 286 AddCommonSymbol(Symbol, Size, ByteAlignment, true); 287 } 288 289 void WinCOFFStreamer::EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size, 290 unsigned ByteAlignment) { 291 assert((Symbol->isInSection() 292 ? Symbol->getSection().getVariant() == MCSection::SV_COFF 293 : true) && "Got non COFF section in the COFF backend!"); 294 AddCommonSymbol(Symbol, Size, ByteAlignment, false); 295 } 296 297 void WinCOFFStreamer::EmitZerofill(const MCSection *Section, MCSymbol *Symbol, 298 uint64_t Size,unsigned ByteAlignment) { 299 llvm_unreachable("not implemented"); 300 } 301 302 void WinCOFFStreamer::EmitTBSSSymbol(const MCSection *Section, MCSymbol *Symbol, 303 uint64_t Size, unsigned ByteAlignment) { 304 llvm_unreachable("not implemented"); 305 } 306 307 void WinCOFFStreamer::EmitFileDirective(StringRef Filename) { 308 // Ignore for now, linkers don't care, and proper debug 309 // info will be a much large effort. 310 } 311 312 void WinCOFFStreamer::EmitWin64EHHandlerData() { 313 MCStreamer::EmitWin64EHHandlerData(); 314 315 // We have to emit the unwind info now, because this directive 316 // actually switches to the .xdata section! 317 MCWin64EHUnwindEmitter::EmitUnwindInfo(*this, getCurrentW64UnwindInfo()); 318 } 319 320 void WinCOFFStreamer::FinishImpl() { 321 EmitW64Tables(); 322 MCObjectStreamer::FinishImpl(); 323 } 324 325 namespace llvm 326 { 327 MCStreamer *createWinCOFFStreamer(MCContext &Context, 328 MCAsmBackend &MAB, 329 MCCodeEmitter &CE, 330 raw_ostream &OS, 331 bool RelaxAll) { 332 WinCOFFStreamer *S = new WinCOFFStreamer(Context, MAB, CE, OS); 333 S->getAssembler().setRelaxAll(RelaxAll); 334 return S; 335 } 336 } 337