bool ARMGNULDBackend::readSection(Input& pInput,
                                  MCLinker& pLinker,
                                  LDSection& pInputSectHdr)
{
  LDSection& out_sect = pLinker.getOrCreateOutputSectHdr(pInputSectHdr.name(),
                                                         pInputSectHdr.kind(),
                                                         pInputSectHdr.type(),
                                                         pInputSectHdr.flag());
  // FIXME: (Luba)
  // Handle ARM attributes in the right way.
  // In current milestone, MCLinker goes through the shortcut.
  // It reads input's ARM attributes and copies the first ARM attributes
  // into the output file. The correct way is merge these sections, not
  // just copy.
  if ((0 == out_sect.name().compare(".ARM.attributes")) &&
      (0 != out_sect.size()))
    return true;

  MemoryRegion* region = pInput.memArea()->request(pInputSectHdr.offset(),
                                                   pInputSectHdr.size());

  llvm::MCSectionData& sect_data = pLinker.getOrCreateSectData(pInputSectHdr);

  new MCRegionFragment(*region, &sect_data);

  out_sect.setSize(out_sect.size() + pInputSectHdr.size());
  return true;
}
void ARMGNULDBackend::initTargetSections(MCLinker& pLinker)
{
 // FIXME: Currently we set exidx and extab to "Exception" and directly emit
 // them from input
  m_pEXIDX        = &pLinker.getOrCreateOutputSectHdr(".ARM.exidx",
                                                      LDFileFormat::Exception,
                                                      llvm::ELF::SHT_ARM_EXIDX,
                                                      llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_LINK_ORDER,
                                                      bitclass() / 8);
  m_pEXTAB        = &pLinker.getOrCreateOutputSectHdr(".ARM.extab",
                                                      LDFileFormat::Exception,
                                                      llvm::ELF::SHT_PROGBITS,
                                                      llvm::ELF::SHF_ALLOC,
                                                      0x1);
  m_pAttributes   = &pLinker.getOrCreateOutputSectHdr(".ARM.attributes",
                                                      LDFileFormat::Target,
                                                      llvm::ELF::SHT_ARM_ATTRIBUTES,
                                                      0x0,
                                                      0x1);
}
void ELFFileFormat::initObjectFormat(MCLinker& pLinker)
{
  f_pTextSection     = &pLinker.getOrCreateOutputSectHdr(".text",
                                              LDFileFormat::Regular,
                                              llvm::ELF::SHT_PROGBITS,
                                              llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_EXECINSTR,
                                              0x1);
  f_pNULLSection     = &pLinker.getOrCreateOutputSectHdr("",
                                              LDFileFormat::Null,
                                              llvm::ELF::SHT_NULL,
                                              0x0);
  f_pReadOnlySection = &pLinker.getOrCreateOutputSectHdr(".rodata",
                                              LDFileFormat::Regular,
                                              llvm::ELF::SHT_PROGBITS,
                                              llvm::ELF::SHF_ALLOC,
                                              0x1);

  f_pBSSSection      = &pLinker.getOrCreateOutputSectHdr(".bss",
                                              LDFileFormat::BSS,
                                              llvm::ELF::SHT_NOBITS,
                                              llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE,
                                              0x1);
  f_pComment         = &pLinker.getOrCreateOutputSectHdr(".comment",
                                              LDFileFormat::MetaData,
                                              llvm::ELF::SHT_PROGBITS,
                                              0x0,
                                              0x1);
  f_pDataSection     = &pLinker.getOrCreateOutputSectHdr(".data",
                                              LDFileFormat::Regular,
                                              llvm::ELF::SHT_PROGBITS,
                                              llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE,
                                              0x1);
  f_pData1           = &pLinker.getOrCreateOutputSectHdr(".data1",
                                              LDFileFormat::Regular,
                                              llvm::ELF::SHT_PROGBITS,
                                              llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE,
                                              0x1);
  f_pDebug           = &pLinker.getOrCreateOutputSectHdr(".debug",
                                              LDFileFormat::Debug,
                                              llvm::ELF::SHT_PROGBITS,
                                              0x0,
                                              0x1);
  f_pInit            = &pLinker.getOrCreateOutputSectHdr(".init",
                                              LDFileFormat::Regular,
                                              llvm::ELF::SHT_PROGBITS,
                                              llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_EXECINSTR,
                                              0x1);
  f_pInitArray       = &pLinker.getOrCreateOutputSectHdr(".init_array",
                                              LDFileFormat::Regular,
                                              llvm::ELF::SHT_INIT_ARRAY,
                                              llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE,
                                              0x1);
  f_pFini            = &pLinker.getOrCreateOutputSectHdr(".fini",
                                              LDFileFormat::Regular,
                                              llvm::ELF::SHT_PROGBITS,
                                              llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_EXECINSTR,
                                              0x1);
  f_pFiniArray       = &pLinker.getOrCreateOutputSectHdr(".fini_array",
                                              LDFileFormat::Regular,
                                              llvm::ELF::SHT_FINI_ARRAY,
                                              llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE,
                                              0x1);
  f_pLine            = &pLinker.getOrCreateOutputSectHdr(".line",
                                              LDFileFormat::Debug,
                                              llvm::ELF::SHT_PROGBITS,
                                              0x0,
                                              0x1);
  f_pPreInitArray    = &pLinker.getOrCreateOutputSectHdr(".preinit_array",
                                              LDFileFormat::Regular,
                                              llvm::ELF::SHT_PREINIT_ARRAY,
                                              llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE,
                                              0x1);
  // the definition of SHF_XXX attributes of rodata in Linux Standard Base
  // conflicts with System V standard. We follow System V standard.
  f_pROData1         = &pLinker.getOrCreateOutputSectHdr(".rodata1",
                                              LDFileFormat::Regular,
                                              llvm::ELF::SHT_PROGBITS,
                                              llvm::ELF::SHF_ALLOC,
                                              0x1);
  f_pShStrTab        = &pLinker.getOrCreateOutputSectHdr(".shstrtab",
                                              LDFileFormat::NamePool,
                                              llvm::ELF::SHT_STRTAB,
                                              0x0,
                                              0x1);
  // In ELF Spec Book I, p1-16. If symbol table and string table are in 
  // loadable segments, set the attribute to SHF_ALLOC bit. But in the
  // real world, this bit always turn off.
  f_pSymTab       = &pLinker.getOrCreateOutputSectHdr(".symtab",
                                              LDFileFormat::NamePool,
                                              llvm::ELF::SHT_SYMTAB,
                                              0x0,
                                              f_Backend.bitclass() / 8);
  f_pStrTab       = &pLinker.getOrCreateOutputSectHdr(".strtab",
                                              LDFileFormat::NamePool,
                                              llvm::ELF::SHT_STRTAB,
                                              0x0,
                                              0x1);
  f_pTBSS         = &pLinker.getOrCreateOutputSectHdr(".tbss",
                                              LDFileFormat::BSS,
                                              llvm::ELF::SHT_NOBITS,
                                              llvm::ELF::SHF_ALLOC |
                                              llvm::ELF::SHF_WRITE |
                                              llvm::ELF::SHF_TLS,
                                              0x1);
  f_pTData        = &pLinker.getOrCreateOutputSectHdr(".tdata",
                                              LDFileFormat::Regular,
                                              llvm::ELF::SHT_PROGBITS,
                                              llvm::ELF::SHF_ALLOC |
                                              llvm::ELF::SHF_WRITE |
                                              llvm::ELF::SHF_TLS,
                                              0x1);

  /// @ref 10.3.1.2, ISO/IEC 23360, Part 1:2010(E), p. 24.
  f_pCtors          = &pLinker.getOrCreateOutputSectHdr(".ctor",
                                              LDFileFormat::Regular,
                                              llvm::ELF::SHT_PROGBITS,
                                              llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE,
                                              0x1);
  f_pDataRelRo      = &pLinker.getOrCreateOutputSectHdr(".data.rel.ro",
                                              LDFileFormat::Regular,
                                              llvm::ELF::SHT_PROGBITS,
                                              llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE,
                                              0x1);
  f_pDtors          = &pLinker.getOrCreateOutputSectHdr(".dtors",
                                              LDFileFormat::Regular,
                                              llvm::ELF::SHT_PROGBITS,
                                              llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE,
                                              0x1);
  f_pEhFrame        = &pLinker.getOrCreateOutputSectHdr(".eh_frame",
                                              LDFileFormat::EhFrame,
                                              llvm::ELF::SHT_PROGBITS,
                                              llvm::ELF::SHF_ALLOC,
                                              0x4);
  f_pGCCExceptTable = &pLinker.getOrCreateOutputSectHdr(".gcc_except_table",
                                              LDFileFormat::GCCExceptTable,
                                              llvm::ELF::SHT_PROGBITS,
                                              llvm::ELF::SHF_ALLOC,
                                              0x4);
  f_pGNUVersion     = &pLinker.getOrCreateOutputSectHdr(".gnu.version",
                                              LDFileFormat::Version,
                                              llvm::ELF::SHT_GNU_versym,
                                              llvm::ELF::SHF_ALLOC,
                                              0x1);
  f_pGNUVersionD    = &pLinker.getOrCreateOutputSectHdr(".gnu.version_d",
                                              LDFileFormat::Version,
                                              llvm::ELF::SHT_GNU_verdef,
                                              llvm::ELF::SHF_ALLOC,
                                              0x1);
  f_pGNUVersionR    = &pLinker.getOrCreateOutputSectHdr(".gnu.version_r",
                                              LDFileFormat::Version,
                                              llvm::ELF::SHT_GNU_verneed,
                                              llvm::ELF::SHF_ALLOC,
                                              0x1);
  f_pJCR            = &pLinker.getOrCreateOutputSectHdr(".jcr",
                                              LDFileFormat::Regular,
                                              llvm::ELF::SHT_PROGBITS,
                                              llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE,
                                              0x1);
  f_pStab           = &pLinker.getOrCreateOutputSectHdr(".stab",
                                              LDFileFormat::Debug,
                                              llvm::ELF::SHT_PROGBITS,
                                              0x0,
                                              0x1);
  f_pStabStr        = &pLinker.getOrCreateOutputSectHdr(".stabstr",
                                              LDFileFormat::Debug,
                                              llvm::ELF::SHT_STRTAB,
                                              0x0,
                                              0x1);
}
/// allocateCommonSymbols - allocate common symbols in the corresponding
/// sections.
/// @refer Google gold linker: common.cc: 214
bool
ARMGNULDBackend::allocateCommonSymbols(const MCLDInfo& pInfo, MCLinker& pLinker) const
{
  SymbolCategory& symbol_list = pLinker.getOutputSymbols();

  if (symbol_list.emptyCommons() && symbol_list.emptyLocals())
    return true;

  // addralign := max value of all common symbols
  uint64_t addralign = 0x0;

  // Due to the visibility, some common symbols may be forcefully local.
  SymbolCategory::iterator com_sym, com_end = symbol_list.localEnd();
  for (com_sym = symbol_list.localBegin(); com_sym != com_end; ++com_sym) {
    if (ResolveInfo::Common == (*com_sym)->desc()) {
      if ((*com_sym)->value() > addralign)
        addralign = (*com_sym)->value();
    }
  }

  // global common symbols.
  com_end = symbol_list.commonEnd();
  for (com_sym = symbol_list.commonBegin(); com_sym != com_end; ++com_sym) {
    if ((*com_sym)->value() > addralign)
      addralign = (*com_sym)->value();
  }

  // FIXME: If the order of common symbols is defined, then sort common symbols
  // com_sym = symbol_list.commonBegin();
  // std::sort(com_sym, com_end, some kind of order);

  // get or create corresponding BSS LDSection
  LDSection* bss_sect_hdr = NULL;
  if (ResolveInfo::ThreadLocal == (*com_sym)->type()) {
    bss_sect_hdr = &pLinker.getOrCreateOutputSectHdr(
                                   ".tbss",
                                   LDFileFormat::BSS,
                                   llvm::ELF::SHT_NOBITS,
                                   llvm::ELF::SHF_WRITE | llvm::ELF::SHF_ALLOC);
  }
  else {
    bss_sect_hdr = &pLinker.getOrCreateOutputSectHdr(".bss",
                                   LDFileFormat::BSS,
                                   llvm::ELF::SHT_NOBITS,
                                   llvm::ELF::SHF_WRITE | llvm::ELF::SHF_ALLOC);
  }

  // get or create corresponding BSS MCSectionData
  assert(NULL != bss_sect_hdr);
  llvm::MCSectionData& bss_section = pLinker.getOrCreateSectData(*bss_sect_hdr);

  // allocate all common symbols
  uint64_t offset = bss_sect_hdr->size();

  // allocate all local common symbols
  com_end = symbol_list.localEnd();
  for (com_sym = symbol_list.localBegin(); com_sym != com_end; ++com_sym) {
    if (ResolveInfo::Common == (*com_sym)->desc()) {
      // We have to reset the description of the symbol here. When doing
      // incremental linking, the output relocatable object may have common
      // symbols. Therefore, we can not treat common symbols as normal symbols
      // when emitting the regular name pools. We must change the symbols'
      // description here.
      (*com_sym)->resolveInfo()->setDesc(ResolveInfo::Define);
      llvm::MCFragment* frag = new llvm::MCFillFragment(0x0, 1, (*com_sym)->size());
      (*com_sym)->setFragmentRef(new MCFragmentRef(*frag, 0));
      uint64_t size = pLinker.getLayout().appendFragment(*frag,
                                                         bss_section,
                                                         (*com_sym)->value());
      offset += size;
    }
  }

  // allocate all global common symbols
  com_end = symbol_list.commonEnd();
  for (com_sym = symbol_list.commonBegin(); com_sym != com_end; ++com_sym) {
    // We have to reset the description of the symbol here. When doing
    // incremental linking, the output relocatable object may have common
    // symbols. Therefore, we can not treat common symbols as normal symbols
    // when emitting the regular name pools. We must change the symbols'
    // description here.
    (*com_sym)->resolveInfo()->setDesc(ResolveInfo::Define);
    llvm::MCFragment* frag = new llvm::MCFillFragment(0x0, 1, (*com_sym)->size());
    (*com_sym)->setFragmentRef(new MCFragmentRef(*frag, 0));
    uint64_t size = pLinker.getLayout().appendFragment(*frag,
                                                       bss_section,
                                                       (*com_sym)->value());
    offset += size;
  }

  bss_sect_hdr->setSize(offset);
  symbol_list.changeCommonsToGlobal();
  return true;
}