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//===----------------------------------------------------------------------===//
937b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/LD/ELFDynObjReader.h"
10d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao
1137b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/IRBuilder.h"
1237b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/LinkerConfig.h"
1337b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/LD/ELFReader.h"
1437b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/LD/LDContext.h"
1537b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/MC/Input.h"
1637b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Support/MemoryArea.h"
1737b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Target/GNULDBackend.h"
18d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao
1987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines#include <llvm/ADT/StringRef.h>
20d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao#include <llvm/ADT/Twine.h>
21d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao#include <llvm/Support/ErrorHandling.h>
225460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <string>
245460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2537b74a387bb3993387029859c2d9d051c41c724eStephen Hinesnamespace mcld {
265460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao//===----------------------------------------------------------------------===//
285460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// ELFDynObjReader
2922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao//===----------------------------------------------------------------------===//
30d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoELFDynObjReader::ELFDynObjReader(GNULDBackend& pBackend,
31d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao                                 IRBuilder& pBuilder,
32d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao                                 const LinkerConfig& pConfig)
3337b74a387bb3993387029859c2d9d051c41c724eStephen Hines    : DynObjReader(), m_pELFReader(0), m_Builder(pBuilder) {
34d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  if (pConfig.targets().is32Bits() && pConfig.targets().isLittleEndian())
355460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    m_pELFReader = new ELFReader<32, true>(pBackend);
366f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  else if (pConfig.targets().is64Bits() && pConfig.targets().isLittleEndian())
376f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    m_pELFReader = new ELFReader<64, true>(pBackend);
385460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
395460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
4037b74a387bb3993387029859c2d9d051c41c724eStephen HinesELFDynObjReader::~ELFDynObjReader() {
415460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  delete m_pELFReader;
425460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
435460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
445460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao/// isMyFormat
4537b74a387bb3993387029859c2d9d051c41c724eStephen Hinesbool ELFDynObjReader::isMyFormat(Input& pInput, bool& pContinue) const {
465460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  assert(pInput.hasMemArea());
475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // Don't warning about the frequently requests.
495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // MemoryArea has a list of cache to handle this.
505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  size_t hdr_size = m_pELFReader->getELFHeaderSize();
5187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (pInput.memArea()->size() < hdr_size)
5287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    return false;
5387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
5437b74a387bb3993387029859c2d9d051c41c724eStephen Hines  llvm::StringRef region =
5537b74a387bb3993387029859c2d9d051c41c724eStephen Hines      pInput.memArea()->request(pInput.fileOffset(), hdr_size);
565460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
5787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  const char* ELF_hdr = region.begin();
585460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  bool result = true;
5987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (!m_pELFReader->isELF(ELF_hdr)) {
6087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    pContinue = true;
615460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    result = false;
6287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  } else if (Input::DynObj != m_pELFReader->fileType(ELF_hdr)) {
6387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    pContinue = true;
645460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    result = false;
6587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  } else if (!m_pELFReader->isMyEndian(ELF_hdr)) {
6687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    pContinue = false;
675460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    result = false;
6887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  } else if (!m_pELFReader->isMyMachine(ELF_hdr)) {
6987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    pContinue = false;
705460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    result = false;
7187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  }
725460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return result;
735460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
745460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
7522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/// readHeader
7637b74a387bb3993387029859c2d9d051c41c724eStephen Hinesbool ELFDynObjReader::readHeader(Input& pInput) {
775460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  assert(pInput.hasMemArea());
785460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
795460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  size_t hdr_size = m_pELFReader->getELFHeaderSize();
8037b74a387bb3993387029859c2d9d051c41c724eStephen Hines  llvm::StringRef region =
8137b74a387bb3993387029859c2d9d051c41c724eStephen Hines      pInput.memArea()->request(pInput.fileOffset(), hdr_size);
8287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  const char* ELF_hdr = region.begin();
835460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
8422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  bool shdr_result = m_pELFReader->readSectionHeaders(pInput, ELF_hdr);
85affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
86affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  // read .dynamic to get the correct SONAME
87affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  bool dyn_result = m_pELFReader->readDynamic(pInput);
88affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
89affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  return (shdr_result && dyn_result);
905460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
915460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
925460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao/// readSymbols
9337b74a387bb3993387029859c2d9d051c41c724eStephen Hinesbool ELFDynObjReader::readSymbols(Input& pInput) {
945460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  assert(pInput.hasMemArea());
955460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
965460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  LDSection* symtab_shdr = pInput.context()->getSection(".dynsym");
9737b74a387bb3993387029859c2d9d051c41c724eStephen Hines  if (symtab_shdr == NULL) {
9837b74a387bb3993387029859c2d9d051c41c724eStephen Hines    note(diag::note_has_no_symtab) << pInput.name() << pInput.path()
99affc150dc44fab1911775a49636d0ce85333b634Zonr Chang                                   << ".dynsym";
100affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    return true;
101affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  }
102affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
1035460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  LDSection* strtab_shdr = symtab_shdr->getLink();
10437b74a387bb3993387029859c2d9d051c41c724eStephen Hines  if (strtab_shdr == NULL) {
10537b74a387bb3993387029859c2d9d051c41c724eStephen Hines    fatal(diag::fatal_cannot_read_strtab) << pInput.name() << pInput.path()
106affc150dc44fab1911775a49636d0ce85333b634Zonr Chang                                          << ".dynsym";
1075460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    return false;
108affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  }
1095460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
11087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  llvm::StringRef symtab_region = pInput.memArea()->request(
11187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      pInput.fileOffset() + symtab_shdr->offset(), symtab_shdr->size());
1125460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
11387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  llvm::StringRef strtab_region = pInput.memArea()->request(
11487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      pInput.fileOffset() + strtab_shdr->offset(), strtab_shdr->size());
11587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  const char* strtab = strtab_region.begin();
11637b74a387bb3993387029859c2d9d051c41c724eStephen Hines  bool result =
11737b74a387bb3993387029859c2d9d051c41c724eStephen Hines      m_pELFReader->readSymbols(pInput, m_Builder, symtab_region, strtab);
1185460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return result;
1195460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
1205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
12137b74a387bb3993387029859c2d9d051c41c724eStephen Hines}  // namespace mcld
122