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>
16f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines#include <mcld/Target/GNUInfo.h>
17affc150dc44fab1911775a49636d0ce85333b634Zonr Chang#include <mcld/Support/MsgHandling.h>
18f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines#include <mcld/Support/MemoryArea.h>
1922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <mcld/Object/ObjectBuilder.h>
2022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
215460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <cstring>
225460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <llvm/ADT/StringRef.h>
2422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <llvm/ADT/Twine.h>
2522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <llvm/Support/ELF.h>
2622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <llvm/Support/Host.h>
2722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
286f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines#include <iostream>
295460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
306f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesusing namespace mcld;
315460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
3222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao//===----------------------------------------------------------------------===//
3322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao// ELFReader<32, true>
3422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao//===----------------------------------------------------------------------===//
3522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/// constructor
3622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei LiaoELFReader<32, true>::ELFReader(GNULDBackend& pBackend)
3722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  : ELFReaderIF(pBackend) {
3822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao}
3922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
4022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/// destructor
4122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei LiaoELFReader<32, true>::~ELFReader()
4222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao{
4322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao}
4422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
4522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/// isELF - is this a ELF file
46f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hinesbool ELFReader<32, true>::isELF(const void* pELFHeader) const
4722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao{
48f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  const llvm::ELF::Elf32_Ehdr* hdr =
49f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      reinterpret_cast<const llvm::ELF::Elf32_Ehdr*>(pELFHeader);
5022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  if (0 == memcmp(llvm::ELF::ElfMagic, hdr, 4))
5122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    return true;
5222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  return false;
5322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao}
5422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
5522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/// readRegularSection - read a regular section and create fragments.
5622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liaobool
5722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei LiaoELFReader<32, true>::readRegularSection(Input& pInput, SectionData& pSD) const
5822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao{
5922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  uint32_t offset = pInput.fileOffset() + pSD.getSection().offset();
6022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  uint32_t size = pSD.getSection().size();
6122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
6222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  Fragment* frag = IRBuilder::CreateRegion(pInput, offset, size);
6322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  ObjectBuilder::AppendFragment(*frag, pSD);
6422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  return true;
6522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao}
6622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
6722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/// readSymbols - read ELF symbols and create LDSymbol
6822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liaobool ELFReader<32, true>::readSymbols(Input& pInput,
69d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao                                      IRBuilder& pBuilder,
70f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines                                      llvm::StringRef pRegion,
7122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                                      const char* pStrTab) const
7222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao{
7322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // get number of symbols
7422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  size_t entsize = pRegion.size()/sizeof(llvm::ELF::Elf32_Sym);
7522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  const llvm::ELF::Elf32_Sym* symtab =
76f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      reinterpret_cast<const llvm::ELF::Elf32_Sym*>(pRegion.begin());
7722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
7822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  uint32_t st_name  = 0x0;
7922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  uint32_t st_value = 0x0;
8022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  uint32_t st_size  = 0x0;
8122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  uint8_t  st_info  = 0x0;
8222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  uint8_t  st_other = 0x0;
8322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  uint16_t st_shndx = 0x0;
8422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
8522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // skip the first NULL symbol
8622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  pInput.context()->addSymbol(LDSymbol::Null());
8722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
88f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  /// recording symbols added from DynObj to analyze weak alias
89f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  std::vector<AliasInfo> potential_aliases;
90f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  bool is_dyn_obj = (pInput.type()==Input::DynObj);
9122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  for (size_t idx = 1; idx < entsize; ++idx) {
9222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    st_info  = symtab[idx].st_info;
9322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    st_other = symtab[idx].st_other;
9422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
9521433dddd6366055d6b305675f4afca0b4592dcdStephen Hines    if (llvm::sys::IsLittleEndianHost) {
9622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      st_name  = symtab[idx].st_name;
9722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      st_value = symtab[idx].st_value;
9822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      st_size  = symtab[idx].st_size;
9922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      st_shndx = symtab[idx].st_shndx;
10022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    }
10122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    else {
102d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao      st_name  = mcld::bswap32(symtab[idx].st_name);
103d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao      st_value = mcld::bswap32(symtab[idx].st_value);
104d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao      st_size  = mcld::bswap32(symtab[idx].st_size);
105d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao      st_shndx = mcld::bswap16(symtab[idx].st_shndx);
10622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    }
10722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
10822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    // If the section should not be included, set the st_shndx SHN_UNDEF
10922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    // - A section in interrelated groups are not included.
11022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    if (pInput.type() == Input::Object &&
11122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao        st_shndx < llvm::ELF::SHN_LORESERVE &&
11222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao        st_shndx != llvm::ELF::SHN_UNDEF) {
11322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      if (NULL == pInput.context()->getSection(st_shndx))
11422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao        st_shndx = llvm::ELF::SHN_UNDEF;
11522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    }
11622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
11722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    // get ld_type
11822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    ResolveInfo::Type ld_type = getSymType(st_info, st_shndx);
11922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
12022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    // get ld_desc
12122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    ResolveInfo::Desc ld_desc = getSymDesc(st_shndx, pInput);
12222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
12322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    // get ld_binding
12422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    ResolveInfo::Binding ld_binding = getSymBinding((st_info >> 4), st_shndx, st_other);
12522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
12622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    // get ld_value - ld_value must be section relative.
12722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    uint64_t ld_value = getSymValue(st_value, st_shndx, pInput);
12822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
12922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    // get ld_vis
13022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    ResolveInfo::Visibility ld_vis = getSymVisibility(st_other);
13122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
132d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    // get section
133d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    LDSection* section = NULL;
134d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    if (st_shndx < llvm::ELF::SHN_LORESERVE) // including ABS and COMMON
135d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao      section = pInput.context()->getSection(st_shndx);
136d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao
13722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    // get ld_name
138d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    std::string ld_name;
13922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    if (ResolveInfo::Section == ld_type) {
14022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      // Section symbol's st_name is the section index.
14122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      assert(NULL != section && "get a invalid section");
142d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao      ld_name = section->name();
14322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    }
14422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    else {
145d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao      ld_name = std::string(pStrTab + st_name);
14622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    }
14722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
148f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    LDSymbol* psym = pBuilder.AddSymbol(pInput,
149f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines                                        ld_name,
150f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines                                        ld_type,
151f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines                                        ld_desc,
152f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines                                        ld_binding,
153f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines                                        st_size,
154f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines                                        ld_value,
155f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines                                        section,
156f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines                                        ld_vis);
157f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines
158f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    if (is_dyn_obj
159f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines        && NULL != psym
160f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines        && ResolveInfo::Undefined != ld_desc
161f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines        && (ResolveInfo::Global == ld_binding ||
162f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines            ResolveInfo::Weak == ld_binding)
163f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines        && ResolveInfo::Object == ld_type) {
164f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      AliasInfo p;
165f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      p.pt_alias = psym;
166f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      p.ld_binding = ld_binding;
167f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      p.ld_value = ld_value;
168f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      potential_aliases.push_back(p);
169f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    }
170f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
17122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  } // end of for loop
172f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
173f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  // analyze weak alias
174f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  // FIXME: it is better to let IRBuilder handle alias anlysis.
175f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  //        1. eliminate code duplication
176f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  //        2. easy to know if a symbol is from .so
177f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  //           (so that it may be a potential alias)
178f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  if (is_dyn_obj) {
179f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    // sort symbols by symbol value and then weak before strong
180f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    std::sort(potential_aliases.begin(), potential_aliases.end(), less);
181f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
182f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    // for each weak symbol, find out all its aliases, and
183f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    // then link them as a circular list in Module
184f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    std::vector<AliasInfo>::iterator sym_it, sym_e;
185f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    sym_e = potential_aliases.end();
186f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    for (sym_it = potential_aliases.begin(); sym_it!=sym_e; ++sym_it) {
187f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      if (ResolveInfo::Weak!=sym_it->ld_binding)
188f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        continue;
189f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
190f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      Module& pModule = pBuilder.getModule();
191f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      std::vector<AliasInfo>::iterator alias_it = sym_it+1;
192f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      while(alias_it!=sym_e) {
193f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines        if (sym_it->ld_value != alias_it->ld_value)
194f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines          break;
195f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
196f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines        if (sym_it + 1 == alias_it)
197f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines          pModule.CreateAliasList(*sym_it->pt_alias->resolveInfo());
198f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        pModule.addAlias(*alias_it->pt_alias->resolveInfo());
199f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        ++alias_it;
200f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      }
201f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
202f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      sym_it = alias_it - 1;
203f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    }// end of for loop
204f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  }
205f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
20622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  return true;
20722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao}
20822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
20922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao//===----------------------------------------------------------------------===//
21022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao// ELFReader::read relocations - read ELF rela and rel, and create Relocation
21122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao//===----------------------------------------------------------------------===//
21222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/// ELFReader::readRela - read ELF rela and create Relocation
21322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liaobool ELFReader<32, true>::readRela(Input& pInput,
21422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                                   LDSection& pSection,
215f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines                                   llvm::StringRef pRegion) const
21622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao{
21722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // get the number of rela
21822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  size_t entsize = pRegion.size() / sizeof(llvm::ELF::Elf32_Rela);
21922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  const llvm::ELF::Elf32_Rela* relaTab =
220f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      reinterpret_cast<const llvm::ELF::Elf32_Rela*>(pRegion.begin());
22122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
22222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  for (size_t idx=0; idx < entsize; ++idx) {
223f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    Relocation::Type r_type = 0x0;
224f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    uint32_t r_sym = 0x0;
22522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    uint32_t r_offset = 0x0;
22622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    int32_t  r_addend = 0;
227f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    if (!target().readRelocation(relaTab[idx], r_type, r_sym, r_offset, r_addend))
228f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      return false;
22922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
23022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    LDSymbol* symbol = pInput.context()->getSymbol(r_sym);
23122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    if (NULL == symbol) {
23222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      fatal(diag::err_cannot_read_symbol) << r_sym << pInput.path();
23322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    }
23422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
235d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    IRBuilder::AddRelocation(pSection, r_type, *symbol, r_offset, r_addend);
23622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  } // end of for
23722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  return true;
23822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao}
23922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
24022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/// readRel - read ELF rel and create Relocation
24122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liaobool ELFReader<32, true>::readRel(Input& pInput,
24222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                                  LDSection& pSection,
243f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines                                  llvm::StringRef pRegion) const
24422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao{
24522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // get the number of rel
24622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  size_t entsize = pRegion.size() / sizeof(llvm::ELF::Elf32_Rel);
24722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  const llvm::ELF::Elf32_Rel* relTab =
248f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      reinterpret_cast<const llvm::ELF::Elf32_Rel*>(pRegion.begin());
24922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
25022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  for (size_t idx=0; idx < entsize; ++idx) {
251f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    Relocation::Type r_type = 0x0;
252f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    uint32_t r_sym = 0x0;
25322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    uint32_t r_offset = 0x0;
25422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
255f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    if (!target().readRelocation(relTab[idx], r_type, r_sym, r_offset))
256f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      return false;
25722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
25822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    LDSymbol* symbol = pInput.context()->getSymbol(r_sym);
25922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    if (NULL == symbol) {
26022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      fatal(diag::err_cannot_read_symbol) << r_sym << pInput.path();
26122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    }
26222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
263d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    IRBuilder::AddRelocation(pSection, r_type, *symbol, r_offset);
26422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  } // end of for
26522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  return true;
26622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao}
26722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
26822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/// isMyEndian - is this ELF file in the same endian to me?
269f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hinesbool ELFReader<32, true>::isMyEndian(const void* pELFHeader) const
27022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao{
271f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  const llvm::ELF::Elf32_Ehdr* hdr =
272f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      reinterpret_cast<const llvm::ELF::Elf32_Ehdr*>(pELFHeader);
27322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
27422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  return (hdr->e_ident[llvm::ELF::EI_DATA] == llvm::ELF::ELFDATA2LSB);
27522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao}
27622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
27722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/// isMyMachine - is this ELF file generated for the same machine.
278f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hinesbool ELFReader<32, true>::isMyMachine(const void* pELFHeader) const
27922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao{
280f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  const llvm::ELF::Elf32_Ehdr* hdr =
281f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      reinterpret_cast<const llvm::ELF::Elf32_Ehdr*>(pELFHeader);
28222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
28321433dddd6366055d6b305675f4afca0b4592dcdStephen Hines  if (llvm::sys::IsLittleEndianHost)
284d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    return (hdr->e_machine == target().getInfo().machine());
285d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  return (mcld::bswap16(hdr->e_machine) == target().getInfo().machine());
28622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao}
28722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
28822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/// fileType - return the file type
289f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen HinesInput::Type ELFReader<32, true>::fileType(const void* pELFHeader) const
29022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao{
291f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  const llvm::ELF::Elf32_Ehdr* hdr =
292f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      reinterpret_cast<const llvm::ELF::Elf32_Ehdr*>(pELFHeader);
29322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  uint32_t type = 0x0;
29421433dddd6366055d6b305675f4afca0b4592dcdStephen Hines  if (llvm::sys::IsLittleEndianHost)
29522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    type = hdr->e_type;
29622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  else
297d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    type = mcld::bswap16(hdr->e_type);
29822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
29922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  switch(type) {
30022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  case llvm::ELF::ET_REL:
30122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    return Input::Object;
30222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  case llvm::ELF::ET_EXEC:
30322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    return Input::Exec;
30422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  case llvm::ELF::ET_DYN:
30522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    return Input::DynObj;
30622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  case llvm::ELF::ET_CORE:
30722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    return Input::CoreFile;
30822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  case llvm::ELF::ET_NONE:
30922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  default:
31022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    return Input::Unknown;
31122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  }
31222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao}
31322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
31422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/// readSectionHeaders - read ELF section header table and create LDSections
315f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hinesbool ELFReader<32, true>::readSectionHeaders(Input& pInput,
316f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines                                             const void* pELFHeader) const
31722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao{
318f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  const llvm::ELF::Elf32_Ehdr* ehdr =
319f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      reinterpret_cast<const llvm::ELF::Elf32_Ehdr*>(pELFHeader);
32022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
32122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  uint32_t shoff     = 0x0;
32222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  uint16_t shentsize = 0x0;
3236f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  uint32_t shnum     = 0x0;
3246f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  uint32_t shstrtab  = 0x0;
32522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
32621433dddd6366055d6b305675f4afca0b4592dcdStephen Hines  if (llvm::sys::IsLittleEndianHost) {
32722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    shoff     = ehdr->e_shoff;
32822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    shentsize = ehdr->e_shentsize;
32922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    shnum     = ehdr->e_shnum;
33022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    shstrtab  = ehdr->e_shstrndx;
33122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  }
33222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  else {
333d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    shoff     = mcld::bswap32(ehdr->e_shoff);
334d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    shentsize = mcld::bswap16(ehdr->e_shentsize);
335d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    shnum     = mcld::bswap16(ehdr->e_shnum);
336d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    shstrtab  = mcld::bswap16(ehdr->e_shstrndx);
33722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  }
33822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
33922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // If the file has no section header table, e_shoff holds zero.
34022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  if (0x0 == shoff)
34122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    return true;
34222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
343f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  const llvm::ELF::Elf32_Shdr *shdr = NULL;
344f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  llvm::StringRef shdr_region;
34522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  uint32_t sh_name      = 0x0;
34622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  uint32_t sh_type      = 0x0;
34722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  uint32_t sh_flags     = 0x0;
34822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  uint32_t sh_offset    = 0x0;
34922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  uint32_t sh_size      = 0x0;
35022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  uint32_t sh_link      = 0x0;
35122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  uint32_t sh_info      = 0x0;
35222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  uint32_t sh_addralign = 0x0;
35322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
3546f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // if shnum and shstrtab overflow, the actual values are in the 1st shdr
3556f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  if (shnum == llvm::ELF::SHN_UNDEF || shstrtab == llvm::ELF::SHN_XINDEX) {
3566f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    shdr_region = pInput.memArea()->request(pInput.fileOffset() + shoff,
3576f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                                            shentsize);
358f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    shdr = reinterpret_cast<const llvm::ELF::Elf32_Shdr*>(shdr_region.begin());
3596f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
36021433dddd6366055d6b305675f4afca0b4592dcdStephen Hines    if (llvm::sys::IsLittleEndianHost) {
3616f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      sh_size = shdr->sh_size;
3626f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      sh_link = shdr->sh_link;
3636f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    }
3646f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    else {
3656f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      sh_size = mcld::bswap32(shdr->sh_size);
3666f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      sh_link = mcld::bswap32(shdr->sh_link);
3676f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    }
3686f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
3696f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    if (shnum == llvm::ELF::SHN_UNDEF)
3706f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      shnum = sh_size;
3716f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    if (shstrtab == llvm::ELF::SHN_XINDEX)
3726f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      shstrtab = sh_link;
3736f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
3746f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    shoff += shentsize;
3756f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  }
3766f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
3776f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  shdr_region = pInput.memArea()->request(pInput.fileOffset() + shoff,
3786f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                                          shnum * shentsize);
379f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  const llvm::ELF::Elf32_Shdr* shdrTab =
380f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      reinterpret_cast<const llvm::ELF::Elf32_Shdr*>(shdr_region.begin());
3816f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
38222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // get .shstrtab first
3836f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  shdr = &shdrTab[shstrtab];
38421433dddd6366055d6b305675f4afca0b4592dcdStephen Hines  if (llvm::sys::IsLittleEndianHost) {
38522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    sh_offset = shdr->sh_offset;
38622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    sh_size   = shdr->sh_size;
38722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  }
38822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  else {
389d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    sh_offset = mcld::bswap32(shdr->sh_offset);
390d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    sh_size   = mcld::bswap32(shdr->sh_size);
39122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  }
39222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
393f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  llvm::StringRef sect_name_region = pInput.memArea()->request(
394f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      pInput.fileOffset() + sh_offset, sh_size);
395f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  const char* sect_name = sect_name_region.begin();
39622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
39722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  LinkInfoList link_info_list;
39822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
39922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // create all LDSections, including first NULL section.
40022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  for (size_t idx = 0; idx < shnum; ++idx) {
40121433dddd6366055d6b305675f4afca0b4592dcdStephen Hines    if (llvm::sys::IsLittleEndianHost) {
40222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      sh_name      = shdrTab[idx].sh_name;
40322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      sh_type      = shdrTab[idx].sh_type;
40422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      sh_flags     = shdrTab[idx].sh_flags;
40522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      sh_offset    = shdrTab[idx].sh_offset;
40622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      sh_size      = shdrTab[idx].sh_size;
40722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      sh_link      = shdrTab[idx].sh_link;
40822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      sh_info      = shdrTab[idx].sh_info;
40922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      sh_addralign = shdrTab[idx].sh_addralign;
41022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    }
41122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    else {
412d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao      sh_name      = mcld::bswap32(shdrTab[idx].sh_name);
413d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao      sh_type      = mcld::bswap32(shdrTab[idx].sh_type);
414d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao      sh_flags     = mcld::bswap32(shdrTab[idx].sh_flags);
415d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao      sh_offset    = mcld::bswap32(shdrTab[idx].sh_offset);
416d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao      sh_size      = mcld::bswap32(shdrTab[idx].sh_size);
417d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao      sh_link      = mcld::bswap32(shdrTab[idx].sh_link);
418d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao      sh_info      = mcld::bswap32(shdrTab[idx].sh_info);
419d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao      sh_addralign = mcld::bswap32(shdrTab[idx].sh_addralign);
42022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    }
42122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
42222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    LDSection* section = IRBuilder::CreateELFHeader(pInput,
42322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                                                    sect_name+sh_name,
42422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                                                    sh_type,
42522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                                                    sh_flags,
42622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                                                    sh_addralign);
42722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    section->setSize(sh_size);
42822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    section->setOffset(sh_offset);
42922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    section->setInfo(sh_info);
43022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
43122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    if (sh_link != 0x0 || sh_info != 0x0) {
43222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      LinkInfo link_info = { section, sh_link, sh_info };
43322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      link_info_list.push_back(link_info);
43422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    }
43522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  } // end of for
43622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
43722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // set up InfoLink
43822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  LinkInfoList::iterator info, infoEnd = link_info_list.end();
43922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  for (info = link_info_list.begin(); info != infoEnd; ++info) {
440f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    if (LDFileFormat::Relocation == info->section->kind())
44122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      info->section->setLink(pInput.context()->getSection(info->sh_info));
442f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    else
443f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      info->section->setLink(pInput.context()->getSection(info->sh_link));
44422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  }
44522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
44622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  return true;
44722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao}
44822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
44922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/// readSignature - read a symbol from the given Input and index in symtab
45022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/// This is used to get the signature of a group section.
45122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei LiaoResolveInfo* ELFReader<32, true>::readSignature(Input& pInput,
45222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                                                LDSection& pSymTab,
45322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                                                uint32_t pSymIdx) const
454affc150dc44fab1911775a49636d0ce85333b634Zonr Chang{
45522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  LDSection* symtab = &pSymTab;
45622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  LDSection* strtab = symtab->getLink();
45722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  assert(NULL != symtab && NULL != strtab);
45822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
45922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  uint32_t offset = pInput.fileOffset() + symtab->offset() +
46022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                      sizeof(llvm::ELF::Elf32_Sym) * pSymIdx;
461f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  llvm::StringRef symbol_region =
462f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      pInput.memArea()->request(offset, sizeof(llvm::ELF::Elf32_Sym));
463f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  const llvm::ELF::Elf32_Sym* entry =
464f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      reinterpret_cast<const llvm::ELF::Elf32_Sym*>(symbol_region.begin());
46522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
46622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  uint32_t st_name  = 0x0;
46722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  uint8_t  st_info  = 0x0;
46822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  uint8_t  st_other = 0x0;
46922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  uint16_t st_shndx = 0x0;
47022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  st_info  = entry->st_info;
47122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  st_other = entry->st_other;
47221433dddd6366055d6b305675f4afca0b4592dcdStephen Hines  if (llvm::sys::IsLittleEndianHost) {
47322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    st_name  = entry->st_name;
47422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    st_shndx = entry->st_shndx;
47522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  }
47622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  else {
477d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    st_name  = mcld::bswap32(entry->st_name);
478d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    st_shndx = mcld::bswap16(entry->st_shndx);
47922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  }
48022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
481f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  llvm::StringRef strtab_region = pInput.memArea()->request(
482f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      pInput.fileOffset() + strtab->offset(), strtab->size());
48322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
48422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // get ld_name
485f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  llvm::StringRef ld_name(strtab_region.begin() + st_name);
486affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
48722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  ResolveInfo* result = ResolveInfo::Create(ld_name);
48822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  result->setSource(pInput.type() == Input::DynObj);
48922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  result->setType(static_cast<ResolveInfo::Type>(st_info & 0xF));
49022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  result->setDesc(getSymDesc(st_shndx, pInput));
49122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  result->setBinding(getSymBinding((st_info >> 4), st_shndx, st_other));
49222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  result->setVisibility(getSymVisibility(st_other));
493affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
49422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  return result;
49522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao}
49622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
49722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/// readDynamic - read ELF .dynamic in input dynobj
49822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liaobool ELFReader<32, true>::readDynamic(Input& pInput) const
49922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao{
50022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  assert(pInput.type() == Input::DynObj);
50122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  const LDSection* dynamic_sect = pInput.context()->getSection(".dynamic");
50222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  if (NULL == dynamic_sect) {
50322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    fatal(diag::err_cannot_read_section) << ".dynamic";
50422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  }
50522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  const LDSection* dynstr_sect = dynamic_sect->getLink();
50622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  if (NULL == dynstr_sect) {
50722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    fatal(diag::err_cannot_read_section) << ".dynstr";
50822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  }
50922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
510f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  llvm::StringRef dynamic_region = pInput.memArea()->request(
511f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      pInput.fileOffset() + dynamic_sect->offset(), dynamic_sect->size());
51222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
513f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  llvm::StringRef dynstr_region = pInput.memArea()->request(
514f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      pInput.fileOffset() + dynstr_sect->offset(), dynstr_sect->size());
51522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
51622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  const llvm::ELF::Elf32_Dyn* dynamic =
517f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      reinterpret_cast<const llvm::ELF::Elf32_Dyn*>(dynamic_region.begin());
518f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  const char* dynstr = dynstr_region.begin();
51922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  bool hasSOName = false;
52022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  size_t numOfEntries = dynamic_sect->size() / sizeof(llvm::ELF::Elf32_Dyn);
52122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
52222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  for (size_t idx = 0; idx < numOfEntries; ++idx) {
52322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
52422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    llvm::ELF::Elf32_Sword d_tag = 0x0;
52522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    llvm::ELF::Elf32_Word d_val = 0x0;
52622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
52721433dddd6366055d6b305675f4afca0b4592dcdStephen Hines    if (llvm::sys::IsLittleEndianHost) {
52822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      d_tag = dynamic[idx].d_tag;
52922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      d_val = dynamic[idx].d_un.d_val;
53022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    } else {
531d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao      d_tag = mcld::bswap32(dynamic[idx].d_tag);
532d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao      d_val = mcld::bswap32(dynamic[idx].d_un.d_val);
53322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    }
53422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
53522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    switch (d_tag) {
53622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      case llvm::ELF::DT_SONAME:
53722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao        assert(d_val < dynstr_sect->size());
53822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao        pInput.setName(sys::fs::Path(dynstr + d_val).filename().native());
53922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao        hasSOName = true;
54022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao        break;
54122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      case llvm::ELF::DT_NEEDED:
54222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao        // TODO:
54322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao        break;
54422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      case llvm::ELF::DT_NULL:
54522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      default:
54622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao        break;
54722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    }
54822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  }
54922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
55022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // if there is no SONAME in .dynamic, then set it from input path
55122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  if (!hasSOName)
55222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    pInput.setName(pInput.path().filename().native());
55322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
554affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  return true;
555affc150dc44fab1911775a49636d0ce85333b634Zonr Chang}
55622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
5576f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines//===----------------------------------------------------------------------===//
5586f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// ELFReader<64, true>
5596f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines//===----------------------------------------------------------------------===//
5606f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines/// constructor
5616f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesELFReader<64, true>::ELFReader(GNULDBackend& pBackend)
5626f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  : ELFReaderIF(pBackend) {
5636f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
5646f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
5656f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines/// destructor
5666f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesELFReader<64, true>::~ELFReader()
5676f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{
5686f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
5696f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
5706f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines/// isELF - is this a ELF file
571f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hinesbool ELFReader<64, true>::isELF(const void* pELFHeader) const
5726f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{
573f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  const llvm::ELF::Elf64_Ehdr* hdr =
574f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      reinterpret_cast<const llvm::ELF::Elf64_Ehdr*>(pELFHeader);
5756f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  if (0 == memcmp(llvm::ELF::ElfMagic, hdr, 4))
5766f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    return true;
5776f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  return false;
5786f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
5796f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
5806f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines/// readRegularSection - read a regular section and create fragments.
5816f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesbool
5826f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesELFReader<64, true>::readRegularSection(Input& pInput, SectionData& pSD) const
5836f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{
5846f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  uint64_t offset = pInput.fileOffset() + pSD.getSection().offset();
5856f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  uint64_t size = pSD.getSection().size();
5866f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
5876f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  Fragment* frag = IRBuilder::CreateRegion(pInput, offset, size);
5886f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  ObjectBuilder::AppendFragment(*frag, pSD);
5896f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  return true;
5906f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
5916f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
5926f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines/// readSymbols - read ELF symbols and create LDSymbol
5936f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesbool ELFReader<64, true>::readSymbols(Input& pInput,
5946f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                                      IRBuilder& pBuilder,
595f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines                                      llvm::StringRef pRegion,
5966f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                                      const char* pStrTab) const
5976f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{
5986f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // get number of symbols
599f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  size_t entsize = pRegion.size() / sizeof(llvm::ELF::Elf64_Sym);
6006f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  const llvm::ELF::Elf64_Sym* symtab =
601f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      reinterpret_cast<const llvm::ELF::Elf64_Sym*>(pRegion.begin());
6026f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
6036f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  uint32_t st_name  = 0x0;
6046f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  uint64_t st_value = 0x0;
6056f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  uint64_t st_size  = 0x0;
6066f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  uint8_t  st_info  = 0x0;
6076f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  uint8_t  st_other = 0x0;
6086f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  uint16_t st_shndx = 0x0;
6096f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
6106f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // skip the first NULL symbol
6116f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  pInput.context()->addSymbol(LDSymbol::Null());
6126f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
613f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  /// recording symbols added from DynObj to analyze weak alias
614f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  std::vector<AliasInfo> potential_aliases;
615f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  bool is_dyn_obj = (pInput.type()==Input::DynObj);
6166f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  for (size_t idx = 1; idx < entsize; ++idx) {
6176f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    st_info  = symtab[idx].st_info;
6186f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    st_other = symtab[idx].st_other;
6196f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
62021433dddd6366055d6b305675f4afca0b4592dcdStephen Hines    if (llvm::sys::IsLittleEndianHost) {
6216f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      st_name  = symtab[idx].st_name;
6226f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      st_value = symtab[idx].st_value;
6236f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      st_size  = symtab[idx].st_size;
6246f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      st_shndx = symtab[idx].st_shndx;
6256f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    }
6266f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    else {
6276f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      st_name  = mcld::bswap32(symtab[idx].st_name);
6286f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      st_value = mcld::bswap64(symtab[idx].st_value);
6296f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      st_size  = mcld::bswap64(symtab[idx].st_size);
6306f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      st_shndx = mcld::bswap16(symtab[idx].st_shndx);
6316f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    }
6326f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
6336f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    // If the section should not be included, set the st_shndx SHN_UNDEF
6346f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    // - A section in interrelated groups are not included.
6356f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    if (pInput.type() == Input::Object &&
6366f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines        st_shndx < llvm::ELF::SHN_LORESERVE &&
6376f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines        st_shndx != llvm::ELF::SHN_UNDEF) {
6386f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      if (NULL == pInput.context()->getSection(st_shndx))
6396f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines        st_shndx = llvm::ELF::SHN_UNDEF;
6406f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    }
6416f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
6426f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    // get ld_type
6436f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    ResolveInfo::Type ld_type = getSymType(st_info, st_shndx);
6446f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
6456f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    // get ld_desc
6466f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    ResolveInfo::Desc ld_desc = getSymDesc(st_shndx, pInput);
6476f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
6486f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    // get ld_binding
6496f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    ResolveInfo::Binding ld_binding = getSymBinding((st_info >> 4), st_shndx, st_other);
6506f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
6516f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    // get ld_value - ld_value must be section relative.
6526f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    uint64_t ld_value = getSymValue(st_value, st_shndx, pInput);
6536f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
6546f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    // get ld_vis
6556f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    ResolveInfo::Visibility ld_vis = getSymVisibility(st_other);
6566f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
6576f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    // get section
6586f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    LDSection* section = NULL;
6596f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    if (st_shndx < llvm::ELF::SHN_LORESERVE) // including ABS and COMMON
6606f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      section = pInput.context()->getSection(st_shndx);
6616f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
6626f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    // get ld_name
6636f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    std::string ld_name;
6646f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    if (ResolveInfo::Section == ld_type) {
6656f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      // Section symbol's st_name is the section index.
6666f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      assert(NULL != section && "get a invalid section");
6676f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      ld_name = section->name();
6686f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    }
6696f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    else {
6706f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      ld_name = std::string(pStrTab + st_name);
6716f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    }
6726f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
673f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    LDSymbol* psym = pBuilder.AddSymbol(pInput,
674f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines                                        ld_name,
675f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines                                        ld_type,
676f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines                                        ld_desc,
677f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines                                        ld_binding,
678f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines                                        st_size,
679f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines                                        ld_value,
680f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines                                        section,
681f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines                                        ld_vis);
682f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines
683f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    if (is_dyn_obj
684f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines        && NULL != psym
685f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines        && ResolveInfo::Undefined != ld_desc
686f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines        && (ResolveInfo::Global == ld_binding ||
687f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines            ResolveInfo::Weak == ld_binding)
688f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines        && ResolveInfo::Object == ld_type ) {
689f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      AliasInfo p;
690f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      p.pt_alias = psym;
691f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      p.ld_binding = ld_binding;
692f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      p.ld_value = ld_value;
693f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      potential_aliases.push_back(p);
694f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    }
695f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
6966f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  } // end of for loop
697f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
698f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  // analyze weak alias here
699f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  if (is_dyn_obj) {
700f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    // sort symbols by symbol value and then weak before strong
701f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    std::sort(potential_aliases.begin(), potential_aliases.end(), less);
702f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
703f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    // for each weak symbol, find out all its aliases, and
704f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    // then link them as a circular list in Module
705f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    std::vector<AliasInfo>::iterator sym_it, sym_e;
706f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    sym_e = potential_aliases.end();
707f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    for (sym_it = potential_aliases.begin(); sym_it!=sym_e; ++sym_it) {
708f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      if (ResolveInfo::Weak!=sym_it->ld_binding)
709f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        continue;
710f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
711f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      Module& pModule = pBuilder.getModule();
712f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      std::vector<AliasInfo>::iterator alias_it = sym_it+1;
713f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      while(alias_it!=sym_e) {
714f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines        if (sym_it->ld_value != alias_it->ld_value)
715f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines          break;
716f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
717f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines        if (sym_it + 1 == alias_it)
718f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines          pModule.CreateAliasList(*sym_it->pt_alias->resolveInfo());
719f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        pModule.addAlias(*alias_it->pt_alias->resolveInfo());
720f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        ++alias_it;
721f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      }
722f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
723f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      sym_it = alias_it - 1;
724f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    }// end of for loop
725f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  }
7266f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  return true;
7276f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
7286f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
7296f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines//===----------------------------------------------------------------------===//
7306f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// ELFReader::read relocations - read ELF rela and rel, and create Relocation
7316f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines//===----------------------------------------------------------------------===//
7326f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines/// ELFReader::readRela - read ELF rela and create Relocation
7336f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesbool ELFReader<64, true>::readRela(Input& pInput,
7346f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                                   LDSection& pSection,
735f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines                                   llvm::StringRef pRegion) const
7366f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{
7376f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // get the number of rela
7386f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  size_t entsize = pRegion.size() / sizeof(llvm::ELF::Elf64_Rela);
7396f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  const llvm::ELF::Elf64_Rela* relaTab =
740f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      reinterpret_cast<const llvm::ELF::Elf64_Rela*>(pRegion.begin());
7416f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
7426f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  for (size_t idx=0; idx < entsize; ++idx) {
743f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    Relocation::Type r_type = 0x0;
744f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    uint32_t r_sym = 0x0;
7456f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    uint64_t r_offset = 0x0;
7466f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    int64_t  r_addend = 0;
747f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    if (!target().readRelocation(relaTab[idx],
748f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines                                 r_type, r_sym, r_offset, r_addend)) {
749f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      return false;
7506f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    }
7516f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
7526f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    LDSymbol* symbol = pInput.context()->getSymbol(r_sym);
7536f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    if (NULL == symbol) {
7546f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      fatal(diag::err_cannot_read_symbol) << r_sym << pInput.path();
7556f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    }
7566f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
7576f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    IRBuilder::AddRelocation(pSection, r_type, *symbol, r_offset, r_addend);
7586f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  } // end of for
7596f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  return true;
7606f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
7616f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
7626f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines/// readRel - read ELF rel and create Relocation
7636f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesbool ELFReader<64, true>::readRel(Input& pInput,
7646f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                                  LDSection& pSection,
765f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines                                  llvm::StringRef pRegion) const
7666f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{
7676f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // get the number of rel
7686f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  size_t entsize = pRegion.size() / sizeof(llvm::ELF::Elf64_Rel);
7696f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  const llvm::ELF::Elf64_Rel* relTab =
770f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      reinterpret_cast<const llvm::ELF::Elf64_Rel*>(pRegion.begin());
7716f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
7726f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  for (size_t idx=0; idx < entsize; ++idx) {
773f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    Relocation::Type r_type = 0x0;
774f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    uint32_t r_sym = 0x0;
7756f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    uint64_t r_offset = 0x0;
776f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    if (!target().readRelocation(relTab[idx], r_type, r_sym, r_offset))
777f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      return false;
7786f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
7796f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    LDSymbol* symbol = pInput.context()->getSymbol(r_sym);
7806f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    if (NULL == symbol) {
7816f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      fatal(diag::err_cannot_read_symbol) << r_sym << pInput.path();
7826f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    }
7836f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
7846f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    IRBuilder::AddRelocation(pSection, r_type, *symbol, r_offset);
7856f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  } // end of for
7866f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  return true;
7876f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
7886f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
7896f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines/// isMyEndian - is this ELF file in the same endian to me?
790f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hinesbool ELFReader<64, true>::isMyEndian(const void* pELFHeader) const
7916f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{
792f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  const llvm::ELF::Elf64_Ehdr* hdr =
793f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      reinterpret_cast<const llvm::ELF::Elf64_Ehdr*>(pELFHeader);
7946f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
7956f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  return (hdr->e_ident[llvm::ELF::EI_DATA] == llvm::ELF::ELFDATA2LSB);
7966f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
7976f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
7986f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines/// isMyMachine - is this ELF file generated for the same machine.
799f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hinesbool ELFReader<64, true>::isMyMachine(const void* pELFHeader) const
8006f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{
801f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  const llvm::ELF::Elf64_Ehdr* hdr =
802f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      reinterpret_cast<const llvm::ELF::Elf64_Ehdr*>(pELFHeader);
8036f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
80421433dddd6366055d6b305675f4afca0b4592dcdStephen Hines  if (llvm::sys::IsLittleEndianHost)
8056f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    return (hdr->e_machine == target().getInfo().machine());
8066f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  return (mcld::bswap16(hdr->e_machine) == target().getInfo().machine());
8076f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
8086f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
8096f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines/// fileType - return the file type
810f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen HinesInput::Type ELFReader<64, true>::fileType(const void* pELFHeader) const
8116f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{
812f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  const llvm::ELF::Elf64_Ehdr* hdr =
813f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      reinterpret_cast<const llvm::ELF::Elf64_Ehdr*>(pELFHeader);
8146f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  uint32_t type = 0x0;
81521433dddd6366055d6b305675f4afca0b4592dcdStephen Hines  if (llvm::sys::IsLittleEndianHost)
8166f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    type = hdr->e_type;
8176f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  else
8186f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    type = mcld::bswap16(hdr->e_type);
8196f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
8206f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  switch(type) {
8216f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  case llvm::ELF::ET_REL:
8226f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    return Input::Object;
8236f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  case llvm::ELF::ET_EXEC:
8246f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    return Input::Exec;
8256f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  case llvm::ELF::ET_DYN:
8266f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    return Input::DynObj;
8276f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  case llvm::ELF::ET_CORE:
8286f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    return Input::CoreFile;
8296f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  case llvm::ELF::ET_NONE:
8306f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  default:
8316f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    return Input::Unknown;
8326f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  }
8336f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
8346f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
8356f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines/// readSectionHeaders - read ELF section header table and create LDSections
836f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hinesbool ELFReader<64, true>::readSectionHeaders(Input& pInput,
837f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines                                             const void* pELFHeader) const
8386f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{
839f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  const llvm::ELF::Elf64_Ehdr* ehdr =
840f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      reinterpret_cast<const llvm::ELF::Elf64_Ehdr*>(pELFHeader);
8416f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
8426f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  uint64_t shoff     = 0x0;
8436f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  uint16_t shentsize = 0x0;
8446f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  uint32_t shnum     = 0x0;
8456f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  uint32_t shstrtab  = 0x0;
8466f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
84721433dddd6366055d6b305675f4afca0b4592dcdStephen Hines  if (llvm::sys::IsLittleEndianHost) {
8486f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    shoff     = ehdr->e_shoff;
8496f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    shentsize = ehdr->e_shentsize;
8506f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    shnum     = ehdr->e_shnum;
8516f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    shstrtab  = ehdr->e_shstrndx;
8526f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  }
8536f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  else {
8546f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    shoff     = mcld::bswap64(ehdr->e_shoff);
8556f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    shentsize = mcld::bswap16(ehdr->e_shentsize);
8566f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    shnum     = mcld::bswap16(ehdr->e_shnum);
8576f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    shstrtab  = mcld::bswap16(ehdr->e_shstrndx);
8586f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  }
8596f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
8606f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // If the file has no section header table, e_shoff holds zero.
8616f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  if (0x0 == shoff)
8626f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    return true;
8636f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
864f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  const llvm::ELF::Elf64_Shdr *shdr = NULL;
865f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  llvm::StringRef shdr_region;
8666f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  uint32_t sh_name      = 0x0;
8676f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  uint32_t sh_type      = 0x0;
8686f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  uint64_t sh_flags     = 0x0;
8696f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  uint64_t sh_offset    = 0x0;
8706f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  uint64_t sh_size      = 0x0;
8716f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  uint32_t sh_link      = 0x0;
8726f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  uint32_t sh_info      = 0x0;
8736f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  uint64_t sh_addralign = 0x0;
8746f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
8756f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // if shnum and shstrtab overflow, the actual values are in the 1st shdr
8766f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  if (shnum == llvm::ELF::SHN_UNDEF || shstrtab == llvm::ELF::SHN_XINDEX) {
8776f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    shdr_region = pInput.memArea()->request(pInput.fileOffset() + shoff,
8786f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                                            shentsize);
879f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    shdr = reinterpret_cast<const llvm::ELF::Elf64_Shdr*>(shdr_region.begin());
8806f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
88121433dddd6366055d6b305675f4afca0b4592dcdStephen Hines    if (llvm::sys::IsLittleEndianHost) {
8826f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      sh_size = shdr->sh_size;
8836f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      sh_link = shdr->sh_link;
8846f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    }
8856f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    else {
8866f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      sh_size = mcld::bswap64(shdr->sh_size);
8876f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      sh_link = mcld::bswap32(shdr->sh_link);
8886f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    }
8896f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
8906f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    if (shnum == llvm::ELF::SHN_UNDEF)
8916f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      shnum = sh_size;
8926f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    if (shstrtab == llvm::ELF::SHN_XINDEX)
8936f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      shstrtab = sh_link;
8946f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
8956f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    shoff += shentsize;
8966f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  }
8976f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
8986f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  shdr_region = pInput.memArea()->request(pInput.fileOffset() + shoff,
8996f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                                          shnum * shentsize);
900f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  const llvm::ELF::Elf64_Shdr* shdrTab =
901f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      reinterpret_cast<const llvm::ELF::Elf64_Shdr*>(shdr_region.begin());
9026f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
9036f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // get .shstrtab first
9046f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  shdr = &shdrTab[shstrtab];
90521433dddd6366055d6b305675f4afca0b4592dcdStephen Hines  if (llvm::sys::IsLittleEndianHost) {
9066f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    sh_offset = shdr->sh_offset;
9076f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    sh_size   = shdr->sh_size;
9086f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  }
9096f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  else {
9106f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    sh_offset = mcld::bswap64(shdr->sh_offset);
9116f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    sh_size   = mcld::bswap64(shdr->sh_size);
9126f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  }
9136f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
914f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  llvm::StringRef sect_name_region = pInput.memArea()->request(
915f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      pInput.fileOffset() + sh_offset, sh_size);
916f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  const char* sect_name = sect_name_region.begin();
9176f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
9186f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  LinkInfoList link_info_list;
9196f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
9206f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // create all LDSections, including first NULL section.
9216f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  for (size_t idx = 0; idx < shnum; ++idx) {
92221433dddd6366055d6b305675f4afca0b4592dcdStephen Hines    if (llvm::sys::IsLittleEndianHost) {
9236f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      sh_name      = shdrTab[idx].sh_name;
9246f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      sh_type      = shdrTab[idx].sh_type;
9256f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      sh_flags     = shdrTab[idx].sh_flags;
9266f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      sh_offset    = shdrTab[idx].sh_offset;
9276f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      sh_size      = shdrTab[idx].sh_size;
9286f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      sh_link      = shdrTab[idx].sh_link;
9296f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      sh_info      = shdrTab[idx].sh_info;
9306f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      sh_addralign = shdrTab[idx].sh_addralign;
9316f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    }
9326f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    else {
9336f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      sh_name      = mcld::bswap32(shdrTab[idx].sh_name);
9346f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      sh_type      = mcld::bswap32(shdrTab[idx].sh_type);
9356f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      sh_flags     = mcld::bswap64(shdrTab[idx].sh_flags);
9366f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      sh_offset    = mcld::bswap64(shdrTab[idx].sh_offset);
9376f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      sh_size      = mcld::bswap64(shdrTab[idx].sh_size);
9386f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      sh_link      = mcld::bswap32(shdrTab[idx].sh_link);
9396f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      sh_info      = mcld::bswap32(shdrTab[idx].sh_info);
9406f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      sh_addralign = mcld::bswap64(shdrTab[idx].sh_addralign);
9416f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    }
9426f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
9436f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    LDSection* section = IRBuilder::CreateELFHeader(pInput,
9446f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                                                    sect_name+sh_name,
9456f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                                                    sh_type,
9466f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                                                    sh_flags,
9476f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                                                    sh_addralign);
9486f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    section->setSize(sh_size);
9496f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    section->setOffset(sh_offset);
9506f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    section->setInfo(sh_info);
9516f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
9526f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    if (sh_link != 0x0 || sh_info != 0x0) {
9536f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      LinkInfo link_info = { section, sh_link, sh_info };
9546f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      link_info_list.push_back(link_info);
9556f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    }
9566f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  } // end of for
9576f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
9586f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // set up InfoLink
9596f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  LinkInfoList::iterator info, infoEnd = link_info_list.end();
9606f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  for (info = link_info_list.begin(); info != infoEnd; ++info) {
961f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    if (LDFileFormat::Relocation == info->section->kind())
9626f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      info->section->setLink(pInput.context()->getSection(info->sh_info));
963f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    else
964f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      info->section->setLink(pInput.context()->getSection(info->sh_link));
9656f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  }
9666f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
9676f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  return true;
9686f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
9696f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
9706f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines/// readSignature - read a symbol from the given Input and index in symtab
9716f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines/// This is used to get the signature of a group section.
9726f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesResolveInfo* ELFReader<64, true>::readSignature(Input& pInput,
9736f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                                                LDSection& pSymTab,
9746f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                                                uint32_t pSymIdx) const
9756f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{
9766f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  LDSection* symtab = &pSymTab;
9776f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  LDSection* strtab = symtab->getLink();
9786f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  assert(NULL != symtab && NULL != strtab);
9796f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
9806f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  uint64_t offset = pInput.fileOffset() + symtab->offset() +
9816f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                      sizeof(llvm::ELF::Elf64_Sym) * pSymIdx;
982f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  llvm::StringRef symbol_region =
983f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      pInput.memArea()->request(offset, sizeof(llvm::ELF::Elf64_Sym));
984f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  const llvm::ELF::Elf64_Sym* entry =
985f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      reinterpret_cast<const llvm::ELF::Elf64_Sym*>(symbol_region.begin());
9866f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
9876f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  uint32_t st_name  = 0x0;
9886f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  uint8_t  st_info  = 0x0;
9896f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  uint8_t  st_other = 0x0;
9906f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  uint16_t st_shndx = 0x0;
9916f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  st_info  = entry->st_info;
9926f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  st_other = entry->st_other;
99321433dddd6366055d6b305675f4afca0b4592dcdStephen Hines  if (llvm::sys::IsLittleEndianHost) {
9946f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    st_name  = entry->st_name;
9956f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    st_shndx = entry->st_shndx;
9966f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  }
9976f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  else {
9986f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    st_name  = mcld::bswap32(entry->st_name);
9996f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    st_shndx = mcld::bswap16(entry->st_shndx);
10006f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  }
10016f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
1002f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  llvm::StringRef strtab_region = pInput.memArea()->request(
1003f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      pInput.fileOffset() + strtab->offset(), strtab->size());
10046f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
10056f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // get ld_name
1006f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  llvm::StringRef ld_name(strtab_region.begin() + st_name);
10076f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
10086f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  ResolveInfo* result = ResolveInfo::Create(ld_name);
10096f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  result->setSource(pInput.type() == Input::DynObj);
10106f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  result->setType(static_cast<ResolveInfo::Type>(st_info & 0xF));
10116f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  result->setDesc(getSymDesc(st_shndx, pInput));
10126f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  result->setBinding(getSymBinding((st_info >> 4), st_shndx, st_other));
10136f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  result->setVisibility(getSymVisibility(st_other));
10146f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
10156f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  return result;
10166f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
10176f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
10186f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines/// readDynamic - read ELF .dynamic in input dynobj
10196f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesbool ELFReader<64, true>::readDynamic(Input& pInput) const
10206f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{
10216f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  assert(pInput.type() == Input::DynObj);
10226f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  const LDSection* dynamic_sect = pInput.context()->getSection(".dynamic");
10236f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  if (NULL == dynamic_sect) {
10246f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    fatal(diag::err_cannot_read_section) << ".dynamic";
10256f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  }
10266f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  const LDSection* dynstr_sect = dynamic_sect->getLink();
10276f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  if (NULL == dynstr_sect) {
10286f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    fatal(diag::err_cannot_read_section) << ".dynstr";
10296f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  }
10306f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
1031f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  llvm::StringRef dynamic_region = pInput.memArea()->request(
1032f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      pInput.fileOffset() + dynamic_sect->offset(), dynamic_sect->size());
10336f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
1034f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  llvm::StringRef dynstr_region = pInput.memArea()->request(
1035f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      pInput.fileOffset() + dynstr_sect->offset(), dynstr_sect->size());
10366f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
10376f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  const llvm::ELF::Elf64_Dyn* dynamic =
1038f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      reinterpret_cast<const llvm::ELF::Elf64_Dyn*>(dynamic_region.begin());
1039f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  const char* dynstr = dynstr_region.begin();
10406f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  bool hasSOName = false;
10416f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  size_t numOfEntries = dynamic_sect->size() / sizeof(llvm::ELF::Elf64_Dyn);
10426f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
10436f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  for (size_t idx = 0; idx < numOfEntries; ++idx) {
10446f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
10456f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    llvm::ELF::Elf64_Sxword d_tag = 0x0;
10466f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    llvm::ELF::Elf64_Xword d_val = 0x0;
10476f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
104821433dddd6366055d6b305675f4afca0b4592dcdStephen Hines    if (llvm::sys::IsLittleEndianHost) {
10496f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      d_tag = dynamic[idx].d_tag;
10506f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      d_val = dynamic[idx].d_un.d_val;
10516f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    } else {
10526f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      d_tag = mcld::bswap64(dynamic[idx].d_tag);
10536f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      d_val = mcld::bswap64(dynamic[idx].d_un.d_val);
10546f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    }
10556f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
10566f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    switch (d_tag) {
10576f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      case llvm::ELF::DT_SONAME:
10586f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines        assert(d_val < dynstr_sect->size());
10596f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines        pInput.setName(sys::fs::Path(dynstr + d_val).filename().native());
10606f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines        hasSOName = true;
10616f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines        break;
10626f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      case llvm::ELF::DT_NEEDED:
10636f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines        // TODO:
10646f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines        break;
10656f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      case llvm::ELF::DT_NULL:
10666f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      default:
10676f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines        break;
10686f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    }
10696f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  }
10706f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
10716f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // if there is no SONAME in .dynamic, then set it from input path
10726f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  if (!hasSOName)
10736f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    pInput.setName(pInput.path().filename().native());
10746f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
10756f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  return true;
10766f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
1077