void WinCOFFObjectWriter::WriteObject(MCAssembler &Asm, const MCAsmLayout &Layout) { // Assign symbol and section indexes and offsets. Header.NumberOfSections = 0; DenseMap<COFFSection *, uint16_t> SectionIndices; for (sections::iterator i = Sections.begin(), e = Sections.end(); i != e; i++) { if (Layout.getSectionAddressSize((*i)->MCData) > 0) { size_t Number = ++Header.NumberOfSections; SectionIndices[*i] = Number; MakeSectionReal(**i, Number); } else { (*i)->Number = -1; } } Header.NumberOfSymbols = 0; for (symbols::iterator i = Symbols.begin(), e = Symbols.end(); i != e; i++) { COFFSymbol *coff_symbol = *i; MCSymbolData const *SymbolData = coff_symbol->MCData; // Update section number & offset for symbols that have them. if ((SymbolData != NULL) && (SymbolData->Fragment != NULL)) { assert(coff_symbol->Section != NULL); coff_symbol->Data.SectionNumber = coff_symbol->Section->Number; coff_symbol->Data.Value = Layout.getFragmentOffset(SymbolData->Fragment) + SymbolData->Offset; } if (coff_symbol->should_keep()) { MakeSymbolReal(*coff_symbol, Header.NumberOfSymbols++); // Update auxiliary symbol info. coff_symbol->Data.NumberOfAuxSymbols = coff_symbol->Aux.size(); Header.NumberOfSymbols += coff_symbol->Data.NumberOfAuxSymbols; } else coff_symbol->Index = -1; } // Fixup weak external references. for (symbols::iterator i = Symbols.begin(), e = Symbols.end(); i != e; i++) { COFFSymbol *coff_symbol = *i; if (coff_symbol->Other != NULL) { assert(coff_symbol->Index != -1); assert(coff_symbol->Aux.size() == 1 && "Symbol must contain one aux symbol!"); assert(coff_symbol->Aux[0].AuxType == ATWeakExternal && "Symbol's aux symbol must be a Weak External!"); coff_symbol->Aux[0].Aux.WeakExternal.TagIndex = coff_symbol->Other->Index; } } // Fixup associative COMDAT sections. for (sections::iterator i = Sections.begin(), e = Sections.end(); i != e; i++) { if ((*i)->Symbol->Aux[0].Aux.SectionDefinition.Selection != COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE) continue; const MCSectionCOFF &MCSec = static_cast<const MCSectionCOFF &>( (*i)->MCData->getSection()); COFFSection *Assoc = SectionMap.lookup(MCSec.getAssocSection()); if (!Assoc) { report_fatal_error(Twine("Missing associated COMDAT section ") + MCSec.getAssocSection()->getSectionName() + " for section " + MCSec.getSectionName()); } // Skip this section if the associated section is unused. if (Assoc->Number == -1) continue; (*i)->Symbol->Aux[0].Aux.SectionDefinition.Number = SectionIndices[Assoc]; } // Assign file offsets to COFF object file structures. unsigned offset = 0; offset += COFF::HeaderSize; offset += COFF::SectionSize * Header.NumberOfSections; for (MCAssembler::const_iterator i = Asm.begin(), e = Asm.end(); i != e; i++) { COFFSection *Sec = SectionMap[&i->getSection()]; if (Sec->Number == -1) continue; Sec->Header.SizeOfRawData = Layout.getSectionAddressSize(i); if (IsPhysicalSection(Sec)) { Sec->Header.PointerToRawData = offset; offset += Sec->Header.SizeOfRawData; } if (Sec->Relocations.size() > 0) { bool RelocationsOverflow = Sec->Relocations.size() >= 0xffff; if (RelocationsOverflow) { // Signal overflow by setting NumberOfSections to max value. Actual // size is found in reloc #0. Microsoft tools understand this. Sec->Header.NumberOfRelocations = 0xffff; } else { Sec->Header.NumberOfRelocations = Sec->Relocations.size(); } Sec->Header.PointerToRelocations = offset; if (RelocationsOverflow) { // Reloc #0 will contain actual count, so make room for it. offset += COFF::RelocationSize; } offset += COFF::RelocationSize * Sec->Relocations.size(); for (relocations::iterator cr = Sec->Relocations.begin(), er = Sec->Relocations.end(); cr != er; ++cr) { assert((*cr).Symb->Index != -1); (*cr).Data.SymbolTableIndex = (*cr).Symb->Index; } } assert(Sec->Symbol->Aux.size() == 1 && "Section's symbol must have one aux!"); AuxSymbol &Aux = Sec->Symbol->Aux[0]; assert(Aux.AuxType == ATSectionDefinition && "Section's symbol's aux symbol must be a Section Definition!"); Aux.Aux.SectionDefinition.Length = Sec->Header.SizeOfRawData; Aux.Aux.SectionDefinition.NumberOfRelocations = Sec->Header.NumberOfRelocations; Aux.Aux.SectionDefinition.NumberOfLinenumbers = Sec->Header.NumberOfLineNumbers; } Header.PointerToSymbolTable = offset; Header.TimeDateStamp = sys::TimeValue::now().toEpochTime(); // Write it all to disk... WriteFileHeader(Header); { sections::iterator i, ie; MCAssembler::const_iterator j, je; for (i = Sections.begin(), ie = Sections.end(); i != ie; i++) if ((*i)->Number != -1) { if ((*i)->Relocations.size() >= 0xffff) { (*i)->Header.Characteristics |= COFF::IMAGE_SCN_LNK_NRELOC_OVFL; } WriteSectionHeader((*i)->Header); } for (i = Sections.begin(), ie = Sections.end(), j = Asm.begin(), je = Asm.end(); (i != ie) && (j != je); ++i, ++j) { if ((*i)->Number == -1) continue; if ((*i)->Header.PointerToRawData != 0) { assert(OS.tell() == (*i)->Header.PointerToRawData && "Section::PointerToRawData is insane!"); Asm.writeSectionData(j, Layout); } if ((*i)->Relocations.size() > 0) { assert(OS.tell() == (*i)->Header.PointerToRelocations && "Section::PointerToRelocations is insane!"); if ((*i)->Relocations.size() >= 0xffff) { // In case of overflow, write actual relocation count as first // relocation. Including the synthetic reloc itself (+ 1). COFF::relocation r; r.VirtualAddress = (*i)->Relocations.size() + 1; r.SymbolTableIndex = 0; r.Type = 0; WriteRelocation(r); } for (relocations::const_iterator k = (*i)->Relocations.begin(), ke = (*i)->Relocations.end(); k != ke; k++) { WriteRelocation(k->Data); } } else assert((*i)->Header.PointerToRelocations == 0 && "Section::PointerToRelocations is insane!"); } } assert(OS.tell() == Header.PointerToSymbolTable && "Header::PointerToSymbolTable is insane!"); for (symbols::iterator i = Symbols.begin(), e = Symbols.end(); i != e; i++) if ((*i)->Index != -1) WriteSymbol(*i); OS.write((char const *)&Strings.Data.front(), Strings.Data.size()); }
void WinCOFFObjectWriter::WriteObject(MCAssembler &Asm, const MCAsmLayout &Layout) { // Assign symbol and section indexes and offsets. Header.NumberOfSections = 0; for (sections::iterator i = Sections.begin(), e = Sections.end(); i != e; i++) { if (Layout.getSectionAddressSize((*i)->MCData) > 0) { MakeSectionReal(**i, ++Header.NumberOfSections); } else { (*i)->Number = -1; } } Header.NumberOfSymbols = 0; for (symbols::iterator i = Symbols.begin(), e = Symbols.end(); i != e; i++) { COFFSymbol *coff_symbol = *i; MCSymbolData const *SymbolData = coff_symbol->MCData; // Update section number & offset for symbols that have them. if ((SymbolData != NULL) && (SymbolData->Fragment != NULL)) { assert(coff_symbol->Section != NULL); coff_symbol->Data.SectionNumber = coff_symbol->Section->Number; coff_symbol->Data.Value = Layout.getFragmentOffset(SymbolData->Fragment) + SymbolData->Offset; } if (coff_symbol->should_keep()) { MakeSymbolReal(*coff_symbol, Header.NumberOfSymbols++); // Update auxiliary symbol info. coff_symbol->Data.NumberOfAuxSymbols = coff_symbol->Aux.size(); Header.NumberOfSymbols += coff_symbol->Data.NumberOfAuxSymbols; } else coff_symbol->Index = -1; } // Fixup weak external references. for (symbols::iterator i = Symbols.begin(), e = Symbols.end(); i != e; i++) { COFFSymbol *coff_symbol = *i; if (coff_symbol->Other != NULL) { assert(coff_symbol->Index != -1); assert(coff_symbol->Aux.size() == 1 && "Symbol must contain one aux symbol!"); assert(coff_symbol->Aux[0].AuxType == ATWeakExternal && "Symbol's aux symbol must be a Weak External!"); coff_symbol->Aux[0].Aux.WeakExternal.TagIndex = coff_symbol->Other->Index; } } // Assign file offsets to COFF object file structures. unsigned offset = 0; offset += COFF::HeaderSize; offset += COFF::SectionSize * Header.NumberOfSections; for (MCAssembler::const_iterator i = Asm.begin(), e = Asm.end(); i != e; i++) { COFFSection *Sec = SectionMap[&i->getSection()]; if (Sec->Number == -1) continue; Sec->Header.SizeOfRawData = Layout.getSectionAddressSize(i); if (IsPhysicalSection(Sec)) { Sec->Header.PointerToRawData = offset; offset += Sec->Header.SizeOfRawData; } if (Sec->Relocations.size() > 0) { Sec->Header.NumberOfRelocations = Sec->Relocations.size(); Sec->Header.PointerToRelocations = offset; offset += COFF::RelocationSize * Sec->Relocations.size(); for (relocations::iterator cr = Sec->Relocations.begin(), er = Sec->Relocations.end(); cr != er; ++cr) { assert((*cr).Symb->Index != -1); (*cr).Data.SymbolTableIndex = (*cr).Symb->Index; } } assert(Sec->Symbol->Aux.size() == 1 && "Section's symbol must have one aux!"); AuxSymbol &Aux = Sec->Symbol->Aux[0]; assert(Aux.AuxType == ATSectionDefinition && "Section's symbol's aux symbol must be a Section Definition!"); Aux.Aux.SectionDefinition.Length = Sec->Header.SizeOfRawData; Aux.Aux.SectionDefinition.NumberOfRelocations = Sec->Header.NumberOfRelocations; Aux.Aux.SectionDefinition.NumberOfLinenumbers = Sec->Header.NumberOfLineNumbers; } Header.PointerToSymbolTable = offset; Header.TimeDateStamp = sys::TimeValue::now().toEpochTime(); // Write it all to disk... WriteFileHeader(Header); { sections::iterator i, ie; MCAssembler::const_iterator j, je; for (i = Sections.begin(), ie = Sections.end(); i != ie; i++) if ((*i)->Number != -1) WriteSectionHeader((*i)->Header); for (i = Sections.begin(), ie = Sections.end(), j = Asm.begin(), je = Asm.end(); (i != ie) && (j != je); ++i, ++j) { if ((*i)->Number == -1) continue; if ((*i)->Header.PointerToRawData != 0) { assert(OS.tell() == (*i)->Header.PointerToRawData && "Section::PointerToRawData is insane!"); Asm.writeSectionData(j, Layout); } if ((*i)->Relocations.size() > 0) { assert(OS.tell() == (*i)->Header.PointerToRelocations && "Section::PointerToRelocations is insane!"); for (relocations::const_iterator k = (*i)->Relocations.begin(), ke = (*i)->Relocations.end(); k != ke; k++) { WriteRelocation(k->Data); } } else assert((*i)->Header.PointerToRelocations == 0 && "Section::PointerToRelocations is insane!"); } } assert(OS.tell() == Header.PointerToSymbolTable && "Header::PointerToSymbolTable is insane!"); for (symbols::iterator i = Symbols.begin(), e = Symbols.end(); i != e; i++) if ((*i)->Index != -1) WriteSymbol(*i); OS.write((char const *)&Strings.Data.front(), Strings.Data.size()); }