LLVM API Documentation
00001 //===-- ELFWriter.cpp - Target-independent ELF Writer code ----------------===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This file implements the target-independent ELF writer. This file writes out 00011 // the ELF file in the following order: 00012 // 00013 // #1. ELF Header 00014 // #2. '.text' section 00015 // #3. '.data' section 00016 // #4. '.bss' section (conceptual position in file) 00017 // ... 00018 // #X. '.shstrtab' section 00019 // #Y. Section Table 00020 // 00021 // The entries in the section table are laid out as: 00022 // #0. Null entry [required] 00023 // #1. ".text" entry - the program code 00024 // #2. ".data" entry - global variables with initializers. [ if needed ] 00025 // #3. ".bss" entry - global variables without initializers. [ if needed ] 00026 // ... 00027 // #N. ".shstrtab" entry - String table for the section names. 00028 // 00029 // NOTE: This code should eventually be extended to support 64-bit ELF (this 00030 // won't be hard), but we haven't done so yet! 00031 // 00032 //===----------------------------------------------------------------------===// 00033 00034 #include "ELFWriter.h" 00035 #include "llvm/Module.h" 00036 #include "llvm/PassManager.h" 00037 #include "llvm/DerivedTypes.h" 00038 #include "llvm/CodeGen/FileWriters.h" 00039 #include "llvm/CodeGen/MachineCodeEmitter.h" 00040 #include "llvm/CodeGen/MachineConstantPool.h" 00041 #include "llvm/CodeGen/MachineFunctionPass.h" 00042 #include "llvm/Target/TargetData.h" 00043 #include "llvm/Target/TargetELFWriterInfo.h" 00044 #include "llvm/Target/TargetMachine.h" 00045 #include "llvm/Support/Mangler.h" 00046 #include "llvm/Support/OutputBuffer.h" 00047 #include "llvm/Support/Streams.h" 00048 #include "llvm/Support/raw_ostream.h" 00049 #include <list> 00050 using namespace llvm; 00051 00052 char ELFWriter::ID = 0; 00053 /// AddELFWriter - Concrete function to add the ELF writer to the function pass 00054 /// manager. 00055 MachineCodeEmitter *llvm::AddELFWriter(PassManagerBase &PM, 00056 raw_ostream &O, 00057 TargetMachine &TM) { 00058 ELFWriter *EW = new ELFWriter(O, TM); 00059 PM.add(EW); 00060 return &EW->getMachineCodeEmitter(); 00061 } 00062 00063 //===----------------------------------------------------------------------===// 00064 // ELFCodeEmitter Implementation 00065 //===----------------------------------------------------------------------===// 00066 00067 namespace llvm { 00068 /// ELFCodeEmitter - This class is used by the ELFWriter to emit the code for 00069 /// functions to the ELF file. 00070 class ELFCodeEmitter : public MachineCodeEmitter { 00071 ELFWriter &EW; 00072 TargetMachine &TM; 00073 ELFWriter::ELFSection *ES; // Section to write to. 00074 std::vector<unsigned char> *OutBuffer; 00075 size_t FnStart; 00076 public: 00077 explicit ELFCodeEmitter(ELFWriter &ew) : EW(ew), TM(EW.TM), OutBuffer(0) {} 00078 00079 void startFunction(MachineFunction &F); 00080 bool finishFunction(MachineFunction &F); 00081 00082 void addRelocation(const MachineRelocation &MR) { 00083 assert(0 && "relo not handled yet!"); 00084 } 00085 00086 virtual void StartMachineBasicBlock(MachineBasicBlock *MBB) { 00087 } 00088 00089 virtual uintptr_t getConstantPoolEntryAddress(unsigned Index) const { 00090 assert(0 && "CP not implementated yet!"); 00091 return 0; 00092 } 00093 virtual uintptr_t getJumpTableEntryAddress(unsigned Index) const { 00094 assert(0 && "JT not implementated yet!"); 00095 return 0; 00096 } 00097 00098 virtual uintptr_t getMachineBasicBlockAddress(MachineBasicBlock *MBB) const { 00099 assert(0 && "JT not implementated yet!"); 00100 return 0; 00101 } 00102 00103 virtual uintptr_t getLabelAddress(uint64_t Label) const { 00104 assert(0 && "Label address not implementated yet!"); 00105 abort(); 00106 return 0; 00107 } 00108 00109 virtual void emitLabel(uint64_t LabelID) { 00110 assert(0 && "emit Label not implementated yet!"); 00111 abort(); 00112 } 00113 00114 00115 virtual void setModuleInfo(llvm::MachineModuleInfo* MMI) { } 00116 00117 00118 /// JIT SPECIFIC FUNCTIONS - DO NOT IMPLEMENT THESE HERE! 00119 void startGVStub(const GlobalValue* F, unsigned StubSize, 00120 unsigned Alignment = 1) { 00121 assert(0 && "JIT specific function called!"); 00122 abort(); 00123 } 00124 void *finishGVStub(const GlobalValue *F) { 00125 assert(0 && "JIT specific function called!"); 00126 abort(); 00127 return 0; 00128 } 00129 }; 00130 } 00131 00132 /// startFunction - This callback is invoked when a new machine function is 00133 /// about to be emitted. 00134 void ELFCodeEmitter::startFunction(MachineFunction &F) { 00135 // Align the output buffer to the appropriate alignment. 00136 unsigned Align = 16; // FIXME: GENERICIZE!! 00137 // Get the ELF Section that this function belongs in. 00138 ES = &EW.getSection(".text", ELFWriter::ELFSection::SHT_PROGBITS, 00139 ELFWriter::ELFSection::SHF_EXECINSTR | 00140 ELFWriter::ELFSection::SHF_ALLOC); 00141 OutBuffer = &ES->SectionData; 00142 cerr << "FIXME: This code needs to be updated for changes in the " 00143 << "CodeEmitter interfaces. In particular, this should set " 00144 << "BufferBegin/BufferEnd/CurBufferPtr, not deal with OutBuffer!"; 00145 abort(); 00146 00147 // Upgrade the section alignment if required. 00148 if (ES->Align < Align) ES->Align = Align; 00149 00150 // Add padding zeros to the end of the buffer to make sure that the 00151 // function will start on the correct byte alignment within the section. 00152 OutputBuffer OB(*OutBuffer, 00153 TM.getTargetData()->getPointerSizeInBits() == 64, 00154 TM.getTargetData()->isLittleEndian()); 00155 OB.align(Align); 00156 FnStart = OutBuffer->size(); 00157 } 00158 00159 /// finishFunction - This callback is invoked after the function is completely 00160 /// finished. 00161 bool ELFCodeEmitter::finishFunction(MachineFunction &F) { 00162 // We now know the size of the function, add a symbol to represent it. 00163 ELFWriter::ELFSym FnSym(F.getFunction()); 00164 00165 // Figure out the binding (linkage) of the symbol. 00166 switch (F.getFunction()->getLinkage()) { 00167 default: 00168 // appending linkage is illegal for functions. 00169 assert(0 && "Unknown linkage type!"); 00170 case GlobalValue::ExternalLinkage: 00171 FnSym.SetBind(ELFWriter::ELFSym::STB_GLOBAL); 00172 break; 00173 case GlobalValue::LinkOnceLinkage: 00174 case GlobalValue::WeakLinkage: 00175 FnSym.SetBind(ELFWriter::ELFSym::STB_WEAK); 00176 break; 00177 case GlobalValue::PrivateLinkage: 00178 assert (0 && "PrivateLinkage should not be in the symbol table."); 00179 case GlobalValue::InternalLinkage: 00180 FnSym.SetBind(ELFWriter::ELFSym::STB_LOCAL); 00181 break; 00182 } 00183 00184 ES->Size = OutBuffer->size(); 00185 00186 FnSym.SetType(ELFWriter::ELFSym::STT_FUNC); 00187 FnSym.SectionIdx = ES->SectionIdx; 00188 FnSym.Value = FnStart; // Value = Offset from start of Section. 00189 FnSym.Size = OutBuffer->size()-FnStart; 00190 00191 // Finally, add it to the symtab. 00192 EW.SymbolTable.push_back(FnSym); 00193 return false; 00194 } 00195 00196 //===----------------------------------------------------------------------===// 00197 // ELFWriter Implementation 00198 //===----------------------------------------------------------------------===// 00199 00200 ELFWriter::ELFWriter(raw_ostream &o, TargetMachine &tm) 00201 : MachineFunctionPass(&ID), O(o), TM(tm) { 00202 e_flags = 0; // e_flags defaults to 0, no flags. 00203 00204 is64Bit = TM.getTargetData()->getPointerSizeInBits() == 64; 00205 isLittleEndian = TM.getTargetData()->isLittleEndian(); 00206 00207 // Create the machine code emitter object for this target. 00208 MCE = new ELFCodeEmitter(*this); 00209 NumSections = 0; 00210 } 00211 00212 ELFWriter::~ELFWriter() { 00213 delete MCE; 00214 } 00215 00216 // doInitialization - Emit the file header and all of the global variables for 00217 // the module to the ELF file. 00218 bool ELFWriter::doInitialization(Module &M) { 00219 Mang = new Mangler(M); 00220 00221 // Local alias to shortenify coming code. 00222 std::vector<unsigned char> &FH = FileHeader; 00223 OutputBuffer FHOut(FH, is64Bit, isLittleEndian); 00224 00225 FHOut.outbyte(0x7F); // EI_MAG0 00226 FHOut.outbyte('E'); // EI_MAG1 00227 FHOut.outbyte('L'); // EI_MAG2 00228 FHOut.outbyte('F'); // EI_MAG3 00229 FHOut.outbyte(is64Bit ? 2 : 1); // EI_CLASS 00230 FHOut.outbyte(isLittleEndian ? 1 : 2); // EI_DATA 00231 FHOut.outbyte(1); // EI_VERSION 00232 FH.resize(16); // EI_PAD up to 16 bytes. 00233 00234 // This should change for shared objects. 00235 FHOut.outhalf(1); // e_type = ET_REL 00236 FHOut.outhalf(TM.getELFWriterInfo()->getEMachine()); // target-defined 00237 FHOut.outword(1); // e_version = 1 00238 FHOut.outaddr(0); // e_entry = 0 -> no entry point in .o file 00239 FHOut.outaddr(0); // e_phoff = 0 -> no program header for .o 00240 00241 ELFHeader_e_shoff_Offset = FH.size(); 00242 FHOut.outaddr(0); // e_shoff 00243 FHOut.outword(e_flags); // e_flags = whatever the target wants 00244 00245 FHOut.outhalf(is64Bit ? 64 : 52); // e_ehsize = ELF header size 00246 FHOut.outhalf(0); // e_phentsize = prog header entry size 00247 FHOut.outhalf(0); // e_phnum = # prog header entries = 0 00248 FHOut.outhalf(is64Bit ? 64 : 40); // e_shentsize = sect hdr entry size 00249 00250 00251 ELFHeader_e_shnum_Offset = FH.size(); 00252 FHOut.outhalf(0); // e_shnum = # of section header ents 00253 ELFHeader_e_shstrndx_Offset = FH.size(); 00254 FHOut.outhalf(0); // e_shstrndx = Section # of '.shstrtab' 00255 00256 // Add the null section, which is required to be first in the file. 00257 getSection("", 0, 0); 00258 00259 // Start up the symbol table. The first entry in the symtab is the null 00260 // entry. 00261 SymbolTable.push_back(ELFSym(0)); 00262 00263 return false; 00264 } 00265 00266 void ELFWriter::EmitGlobal(GlobalVariable *GV) { 00267 // If this is an external global, emit it now. TODO: Note that it would be 00268 // better to ignore the symbol here and only add it to the symbol table if 00269 // referenced. 00270 if (!GV->hasInitializer()) { 00271 ELFSym ExternalSym(GV); 00272 ExternalSym.SetBind(ELFSym::STB_GLOBAL); 00273 ExternalSym.SetType(ELFSym::STT_NOTYPE); 00274 ExternalSym.SectionIdx = ELFSection::SHN_UNDEF; 00275 SymbolTable.push_back(ExternalSym); 00276 return; 00277 } 00278 00279 unsigned Align = TM.getTargetData()->getPreferredAlignment(GV); 00280 unsigned Size = 00281 TM.getTargetData()->getTypePaddedSize(GV->getType()->getElementType()); 00282 00283 // If this global has a zero initializer, it is part of the .bss or common 00284 // section. 00285 if (GV->getInitializer()->isNullValue()) { 00286 // If this global is part of the common block, add it now. Variables are 00287 // part of the common block if they are zero initialized and allowed to be 00288 // merged with other symbols. 00289 if (GV->hasLinkOnceLinkage() || GV->hasWeakLinkage() || 00290 GV->hasCommonLinkage()) { 00291 ELFSym CommonSym(GV); 00292 // Value for common symbols is the alignment required. 00293 CommonSym.Value = Align; 00294 CommonSym.Size = Size; 00295 CommonSym.SetBind(ELFSym::STB_GLOBAL); 00296 CommonSym.SetType(ELFSym::STT_OBJECT); 00297 // TODO SOMEDAY: add ELF visibility. 00298 CommonSym.SectionIdx = ELFSection::SHN_COMMON; 00299 SymbolTable.push_back(CommonSym); 00300 return; 00301 } 00302 00303 // Otherwise, this symbol is part of the .bss section. Emit it now. 00304 00305 // Handle alignment. Ensure section is aligned at least as much as required 00306 // by this symbol. 00307 ELFSection &BSSSection = getBSSSection(); 00308 BSSSection.Align = std::max(BSSSection.Align, Align); 00309 00310 // Within the section, emit enough virtual padding to get us to an alignment 00311 // boundary. 00312 if (Align) 00313 BSSSection.Size = (BSSSection.Size + Align - 1) & ~(Align-1); 00314 00315 ELFSym BSSSym(GV); 00316 BSSSym.Value = BSSSection.Size; 00317 BSSSym.Size = Size; 00318 BSSSym.SetType(ELFSym::STT_OBJECT); 00319 00320 switch (GV->getLinkage()) { 00321 default: // weak/linkonce/common handled above 00322 assert(0 && "Unexpected linkage type!"); 00323 case GlobalValue::AppendingLinkage: // FIXME: This should be improved! 00324 case GlobalValue::ExternalLinkage: 00325 BSSSym.SetBind(ELFSym::STB_GLOBAL); 00326 break; 00327 case GlobalValue::InternalLinkage: 00328 BSSSym.SetBind(ELFSym::STB_LOCAL); 00329 break; 00330 } 00331 00332 // Set the idx of the .bss section 00333 BSSSym.SectionIdx = BSSSection.SectionIdx; 00334 if (!GV->hasPrivateLinkage()) 00335 SymbolTable.push_back(BSSSym); 00336 00337 // Reserve space in the .bss section for this symbol. 00338 BSSSection.Size += Size; 00339 return; 00340 } 00341 00342 // FIXME: handle .rodata 00343 //assert(!GV->isConstant() && "unimp"); 00344 00345 // FIXME: handle .data 00346 //assert(0 && "unimp"); 00347 } 00348 00349 00350 bool ELFWriter::runOnMachineFunction(MachineFunction &MF) { 00351 // Nothing to do here, this is all done through the MCE object above. 00352 return false; 00353 } 00354 00355 /// doFinalization - Now that the module has been completely processed, emit 00356 /// the ELF file to 'O'. 00357 bool ELFWriter::doFinalization(Module &M) { 00358 // Okay, the ELF header and .text sections have been completed, build the 00359 // .data, .bss, and "common" sections next. 00360 for (Module::global_iterator I = M.global_begin(), E = M.global_end(); 00361 I != E; ++I) 00362 EmitGlobal(I); 00363 00364 // Emit the symbol table now, if non-empty. 00365 EmitSymbolTable(); 00366 00367 // FIXME: Emit the relocations now. 00368 00369 // Emit the string table for the sections in the ELF file we have. 00370 EmitSectionTableStringTable(); 00371 00372 // Emit the sections to the .o file, and emit the section table for the file. 00373 OutputSectionsAndSectionTable(); 00374 00375 // We are done with the abstract symbols. 00376 SectionList.clear(); 00377 NumSections = 0; 00378 00379 // Release the name mangler object. 00380 delete Mang; Mang = 0; 00381 return false; 00382 } 00383 00384 /// EmitSymbolTable - If the current symbol table is non-empty, emit the string 00385 /// table for it and then the symbol table itself. 00386 void ELFWriter::EmitSymbolTable() { 00387 if (SymbolTable.size() == 1) return; // Only the null entry. 00388 00389 // FIXME: compact all local symbols to the start of the symtab. 00390 unsigned FirstNonLocalSymbol = 1; 00391 00392 ELFSection &StrTab = getSection(".strtab", ELFSection::SHT_STRTAB, 0); 00393 StrTab.Align = 1; 00394 00395 DataBuffer &StrTabBuf = StrTab.SectionData; 00396 OutputBuffer StrTabOut(StrTabBuf, is64Bit, isLittleEndian); 00397 00398 // Set the zero'th symbol to a null byte, as required. 00399 StrTabOut.outbyte(0); 00400 SymbolTable[0].NameIdx = 0; 00401 unsigned Index = 1; 00402 for (unsigned i = 1, e = SymbolTable.size(); i != e; ++i) { 00403 // Use the name mangler to uniquify the LLVM symbol. 00404 std::string Name = Mang->getValueName(SymbolTable[i].GV); 00405 00406 if (Name.empty()) { 00407 SymbolTable[i].NameIdx = 0; 00408 } else { 00409 SymbolTable[i].NameIdx = Index; 00410 00411 // Add the name to the output buffer, including the null terminator. 00412 StrTabBuf.insert(StrTabBuf.end(), Name.begin(), Name.end()); 00413 00414 // Add a null terminator. 00415 StrTabBuf.push_back(0); 00416 00417 // Keep track of the number of bytes emitted to this section. 00418 Index += Name.size()+1; 00419 } 00420 } 00421 assert(Index == StrTabBuf.size()); 00422 StrTab.Size = Index; 00423 00424 // Now that we have emitted the string table and know the offset into the 00425 // string table of each symbol, emit the symbol table itself. 00426 ELFSection &SymTab = getSection(".symtab", ELFSection::SHT_SYMTAB, 0); 00427 SymTab.Align = is64Bit ? 8 : 4; 00428 SymTab.Link = SymTab.SectionIdx; // Section Index of .strtab. 00429 SymTab.Info = FirstNonLocalSymbol; // First non-STB_LOCAL symbol. 00430 SymTab.EntSize = 16; // Size of each symtab entry. FIXME: wrong for ELF64 00431 DataBuffer &SymTabBuf = SymTab.SectionData; 00432 OutputBuffer SymTabOut(SymTabBuf, is64Bit, isLittleEndian); 00433 00434 if (!is64Bit) { // 32-bit and 64-bit formats are shuffled a bit. 00435 for (unsigned i = 0, e = SymbolTable.size(); i != e; ++i) { 00436 ELFSym &Sym = SymbolTable[i]; 00437 SymTabOut.outword(Sym.NameIdx); 00438 SymTabOut.outaddr32(Sym.Value); 00439 SymTabOut.outword(Sym.Size); 00440 SymTabOut.outbyte(Sym.Info); 00441 SymTabOut.outbyte(Sym.Other); 00442 SymTabOut.outhalf(Sym.SectionIdx); 00443 } 00444 } else { 00445 for (unsigned i = 0, e = SymbolTable.size(); i != e; ++i) { 00446 ELFSym &Sym = SymbolTable[i]; 00447 SymTabOut.outword(Sym.NameIdx); 00448 SymTabOut.outbyte(Sym.Info); 00449 SymTabOut.outbyte(Sym.Other); 00450 SymTabOut.outhalf(Sym.SectionIdx); 00451 SymTabOut.outaddr64(Sym.Value); 00452 SymTabOut.outxword(Sym.Size); 00453 } 00454 } 00455 00456 SymTab.Size = SymTabBuf.size(); 00457 } 00458 00459 /// EmitSectionTableStringTable - This method adds and emits a section for the 00460 /// ELF Section Table string table: the string table that holds all of the 00461 /// section names. 00462 void ELFWriter::EmitSectionTableStringTable() { 00463 // First step: add the section for the string table to the list of sections: 00464 ELFSection &SHStrTab = getSection(".shstrtab", ELFSection::SHT_STRTAB, 0); 00465 00466 // Now that we know which section number is the .shstrtab section, update the 00467 // e_shstrndx entry in the ELF header. 00468 OutputBuffer FHOut(FileHeader, is64Bit, isLittleEndian); 00469 FHOut.fixhalf(SHStrTab.SectionIdx, ELFHeader_e_shstrndx_Offset); 00470 00471 // Set the NameIdx of each section in the string table and emit the bytes for 00472 // the string table. 00473 unsigned Index = 0; 00474 DataBuffer &Buf = SHStrTab.SectionData; 00475 00476 for (std::list<ELFSection>::iterator I = SectionList.begin(), 00477 E = SectionList.end(); I != E; ++I) { 00478 // Set the index into the table. Note if we have lots of entries with 00479 // common suffixes, we could memoize them here if we cared. 00480 I->NameIdx = Index; 00481 00482 // Add the name to the output buffer, including the null terminator. 00483 Buf.insert(Buf.end(), I->Name.begin(), I->Name.end()); 00484 00485 // Add a null terminator. 00486 Buf.push_back(0); 00487 00488 // Keep track of the number of bytes emitted to this section. 00489 Index += I->Name.size()+1; 00490 } 00491 00492 // Set the size of .shstrtab now that we know what it is. 00493 assert(Index == Buf.size()); 00494 SHStrTab.Size = Index; 00495 } 00496 00497 /// OutputSectionsAndSectionTable - Now that we have constructed the file header 00498 /// and all of the sections, emit these to the ostream destination and emit the 00499 /// SectionTable. 00500 void ELFWriter::OutputSectionsAndSectionTable() { 00501 // Pass #1: Compute the file offset for each section. 00502 size_t FileOff = FileHeader.size(); // File header first. 00503 00504 // Emit all of the section data in order. 00505 for (std::list<ELFSection>::iterator I = SectionList.begin(), 00506 E = SectionList.end(); I != E; ++I) { 00507 // Align FileOff to whatever the alignment restrictions of the section are. 00508 if (I->Align) 00509 FileOff = (FileOff+I->Align-1) & ~(I->Align-1); 00510 I->Offset = FileOff; 00511 FileOff += I->SectionData.size(); 00512 } 00513 00514 // Align Section Header. 00515 unsigned TableAlign = is64Bit ? 8 : 4; 00516 FileOff = (FileOff+TableAlign-1) & ~(TableAlign-1); 00517 00518 // Now that we know where all of the sections will be emitted, set the e_shnum 00519 // entry in the ELF header. 00520 OutputBuffer FHOut(FileHeader, is64Bit, isLittleEndian); 00521 FHOut.fixhalf(NumSections, ELFHeader_e_shnum_Offset); 00522 00523 // Now that we know the offset in the file of the section table, update the 00524 // e_shoff address in the ELF header. 00525 FHOut.fixaddr(FileOff, ELFHeader_e_shoff_Offset); 00526 00527 // Now that we know all of the data in the file header, emit it and all of the 00528 // sections! 00529 O.write((char*)&FileHeader[0], FileHeader.size()); 00530 FileOff = FileHeader.size(); 00531 DataBuffer().swap(FileHeader); 00532 00533 DataBuffer Table; 00534 OutputBuffer TableOut(Table, is64Bit, isLittleEndian); 00535 00536 // Emit all of the section data and build the section table itself. 00537 while (!SectionList.empty()) { 00538 const ELFSection &S = *SectionList.begin(); 00539 00540 // Align FileOff to whatever the alignment restrictions of the section are. 00541 if (S.Align) 00542 for (size_t NewFileOff = (FileOff+S.Align-1) & ~(S.Align-1); 00543 FileOff != NewFileOff; ++FileOff) 00544 O << (char)0xAB; 00545 O.write((char*)&S.SectionData[0], S.SectionData.size()); 00546 FileOff += S.SectionData.size(); 00547 00548 TableOut.outword(S.NameIdx); // sh_name - Symbol table name idx 00549 TableOut.outword(S.Type); // sh_type - Section contents & semantics 00550 TableOut.outword(S.Flags); // sh_flags - Section flags. 00551 TableOut.outaddr(S.Addr); // sh_addr - The mem addr this section is in. 00552 TableOut.outaddr(S.Offset); // sh_offset - Offset from the file start. 00553 TableOut.outword(S.Size); // sh_size - The section size. 00554 TableOut.outword(S.Link); // sh_link - Section header table index link. 00555 TableOut.outword(S.Info); // sh_info - Auxillary information. 00556 TableOut.outword(S.Align); // sh_addralign - Alignment of section. 00557 TableOut.outword(S.EntSize); // sh_entsize - Size of entries in the section 00558 00559 SectionList.pop_front(); 00560 } 00561 00562 // Align output for the section table. 00563 for (size_t NewFileOff = (FileOff+TableAlign-1) & ~(TableAlign-1); 00564 FileOff != NewFileOff; ++FileOff) 00565 O << (char)0xAB; 00566 00567 // Emit the section table itself. 00568 O.write((char*)&Table[0], Table.size()); 00569 }