ELFReader.cpp revision 6f75755c9204b1d8817ae5a65a2f7e5af0ec3f70
15460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//===- ELFReader.cpp ------------------------------------------------------===//
25460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//
35460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//                     The MCLinker Project
45460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//
55460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// This file is distributed under the University of Illinois Open Source
65460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// License. See LICENSE.TXT for details.
75460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//
85460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//===----------------------------------------------------------------------===//
95460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <mcld/LD/ELFReader.h>
1022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
1122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <mcld/IRBuilder.h>
1222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <mcld/Fragment/FillFragment.h>
1322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <mcld/LD/EhFrame.h>
1422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <mcld/LD/SectionData.h>
155460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <mcld/Target/GNULDBackend.h>
16affc150dc44fab1911775a49636d0ce85333b634Zonr Chang#include <mcld/Support/MemoryRegion.h>
17affc150dc44fab1911775a49636d0ce85333b634Zonr Chang#include <mcld/Support/MsgHandling.h>
1822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <mcld/Object/ObjectBuilder.h>
1922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <cstring>
215460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <llvm/ADT/StringRef.h>
2322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <llvm/ADT/Twine.h>
2422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <llvm/Support/ELF.h>
2522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <llvm/Support/Host.h>
2622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
276f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines#include <iostream>
285460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
296f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesusing namespace mcld;
305460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
3122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao//===----------------------------------------------------------------------===//
3222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao// ELFReader<32, true>
3322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao//===----------------------------------------------------------------------===//
3422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/// constructor
3522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei LiaoELFReader<32, true>::ELFReader(GNULDBackend& pBackend)
3622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  : ELFReaderIF(pBackend) {
3722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao}
3822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
3922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/// destructor
4022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei LiaoELFReader<32, true>::~ELFReader()
4122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao{
4222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao}
4322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
4422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/// isELF - is this a ELF file
4522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liaobool ELFReader<32, true>::isELF(void* pELFHeader) const
4622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao{
4722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  llvm::ELF::Elf32_Ehdr* hdr =
4822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                          reinterpret_cast<llvm::ELF::Elf32_Ehdr*>(pELFHeader);
4922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  if (0 == memcmp(llvm::ELF::ElfMagic, hdr, 4))
5022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    return true;
5122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  return false;
5222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao}
5322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
5422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/// readRegularSection - read a regular section and create fragments.
5522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liaobool
5622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei LiaoELFReader<32, true>::readRegularSection(Input& pInput, SectionData& pSD) const
5722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao{
5822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  uint32_t offset = pInput.fileOffset() + pSD.getSection().offset();
5922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  uint32_t size = pSD.getSection().size();
6022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
6122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  Fragment* frag = IRBuilder::CreateRegion(pInput, offset, size);
6222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  ObjectBuilder::AppendFragment(*frag, pSD);
6322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  return true;
6422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao}
6522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
6622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/// readSymbols - read ELF symbols and create LDSymbol
6722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liaobool ELFReader<32, true>::readSymbols(Input& pInput,
68d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao                                      IRBuilder& pBuilder,
6922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                                      const MemoryRegion& pRegion,
7022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                                      const char* pStrTab) const
7122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao{
7222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // get number of symbols
7322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  size_t entsize = pRegion.size()/sizeof(llvm::ELF::Elf32_Sym);
7422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  const llvm::ELF::Elf32_Sym* symtab =
7522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                 reinterpret_cast<const llvm::ELF::Elf32_Sym*>(pRegion.start());
7622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
7722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  uint32_t st_name  = 0x0;
7822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  uint32_t st_value = 0x0;
7922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  uint32_t st_size  = 0x0;
8022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  uint8_t  st_info  = 0x0;
8122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  uint8_t  st_other = 0x0;
8222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  uint16_t st_shndx = 0x0;
8322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
8422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // skip the first NULL symbol
8522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  pInput.context()->addSymbol(LDSymbol::Null());
8622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
8722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  for (size_t idx = 1; idx < entsize; ++idx) {
8822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    st_info  = symtab[idx].st_info;
8922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    st_other = symtab[idx].st_other;
9022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
9122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    if (llvm::sys::isLittleEndianHost()) {
9222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      st_name  = symtab[idx].st_name;
9322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      st_value = symtab[idx].st_value;
9422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      st_size  = symtab[idx].st_size;
9522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      st_shndx = symtab[idx].st_shndx;
9622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    }
9722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    else {
98d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao      st_name  = mcld::bswap32(symtab[idx].st_name);
99d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao      st_value = mcld::bswap32(symtab[idx].st_value);
100d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao      st_size  = mcld::bswap32(symtab[idx].st_size);
101d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao      st_shndx = mcld::bswap16(symtab[idx].st_shndx);
10222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    }
10322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
10422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    // If the section should not be included, set the st_shndx SHN_UNDEF
10522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    // - A section in interrelated groups are not included.
10622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    if (pInput.type() == Input::Object &&
10722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao        st_shndx < llvm::ELF::SHN_LORESERVE &&
10822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao        st_shndx != llvm::ELF::SHN_UNDEF) {
10922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      if (NULL == pInput.context()->getSection(st_shndx))
11022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao        st_shndx = llvm::ELF::SHN_UNDEF;
11122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    }
11222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
11322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    // get ld_type
11422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    ResolveInfo::Type ld_type = getSymType(st_info, st_shndx);
11522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
11622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    // get ld_desc
11722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    ResolveInfo::Desc ld_desc = getSymDesc(st_shndx, pInput);
11822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
11922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    // get ld_binding
12022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    ResolveInfo::Binding ld_binding = getSymBinding((st_info >> 4), st_shndx, st_other);
12122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
12222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    // get ld_value - ld_value must be section relative.
12322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    uint64_t ld_value = getSymValue(st_value, st_shndx, pInput);
12422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
12522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    // get ld_vis
12622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    ResolveInfo::Visibility ld_vis = getSymVisibility(st_other);
12722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
128d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    // get section
129d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    LDSection* section = NULL;
130d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    if (st_shndx < llvm::ELF::SHN_LORESERVE) // including ABS and COMMON
131d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao      section = pInput.context()->getSection(st_shndx);
132d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao
13322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    // get ld_name
134d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    std::string ld_name;
13522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    if (ResolveInfo::Section == ld_type) {
13622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      // Section symbol's st_name is the section index.
13722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      assert(NULL != section && "get a invalid section");
138d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao      ld_name = section->name();
13922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    }
14022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    else {
141d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao      ld_name = std::string(pStrTab + st_name);
14222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    }
14322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
144d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    pBuilder.AddSymbol(pInput,
145d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao                       ld_name,
146d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao                       ld_type,
147d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao                       ld_desc,
148d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao                       ld_binding,
149d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao                       st_size,
150d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao                       ld_value,
151d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao                       section, ld_vis);
15222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  } // end of for loop
15322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  return true;
15422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao}
15522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
15622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao//===----------------------------------------------------------------------===//
15722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao// ELFReader::read relocations - read ELF rela and rel, and create Relocation
15822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao//===----------------------------------------------------------------------===//
15922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/// ELFReader::readRela - read ELF rela and create Relocation
16022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liaobool ELFReader<32, true>::readRela(Input& pInput,
16122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                                   LDSection& pSection,
16222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                                   const MemoryRegion& pRegion) const
16322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao{
16422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // get the number of rela
16522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  size_t entsize = pRegion.size() / sizeof(llvm::ELF::Elf32_Rela);
16622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  const llvm::ELF::Elf32_Rela* relaTab =
16722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                reinterpret_cast<const llvm::ELF::Elf32_Rela*>(pRegion.start());
16822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
16922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  for (size_t idx=0; idx < entsize; ++idx) {
17022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    uint32_t r_offset = 0x0;
17122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    uint32_t r_info   = 0x0;
17222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    int32_t  r_addend = 0;
17322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    if (llvm::sys::isLittleEndianHost()) {
17422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      r_offset = relaTab[idx].r_offset;
17522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      r_info   = relaTab[idx].r_info;
17622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      r_addend = relaTab[idx].r_addend;
17722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    }
17822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    else {
179d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao      r_offset = mcld::bswap32(relaTab[idx].r_offset);
180d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao      r_info   = mcld::bswap32(relaTab[idx].r_info);
181d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao      r_addend = mcld::bswap32(relaTab[idx].r_addend);
18222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    }
18322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
18422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    uint8_t  r_type = static_cast<unsigned char>(r_info);
18522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    uint32_t r_sym  = (r_info >> 8);
18622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    LDSymbol* symbol = pInput.context()->getSymbol(r_sym);
18722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    if (NULL == symbol) {
18822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      fatal(diag::err_cannot_read_symbol) << r_sym << pInput.path();
18922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    }
19022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
191d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    IRBuilder::AddRelocation(pSection, r_type, *symbol, r_offset, r_addend);
19222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  } // end of for
19322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  return true;
19422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao}
19522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
19622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/// readRel - read ELF rel and create Relocation
19722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liaobool ELFReader<32, true>::readRel(Input& pInput,
19822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                                  LDSection& pSection,
19922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                                  const MemoryRegion& pRegion) const
20022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao{
20122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // get the number of rel
20222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  size_t entsize = pRegion.size() / sizeof(llvm::ELF::Elf32_Rel);
20322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  const llvm::ELF::Elf32_Rel* relTab =
20422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                 reinterpret_cast<const llvm::ELF::Elf32_Rel*>(pRegion.start());
20522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
20622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  for (size_t idx=0; idx < entsize; ++idx) {
20722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    uint32_t r_offset = 0x0;
20822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    uint32_t r_info   = 0x0;
20922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    if (llvm::sys::isLittleEndianHost()) {
21022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      r_offset = relTab[idx].r_offset;
21122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      r_info   = relTab[idx].r_info;
21222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    }
21322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    else {
214d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao      r_offset = mcld::bswap32(relTab[idx].r_offset);
215d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao      r_info   = mcld::bswap32(relTab[idx].r_info);
21622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    }
21722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
21822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    uint8_t  r_type = static_cast<unsigned char>(r_info);
21922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    uint32_t r_sym  = (r_info >> 8);
22022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
22122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    LDSymbol* symbol = pInput.context()->getSymbol(r_sym);
22222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    if (NULL == symbol) {
22322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      fatal(diag::err_cannot_read_symbol) << r_sym << pInput.path();
22422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    }
22522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
226d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    IRBuilder::AddRelocation(pSection, r_type, *symbol, r_offset);
22722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  } // end of for
22822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  return true;
22922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao}
23022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
23122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/// isMyEndian - is this ELF file in the same endian to me?
23222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liaobool ELFReader<32, true>::isMyEndian(void* pELFHeader) const
23322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao{
23422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  llvm::ELF::Elf32_Ehdr* hdr =
23522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                          reinterpret_cast<llvm::ELF::Elf32_Ehdr*>(pELFHeader);
23622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
23722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  return (hdr->e_ident[llvm::ELF::EI_DATA] == llvm::ELF::ELFDATA2LSB);
23822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao}
23922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
24022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/// isMyMachine - is this ELF file generated for the same machine.
24122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liaobool ELFReader<32, true>::isMyMachine(void* pELFHeader) const
24222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao{
24322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  llvm::ELF::Elf32_Ehdr* hdr =
24422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                          reinterpret_cast<llvm::ELF::Elf32_Ehdr*>(pELFHeader);
24522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
24622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  if (llvm::sys::isLittleEndianHost())
247d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    return (hdr->e_machine == target().getInfo().machine());
248d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  return (mcld::bswap16(hdr->e_machine) == target().getInfo().machine());
24922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao}
25022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
25122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/// fileType - return the file type
25222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei LiaoInput::Type ELFReader<32, true>::fileType(void* pELFHeader) const
25322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao{
25422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  llvm::ELF::Elf32_Ehdr* hdr =
25522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                          reinterpret_cast<llvm::ELF::Elf32_Ehdr*>(pELFHeader);
25622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  uint32_t type = 0x0;
25722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  if (llvm::sys::isLittleEndianHost())
25822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    type = hdr->e_type;
25922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  else
260d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    type = mcld::bswap16(hdr->e_type);
26122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
26222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  switch(type) {
26322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  case llvm::ELF::ET_REL:
26422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    return Input::Object;
26522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  case llvm::ELF::ET_EXEC:
26622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    return Input::Exec;
26722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  case llvm::ELF::ET_DYN:
26822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    return Input::DynObj;
26922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  case llvm::ELF::ET_CORE:
27022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    return Input::CoreFile;
27122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  case llvm::ELF::ET_NONE:
27222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  default:
27322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    return Input::Unknown;
27422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  }
27522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao}
27622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
27722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/// readSectionHeaders - read ELF section header table and create LDSections
27822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liaobool
27922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei LiaoELFReader<32, true>::readSectionHeaders(Input& pInput, void* pELFHeader) const
28022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao{
28122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  llvm::ELF::Elf32_Ehdr* ehdr =
28222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                          reinterpret_cast<llvm::ELF::Elf32_Ehdr*>(pELFHeader);
28322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
28422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  uint32_t shoff     = 0x0;
28522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  uint16_t shentsize = 0x0;
2866f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  uint32_t shnum     = 0x0;
2876f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  uint32_t shstrtab  = 0x0;
28822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
28922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  if (llvm::sys::isLittleEndianHost()) {
29022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    shoff     = ehdr->e_shoff;
29122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    shentsize = ehdr->e_shentsize;
29222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    shnum     = ehdr->e_shnum;
29322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    shstrtab  = ehdr->e_shstrndx;
29422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  }
29522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  else {
296d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    shoff     = mcld::bswap32(ehdr->e_shoff);
297d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    shentsize = mcld::bswap16(ehdr->e_shentsize);
298d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    shnum     = mcld::bswap16(ehdr->e_shnum);
299d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    shstrtab  = mcld::bswap16(ehdr->e_shstrndx);
30022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  }
30122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
30222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // If the file has no section header table, e_shoff holds zero.
30322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  if (0x0 == shoff)
30422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    return true;
30522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
3066f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  llvm::ELF::Elf32_Shdr *shdr = NULL;
3076f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  MemoryRegion* shdr_region = NULL;
30822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  uint32_t sh_name      = 0x0;
30922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  uint32_t sh_type      = 0x0;
31022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  uint32_t sh_flags     = 0x0;
31122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  uint32_t sh_offset    = 0x0;
31222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  uint32_t sh_size      = 0x0;
31322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  uint32_t sh_link      = 0x0;
31422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  uint32_t sh_info      = 0x0;
31522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  uint32_t sh_addralign = 0x0;
31622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
3176f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // if shnum and shstrtab overflow, the actual values are in the 1st shdr
3186f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  if (shnum == llvm::ELF::SHN_UNDEF || shstrtab == llvm::ELF::SHN_XINDEX) {
3196f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    shdr_region = pInput.memArea()->request(pInput.fileOffset() + shoff,
3206f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                                            shentsize);
3216f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    shdr = reinterpret_cast<llvm::ELF::Elf32_Shdr*>(shdr_region->start());
3226f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
3236f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    if (llvm::sys::isLittleEndianHost()) {
3246f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      sh_size = shdr->sh_size;
3256f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      sh_link = shdr->sh_link;
3266f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    }
3276f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    else {
3286f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      sh_size = mcld::bswap32(shdr->sh_size);
3296f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      sh_link = mcld::bswap32(shdr->sh_link);
3306f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    }
3316f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    pInput.memArea()->release(shdr_region);
3326f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
3336f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    if (shnum == llvm::ELF::SHN_UNDEF)
3346f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      shnum = sh_size;
3356f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    if (shstrtab == llvm::ELF::SHN_XINDEX)
3366f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      shstrtab = sh_link;
3376f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
3386f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    shoff += shentsize;
3396f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  }
3406f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
3416f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  shdr_region = pInput.memArea()->request(pInput.fileOffset() + shoff,
3426f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                                          shnum * shentsize);
3436f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  llvm::ELF::Elf32_Shdr * shdrTab =
3446f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    reinterpret_cast<llvm::ELF::Elf32_Shdr*>(shdr_region->start());
3456f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
34622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // get .shstrtab first
3476f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  shdr = &shdrTab[shstrtab];
34822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  if (llvm::sys::isLittleEndianHost()) {
34922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    sh_offset = shdr->sh_offset;
35022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    sh_size   = shdr->sh_size;
35122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  }
35222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  else {
353d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    sh_offset = mcld::bswap32(shdr->sh_offset);
354d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    sh_size   = mcld::bswap32(shdr->sh_size);
35522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  }
35622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
35722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  MemoryRegion* sect_name_region = pInput.memArea()->request(
35822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                                      pInput.fileOffset() + sh_offset, sh_size);
35922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  const char* sect_name =
36022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                       reinterpret_cast<const char*>(sect_name_region->start());
36122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
36222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  LinkInfoList link_info_list;
36322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
36422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // create all LDSections, including first NULL section.
36522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  for (size_t idx = 0; idx < shnum; ++idx) {
36622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    if (llvm::sys::isLittleEndianHost()) {
36722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      sh_name      = shdrTab[idx].sh_name;
36822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      sh_type      = shdrTab[idx].sh_type;
36922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      sh_flags     = shdrTab[idx].sh_flags;
37022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      sh_offset    = shdrTab[idx].sh_offset;
37122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      sh_size      = shdrTab[idx].sh_size;
37222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      sh_link      = shdrTab[idx].sh_link;
37322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      sh_info      = shdrTab[idx].sh_info;
37422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      sh_addralign = shdrTab[idx].sh_addralign;
37522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    }
37622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    else {
377d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao      sh_name      = mcld::bswap32(shdrTab[idx].sh_name);
378d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao      sh_type      = mcld::bswap32(shdrTab[idx].sh_type);
379d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao      sh_flags     = mcld::bswap32(shdrTab[idx].sh_flags);
380d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao      sh_offset    = mcld::bswap32(shdrTab[idx].sh_offset);
381d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao      sh_size      = mcld::bswap32(shdrTab[idx].sh_size);
382d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao      sh_link      = mcld::bswap32(shdrTab[idx].sh_link);
383d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao      sh_info      = mcld::bswap32(shdrTab[idx].sh_info);
384d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao      sh_addralign = mcld::bswap32(shdrTab[idx].sh_addralign);
38522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    }
38622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
38722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    LDSection* section = IRBuilder::CreateELFHeader(pInput,
38822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                                                    sect_name+sh_name,
38922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                                                    sh_type,
39022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                                                    sh_flags,
39122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                                                    sh_addralign);
39222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    section->setSize(sh_size);
39322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    section->setOffset(sh_offset);
39422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    section->setInfo(sh_info);
39522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
39622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    if (sh_link != 0x0 || sh_info != 0x0) {
39722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      LinkInfo link_info = { section, sh_link, sh_info };
39822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      link_info_list.push_back(link_info);
39922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    }
40022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  } // end of for
40122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
40222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // set up InfoLink
40322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  LinkInfoList::iterator info, infoEnd = link_info_list.end();
40422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  for (info = link_info_list.begin(); info != infoEnd; ++info) {
40522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    if (LDFileFormat::NamePool == info->section->kind() ||
40622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao        LDFileFormat::Group == info->section->kind() ||
40722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao        LDFileFormat::Note == info->section->kind()) {
40822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      info->section->setLink(pInput.context()->getSection(info->sh_link));
40922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      continue;
41022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    }
41122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    if (LDFileFormat::Relocation == info->section->kind()) {
41222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      info->section->setLink(pInput.context()->getSection(info->sh_info));
41322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      continue;
41422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    }
41522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  }
41622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
41722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  pInput.memArea()->release(shdr_region);
41822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  pInput.memArea()->release(sect_name_region);
41922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
42022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  return true;
42122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao}
42222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
42322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/// readSignature - read a symbol from the given Input and index in symtab
42422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/// This is used to get the signature of a group section.
42522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei LiaoResolveInfo* ELFReader<32, true>::readSignature(Input& pInput,
42622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                                                LDSection& pSymTab,
42722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                                                uint32_t pSymIdx) const
428affc150dc44fab1911775a49636d0ce85333b634Zonr Chang{
42922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  LDSection* symtab = &pSymTab;
43022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  LDSection* strtab = symtab->getLink();
43122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  assert(NULL != symtab && NULL != strtab);
43222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
43322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  uint32_t offset = pInput.fileOffset() + symtab->offset() +
43422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                      sizeof(llvm::ELF::Elf32_Sym) * pSymIdx;
43522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  MemoryRegion* symbol_region =
43622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                pInput.memArea()->request(offset, sizeof(llvm::ELF::Elf32_Sym));
43722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  llvm::ELF::Elf32_Sym* entry =
43822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                reinterpret_cast<llvm::ELF::Elf32_Sym*>(symbol_region->start());
43922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
44022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  uint32_t st_name  = 0x0;
44122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  uint8_t  st_info  = 0x0;
44222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  uint8_t  st_other = 0x0;
44322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  uint16_t st_shndx = 0x0;
44422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  st_info  = entry->st_info;
44522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  st_other = entry->st_other;
44622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  if (llvm::sys::isLittleEndianHost()) {
44722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    st_name  = entry->st_name;
44822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    st_shndx = entry->st_shndx;
44922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  }
45022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  else {
451d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    st_name  = mcld::bswap32(entry->st_name);
452d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    st_shndx = mcld::bswap16(entry->st_shndx);
45322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  }
45422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
45522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  MemoryRegion* strtab_region = pInput.memArea()->request(
45622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                       pInput.fileOffset() + strtab->offset(), strtab->size());
45722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
45822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // get ld_name
45922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  llvm::StringRef ld_name(
46022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                    reinterpret_cast<char*>(strtab_region->start() + st_name));
461affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
46222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  ResolveInfo* result = ResolveInfo::Create(ld_name);
46322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  result->setSource(pInput.type() == Input::DynObj);
46422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  result->setType(static_cast<ResolveInfo::Type>(st_info & 0xF));
46522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  result->setDesc(getSymDesc(st_shndx, pInput));
46622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  result->setBinding(getSymBinding((st_info >> 4), st_shndx, st_other));
46722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  result->setVisibility(getSymVisibility(st_other));
468affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
46922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // release regions
47022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  pInput.memArea()->release(symbol_region);
47122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  pInput.memArea()->release(strtab_region);
47222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
47322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  return result;
47422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao}
47522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
47622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/// readDynamic - read ELF .dynamic in input dynobj
47722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liaobool ELFReader<32, true>::readDynamic(Input& pInput) const
47822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao{
47922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  assert(pInput.type() == Input::DynObj);
48022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  const LDSection* dynamic_sect = pInput.context()->getSection(".dynamic");
48122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  if (NULL == dynamic_sect) {
48222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    fatal(diag::err_cannot_read_section) << ".dynamic";
48322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  }
48422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  const LDSection* dynstr_sect = dynamic_sect->getLink();
48522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  if (NULL == dynstr_sect) {
48622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    fatal(diag::err_cannot_read_section) << ".dynstr";
48722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  }
48822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
48922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  MemoryRegion* dynamic_region = pInput.memArea()->request(
49022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao           pInput.fileOffset() + dynamic_sect->offset(), dynamic_sect->size());
49122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
49222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  MemoryRegion* dynstr_region = pInput.memArea()->request(
49322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao             pInput.fileOffset() + dynstr_sect->offset(), dynstr_sect->size());
49422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
49522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  assert(NULL != dynamic_region && NULL != dynstr_region);
49622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
49722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  const llvm::ELF::Elf32_Dyn* dynamic =
49822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    (llvm::ELF::Elf32_Dyn*) dynamic_region->start();
49922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  const char* dynstr = (const char*) dynstr_region->start();
50022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  bool hasSOName = false;
50122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  size_t numOfEntries = dynamic_sect->size() / sizeof(llvm::ELF::Elf32_Dyn);
50222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
50322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  for (size_t idx = 0; idx < numOfEntries; ++idx) {
50422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
50522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    llvm::ELF::Elf32_Sword d_tag = 0x0;
50622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    llvm::ELF::Elf32_Word d_val = 0x0;
50722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
50822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    if (llvm::sys::isLittleEndianHost()) {
50922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      d_tag = dynamic[idx].d_tag;
51022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      d_val = dynamic[idx].d_un.d_val;
51122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    } else {
512d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao      d_tag = mcld::bswap32(dynamic[idx].d_tag);
513d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao      d_val = mcld::bswap32(dynamic[idx].d_un.d_val);
51422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    }
51522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
51622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    switch (d_tag) {
51722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      case llvm::ELF::DT_SONAME:
51822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao        assert(d_val < dynstr_sect->size());
51922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao        pInput.setName(sys::fs::Path(dynstr + d_val).filename().native());
52022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao        hasSOName = true;
52122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao        break;
52222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      case llvm::ELF::DT_NEEDED:
52322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao        // TODO:
52422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao        break;
52522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      case llvm::ELF::DT_NULL:
52622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      default:
52722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao        break;
52822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    }
52922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  }
53022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
53122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // if there is no SONAME in .dynamic, then set it from input path
53222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  if (!hasSOName)
53322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    pInput.setName(pInput.path().filename().native());
53422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
53522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  pInput.memArea()->release(dynamic_region);
53622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  pInput.memArea()->release(dynstr_region);
537affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  return true;
538affc150dc44fab1911775a49636d0ce85333b634Zonr Chang}
53922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
5406f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines//===----------------------------------------------------------------------===//
5416f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// ELFReader<64, true>
5426f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines//===----------------------------------------------------------------------===//
5436f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines/// constructor
5446f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesELFReader<64, true>::ELFReader(GNULDBackend& pBackend)
5456f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  : ELFReaderIF(pBackend) {
5466f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
5476f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
5486f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines/// destructor
5496f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesELFReader<64, true>::~ELFReader()
5506f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{
5516f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
5526f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
5536f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines/// isELF - is this a ELF file
5546f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesbool ELFReader<64, true>::isELF(void* pELFHeader) const
5556f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{
5566f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  llvm::ELF::Elf64_Ehdr* hdr =
5576f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                          reinterpret_cast<llvm::ELF::Elf64_Ehdr*>(pELFHeader);
5586f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  if (0 == memcmp(llvm::ELF::ElfMagic, hdr, 4))
5596f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    return true;
5606f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  return false;
5616f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
5626f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
5636f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines/// readRegularSection - read a regular section and create fragments.
5646f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesbool
5656f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesELFReader<64, true>::readRegularSection(Input& pInput, SectionData& pSD) const
5666f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{
5676f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  uint64_t offset = pInput.fileOffset() + pSD.getSection().offset();
5686f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  uint64_t size = pSD.getSection().size();
5696f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
5706f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  Fragment* frag = IRBuilder::CreateRegion(pInput, offset, size);
5716f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  ObjectBuilder::AppendFragment(*frag, pSD);
5726f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  return true;
5736f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
5746f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
5756f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines/// readSymbols - read ELF symbols and create LDSymbol
5766f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesbool ELFReader<64, true>::readSymbols(Input& pInput,
5776f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                                      IRBuilder& pBuilder,
5786f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                                      const MemoryRegion& pRegion,
5796f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                                      const char* pStrTab) const
5806f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{
5816f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // get number of symbols
5826f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  size_t entsize = pRegion.size()/sizeof(llvm::ELF::Elf64_Sym);
5836f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  const llvm::ELF::Elf64_Sym* symtab =
5846f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                 reinterpret_cast<const llvm::ELF::Elf64_Sym*>(pRegion.start());
5856f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
5866f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  uint32_t st_name  = 0x0;
5876f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  uint64_t st_value = 0x0;
5886f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  uint64_t st_size  = 0x0;
5896f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  uint8_t  st_info  = 0x0;
5906f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  uint8_t  st_other = 0x0;
5916f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  uint16_t st_shndx = 0x0;
5926f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
5936f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // skip the first NULL symbol
5946f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  pInput.context()->addSymbol(LDSymbol::Null());
5956f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
5966f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  for (size_t idx = 1; idx < entsize; ++idx) {
5976f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    st_info  = symtab[idx].st_info;
5986f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    st_other = symtab[idx].st_other;
5996f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
6006f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    if (llvm::sys::isLittleEndianHost()) {
6016f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      st_name  = symtab[idx].st_name;
6026f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      st_value = symtab[idx].st_value;
6036f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      st_size  = symtab[idx].st_size;
6046f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      st_shndx = symtab[idx].st_shndx;
6056f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    }
6066f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    else {
6076f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      st_name  = mcld::bswap32(symtab[idx].st_name);
6086f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      st_value = mcld::bswap64(symtab[idx].st_value);
6096f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      st_size  = mcld::bswap64(symtab[idx].st_size);
6106f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      st_shndx = mcld::bswap16(symtab[idx].st_shndx);
6116f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    }
6126f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
6136f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    // If the section should not be included, set the st_shndx SHN_UNDEF
6146f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    // - A section in interrelated groups are not included.
6156f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    if (pInput.type() == Input::Object &&
6166f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines        st_shndx < llvm::ELF::SHN_LORESERVE &&
6176f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines        st_shndx != llvm::ELF::SHN_UNDEF) {
6186f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      if (NULL == pInput.context()->getSection(st_shndx))
6196f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines        st_shndx = llvm::ELF::SHN_UNDEF;
6206f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    }
6216f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
6226f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    // get ld_type
6236f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    ResolveInfo::Type ld_type = getSymType(st_info, st_shndx);
6246f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
6256f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    // get ld_desc
6266f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    ResolveInfo::Desc ld_desc = getSymDesc(st_shndx, pInput);
6276f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
6286f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    // get ld_binding
6296f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    ResolveInfo::Binding ld_binding = getSymBinding((st_info >> 4), st_shndx, st_other);
6306f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
6316f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    // get ld_value - ld_value must be section relative.
6326f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    uint64_t ld_value = getSymValue(st_value, st_shndx, pInput);
6336f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
6346f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    // get ld_vis
6356f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    ResolveInfo::Visibility ld_vis = getSymVisibility(st_other);
6366f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
6376f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    // get section
6386f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    LDSection* section = NULL;
6396f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    if (st_shndx < llvm::ELF::SHN_LORESERVE) // including ABS and COMMON
6406f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      section = pInput.context()->getSection(st_shndx);
6416f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
6426f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    // get ld_name
6436f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    std::string ld_name;
6446f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    if (ResolveInfo::Section == ld_type) {
6456f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      // Section symbol's st_name is the section index.
6466f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      assert(NULL != section && "get a invalid section");
6476f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      ld_name = section->name();
6486f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    }
6496f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    else {
6506f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      ld_name = std::string(pStrTab + st_name);
6516f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    }
6526f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
6536f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    pBuilder.AddSymbol(pInput,
6546f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                       ld_name,
6556f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                       ld_type,
6566f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                       ld_desc,
6576f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                       ld_binding,
6586f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                       st_size,
6596f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                       ld_value,
6606f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                       section, ld_vis);
6616f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  } // end of for loop
6626f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  return true;
6636f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
6646f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
6656f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines//===----------------------------------------------------------------------===//
6666f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// ELFReader::read relocations - read ELF rela and rel, and create Relocation
6676f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines//===----------------------------------------------------------------------===//
6686f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines/// ELFReader::readRela - read ELF rela and create Relocation
6696f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesbool ELFReader<64, true>::readRela(Input& pInput,
6706f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                                   LDSection& pSection,
6716f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                                   const MemoryRegion& pRegion) const
6726f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{
6736f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // get the number of rela
6746f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  size_t entsize = pRegion.size() / sizeof(llvm::ELF::Elf64_Rela);
6756f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  const llvm::ELF::Elf64_Rela* relaTab =
6766f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                reinterpret_cast<const llvm::ELF::Elf64_Rela*>(pRegion.start());
6776f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
6786f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  for (size_t idx=0; idx < entsize; ++idx) {
6796f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    uint64_t r_offset = 0x0;
6806f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    uint64_t r_info   = 0x0;
6816f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    int64_t  r_addend = 0;
6826f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    if (llvm::sys::isLittleEndianHost()) {
6836f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      r_offset = relaTab[idx].r_offset;
6846f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      r_info   = relaTab[idx].r_info;
6856f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      r_addend = relaTab[idx].r_addend;
6866f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    }
6876f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    else {
6886f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      r_offset = mcld::bswap64(relaTab[idx].r_offset);
6896f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      r_info   = mcld::bswap64(relaTab[idx].r_info);
6906f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      r_addend = mcld::bswap64(relaTab[idx].r_addend);
6916f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    }
6926f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
6936f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    uint32_t  r_type = static_cast<uint32_t>(r_info);
6946f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    uint32_t r_sym  = (r_info >> 32);
6956f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    LDSymbol* symbol = pInput.context()->getSymbol(r_sym);
6966f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    if (NULL == symbol) {
6976f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      fatal(diag::err_cannot_read_symbol) << r_sym << pInput.path();
6986f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    }
6996f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
7006f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    IRBuilder::AddRelocation(pSection, r_type, *symbol, r_offset, r_addend);
7016f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  } // end of for
7026f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  return true;
7036f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
7046f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
7056f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines/// readRel - read ELF rel and create Relocation
7066f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesbool ELFReader<64, true>::readRel(Input& pInput,
7076f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                                  LDSection& pSection,
7086f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                                  const MemoryRegion& pRegion) const
7096f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{
7106f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // get the number of rel
7116f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  size_t entsize = pRegion.size() / sizeof(llvm::ELF::Elf64_Rel);
7126f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  const llvm::ELF::Elf64_Rel* relTab =
7136f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                 reinterpret_cast<const llvm::ELF::Elf64_Rel*>(pRegion.start());
7146f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
7156f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  for (size_t idx=0; idx < entsize; ++idx) {
7166f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    uint64_t r_offset = 0x0;
7176f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    uint64_t r_info   = 0x0;
7186f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    if (llvm::sys::isLittleEndianHost()) {
7196f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      r_offset = relTab[idx].r_offset;
7206f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      r_info   = relTab[idx].r_info;
7216f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    }
7226f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    else {
7236f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      r_offset = mcld::bswap64(relTab[idx].r_offset);
7246f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      r_info   = mcld::bswap64(relTab[idx].r_info);
7256f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    }
7266f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
7276f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    uint32_t  r_type = static_cast<uint32_t>(r_info);
7286f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    uint32_t r_sym  = (r_info >> 32);
7296f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
7306f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    LDSymbol* symbol = pInput.context()->getSymbol(r_sym);
7316f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    if (NULL == symbol) {
7326f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      fatal(diag::err_cannot_read_symbol) << r_sym << pInput.path();
7336f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    }
7346f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
7356f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    IRBuilder::AddRelocation(pSection, r_type, *symbol, r_offset);
7366f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  } // end of for
7376f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  return true;
7386f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
7396f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
7406f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines/// isMyEndian - is this ELF file in the same endian to me?
7416f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesbool ELFReader<64, true>::isMyEndian(void* pELFHeader) const
7426f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{
7436f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  llvm::ELF::Elf64_Ehdr* hdr =
7446f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                          reinterpret_cast<llvm::ELF::Elf64_Ehdr*>(pELFHeader);
7456f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
7466f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  return (hdr->e_ident[llvm::ELF::EI_DATA] == llvm::ELF::ELFDATA2LSB);
7476f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
7486f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
7496f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines/// isMyMachine - is this ELF file generated for the same machine.
7506f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesbool ELFReader<64, true>::isMyMachine(void* pELFHeader) const
7516f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{
7526f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  llvm::ELF::Elf64_Ehdr* hdr =
7536f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                          reinterpret_cast<llvm::ELF::Elf64_Ehdr*>(pELFHeader);
7546f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
7556f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  if (llvm::sys::isLittleEndianHost())
7566f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    return (hdr->e_machine == target().getInfo().machine());
7576f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  return (mcld::bswap16(hdr->e_machine) == target().getInfo().machine());
7586f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
7596f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
7606f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines/// fileType - return the file type
7616f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesInput::Type ELFReader<64, true>::fileType(void* pELFHeader) const
7626f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{
7636f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  llvm::ELF::Elf64_Ehdr* hdr =
7646f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                          reinterpret_cast<llvm::ELF::Elf64_Ehdr*>(pELFHeader);
7656f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  uint32_t type = 0x0;
7666f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  if (llvm::sys::isLittleEndianHost())
7676f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    type = hdr->e_type;
7686f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  else
7696f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    type = mcld::bswap16(hdr->e_type);
7706f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
7716f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  switch(type) {
7726f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  case llvm::ELF::ET_REL:
7736f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    return Input::Object;
7746f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  case llvm::ELF::ET_EXEC:
7756f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    return Input::Exec;
7766f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  case llvm::ELF::ET_DYN:
7776f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    return Input::DynObj;
7786f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  case llvm::ELF::ET_CORE:
7796f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    return Input::CoreFile;
7806f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  case llvm::ELF::ET_NONE:
7816f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  default:
7826f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    return Input::Unknown;
7836f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  }
7846f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
7856f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
7866f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines/// readSectionHeaders - read ELF section header table and create LDSections
7876f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesbool
7886f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesELFReader<64, true>::readSectionHeaders(Input& pInput, void* pELFHeader) const
7896f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{
7906f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  llvm::ELF::Elf64_Ehdr* ehdr =
7916f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                          reinterpret_cast<llvm::ELF::Elf64_Ehdr*>(pELFHeader);
7926f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
7936f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  uint64_t shoff     = 0x0;
7946f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  uint16_t shentsize = 0x0;
7956f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  uint32_t shnum     = 0x0;
7966f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  uint32_t shstrtab  = 0x0;
7976f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
7986f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  if (llvm::sys::isLittleEndianHost()) {
7996f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    shoff     = ehdr->e_shoff;
8006f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    shentsize = ehdr->e_shentsize;
8016f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    shnum     = ehdr->e_shnum;
8026f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    shstrtab  = ehdr->e_shstrndx;
8036f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  }
8046f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  else {
8056f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    shoff     = mcld::bswap64(ehdr->e_shoff);
8066f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    shentsize = mcld::bswap16(ehdr->e_shentsize);
8076f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    shnum     = mcld::bswap16(ehdr->e_shnum);
8086f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    shstrtab  = mcld::bswap16(ehdr->e_shstrndx);
8096f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  }
8106f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
8116f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // If the file has no section header table, e_shoff holds zero.
8126f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  if (0x0 == shoff)
8136f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    return true;
8146f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
8156f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  llvm::ELF::Elf64_Shdr *shdr = NULL;
8166f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  MemoryRegion* shdr_region = NULL;
8176f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  uint32_t sh_name      = 0x0;
8186f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  uint32_t sh_type      = 0x0;
8196f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  uint64_t sh_flags     = 0x0;
8206f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  uint64_t sh_offset    = 0x0;
8216f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  uint64_t sh_size      = 0x0;
8226f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  uint32_t sh_link      = 0x0;
8236f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  uint32_t sh_info      = 0x0;
8246f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  uint64_t sh_addralign = 0x0;
8256f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
8266f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // if shnum and shstrtab overflow, the actual values are in the 1st shdr
8276f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  if (shnum == llvm::ELF::SHN_UNDEF || shstrtab == llvm::ELF::SHN_XINDEX) {
8286f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    shdr_region = pInput.memArea()->request(pInput.fileOffset() + shoff,
8296f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                                            shentsize);
8306f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    shdr = reinterpret_cast<llvm::ELF::Elf64_Shdr*>(shdr_region->start());
8316f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
8326f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    if (llvm::sys::isLittleEndianHost()) {
8336f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      sh_size = shdr->sh_size;
8346f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      sh_link = shdr->sh_link;
8356f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    }
8366f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    else {
8376f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      sh_size = mcld::bswap64(shdr->sh_size);
8386f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      sh_link = mcld::bswap32(shdr->sh_link);
8396f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    }
8406f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    pInput.memArea()->release(shdr_region);
8416f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
8426f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    if (shnum == llvm::ELF::SHN_UNDEF)
8436f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      shnum = sh_size;
8446f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    if (shstrtab == llvm::ELF::SHN_XINDEX)
8456f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      shstrtab = sh_link;
8466f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
8476f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    shoff += shentsize;
8486f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  }
8496f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
8506f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  shdr_region = pInput.memArea()->request(pInput.fileOffset() + shoff,
8516f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                                          shnum * shentsize);
8526f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  llvm::ELF::Elf64_Shdr * shdrTab =
8536f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    reinterpret_cast<llvm::ELF::Elf64_Shdr*>(shdr_region->start());
8546f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
8556f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // get .shstrtab first
8566f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  shdr = &shdrTab[shstrtab];
8576f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  if (llvm::sys::isLittleEndianHost()) {
8586f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    sh_offset = shdr->sh_offset;
8596f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    sh_size   = shdr->sh_size;
8606f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  }
8616f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  else {
8626f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    sh_offset = mcld::bswap64(shdr->sh_offset);
8636f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    sh_size   = mcld::bswap64(shdr->sh_size);
8646f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  }
8656f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
8666f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  MemoryRegion* sect_name_region = pInput.memArea()->request(
8676f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                                      pInput.fileOffset() + sh_offset, sh_size);
8686f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  const char* sect_name =
8696f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                       reinterpret_cast<const char*>(sect_name_region->start());
8706f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
8716f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  LinkInfoList link_info_list;
8726f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
8736f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // create all LDSections, including first NULL section.
8746f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  for (size_t idx = 0; idx < shnum; ++idx) {
8756f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    if (llvm::sys::isLittleEndianHost()) {
8766f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      sh_name      = shdrTab[idx].sh_name;
8776f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      sh_type      = shdrTab[idx].sh_type;
8786f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      sh_flags     = shdrTab[idx].sh_flags;
8796f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      sh_offset    = shdrTab[idx].sh_offset;
8806f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      sh_size      = shdrTab[idx].sh_size;
8816f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      sh_link      = shdrTab[idx].sh_link;
8826f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      sh_info      = shdrTab[idx].sh_info;
8836f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      sh_addralign = shdrTab[idx].sh_addralign;
8846f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    }
8856f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    else {
8866f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      sh_name      = mcld::bswap32(shdrTab[idx].sh_name);
8876f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      sh_type      = mcld::bswap32(shdrTab[idx].sh_type);
8886f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      sh_flags     = mcld::bswap64(shdrTab[idx].sh_flags);
8896f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      sh_offset    = mcld::bswap64(shdrTab[idx].sh_offset);
8906f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      sh_size      = mcld::bswap64(shdrTab[idx].sh_size);
8916f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      sh_link      = mcld::bswap32(shdrTab[idx].sh_link);
8926f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      sh_info      = mcld::bswap32(shdrTab[idx].sh_info);
8936f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      sh_addralign = mcld::bswap64(shdrTab[idx].sh_addralign);
8946f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    }
8956f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
8966f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    LDSection* section = IRBuilder::CreateELFHeader(pInput,
8976f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                                                    sect_name+sh_name,
8986f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                                                    sh_type,
8996f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                                                    sh_flags,
9006f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                                                    sh_addralign);
9016f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    section->setSize(sh_size);
9026f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    section->setOffset(sh_offset);
9036f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    section->setInfo(sh_info);
9046f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
9056f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    if (sh_link != 0x0 || sh_info != 0x0) {
9066f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      LinkInfo link_info = { section, sh_link, sh_info };
9076f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      link_info_list.push_back(link_info);
9086f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    }
9096f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  } // end of for
9106f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
9116f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // set up InfoLink
9126f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  LinkInfoList::iterator info, infoEnd = link_info_list.end();
9136f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  for (info = link_info_list.begin(); info != infoEnd; ++info) {
9146f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    if (LDFileFormat::NamePool == info->section->kind() ||
9156f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines        LDFileFormat::Group == info->section->kind() ||
9166f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines        LDFileFormat::Note == info->section->kind()) {
9176f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      info->section->setLink(pInput.context()->getSection(info->sh_link));
9186f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      continue;
9196f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    }
9206f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    if (LDFileFormat::Relocation == info->section->kind()) {
9216f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      info->section->setLink(pInput.context()->getSection(info->sh_info));
9226f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      continue;
9236f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    }
9246f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  }
9256f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
9266f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  pInput.memArea()->release(shdr_region);
9276f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  pInput.memArea()->release(sect_name_region);
9286f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
9296f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  return true;
9306f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
9316f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
9326f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines/// readSignature - read a symbol from the given Input and index in symtab
9336f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines/// This is used to get the signature of a group section.
9346f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesResolveInfo* ELFReader<64, true>::readSignature(Input& pInput,
9356f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                                                LDSection& pSymTab,
9366f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                                                uint32_t pSymIdx) const
9376f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{
9386f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  LDSection* symtab = &pSymTab;
9396f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  LDSection* strtab = symtab->getLink();
9406f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  assert(NULL != symtab && NULL != strtab);
9416f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
9426f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  uint64_t offset = pInput.fileOffset() + symtab->offset() +
9436f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                      sizeof(llvm::ELF::Elf64_Sym) * pSymIdx;
9446f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  MemoryRegion* symbol_region =
9456f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                pInput.memArea()->request(offset, sizeof(llvm::ELF::Elf64_Sym));
9466f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  llvm::ELF::Elf64_Sym* entry =
9476f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                reinterpret_cast<llvm::ELF::Elf64_Sym*>(symbol_region->start());
9486f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
9496f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  uint32_t st_name  = 0x0;
9506f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  uint8_t  st_info  = 0x0;
9516f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  uint8_t  st_other = 0x0;
9526f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  uint16_t st_shndx = 0x0;
9536f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  st_info  = entry->st_info;
9546f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  st_other = entry->st_other;
9556f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  if (llvm::sys::isLittleEndianHost()) {
9566f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    st_name  = entry->st_name;
9576f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    st_shndx = entry->st_shndx;
9586f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  }
9596f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  else {
9606f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    st_name  = mcld::bswap32(entry->st_name);
9616f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    st_shndx = mcld::bswap16(entry->st_shndx);
9626f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  }
9636f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
9646f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  MemoryRegion* strtab_region = pInput.memArea()->request(
9656f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                       pInput.fileOffset() + strtab->offset(), strtab->size());
9666f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
9676f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // get ld_name
9686f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  llvm::StringRef ld_name(
9696f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                    reinterpret_cast<char*>(strtab_region->start() + st_name));
9706f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
9716f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  ResolveInfo* result = ResolveInfo::Create(ld_name);
9726f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  result->setSource(pInput.type() == Input::DynObj);
9736f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  result->setType(static_cast<ResolveInfo::Type>(st_info & 0xF));
9746f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  result->setDesc(getSymDesc(st_shndx, pInput));
9756f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  result->setBinding(getSymBinding((st_info >> 4), st_shndx, st_other));
9766f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  result->setVisibility(getSymVisibility(st_other));
9776f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
9786f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // release regions
9796f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  pInput.memArea()->release(symbol_region);
9806f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  pInput.memArea()->release(strtab_region);
9816f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
9826f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  return result;
9836f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
9846f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
9856f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines/// readDynamic - read ELF .dynamic in input dynobj
9866f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesbool ELFReader<64, true>::readDynamic(Input& pInput) const
9876f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{
9886f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  assert(pInput.type() == Input::DynObj);
9896f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  const LDSection* dynamic_sect = pInput.context()->getSection(".dynamic");
9906f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  if (NULL == dynamic_sect) {
9916f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    fatal(diag::err_cannot_read_section) << ".dynamic";
9926f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  }
9936f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  const LDSection* dynstr_sect = dynamic_sect->getLink();
9946f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  if (NULL == dynstr_sect) {
9956f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    fatal(diag::err_cannot_read_section) << ".dynstr";
9966f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  }
9976f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
9986f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  MemoryRegion* dynamic_region = pInput.memArea()->request(
9996f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines           pInput.fileOffset() + dynamic_sect->offset(), dynamic_sect->size());
10006f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
10016f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  MemoryRegion* dynstr_region = pInput.memArea()->request(
10026f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines             pInput.fileOffset() + dynstr_sect->offset(), dynstr_sect->size());
10036f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
10046f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  assert(NULL != dynamic_region && NULL != dynstr_region);
10056f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
10066f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  const llvm::ELF::Elf64_Dyn* dynamic =
10076f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    (llvm::ELF::Elf64_Dyn*) dynamic_region->start();
10086f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  const char* dynstr = (const char*) dynstr_region->start();
10096f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  bool hasSOName = false;
10106f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  size_t numOfEntries = dynamic_sect->size() / sizeof(llvm::ELF::Elf64_Dyn);
10116f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
10126f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  for (size_t idx = 0; idx < numOfEntries; ++idx) {
10136f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
10146f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    llvm::ELF::Elf64_Sxword d_tag = 0x0;
10156f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    llvm::ELF::Elf64_Xword d_val = 0x0;
10166f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
10176f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    if (llvm::sys::isLittleEndianHost()) {
10186f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      d_tag = dynamic[idx].d_tag;
10196f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      d_val = dynamic[idx].d_un.d_val;
10206f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    } else {
10216f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      d_tag = mcld::bswap64(dynamic[idx].d_tag);
10226f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      d_val = mcld::bswap64(dynamic[idx].d_un.d_val);
10236f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    }
10246f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
10256f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    switch (d_tag) {
10266f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      case llvm::ELF::DT_SONAME:
10276f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines        assert(d_val < dynstr_sect->size());
10286f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines        pInput.setName(sys::fs::Path(dynstr + d_val).filename().native());
10296f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines        hasSOName = true;
10306f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines        break;
10316f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      case llvm::ELF::DT_NEEDED:
10326f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines        // TODO:
10336f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines        break;
10346f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      case llvm::ELF::DT_NULL:
10356f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      default:
10366f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines        break;
10376f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    }
10386f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  }
10396f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
10406f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // if there is no SONAME in .dynamic, then set it from input path
10416f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  if (!hasSOName)
10426f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    pInput.setName(pInput.path().filename().native());
10436f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
10446f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  pInput.memArea()->release(dynamic_region);
10456f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  pInput.memArea()->release(dynstr_region);
10466f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  return true;
10476f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
10486f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
1049