15460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//===- ELFDynObjReader.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/ELFDynObjReader.h>
10d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao
11d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao#include <mcld/LinkerConfig.h>
12d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao#include <mcld/IRBuilder.h>
135460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <mcld/LD/ELFReader.h>
14f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines#include <mcld/MC/Input.h>
15d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao#include <mcld/Target/GNULDBackend.h>
16f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines#include <mcld/Support/MemoryArea.h>
17d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao
18f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines#include <llvm/ADT/StringRef.h>
19d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao#include <llvm/ADT/Twine.h>
20d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao#include <llvm/Support/ErrorHandling.h>
215460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
225460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <string>
235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
245460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaousing namespace mcld;
255460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao//===----------------------------------------------------------------------===//
275460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// ELFDynObjReader
2822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao//===----------------------------------------------------------------------===//
29d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoELFDynObjReader::ELFDynObjReader(GNULDBackend& pBackend,
30d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao                                 IRBuilder& pBuilder,
31d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao                                 const LinkerConfig& pConfig)
325460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  : DynObjReader(),
335460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    m_pELFReader(0),
34d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    m_Builder(pBuilder) {
35d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  if (pConfig.targets().is32Bits() && pConfig.targets().isLittleEndian())
365460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    m_pELFReader = new ELFReader<32, true>(pBackend);
376f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  else if (pConfig.targets().is64Bits() && pConfig.targets().isLittleEndian())
386f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    m_pELFReader = new ELFReader<64, true>(pBackend);
395460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
405460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
415460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoELFDynObjReader::~ELFDynObjReader()
425460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
435460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  delete m_pELFReader;
445460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
455460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
465460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao/// isMyFormat
47f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hinesbool ELFDynObjReader::isMyFormat(Input &pInput, bool &pContinue) const
485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  assert(pInput.hasMemArea());
505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // Don't warning about the frequently requests.
525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // MemoryArea has a list of cache to handle this.
535460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  size_t hdr_size = m_pELFReader->getELFHeaderSize();
54f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  if (pInput.memArea()->size() < hdr_size)
55f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    return false;
56f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines
57f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  llvm::StringRef region = pInput.memArea()->request(pInput.fileOffset(),
58f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines                                                     hdr_size);
595460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
60f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  const char* ELF_hdr = region.begin();
615460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  bool result = true;
62f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  if (!m_pELFReader->isELF(ELF_hdr)) {
63f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    pContinue = true;
645460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    result = false;
65f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  } else if (Input::DynObj != m_pELFReader->fileType(ELF_hdr)) {
66f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    pContinue = true;
675460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    result = false;
68f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  } else if (!m_pELFReader->isMyEndian(ELF_hdr)) {
69f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    pContinue = false;
705460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    result = false;
71f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  } else if (!m_pELFReader->isMyMachine(ELF_hdr)) {
72f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    pContinue = false;
735460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    result = false;
74f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  }
755460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return result;
765460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
775460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
7822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/// readHeader
7922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liaobool ELFDynObjReader::readHeader(Input& pInput)
805460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
815460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  assert(pInput.hasMemArea());
825460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
835460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  size_t hdr_size = m_pELFReader->getELFHeaderSize();
84f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  llvm::StringRef region = pInput.memArea()->request(pInput.fileOffset(),
85f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines                                                     hdr_size);
86f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  const char* ELF_hdr = region.begin();
875460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
8822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  bool shdr_result = m_pELFReader->readSectionHeaders(pInput, ELF_hdr);
89affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
90affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  // read .dynamic to get the correct SONAME
91affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  bool dyn_result = m_pELFReader->readDynamic(pInput);
92affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
93affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  return (shdr_result && dyn_result);
945460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
955460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
965460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao/// readSymbols
975460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaobool ELFDynObjReader::readSymbols(Input& pInput)
985460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{
995460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  assert(pInput.hasMemArea());
1005460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
1015460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  LDSection* symtab_shdr = pInput.context()->getSection(".dynsym");
102affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  if (NULL == symtab_shdr) {
103affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    note(diag::note_has_no_symtab) << pInput.name()
104affc150dc44fab1911775a49636d0ce85333b634Zonr Chang                                   << pInput.path()
105affc150dc44fab1911775a49636d0ce85333b634Zonr Chang                                   << ".dynsym";
106affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    return true;
107affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  }
108affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
1095460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  LDSection* strtab_shdr = symtab_shdr->getLink();
110affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  if (NULL == strtab_shdr) {
111affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    fatal(diag::fatal_cannot_read_strtab) << pInput.name()
112affc150dc44fab1911775a49636d0ce85333b634Zonr Chang                                          << pInput.path()
113affc150dc44fab1911775a49636d0ce85333b634Zonr Chang                                          << ".dynsym";
1145460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    return false;
115affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  }
1165460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
117f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  llvm::StringRef symtab_region = pInput.memArea()->request(
118f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      pInput.fileOffset() + symtab_shdr->offset(), symtab_shdr->size());
1195460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
120f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  llvm::StringRef strtab_region = pInput.memArea()->request(
121f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      pInput.fileOffset() + strtab_shdr->offset(), strtab_shdr->size());
122f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  const char* strtab = strtab_region.begin();
123d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  bool result = m_pELFReader->readSymbols(pInput, m_Builder,
124f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines                                          symtab_region, strtab);
1255460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return result;
1265460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
1275460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
128