MCAsmLayout::MCAsmLayout(MCAssembler &Asm) : Assembler(Asm), LastValidFragment() { // Compute the section layout order. Virtual sections must go last. for (MCAssembler::iterator it = Asm.begin(), ie = Asm.end(); it != ie; ++it) if (!it->getSection().isVirtualSection()) SectionOrder.push_back(&*it); for (MCAssembler::iterator it = Asm.begin(), ie = Asm.end(); it != ie; ++it) if (it->getSection().isVirtualSection()) SectionOrder.push_back(&*it); }
void WinCOFFObjectWriter::ExecutePostLayoutBinding(MCAssembler &Asm, const MCAsmLayout &Layout) { // "Define" each section & symbol. This creates section & symbol // entries in the staging area. for (MCAssembler::const_iterator i = Asm.begin(), e = Asm.end(); i != e; i++) DefineSection(*i); for (MCAssembler::const_symbol_iterator i = Asm.symbol_begin(), e = Asm.symbol_end(); i != e; i++) { if (ExportSymbol(*i, Asm)) DefineSymbol(*i, Asm); } }
void SVMMemoryLayout::AllocateSections(MCAssembler &Asm, const MCAsmLayout &Layout) { memset(spsMemSize, 0, sizeof spsMemSize); memset(spsDiskSize, 0, sizeof spsDiskSize); bssAlign = 1; // Leave one free block at the beginning of DEBUG, for a special message. spsMemSize[SPS_DEBUG] = SVMTargetMachine::getBlockSize(); spsDiskSize[SPS_DEBUG] = spsMemSize[SPS_DEBUG]; for (MCAssembler::const_iterator it = Asm.begin(), ie = Asm.end(); it != ie; ++it) { const MCSectionData *SD = &*it; SVMProgramSection sps = getSectionKind(SD); switch (sps) { case SPS_BSS: // Also track BSS segment alignment, then fall through... bssAlign = std::max(bssAlign, SD->getAlignment()); case SPS_RO: case SPS_RW_Z: case SPS_RW_PLAIN: case SPS_DEBUG: case SPS_META: spsMemSize[sps] = RoundUpToAlignment(spsMemSize[sps], SD->getAlignment()); spsDiskSize[sps] = RoundUpToAlignment(spsDiskSize[sps], SD->getAlignment()); SectionOffsetMap[SD] = spsDiskSize[sps]; spsMemSize[sps] += getSectionMemSize(SD, Layout); spsDiskSize[sps] += Layout.getSectionAddressSize(SD); break; default: break; } } unsigned memUsed = getSectionMemAddress(SPS_END) - SVMTargetMachine::getRAMBase(); unsigned memMax = SVMTargetMachine::getRAMSize(); if (memUsed > memMax) report_fatal_error("Application is too large to fit in RAM! Need " + Twine(memUsed) + " bytes, which exceeds the maximum of " + Twine(memMax)); }
void WinCOFFObjectWriter::ExecutePostLayoutBinding(MCAssembler &Asm, const MCAsmLayout &Layout) { // "Define" each section & symbol. This creates section & symbol // entries in the staging area. static_assert(sizeof(((COFF::AuxiliaryFile *)nullptr)->FileName) == COFF::SymbolSize, "size mismatch for COFF::AuxiliaryFile::FileName"); for (auto FI = Asm.file_names_begin(), FE = Asm.file_names_end(); FI != FE; ++FI) { // round up to calculate the number of auxiliary symbols required unsigned Count = (FI->size() + COFF::SymbolSize - 1) / COFF::SymbolSize; COFFSymbol *file = createSymbol(".file"); file->Data.StorageClass = COFF::IMAGE_SYM_CLASS_FILE; file->Aux.resize(Count); unsigned Offset = 0; unsigned Length = FI->size(); for (auto & Aux : file->Aux) { Aux.AuxType = ATFile; if (Length > COFF::SymbolSize) { memcpy(Aux.Aux.File.FileName, FI->c_str() + Offset, COFF::SymbolSize); Length = Length - COFF::SymbolSize; } else { memcpy(Aux.Aux.File.FileName, FI->c_str() + Offset, Length); memset(&Aux.Aux.File.FileName[Length], 0, COFF::SymbolSize - Length); Length = 0; } Offset = Offset + COFF::SymbolSize; } } for (MCAssembler::const_iterator i = Asm.begin(), e = Asm.end(); i != e; i++) DefineSection(*i); for (MCSymbolData &SD : Asm.symbols()) if (ExportSymbol(SD, Asm)) DefineSymbol(SD, Asm, Layout); }
/// computeSymbolTable - Compute the symbol table data void MachObjectWriter::computeSymbolTable( MCAssembler &Asm, std::vector<MachSymbolData> &LocalSymbolData, std::vector<MachSymbolData> &ExternalSymbolData, std::vector<MachSymbolData> &UndefinedSymbolData) { // Build section lookup table. DenseMap<const MCSection*, uint8_t> SectionIndexMap; unsigned Index = 1; for (MCAssembler::iterator it = Asm.begin(), ie = Asm.end(); it != ie; ++it, ++Index) SectionIndexMap[&*it] = Index; assert(Index <= 256 && "Too many sections!"); // Build the string table. for (const MCSymbol &Symbol : Asm.symbols()) { if (!Asm.isSymbolLinkerVisible(Symbol)) continue; StringTable.add(Symbol.getName()); } StringTable.finalize(); // Build the symbol arrays but only for non-local symbols. // // The particular order that we collect and then sort the symbols is chosen to // match 'as'. Even though it doesn't matter for correctness, this is // important for letting us diff .o files. for (const MCSymbol &Symbol : Asm.symbols()) { // Ignore non-linker visible symbols. if (!Asm.isSymbolLinkerVisible(Symbol)) continue; if (!Symbol.isExternal() && !Symbol.isUndefined()) continue; MachSymbolData MSD; MSD.Symbol = &Symbol; MSD.StringIndex = StringTable.getOffset(Symbol.getName()); if (Symbol.isUndefined()) { MSD.SectionIndex = 0; UndefinedSymbolData.push_back(MSD); } else if (Symbol.isAbsolute()) { MSD.SectionIndex = 0; ExternalSymbolData.push_back(MSD); } else { MSD.SectionIndex = SectionIndexMap.lookup(&Symbol.getSection()); assert(MSD.SectionIndex && "Invalid section index!"); ExternalSymbolData.push_back(MSD); } } // Now add the data for local symbols. for (const MCSymbol &Symbol : Asm.symbols()) { // Ignore non-linker visible symbols. if (!Asm.isSymbolLinkerVisible(Symbol)) continue; if (Symbol.isExternal() || Symbol.isUndefined()) continue; MachSymbolData MSD; MSD.Symbol = &Symbol; MSD.StringIndex = StringTable.getOffset(Symbol.getName()); if (Symbol.isAbsolute()) { MSD.SectionIndex = 0; LocalSymbolData.push_back(MSD); } else { MSD.SectionIndex = SectionIndexMap.lookup(&Symbol.getSection()); assert(MSD.SectionIndex && "Invalid section index!"); LocalSymbolData.push_back(MSD); } } // External and undefined symbols are required to be in lexicographic order. std::sort(ExternalSymbolData.begin(), ExternalSymbolData.end()); std::sort(UndefinedSymbolData.begin(), UndefinedSymbolData.end()); // Set the symbol indices. Index = 0; for (auto *SymbolData : {&LocalSymbolData, &ExternalSymbolData, &UndefinedSymbolData}) for (MachSymbolData &Entry : *SymbolData) Entry.Symbol->setIndex(Index++); for (const MCSection &Section : Asm) { for (RelAndSymbol &Rel : Relocations[&Section]) { if (!Rel.Sym) continue; // Set the Index and the IsExtern bit. unsigned Index = Rel.Sym->getIndex(); assert(isInt<24>(Index)); if (IsLittleEndian) Rel.MRE.r_word1 = (Rel.MRE.r_word1 & (~0U << 24)) | Index | (1 << 27); else Rel.MRE.r_word1 = (Rel.MRE.r_word1 & 0xff) | Index << 8 | (1 << 4); } } }
void MachObjectWriter::WriteObject(MCAssembler &Asm, const MCAsmLayout &Layout) { unsigned NumSections = Asm.size(); // The section data starts after the header, the segment load command (and // section headers) and the symbol table. unsigned NumLoadCommands = 1; uint64_t LoadCommandsSize = is64Bit() ? macho::SegmentLoadCommand64Size + NumSections * macho::Section64Size : macho::SegmentLoadCommand32Size + NumSections * macho::Section32Size; // Add the data-in-code load command size, if used. unsigned NumDataRegions = Asm.getDataRegions().size(); if (NumDataRegions) { ++NumLoadCommands; LoadCommandsSize += macho::LinkeditLoadCommandSize; } // Add the symbol table load command sizes, if used. unsigned NumSymbols = LocalSymbolData.size() + ExternalSymbolData.size() + UndefinedSymbolData.size(); if (NumSymbols) { NumLoadCommands += 2; LoadCommandsSize += (macho::SymtabLoadCommandSize + macho::DysymtabLoadCommandSize); } // Add the linker option load commands sizes. const std::vector<std::vector<std::string> > &LinkerOptions = Asm.getLinkerOptions(); for (unsigned i = 0, e = LinkerOptions.size(); i != e; ++i) { ++NumLoadCommands; LoadCommandsSize += ComputeLinkerOptionsLoadCommandSize(LinkerOptions[i], is64Bit()); } // Compute the total size of the section data, as well as its file size and vm // size. uint64_t SectionDataStart = (is64Bit() ? macho::Header64Size : macho::Header32Size) + LoadCommandsSize; uint64_t SectionDataSize = 0; uint64_t SectionDataFileSize = 0; uint64_t VMSize = 0; for (MCAssembler::const_iterator it = Asm.begin(), ie = Asm.end(); it != ie; ++it) { const MCSectionData &SD = *it; uint64_t Address = getSectionAddress(&SD); uint64_t Size = Layout.getSectionAddressSize(&SD); uint64_t FileSize = Layout.getSectionFileSize(&SD); FileSize += getPaddingSize(&SD, Layout); VMSize = std::max(VMSize, Address + Size); if (SD.getSection().isVirtualSection()) continue; SectionDataSize = std::max(SectionDataSize, Address + Size); SectionDataFileSize = std::max(SectionDataFileSize, Address + FileSize); } // The section data is padded to 4 bytes. // // FIXME: Is this machine dependent? unsigned SectionDataPadding = OffsetToAlignment(SectionDataFileSize, 4); SectionDataFileSize += SectionDataPadding; // Write the prolog, starting with the header and load command... WriteHeader(NumLoadCommands, LoadCommandsSize, Asm.getSubsectionsViaSymbols()); WriteSegmentLoadCommand(NumSections, VMSize, SectionDataStart, SectionDataSize); // ... and then the section headers. uint64_t RelocTableEnd = SectionDataStart + SectionDataFileSize; for (MCAssembler::const_iterator it = Asm.begin(), ie = Asm.end(); it != ie; ++it) { std::vector<macho::RelocationEntry> &Relocs = Relocations[it]; unsigned NumRelocs = Relocs.size(); uint64_t SectionStart = SectionDataStart + getSectionAddress(it); WriteSection(Asm, Layout, *it, SectionStart, RelocTableEnd, NumRelocs); RelocTableEnd += NumRelocs * macho::RelocationInfoSize; } // Write the data-in-code load command, if used. uint64_t DataInCodeTableEnd = RelocTableEnd + NumDataRegions * 8; if (NumDataRegions) { uint64_t DataRegionsOffset = RelocTableEnd; uint64_t DataRegionsSize = NumDataRegions * 8; WriteLinkeditLoadCommand(macho::LCT_DataInCode, DataRegionsOffset, DataRegionsSize); } // Write the symbol table load command, if used. if (NumSymbols) { unsigned FirstLocalSymbol = 0; unsigned NumLocalSymbols = LocalSymbolData.size(); unsigned FirstExternalSymbol = FirstLocalSymbol + NumLocalSymbols; unsigned NumExternalSymbols = ExternalSymbolData.size(); unsigned FirstUndefinedSymbol = FirstExternalSymbol + NumExternalSymbols; unsigned NumUndefinedSymbols = UndefinedSymbolData.size(); unsigned NumIndirectSymbols = Asm.indirect_symbol_size(); unsigned NumSymTabSymbols = NumLocalSymbols + NumExternalSymbols + NumUndefinedSymbols; uint64_t IndirectSymbolSize = NumIndirectSymbols * 4; uint64_t IndirectSymbolOffset = 0; // If used, the indirect symbols are written after the section data. if (NumIndirectSymbols) IndirectSymbolOffset = DataInCodeTableEnd; // The symbol table is written after the indirect symbol data. uint64_t SymbolTableOffset = DataInCodeTableEnd + IndirectSymbolSize; // The string table is written after symbol table. uint64_t StringTableOffset = SymbolTableOffset + NumSymTabSymbols * (is64Bit() ? macho::Nlist64Size : macho::Nlist32Size); WriteSymtabLoadCommand(SymbolTableOffset, NumSymTabSymbols, StringTableOffset, StringTable.size()); WriteDysymtabLoadCommand(FirstLocalSymbol, NumLocalSymbols, FirstExternalSymbol, NumExternalSymbols, FirstUndefinedSymbol, NumUndefinedSymbols, IndirectSymbolOffset, NumIndirectSymbols); } // Write the linker options load commands. for (unsigned i = 0, e = LinkerOptions.size(); i != e; ++i) { WriteLinkerOptionsLoadCommand(LinkerOptions[i]); } // Write the actual section data. for (MCAssembler::const_iterator it = Asm.begin(), ie = Asm.end(); it != ie; ++it) { Asm.writeSectionData(it, Layout); uint64_t Pad = getPaddingSize(it, Layout); for (unsigned int i = 0; i < Pad; ++i) Write8(0); } // Write the extra padding. WriteZeros(SectionDataPadding); // Write the relocation entries. for (MCAssembler::const_iterator it = Asm.begin(), ie = Asm.end(); it != ie; ++it) { // Write the section relocation entries, in reverse order to match 'as' // (approximately, the exact algorithm is more complicated than this). std::vector<macho::RelocationEntry> &Relocs = Relocations[it]; for (unsigned i = 0, e = Relocs.size(); i != e; ++i) { Write32(Relocs[e - i - 1].Word0); Write32(Relocs[e - i - 1].Word1); } } // Write out the data-in-code region payload, if there is one. for (MCAssembler::const_data_region_iterator it = Asm.data_region_begin(), ie = Asm.data_region_end(); it != ie; ++it) { const DataRegionData *Data = &(*it); uint64_t Start = getSymbolAddress(&Layout.getAssembler().getSymbolData(*Data->Start), Layout); uint64_t End = getSymbolAddress(&Layout.getAssembler().getSymbolData(*Data->End), Layout); DEBUG(dbgs() << "data in code region-- kind: " << Data->Kind << " start: " << Start << "(" << Data->Start->getName() << ")" << " end: " << End << "(" << Data->End->getName() << ")" << " size: " << End - Start << "\n"); Write32(Start); Write16(End - Start); Write16(Data->Kind); } // Write the symbol table data, if used. if (NumSymbols) { // Write the indirect symbol entries. for (MCAssembler::const_indirect_symbol_iterator it = Asm.indirect_symbol_begin(), ie = Asm.indirect_symbol_end(); it != ie; ++it) { // Indirect symbols in the non lazy symbol pointer section have some // special handling. const MCSectionMachO &Section = static_cast<const MCSectionMachO&>(it->SectionData->getSection()); if (Section.getType() == MCSectionMachO::S_NON_LAZY_SYMBOL_POINTERS) { // If this symbol is defined and internal, mark it as such. if (it->Symbol->isDefined() && !Asm.getSymbolData(*it->Symbol).isExternal()) { uint32_t Flags = macho::ISF_Local; if (it->Symbol->isAbsolute()) Flags |= macho::ISF_Absolute; Write32(Flags); continue; } } Write32(Asm.getSymbolData(*it->Symbol).getIndex()); } // FIXME: Check that offsets match computed ones. // Write the symbol table entries. for (unsigned i = 0, e = LocalSymbolData.size(); i != e; ++i) WriteNlist(LocalSymbolData[i], Layout); for (unsigned i = 0, e = ExternalSymbolData.size(); i != e; ++i) WriteNlist(ExternalSymbolData[i], Layout); for (unsigned i = 0, e = UndefinedSymbolData.size(); i != e; ++i) WriteNlist(UndefinedSymbolData[i], Layout); // Write the string table. OS << StringTable.str(); } }
/// ComputeSymbolTable - Compute the symbol table data /// /// \param StringTable [out] - The string table data. /// \param StringIndexMap [out] - Map from symbol names to offsets in the /// string table. void MachObjectWriter:: ComputeSymbolTable(MCAssembler &Asm, SmallString<256> &StringTable, std::vector<MachSymbolData> &LocalSymbolData, std::vector<MachSymbolData> &ExternalSymbolData, std::vector<MachSymbolData> &UndefinedSymbolData) { // Build section lookup table. DenseMap<const MCSection*, uint8_t> SectionIndexMap; unsigned Index = 1; for (MCAssembler::iterator it = Asm.begin(), ie = Asm.end(); it != ie; ++it, ++Index) SectionIndexMap[&it->getSection()] = Index; assert(Index <= 256 && "Too many sections!"); // Index 0 is always the empty string. StringMap<uint64_t> StringIndexMap; StringTable += '\x00'; // Build the symbol arrays and the string table, but only for non-local // symbols. // // The particular order that we collect the symbols and create the string // table, then sort the symbols is chosen to match 'as'. Even though it // doesn't matter for correctness, this is important for letting us diff .o // files. for (MCAssembler::symbol_iterator it = Asm.symbol_begin(), ie = Asm.symbol_end(); it != ie; ++it) { const MCSymbol &Symbol = it->getSymbol(); // Ignore non-linker visible symbols. if (!Asm.isSymbolLinkerVisible(it->getSymbol())) continue; if (!it->isExternal() && !Symbol.isUndefined()) continue; uint64_t &Entry = StringIndexMap[Symbol.getName()]; if (!Entry) { Entry = StringTable.size(); StringTable += Symbol.getName(); StringTable += '\x00'; } MachSymbolData MSD; MSD.SymbolData = it; MSD.StringIndex = Entry; if (Symbol.isUndefined()) { MSD.SectionIndex = 0; UndefinedSymbolData.push_back(MSD); } else if (Symbol.isAbsolute()) { MSD.SectionIndex = 0; ExternalSymbolData.push_back(MSD); } else { MSD.SectionIndex = SectionIndexMap.lookup(&Symbol.getSection()); assert(MSD.SectionIndex && "Invalid section index!"); ExternalSymbolData.push_back(MSD); } } // Now add the data for local symbols. for (MCAssembler::symbol_iterator it = Asm.symbol_begin(), ie = Asm.symbol_end(); it != ie; ++it) { const MCSymbol &Symbol = it->getSymbol(); // Ignore non-linker visible symbols. if (!Asm.isSymbolLinkerVisible(it->getSymbol())) continue; if (it->isExternal() || Symbol.isUndefined()) continue; uint64_t &Entry = StringIndexMap[Symbol.getName()]; if (!Entry) { Entry = StringTable.size(); StringTable += Symbol.getName(); StringTable += '\x00'; } MachSymbolData MSD; MSD.SymbolData = it; MSD.StringIndex = Entry; if (Symbol.isAbsolute()) { MSD.SectionIndex = 0; LocalSymbolData.push_back(MSD); } else { MSD.SectionIndex = SectionIndexMap.lookup(&Symbol.getSection()); assert(MSD.SectionIndex && "Invalid section index!"); LocalSymbolData.push_back(MSD); } } // External and undefined symbols are required to be in lexicographic order. std::sort(ExternalSymbolData.begin(), ExternalSymbolData.end()); std::sort(UndefinedSymbolData.begin(), UndefinedSymbolData.end()); // Set the symbol indices. Index = 0; for (unsigned i = 0, e = LocalSymbolData.size(); i != e; ++i) LocalSymbolData[i].SymbolData->setIndex(Index++); for (unsigned i = 0, e = ExternalSymbolData.size(); i != e; ++i) ExternalSymbolData[i].SymbolData->setIndex(Index++); for (unsigned i = 0, e = UndefinedSymbolData.size(); i != e; ++i) UndefinedSymbolData[i].SymbolData->setIndex(Index++); // The string table is padded to a multiple of 4. while (StringTable.size() % 4) StringTable += '\x00'; }
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 AMDGPUMCObjectWriter::WriteObject(MCAssembler &Asm, const MCAsmLayout &Layout) { for (MCAssembler::iterator I = Asm.begin(), E = Asm.end(); I != E; ++I) { Asm.writeSectionData(I, Layout); } }
void MachObjectWriter::WriteObject(MCAssembler &Asm, const MCAsmLayout &Layout) { unsigned NumSections = Asm.size(); const MCAssembler::VersionMinInfoType &VersionInfo = Layout.getAssembler().getVersionMinInfo(); // The section data starts after the header, the segment load command (and // section headers) and the symbol table. unsigned NumLoadCommands = 1; uint64_t LoadCommandsSize = is64Bit() ? sizeof(MachO::segment_command_64) + NumSections * sizeof(MachO::section_64): sizeof(MachO::segment_command) + NumSections * sizeof(MachO::section); // Add the deployment target version info load command size, if used. if (VersionInfo.Major != 0) { ++NumLoadCommands; LoadCommandsSize += sizeof(MachO::version_min_command); } // Add the data-in-code load command size, if used. unsigned NumDataRegions = Asm.getDataRegions().size(); if (NumDataRegions) { ++NumLoadCommands; LoadCommandsSize += sizeof(MachO::linkedit_data_command); } // Add the loh load command size, if used. uint64_t LOHRawSize = Asm.getLOHContainer().getEmitSize(*this, Layout); uint64_t LOHSize = RoundUpToAlignment(LOHRawSize, is64Bit() ? 8 : 4); if (LOHSize) { ++NumLoadCommands; LoadCommandsSize += sizeof(MachO::linkedit_data_command); } // Add the symbol table load command sizes, if used. unsigned NumSymbols = LocalSymbolData.size() + ExternalSymbolData.size() + UndefinedSymbolData.size(); if (NumSymbols) { NumLoadCommands += 2; LoadCommandsSize += (sizeof(MachO::symtab_command) + sizeof(MachO::dysymtab_command)); } // Add the linker option load commands sizes. const std::vector<std::vector<std::string> > &LinkerOptions = Asm.getLinkerOptions(); for (unsigned i = 0, e = LinkerOptions.size(); i != e; ++i) { ++NumLoadCommands; LoadCommandsSize += ComputeLinkerOptionsLoadCommandSize(LinkerOptions[i], is64Bit()); } // Compute the total size of the section data, as well as its file size and vm // size. uint64_t SectionDataStart = (is64Bit() ? sizeof(MachO::mach_header_64) : sizeof(MachO::mach_header)) + LoadCommandsSize; uint64_t SectionDataSize = 0; uint64_t SectionDataFileSize = 0; uint64_t VMSize = 0; for (MCAssembler::const_iterator it = Asm.begin(), ie = Asm.end(); it != ie; ++it) { const MCSectionData &SD = *it; uint64_t Address = getSectionAddress(&SD); uint64_t Size = Layout.getSectionAddressSize(&SD); uint64_t FileSize = Layout.getSectionFileSize(&SD); FileSize += getPaddingSize(&SD, Layout); VMSize = std::max(VMSize, Address + Size); if (SD.getSection().isVirtualSection()) continue; SectionDataSize = std::max(SectionDataSize, Address + Size); SectionDataFileSize = std::max(SectionDataFileSize, Address + FileSize); } // The section data is padded to 4 bytes. // // FIXME: Is this machine dependent? unsigned SectionDataPadding = OffsetToAlignment(SectionDataFileSize, 4); SectionDataFileSize += SectionDataPadding; // Write the prolog, starting with the header and load command... WriteHeader(NumLoadCommands, LoadCommandsSize, Asm.getSubsectionsViaSymbols()); WriteSegmentLoadCommand(NumSections, VMSize, SectionDataStart, SectionDataSize); // ... and then the section headers. uint64_t RelocTableEnd = SectionDataStart + SectionDataFileSize; for (MCAssembler::const_iterator it = Asm.begin(), ie = Asm.end(); it != ie; ++it) { std::vector<MachO::any_relocation_info> &Relocs = Relocations[it]; unsigned NumRelocs = Relocs.size(); uint64_t SectionStart = SectionDataStart + getSectionAddress(it); WriteSection(Asm, Layout, *it, SectionStart, RelocTableEnd, NumRelocs); RelocTableEnd += NumRelocs * sizeof(MachO::any_relocation_info); } // Write out the deployment target information, if it's available. if (VersionInfo.Major != 0) { assert(VersionInfo.Update < 256 && "unencodable update target version"); assert(VersionInfo.Minor < 256 && "unencodable minor target version"); assert(VersionInfo.Major < 65536 && "unencodable major target version"); uint32_t EncodedVersion = VersionInfo.Update | (VersionInfo.Minor << 8) | (VersionInfo.Major << 16); Write32(VersionInfo.Kind == MCVM_OSXVersionMin ? MachO::LC_VERSION_MIN_MACOSX : MachO::LC_VERSION_MIN_IPHONEOS); Write32(sizeof(MachO::version_min_command)); Write32(EncodedVersion); Write32(0); // reserved. } // Write the data-in-code load command, if used. uint64_t DataInCodeTableEnd = RelocTableEnd + NumDataRegions * 8; if (NumDataRegions) { uint64_t DataRegionsOffset = RelocTableEnd; uint64_t DataRegionsSize = NumDataRegions * 8; WriteLinkeditLoadCommand(MachO::LC_DATA_IN_CODE, DataRegionsOffset, DataRegionsSize); } // Write the loh load command, if used. uint64_t LOHTableEnd = DataInCodeTableEnd + LOHSize; if (LOHSize) WriteLinkeditLoadCommand(MachO::LC_LINKER_OPTIMIZATION_HINT, DataInCodeTableEnd, LOHSize); // Write the symbol table load command, if used. if (NumSymbols) { unsigned FirstLocalSymbol = 0; unsigned NumLocalSymbols = LocalSymbolData.size(); unsigned FirstExternalSymbol = FirstLocalSymbol + NumLocalSymbols; unsigned NumExternalSymbols = ExternalSymbolData.size(); unsigned FirstUndefinedSymbol = FirstExternalSymbol + NumExternalSymbols; unsigned NumUndefinedSymbols = UndefinedSymbolData.size(); unsigned NumIndirectSymbols = Asm.indirect_symbol_size(); unsigned NumSymTabSymbols = NumLocalSymbols + NumExternalSymbols + NumUndefinedSymbols; uint64_t IndirectSymbolSize = NumIndirectSymbols * 4; uint64_t IndirectSymbolOffset = 0; // If used, the indirect symbols are written after the section data. if (NumIndirectSymbols) IndirectSymbolOffset = LOHTableEnd; // The symbol table is written after the indirect symbol data. uint64_t SymbolTableOffset = LOHTableEnd + IndirectSymbolSize; // The string table is written after symbol table. uint64_t StringTableOffset = SymbolTableOffset + NumSymTabSymbols * (is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist)); WriteSymtabLoadCommand(SymbolTableOffset, NumSymTabSymbols, StringTableOffset, StringTable.data().size()); WriteDysymtabLoadCommand(FirstLocalSymbol, NumLocalSymbols, FirstExternalSymbol, NumExternalSymbols, FirstUndefinedSymbol, NumUndefinedSymbols, IndirectSymbolOffset, NumIndirectSymbols); } // Write the linker options load commands. for (unsigned i = 0, e = LinkerOptions.size(); i != e; ++i) { WriteLinkerOptionsLoadCommand(LinkerOptions[i]); } // Write the actual section data. for (MCAssembler::const_iterator it = Asm.begin(), ie = Asm.end(); it != ie; ++it) { Asm.writeSectionData(it, Layout); uint64_t Pad = getPaddingSize(it, Layout); for (unsigned int i = 0; i < Pad; ++i) Write8(0); } // Write the extra padding. WriteZeros(SectionDataPadding); // Write the relocation entries. for (MCAssembler::const_iterator it = Asm.begin(), ie = Asm.end(); it != ie; ++it) { // Write the section relocation entries, in reverse order to match 'as' // (approximately, the exact algorithm is more complicated than this). std::vector<MachO::any_relocation_info> &Relocs = Relocations[it]; for (unsigned i = 0, e = Relocs.size(); i != e; ++i) { Write32(Relocs[e - i - 1].r_word0); Write32(Relocs[e - i - 1].r_word1); } } // Write out the data-in-code region payload, if there is one. for (MCAssembler::const_data_region_iterator it = Asm.data_region_begin(), ie = Asm.data_region_end(); it != ie; ++it) { const DataRegionData *Data = &(*it); uint64_t Start = getSymbolAddress(&Layout.getAssembler().getSymbolData(*Data->Start), Layout); uint64_t End = getSymbolAddress(&Layout.getAssembler().getSymbolData(*Data->End), Layout); DEBUG(dbgs() << "data in code region-- kind: " << Data->Kind << " start: " << Start << "(" << Data->Start->getName() << ")" << " end: " << End << "(" << Data->End->getName() << ")" << " size: " << End - Start << "\n"); Write32(Start); Write16(End - Start); Write16(Data->Kind); } // Write out the loh commands, if there is one. if (LOHSize) { #ifndef NDEBUG unsigned Start = OS.tell(); #endif Asm.getLOHContainer().Emit(*this, Layout); // Pad to a multiple of the pointer size. WriteBytes("", OffsetToAlignment(LOHRawSize, is64Bit() ? 8 : 4)); assert(OS.tell() - Start == LOHSize); } // Write the symbol table data, if used. if (NumSymbols) { // Write the indirect symbol entries. for (MCAssembler::const_indirect_symbol_iterator it = Asm.indirect_symbol_begin(), ie = Asm.indirect_symbol_end(); it != ie; ++it) { // Indirect symbols in the non-lazy symbol pointer section have some // special handling. const MCSectionMachO &Section = static_cast<const MCSectionMachO&>(it->SectionData->getSection()); if (Section.getType() == MachO::S_NON_LAZY_SYMBOL_POINTERS) { // If this symbol is defined and internal, mark it as such. if (it->Symbol->isDefined() && !Asm.getSymbolData(*it->Symbol).isExternal()) { uint32_t Flags = MachO::INDIRECT_SYMBOL_LOCAL; if (it->Symbol->isAbsolute()) Flags |= MachO::INDIRECT_SYMBOL_ABS; Write32(Flags); continue; } } Write32(Asm.getSymbolData(*it->Symbol).getIndex()); } // FIXME: Check that offsets match computed ones. // Write the symbol table entries. for (unsigned i = 0, e = LocalSymbolData.size(); i != e; ++i) WriteNlist(LocalSymbolData[i], Layout); for (unsigned i = 0, e = ExternalSymbolData.size(); i != e; ++i) WriteNlist(ExternalSymbolData[i], Layout); for (unsigned i = 0, e = UndefinedSymbolData.size(); i != e; ++i) WriteNlist(UndefinedSymbolData[i], Layout); // Write the string table. OS << StringTable.data(); } }
/// ComputeSymbolTable - Compute the symbol table data void MachObjectWriter::ComputeSymbolTable( MCAssembler &Asm, std::vector<MachSymbolData> &LocalSymbolData, std::vector<MachSymbolData> &ExternalSymbolData, std::vector<MachSymbolData> &UndefinedSymbolData) { // Build section lookup table. DenseMap<const MCSection*, uint8_t> SectionIndexMap; unsigned Index = 1; for (MCAssembler::iterator it = Asm.begin(), ie = Asm.end(); it != ie; ++it, ++Index) SectionIndexMap[&it->getSection()] = Index; assert(Index <= 256 && "Too many sections!"); // Build the string table. for (MCSymbolData &SD : Asm.symbols()) { const MCSymbol &Symbol = SD.getSymbol(); if (!Asm.isSymbolLinkerVisible(Symbol)) continue; StringTable.add(Symbol.getName()); } StringTable.finalize(StringTableBuilder::MachO); // Build the symbol arrays but only for non-local symbols. // // The particular order that we collect and then sort the symbols is chosen to // match 'as'. Even though it doesn't matter for correctness, this is // important for letting us diff .o files. for (MCSymbolData &SD : Asm.symbols()) { const MCSymbol &Symbol = SD.getSymbol(); // Ignore non-linker visible symbols. if (!Asm.isSymbolLinkerVisible(Symbol)) continue; if (!SD.isExternal() && !Symbol.isUndefined()) continue; MachSymbolData MSD; MSD.SymbolData = &SD; MSD.StringIndex = StringTable.getOffset(Symbol.getName()); if (Symbol.isUndefined()) { MSD.SectionIndex = 0; UndefinedSymbolData.push_back(MSD); } else if (Symbol.isAbsolute()) { MSD.SectionIndex = 0; ExternalSymbolData.push_back(MSD); } else { MSD.SectionIndex = SectionIndexMap.lookup(&Symbol.getSection()); assert(MSD.SectionIndex && "Invalid section index!"); ExternalSymbolData.push_back(MSD); } } // Now add the data for local symbols. for (MCSymbolData &SD : Asm.symbols()) { const MCSymbol &Symbol = SD.getSymbol(); // Ignore non-linker visible symbols. if (!Asm.isSymbolLinkerVisible(Symbol)) continue; if (SD.isExternal() || Symbol.isUndefined()) continue; MachSymbolData MSD; MSD.SymbolData = &SD; MSD.StringIndex = StringTable.getOffset(Symbol.getName()); if (Symbol.isAbsolute()) { MSD.SectionIndex = 0; LocalSymbolData.push_back(MSD); } else { MSD.SectionIndex = SectionIndexMap.lookup(&Symbol.getSection()); assert(MSD.SectionIndex && "Invalid section index!"); LocalSymbolData.push_back(MSD); } } // External and undefined symbols are required to be in lexicographic order. std::sort(ExternalSymbolData.begin(), ExternalSymbolData.end()); std::sort(UndefinedSymbolData.begin(), UndefinedSymbolData.end()); // Set the symbol indices. Index = 0; for (unsigned i = 0, e = LocalSymbolData.size(); i != e; ++i) LocalSymbolData[i].SymbolData->setIndex(Index++); for (unsigned i = 0, e = ExternalSymbolData.size(); i != e; ++i) ExternalSymbolData[i].SymbolData->setIndex(Index++); for (unsigned i = 0, e = UndefinedSymbolData.size(); i != e; ++i) UndefinedSymbolData[i].SymbolData->setIndex(Index++); }
void SVMELFProgramWriter::WriteObject(MCAssembler &Asm, const MCAsmLayout &Layout) { // First pass, allocate all non-debug sections and compute the // initial layout of the plaintext RWDATA segments. ML.AllocateSections(Asm, Layout); // Apply fixups that were stored in RecordRelocation ML.ApplyLateFixups(Asm, Layout); // Now we can know the final binary image of the RWDATA segments. Compress them. rwCompress(Asm, Layout, ML); ML.AllocateSections(Asm, Layout); if (ELFDebug) { // Allocate all debug sections last EMB.BuildSections(Asm, Layout, ML); ML.AllocateSections(Asm, Layout); } // Write header blocks writeELFHeader(Asm, Layout); for (int S = 0; S < SPS_DEBUG; ++S) writeProgramHeader((SVMProgramSection) S); // Write program data, sorted by SPS section int endS = ELFDebug ? SPS_NUM_SECTIONS : SPS_DEBUG; for (int S = 0; S < endS; ++S) { if (S == SPS_DEBUG) writeDebugMessage(); for (MCAssembler::const_iterator it = Asm.begin(), ie = Asm.end(); it != ie; ++it) { const MCSectionData *SD = &*it; if (ML.getSectionKind(SD) != S) continue; if (Layout.getSectionFileSize(SD) == 0) continue; padToOffset(ML.getSectionDiskOffset(SD)); Asm.WriteSectionData(SD, Layout); } } if (ELFDebug) { // On debug binaries, generate section headers last padToOffset(SHOffset); // Dummy NULL section header (index 0) WriteZeros(sizeof(ELF::Elf32_Shdr)); for (MCAssembler::const_iterator it = Asm.begin(), ie = Asm.end(); it != ie; ++it) { const MCSectionData *SD = &*it; writeSectionHeader(Layout, SD); } } }
void SVMELFProgramWriter::rwCompress(MCAssembler &Asm, const MCAsmLayout &Layout, SVMMemoryLayout &ML) { /* * Look for all segments with initialized data for RAM, flatten them, and * compress the resulting data. Create a new segment with the compressed * RWDATA. This segment will always be included in the binary. The originals * are considered debug-only sections, since they are no longer needed * at runtime. */ // Flattened binary contents of RAM std::vector<uint8_t> plaintext; // Iterate over SPS_RW sections for (MCAssembler::const_iterator IS = Asm.begin(), ES = Asm.end(); IS != ES; ++IS) { const MCSectionData *SD = &*IS; if (ML.getSectionKind(SD) != SPS_RW_PLAIN) continue; int offset = ML.getSectionMemAddress(SD) - SVMTargetMachine::getRAMBase(); int limit = SVMTargetMachine::getRAMSize(); // Iterate over fragments, pasting them into 'plaintext' for (MCSectionData::const_iterator IF = SD->begin(), EF = SD->end(); IF != EF; ++IF) { const MCFragment *F = &*IF; if (F->getKind() == MCFragment::FT_Data) { const MCDataFragment *DF = cast<MCDataFragment>(F); int fragmentOffset = Layout.getFragmentOffset(F); for (unsigned i = 0; i < DF->getContents().size(); i++) { int totalOffset = fragmentOffset + offset + i; if (totalOffset < limit) { while (totalOffset >= int(plaintext.size())) plaintext.push_back(0); plaintext[totalOffset] = DF->getContents()[i]; } } } } } // FastLZ requires a minimum of 16 bytes to compress. Pad our section data. while (plaintext.size() < 16) plaintext.push_back(0); // Compress using FastLZ level 1 std::vector<uint8_t> compressed(plaintext.size() * 2); compressed.resize(fastlz_compress_level(1, &plaintext[0], plaintext.size(), &compressed[0])); // Create the new section const MCSectionELF *LZSection = Asm.getContext().getELFSection(".rwdata.lz", ELF::SHT_NOTE, 0, SectionKind::getDataNoRel()); MCSectionData &LZSectionSD = Asm.getOrCreateSectionData(*LZSection); LZSectionSD.setAlignment(1); // Force it to be interpreted as SPS_RW, and set the decompressed size ML.setSectionKind(&LZSectionSD, SPS_RW_Z); ML.setSectionMemSize(&LZSectionSD, plaintext.size()); // Add compressed data MCDataFragment *F = new MCDataFragment(&LZSectionSD); F->getContents().append(compressed.begin(), compressed.end()); }
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()); }