//===- ELFExecWriter.cpp --------------------------------------------------===// // // The MCLinker Project // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include <mcld/LD/ELFExecWriter.h> #include <mcld/LD/LDSymbol.h> #include <mcld/Target/GNULDBackend.h> #include <mcld/MC/MCLDInput.h> #include <mcld/MC/MCLDOutput.h> #include <mcld/MC/MCLDInfo.h> #include <mcld/MC/MCLinker.h> #include <llvm/Support/ELF.h> #include <vector> using namespace llvm; using namespace mcld; //========================== // ELFExecWriter ELFExecWriter::ELFExecWriter(GNULDBackend& pBackend, MCLinker& pLinker) : ExecWriter(pBackend), ELFWriter(pBackend), m_Backend(pBackend), m_Linker(pLinker) { } ELFExecWriter::~ELFExecWriter() { } llvm::error_code ELFExecWriter::writeExecutable(Output& pOutput) { // write out the interpreter section: .interp target().emitInterp(pOutput, m_Linker.getLDInfo()); // Write out name pool sections: .dynsym, .dynstr, .hash target().emitDynNamePools(pOutput, m_Linker.getOutputSymbols(), m_Linker.getLayout(), m_Linker.getLDInfo()); // Write out name pool sections: .symtab, .strtab target().emitRegNamePools(pOutput, m_Linker.getOutputSymbols(), m_Linker.getLayout(), m_Linker.getLDInfo()); // Write out regular ELF sections unsigned int secIdx = 0; unsigned int secEnd = pOutput.context()->numOfSections(); for (secIdx = 0; secIdx < secEnd; ++secIdx) { LDSection* sect = pOutput.context()->getSection(secIdx); MemoryRegion* region = NULL; // request output region switch(sect->kind()) { case LDFileFormat::Regular: case LDFileFormat::Relocation: case LDFileFormat::Target: case LDFileFormat::Debug: case LDFileFormat::GCCExceptTable: case LDFileFormat::EhFrame: { region = pOutput.memArea()->request(sect->offset(), sect->size()); if (NULL == region) { llvm::report_fatal_error(llvm::Twine("cannot get enough memory region for output section[") + llvm::Twine(secIdx) + llvm::Twine("] - `") + sect->name() + llvm::Twine("'.\n")); } break; } case LDFileFormat::Null: case LDFileFormat::NamePool: case LDFileFormat::BSS: case LDFileFormat::Note: case LDFileFormat::MetaData: case LDFileFormat::Version: case LDFileFormat::EhFrameHdr: // ignore these sections continue; default: { llvm::errs() << "WARNING: unsupported section kind: " << sect->kind() << " of section " << sect->name() << ".\n"; continue; } } // write out sections with data switch(sect->kind()) { case LDFileFormat::Regular: case LDFileFormat::Debug: case LDFileFormat::GCCExceptTable: case LDFileFormat::EhFrame: { // FIXME: if optimization of exception handling sections is enabled, // then we should emit these sections by the other way. emitSectionData(m_Linker.getLayout(), *sect, *region); break; } case LDFileFormat::Relocation: emitRelocation(m_Linker.getLayout(), pOutput, *sect, *region); break; case LDFileFormat::Target: target().emitSectionData(pOutput, *sect, m_Linker.getLDInfo(), m_Linker.getLayout(), *region); break; default: continue; } } // end of for loop if (32 == target().bitclass()) { // Write out ELF header // Write out section header table emitELF32ShStrTab(pOutput, m_Linker); writeELF32Header(m_Linker.getLDInfo(), m_Linker.getLayout(), target(), pOutput); emitELF32ProgramHeader(pOutput, target()); emitELF32SectionHeader(pOutput, m_Linker); } else if (64 == target().bitclass()) { // Write out ELF header // Write out section header table emitELF64ShStrTab(pOutput, m_Linker); writeELF64Header(m_Linker.getLDInfo(), m_Linker.getLayout(), target(), pOutput); emitELF64ProgramHeader(pOutput, target()); emitELF64SectionHeader(pOutput, m_Linker); } else return make_error_code(errc::not_supported); pOutput.memArea()->clear(); return llvm::make_error_code(llvm::errc::success); }