//===- ObjectLinker.cpp ---------------------------------------------------===//
//
//                     The MCLinker Project
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include <mcld/Object/ObjectLinker.h>

#include <mcld/LinkerConfig.h>
#include <mcld/LinkerScript.h>
#include <mcld/Module.h>
#include <mcld/InputTree.h>
#include <mcld/IRBuilder.h>
#include <mcld/LD/LDSection.h>
#include <mcld/LD/LDContext.h>
#include <mcld/LD/Archive.h>
#include <mcld/LD/ArchiveReader.h>
#include <mcld/LD/ObjectReader.h>
#include <mcld/LD/DynObjReader.h>
#include <mcld/LD/GroupReader.h>
#include <mcld/LD/BinaryReader.h>
#include <mcld/LD/GarbageCollection.h>
#include <mcld/LD/IdenticalCodeFolding.h>
#include <mcld/LD/ObjectWriter.h>
#include <mcld/LD/ResolveInfo.h>
#include <mcld/LD/RelocData.h>
#include <mcld/LD/Relocator.h>
#include <mcld/LD/SectionData.h>
#include <mcld/LD/BranchIslandFactory.h>
#include <mcld/Script/ScriptFile.h>
#include <mcld/Script/ScriptReader.h>
#include <mcld/Script/Assignment.h>
#include <mcld/Script/Operand.h>
#include <mcld/Script/RpnEvaluator.h>
#include <mcld/Support/RealPath.h>
#include <mcld/Support/FileOutputBuffer.h>
#include <mcld/Support/MsgHandling.h>
#include <mcld/Target/TargetLDBackend.h>
#include <mcld/Fragment/Relocation.h>
#include <mcld/Object/ObjectBuilder.h>

#include <llvm/Support/Casting.h>
#include <llvm/Support/Host.h>
#include <system_error>

using namespace llvm;
using namespace mcld;

//===----------------------------------------------------------------------===//
// ObjectLinker
//===----------------------------------------------------------------------===//
ObjectLinker::ObjectLinker(const LinkerConfig& pConfig,
                           TargetLDBackend& pLDBackend)
  : m_Config(pConfig),
    m_pModule(NULL),
    m_pBuilder(NULL),
    m_LDBackend(pLDBackend),
    m_pObjectReader(NULL),
    m_pDynObjReader(NULL),
    m_pArchiveReader(NULL),
    m_pGroupReader(NULL),
    m_pBinaryReader(NULL),
    m_pScriptReader(NULL),
    m_pWriter(NULL) {
}

ObjectLinker::~ObjectLinker()
{
  delete m_pObjectReader;
  delete m_pDynObjReader;
  delete m_pArchiveReader;
  delete m_pGroupReader;
  delete m_pBinaryReader;
  delete m_pScriptReader;
  delete m_pWriter;
}

bool ObjectLinker::initialize(Module& pModule, IRBuilder& pBuilder)
{
  m_pModule = &pModule;
  m_pBuilder = &pBuilder;

  // initialize the readers and writers
  m_pObjectReader  = m_LDBackend.createObjectReader(*m_pBuilder);
  m_pArchiveReader = m_LDBackend.createArchiveReader(*m_pModule);
  m_pDynObjReader  = m_LDBackend.createDynObjReader(*m_pBuilder);
  m_pBinaryReader  = m_LDBackend.createBinaryReader(*m_pBuilder);
  m_pGroupReader   = new GroupReader(*m_pModule, *m_pObjectReader,
                         *m_pDynObjReader, *m_pArchiveReader, *m_pBinaryReader);
  m_pScriptReader  = new ScriptReader(*m_pGroupReader);
  m_pWriter        = m_LDBackend.createWriter();

  // initialize Relocator
  m_LDBackend.initRelocator();

  return true;
}

/// initStdSections - initialize standard sections
bool ObjectLinker::initStdSections()
{
  ObjectBuilder builder(*m_pModule);

  // initialize standard sections
  if (!m_LDBackend.initStdSections(builder))
    return false;

  // initialize target-dependent sections
  m_LDBackend.initTargetSections(*m_pModule, builder);

  return true;
}

void ObjectLinker::addUndefinedSymbols()
{
  // Add the symbol set by -u as an undefind global symbol into symbol pool
  GeneralOptions::const_undef_sym_iterator usym;
  GeneralOptions::const_undef_sym_iterator usymEnd =
                                             m_Config.options().undef_sym_end();
  for (usym = m_Config.options().undef_sym_begin(); usym != usymEnd; ++usym) {
    Resolver::Result result;
    m_pModule->getNamePool().insertSymbol(*usym, // name
                                          false, // isDyn
                                          ResolveInfo::NoType,
                                          ResolveInfo::Undefined,
                                          ResolveInfo::Global,
                                          0x0, // size
                                          0x0, // value
                                          ResolveInfo::Default,
                                          NULL,
                                          result);

    LDSymbol* output_sym = result.info->outSymbol();
    bool has_output_sym = (NULL != output_sym);

    // create the output symbol if it dose not have one
    if (!result.existent || !has_output_sym) {
      output_sym = LDSymbol::Create(*result.info);
      result.info->setSymPtr(output_sym);
      output_sym->setFragmentRef(FragmentRef::Null());
    }
  }
}

void ObjectLinker::normalize()
{
  // -----  set up inputs  ----- //
  Module::input_iterator input, inEnd = m_pModule->input_end();
  for (input = m_pModule->input_begin(); input!=inEnd; ++input) {
    // is a group node
    if (isGroup(input)) {
      getGroupReader()->readGroup(input, inEnd, m_pBuilder->getInputBuilder(),
                                  m_Config);
      continue;
    }

    // already got type - for example, bitcode or external OIR (object
    // intermediate representation)
    if ((*input)->type() == Input::Script ||
        (*input)->type() == Input::Archive ||
        (*input)->type() == Input::External)
      continue;

    if (Input::Object == (*input)->type()) {
      m_pModule->getObjectList().push_back(*input);
      continue;
    }

    if (Input::DynObj == (*input)->type()) {
      m_pModule->getLibraryList().push_back(*input);
      continue;
    }

    bool doContinue = false;
    // read input as a binary file
    if (getBinaryReader()->isMyFormat(**input, doContinue)) {
      (*input)->setType(Input::Object);
      getBinaryReader()->readBinary(**input);
      m_pModule->getObjectList().push_back(*input);
    }
    // is a relocatable object file
    else if (doContinue && getObjectReader()->isMyFormat(**input, doContinue)) {
      (*input)->setType(Input::Object);
      getObjectReader()->readHeader(**input);
      getObjectReader()->readSections(**input);
      getObjectReader()->readSymbols(**input);
      m_pModule->getObjectList().push_back(*input);
    }
    // is a shared object file
    else if (doContinue && getDynObjReader()->isMyFormat(**input, doContinue)) {
      (*input)->setType(Input::DynObj);
      getDynObjReader()->readHeader(**input);
      getDynObjReader()->readSymbols(**input);
      m_pModule->getLibraryList().push_back(*input);
    }
    // is an archive
    else if (doContinue && getArchiveReader()->isMyFormat(**input, doContinue)) {
      (*input)->setType(Input::Archive);
      if (m_Config.options().isInExcludeLIBS(**input)) {
        (*input)->setNoExport();
      }
      Archive archive(**input, m_pBuilder->getInputBuilder());
      getArchiveReader()->readArchive(m_Config, archive);
      if(archive.numOfObjectMember() > 0) {
        m_pModule->getInputTree().merge<InputTree::Inclusive>(input,
                                                              archive.inputs());
      }
    }
    // try to parse input as a linker script
    else if (doContinue && getScriptReader()->isMyFormat(**input, doContinue)) {
      ScriptFile script(ScriptFile::LDScript, **input,
                        m_pBuilder->getInputBuilder());
      if (getScriptReader()->readScript(m_Config, script)) {
        (*input)->setType(Input::Script);
        script.activate(*m_pModule);
        if (script.inputs().size() > 0) {
          m_pModule->getInputTree().merge<InputTree::Inclusive>(input,
            script.inputs());
        }
      }
    }
    else {
      if (m_Config.options().warnMismatch())
        warning(diag::warn_unrecognized_input_file) << (*input)->path()
          << m_Config.targets().triple().str();
    }
  } // end of for
}

bool ObjectLinker::linkable() const
{
  // check we have input and output files
  if (m_pModule->getInputTree().empty()) {
    error(diag::err_no_inputs);
    return false;
  }

  // can not mix -static with shared objects
  Module::const_lib_iterator lib, libEnd = m_pModule->lib_end();
  for (lib = m_pModule->lib_begin(); lib != libEnd; ++lib) {
    if((*lib)->attribute()->isStatic()) {
      error(diag::err_mixed_shared_static_objects)
                                      << (*lib)->name() << (*lib)->path();
      return false;
    }
  }

  // --nmagic and --omagic options lead to static executable program.
  // These options turn off page alignment of sections. Because the
  // sections are not aligned to pages, these sections can not contain any
  // exported functions. Also, because the two options disable linking
  // against shared libraries, the output absolutely does not call outside
  // functions.
  if (m_Config.options().nmagic() && !m_Config.isCodeStatic()) {
    error(diag::err_nmagic_not_static);
    return false;
  }
  if (m_Config.options().omagic() && !m_Config.isCodeStatic()) {
    error(diag::err_omagic_not_static);
    return false;
  }

  return true;
}

void ObjectLinker::dataStrippingOpt()
{
  // Garbege collection
  if (m_Config.options().GCSections()) {
    GarbageCollection GC(m_Config, m_LDBackend, *m_pModule);
    GC.run();
  }

  // Identical code folding
  if (m_Config.options().getICFMode() != GeneralOptions::ICF_None) {
    IdenticalCodeFolding icf(m_Config, m_LDBackend, *m_pModule);
    icf.foldIdenticalCode();
  }
  return;
}

/// readRelocations - read all relocation entries
///
/// All symbols should be read and resolved before this function.
bool ObjectLinker::readRelocations()
{
  // Bitcode is read by the other path. This function reads relocation sections
  // in object files.
  mcld::InputTree::bfs_iterator input, inEnd = m_pModule->getInputTree().bfs_end();
  for (input=m_pModule->getInputTree().bfs_begin(); input!=inEnd; ++input) {
    if ((*input)->type() == Input::Object && (*input)->hasMemArea()) {
      if (!getObjectReader()->readRelocations(**input))
        return false;
    }
    // ignore the other kinds of files.
  }
  return true;
}

/// mergeSections - put allinput sections into output sections
bool ObjectLinker::mergeSections()
{
  ObjectBuilder builder(*m_pModule);
  Module::obj_iterator obj, objEnd = m_pModule->obj_end();
  for (obj = m_pModule->obj_begin(); obj != objEnd; ++obj) {
    LDContext::sect_iterator sect, sectEnd = (*obj)->context()->sectEnd();
    for (sect = (*obj)->context()->sectBegin(); sect != sectEnd; ++sect) {
      switch ((*sect)->kind()) {
        // Some *INPUT sections should not be merged.
        case LDFileFormat::Folded:
        case LDFileFormat::Ignore:
        case LDFileFormat::Null:
        case LDFileFormat::NamePool:
        case LDFileFormat::Group:
        case LDFileFormat::StackNote:
          // skip
          continue;
        case LDFileFormat::Relocation: {
          if (!(*sect)->hasRelocData())
            continue; // skip

          if ((*sect)->getLink()->kind() == LDFileFormat::Ignore ||
              (*sect)->getLink()->kind() == LDFileFormat::Folded)
            (*sect)->setKind(LDFileFormat::Ignore);
          break;
        }
        case LDFileFormat::Target:
          if (!m_LDBackend.mergeSection(*m_pModule, **obj, **sect)) {
            error(diag::err_cannot_merge_section) << (*sect)->name()
                                                  << (*obj)->name();
            return false;
          }
          break;
        case LDFileFormat::EhFrame: {
          if (!(*sect)->hasEhFrame())
            continue; // skip

          LDSection* out_sect = NULL;
          if (NULL != (out_sect = builder.MergeSection(**obj, **sect))) {
            if (!m_LDBackend.updateSectionFlags(*out_sect, **sect)) {
              error(diag::err_cannot_merge_section) << (*sect)->name()
                                                    << (*obj)->name();
              return false;
            }
          }
          break;
        }
        default: {
          if (!(*sect)->hasSectionData())
            continue; // skip

          LDSection* out_sect = NULL;
          if (NULL != (out_sect = builder.MergeSection(**obj, **sect))) {
            if (!m_LDBackend.updateSectionFlags(*out_sect, **sect)) {
              error(diag::err_cannot_merge_section) << (*sect)->name()
                                                    << (*obj)->name();
              return false;
            }
          }
          break;
        }
      } // end of switch
    } // for each section
  } // for each obj

  RpnEvaluator evaluator(*m_pModule, m_LDBackend);
  SectionMap::iterator out, outBegin, outEnd;
  outBegin = m_pModule->getScript().sectionMap().begin();
  outEnd = m_pModule->getScript().sectionMap().end();
  for (out = outBegin; out != outEnd; ++out) {
    uint64_t out_align = 0x0, in_align = 0x0;
    LDSection* out_sect = (*out)->getSection();
    SectionMap::Output::iterator in, inBegin, inEnd;
    inBegin = (*out)->begin();
    inEnd = (*out)->end();

    // force input alignment from ldscript if any
    if ((*out)->prolog().hasSubAlign()) {
      evaluator.eval((*out)->prolog().subAlign(), in_align);
    }

    for (in = inBegin; in != inEnd; ++in) {
      LDSection* in_sect = (*in)->getSection();
      if ((*out)->prolog().hasSubAlign())
        in_sect->setAlign(in_align);

      if (builder.MoveSectionData(*in_sect->getSectionData(),
                                  *out_sect->getSectionData())) {
        builder.UpdateSectionAlign(*out_sect, *in_sect);
        m_LDBackend.updateSectionFlags(*out_sect, *in_sect);
      }
    } // for each input section description

    // force output alignment from ldscript if any
    if ((*out)->prolog().hasAlign()) {
      evaluator.eval((*out)->prolog().align(), out_align);
      out_sect->setAlign(out_align);
    }

    if ((*out)->hasContent()) {
      LDSection* target = m_pModule->getSection((*out)->name());
      assert(target != NULL && target->hasSectionData());
      if (builder.MoveSectionData(*out_sect->getSectionData(),
                                  *target->getSectionData())) {
        builder.UpdateSectionAlign(*target, *out_sect);
        m_LDBackend.updateSectionFlags(*target, *out_sect);
      }
    }
  } // for each output section description

  return true;
}

void ObjectLinker::addSymbolToOutput(ResolveInfo& pInfo, Module& pModule)
{
  // section symbols will be defined by linker later, we should not add section
  // symbols to output here
  if (ResolveInfo::Section == pInfo.type() || NULL == pInfo.outSymbol())
    return;

  // if the symbols defined in the Ignore sections (e.g. discared by GC), then
  // not to put them to output
  if (pInfo.outSymbol()->hasFragRef() && LDFileFormat::Ignore ==
        pInfo.outSymbol()->fragRef()->frag()->getParent()->getSection().kind())
    return;

  if (pInfo.shouldForceLocal(m_Config))
    pModule.getSymbolTable().forceLocal(*pInfo.outSymbol());
  else
    pModule.getSymbolTable().add(*pInfo.outSymbol());
}

void ObjectLinker::addSymbolsToOutput(Module& pModule)
{
  // Traverse all the free ResolveInfo and add the output symobols to output
  NamePool::freeinfo_iterator free_it,
                              free_end = pModule.getNamePool().freeinfo_end();
  for (free_it = pModule.getNamePool().freeinfo_begin(); free_it != free_end;
                                                                      ++free_it)
    addSymbolToOutput(**free_it, pModule);


  // Traverse all the resolveInfo and add the output symbol to output
  NamePool::syminfo_iterator info_it,
                             info_end = pModule.getNamePool().syminfo_end();
  for (info_it = pModule.getNamePool().syminfo_begin(); info_it != info_end;
                                                                      ++info_it)
    addSymbolToOutput(*info_it.getEntry(), pModule);
}


/// addStandardSymbols - shared object and executable files need some
/// standard symbols
///   @return if there are some input symbols with the same name to the
///   standard symbols, return false
bool ObjectLinker::addStandardSymbols()
{
  // create and add section symbols for each output section
  Module::iterator iter, iterEnd = m_pModule->end();
  for (iter = m_pModule->begin(); iter != iterEnd; ++iter) {
    m_pModule->getSectionSymbolSet().add(**iter, m_pModule->getNamePool());
  }

  return m_LDBackend.initStandardSymbols(*m_pBuilder, *m_pModule);
}

/// addTargetSymbols - some targets, such as MIPS and ARM, need some
/// target-dependent symbols
///   @return if there are some input symbols with the same name to the
///   target symbols, return false
bool ObjectLinker::addTargetSymbols()
{
  m_LDBackend.initTargetSymbols(*m_pBuilder, *m_pModule);
  return true;
}

/// addScriptSymbols - define symbols from the command line option or linker
/// scripts.
bool ObjectLinker::addScriptSymbols()
{
  LinkerScript& script = m_pModule->getScript();
  LinkerScript::Assignments::iterator it, ie = script.assignments().end();
  // go through the entire symbol assignments
  for (it = script.assignments().begin(); it != ie; ++it) {
    LDSymbol* symbol = NULL;
    assert((*it).second.symbol().type() == Operand::SYMBOL);
    const llvm::StringRef symName =  (*it).second.symbol().name();
    ResolveInfo::Type       type = ResolveInfo::NoType;
    ResolveInfo::Visibility vis  = ResolveInfo::Default;
    size_t size = 0;
    ResolveInfo* old_info = m_pModule->getNamePool().findInfo(symName);
    // if the symbol does not exist, we can set type to NOTYPE
    // else we retain its type, same goes for size - 0 or retain old value
    // and visibility - Default or retain
    if (old_info != NULL) {
      type = static_cast<ResolveInfo::Type>(old_info->type());
      vis = old_info->visibility();
      size = old_info->size();
    }

    // Add symbol and refine the visibility if needed
    // FIXME: bfd linker would change the binding instead, but currently
    //        ABS is also a kind of Binding in ResolveInfo.
    switch ((*it).second.type()) {
    case Assignment::HIDDEN:
      vis = ResolveInfo::Hidden;
      // Fall through
    case Assignment::DEFAULT:
      symbol =
        m_pBuilder->AddSymbol<IRBuilder::Force,
                              IRBuilder::Unresolve>(symName,
                                                    type,
                                                    ResolveInfo::Define,
                                                    ResolveInfo::Absolute,
                                                    size,
                                                    0x0,
                                                    FragmentRef::Null(),
                                                    vis);
      break;
    case Assignment::PROVIDE_HIDDEN:
      vis = ResolveInfo::Hidden;
      // Fall through
    case Assignment::PROVIDE:
      symbol =
        m_pBuilder->AddSymbol<IRBuilder::AsReferred,
                              IRBuilder::Unresolve>(symName,
                                                    type,
                                                    ResolveInfo::Define,
                                                    ResolveInfo::Absolute,
                                                    size,
                                                    0x0,
                                                    FragmentRef::Null(),
                                                    vis);
      break;
    }
    // Set symbol of this assignment.
    (*it).first = symbol;
  }
  return true;
}

bool ObjectLinker::scanRelocations()
{
  // apply all relocations of all inputs
  Module::obj_iterator input, inEnd = m_pModule->obj_end();
  for (input = m_pModule->obj_begin(); input != inEnd; ++input) {
    m_LDBackend.getRelocator()->initializeScan(**input);
    LDContext::sect_iterator rs, rsEnd = (*input)->context()->relocSectEnd();
    for (rs = (*input)->context()->relocSectBegin(); rs != rsEnd; ++rs) {
      // bypass the reloc section if
      // 1. its section kind is changed to Ignore. (The target section is a
      // discarded group section.)
      // 2. it has no reloc data. (All symbols in the input relocs are in the
      // discarded group sections)
      if (LDFileFormat::Ignore == (*rs)->kind() || !(*rs)->hasRelocData())
        continue;
      RelocData::iterator reloc, rEnd = (*rs)->getRelocData()->end();
      for (reloc = (*rs)->getRelocData()->begin(); reloc != rEnd; ++reloc) {
        Relocation* relocation = llvm::cast<Relocation>(reloc);

        // bypass the reloc if the symbol is in the discarded input section
        ResolveInfo* info = relocation->symInfo();
        if (!info->outSymbol()->hasFragRef() &&
            ResolveInfo::Section == info->type() &&
            ResolveInfo::Undefined == info->desc())
           continue;

        // scan relocation
        if (LinkerConfig::Object != m_Config.codeGenType())
          m_LDBackend.getRelocator()->scanRelocation(
                                    *relocation, *m_pBuilder, *m_pModule, **rs, **input);
        else
          m_LDBackend.getRelocator()->partialScanRelocation(
                                                 *relocation, *m_pModule, **rs);
      } // for all relocations
    } // for all relocation section
    m_LDBackend.getRelocator()->finalizeScan(**input);
  } // for all inputs
  return true;
}

/// initStubs - initialize stub-related stuff.
bool ObjectLinker::initStubs()
{
  // initialize BranchIslandFactory
  m_LDBackend.initBRIslandFactory();

  // initialize StubFactory
  m_LDBackend.initStubFactory();

  // initialize target stubs
  m_LDBackend.initTargetStubs();
  return true;
}

/// allocateCommonSymobols - allocate fragments for common symbols to the
/// corresponding sections
bool ObjectLinker::allocateCommonSymbols()
{
  if (LinkerConfig::Object != m_Config.codeGenType() ||
      m_Config.options().isDefineCommon())
    return m_LDBackend.allocateCommonSymbols(*m_pModule);
  return true;
}

/// prelayout - help backend to do some modification before layout
bool ObjectLinker::prelayout()
{
  // finalize the section symbols, set their fragment reference and push them
  // into output symbol table
  Module::iterator sect, sEnd = m_pModule->end();
  for (sect = m_pModule->begin(); sect != sEnd; ++sect) {
    m_pModule->getSectionSymbolSet().finalize(**sect,
        m_pModule->getSymbolTable(),
        m_Config.codeGenType() == LinkerConfig::Object);
  }

  m_LDBackend.preLayout(*m_pModule, *m_pBuilder);

  /// check program interpreter - computer the name size of the runtime dyld
  if (!m_Config.isCodeStatic() &&
      (LinkerConfig::Exec == m_Config.codeGenType() ||
       m_Config.options().isPIE() ||
       m_Config.options().hasDyld()))
    m_LDBackend.sizeInterp();

  /// measure NamePools - compute the size of name pool sections
  /// In ELF, will compute  the size of.symtab, .strtab, .dynsym, .dynstr,
  /// .hash and .shstrtab sections.
  ///
  /// dump all symbols and strings from ObjectLinker and build the format-dependent
  /// hash table.
  /// @note sizeNamePools replies on LinkerConfig::CodePosition. Must determine
  /// code position model before calling GNULDBackend::sizeNamePools()
  m_LDBackend.sizeNamePools(*m_pModule);

  // Do this after backend prelayout since it may add eh_frame entries.
  LDSection* eh_frame_sect = m_pModule->getSection(".eh_frame");
  if (eh_frame_sect && eh_frame_sect->hasEhFrame())
    eh_frame_sect->getEhFrame()->computeOffsetSize();
  m_LDBackend.createAndSizeEhFrameHdr(*m_pModule);

  return true;
}

/// layout - linearly layout all output sections and reserve some space
/// for GOT/PLT
///   Because we do not support instruction relaxing in this early version,
///   if there is a branch can not jump to its target, we return false
///   directly
bool ObjectLinker::layout()
{
  m_LDBackend.layout(*m_pModule);
  return true;
}

/// prelayout - help backend to do some modification after layout
bool ObjectLinker::postlayout()
{
  m_LDBackend.postLayout(*m_pModule, *m_pBuilder);
  return true;
}

/// finalizeSymbolValue - finalize the resolved symbol value.
///   Before relocate(), after layout(), ObjectLinker should correct value of all
///   symbol.
bool ObjectLinker::finalizeSymbolValue()
{
  Module::sym_iterator symbol, symEnd = m_pModule->sym_end();
  for (symbol = m_pModule->sym_begin(); symbol != symEnd; ++symbol) {

    if ((*symbol)->resolveInfo()->isAbsolute() ||
        (*symbol)->resolveInfo()->type() == ResolveInfo::File) {
      // absolute symbols should just use its value directly (i.e., the result
      // of symbol resolution)
      continue;
    }

    if ((*symbol)->resolveInfo()->type() == ResolveInfo::ThreadLocal) {
      m_LDBackend.finalizeTLSSymbol(**symbol);
      continue;
    }

    if ((*symbol)->hasFragRef()) {
      // set the virtual address of the symbol. If the output file is
      // relocatable object file, the section's virtual address becomes zero.
      // And the symbol's value become section relative offset.
      uint64_t value = (*symbol)->fragRef()->getOutputOffset();
      assert(NULL != (*symbol)->fragRef()->frag());
      uint64_t addr =
        (*symbol)->fragRef()->frag()->getParent()->getSection().addr();
      (*symbol)->setValue(value + addr);
      continue;
    }
  }

  RpnEvaluator evaluator(*m_pModule, m_LDBackend);
  bool finalized = m_LDBackend.finalizeSymbols();
  bool scriptSymsFinalized = true;
  LinkerScript& script = m_pModule->getScript();
  LinkerScript::Assignments::iterator assign, assignEnd;
  assignEnd = script.assignments().end();
  for (assign = script.assignments().begin(); assign != assignEnd; ++assign) {
    LDSymbol* symbol = (*assign).first;
    Assignment& assignment = (*assign).second;

    if (symbol == NULL)
      continue;

    scriptSymsFinalized &= assignment.assign(evaluator);
    if (!scriptSymsFinalized)
      break;

    symbol->setValue(assignment.symbol().value());
  } // for each script symbol assignment

  bool assertionsPassed = true;
  LinkerScript::Assertions::iterator assert, assertEnd;
  assertEnd = script.assertions().end();
  for (assert = script.assertions().begin(); assert != assertEnd; ++assert) {
    uint64_t res = 0x0;
    evaluator.eval((*assert).getRpnExpr(), res);
    if (res == 0x0)
      fatal(diag::err_assert_failed) << (*assert).message();
  } // for each assertion in ldscript

  return finalized && scriptSymsFinalized && assertionsPassed;
}

/// relocate - applying relocation entries and create relocation
/// section in the output files
/// Create relocation section, asking TargetLDBackend to
/// read the relocation information into RelocationEntry
/// and push_back into the relocation section
bool ObjectLinker::relocation()
{
  // when producing relocatables, no need to apply relocation
  if (LinkerConfig::Object == m_Config.codeGenType())
    return true;

  // apply all relocations of all inputs
  Module::obj_iterator input, inEnd = m_pModule->obj_end();
  for (input = m_pModule->obj_begin(); input != inEnd; ++input) {
    m_LDBackend.getRelocator()->initializeApply(**input);
    LDContext::sect_iterator rs, rsEnd = (*input)->context()->relocSectEnd();
    for (rs = (*input)->context()->relocSectBegin(); rs != rsEnd; ++rs) {
      // bypass the reloc section if
      // 1. its section kind is changed to Ignore. (The target section is a
      // discarded group section.)
      // 2. it has no reloc data. (All symbols in the input relocs are in the
      // discarded group sections)
      if (LDFileFormat::Ignore == (*rs)->kind() || !(*rs)->hasRelocData())
        continue;
      RelocData::iterator reloc, rEnd = (*rs)->getRelocData()->end();
      for (reloc = (*rs)->getRelocData()->begin(); reloc != rEnd; ++reloc) {
        Relocation* relocation = llvm::cast<Relocation>(reloc);

        // bypass the reloc if the symbol is in the discarded input section
        ResolveInfo* info = relocation->symInfo();
        if (!info->outSymbol()->hasFragRef() &&
            ResolveInfo::Section == info->type() &&
            ResolveInfo::Undefined == info->desc())
          continue;

        relocation->apply(*m_LDBackend.getRelocator());
      } // for all relocations
    } // for all relocation section
    m_LDBackend.getRelocator()->finalizeApply(**input);
  } // for all inputs

  // apply relocations created by relaxation
  BranchIslandFactory* br_factory = m_LDBackend.getBRIslandFactory();
  BranchIslandFactory::iterator facIter, facEnd = br_factory->end();
  for (facIter = br_factory->begin(); facIter != facEnd; ++facIter) {
    BranchIsland& island = *facIter;
    BranchIsland::reloc_iterator iter, iterEnd = island.reloc_end();
    for (iter = island.reloc_begin(); iter != iterEnd; ++iter)
      (*iter)->apply(*m_LDBackend.getRelocator());
  }
  return true;
}

/// emitOutput - emit the output file.
bool ObjectLinker::emitOutput(FileOutputBuffer& pOutput)
{
  return std::error_code() == getWriter()->writeObject(*m_pModule, pOutput);
}


/// postProcessing - do modification after all processes
bool ObjectLinker::postProcessing(FileOutputBuffer& pOutput)
{
  if (LinkerConfig::Object != m_Config.codeGenType())
    normalSyncRelocationResult(pOutput);
  else
    partialSyncRelocationResult(pOutput);

  // emit .eh_frame_hdr
  // eh_frame_hdr should be emitted after syncRelocation, because eh_frame_hdr
  // needs FDE PC value, which will be corrected at syncRelocation
  m_LDBackend.postProcessing(pOutput);
  return true;
}

void ObjectLinker::normalSyncRelocationResult(FileOutputBuffer& pOutput)
{
  uint8_t* data = pOutput.getBufferStart();

  // sync all relocations of all inputs
  Module::obj_iterator input, inEnd = m_pModule->obj_end();
  for (input = m_pModule->obj_begin(); input != inEnd; ++input) {
    LDContext::sect_iterator rs, rsEnd = (*input)->context()->relocSectEnd();
    for (rs = (*input)->context()->relocSectBegin(); rs != rsEnd; ++rs) {
      // bypass the reloc section if
      // 1. its section kind is changed to Ignore. (The target section is a
      // discarded group section.)
      // 2. it has no reloc data. (All symbols in the input relocs are in the
      // discarded group sections)
      if (LDFileFormat::Ignore == (*rs)->kind() || !(*rs)->hasRelocData())
        continue;
      RelocData::iterator reloc, rEnd = (*rs)->getRelocData()->end();
      for (reloc = (*rs)->getRelocData()->begin(); reloc != rEnd; ++reloc) {
        Relocation* relocation = llvm::cast<Relocation>(reloc);

        // bypass the reloc if the symbol is in the discarded input section
        ResolveInfo* info = relocation->symInfo();
        if (!info->outSymbol()->hasFragRef() &&
            ResolveInfo::Section == info->type() &&
            ResolveInfo::Undefined == info->desc())
          continue;

        // bypass the relocation with NONE type. This is to avoid overwrite the
        // target result by NONE type relocation if there is a place which has
        // two relocations to apply to, and one of it is NONE type. The result
        // we want is the value of the other relocation result. For example,
        // in .exidx, there are usually an R_ARM_NONE and R_ARM_PREL31 apply to
        // the same place
        if (0x0 == relocation->type())
          continue;
        writeRelocationResult(*relocation, data);
      } // for all relocations
    } // for all relocation section
  } // for all inputs

  // sync relocations created by relaxation
  BranchIslandFactory* br_factory = m_LDBackend.getBRIslandFactory();
  BranchIslandFactory::iterator facIter, facEnd = br_factory->end();
  for (facIter = br_factory->begin(); facIter != facEnd; ++facIter) {
    BranchIsland& island = *facIter;
    BranchIsland::reloc_iterator iter, iterEnd = island.reloc_end();
    for (iter = island.reloc_begin(); iter != iterEnd; ++iter) {
      Relocation* reloc = *iter;
      writeRelocationResult(*reloc, data);
    }
  }
}

void ObjectLinker::partialSyncRelocationResult(FileOutputBuffer& pOutput)
{
  uint8_t* data = pOutput.getBufferStart();

  // traverse outputs' LDSection to get RelocData
  Module::iterator sectIter, sectEnd = m_pModule->end();
  for (sectIter = m_pModule->begin(); sectIter != sectEnd; ++sectIter) {
    if (LDFileFormat::Relocation != (*sectIter)->kind())
      continue;

    RelocData* reloc_data = (*sectIter)->getRelocData();
    RelocData::iterator relocIter, relocEnd = reloc_data->end();
    for (relocIter = reloc_data->begin(); relocIter != relocEnd; ++relocIter) {
      Relocation* reloc = llvm::cast<Relocation>(relocIter);

      // bypass the relocation with NONE type. This is to avoid overwrite the
      // target result by NONE type relocation if there is a place which has
      // two relocations to apply to, and one of it is NONE type. The result
      // we want is the value of the other relocation result. For example,
      // in .exidx, there are usually an R_ARM_NONE and R_ARM_PREL31 apply to
      // the same place
      if (0x0 == reloc->type())
        continue;
      writeRelocationResult(*reloc, data);
    }
  }
}

void ObjectLinker::writeRelocationResult(Relocation& pReloc, uint8_t* pOutput)
{
  // get output file offset
  size_t out_offset =
                 pReloc.targetRef().frag()->getParent()->getSection().offset() +
                 pReloc.targetRef().getOutputOffset();

  uint8_t* target_addr = pOutput + out_offset;
  // byte swapping if target and host has different endian, and then write back
  if(llvm::sys::IsLittleEndianHost != m_Config.targets().isLittleEndian()) {
     uint64_t tmp_data = 0;

     switch(pReloc.size(*m_LDBackend.getRelocator())) {
       case 8u:
         std::memcpy(target_addr, &pReloc.target(), 1);
         break;

       case 16u:
         tmp_data = mcld::bswap16(pReloc.target());
         std::memcpy(target_addr, &tmp_data, 2);
         break;

       case 32u:
         tmp_data = mcld::bswap32(pReloc.target());
         std::memcpy(target_addr, &tmp_data, 4);
         break;

       case 64u:
         tmp_data = mcld::bswap64(pReloc.target());
         std::memcpy(target_addr, &tmp_data, 8);
         break;

       default:
         break;
    }
  }
  else
    std::memcpy(target_addr, &pReloc.target(),
                                      pReloc.size(*m_LDBackend.getRelocator())/8);
}

