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//===----------------------------------------------------------------------===//
937b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/LD/ELFReader.h"
1037b74a387bb3993387029859c2d9d051c41c724eStephen Hines
1137b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/IRBuilder.h"
1237b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Fragment/FillFragment.h"
1337b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/LD/EhFrame.h"
1437b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/LD/LDContext.h"
1537b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/LD/SectionData.h"
1637b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Object/ObjectBuilder.h"
1737b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Support/MemoryArea.h"
1837b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Support/MsgHandling.h"
1937b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Target/GNUInfo.h"
2037b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Target/GNULDBackend.h"
215460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <llvm/ADT/StringRef.h>
2322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <llvm/ADT/Twine.h>
2422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <llvm/Support/ELF.h>
2522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <llvm/Support/Host.h>
2622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
276f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines#include <iostream>
285460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2937b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include <cstring>
3037b74a387bb3993387029859c2d9d051c41c724eStephen Hines
3137b74a387bb3993387029859c2d9d051c41c724eStephen Hinesnamespace mcld {
325460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
3322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao//===----------------------------------------------------------------------===//
3422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao// ELFReader<32, true>
3522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao//===----------------------------------------------------------------------===//
3622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/// constructor
3737b74a387bb3993387029859c2d9d051c41c724eStephen HinesELFReader<32, true>::ELFReader(GNULDBackend& pBackend) : ELFReaderIF(pBackend) {
3822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao}
3922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
4022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/// destructor
4137b74a387bb3993387029859c2d9d051c41c724eStephen HinesELFReader<32, true>::~ELFReader() {
4222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao}
4322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
4422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/// isELF - is this a ELF file
4537b74a387bb3993387029859c2d9d051c41c724eStephen Hinesbool ELFReader<32, true>::isELF(const void* pELFHeader) const {
46f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  const llvm::ELF::Elf32_Ehdr* hdr =
47f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      reinterpret_cast<const llvm::ELF::Elf32_Ehdr*>(pELFHeader);
4837b74a387bb3993387029859c2d9d051c41c724eStephen Hines  if (memcmp(llvm::ELF::ElfMagic, hdr, 4) == 0)
4922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    return true;
5022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  return false;
5122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao}
5222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
5322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/// readRegularSection - read a regular section and create fragments.
5437b74a387bb3993387029859c2d9d051c41c724eStephen Hinesbool ELFReader<32, true>::readRegularSection(Input& pInput,
5537b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                             SectionData& pSD) const {
5622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  uint32_t offset = pInput.fileOffset() + pSD.getSection().offset();
5722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  uint32_t size = pSD.getSection().size();
5822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
5922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  Fragment* frag = IRBuilder::CreateRegion(pInput, offset, size);
6022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  ObjectBuilder::AppendFragment(*frag, pSD);
6122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  return true;
6222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao}
6322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
6422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/// readSymbols - read ELF symbols and create LDSymbol
6522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liaobool ELFReader<32, true>::readSymbols(Input& pInput,
66d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao                                      IRBuilder& pBuilder,
67f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines                                      llvm::StringRef pRegion,
6837b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                      const char* pStrTab) const {
6922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // get number of symbols
7037b74a387bb3993387029859c2d9d051c41c724eStephen Hines  size_t entsize = pRegion.size() / sizeof(llvm::ELF::Elf32_Sym);
7122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  const llvm::ELF::Elf32_Sym* symtab =
72f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      reinterpret_cast<const llvm::ELF::Elf32_Sym*>(pRegion.begin());
7322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
7437b74a387bb3993387029859c2d9d051c41c724eStephen Hines  uint32_t st_name = 0x0;
7522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  uint32_t st_value = 0x0;
7637b74a387bb3993387029859c2d9d051c41c724eStephen Hines  uint32_t st_size = 0x0;
7737b74a387bb3993387029859c2d9d051c41c724eStephen Hines  uint8_t st_info = 0x0;
7837b74a387bb3993387029859c2d9d051c41c724eStephen Hines  uint8_t st_other = 0x0;
7922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  uint16_t st_shndx = 0x0;
8022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
8122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // skip the first NULL symbol
8222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  pInput.context()->addSymbol(LDSymbol::Null());
8322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
84f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  /// recording symbols added from DynObj to analyze weak alias
85f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  std::vector<AliasInfo> potential_aliases;
8637b74a387bb3993387029859c2d9d051c41c724eStephen Hines  bool is_dyn_obj = (pInput.type() == Input::DynObj);
8722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  for (size_t idx = 1; idx < entsize; ++idx) {
8837b74a387bb3993387029859c2d9d051c41c724eStephen Hines    st_info = symtab[idx].st_info;
8922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    st_other = symtab[idx].st_other;
9022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
9121433dddd6366055d6b305675f4afca0b4592dcdStephen Hines    if (llvm::sys::IsLittleEndianHost) {
9237b74a387bb3993387029859c2d9d051c41c724eStephen Hines      st_name = symtab[idx].st_name;
9322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      st_value = symtab[idx].st_value;
9437b74a387bb3993387029859c2d9d051c41c724eStephen Hines      st_size = symtab[idx].st_size;
9522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      st_shndx = symtab[idx].st_shndx;
9637b74a387bb3993387029859c2d9d051c41c724eStephen Hines    } else {
9737b74a387bb3993387029859c2d9d051c41c724eStephen Hines      st_name = mcld::bswap32(symtab[idx].st_name);
98d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao      st_value = mcld::bswap32(symtab[idx].st_value);
9937b74a387bb3993387029859c2d9d051c41c724eStephen Hines      st_size = mcld::bswap32(symtab[idx].st_size);
100d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao      st_shndx = mcld::bswap16(symtab[idx].st_shndx);
10122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    }
10222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
10322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    // If the section should not be included, set the st_shndx SHN_UNDEF
10422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    // - A section in interrelated groups are not included.
10537b74a387bb3993387029859c2d9d051c41c724eStephen Hines    if (pInput.type() == Input::Object && st_shndx < llvm::ELF::SHN_LORESERVE &&
10622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao        st_shndx != llvm::ELF::SHN_UNDEF) {
10737b74a387bb3993387029859c2d9d051c41c724eStephen Hines      if (pInput.context()->getSection(st_shndx) == NULL)
10822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao        st_shndx = llvm::ELF::SHN_UNDEF;
10922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    }
11022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
11122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    // get ld_type
11222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    ResolveInfo::Type ld_type = getSymType(st_info, st_shndx);
11322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
11422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    // get ld_desc
11522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    ResolveInfo::Desc ld_desc = getSymDesc(st_shndx, pInput);
11622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
11722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    // get ld_binding
11837b74a387bb3993387029859c2d9d051c41c724eStephen Hines    ResolveInfo::Binding ld_binding =
11937b74a387bb3993387029859c2d9d051c41c724eStephen Hines        getSymBinding((st_info >> 4), st_shndx, st_other);
12022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
12122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    // get ld_value - ld_value must be section relative.
12222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    uint64_t ld_value = getSymValue(st_value, st_shndx, pInput);
12322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
12422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    // get ld_vis
12522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    ResolveInfo::Visibility ld_vis = getSymVisibility(st_other);
12622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
127d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    // get section
128d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    LDSection* section = NULL;
12937b74a387bb3993387029859c2d9d051c41c724eStephen Hines    if (st_shndx < llvm::ELF::SHN_LORESERVE)  // including ABS and COMMON
130d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao      section = pInput.context()->getSection(st_shndx);
131d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao
13222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    // get ld_name
133d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    std::string ld_name;
13422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    if (ResolveInfo::Section == ld_type) {
13522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      // Section symbol's st_name is the section index.
13637b74a387bb3993387029859c2d9d051c41c724eStephen Hines      assert(section != NULL && "get a invalid section");
137d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao      ld_name = section->name();
13837b74a387bb3993387029859c2d9d051c41c724eStephen Hines    } else {
139d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao      ld_name = std::string(pStrTab + st_name);
14022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    }
14122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
142f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    LDSymbol* psym = pBuilder.AddSymbol(pInput,
143f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines                                        ld_name,
144f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines                                        ld_type,
145f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines                                        ld_desc,
146f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines                                        ld_binding,
147f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines                                        st_size,
148f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines                                        ld_value,
149f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines                                        section,
150f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines                                        ld_vis);
151f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines
15237b74a387bb3993387029859c2d9d051c41c724eStephen Hines    if (is_dyn_obj && psym != NULL && ResolveInfo::Undefined != ld_desc &&
15337b74a387bb3993387029859c2d9d051c41c724eStephen Hines        (ResolveInfo::Global == ld_binding ||
15437b74a387bb3993387029859c2d9d051c41c724eStephen Hines         ResolveInfo::Weak == ld_binding) &&
15537b74a387bb3993387029859c2d9d051c41c724eStephen Hines        ResolveInfo::Object == ld_type) {
156f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      AliasInfo p;
157f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      p.pt_alias = psym;
158f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      p.ld_binding = ld_binding;
159f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      p.ld_value = ld_value;
160f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      potential_aliases.push_back(p);
161f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    }
16237b74a387bb3993387029859c2d9d051c41c724eStephen Hines  }  // end of for loop
163f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
164f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  // analyze weak alias
165f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  // FIXME: it is better to let IRBuilder handle alias anlysis.
166f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  //        1. eliminate code duplication
167f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  //        2. easy to know if a symbol is from .so
168f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  //           (so that it may be a potential alias)
169f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  if (is_dyn_obj) {
170f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    // sort symbols by symbol value and then weak before strong
171f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    std::sort(potential_aliases.begin(), potential_aliases.end(), less);
172f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
173f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    // for each weak symbol, find out all its aliases, and
174f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    // then link them as a circular list in Module
175f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    std::vector<AliasInfo>::iterator sym_it, sym_e;
176f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    sym_e = potential_aliases.end();
17737b74a387bb3993387029859c2d9d051c41c724eStephen Hines    for (sym_it = potential_aliases.begin(); sym_it != sym_e; ++sym_it) {
17837b74a387bb3993387029859c2d9d051c41c724eStephen Hines      if (ResolveInfo::Weak != sym_it->ld_binding)
179f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        continue;
180f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
181f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      Module& pModule = pBuilder.getModule();
18237b74a387bb3993387029859c2d9d051c41c724eStephen Hines      std::vector<AliasInfo>::iterator alias_it = sym_it + 1;
18337b74a387bb3993387029859c2d9d051c41c724eStephen Hines      while (alias_it != sym_e) {
184f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines        if (sym_it->ld_value != alias_it->ld_value)
185f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines          break;
186f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
187f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines        if (sym_it + 1 == alias_it)
188f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines          pModule.CreateAliasList(*sym_it->pt_alias->resolveInfo());
189f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        pModule.addAlias(*alias_it->pt_alias->resolveInfo());
190f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        ++alias_it;
191f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      }
192f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
193f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      sym_it = alias_it - 1;
19437b74a387bb3993387029859c2d9d051c41c724eStephen Hines    }  // end of for loop
195f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  }
196f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
19722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  return true;
19822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao}
19922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
20022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao//===----------------------------------------------------------------------===//
20122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao// ELFReader::read relocations - read ELF rela and rel, and create Relocation
20222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao//===----------------------------------------------------------------------===//
20322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/// ELFReader::readRela - read ELF rela and create Relocation
20422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liaobool ELFReader<32, true>::readRela(Input& pInput,
20522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                                   LDSection& pSection,
20637b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                   llvm::StringRef pRegion) const {
20722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // get the number of rela
20822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  size_t entsize = pRegion.size() / sizeof(llvm::ELF::Elf32_Rela);
20922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  const llvm::ELF::Elf32_Rela* relaTab =
210f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      reinterpret_cast<const llvm::ELF::Elf32_Rela*>(pRegion.begin());
21122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
21237b74a387bb3993387029859c2d9d051c41c724eStephen Hines  for (size_t idx = 0; idx < entsize; ++idx) {
213f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    Relocation::Type r_type = 0x0;
214f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    uint32_t r_sym = 0x0;
21522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    uint32_t r_offset = 0x0;
21637b74a387bb3993387029859c2d9d051c41c724eStephen Hines    int32_t r_addend = 0;
21737b74a387bb3993387029859c2d9d051c41c724eStephen Hines    if (!target()
21837b74a387bb3993387029859c2d9d051c41c724eStephen Hines             .readRelocation(relaTab[idx], r_type, r_sym, r_offset, r_addend)) {
219f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      return false;
22037b74a387bb3993387029859c2d9d051c41c724eStephen Hines    }
22122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
22222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    LDSymbol* symbol = pInput.context()->getSymbol(r_sym);
22337b74a387bb3993387029859c2d9d051c41c724eStephen Hines    if (symbol == NULL) {
22422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      fatal(diag::err_cannot_read_symbol) << r_sym << pInput.path();
22522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    }
22622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
227d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    IRBuilder::AddRelocation(pSection, r_type, *symbol, r_offset, r_addend);
22837b74a387bb3993387029859c2d9d051c41c724eStephen Hines  }  // end of for
22922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  return true;
23022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao}
23122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
23222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/// readRel - read ELF rel and create Relocation
23322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liaobool ELFReader<32, true>::readRel(Input& pInput,
23422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                                  LDSection& pSection,
23537b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                  llvm::StringRef pRegion) const {
23622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // get the number of rel
23722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  size_t entsize = pRegion.size() / sizeof(llvm::ELF::Elf32_Rel);
23822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  const llvm::ELF::Elf32_Rel* relTab =
239f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      reinterpret_cast<const llvm::ELF::Elf32_Rel*>(pRegion.begin());
24022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
24137b74a387bb3993387029859c2d9d051c41c724eStephen Hines  for (size_t idx = 0; idx < entsize; ++idx) {
242f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    Relocation::Type r_type = 0x0;
243f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    uint32_t r_sym = 0x0;
24422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    uint32_t r_offset = 0x0;
24522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
246f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    if (!target().readRelocation(relTab[idx], r_type, r_sym, r_offset))
247f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      return false;
24822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
24922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    LDSymbol* symbol = pInput.context()->getSymbol(r_sym);
25037b74a387bb3993387029859c2d9d051c41c724eStephen Hines    if (symbol == NULL) {
25122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      fatal(diag::err_cannot_read_symbol) << r_sym << pInput.path();
25222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    }
25322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
254d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    IRBuilder::AddRelocation(pSection, r_type, *symbol, r_offset);
25537b74a387bb3993387029859c2d9d051c41c724eStephen Hines  }  // end of for
25622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  return true;
25722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao}
25822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
25922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/// isMyEndian - is this ELF file in the same endian to me?
26037b74a387bb3993387029859c2d9d051c41c724eStephen Hinesbool ELFReader<32, true>::isMyEndian(const void* pELFHeader) const {
261f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  const llvm::ELF::Elf32_Ehdr* hdr =
262f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      reinterpret_cast<const llvm::ELF::Elf32_Ehdr*>(pELFHeader);
26322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
26422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  return (hdr->e_ident[llvm::ELF::EI_DATA] == llvm::ELF::ELFDATA2LSB);
26522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao}
26622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
26722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/// isMyMachine - is this ELF file generated for the same machine.
26837b74a387bb3993387029859c2d9d051c41c724eStephen Hinesbool ELFReader<32, true>::isMyMachine(const void* pELFHeader) const {
269f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  const llvm::ELF::Elf32_Ehdr* hdr =
270f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      reinterpret_cast<const llvm::ELF::Elf32_Ehdr*>(pELFHeader);
27122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
27221433dddd6366055d6b305675f4afca0b4592dcdStephen Hines  if (llvm::sys::IsLittleEndianHost)
273d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    return (hdr->e_machine == target().getInfo().machine());
274d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  return (mcld::bswap16(hdr->e_machine) == target().getInfo().machine());
27522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao}
27622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
27722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/// fileType - return the file type
27837b74a387bb3993387029859c2d9d051c41c724eStephen HinesInput::Type ELFReader<32, true>::fileType(const void* pELFHeader) const {
279f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  const llvm::ELF::Elf32_Ehdr* hdr =
280f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      reinterpret_cast<const llvm::ELF::Elf32_Ehdr*>(pELFHeader);
28122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  uint32_t type = 0x0;
28221433dddd6366055d6b305675f4afca0b4592dcdStephen Hines  if (llvm::sys::IsLittleEndianHost)
28322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    type = hdr->e_type;
28422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  else
285d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    type = mcld::bswap16(hdr->e_type);
28622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
28737b74a387bb3993387029859c2d9d051c41c724eStephen Hines  switch (type) {
28837b74a387bb3993387029859c2d9d051c41c724eStephen Hines    case llvm::ELF::ET_REL:
28937b74a387bb3993387029859c2d9d051c41c724eStephen Hines      return Input::Object;
29037b74a387bb3993387029859c2d9d051c41c724eStephen Hines    case llvm::ELF::ET_EXEC:
29137b74a387bb3993387029859c2d9d051c41c724eStephen Hines      return Input::Exec;
29237b74a387bb3993387029859c2d9d051c41c724eStephen Hines    case llvm::ELF::ET_DYN:
29337b74a387bb3993387029859c2d9d051c41c724eStephen Hines      return Input::DynObj;
29437b74a387bb3993387029859c2d9d051c41c724eStephen Hines    case llvm::ELF::ET_CORE:
29537b74a387bb3993387029859c2d9d051c41c724eStephen Hines      return Input::CoreFile;
29637b74a387bb3993387029859c2d9d051c41c724eStephen Hines    case llvm::ELF::ET_NONE:
29737b74a387bb3993387029859c2d9d051c41c724eStephen Hines    default:
29837b74a387bb3993387029859c2d9d051c41c724eStephen Hines      return Input::Unknown;
29922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  }
30022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao}
30122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
30222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/// readSectionHeaders - read ELF section header table and create LDSections
303f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hinesbool ELFReader<32, true>::readSectionHeaders(Input& pInput,
30437b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                             const void* pELFHeader) const {
305f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  const llvm::ELF::Elf32_Ehdr* ehdr =
306f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      reinterpret_cast<const llvm::ELF::Elf32_Ehdr*>(pELFHeader);
30722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
30837b74a387bb3993387029859c2d9d051c41c724eStephen Hines  uint32_t shoff = 0x0;
30922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  uint16_t shentsize = 0x0;
31037b74a387bb3993387029859c2d9d051c41c724eStephen Hines  uint32_t shnum = 0x0;
31137b74a387bb3993387029859c2d9d051c41c724eStephen Hines  uint32_t shstrtab = 0x0;
31222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
31321433dddd6366055d6b305675f4afca0b4592dcdStephen Hines  if (llvm::sys::IsLittleEndianHost) {
31437b74a387bb3993387029859c2d9d051c41c724eStephen Hines    shoff = ehdr->e_shoff;
31522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    shentsize = ehdr->e_shentsize;
31637b74a387bb3993387029859c2d9d051c41c724eStephen Hines    shnum = ehdr->e_shnum;
31737b74a387bb3993387029859c2d9d051c41c724eStephen Hines    shstrtab = ehdr->e_shstrndx;
31837b74a387bb3993387029859c2d9d051c41c724eStephen Hines  } else {
31937b74a387bb3993387029859c2d9d051c41c724eStephen Hines    shoff = mcld::bswap32(ehdr->e_shoff);
320d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    shentsize = mcld::bswap16(ehdr->e_shentsize);
32137b74a387bb3993387029859c2d9d051c41c724eStephen Hines    shnum = mcld::bswap16(ehdr->e_shnum);
32237b74a387bb3993387029859c2d9d051c41c724eStephen Hines    shstrtab = mcld::bswap16(ehdr->e_shstrndx);
32322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  }
32422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
32522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // If the file has no section header table, e_shoff holds zero.
32637b74a387bb3993387029859c2d9d051c41c724eStephen Hines  if (shoff == 0x0)
32722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    return true;
32822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
32937b74a387bb3993387029859c2d9d051c41c724eStephen Hines  const llvm::ELF::Elf32_Shdr* shdr = NULL;
330f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  llvm::StringRef shdr_region;
33137b74a387bb3993387029859c2d9d051c41c724eStephen Hines  uint32_t sh_name = 0x0;
33237b74a387bb3993387029859c2d9d051c41c724eStephen Hines  uint32_t sh_type = 0x0;
33337b74a387bb3993387029859c2d9d051c41c724eStephen Hines  uint32_t sh_flags = 0x0;
33437b74a387bb3993387029859c2d9d051c41c724eStephen Hines  uint32_t sh_offset = 0x0;
33537b74a387bb3993387029859c2d9d051c41c724eStephen Hines  uint32_t sh_size = 0x0;
33637b74a387bb3993387029859c2d9d051c41c724eStephen Hines  uint32_t sh_link = 0x0;
33737b74a387bb3993387029859c2d9d051c41c724eStephen Hines  uint32_t sh_info = 0x0;
33822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  uint32_t sh_addralign = 0x0;
33922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
3406f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // if shnum and shstrtab overflow, the actual values are in the 1st shdr
3416f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  if (shnum == llvm::ELF::SHN_UNDEF || shstrtab == llvm::ELF::SHN_XINDEX) {
34237b74a387bb3993387029859c2d9d051c41c724eStephen Hines    shdr_region =
34337b74a387bb3993387029859c2d9d051c41c724eStephen Hines        pInput.memArea()->request(pInput.fileOffset() + shoff, shentsize);
344f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    shdr = reinterpret_cast<const llvm::ELF::Elf32_Shdr*>(shdr_region.begin());
3456f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
34621433dddd6366055d6b305675f4afca0b4592dcdStephen Hines    if (llvm::sys::IsLittleEndianHost) {
3476f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      sh_size = shdr->sh_size;
3486f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      sh_link = shdr->sh_link;
34937b74a387bb3993387029859c2d9d051c41c724eStephen Hines    } else {
3506f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      sh_size = mcld::bswap32(shdr->sh_size);
3516f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      sh_link = mcld::bswap32(shdr->sh_link);
3526f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    }
3536f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
3546f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    if (shnum == llvm::ELF::SHN_UNDEF)
3556f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      shnum = sh_size;
3566f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    if (shstrtab == llvm::ELF::SHN_XINDEX)
3576f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      shstrtab = sh_link;
3586f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
3596f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    shoff += shentsize;
3606f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  }
3616f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
36237b74a387bb3993387029859c2d9d051c41c724eStephen Hines  shdr_region =
36337b74a387bb3993387029859c2d9d051c41c724eStephen Hines      pInput.memArea()->request(pInput.fileOffset() + shoff, shnum * shentsize);
364f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  const llvm::ELF::Elf32_Shdr* shdrTab =
365f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      reinterpret_cast<const llvm::ELF::Elf32_Shdr*>(shdr_region.begin());
3666f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
36722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // get .shstrtab first
3686f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  shdr = &shdrTab[shstrtab];
36921433dddd6366055d6b305675f4afca0b4592dcdStephen Hines  if (llvm::sys::IsLittleEndianHost) {
37022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    sh_offset = shdr->sh_offset;
37137b74a387bb3993387029859c2d9d051c41c724eStephen Hines    sh_size = shdr->sh_size;
37237b74a387bb3993387029859c2d9d051c41c724eStephen Hines  } else {
373d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    sh_offset = mcld::bswap32(shdr->sh_offset);
37437b74a387bb3993387029859c2d9d051c41c724eStephen Hines    sh_size = mcld::bswap32(shdr->sh_size);
37522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  }
37622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
37737b74a387bb3993387029859c2d9d051c41c724eStephen Hines  llvm::StringRef sect_name_region =
37837b74a387bb3993387029859c2d9d051c41c724eStephen Hines      pInput.memArea()->request(pInput.fileOffset() + sh_offset, sh_size);
379f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  const char* sect_name = sect_name_region.begin();
38022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
38122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  LinkInfoList link_info_list;
38222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
38322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // create all LDSections, including first NULL section.
38422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  for (size_t idx = 0; idx < shnum; ++idx) {
38521433dddd6366055d6b305675f4afca0b4592dcdStephen Hines    if (llvm::sys::IsLittleEndianHost) {
38637b74a387bb3993387029859c2d9d051c41c724eStephen Hines      sh_name = shdrTab[idx].sh_name;
38737b74a387bb3993387029859c2d9d051c41c724eStephen Hines      sh_type = shdrTab[idx].sh_type;
38837b74a387bb3993387029859c2d9d051c41c724eStephen Hines      sh_flags = shdrTab[idx].sh_flags;
38937b74a387bb3993387029859c2d9d051c41c724eStephen Hines      sh_offset = shdrTab[idx].sh_offset;
39037b74a387bb3993387029859c2d9d051c41c724eStephen Hines      sh_size = shdrTab[idx].sh_size;
39137b74a387bb3993387029859c2d9d051c41c724eStephen Hines      sh_link = shdrTab[idx].sh_link;
39237b74a387bb3993387029859c2d9d051c41c724eStephen Hines      sh_info = shdrTab[idx].sh_info;
39322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      sh_addralign = shdrTab[idx].sh_addralign;
39437b74a387bb3993387029859c2d9d051c41c724eStephen Hines    } else {
39537b74a387bb3993387029859c2d9d051c41c724eStephen Hines      sh_name = mcld::bswap32(shdrTab[idx].sh_name);
39637b74a387bb3993387029859c2d9d051c41c724eStephen Hines      sh_type = mcld::bswap32(shdrTab[idx].sh_type);
39737b74a387bb3993387029859c2d9d051c41c724eStephen Hines      sh_flags = mcld::bswap32(shdrTab[idx].sh_flags);
39837b74a387bb3993387029859c2d9d051c41c724eStephen Hines      sh_offset = mcld::bswap32(shdrTab[idx].sh_offset);
39937b74a387bb3993387029859c2d9d051c41c724eStephen Hines      sh_size = mcld::bswap32(shdrTab[idx].sh_size);
40037b74a387bb3993387029859c2d9d051c41c724eStephen Hines      sh_link = mcld::bswap32(shdrTab[idx].sh_link);
40137b74a387bb3993387029859c2d9d051c41c724eStephen Hines      sh_info = mcld::bswap32(shdrTab[idx].sh_info);
402d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao      sh_addralign = mcld::bswap32(shdrTab[idx].sh_addralign);
40322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    }
40422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
40537b74a387bb3993387029859c2d9d051c41c724eStephen Hines    LDSection* section = IRBuilder::CreateELFHeader(
40637b74a387bb3993387029859c2d9d051c41c724eStephen Hines        pInput, sect_name + sh_name, sh_type, sh_flags, sh_addralign);
40722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    section->setSize(sh_size);
40822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    section->setOffset(sh_offset);
40922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    section->setInfo(sh_info);
41022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
41122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    if (sh_link != 0x0 || sh_info != 0x0) {
41237b74a387bb3993387029859c2d9d051c41c724eStephen Hines      LinkInfo link_info = {section, sh_link, sh_info};
41322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      link_info_list.push_back(link_info);
41422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    }
41537b74a387bb3993387029859c2d9d051c41c724eStephen Hines  }  // end of for
41622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
41722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // set up InfoLink
41822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  LinkInfoList::iterator info, infoEnd = link_info_list.end();
41922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  for (info = link_info_list.begin(); info != infoEnd; ++info) {
420f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    if (LDFileFormat::Relocation == info->section->kind())
42122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      info->section->setLink(pInput.context()->getSection(info->sh_info));
422f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    else
423f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      info->section->setLink(pInput.context()->getSection(info->sh_link));
42422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  }
42522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
42622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  return true;
42722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao}
42822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
42922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/// readSignature - read a symbol from the given Input and index in symtab
43022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/// This is used to get the signature of a group section.
43122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei LiaoResolveInfo* ELFReader<32, true>::readSignature(Input& pInput,
43222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                                                LDSection& pSymTab,
43337b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                                uint32_t pSymIdx) const {
43422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  LDSection* symtab = &pSymTab;
43522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  LDSection* strtab = symtab->getLink();
43637b74a387bb3993387029859c2d9d051c41c724eStephen Hines  assert(symtab != NULL && strtab != NULL);
43722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
43822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  uint32_t offset = pInput.fileOffset() + symtab->offset() +
43937b74a387bb3993387029859c2d9d051c41c724eStephen Hines                    sizeof(llvm::ELF::Elf32_Sym) * pSymIdx;
440f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  llvm::StringRef symbol_region =
441f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      pInput.memArea()->request(offset, sizeof(llvm::ELF::Elf32_Sym));
442f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  const llvm::ELF::Elf32_Sym* entry =
443f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      reinterpret_cast<const llvm::ELF::Elf32_Sym*>(symbol_region.begin());
44422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
44537b74a387bb3993387029859c2d9d051c41c724eStephen Hines  uint32_t st_name = 0x0;
44637b74a387bb3993387029859c2d9d051c41c724eStephen Hines  uint8_t st_info = 0x0;
44737b74a387bb3993387029859c2d9d051c41c724eStephen Hines  uint8_t st_other = 0x0;
44822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  uint16_t st_shndx = 0x0;
44937b74a387bb3993387029859c2d9d051c41c724eStephen Hines  st_info = entry->st_info;
45022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  st_other = entry->st_other;
45121433dddd6366055d6b305675f4afca0b4592dcdStephen Hines  if (llvm::sys::IsLittleEndianHost) {
45237b74a387bb3993387029859c2d9d051c41c724eStephen Hines    st_name = entry->st_name;
45322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    st_shndx = entry->st_shndx;
45437b74a387bb3993387029859c2d9d051c41c724eStephen Hines  } else {
45537b74a387bb3993387029859c2d9d051c41c724eStephen Hines    st_name = mcld::bswap32(entry->st_name);
456d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    st_shndx = mcld::bswap16(entry->st_shndx);
45722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  }
45822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
459f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  llvm::StringRef strtab_region = pInput.memArea()->request(
460f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      pInput.fileOffset() + strtab->offset(), strtab->size());
46122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
46222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // get ld_name
463f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  llvm::StringRef ld_name(strtab_region.begin() + st_name);
464affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
46522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  ResolveInfo* result = ResolveInfo::Create(ld_name);
46622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  result->setSource(pInput.type() == Input::DynObj);
46722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  result->setType(static_cast<ResolveInfo::Type>(st_info & 0xF));
46822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  result->setDesc(getSymDesc(st_shndx, pInput));
46922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  result->setBinding(getSymBinding((st_info >> 4), st_shndx, st_other));
47022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  result->setVisibility(getSymVisibility(st_other));
471affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
47222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  return result;
47322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao}
47422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
47522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/// readDynamic - read ELF .dynamic in input dynobj
47637b74a387bb3993387029859c2d9d051c41c724eStephen Hinesbool ELFReader<32, true>::readDynamic(Input& pInput) const {
47722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  assert(pInput.type() == Input::DynObj);
47822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  const LDSection* dynamic_sect = pInput.context()->getSection(".dynamic");
47937b74a387bb3993387029859c2d9d051c41c724eStephen Hines  if (dynamic_sect == NULL) {
48022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    fatal(diag::err_cannot_read_section) << ".dynamic";
48122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  }
48222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  const LDSection* dynstr_sect = dynamic_sect->getLink();
48337b74a387bb3993387029859c2d9d051c41c724eStephen Hines  if (dynstr_sect == NULL) {
48422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    fatal(diag::err_cannot_read_section) << ".dynstr";
48522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  }
48622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
487f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  llvm::StringRef dynamic_region = pInput.memArea()->request(
488f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      pInput.fileOffset() + dynamic_sect->offset(), dynamic_sect->size());
48922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
490f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  llvm::StringRef dynstr_region = pInput.memArea()->request(
491f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      pInput.fileOffset() + dynstr_sect->offset(), dynstr_sect->size());
49222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
49322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  const llvm::ELF::Elf32_Dyn* dynamic =
494f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      reinterpret_cast<const llvm::ELF::Elf32_Dyn*>(dynamic_region.begin());
495f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  const char* dynstr = dynstr_region.begin();
49622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  bool hasSOName = false;
49722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  size_t numOfEntries = dynamic_sect->size() / sizeof(llvm::ELF::Elf32_Dyn);
49822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
49922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  for (size_t idx = 0; idx < numOfEntries; ++idx) {
50022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    llvm::ELF::Elf32_Sword d_tag = 0x0;
50122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    llvm::ELF::Elf32_Word d_val = 0x0;
50222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
50321433dddd6366055d6b305675f4afca0b4592dcdStephen Hines    if (llvm::sys::IsLittleEndianHost) {
50422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      d_tag = dynamic[idx].d_tag;
50522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      d_val = dynamic[idx].d_un.d_val;
50622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    } else {
507d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao      d_tag = mcld::bswap32(dynamic[idx].d_tag);
508d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao      d_val = mcld::bswap32(dynamic[idx].d_un.d_val);
50922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    }
51022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
51122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    switch (d_tag) {
51222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      case llvm::ELF::DT_SONAME:
51322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao        assert(d_val < dynstr_sect->size());
51422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao        pInput.setName(sys::fs::Path(dynstr + d_val).filename().native());
51522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao        hasSOName = true;
51622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao        break;
51722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      case llvm::ELF::DT_NEEDED:
51822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao        // TODO:
51922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao        break;
52022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      case llvm::ELF::DT_NULL:
52122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      default:
52222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao        break;
52322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    }
52422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  }
52522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
52622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // if there is no SONAME in .dynamic, then set it from input path
52722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  if (!hasSOName)
52822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    pInput.setName(pInput.path().filename().native());
52922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
530affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  return true;
531affc150dc44fab1911775a49636d0ce85333b634Zonr Chang}
53222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
5336f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines//===----------------------------------------------------------------------===//
5346f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// ELFReader<64, true>
5356f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines//===----------------------------------------------------------------------===//
5366f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines/// constructor
53737b74a387bb3993387029859c2d9d051c41c724eStephen HinesELFReader<64, true>::ELFReader(GNULDBackend& pBackend) : ELFReaderIF(pBackend) {
5386f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
5396f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
5406f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines/// destructor
54137b74a387bb3993387029859c2d9d051c41c724eStephen HinesELFReader<64, true>::~ELFReader() {
5426f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
5436f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
5446f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines/// isELF - is this a ELF file
54537b74a387bb3993387029859c2d9d051c41c724eStephen Hinesbool ELFReader<64, true>::isELF(const void* pELFHeader) const {
546f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  const llvm::ELF::Elf64_Ehdr* hdr =
547f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      reinterpret_cast<const llvm::ELF::Elf64_Ehdr*>(pELFHeader);
54837b74a387bb3993387029859c2d9d051c41c724eStephen Hines  if (memcmp(llvm::ELF::ElfMagic, hdr, 4) == 0)
5496f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    return true;
5506f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  return false;
5516f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
5526f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
5536f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines/// readRegularSection - read a regular section and create fragments.
55437b74a387bb3993387029859c2d9d051c41c724eStephen Hinesbool ELFReader<64, true>::readRegularSection(Input& pInput,
55537b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                             SectionData& pSD) const {
5566f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  uint64_t offset = pInput.fileOffset() + pSD.getSection().offset();
5576f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  uint64_t size = pSD.getSection().size();
5586f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
5596f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  Fragment* frag = IRBuilder::CreateRegion(pInput, offset, size);
5606f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  ObjectBuilder::AppendFragment(*frag, pSD);
5616f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  return true;
5626f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
5636f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
5646f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines/// readSymbols - read ELF symbols and create LDSymbol
5656f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesbool ELFReader<64, true>::readSymbols(Input& pInput,
5666f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                                      IRBuilder& pBuilder,
567f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines                                      llvm::StringRef pRegion,
56837b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                      const char* pStrTab) const {
5696f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // get number of symbols
570f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  size_t entsize = pRegion.size() / sizeof(llvm::ELF::Elf64_Sym);
5716f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  const llvm::ELF::Elf64_Sym* symtab =
572f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      reinterpret_cast<const llvm::ELF::Elf64_Sym*>(pRegion.begin());
5736f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
57437b74a387bb3993387029859c2d9d051c41c724eStephen Hines  uint32_t st_name = 0x0;
5756f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  uint64_t st_value = 0x0;
57637b74a387bb3993387029859c2d9d051c41c724eStephen Hines  uint64_t st_size = 0x0;
57737b74a387bb3993387029859c2d9d051c41c724eStephen Hines  uint8_t st_info = 0x0;
57837b74a387bb3993387029859c2d9d051c41c724eStephen Hines  uint8_t st_other = 0x0;
5796f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  uint16_t st_shndx = 0x0;
5806f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
5816f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // skip the first NULL symbol
5826f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  pInput.context()->addSymbol(LDSymbol::Null());
5836f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
584f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  /// recording symbols added from DynObj to analyze weak alias
585f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  std::vector<AliasInfo> potential_aliases;
58637b74a387bb3993387029859c2d9d051c41c724eStephen Hines  bool is_dyn_obj = (pInput.type() == Input::DynObj);
5876f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  for (size_t idx = 1; idx < entsize; ++idx) {
58837b74a387bb3993387029859c2d9d051c41c724eStephen Hines    st_info = symtab[idx].st_info;
5896f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    st_other = symtab[idx].st_other;
5906f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
59121433dddd6366055d6b305675f4afca0b4592dcdStephen Hines    if (llvm::sys::IsLittleEndianHost) {
59237b74a387bb3993387029859c2d9d051c41c724eStephen Hines      st_name = symtab[idx].st_name;
5936f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      st_value = symtab[idx].st_value;
59437b74a387bb3993387029859c2d9d051c41c724eStephen Hines      st_size = symtab[idx].st_size;
5956f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      st_shndx = symtab[idx].st_shndx;
59637b74a387bb3993387029859c2d9d051c41c724eStephen Hines    } else {
59737b74a387bb3993387029859c2d9d051c41c724eStephen Hines      st_name = mcld::bswap32(symtab[idx].st_name);
5986f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      st_value = mcld::bswap64(symtab[idx].st_value);
59937b74a387bb3993387029859c2d9d051c41c724eStephen Hines      st_size = mcld::bswap64(symtab[idx].st_size);
6006f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      st_shndx = mcld::bswap16(symtab[idx].st_shndx);
6016f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    }
6026f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
6036f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    // If the section should not be included, set the st_shndx SHN_UNDEF
6046f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    // - A section in interrelated groups are not included.
60537b74a387bb3993387029859c2d9d051c41c724eStephen Hines    if (pInput.type() == Input::Object && st_shndx < llvm::ELF::SHN_LORESERVE &&
6066f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines        st_shndx != llvm::ELF::SHN_UNDEF) {
60737b74a387bb3993387029859c2d9d051c41c724eStephen Hines      if (pInput.context()->getSection(st_shndx) == NULL)
6086f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines        st_shndx = llvm::ELF::SHN_UNDEF;
6096f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    }
6106f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
6116f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    // get ld_type
6126f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    ResolveInfo::Type ld_type = getSymType(st_info, st_shndx);
6136f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
6146f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    // get ld_desc
6156f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    ResolveInfo::Desc ld_desc = getSymDesc(st_shndx, pInput);
6166f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
6176f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    // get ld_binding
61837b74a387bb3993387029859c2d9d051c41c724eStephen Hines    ResolveInfo::Binding ld_binding =
61937b74a387bb3993387029859c2d9d051c41c724eStephen Hines        getSymBinding((st_info >> 4), st_shndx, st_other);
6206f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
6216f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    // get ld_value - ld_value must be section relative.
6226f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    uint64_t ld_value = getSymValue(st_value, st_shndx, pInput);
6236f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
6246f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    // get ld_vis
6256f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    ResolveInfo::Visibility ld_vis = getSymVisibility(st_other);
6266f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
6276f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    // get section
6286f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    LDSection* section = NULL;
62937b74a387bb3993387029859c2d9d051c41c724eStephen Hines    if (st_shndx < llvm::ELF::SHN_LORESERVE)  // including ABS and COMMON
6306f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      section = pInput.context()->getSection(st_shndx);
6316f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
6326f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    // get ld_name
6336f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    std::string ld_name;
6346f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    if (ResolveInfo::Section == ld_type) {
6356f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      // Section symbol's st_name is the section index.
63637b74a387bb3993387029859c2d9d051c41c724eStephen Hines      assert(section != NULL && "get a invalid section");
6376f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      ld_name = section->name();
63837b74a387bb3993387029859c2d9d051c41c724eStephen Hines    } else {
6396f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      ld_name = std::string(pStrTab + st_name);
6406f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    }
6416f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
642f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    LDSymbol* psym = pBuilder.AddSymbol(pInput,
643f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines                                        ld_name,
644f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines                                        ld_type,
645f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines                                        ld_desc,
646f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines                                        ld_binding,
647f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines                                        st_size,
648f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines                                        ld_value,
649f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines                                        section,
650f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines                                        ld_vis);
651f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines
65237b74a387bb3993387029859c2d9d051c41c724eStephen Hines    if (is_dyn_obj && psym != NULL && ResolveInfo::Undefined != ld_desc &&
65337b74a387bb3993387029859c2d9d051c41c724eStephen Hines        (ResolveInfo::Global == ld_binding ||
65437b74a387bb3993387029859c2d9d051c41c724eStephen Hines         ResolveInfo::Weak == ld_binding) &&
65537b74a387bb3993387029859c2d9d051c41c724eStephen Hines        ResolveInfo::Object == ld_type) {
656f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      AliasInfo p;
657f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      p.pt_alias = psym;
658f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      p.ld_binding = ld_binding;
659f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      p.ld_value = ld_value;
660f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      potential_aliases.push_back(p);
661f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    }
66237b74a387bb3993387029859c2d9d051c41c724eStephen Hines  }  // end of for loop
663f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
664f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  // analyze weak alias here
665f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  if (is_dyn_obj) {
666f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    // sort symbols by symbol value and then weak before strong
667f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    std::sort(potential_aliases.begin(), potential_aliases.end(), less);
668f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
669f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    // for each weak symbol, find out all its aliases, and
670f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    // then link them as a circular list in Module
671f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    std::vector<AliasInfo>::iterator sym_it, sym_e;
672f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    sym_e = potential_aliases.end();
67337b74a387bb3993387029859c2d9d051c41c724eStephen Hines    for (sym_it = potential_aliases.begin(); sym_it != sym_e; ++sym_it) {
67437b74a387bb3993387029859c2d9d051c41c724eStephen Hines      if (ResolveInfo::Weak != sym_it->ld_binding)
675f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        continue;
676f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
677f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      Module& pModule = pBuilder.getModule();
67837b74a387bb3993387029859c2d9d051c41c724eStephen Hines      std::vector<AliasInfo>::iterator alias_it = sym_it + 1;
67937b74a387bb3993387029859c2d9d051c41c724eStephen Hines      while (alias_it != sym_e) {
680f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines        if (sym_it->ld_value != alias_it->ld_value)
681f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines          break;
682f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
683f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines        if (sym_it + 1 == alias_it)
684f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines          pModule.CreateAliasList(*sym_it->pt_alias->resolveInfo());
685f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        pModule.addAlias(*alias_it->pt_alias->resolveInfo());
686f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines        ++alias_it;
687f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      }
688f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
689f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      sym_it = alias_it - 1;
69037b74a387bb3993387029859c2d9d051c41c724eStephen Hines    }  // end of for loop
691f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  }
6926f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  return true;
6936f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
6946f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
6956f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines//===----------------------------------------------------------------------===//
6966f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// ELFReader::read relocations - read ELF rela and rel, and create Relocation
6976f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines//===----------------------------------------------------------------------===//
6986f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines/// ELFReader::readRela - read ELF rela and create Relocation
6996f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesbool ELFReader<64, true>::readRela(Input& pInput,
7006f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                                   LDSection& pSection,
70137b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                   llvm::StringRef pRegion) const {
7026f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // get the number of rela
7036f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  size_t entsize = pRegion.size() / sizeof(llvm::ELF::Elf64_Rela);
7046f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  const llvm::ELF::Elf64_Rela* relaTab =
705f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      reinterpret_cast<const llvm::ELF::Elf64_Rela*>(pRegion.begin());
7066f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
70737b74a387bb3993387029859c2d9d051c41c724eStephen Hines  for (size_t idx = 0; idx < entsize; ++idx) {
708f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    Relocation::Type r_type = 0x0;
709f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    uint32_t r_sym = 0x0;
7106f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    uint64_t r_offset = 0x0;
71137b74a387bb3993387029859c2d9d051c41c724eStephen Hines    int64_t r_addend = 0;
71237b74a387bb3993387029859c2d9d051c41c724eStephen Hines    if (!target()
71337b74a387bb3993387029859c2d9d051c41c724eStephen Hines             .readRelocation(relaTab[idx], r_type, r_sym, r_offset, r_addend)) {
714f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      return false;
7156f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    }
7166f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
7176f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    LDSymbol* symbol = pInput.context()->getSymbol(r_sym);
71837b74a387bb3993387029859c2d9d051c41c724eStephen Hines    if (symbol == NULL) {
7196f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      fatal(diag::err_cannot_read_symbol) << r_sym << pInput.path();
7206f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    }
7216f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
7226f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    IRBuilder::AddRelocation(pSection, r_type, *symbol, r_offset, r_addend);
72337b74a387bb3993387029859c2d9d051c41c724eStephen Hines  }  // end of for
7246f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  return true;
7256f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
7266f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
7276f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines/// readRel - read ELF rel and create Relocation
7286f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesbool ELFReader<64, true>::readRel(Input& pInput,
7296f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                                  LDSection& pSection,
73037b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                  llvm::StringRef pRegion) const {
7316f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // get the number of rel
7326f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  size_t entsize = pRegion.size() / sizeof(llvm::ELF::Elf64_Rel);
7336f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  const llvm::ELF::Elf64_Rel* relTab =
734f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      reinterpret_cast<const llvm::ELF::Elf64_Rel*>(pRegion.begin());
7356f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
73637b74a387bb3993387029859c2d9d051c41c724eStephen Hines  for (size_t idx = 0; idx < entsize; ++idx) {
737f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    Relocation::Type r_type = 0x0;
738f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    uint32_t r_sym = 0x0;
7396f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    uint64_t r_offset = 0x0;
740f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    if (!target().readRelocation(relTab[idx], r_type, r_sym, r_offset))
741f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      return false;
7426f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
7436f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    LDSymbol* symbol = pInput.context()->getSymbol(r_sym);
74437b74a387bb3993387029859c2d9d051c41c724eStephen Hines    if (symbol == NULL) {
7456f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      fatal(diag::err_cannot_read_symbol) << r_sym << pInput.path();
7466f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    }
7476f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
7486f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    IRBuilder::AddRelocation(pSection, r_type, *symbol, r_offset);
74937b74a387bb3993387029859c2d9d051c41c724eStephen Hines  }  // end of for
7506f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  return true;
7516f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
7526f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
7536f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines/// isMyEndian - is this ELF file in the same endian to me?
75437b74a387bb3993387029859c2d9d051c41c724eStephen Hinesbool ELFReader<64, true>::isMyEndian(const void* pELFHeader) const {
755f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  const llvm::ELF::Elf64_Ehdr* hdr =
756f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      reinterpret_cast<const llvm::ELF::Elf64_Ehdr*>(pELFHeader);
7576f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
7586f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  return (hdr->e_ident[llvm::ELF::EI_DATA] == llvm::ELF::ELFDATA2LSB);
7596f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
7606f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
7616f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines/// isMyMachine - is this ELF file generated for the same machine.
76237b74a387bb3993387029859c2d9d051c41c724eStephen Hinesbool ELFReader<64, true>::isMyMachine(const void* pELFHeader) const {
763f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  const llvm::ELF::Elf64_Ehdr* hdr =
764f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      reinterpret_cast<const llvm::ELF::Elf64_Ehdr*>(pELFHeader);
7656f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
76621433dddd6366055d6b305675f4afca0b4592dcdStephen Hines  if (llvm::sys::IsLittleEndianHost)
7676f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    return (hdr->e_machine == target().getInfo().machine());
7686f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  return (mcld::bswap16(hdr->e_machine) == target().getInfo().machine());
7696f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
7706f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
7716f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines/// fileType - return the file type
77237b74a387bb3993387029859c2d9d051c41c724eStephen HinesInput::Type ELFReader<64, true>::fileType(const void* pELFHeader) const {
773f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  const llvm::ELF::Elf64_Ehdr* hdr =
774f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      reinterpret_cast<const llvm::ELF::Elf64_Ehdr*>(pELFHeader);
7756f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  uint32_t type = 0x0;
77621433dddd6366055d6b305675f4afca0b4592dcdStephen Hines  if (llvm::sys::IsLittleEndianHost)
7776f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    type = hdr->e_type;
7786f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  else
7796f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    type = mcld::bswap16(hdr->e_type);
7806f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
78137b74a387bb3993387029859c2d9d051c41c724eStephen Hines  switch (type) {
78237b74a387bb3993387029859c2d9d051c41c724eStephen Hines    case llvm::ELF::ET_REL:
78337b74a387bb3993387029859c2d9d051c41c724eStephen Hines      return Input::Object;
78437b74a387bb3993387029859c2d9d051c41c724eStephen Hines    case llvm::ELF::ET_EXEC:
78537b74a387bb3993387029859c2d9d051c41c724eStephen Hines      return Input::Exec;
78637b74a387bb3993387029859c2d9d051c41c724eStephen Hines    case llvm::ELF::ET_DYN:
78737b74a387bb3993387029859c2d9d051c41c724eStephen Hines      return Input::DynObj;
78837b74a387bb3993387029859c2d9d051c41c724eStephen Hines    case llvm::ELF::ET_CORE:
78937b74a387bb3993387029859c2d9d051c41c724eStephen Hines      return Input::CoreFile;
79037b74a387bb3993387029859c2d9d051c41c724eStephen Hines    case llvm::ELF::ET_NONE:
79137b74a387bb3993387029859c2d9d051c41c724eStephen Hines    default:
79237b74a387bb3993387029859c2d9d051c41c724eStephen Hines      return Input::Unknown;
7936f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  }
7946f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
7956f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
7966f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines/// readSectionHeaders - read ELF section header table and create LDSections
797f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hinesbool ELFReader<64, true>::readSectionHeaders(Input& pInput,
79837b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                             const void* pELFHeader) const {
799f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  const llvm::ELF::Elf64_Ehdr* ehdr =
800f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      reinterpret_cast<const llvm::ELF::Elf64_Ehdr*>(pELFHeader);
8016f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
80237b74a387bb3993387029859c2d9d051c41c724eStephen Hines  uint64_t shoff = 0x0;
8036f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  uint16_t shentsize = 0x0;
80437b74a387bb3993387029859c2d9d051c41c724eStephen Hines  uint32_t shnum = 0x0;
80537b74a387bb3993387029859c2d9d051c41c724eStephen Hines  uint32_t shstrtab = 0x0;
8066f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
80721433dddd6366055d6b305675f4afca0b4592dcdStephen Hines  if (llvm::sys::IsLittleEndianHost) {
80837b74a387bb3993387029859c2d9d051c41c724eStephen Hines    shoff = ehdr->e_shoff;
8096f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    shentsize = ehdr->e_shentsize;
81037b74a387bb3993387029859c2d9d051c41c724eStephen Hines    shnum = ehdr->e_shnum;
81137b74a387bb3993387029859c2d9d051c41c724eStephen Hines    shstrtab = ehdr->e_shstrndx;
81237b74a387bb3993387029859c2d9d051c41c724eStephen Hines  } else {
81337b74a387bb3993387029859c2d9d051c41c724eStephen Hines    shoff = mcld::bswap64(ehdr->e_shoff);
8146f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    shentsize = mcld::bswap16(ehdr->e_shentsize);
81537b74a387bb3993387029859c2d9d051c41c724eStephen Hines    shnum = mcld::bswap16(ehdr->e_shnum);
81637b74a387bb3993387029859c2d9d051c41c724eStephen Hines    shstrtab = mcld::bswap16(ehdr->e_shstrndx);
8176f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  }
8186f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
8196f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // If the file has no section header table, e_shoff holds zero.
82037b74a387bb3993387029859c2d9d051c41c724eStephen Hines  if (shoff == 0x0)
8216f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    return true;
8226f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
82337b74a387bb3993387029859c2d9d051c41c724eStephen Hines  const llvm::ELF::Elf64_Shdr* shdr = NULL;
824f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  llvm::StringRef shdr_region;
82537b74a387bb3993387029859c2d9d051c41c724eStephen Hines  uint32_t sh_name = 0x0;
82637b74a387bb3993387029859c2d9d051c41c724eStephen Hines  uint32_t sh_type = 0x0;
82737b74a387bb3993387029859c2d9d051c41c724eStephen Hines  uint64_t sh_flags = 0x0;
82837b74a387bb3993387029859c2d9d051c41c724eStephen Hines  uint64_t sh_offset = 0x0;
82937b74a387bb3993387029859c2d9d051c41c724eStephen Hines  uint64_t sh_size = 0x0;
83037b74a387bb3993387029859c2d9d051c41c724eStephen Hines  uint32_t sh_link = 0x0;
83137b74a387bb3993387029859c2d9d051c41c724eStephen Hines  uint32_t sh_info = 0x0;
8326f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  uint64_t sh_addralign = 0x0;
8336f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
8346f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // if shnum and shstrtab overflow, the actual values are in the 1st shdr
8356f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  if (shnum == llvm::ELF::SHN_UNDEF || shstrtab == llvm::ELF::SHN_XINDEX) {
83637b74a387bb3993387029859c2d9d051c41c724eStephen Hines    shdr_region =
83737b74a387bb3993387029859c2d9d051c41c724eStephen Hines        pInput.memArea()->request(pInput.fileOffset() + shoff, shentsize);
838f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    shdr = reinterpret_cast<const llvm::ELF::Elf64_Shdr*>(shdr_region.begin());
8396f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
84021433dddd6366055d6b305675f4afca0b4592dcdStephen Hines    if (llvm::sys::IsLittleEndianHost) {
8416f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      sh_size = shdr->sh_size;
8426f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      sh_link = shdr->sh_link;
84337b74a387bb3993387029859c2d9d051c41c724eStephen Hines    } else {
8446f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      sh_size = mcld::bswap64(shdr->sh_size);
8456f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      sh_link = mcld::bswap32(shdr->sh_link);
8466f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    }
8476f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
8486f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    if (shnum == llvm::ELF::SHN_UNDEF)
8496f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      shnum = sh_size;
8506f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    if (shstrtab == llvm::ELF::SHN_XINDEX)
8516f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      shstrtab = sh_link;
8526f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
8536f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    shoff += shentsize;
8546f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  }
8556f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
85637b74a387bb3993387029859c2d9d051c41c724eStephen Hines  shdr_region =
85737b74a387bb3993387029859c2d9d051c41c724eStephen Hines      pInput.memArea()->request(pInput.fileOffset() + shoff, shnum * shentsize);
858f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  const llvm::ELF::Elf64_Shdr* shdrTab =
859f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      reinterpret_cast<const llvm::ELF::Elf64_Shdr*>(shdr_region.begin());
8606f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
8616f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // get .shstrtab first
8626f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  shdr = &shdrTab[shstrtab];
86321433dddd6366055d6b305675f4afca0b4592dcdStephen Hines  if (llvm::sys::IsLittleEndianHost) {
8646f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    sh_offset = shdr->sh_offset;
86537b74a387bb3993387029859c2d9d051c41c724eStephen Hines    sh_size = shdr->sh_size;
86637b74a387bb3993387029859c2d9d051c41c724eStephen Hines  } else {
8676f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    sh_offset = mcld::bswap64(shdr->sh_offset);
86837b74a387bb3993387029859c2d9d051c41c724eStephen Hines    sh_size = mcld::bswap64(shdr->sh_size);
8696f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  }
8706f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
87137b74a387bb3993387029859c2d9d051c41c724eStephen Hines  llvm::StringRef sect_name_region =
87237b74a387bb3993387029859c2d9d051c41c724eStephen Hines      pInput.memArea()->request(pInput.fileOffset() + sh_offset, sh_size);
873f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  const char* sect_name = sect_name_region.begin();
8746f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
8756f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  LinkInfoList link_info_list;
8766f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
8776f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // create all LDSections, including first NULL section.
8786f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  for (size_t idx = 0; idx < shnum; ++idx) {
87921433dddd6366055d6b305675f4afca0b4592dcdStephen Hines    if (llvm::sys::IsLittleEndianHost) {
88037b74a387bb3993387029859c2d9d051c41c724eStephen Hines      sh_name = shdrTab[idx].sh_name;
88137b74a387bb3993387029859c2d9d051c41c724eStephen Hines      sh_type = shdrTab[idx].sh_type;
88237b74a387bb3993387029859c2d9d051c41c724eStephen Hines      sh_flags = shdrTab[idx].sh_flags;
88337b74a387bb3993387029859c2d9d051c41c724eStephen Hines      sh_offset = shdrTab[idx].sh_offset;
88437b74a387bb3993387029859c2d9d051c41c724eStephen Hines      sh_size = shdrTab[idx].sh_size;
88537b74a387bb3993387029859c2d9d051c41c724eStephen Hines      sh_link = shdrTab[idx].sh_link;
88637b74a387bb3993387029859c2d9d051c41c724eStephen Hines      sh_info = shdrTab[idx].sh_info;
8876f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      sh_addralign = shdrTab[idx].sh_addralign;
88837b74a387bb3993387029859c2d9d051c41c724eStephen Hines    } else {
88937b74a387bb3993387029859c2d9d051c41c724eStephen Hines      sh_name = mcld::bswap32(shdrTab[idx].sh_name);
890