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