//===-- 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.
//
//===----------------------------------------------------------------------===//

#define DEBUG_TYPE "elfwriter"
#include "ELF.h"
#include "ELFWriter.h"
#include "ELFCodeEmitter.h"
#include "llvm/Constants.h"
#include "llvm/Module.h"
#include "llvm/PassManager.h"
#include "llvm/DerivedTypes.h"
#include "llvm/CodeGen/BinaryObject.h"
#include "llvm/CodeGen/MachineCodeEmitter.h"
#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"
#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"
#include "llvm/Target/TargetRegisterInfo.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/ADT/SmallString.h"
using namespace llvm;

char ELFWriter::ID = 0;

//===----------------------------------------------------------------------===//
//                          ELFWriter Implementation
//===----------------------------------------------------------------------===//

ELFWriter::ELFWriter(raw_ostream &o, TargetMachine &tm)
  : MachineFunctionPass(ID), O(o), TM(tm),
    OutContext(*new MCContext(*TM.getMCAsmInfo(), *TM.getRegisterInfo(),
                              &TM.getTargetLowering()->getObjFileLowering())),
    TLOF(TM.getTargetLowering()->getObjFileLowering()),
    is64Bit(TM.getTargetData()->getPointerSizeInBits() == 64),
    isLittleEndian(TM.getTargetData()->isLittleEndian()),
    ElfHdr(isLittleEndian, is64Bit) {

  MAI = TM.getMCAsmInfo();
  TEW = TM.getELFWriterInfo();

  // Create the object code emitter object for this target.
  ElfCE = new ELFCodeEmitter(*this);

  // Initial 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());

  // 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
  // ----
  // emitWord method behaves differently for ELF32 and ELF64, writing
  // 4 bytes in the former and 8 in the last for *_off and *_addr elf types

  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]
  ElfHdr.emitAlignment(16);           // e_ident[EI_NIDENT-EI_PAD]

  ElfHdr.emitWord16(ELF::ET_REL);        // e_type
  ElfHdr.emitWord16(TEW->getEMachine()); // e_machine = target
  ElfHdr.emitWord32(ELF::EV_CURRENT);    // e_version
  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

  // e_shentsize = Section header entry size
  ElfHdr.emitWord16(TEW->getSHdrSize());

  // e_shnum     = # of section header ents
  ELFHdr_e_shnum_Offset = ElfHdr.size();
  ElfHdr.emitWord16(0); // Placeholder

  // e_shstrndx  = Section # of '.shstrtab'
  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());

  return false;
}

// 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();
  return getSection(Ctor->getSectionName(), Ctor->getType(), Ctor->getFlags()); 
}

// getDtorSection - Get the static destructor section
ELFSection &ELFWriter::getDtorSection() {
  const MCSectionELF *Dtor = (const MCSectionELF *)TLOF.getStaticDtorSection();
  return getSection(Dtor->getSectionName(), Dtor->getType(), Dtor->getFlags());
}

// getTextSection - Get the text section for the specified function
ELFSection &ELFWriter::getTextSection(const Function *F) {
  const MCSectionELF *Text = 
    (const MCSectionELF *)TLOF.SectionForGlobal(F, Mang, TM);
  return getSection(Text->getSectionName(), Text->getType(), Text->getFlags());
}

// getJumpTableSection - Get a read only section for constants when 
// emitting jump tables. TODO: add PIC support
ELFSection &ELFWriter::getJumpTableSection() {
  const MCSectionELF *JT = 
    (const MCSectionELF *)TLOF.getSectionForConstant(SectionKind::getReadOnly());
  return getSection(JT->getSectionName(), JT->getType(), JT->getFlags(),
                    TM.getTargetData()->getPointerABIAlignment());
}

// getConstantPoolSection - Get a constant pool section based on the machine 
// constant pool entry type and relocation info.
ELFSection &ELFWriter::getConstantPoolSection(MachineConstantPoolEntry &CPE) {
  SectionKind Kind;
  switch (CPE.getRelocationInfo()) {
  default: llvm_unreachable("Unknown section kind");
  case 2: Kind = SectionKind::getReadOnlyWithRel(); break;
  case 1:
    Kind = SectionKind::getReadOnlyWithRelLocal();
    break;
  case 0:
    switch (TM.getTargetData()->getTypeAllocSize(CPE.getType())) {
    case 4:  Kind = SectionKind::getMergeableConst4(); break;
    case 8:  Kind = SectionKind::getMergeableConst8(); break;
    case 16: Kind = SectionKind::getMergeableConst16(); break;
    default: Kind = SectionKind::getMergeableConst(); break;
    }
  }

  const MCSectionELF *CPSect = 
    (const MCSectionELF *)TLOF.getSectionForConstant(Kind);
  return getSection(CPSect->getSectionName(), CPSect->getType(), 
                    CPSect->getFlags(), CPE.getAlignment());
}

// getRelocSection - Return the relocation section of section 'S'. 'RelA' 
// is true if the relocation section contains entries with addends.
ELFSection &ELFWriter::getRelocSection(ELFSection &S) {
  unsigned SectionType = TEW->hasRelocationAddend() ?
                ELF::SHT_RELA : ELF::SHT_REL;

  std::string SectionName(".rel");
  if (TEW->hasRelocationAddend())
    SectionName.append("a");
  SectionName.append(S.getName());

  return getSection(SectionName, SectionType, 0, TEW->getPrefELFAlignment());
}

// getGlobalELFVisibility - Returns the ELF specific visibility type
unsigned ELFWriter::getGlobalELFVisibility(const GlobalValue *GV) {
  switch (GV->getVisibility()) {
  default:
    llvm_unreachable("unknown visibility type");
  case GlobalValue::DefaultVisibility:
    return ELF::STV_DEFAULT;
  case GlobalValue::HiddenVisibility:
    return ELF::STV_HIDDEN;
  case GlobalValue::ProtectedVisibility:
    return ELF::STV_PROTECTED;
  }
  return 0;
}

// getGlobalELFBinding - Returns the ELF specific binding type
unsigned ELFWriter::getGlobalELFBinding(const GlobalValue *GV) {
  if (GV->hasInternalLinkage())
    return ELF::STB_LOCAL;

  if (GV->isWeakForLinker() && !GV->hasCommonLinkage())
    return ELF::STB_WEAK;

  return ELF::STB_GLOBAL;
}

// getGlobalELFType - Returns the ELF specific type for a global
unsigned ELFWriter::getGlobalELFType(const GlobalValue *GV) {
  if (GV->isDeclaration())
    return ELF::STT_NOTYPE;

  if (isa<Function>(GV))
    return ELF::STT_FUNC;

  return ELF::STT_OBJECT;
}

// IsELFUndefSym - True if the global value must be marked as a symbol
// which points to a SHN_UNDEF section. This means that the symbol has
// no definition on the module.
static bool IsELFUndefSym(const GlobalValue *GV) {
  return GV->isDeclaration() || (isa<Function>(GV));
}

// AddToSymbolList - Update the symbol lookup and If the symbol is 
// private add it to PrivateSyms list, otherwise to SymbolList. 
void ELFWriter::AddToSymbolList(ELFSym *GblSym) {
  assert(GblSym->isGlobalValue() && "Symbol must be a global value");

  const GlobalValue *GV = GblSym->getGlobalValue(); 
  if (GV->hasPrivateLinkage()) {
    // For a private symbols, keep track of the index inside 
    // the private list since it will never go to the symbol 
    // table and won't be patched up later.
    PrivateSyms.push_back(GblSym);
    GblSymLookup[GV] = PrivateSyms.size()-1;
  } else {
    // Non private symbol are left with zero indices until 
    // they are patched up during the symbol table emition 
    // (where the indicies are created).
    SymbolList.push_back(GblSym);
    GblSymLookup[GV] = 0;
  }
}

/// HasCommonSymbols - True if this section holds common symbols, this is
/// indicated on the ELF object file by a symbol with SHN_COMMON section
/// header index.
static bool HasCommonSymbols(const MCSectionELF &S) {
  // FIXME: this is wrong, a common symbol can be in .data for example.
  if (StringRef(S.getSectionName()).startswith(".gnu.linkonce."))
    return true;

  return false;
}


// EmitGlobal - Choose the right section for global and emit it
void ELFWriter::EmitGlobal(const GlobalValue *GV) {

  // Check if the referenced symbol is already emitted
  if (GblSymLookup.find(GV) != GblSymLookup.end())
    return;

  // Handle ELF Bind, Visibility and Type for the current symbol
  unsigned SymBind = getGlobalELFBinding(GV);
  unsigned SymType = getGlobalELFType(GV);
  bool IsUndefSym = IsELFUndefSym(GV);

  ELFSym *GblSym = IsUndefSym ? ELFSym::getUndefGV(GV, SymBind)
    : ELFSym::getGV(GV, SymBind, SymType, getGlobalELFVisibility(GV));

  if (!IsUndefSym) {
    assert(isa<GlobalVariable>(GV) && "GV not a global variable!");
    const GlobalVariable *GVar = dyn_cast<GlobalVariable>(GV);

    // Handle special llvm globals
    if (EmitSpecialLLVMGlobal(GVar))
      return;

    // Get the ELF section where this global belongs from TLOF
    const MCSectionELF *S = 
      (const MCSectionELF *)TLOF.SectionForGlobal(GV, Mang, TM);
    ELFSection &ES = 
      getSection(S->getSectionName(), S->getType(), S->getFlags());
    SectionKind Kind = S->getKind();

    // The symbol align should update the section alignment if needed
    const TargetData *TD = TM.getTargetData();
    unsigned Align = TD->getPreferredAlignment(GVar);
    unsigned Size = TD->getTypeAllocSize(GVar->getInitializer()->getType());
    GblSym->Size = Size;

    if (HasCommonSymbols(*S)) { // Symbol must go to a common section
      GblSym->SectionIdx = ELF::SHN_COMMON;

      // A new linkonce section is created for each global in the
      // common section, the default alignment is 1 and the symbol
      // value contains its alignment.
      ES.Align = 1;
      GblSym->Value = Align;

    } else if (Kind.isBSS() || Kind.isThreadBSS()) { // Symbol goes to BSS.
      GblSym->SectionIdx = ES.SectionIdx;

      // Update the size with alignment and the next object can
      // start in the right offset in the section
      if (Align) ES.Size = (ES.Size + Align-1) & ~(Align-1);
      ES.Align = std::max(ES.Align, Align);

      // GblSym->Value should contain the virtual offset inside the section.
      // Virtual because the BSS space is not allocated on ELF objects
      GblSym->Value = ES.Size;
      ES.Size += Size;

    } else { // The symbol must go to some kind of data section
      GblSym->SectionIdx = ES.SectionIdx;

      // GblSym->Value should contain the symbol offset inside the section,
      // and all symbols should start on their required alignment boundary
      ES.Align = std::max(ES.Align, Align);
      ES.emitAlignment(Align);
      GblSym->Value = ES.size();

      // Emit the global to the data section 'ES'
      EmitGlobalConstant(GVar->getInitializer(), ES);
    }
  }

  AddToSymbolList(GblSym);
}

void ELFWriter::EmitGlobalConstantStruct(const ConstantStruct *CVS,
                                         ELFSection &GblS) {

  // Print the fields in successive locations. Pad to align if needed!
  const TargetData *TD = TM.getTargetData();
  unsigned Size = TD->getTypeAllocSize(CVS->getType());
  const StructLayout *cvsLayout = TD->getStructLayout(CVS->getType());
  uint64_t sizeSoFar = 0;
  for (unsigned i = 0, e = CVS->getNumOperands(); i != e; ++i) {
    const Constant* field = CVS->getOperand(i);

    // Check if padding is needed and insert one or more 0s.
    uint64_t fieldSize = TD->getTypeAllocSize(field->getType());
    uint64_t padSize = ((i == e-1 ? Size : cvsLayout->getElementOffset(i+1))
                        - cvsLayout->getElementOffset(i)) - fieldSize;
    sizeSoFar += fieldSize + padSize;

    // Now print the actual field value.
    EmitGlobalConstant(field, GblS);

    // Insert padding - this may include padding to increase the size of the
    // current field up to the ABI size (if the struct is not packed) as well
    // as padding to ensure that the next field starts at the right offset.
    GblS.emitZeros(padSize);
  }
  assert(sizeSoFar == cvsLayout->getSizeInBytes() &&
         "Layout of constant struct may be incorrect!");
}

void ELFWriter::EmitGlobalConstant(const Constant *CV, ELFSection &GblS) {
  const TargetData *TD = TM.getTargetData();
  unsigned Size = TD->getTypeAllocSize(CV->getType());

  if (const ConstantArray *CVA = dyn_cast<ConstantArray>(CV)) {
    for (unsigned i = 0, e = CVA->getNumOperands(); i != e; ++i)
      EmitGlobalConstant(CVA->getOperand(i), GblS);
    return;
  } else if (isa<ConstantAggregateZero>(CV)) {
    GblS.emitZeros(Size);
    return;
  } else if (const ConstantStruct *CVS = dyn_cast<ConstantStruct>(CV)) {
    EmitGlobalConstantStruct(CVS, GblS);
    return;
  } else if (const ConstantFP *CFP = dyn_cast<ConstantFP>(CV)) {
    APInt Val = CFP->getValueAPF().bitcastToAPInt();
    if (CFP->getType()->isDoubleTy())
      GblS.emitWord64(Val.getZExtValue());
    else if (CFP->getType()->isFloatTy())
      GblS.emitWord32(Val.getZExtValue());
    else if (CFP->getType()->isX86_FP80Ty()) {
      unsigned PadSize = TD->getTypeAllocSize(CFP->getType())-
                         TD->getTypeStoreSize(CFP->getType());
      GblS.emitWordFP80(Val.getRawData(), PadSize);
    } else if (CFP->getType()->isPPC_FP128Ty())
      llvm_unreachable("PPC_FP128Ty global emission not implemented");
    return;
  } else if (const ConstantInt *CI = dyn_cast<ConstantInt>(CV)) {
    if (Size == 1)
      GblS.emitByte(CI->getZExtValue());
    else if (Size == 2) 
      GblS.emitWord16(CI->getZExtValue());
    else if (Size == 4)
      GblS.emitWord32(CI->getZExtValue());
    else 
      EmitGlobalConstantLargeInt(CI, GblS);
    return;
  } else if (const ConstantVector *CP = dyn_cast<ConstantVector>(CV)) {
    VectorType *PTy = CP->getType();
    for (unsigned I = 0, E = PTy->getNumElements(); I < E; ++I)
      EmitGlobalConstant(CP->getOperand(I), GblS);
    return;
  } else if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(CV)) {
    // Resolve a constant expression which returns a (Constant, Offset)
    // pair. If 'Res.first' is a GlobalValue, emit a relocation with 
    // the offset 'Res.second', otherwise emit a global constant like
    // it is always done for not contant expression types.
    CstExprResTy Res = ResolveConstantExpr(CE);
    const Constant *Op = Res.first;

    if (isa<GlobalValue>(Op))
      EmitGlobalDataRelocation(cast<const GlobalValue>(Op), 
                               TD->getTypeAllocSize(Op->getType()), 
                               GblS, Res.second);
    else
      EmitGlobalConstant(Op, GblS);

    return;
  } else if (CV->getType()->getTypeID() == Type::PointerTyID) {
    // Fill the data entry with zeros or emit a relocation entry
    if (isa<ConstantPointerNull>(CV))
      GblS.emitZeros(Size);
    else 
      EmitGlobalDataRelocation(cast<const GlobalValue>(CV), 
                               Size, GblS);
    return;
  } else if (const GlobalValue *GV = dyn_cast<GlobalValue>(CV)) {
    // This is a constant address for a global variable or function and
    // therefore must be referenced using a relocation entry.
    EmitGlobalDataRelocation(GV, Size, GblS);
    return;
  }

  std::string msg;
  raw_string_ostream ErrorMsg(msg);
  ErrorMsg << "Constant unimp for type: " << *CV->getType();
  report_fatal_error(ErrorMsg.str());
}

// ResolveConstantExpr - Resolve the constant expression until it stop
// yielding other constant expressions.
CstExprResTy ELFWriter::ResolveConstantExpr(const Constant *CV) {
  const TargetData *TD = TM.getTargetData();
  
  // There ins't constant expression inside others anymore
  if (!isa<ConstantExpr>(CV))
    return std::make_pair(CV, 0);

  const ConstantExpr *CE = dyn_cast<ConstantExpr>(CV);
  switch (CE->getOpcode()) {
  case Instruction::BitCast:
    return ResolveConstantExpr(CE->getOperand(0));
  
  case Instruction::GetElementPtr: {
    const Constant *ptrVal = CE->getOperand(0);
    SmallVector<Value*, 8> idxVec(CE->op_begin()+1, CE->op_end());
    int64_t Offset = TD->getIndexedOffset(ptrVal->getType(), idxVec);
    return std::make_pair(ptrVal, Offset);
  }
  case Instruction::IntToPtr: {
    Constant *Op = CE->getOperand(0);
    Op = ConstantExpr::getIntegerCast(Op, TD->getIntPtrType(CV->getContext()),
                                      false/*ZExt*/);
    return ResolveConstantExpr(Op);
  }
  case Instruction::PtrToInt: {
    Constant *Op = CE->getOperand(0);
    Type *Ty = CE->getType();

    // We can emit the pointer value into this slot if the slot is an
    // integer slot greater or equal to the size of the pointer.
    if (TD->getTypeAllocSize(Ty) == TD->getTypeAllocSize(Op->getType()))
      return ResolveConstantExpr(Op);

    llvm_unreachable("Integer size less then pointer size");
  }
  case Instruction::Add:
  case Instruction::Sub: {
    // Only handle cases where there's a constant expression with GlobalValue
    // as first operand and ConstantInt as second, which are the cases we can
    // solve direclty using a relocation entry. GlobalValue=Op0, CstInt=Op1
    // 1)  Instruction::Add  => (global) + CstInt
    // 2)  Instruction::Sub  => (global) + -CstInt
    const Constant *Op0 = CE->getOperand(0); 
    const Constant *Op1 = CE->getOperand(1); 
    assert(isa<ConstantInt>(Op1) && "Op1 must be a ConstantInt");

    CstExprResTy Res = ResolveConstantExpr(Op0);
    assert(isa<GlobalValue>(Res.first) && "Op0 must be a GlobalValue");

    const APInt &RHS = cast<ConstantInt>(Op1)->getValue();
    switch (CE->getOpcode()) {
    case Instruction::Add: 
      return std::make_pair(Res.first, RHS.getSExtValue());
    case Instruction::Sub:
      return std::make_pair(Res.first, (-RHS).getSExtValue());
    }
  }
  }

  report_fatal_error(CE->getOpcodeName() +
                     StringRef(": Unsupported ConstantExpr type"));

  return std::make_pair(CV, 0); // silence warning
}

void ELFWriter::EmitGlobalDataRelocation(const GlobalValue *GV, unsigned Size,
                                         ELFSection &GblS, int64_t Offset) {
  // Create the relocation entry for the global value
  MachineRelocation MR =
    MachineRelocation::getGV(GblS.getCurrentPCOffset(),
                             TEW->getAbsoluteLabelMachineRelTy(),
                             const_cast<GlobalValue*>(GV),
                             Offset);

  // Fill the data entry with zeros
  GblS.emitZeros(Size);

  // Add the relocation entry for the current data section
  GblS.addRelocation(MR);
}

void ELFWriter::EmitGlobalConstantLargeInt(const ConstantInt *CI, 
                                           ELFSection &S) {
  const TargetData *TD = TM.getTargetData();
  unsigned BitWidth = CI->getBitWidth();
  assert(isPowerOf2_32(BitWidth) &&
         "Non-power-of-2-sized integers not handled!");

  const uint64_t *RawData = CI->getValue().getRawData();
  uint64_t Val = 0;
  for (unsigned i = 0, e = BitWidth / 64; i != e; ++i) {
    Val = (TD->isBigEndian()) ? RawData[e - i - 1] : RawData[i];
    S.emitWord64(Val);
  }
}

/// EmitSpecialLLVMGlobal - Check to see if the specified global is a
/// special global used by LLVM.  If so, emit it and return true, otherwise
/// do nothing and return false.
bool ELFWriter::EmitSpecialLLVMGlobal(const GlobalVariable *GV) {
  if (GV->getName() == "llvm.used")
    llvm_unreachable("not implemented yet");

  // Ignore debug and non-emitted data.  This handles llvm.compiler.used.
  if (GV->getSection() == "llvm.metadata" ||
      GV->hasAvailableExternallyLinkage())
    return true;
  
  if (!GV->hasAppendingLinkage()) return false;

  assert(GV->hasInitializer() && "Not a special LLVM global!");
  
  const TargetData *TD = TM.getTargetData();
  unsigned Align = TD->getPointerPrefAlignment();
  if (GV->getName() == "llvm.global_ctors") {
    ELFSection &Ctor = getCtorSection();
    Ctor.emitAlignment(Align);
    EmitXXStructorList(GV->getInitializer(), Ctor);
    return true;
  } 
  
  if (GV->getName() == "llvm.global_dtors") {
    ELFSection &Dtor = getDtorSection();
    Dtor.emitAlignment(Align);
    EmitXXStructorList(GV->getInitializer(), Dtor);
    return true;
  }
  
  return false;
}

/// EmitXXStructorList - Emit the ctor or dtor list.  This just emits out the 
/// function pointers, ignoring the init priority.
void ELFWriter::EmitXXStructorList(const Constant *List, ELFSection &Xtor) {
  // Should be an array of '{ i32, void ()* }' structs.  The first value is the
  // init priority, which we ignore.
  if (List->isNullValue()) return;
  const ConstantArray *InitList = cast<ConstantArray>(List);
  for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i) {
    if (InitList->getOperand(i)->isNullValue())
      continue;
    ConstantStruct *CS = cast<ConstantStruct>(InitList->getOperand(i));

    if (CS->getOperand(1)->isNullValue())
      continue;

    // Emit the function pointer.
    EmitGlobalConstant(CS->getOperand(1), Xtor);
  }
}

bool ELFWriter::runOnMachineFunction(MachineFunction &MF) {
  // Nothing to do here, this is all done through the ElfCE object above.
  return false;
}

/// doFinalization - Now that the module has been completely processed, emit
/// the ELF file to 'O'.
bool ELFWriter::doFinalization(Module &M) {
  // Emit .data section placeholder
  getDataSection();

  // Emit .bss section placeholder
  getBSSSection();

  // Build and emit data, bss and "common" sections.
  for (Module::global_iterator I = M.global_begin(), E = M.global_end();
       I != E; ++I)
    EmitGlobal(I);

  // Emit all pending globals
  for (PendingGblsIter I = PendingGlobals.begin(), E = PendingGlobals.end();
       I != E; ++I)
    EmitGlobal(*I);

  // Emit all pending externals
  for (PendingExtsIter I = PendingExternals.begin(), E = PendingExternals.end();
       I != E; ++I)
    SymbolList.push_back(ELFSym::getExtSym(*I));

  // Emit a symbol for each section created until now, skip null section
  for (unsigned i = 1, e = SectionList.size(); i < e; ++i) {
    ELFSection &ES = *SectionList[i];
    ELFSym *SectionSym = ELFSym::getSectionSym();
    SectionSym->SectionIdx = ES.SectionIdx;
    SymbolList.push_back(SectionSym);
    ES.Sym = SymbolList.back();
  }

  // Emit string table
  EmitStringTable(M.getModuleIdentifier());

  // Emit the symbol table now, if non-empty.
  EmitSymbolTable();

  // Emit the relocation sections.
  EmitRelocations();

  // Emit the sections string table.
  EmitSectionTableStringTable();

  // Dump the sections and section table to the .o file.
  OutputSectionsAndSectionTable();

  return false;
}

// RelocateField - Patch relocatable field with 'Offset' in 'BO'
// using a 'Value' of known 'Size'
void ELFWriter::RelocateField(BinaryObject &BO, uint32_t Offset,
                              int64_t Value, unsigned Size) {
  if (Size == 32)
    BO.fixWord32(Value, Offset);
  else if (Size == 64)
    BO.fixWord64(Value, Offset);
  else
    llvm_unreachable("don't know howto patch relocatable field");
}

/// EmitRelocations - Emit relocations
void ELFWriter::EmitRelocations() {

  // True if the target uses the relocation entry to hold the addend,
  // otherwise the addend is written directly to the relocatable field.
  bool HasRelA = TEW->hasRelocationAddend();

  // Create Relocation sections for each section which needs it.
  for (unsigned i=0, e=SectionList.size(); i != e; ++i) {
    ELFSection &S = *SectionList[i];

    // This section does not have relocations
    if (!S.hasRelocations()) continue;
    ELFSection &RelSec = getRelocSection(S);

    // 'Link' - Section hdr idx of the associated symbol table
    // 'Info' - Section hdr idx of the section to which the relocation applies
    ELFSection &SymTab = getSymbolTableSection();
    RelSec.Link = SymTab.SectionIdx;
    RelSec.Info = S.SectionIdx;
    RelSec.EntSize = TEW->getRelocationEntrySize();

    // Get the relocations from Section
    std::vector<MachineRelocation> Relos = S.getRelocations();
    for (std::vector<MachineRelocation>::iterator MRI = Relos.begin(),
         MRE = Relos.end(); MRI != MRE; ++MRI) {
      MachineRelocation &MR = *MRI;

      // Relocatable field offset from the section start
      unsigned RelOffset = MR.getMachineCodeOffset();

      // Symbol index in the symbol table
      unsigned SymIdx = 0;

      // Target specific relocation field type and size
      unsigned RelType = TEW->getRelocationType(MR.getRelocationType());
      unsigned RelTySize = TEW->getRelocationTySize(RelType);
      int64_t Addend = 0;

      // There are several machine relocations types, and each one of
      // them needs a different approach to retrieve the symbol table index.
      if (MR.isGlobalValue()) {
        const GlobalValue *G = MR.getGlobalValue();
        int64_t GlobalOffset = MR.getConstantVal();
        SymIdx = GblSymLookup[G];
        if (G->hasPrivateLinkage()) {
          // If the target uses a section offset in the relocation:
          // SymIdx + Addend = section sym for global + section offset
          unsigned SectionIdx = PrivateSyms[SymIdx]->SectionIdx;
          Addend = PrivateSyms[SymIdx]->Value + GlobalOffset;
          SymIdx = SectionList[SectionIdx]->getSymbolTableIndex();
        } else {
          Addend = TEW->getDefaultAddendForRelTy(RelType, GlobalOffset);
        }
      } else if (MR.isExternalSymbol()) {
        const char *ExtSym = MR.getExternalSymbol();
        SymIdx = ExtSymLookup[ExtSym];
        Addend = TEW->getDefaultAddendForRelTy(RelType);
      } else {
        // Get the symbol index for the section symbol
        unsigned SectionIdx = MR.getConstantVal();
        SymIdx = SectionList[SectionIdx]->getSymbolTableIndex();

        // The symbol offset inside the section
        int64_t SymOffset = (int64_t)MR.getResultPointer();

        // For pc relative relocations where symbols are defined in the same
        // section they are referenced, ignore the relocation entry and patch
        // the relocatable field with the symbol offset directly.
        if (S.SectionIdx == SectionIdx && TEW->isPCRelativeRel(RelType)) {
          int64_t Value = TEW->computeRelocation(SymOffset, RelOffset, RelType);
          RelocateField(S, RelOffset, Value, RelTySize);
          continue;
        }

        Addend = TEW->getDefaultAddendForRelTy(RelType, SymOffset);
      }

      // The target without addend on the relocation symbol must be
      // patched in the relocation place itself to contain the addend
      // otherwise write zeros to make sure there is no garbage there
      RelocateField(S, RelOffset, HasRelA ? 0 : Addend, RelTySize);

      // Get the relocation entry and emit to the relocation section
      ELFRelocation Rel(RelOffset, SymIdx, RelType, HasRelA, Addend);
      EmitRelocation(RelSec, Rel, HasRelA);
    }
  }
}

/// EmitRelocation - Write relocation 'Rel' to the relocation section 'Rel'
void ELFWriter::EmitRelocation(BinaryObject &RelSec, ELFRelocation &Rel,
                               bool HasRelA) {
  RelSec.emitWord(Rel.getOffset());
  RelSec.emitWord(Rel.getInfo(is64Bit));
  if (HasRelA)
    RelSec.emitWord(Rel.getAddend());
}

/// EmitSymbol - Write symbol 'Sym' to the symbol table 'SymbolTable'
void ELFWriter::EmitSymbol(BinaryObject &SymbolTable, ELFSym &Sym) {
  if (is64Bit) {
    SymbolTable.emitWord32(Sym.NameIdx);
    SymbolTable.emitByte(Sym.Info);
    SymbolTable.emitByte(Sym.Other);
    SymbolTable.emitWord16(Sym.SectionIdx);
    SymbolTable.emitWord64(Sym.Value);
    SymbolTable.emitWord64(Sym.Size);
  } else {
    SymbolTable.emitWord32(Sym.NameIdx);
    SymbolTable.emitWord32(Sym.Value);
    SymbolTable.emitWord32(Sym.Size);
    SymbolTable.emitByte(Sym.Info);
    SymbolTable.emitByte(Sym.Other);
    SymbolTable.emitWord16(Sym.SectionIdx);
  }
}

/// EmitSectionHeader - Write section 'Section' header in 'SHdrTab'
/// Section Header Table
void ELFWriter::EmitSectionHeader(BinaryObject &SHdrTab,
                                  const ELFSection &SHdr) {
  SHdrTab.emitWord32(SHdr.NameIdx);
  SHdrTab.emitWord32(SHdr.Type);
  if (is64Bit) {
    SHdrTab.emitWord64(SHdr.Flags);
    SHdrTab.emitWord(SHdr.Addr);
    SHdrTab.emitWord(SHdr.Offset);
    SHdrTab.emitWord64(SHdr.Size);
    SHdrTab.emitWord32(SHdr.Link);
    SHdrTab.emitWord32(SHdr.Info);
    SHdrTab.emitWord64(SHdr.Align);
    SHdrTab.emitWord64(SHdr.EntSize);
  } else {
    SHdrTab.emitWord32(SHdr.Flags);
    SHdrTab.emitWord(SHdr.Addr);
    SHdrTab.emitWord(SHdr.Offset);
    SHdrTab.emitWord32(SHdr.Size);
    SHdrTab.emitWord32(SHdr.Link);
    SHdrTab.emitWord32(SHdr.Info);
    SHdrTab.emitWord32(SHdr.Align);
    SHdrTab.emitWord32(SHdr.EntSize);
  }
}

/// EmitStringTable - If the current symbol table is non-empty, emit the string
/// table for it
void ELFWriter::EmitStringTable(const std::string &ModuleName) {
  if (!SymbolList.size()) return;  // Empty symbol table.
  ELFSection &StrTab = getStringTableSection();

  // Set the zero'th symbol to a null byte, as required.
  StrTab.emitByte(0);

  // Walk on the symbol list and write symbol names into the string table.
  unsigned Index = 1;
  for (ELFSymIter I=SymbolList.begin(), E=SymbolList.end(); I != E; ++I) {
    ELFSym &Sym = *(*I);

    std::string Name;
    if (Sym.isGlobalValue()) {
      SmallString<40> NameStr;
      Mang->getNameWithPrefix(NameStr, Sym.getGlobalValue(), false);
      Name.append(NameStr.begin(), NameStr.end());
    } else if (Sym.isExternalSym())
      Name.append(Sym.getExternalSymbol());
    else if (Sym.isFileType())
      Name.append(ModuleName);

    if (Name.empty()) {
      Sym.NameIdx = 0;
    } else {
      Sym.NameIdx = Index;
      StrTab.emitString(Name);

      // Keep track of the number of bytes emitted to this section.
      Index += Name.size()+1;
    }
  }
  assert(Index == StrTab.size());
  StrTab.Size = Index;
}

// SortSymbols - On the symbol table local symbols must come before
// all other symbols with non-local bindings. The return value is
// the position of the first non local symbol.
unsigned ELFWriter::SortSymbols() {
  unsigned FirstNonLocalSymbol;
  std::vector<ELFSym*> LocalSyms, OtherSyms;

  for (ELFSymIter I=SymbolList.begin(), E=SymbolList.end(); I != E; ++I) {
    if ((*I)->isLocalBind())
      LocalSyms.push_back(*I);
    else
      OtherSyms.push_back(*I);
  }
  SymbolList.clear();
  FirstNonLocalSymbol = LocalSyms.size();

  for (unsigned i = 0; i < FirstNonLocalSymbol; ++i)
    SymbolList.push_back(LocalSyms[i]);

  for (ELFSymIter I=OtherSyms.begin(), E=OtherSyms.end(); I != E; ++I)
    SymbolList.push_back(*I);

  LocalSyms.clear();
  OtherSyms.clear();

  return FirstNonLocalSymbol;
}

/// EmitSymbolTable - Emit the symbol table itself.
void ELFWriter::EmitSymbolTable() {
  if (!SymbolList.size()) return;  // Empty symbol table.

  // Now that we have emitted the string table and know the offset into the
  // string table of each symbol, emit the symbol table itself.
  ELFSection &SymTab = getSymbolTableSection();
  SymTab.Align = TEW->getPrefELFAlignment();

  // Section Index of .strtab.
  SymTab.Link = getStringTableSection().SectionIdx;

  // Size of each symtab entry.
  SymTab.EntSize = TEW->getSymTabEntrySize();

  // Reorder the symbol table with local symbols first!
  unsigned FirstNonLocalSymbol = SortSymbols();

  // Emit all the symbols to the symbol table.
  for (unsigned i = 0, e = SymbolList.size(); i < e; ++i) {
    ELFSym &Sym = *SymbolList[i];

    // Emit symbol to the symbol table
    EmitSymbol(SymTab, Sym);

    // Record the symbol table index for each symbol
    if (Sym.isGlobalValue())
      GblSymLookup[Sym.getGlobalValue()] = i;
    else if (Sym.isExternalSym())
      ExtSymLookup[Sym.getExternalSymbol()] = i;

    // Keep track on the symbol index into the symbol table
    Sym.SymTabIdx = i;
  }

  // One greater than the symbol table index of the last local symbol
  SymTab.Info = FirstNonLocalSymbol;
  SymTab.Size = SymTab.size();
}

/// EmitSectionTableStringTable - This method adds and emits a section for the
/// ELF Section Table string table: the string table that holds all of the
/// section names.
void ELFWriter::EmitSectionTableStringTable() {
  // First step: add the section for the string table to the list of sections:
  ELFSection &SHStrTab = getSectionHeaderStringTableSection();

  // Now that we know which section number is the .shstrtab section, update the
  // e_shstrndx entry in the ELF header.
  ElfHdr.fixWord16(SHStrTab.SectionIdx, ELFHdr_e_shstrndx_Offset);

  // Set the NameIdx of each section in the string table and emit the bytes for
  // the string table.
  unsigned Index = 0;

  for (ELFSectionIter I=SectionList.begin(), E=SectionList.end(); I != E; ++I) {
    ELFSection &S = *(*I);
    // Set the index into the table.  Note if we have lots of entries with
    // common suffixes, we could memoize them here if we cared.
    S.NameIdx = Index;
    SHStrTab.emitString(S.getName());

    // Keep track of the number of bytes emitted to this section.
    Index += S.getName().size()+1;
  }

  // Set the size of .shstrtab now that we know what it is.
  assert(Index == SHStrTab.size());
  SHStrTab.Size = Index;
}

/// OutputSectionsAndSectionTable - Now that we have constructed the file header
/// and all of the sections, emit these to the ostream destination and emit the
/// SectionTable.
void ELFWriter::OutputSectionsAndSectionTable() {
  // Pass #1: Compute the file offset for each section.
  size_t FileOff = ElfHdr.size();   // File header first.

  // Adjust alignment of all section if needed, skip the null section.
  for (unsigned i=1, e=SectionList.size(); i < e; ++i) {
    ELFSection &ES = *SectionList[i];
    if (!ES.size()) {
      ES.Offset = FileOff;
      continue;
    }

    // Update Section size
    if (!ES.Size)
      ES.Size = ES.size();

    // Align FileOff to whatever the alignment restrictions of the section are.
    if (ES.Align)
      FileOff = (FileOff+ES.Align-1) & ~(ES.Align-1);

    ES.Offset = FileOff;
    FileOff += ES.Size;
  }

  // Align Section Header.
  unsigned TableAlign = TEW->getPrefELFAlignment();
  FileOff = (FileOff+TableAlign-1) & ~(TableAlign-1);

  // Now that we know where all of the sections will be emitted, set the e_shnum
  // entry in the ELF header.
  ElfHdr.fixWord16(NumSections, ELFHdr_e_shnum_Offset);

  // Now that we know the offset in the file of the section table, update the
  // e_shoff address in the ELF header.
  ElfHdr.fixWord(FileOff, ELFHdr_e_shoff_Offset);

  // Now that we know all of the data in the file header, emit it and all of the
  // sections!
  O.write((char *)&ElfHdr.getData()[0], ElfHdr.size());
  FileOff = ElfHdr.size();

  // Section Header Table blob
  BinaryObject SHdrTable(isLittleEndian, is64Bit);

  // Emit all of sections to the file and build the section header table.
  for (ELFSectionIter I=SectionList.begin(), E=SectionList.end(); I != E; ++I) {
    ELFSection &S = *(*I);
    DEBUG(dbgs() << "SectionIdx: " << S.SectionIdx << ", Name: " << S.getName()
                 << ", Size: " << S.Size << ", Offset: " << S.Offset
                 << ", SectionData Size: " << S.size() << "\n");

    // Align FileOff to whatever the alignment restrictions of the section are.
    if (S.size()) {
      if (S.Align)  {
        for (size_t NewFileOff = (FileOff+S.Align-1) & ~(S.Align-1);
             FileOff != NewFileOff; ++FileOff)
          O << (char)0xAB;
      }
      O.write((char *)&S.getData()[0], S.Size);
      FileOff += S.Size;
    }

    EmitSectionHeader(SHdrTable, S);
  }

  // Align output for the section table.
  for (size_t NewFileOff = (FileOff+TableAlign-1) & ~(TableAlign-1);
       FileOff != NewFileOff; ++FileOff)
    O << (char)0xAB;

  // Emit the section table itself.
  O.write((char *)&SHdrTable.getData()[0], SHdrTable.size());
}
