Newer
Older
//===-- ELFWriter.cpp - Target-independent ELF Writer code ----------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the target-independent ELF writer. This file writes out
// the ELF file in the following order:
//
// #1. ELF Header
// #2. '.text' section
// #3. '.data' section
// #4. '.bss' section (conceptual position in file)
// ...
// #X. '.shstrtab' section
// #Y. Section Table
//
// The entries in the section table are laid out as:
// #0. Null entry [required]
// #1. ".text" entry - the program code
// #2. ".data" entry - global variables with initializers. [ if needed ]
// #3. ".bss" entry - global variables without initializers. [ if needed ]
// ...
// #N. ".shstrtab" entry - String table for the section names.
//
//===----------------------------------------------------------------------===//
Bruno Cardoso Lopes
committed
#define DEBUG_TYPE "elfwriter"
#include "llvm/DerivedTypes.h"
Bruno Cardoso Lopes
committed
#include "llvm/CodeGen/BinaryObject.h"
#include "llvm/CodeGen/MachineCodeEmitter.h"
Bruno Cardoso Lopes
committed
#include "llvm/CodeGen/ObjectCodeEmitter.h"
#include "llvm/CodeGen/MachineCodeEmitter.h"
#include "llvm/CodeGen/MachineConstantPool.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCSectionELF.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/Target/Mangler.h"
Owen Anderson
committed
#include "llvm/Target/TargetData.h"
#include "llvm/Target/TargetELFWriterInfo.h"
#include "llvm/Target/TargetLowering.h"
#include "llvm/Target/TargetLoweringObjectFile.h"
#include "llvm/Target/TargetMachine.h"
Bruno Cardoso Lopes
committed
#include "llvm/Support/Debug.h"
#include "llvm/ADT/SmallString.h"
//===----------------------------------------------------------------------===//
// ELFWriter Implementation
//===----------------------------------------------------------------------===//
ELFWriter::ELFWriter(raw_ostream &o, TargetMachine &tm)
: MachineFunctionPass(&ID), O(o), TM(tm),
OutContext(*new MCContext(*TM.getMCAsmInfo())),
TLOF(TM.getTargetLowering()->getObjFileLowering()),
Bruno Cardoso Lopes
committed
is64Bit(TM.getTargetData()->getPointerSizeInBits() == 64),
isLittleEndian(TM.getTargetData()->isLittleEndian()),
ElfHdr(isLittleEndian, is64Bit) {
MAI = TM.getMCAsmInfo();
Bruno Cardoso Lopes
committed
TEW = TM.getELFWriterInfo();
Bruno Cardoso Lopes
committed
// Create the object code emitter object for this target.
ElfCE = new ELFCodeEmitter(*this);
Bruno Cardoso Lopes
committed
// Inital number of sections
NumSections = 0;
}
ELFWriter::~ELFWriter() {
delete ElfCE;
delete &OutContext;
while(!SymbolList.empty()) {
delete SymbolList.back();
SymbolList.pop_back();
}
while(!PrivateSyms.empty()) {
delete PrivateSyms.back();
PrivateSyms.pop_back();
}
while(!SectionList.empty()) {
delete SectionList.back();
SectionList.pop_back();
}
// Release the name mangler object.
delete Mang; Mang = 0;
}
// doInitialization - Emit the file header and all of the global variables for
// the module to the ELF file.
bool ELFWriter::doInitialization(Module &M) {
// Initialize TargetLoweringObjectFile.
const_cast<TargetLoweringObjectFile&>(TLOF).Initialize(OutContext, TM);
Mang = new Mangler(OutContext, *TM.getTargetData());
Bruno Cardoso Lopes
committed
// ELF Header
// ----------
// Fields e_shnum e_shstrndx are only known after all section have
// been emitted. They locations in the ouput buffer are recorded so
// to be patched up later.
//
// Note
// ----
Bruno Cardoso Lopes
committed
// emitWord method behaves differently for ELF32 and ELF64, writing
Bruno Cardoso Lopes
committed
// 4 bytes in the former and 8 in the last for *_off and *_addr elf types
Bruno Cardoso Lopes
committed
ElfHdr.emitByte(0x7f); // e_ident[EI_MAG0]
ElfHdr.emitByte('E'); // e_ident[EI_MAG1]
ElfHdr.emitByte('L'); // e_ident[EI_MAG2]
ElfHdr.emitByte('F'); // e_ident[EI_MAG3]
ElfHdr.emitByte(TEW->getEIClass()); // e_ident[EI_CLASS]
ElfHdr.emitByte(TEW->getEIData()); // e_ident[EI_DATA]
ElfHdr.emitByte(ELF::EV_CURRENT); // e_ident[EI_VERSION]
Bruno Cardoso Lopes
committed
ElfHdr.emitAlignment(16); // e_ident[EI_NIDENT-EI_PAD]
ElfHdr.emitWord16(ELF::ET_REL); // e_type
Bruno Cardoso Lopes
committed
ElfHdr.emitWord16(TEW->getEMachine()); // e_machine = target
ElfHdr.emitWord32(ELF::EV_CURRENT); // e_version
Bruno Cardoso Lopes
committed
ElfHdr.emitWord(0); // e_entry, no entry point in .o file
ElfHdr.emitWord(0); // e_phoff, no program header for .o
ELFHdr_e_shoff_Offset = ElfHdr.size();
ElfHdr.emitWord(0); // e_shoff = sec hdr table off in bytes
ElfHdr.emitWord32(TEW->getEFlags()); // e_flags = whatever the target wants
ElfHdr.emitWord16(TEW->getHdrSize()); // e_ehsize = ELF header size
ElfHdr.emitWord16(0); // e_phentsize = prog header entry size
ElfHdr.emitWord16(0); // e_phnum = # prog header entries = 0
Bruno Cardoso Lopes
committed
// e_shentsize = Section header entry size
Bruno Cardoso Lopes
committed
ElfHdr.emitWord16(TEW->getSHdrSize());
Bruno Cardoso Lopes
committed
// e_shnum = # of section header ents
Bruno Cardoso Lopes
committed
ELFHdr_e_shnum_Offset = ElfHdr.size();
ElfHdr.emitWord16(0); // Placeholder
Bruno Cardoso Lopes
committed
// e_shstrndx = Section # of '.shstrtab'
Bruno Cardoso Lopes
committed
ELFHdr_e_shstrndx_Offset = ElfHdr.size();
ElfHdr.emitWord16(0); // Placeholder
// Add the null section, which is required to be first in the file.
getNullSection();
// The first entry in the symtab is the null symbol and the second
// is a local symbol containing the module/file name
SymbolList.push_back(new ELFSym());
SymbolList.push_back(ELFSym::getFileSym());
// AddPendingGlobalSymbol - Add a global to be processed and to
// the global symbol lookup, use a zero index because the table
// index will be determined later.
void ELFWriter::AddPendingGlobalSymbol(const GlobalValue *GV,
bool AddToLookup /* = false */) {
PendingGlobals.insert(GV);
if (AddToLookup)
GblSymLookup[GV] = 0;
}
// AddPendingExternalSymbol - Add the external to be processed
// and to the external symbol lookup, use a zero index because
// the symbol table index will be determined later.
void ELFWriter::AddPendingExternalSymbol(const char *External) {
PendingExternals.insert(External);
ExtSymLookup[External] = 0;
}
ELFSection &ELFWriter::getDataSection() {
const MCSectionELF *Data = (const MCSectionELF *)TLOF.getDataSection();
return getSection(Data->getSectionName(), Data->getType(),
Data->getFlags(), 4);
}
ELFSection &ELFWriter::getBSSSection() {
const MCSectionELF *BSS = (const MCSectionELF *)TLOF.getBSSSection();
return getSection(BSS->getSectionName(), BSS->getType(), BSS->getFlags(), 4);
}
// getCtorSection - Get the static constructor section
ELFSection &ELFWriter::getCtorSection() {
const MCSectionELF *Ctor = (const MCSectionELF *)TLOF.getStaticCtorSection();
Loading
Loading full blame...