ELFReader.cpp revision f7ac0f19a1c8d0ad14bcf6456ce368b830fea886
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
87f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  /// recording symbols added from DynObj to analyze weak alias
88f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  std::vector<AliasInfo> potential_aliases;
89f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  bool is_dyn_obj = (pInput.type()==Input::DynObj);
9022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  for (size_t idx = 1; idx < entsize; ++idx) {
9122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    st_info  = symtab[idx].st_info;
9222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    st_other = symtab[idx].st_other;
9322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
9422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    if (llvm::sys::isLittleEndianHost()) {
9522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      st_name  = symtab[idx].st_name;
9622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      st_value = symtab[idx].st_value;
9722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      st_size  = symtab[idx].st_size;
9822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      st_shndx = symtab[idx].st_shndx;
9922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    }
10022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    else {
101d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao      st_name  = mcld::bswap32(symtab[idx].st_name);
102d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao      st_value = mcld::bswap32(symtab[idx].st_value);
103d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao      st_size  = mcld::bswap32(symtab[idx].st_size);
104d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao      st_shndx = mcld::bswap16(symtab[idx].st_shndx);
10522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    }
10622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
10722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    // If the section should not be included, set the st_shndx SHN_UNDEF
10822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    // - A section in interrelated groups are not included.
10922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    if (pInput.type() == Input::Object &&
11022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao        st_shndx < llvm::ELF::SHN_LORESERVE &&
11122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao        st_shndx != llvm::ELF::SHN_UNDEF) {
11222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      if (NULL == pInput.context()->getSection(st_shndx))
11322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao        st_shndx = llvm::ELF::SHN_UNDEF;
11422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    }
11522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
11622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    // get ld_type
11722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    ResolveInfo::Type ld_type = getSymType(st_info, st_shndx);
11822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
11922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    // get ld_desc
12022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    ResolveInfo::Desc ld_desc = getSymDesc(st_shndx, pInput);
12122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
12222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    // get ld_binding
12322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    ResolveInfo::Binding ld_binding = getSymBinding((st_info >> 4), st_shndx, st_other);
12422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
12522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    // get ld_value - ld_value must be section relative.
12622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    uint64_t ld_value = getSymValue(st_value, st_shndx, pInput);
12722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
12822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    // get ld_vis
12922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    ResolveInfo::Visibility ld_vis = getSymVisibility(st_other);
13022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
131d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    // get section
132d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    LDSection* section = NULL;
133d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    if (st_shndx < llvm::ELF::SHN_LORESERVE) // including ABS and COMMON
134d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao      section = pInput.context()->getSection(st_shndx);
135d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao
13622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    // get ld_name
137d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    std::string ld_name;
13822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    if (ResolveInfo::Section == ld_type) {
13922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      // Section symbol's st_name is the section index.
14022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      assert(NULL != section && "get a invalid section");
141d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao      ld_name = section->name();
14222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    }
14322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    else {
144d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao      ld_name = std::string(pStrTab + st_name);
14522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    }
14622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
147f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    LDSymbol *psym =
148f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        pBuilder.AddSymbol(pInput,
149f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                           ld_name,
150f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                           ld_type,
151f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                           ld_desc,
152f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                           ld_binding,
153f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                           st_size,
154f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                           ld_value,
155f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                           section, ld_vis);
156f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
157f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    if ( is_dyn_obj
158f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines         && NULL!=psym
159f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines         && ResolveInfo::Undefined!=ld_desc
160f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines         && (ResolveInfo::Global==ld_binding ||
161f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines             ResolveInfo::Weak==ld_binding)
162f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines         && ResolveInfo::Object==ld_type ) {
163f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      AliasInfo p;
164f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      p.pt_alias = psym;
165f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      p.ld_binding = ld_binding;
166f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      p.ld_value = ld_value;
167f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      potential_aliases.push_back(p);
168f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    }
169f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
17022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  } // end of for loop
171f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
172f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  // analyze weak alias
173f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  // FIXME: it is better to let IRBuilder handle alias anlysis.
174f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  //        1. eliminate code duplication
175f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  //        2. easy to know if a symbol is from .so
176f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  //           (so that it may be a potential alias)
177f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if ( is_dyn_obj ) {
178f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    // sort symbols by symbol value and then weak before strong
179f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    std::sort( potential_aliases.begin(), potential_aliases.end(), less);
180f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
181f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    // for each weak symbol, find out all its aliases, and
182f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    // then link them as a circular list in Module
183f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    std::vector<AliasInfo>::iterator sym_it, sym_e;
184f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    sym_e = potential_aliases.end();
185f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    for (sym_it = potential_aliases.begin(); sym_it!=sym_e; ++sym_it) {
186f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      if (ResolveInfo::Weak!=sym_it->ld_binding)
187f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        continue;
188f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
189f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      Module& pModule = pBuilder.getModule();
190f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      std::vector<AliasInfo>::iterator alias_it = sym_it+1;
191f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      while(alias_it!=sym_e) {
192f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        if ( sym_it->ld_value != alias_it->ld_value )
193f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines          break;
194f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
195f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        if (sym_it+1==alias_it)
196f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines          pModule.CreateAliasList(*sym_it->pt_alias->resolveInfo());
197f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        pModule.addAlias(*alias_it->pt_alias->resolveInfo());
198f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        ++alias_it;
199f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      }
200f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
201f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      sym_it = alias_it-1;
202f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    }// end of for loop
203f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  }
204f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
20522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  return true;
20622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao}
20722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
20822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao//===----------------------------------------------------------------------===//
20922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao// ELFReader::read relocations - read ELF rela and rel, and create Relocation
21022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao//===----------------------------------------------------------------------===//
21122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/// ELFReader::readRela - read ELF rela and create Relocation
21222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liaobool ELFReader<32, true>::readRela(Input& pInput,
21322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                                   LDSection& pSection,
21422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                                   const MemoryRegion& pRegion) const
21522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao{
21622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // get the number of rela
21722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  size_t entsize = pRegion.size() / sizeof(llvm::ELF::Elf32_Rela);
21822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  const llvm::ELF::Elf32_Rela* relaTab =
21922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                reinterpret_cast<const llvm::ELF::Elf32_Rela*>(pRegion.start());
22022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
22122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  for (size_t idx=0; idx < entsize; ++idx) {
22222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    uint32_t r_offset = 0x0;
22322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    uint32_t r_info   = 0x0;
22422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    int32_t  r_addend = 0;
22522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    if (llvm::sys::isLittleEndianHost()) {
22622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      r_offset = relaTab[idx].r_offset;
22722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      r_info   = relaTab[idx].r_info;
22822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      r_addend = relaTab[idx].r_addend;
22922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    }
23022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    else {
231d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao      r_offset = mcld::bswap32(relaTab[idx].r_offset);
232d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao      r_info   = mcld::bswap32(relaTab[idx].r_info);
233d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao      r_addend = mcld::bswap32(relaTab[idx].r_addend);
23422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    }
23522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
23622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    uint8_t  r_type = static_cast<unsigned char>(r_info);
23722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    uint32_t r_sym  = (r_info >> 8);
23822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    LDSymbol* symbol = pInput.context()->getSymbol(r_sym);
23922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    if (NULL == symbol) {
24022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      fatal(diag::err_cannot_read_symbol) << r_sym << pInput.path();
24122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    }
24222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
243d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    IRBuilder::AddRelocation(pSection, r_type, *symbol, r_offset, r_addend);
24422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  } // end of for
24522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  return true;
24622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao}
24722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
24822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/// readRel - read ELF rel and create Relocation
24922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liaobool ELFReader<32, true>::readRel(Input& pInput,
25022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                                  LDSection& pSection,
25122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                                  const MemoryRegion& pRegion) const
25222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao{
25322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // get the number of rel
25422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  size_t entsize = pRegion.size() / sizeof(llvm::ELF::Elf32_Rel);
25522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  const llvm::ELF::Elf32_Rel* relTab =
25622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                 reinterpret_cast<const llvm::ELF::Elf32_Rel*>(pRegion.start());
25722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
25822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  for (size_t idx=0; idx < entsize; ++idx) {
25922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    uint32_t r_offset = 0x0;
26022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    uint32_t r_info   = 0x0;
26122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    if (llvm::sys::isLittleEndianHost()) {
26222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      r_offset = relTab[idx].r_offset;
26322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      r_info   = relTab[idx].r_info;
26422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    }
26522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    else {
266d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao      r_offset = mcld::bswap32(relTab[idx].r_offset);
267d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao      r_info   = mcld::bswap32(relTab[idx].r_info);
26822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    }
26922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
27022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    uint8_t  r_type = static_cast<unsigned char>(r_info);
27122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    uint32_t r_sym  = (r_info >> 8);
27222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
27322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    LDSymbol* symbol = pInput.context()->getSymbol(r_sym);
27422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    if (NULL == symbol) {
27522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      fatal(diag::err_cannot_read_symbol) << r_sym << pInput.path();
27622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    }
27722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
278d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    IRBuilder::AddRelocation(pSection, r_type, *symbol, r_offset);
27922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  } // end of for
28022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  return true;
28122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao}
28222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
28322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/// isMyEndian - is this ELF file in the same endian to me?
28422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liaobool ELFReader<32, true>::isMyEndian(void* pELFHeader) const
28522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao{
28622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  llvm::ELF::Elf32_Ehdr* hdr =
28722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                          reinterpret_cast<llvm::ELF::Elf32_Ehdr*>(pELFHeader);
28822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
28922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  return (hdr->e_ident[llvm::ELF::EI_DATA] == llvm::ELF::ELFDATA2LSB);
29022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao}
29122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
29222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/// isMyMachine - is this ELF file generated for the same machine.
29322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liaobool ELFReader<32, true>::isMyMachine(void* pELFHeader) const
29422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao{
29522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  llvm::ELF::Elf32_Ehdr* hdr =
29622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                          reinterpret_cast<llvm::ELF::Elf32_Ehdr*>(pELFHeader);
29722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
29822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  if (llvm::sys::isLittleEndianHost())
299d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    return (hdr->e_machine == target().getInfo().machine());
300d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  return (mcld::bswap16(hdr->e_machine) == target().getInfo().machine());
30122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao}
30222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
30322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/// fileType - return the file type
30422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei LiaoInput::Type ELFReader<32, true>::fileType(void* pELFHeader) const
30522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao{
30622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  llvm::ELF::Elf32_Ehdr* hdr =
30722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                          reinterpret_cast<llvm::ELF::Elf32_Ehdr*>(pELFHeader);
30822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  uint32_t type = 0x0;
30922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  if (llvm::sys::isLittleEndianHost())
31022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    type = hdr->e_type;
31122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  else
312d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    type = mcld::bswap16(hdr->e_type);
31322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
31422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  switch(type) {
31522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  case llvm::ELF::ET_REL:
31622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    return Input::Object;
31722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  case llvm::ELF::ET_EXEC:
31822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    return Input::Exec;
31922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  case llvm::ELF::ET_DYN:
32022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    return Input::DynObj;
32122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  case llvm::ELF::ET_CORE:
32222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    return Input::CoreFile;
32322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  case llvm::ELF::ET_NONE:
32422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  default:
32522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    return Input::Unknown;
32622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  }
32722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao}
32822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
32922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/// readSectionHeaders - read ELF section header table and create LDSections
33022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liaobool
33122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei LiaoELFReader<32, true>::readSectionHeaders(Input& pInput, void* pELFHeader) const
33222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao{
33322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  llvm::ELF::Elf32_Ehdr* ehdr =
33422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                          reinterpret_cast<llvm::ELF::Elf32_Ehdr*>(pELFHeader);
33522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
33622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  uint32_t shoff     = 0x0;
33722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  uint16_t shentsize = 0x0;
3386f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  uint32_t shnum     = 0x0;
3396f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  uint32_t shstrtab  = 0x0;
34022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
34122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  if (llvm::sys::isLittleEndianHost()) {
34222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    shoff     = ehdr->e_shoff;
34322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    shentsize = ehdr->e_shentsize;
34422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    shnum     = ehdr->e_shnum;
34522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    shstrtab  = ehdr->e_shstrndx;
34622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  }
34722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  else {
348d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    shoff     = mcld::bswap32(ehdr->e_shoff);
349d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    shentsize = mcld::bswap16(ehdr->e_shentsize);
350d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    shnum     = mcld::bswap16(ehdr->e_shnum);
351d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    shstrtab  = mcld::bswap16(ehdr->e_shstrndx);
35222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  }
35322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
35422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // If the file has no section header table, e_shoff holds zero.
35522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  if (0x0 == shoff)
35622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    return true;
35722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
3586f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  llvm::ELF::Elf32_Shdr *shdr = NULL;
3596f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  MemoryRegion* shdr_region = NULL;
36022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  uint32_t sh_name      = 0x0;
36122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  uint32_t sh_type      = 0x0;
36222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  uint32_t sh_flags     = 0x0;
36322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  uint32_t sh_offset    = 0x0;
36422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  uint32_t sh_size      = 0x0;
36522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  uint32_t sh_link      = 0x0;
36622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  uint32_t sh_info      = 0x0;
36722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  uint32_t sh_addralign = 0x0;
36822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
3696f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // if shnum and shstrtab overflow, the actual values are in the 1st shdr
3706f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  if (shnum == llvm::ELF::SHN_UNDEF || shstrtab == llvm::ELF::SHN_XINDEX) {
3716f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    shdr_region = pInput.memArea()->request(pInput.fileOffset() + shoff,
3726f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                                            shentsize);
3736f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    shdr = reinterpret_cast<llvm::ELF::Elf32_Shdr*>(shdr_region->start());
3746f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
3756f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    if (llvm::sys::isLittleEndianHost()) {
3766f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      sh_size = shdr->sh_size;
3776f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      sh_link = shdr->sh_link;
3786f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    }
3796f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    else {
3806f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      sh_size = mcld::bswap32(shdr->sh_size);
3816f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      sh_link = mcld::bswap32(shdr->sh_link);
3826f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    }
3836f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    pInput.memArea()->release(shdr_region);
3846f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
3856f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    if (shnum == llvm::ELF::SHN_UNDEF)
3866f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      shnum = sh_size;
3876f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    if (shstrtab == llvm::ELF::SHN_XINDEX)
3886f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      shstrtab = sh_link;
3896f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
3906f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    shoff += shentsize;
3916f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  }
3926f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
3936f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  shdr_region = pInput.memArea()->request(pInput.fileOffset() + shoff,
3946f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                                          shnum * shentsize);
3956f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  llvm::ELF::Elf32_Shdr * shdrTab =
3966f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    reinterpret_cast<llvm::ELF::Elf32_Shdr*>(shdr_region->start());
3976f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
39822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // get .shstrtab first
3996f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  shdr = &shdrTab[shstrtab];
40022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  if (llvm::sys::isLittleEndianHost()) {
40122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    sh_offset = shdr->sh_offset;
40222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    sh_size   = shdr->sh_size;
40322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  }
40422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  else {
405d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    sh_offset = mcld::bswap32(shdr->sh_offset);
406d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    sh_size   = mcld::bswap32(shdr->sh_size);
40722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  }
40822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
40922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  MemoryRegion* sect_name_region = pInput.memArea()->request(
41022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                                      pInput.fileOffset() + sh_offset, sh_size);
41122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  const char* sect_name =
41222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                       reinterpret_cast<const char*>(sect_name_region->start());
41322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
41422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  LinkInfoList link_info_list;
41522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
41622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // create all LDSections, including first NULL section.
41722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  for (size_t idx = 0; idx < shnum; ++idx) {
41822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    if (llvm::sys::isLittleEndianHost()) {
41922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      sh_name      = shdrTab[idx].sh_name;
42022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      sh_type      = shdrTab[idx].sh_type;
42122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      sh_flags     = shdrTab[idx].sh_flags;
42222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      sh_offset    = shdrTab[idx].sh_offset;
42322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      sh_size      = shdrTab[idx].sh_size;
42422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      sh_link      = shdrTab[idx].sh_link;
42522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      sh_info      = shdrTab[idx].sh_info;
42622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      sh_addralign = shdrTab[idx].sh_addralign;
42722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    }
42822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    else {
429d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao      sh_name      = mcld::bswap32(shdrTab[idx].sh_name);
430d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao      sh_type      = mcld::bswap32(shdrTab[idx].sh_type);
431d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao      sh_flags     = mcld::bswap32(shdrTab[idx].sh_flags);
432d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao      sh_offset    = mcld::bswap32(shdrTab[idx].sh_offset);
433d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao      sh_size      = mcld::bswap32(shdrTab[idx].sh_size);
434d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao      sh_link      = mcld::bswap32(shdrTab[idx].sh_link);
435d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao      sh_info      = mcld::bswap32(shdrTab[idx].sh_info);
436d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao      sh_addralign = mcld::bswap32(shdrTab[idx].sh_addralign);
43722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    }
43822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
43922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    LDSection* section = IRBuilder::CreateELFHeader(pInput,
44022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                                                    sect_name+sh_name,
44122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                                                    sh_type,
44222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                                                    sh_flags,
44322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                                                    sh_addralign);
44422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    section->setSize(sh_size);
44522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    section->setOffset(sh_offset);
44622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    section->setInfo(sh_info);
44722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
44822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    if (sh_link != 0x0 || sh_info != 0x0) {
44922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      LinkInfo link_info = { section, sh_link, sh_info };
45022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      link_info_list.push_back(link_info);
45122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    }
45222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  } // end of for
45322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
45422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // set up InfoLink
45522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  LinkInfoList::iterator info, infoEnd = link_info_list.end();
45622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  for (info = link_info_list.begin(); info != infoEnd; ++info) {
45722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    if (LDFileFormat::NamePool == info->section->kind() ||
45822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao        LDFileFormat::Group == info->section->kind() ||
45922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao        LDFileFormat::Note == info->section->kind()) {
46022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      info->section->setLink(pInput.context()->getSection(info->sh_link));
46122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      continue;
46222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    }
46322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    if (LDFileFormat::Relocation == info->section->kind()) {
46422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      info->section->setLink(pInput.context()->getSection(info->sh_info));
46522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      continue;
46622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    }
46722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  }
46822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
46922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  pInput.memArea()->release(shdr_region);
47022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  pInput.memArea()->release(sect_name_region);
47122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
47222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  return true;
47322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao}
47422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
47522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/// readSignature - read a symbol from the given Input and index in symtab
47622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/// This is used to get the signature of a group section.
47722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei LiaoResolveInfo* ELFReader<32, true>::readSignature(Input& pInput,
47822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                                                LDSection& pSymTab,
47922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                                                uint32_t pSymIdx) const
480affc150dc44fab1911775a49636d0ce85333b634Zonr Chang{
48122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  LDSection* symtab = &pSymTab;
48222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  LDSection* strtab = symtab->getLink();
48322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  assert(NULL != symtab && NULL != strtab);
48422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
48522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  uint32_t offset = pInput.fileOffset() + symtab->offset() +
48622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                      sizeof(llvm::ELF::Elf32_Sym) * pSymIdx;
48722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  MemoryRegion* symbol_region =
48822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                pInput.memArea()->request(offset, sizeof(llvm::ELF::Elf32_Sym));
48922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  llvm::ELF::Elf32_Sym* entry =
49022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                reinterpret_cast<llvm::ELF::Elf32_Sym*>(symbol_region->start());
49122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
49222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  uint32_t st_name  = 0x0;
49322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  uint8_t  st_info  = 0x0;
49422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  uint8_t  st_other = 0x0;
49522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  uint16_t st_shndx = 0x0;
49622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  st_info  = entry->st_info;
49722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  st_other = entry->st_other;
49822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  if (llvm::sys::isLittleEndianHost()) {
49922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    st_name  = entry->st_name;
50022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    st_shndx = entry->st_shndx;
50122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  }
50222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  else {
503d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    st_name  = mcld::bswap32(entry->st_name);
504d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    st_shndx = mcld::bswap16(entry->st_shndx);
50522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  }
50622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
50722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  MemoryRegion* strtab_region = pInput.memArea()->request(
50822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                       pInput.fileOffset() + strtab->offset(), strtab->size());
50922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
51022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // get ld_name
51122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  llvm::StringRef ld_name(
51222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                    reinterpret_cast<char*>(strtab_region->start() + st_name));
513affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
51422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  ResolveInfo* result = ResolveInfo::Create(ld_name);
51522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  result->setSource(pInput.type() == Input::DynObj);
51622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  result->setType(static_cast<ResolveInfo::Type>(st_info & 0xF));
51722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  result->setDesc(getSymDesc(st_shndx, pInput));
51822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  result->setBinding(getSymBinding((st_info >> 4), st_shndx, st_other));
51922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  result->setVisibility(getSymVisibility(st_other));
520affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
52122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // release regions
52222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  pInput.memArea()->release(symbol_region);
52322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  pInput.memArea()->release(strtab_region);
52422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
52522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  return result;
52622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao}
52722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
52822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/// readDynamic - read ELF .dynamic in input dynobj
52922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liaobool ELFReader<32, true>::readDynamic(Input& pInput) const
53022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao{
53122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  assert(pInput.type() == Input::DynObj);
53222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  const LDSection* dynamic_sect = pInput.context()->getSection(".dynamic");
53322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  if (NULL == dynamic_sect) {
53422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    fatal(diag::err_cannot_read_section) << ".dynamic";
53522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  }
53622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  const LDSection* dynstr_sect = dynamic_sect->getLink();
53722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  if (NULL == dynstr_sect) {
53822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    fatal(diag::err_cannot_read_section) << ".dynstr";
53922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  }
54022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
54122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  MemoryRegion* dynamic_region = pInput.memArea()->request(
54222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao           pInput.fileOffset() + dynamic_sect->offset(), dynamic_sect->size());
54322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
54422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  MemoryRegion* dynstr_region = pInput.memArea()->request(
54522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao             pInput.fileOffset() + dynstr_sect->offset(), dynstr_sect->size());
54622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
54722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  assert(NULL != dynamic_region && NULL != dynstr_region);
54822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
54922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  const llvm::ELF::Elf32_Dyn* dynamic =
55022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    (llvm::ELF::Elf32_Dyn*) dynamic_region->start();
55122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  const char* dynstr = (const char*) dynstr_region->start();
55222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  bool hasSOName = false;
55322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  size_t numOfEntries = dynamic_sect->size() / sizeof(llvm::ELF::Elf32_Dyn);
55422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
55522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  for (size_t idx = 0; idx < numOfEntries; ++idx) {
55622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
55722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    llvm::ELF::Elf32_Sword d_tag = 0x0;
55822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    llvm::ELF::Elf32_Word d_val = 0x0;
55922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
56022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    if (llvm::sys::isLittleEndianHost()) {
56122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      d_tag = dynamic[idx].d_tag;
56222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      d_val = dynamic[idx].d_un.d_val;
56322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    } else {
564d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao      d_tag = mcld::bswap32(dynamic[idx].d_tag);
565d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao      d_val = mcld::bswap32(dynamic[idx].d_un.d_val);
56622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    }
56722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
56822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    switch (d_tag) {
56922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      case llvm::ELF::DT_SONAME:
57022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao        assert(d_val < dynstr_sect->size());
57122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao        pInput.setName(sys::fs::Path(dynstr + d_val).filename().native());
57222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao        hasSOName = true;
57322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao        break;
57422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      case llvm::ELF::DT_NEEDED:
57522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao        // TODO:
57622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao        break;
57722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      case llvm::ELF::DT_NULL:
57822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      default:
57922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao        break;
58022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    }
58122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  }
58222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
58322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // if there is no SONAME in .dynamic, then set it from input path
58422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  if (!hasSOName)
58522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    pInput.setName(pInput.path().filename().native());
58622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
58722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  pInput.memArea()->release(dynamic_region);
58822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  pInput.memArea()->release(dynstr_region);
589affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  return true;
590affc150dc44fab1911775a49636d0ce85333b634Zonr Chang}
59122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
5926f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines//===----------------------------------------------------------------------===//
5936f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// ELFReader<64, true>
5946f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines//===----------------------------------------------------------------------===//
5956f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines/// constructor
5966f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesELFReader<64, true>::ELFReader(GNULDBackend& pBackend)
5976f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  : ELFReaderIF(pBackend) {
5986f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
5996f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
6006f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines/// destructor
6016f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesELFReader<64, true>::~ELFReader()
6026f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{
6036f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
6046f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
6056f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines/// isELF - is this a ELF file
6066f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesbool ELFReader<64, true>::isELF(void* pELFHeader) const
6076f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{
6086f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  llvm::ELF::Elf64_Ehdr* hdr =
6096f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                          reinterpret_cast<llvm::ELF::Elf64_Ehdr*>(pELFHeader);
6106f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  if (0 == memcmp(llvm::ELF::ElfMagic, hdr, 4))
6116f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    return true;
6126f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  return false;
6136f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
6146f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
6156f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines/// readRegularSection - read a regular section and create fragments.
6166f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesbool
6176f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesELFReader<64, true>::readRegularSection(Input& pInput, SectionData& pSD) const
6186f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{
6196f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  uint64_t offset = pInput.fileOffset() + pSD.getSection().offset();
6206f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  uint64_t size = pSD.getSection().size();
6216f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
6226f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  Fragment* frag = IRBuilder::CreateRegion(pInput, offset, size);
6236f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  ObjectBuilder::AppendFragment(*frag, pSD);
6246f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  return true;
6256f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
6266f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
6276f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines/// readSymbols - read ELF symbols and create LDSymbol
6286f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesbool ELFReader<64, true>::readSymbols(Input& pInput,
6296f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                                      IRBuilder& pBuilder,
6306f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                                      const MemoryRegion& pRegion,
6316f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                                      const char* pStrTab) const
6326f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{
6336f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // get number of symbols
6346f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  size_t entsize = pRegion.size()/sizeof(llvm::ELF::Elf64_Sym);
6356f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  const llvm::ELF::Elf64_Sym* symtab =
6366f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                 reinterpret_cast<const llvm::ELF::Elf64_Sym*>(pRegion.start());
6376f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
6386f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  uint32_t st_name  = 0x0;
6396f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  uint64_t st_value = 0x0;
6406f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  uint64_t st_size  = 0x0;
6416f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  uint8_t  st_info  = 0x0;
6426f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  uint8_t  st_other = 0x0;
6436f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  uint16_t st_shndx = 0x0;
6446f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
6456f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // skip the first NULL symbol
6466f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  pInput.context()->addSymbol(LDSymbol::Null());
6476f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
648f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  /// recording symbols added from DynObj to analyze weak alias
649f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  std::vector<AliasInfo> potential_aliases;
650f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  bool is_dyn_obj = (pInput.type()==Input::DynObj);
6516f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  for (size_t idx = 1; idx < entsize; ++idx) {
6526f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    st_info  = symtab[idx].st_info;
6536f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    st_other = symtab[idx].st_other;
6546f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
6556f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    if (llvm::sys::isLittleEndianHost()) {
6566f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      st_name  = symtab[idx].st_name;
6576f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      st_value = symtab[idx].st_value;
6586f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      st_size  = symtab[idx].st_size;
6596f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      st_shndx = symtab[idx].st_shndx;
6606f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    }
6616f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    else {
6626f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      st_name  = mcld::bswap32(symtab[idx].st_name);
6636f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      st_value = mcld::bswap64(symtab[idx].st_value);
6646f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      st_size  = mcld::bswap64(symtab[idx].st_size);
6656f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      st_shndx = mcld::bswap16(symtab[idx].st_shndx);
6666f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    }
6676f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
6686f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    // If the section should not be included, set the st_shndx SHN_UNDEF
6696f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    // - A section in interrelated groups are not included.
6706f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    if (pInput.type() == Input::Object &&
6716f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines        st_shndx < llvm::ELF::SHN_LORESERVE &&
6726f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines        st_shndx != llvm::ELF::SHN_UNDEF) {
6736f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      if (NULL == pInput.context()->getSection(st_shndx))
6746f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines        st_shndx = llvm::ELF::SHN_UNDEF;
6756f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    }
6766f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
6776f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    // get ld_type
6786f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    ResolveInfo::Type ld_type = getSymType(st_info, st_shndx);
6796f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
6806f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    // get ld_desc
6816f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    ResolveInfo::Desc ld_desc = getSymDesc(st_shndx, pInput);
6826f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
6836f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    // get ld_binding
6846f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    ResolveInfo::Binding ld_binding = getSymBinding((st_info >> 4), st_shndx, st_other);
6856f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
6866f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    // get ld_value - ld_value must be section relative.
6876f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    uint64_t ld_value = getSymValue(st_value, st_shndx, pInput);
6886f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
6896f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    // get ld_vis
6906f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    ResolveInfo::Visibility ld_vis = getSymVisibility(st_other);
6916f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
6926f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    // get section
6936f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    LDSection* section = NULL;
6946f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    if (st_shndx < llvm::ELF::SHN_LORESERVE) // including ABS and COMMON
6956f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      section = pInput.context()->getSection(st_shndx);
6966f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
6976f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    // get ld_name
6986f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    std::string ld_name;
6996f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    if (ResolveInfo::Section == ld_type) {
7006f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      // Section symbol's st_name is the section index.
7016f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      assert(NULL != section && "get a invalid section");
7026f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      ld_name = section->name();
7036f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    }
7046f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    else {
7056f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      ld_name = std::string(pStrTab + st_name);
7066f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    }
7076f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
708f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    LDSymbol *psym =
709f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines            pBuilder.AddSymbol(pInput,
710f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                               ld_name,
711f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                               ld_type,
712f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                               ld_desc,
713f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                               ld_binding,
714f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                               st_size,
715f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                               ld_value,
716f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines                               section, ld_vis);
717f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
718f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    if ( is_dyn_obj
719f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines         && NULL!=psym
720f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines         && ResolveInfo::Undefined!=ld_desc
721f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines         && (ResolveInfo::Global==ld_binding ||
722f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines             ResolveInfo::Weak==ld_binding)
723f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines         && ResolveInfo::Object==ld_type ) {
724f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      AliasInfo p;
725f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      p.pt_alias = psym;
726f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      p.ld_binding = ld_binding;
727f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      p.ld_value = ld_value;
728f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      potential_aliases.push_back(p);
729f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    }
730f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
7316f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  } // end of for loop
732f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
733f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  // analyze weak alias here
734f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if ( is_dyn_obj ) {
735f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    // sort symbols by symbol value and then weak before strong
736f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    std::sort( potential_aliases.begin(), potential_aliases.end(), less);
737f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
738f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    // for each weak symbol, find out all its aliases, and
739f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    // then link them as a circular list in Module
740f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    std::vector<AliasInfo>::iterator sym_it, sym_e;
741f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    sym_e = potential_aliases.end();
742f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    for (sym_it = potential_aliases.begin(); sym_it!=sym_e; ++sym_it) {
743f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      if (ResolveInfo::Weak!=sym_it->ld_binding)
744f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        continue;
745f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
746f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      Module& pModule = pBuilder.getModule();
747f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      std::vector<AliasInfo>::iterator alias_it = sym_it+1;
748f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      while(alias_it!=sym_e) {
749f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        if ( sym_it->ld_value != alias_it->ld_value )
750f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines          break;
751f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
752f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        if (sym_it+1==alias_it)
753f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines          pModule.CreateAliasList(*sym_it->pt_alias->resolveInfo());
754f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        pModule.addAlias(*alias_it->pt_alias->resolveInfo());
755f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        ++alias_it;
756f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      }
757f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
758f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      sym_it = alias_it-1;
759f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    }// end of for loop
760f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  }
7616f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  return true;
7626f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
7636f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
7646f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines//===----------------------------------------------------------------------===//
7656f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// ELFReader::read relocations - read ELF rela and rel, and create Relocation
7666f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines//===----------------------------------------------------------------------===//
7676f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines/// ELFReader::readRela - read ELF rela and create Relocation
7686f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesbool ELFReader<64, true>::readRela(Input& pInput,
7696f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                                   LDSection& pSection,
7706f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                                   const MemoryRegion& pRegion) const
7716f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{
7726f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // get the number of rela
7736f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  size_t entsize = pRegion.size() / sizeof(llvm::ELF::Elf64_Rela);
7746f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  const llvm::ELF::Elf64_Rela* relaTab =
7756f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                reinterpret_cast<const llvm::ELF::Elf64_Rela*>(pRegion.start());
7766f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
7776f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  for (size_t idx=0; idx < entsize; ++idx) {
7786f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    uint64_t r_offset = 0x0;
7796f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    uint64_t r_info   = 0x0;
7806f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    int64_t  r_addend = 0;
7816f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    if (llvm::sys::isLittleEndianHost()) {
7826f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      r_offset = relaTab[idx].r_offset;
7836f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      r_info   = relaTab[idx].r_info;
7846f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      r_addend = relaTab[idx].r_addend;
7856f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    }
7866f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    else {
7876f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      r_offset = mcld::bswap64(relaTab[idx].r_offset);
7886f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      r_info   = mcld::bswap64(relaTab[idx].r_info);
7896f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      r_addend = mcld::bswap64(relaTab[idx].r_addend);
7906f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    }
7916f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
7926f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    uint32_t  r_type = static_cast<uint32_t>(r_info);
7936f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    uint32_t r_sym  = (r_info >> 32);
7946f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    LDSymbol* symbol = pInput.context()->getSymbol(r_sym);
7956f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    if (NULL == symbol) {
7966f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      fatal(diag::err_cannot_read_symbol) << r_sym << pInput.path();
7976f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    }
7986f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
7996f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    IRBuilder::AddRelocation(pSection, r_type, *symbol, r_offset, r_addend);
8006f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  } // end of for
8016f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  return true;
8026f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
8036f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
8046f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines/// readRel - read ELF rel and create Relocation
8056f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesbool ELFReader<64, true>::readRel(Input& pInput,
8066f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                                  LDSection& pSection,
8076f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                                  const MemoryRegion& pRegion) const
8086f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{
8096f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // get the number of rel
8106f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  size_t entsize = pRegion.size() / sizeof(llvm::ELF::Elf64_Rel);
8116f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  const llvm::ELF::Elf64_Rel* relTab =
8126f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                 reinterpret_cast<const llvm::ELF::Elf64_Rel*>(pRegion.start());
8136f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
8146f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  for (size_t idx=0; idx < entsize; ++idx) {
8156f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    uint64_t r_offset = 0x0;
8166f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    uint64_t r_info   = 0x0;
8176f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    if (llvm::sys::isLittleEndianHost()) {
8186f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      r_offset = relTab[idx].r_offset;
8196f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      r_info   = relTab[idx].r_info;
8206f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    }
8216f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    else {
8226f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      r_offset = mcld::bswap64(relTab[idx].r_offset);
8236f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      r_info   = mcld::bswap64(relTab[idx].r_info);
8246f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    }
8256f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
8266f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    uint32_t  r_type = static_cast<uint32_t>(r_info);
8276f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    uint32_t r_sym  = (r_info >> 32);
8286f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
8296f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    LDSymbol* symbol = pInput.context()->getSymbol(r_sym);
8306f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    if (NULL == symbol) {
8316f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      fatal(diag::err_cannot_read_symbol) << r_sym << pInput.path();
8326f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    }
8336f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
8346f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    IRBuilder::AddRelocation(pSection, r_type, *symbol, r_offset);
8356f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  } // end of for
8366f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  return true;
8376f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
8386f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
8396f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines/// isMyEndian - is this ELF file in the same endian to me?
8406f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesbool ELFReader<64, true>::isMyEndian(void* pELFHeader) const
8416f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{
8426f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  llvm::ELF::Elf64_Ehdr* hdr =
8436f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                          reinterpret_cast<llvm::ELF::Elf64_Ehdr*>(pELFHeader);
8446f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
8456f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  return (hdr->e_ident[llvm::ELF::EI_DATA] == llvm::ELF::ELFDATA2LSB);
8466f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
8476f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
8486f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines/// isMyMachine - is this ELF file generated for the same machine.
8496f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesbool ELFReader<64, true>::isMyMachine(void* pELFHeader) const
8506f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{
8516f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  llvm::ELF::Elf64_Ehdr* hdr =
8526f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                          reinterpret_cast<llvm::ELF::Elf64_Ehdr*>(pELFHeader);
8536f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
8546f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  if (llvm::sys::isLittleEndianHost())
8556f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    return (hdr->e_machine == target().getInfo().machine());
8566f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  return (mcld::bswap16(hdr->e_machine) == target().getInfo().machine());
8576f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
8586f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
8596f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines/// fileType - return the file type
8606f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesInput::Type ELFReader<64, true>::fileType(void* pELFHeader) const
8616f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{
8626f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  llvm::ELF::Elf64_Ehdr* hdr =
8636f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                          reinterpret_cast<llvm::ELF::Elf64_Ehdr*>(pELFHeader);
8646f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  uint32_t type = 0x0;
8656f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  if (llvm::sys::isLittleEndianHost())
8666f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    type = hdr->e_type;
8676f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  else
8686f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    type = mcld::bswap16(hdr->e_type);
8696f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
8706f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  switch(type) {
8716f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  case llvm::ELF::ET_REL:
8726f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    return Input::Object;
8736f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  case llvm::ELF::ET_EXEC:
8746f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    return Input::Exec;
8756f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  case llvm::ELF::ET_DYN:
8766f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    return Input::DynObj;
8776f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  case llvm::ELF::ET_CORE:
8786f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    return Input::CoreFile;
8796f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  case llvm::ELF::ET_NONE:
8806f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  default:
8816f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    return Input::Unknown;
8826f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  }
8836f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
8846f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
8856f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines/// readSectionHeaders - read ELF section header table and create LDSections
8866f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesbool
8876f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesELFReader<64, true>::readSectionHeaders(Input& pInput, void* pELFHeader) const
8886f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{
8896f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  llvm::ELF::Elf64_Ehdr* ehdr =
8906f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                          reinterpret_cast<llvm::ELF::Elf64_Ehdr*>(pELFHeader);
8916f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
8926f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  uint64_t shoff     = 0x0;
8936f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  uint16_t shentsize = 0x0;
8946f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  uint32_t shnum     = 0x0;
8956f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  uint32_t shstrtab  = 0x0;
8966f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
8976f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  if (llvm::sys::isLittleEndianHost()) {
8986f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    shoff     = ehdr->e_shoff;
8996f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    shentsize = ehdr->e_shentsize;
9006f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    shnum     = ehdr->e_shnum;
9016f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    shstrtab  = ehdr->e_shstrndx;
9026f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  }
9036f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  else {
9046f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    shoff     = mcld::bswap64(ehdr->e_shoff);
9056f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    shentsize = mcld::bswap16(ehdr->e_shentsize);
9066f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    shnum     = mcld::bswap16(ehdr->e_shnum);
9076f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    shstrtab  = mcld::bswap16(ehdr->e_shstrndx);
9086f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  }
9096f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
9106f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // If the file has no section header table, e_shoff holds zero.
9116f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  if (0x0 == shoff)
9126f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    return true;
9136f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
9146f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  llvm::ELF::Elf64_Shdr *shdr = NULL;
9156f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  MemoryRegion* shdr_region = NULL;
9166f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  uint32_t sh_name      = 0x0;
9176f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  uint32_t sh_type      = 0x0;
9186f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  uint64_t sh_flags     = 0x0;
9196f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  uint64_t sh_offset    = 0x0;
9206f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  uint64_t sh_size      = 0x0;
9216f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  uint32_t sh_link      = 0x0;
9226f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  uint32_t sh_info      = 0x0;
9236f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  uint64_t sh_addralign = 0x0;
9246f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
9256f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // if shnum and shstrtab overflow, the actual values are in the 1st shdr
9266f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  if (shnum == llvm::ELF::SHN_UNDEF || shstrtab == llvm::ELF::SHN_XINDEX) {
9276f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    shdr_region = pInput.memArea()->request(pInput.fileOffset() + shoff,
9286f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                                            shentsize);
9296f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    shdr = reinterpret_cast<llvm::ELF::Elf64_Shdr*>(shdr_region->start());
9306f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
9316f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    if (llvm::sys::isLittleEndianHost()) {
9326f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      sh_size = shdr->sh_size;
9336f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      sh_link = shdr->sh_link;
9346f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    }
9356f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    else {
9366f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      sh_size = mcld::bswap64(shdr->sh_size);
9376f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      sh_link = mcld::bswap32(shdr->sh_link);
9386f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    }
9396f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    pInput.memArea()->release(shdr_region);
9406f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
9416f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    if (shnum == llvm::ELF::SHN_UNDEF)
9426f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      shnum = sh_size;
9436f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    if (shstrtab == llvm::ELF::SHN_XINDEX)
9446f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      shstrtab = sh_link;
9456f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
9466f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    shoff += shentsize;
9476f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  }
9486f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
9496f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  shdr_region = pInput.memArea()->request(pInput.fileOffset() + shoff,
9506f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                                          shnum * shentsize);
9516f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  llvm::ELF::Elf64_Shdr * shdrTab =
9526f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    reinterpret_cast<llvm::ELF::Elf64_Shdr*>(shdr_region->start());
9536f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
9546f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // get .shstrtab first
9556f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  shdr = &shdrTab[shstrtab];
9566f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  if (llvm::sys::isLittleEndianHost()) {
9576f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    sh_offset = shdr->sh_offset;
9586f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    sh_size   = shdr->sh_size;
9596f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  }
9606f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  else {
9616f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    sh_offset = mcld::bswap64(shdr->sh_offset);
9626f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    sh_size   = mcld::bswap64(shdr->sh_size);
9636f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  }
9646f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
9656f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  MemoryRegion* sect_name_region = pInput.memArea()->request(
9666f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                                      pInput.fileOffset() + sh_offset, sh_size);
9676f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  const char* sect_name =
9686f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                       reinterpret_cast<const char*>(sect_name_region->start());
9696f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
9706f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  LinkInfoList link_info_list;
9716f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
9726f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // create all LDSections, including first NULL section.
9736f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  for (size_t idx = 0; idx < shnum; ++idx) {
9746f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    if (llvm::sys::isLittleEndianHost()) {
9756f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      sh_name      = shdrTab[idx].sh_name;
9766f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      sh_type      = shdrTab[idx].sh_type;
9776f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      sh_flags     = shdrTab[idx].sh_flags;
9786f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      sh_offset    = shdrTab[idx].sh_offset;
9796f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      sh_size      = shdrTab[idx].sh_size;
9806f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      sh_link      = shdrTab[idx].sh_link;
9816f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      sh_info      = shdrTab[idx].sh_info;
9826f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      sh_addralign = shdrTab[idx].sh_addralign;
9836f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    }
9846f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    else {
9856f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      sh_name      = mcld::bswap32(shdrTab[idx].sh_name);
9866f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      sh_type      = mcld::bswap32(shdrTab[idx].sh_type);
9876f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      sh_flags     = mcld::bswap64(shdrTab[idx].sh_flags);
9886f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      sh_offset    = mcld::bswap64(shdrTab[idx].sh_offset);
9896f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      sh_size      = mcld::bswap64(shdrTab[idx].sh_size);
9906f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      sh_link      = mcld::bswap32(shdrTab[idx].sh_link);
9916f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      sh_info      = mcld::bswap32(shdrTab[idx].sh_info);
9926f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      sh_addralign = mcld::bswap64(shdrTab[idx].sh_addralign);
9936f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    }
9946f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
9956f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    LDSection* section = IRBuilder::CreateELFHeader(pInput,
9966f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                                                    sect_name+sh_name,
9976f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                                                    sh_type,
9986f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                                                    sh_flags,
9996f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                                                    sh_addralign);
10006f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    section->setSize(sh_size);
10016f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    section->setOffset(sh_offset);
10026f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    section->setInfo(sh_info);
10036f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
10046f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    if (sh_link != 0x0 || sh_info != 0x0) {
10056f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      LinkInfo link_info = { section, sh_link, sh_info };
10066f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      link_info_list.push_back(link_info);
10076f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    }
10086f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  } // end of for
10096f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
10106f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // set up InfoLink
10116f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  LinkInfoList::iterator info, infoEnd = link_info_list.end();
10126f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  for (info = link_info_list.begin(); info != infoEnd; ++info) {
10136f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    if (LDFileFormat::NamePool == info->section->kind() ||
10146f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines        LDFileFormat::Group == info->section->kind() ||
10156f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines        LDFileFormat::Note == info->section->kind()) {
10166f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      info->section->setLink(pInput.context()->getSection(info->sh_link));
10176f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      continue;
10186f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    }
10196f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    if (LDFileFormat::Relocation == info->section->kind()) {
10206f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      info->section->setLink(pInput.context()->getSection(info->sh_info));
10216f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      continue;
10226f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    }
10236f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  }
10246f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
10256f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  pInput.memArea()->release(shdr_region);
10266f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  pInput.memArea()->release(sect_name_region);
10276f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
10286f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  return true;
10296f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
10306f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
10316f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines/// readSignature - read a symbol from the given Input and index in symtab
10326f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines/// This is used to get the signature of a group section.
10336f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesResolveInfo* ELFReader<64, true>::readSignature(Input& pInput,
10346f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                                                LDSection& pSymTab,
10356f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                                                uint32_t pSymIdx) const
10366f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{
10376f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  LDSection* symtab = &pSymTab;
10386f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  LDSection* strtab = symtab->getLink();
10396f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  assert(NULL != symtab && NULL != strtab);
10406f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
10416f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  uint64_t offset = pInput.fileOffset() + symtab->offset() +
10426f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                      sizeof(llvm::ELF::Elf64_Sym) * pSymIdx;
10436f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  MemoryRegion* symbol_region =
10446f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                pInput.memArea()->request(offset, sizeof(llvm::ELF::Elf64_Sym));
10456f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  llvm::ELF::Elf64_Sym* entry =
10466f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                reinterpret_cast<llvm::ELF::Elf64_Sym*>(symbol_region->start());
10476f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
10486f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  uint32_t st_name  = 0x0;
10496f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  uint8_t  st_info  = 0x0;
10506f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  uint8_t  st_other = 0x0;
10516f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  uint16_t st_shndx = 0x0;
10526f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  st_info  = entry->st_info;
10536f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  st_other = entry->st_other;
10546f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  if (llvm::sys::isLittleEndianHost()) {
10556f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    st_name  = entry->st_name;
10566f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    st_shndx = entry->st_shndx;
10576f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  }
10586f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  else {
10596f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    st_name  = mcld::bswap32(entry->st_name);
10606f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    st_shndx = mcld::bswap16(entry->st_shndx);
10616f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  }
10626f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
10636f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  MemoryRegion* strtab_region = pInput.memArea()->request(
10646f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                       pInput.fileOffset() + strtab->offset(), strtab->size());
10656f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
10666f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // get ld_name
10676f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  llvm::StringRef ld_name(
10686f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                    reinterpret_cast<char*>(strtab_region->start() + st_name));
10696f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
10706f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  ResolveInfo* result = ResolveInfo::Create(ld_name);
10716f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  result->setSource(pInput.type() == Input::DynObj);
10726f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  result->setType(static_cast<ResolveInfo::Type>(st_info & 0xF));
10736f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  result->setDesc(getSymDesc(st_shndx, pInput));
10746f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  result->setBinding(getSymBinding((st_info >> 4), st_shndx, st_other));
10756f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  result->setVisibility(getSymVisibility(st_other));
10766f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
10776f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // release regions
10786f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  pInput.memArea()->release(symbol_region);
10796f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  pInput.memArea()->release(strtab_region);
10806f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
10816f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  return result;
10826f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
10836f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
10846f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines/// readDynamic - read ELF .dynamic in input dynobj
10856f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesbool ELFReader<64, true>::readDynamic(Input& pInput) const
10866f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{
10876f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  assert(pInput.type() == Input::DynObj);
10886f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  const LDSection* dynamic_sect = pInput.context()->getSection(".dynamic");
10896f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  if (NULL == dynamic_sect) {
10906f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    fatal(diag::err_cannot_read_section) << ".dynamic";
10916f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  }
10926f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  const LDSection* dynstr_sect = dynamic_sect->getLink();
10936f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  if (NULL == dynstr_sect) {
10946f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    fatal(diag::err_cannot_read_section) << ".dynstr";
10956f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  }
10966f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
10976f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  MemoryRegion* dynamic_region = pInput.memArea()->request(
10986f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines           pInput.fileOffset() + dynamic_sect->offset(), dynamic_sect->size());
10996f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
11006f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  MemoryRegion* dynstr_region = pInput.memArea()->request(
11016f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines             pInput.fileOffset() + dynstr_sect->offset(), dynstr_sect->size());
11026f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
11036f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  assert(NULL != dynamic_region && NULL != dynstr_region);
11046f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
11056f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  const llvm::ELF::Elf64_Dyn* dynamic =
11066f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    (llvm::ELF::Elf64_Dyn*) dynamic_region->start();
11076f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  const char* dynstr = (const char*) dynstr_region->start();
11086f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  bool hasSOName = false;
11096f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  size_t numOfEntries = dynamic_sect->size() / sizeof(llvm::ELF::Elf64_Dyn);
11106f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
11116f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  for (size_t idx = 0; idx < numOfEntries; ++idx) {
11126f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
11136f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    llvm::ELF::Elf64_Sxword d_tag = 0x0;
11146f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    llvm::ELF::Elf64_Xword d_val = 0x0;
11156f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
11166f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    if (llvm::sys::isLittleEndianHost()) {
11176f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      d_tag = dynamic[idx].d_tag;
11186f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      d_val = dynamic[idx].d_un.d_val;
11196f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    } else {
11206f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      d_tag = mcld::bswap64(dynamic[idx].d_tag);
11216f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      d_val = mcld::bswap64(dynamic[idx].d_un.d_val);
11226f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    }
11236f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
11246f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    switch (d_tag) {
11256f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      case llvm::ELF::DT_SONAME:
11266f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines        assert(d_val < dynstr_sect->size());
11276f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines        pInput.setName(sys::fs::Path(dynstr + d_val).filename().native());
11286f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines        hasSOName = true;
11296f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines        break;
11306f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      case llvm::ELF::DT_NEEDED:
11316f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines        // TODO:
11326f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines        break;
11336f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      case llvm::ELF::DT_NULL:
11346f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      default:
11356f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines        break;
11366f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    }
11376f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  }
11386f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
11396f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // if there is no SONAME in .dynamic, then set it from input path
11406f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  if (!hasSOName)
11416f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    pInput.setName(pInput.path().filename().native());
11426f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
11436f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  pInput.memArea()->release(dynamic_region);
11446f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  pInput.memArea()->release(dynstr_region);
11456f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  return true;
11466f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
11476f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
1148