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