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