ELFDynObjReader.cpp revision affc150dc44fab1911775a49636d0ce85333b634
1//===- ELFDynObjReader.cpp ------------------------------------------------===//
2//
3//                     The MCLinker Project
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9#include <llvm/ADT/Twine.h>
10#include <llvm/ADT/OwningPtr.h>
11#include <llvm/Support/ErrorHandling.h>
12
13#include <mcld/LD/ELFDynObjReader.h>
14#include <mcld/LD/ELFReader.h>
15#include <mcld/MC/MCLDInput.h>
16#include <mcld/MC/MCLinker.h>
17#include <mcld/Target/GNULDBackend.h>
18#include <mcld/Support/MemoryRegion.h>
19
20#include <string>
21
22using namespace mcld;
23
24//==========================
25// ELFDynObjReader
26ELFDynObjReader::ELFDynObjReader(GNULDBackend& pBackend, MCLinker& pLinker)
27  : DynObjReader(),
28    m_pELFReader(0),
29    m_Linker(pLinker) {
30  if (32 == pBackend.bitclass() && pBackend.isLittleEndian())
31    m_pELFReader = new ELFReader<32, true>(pBackend);
32}
33
34ELFDynObjReader::~ELFDynObjReader()
35{
36  delete m_pELFReader;
37}
38
39/// isMyFormat
40bool ELFDynObjReader::isMyFormat(Input &pInput) const
41{
42  assert(pInput.hasMemArea());
43
44  // Don't warning about the frequently requests.
45  // MemoryArea has a list of cache to handle this.
46  size_t hdr_size = m_pELFReader->getELFHeaderSize();
47  MemoryRegion* region = pInput.memArea()->request(0, hdr_size);
48
49  uint8_t* ELF_hdr = region->start();
50  bool result = true;
51  if (!m_pELFReader->isELF(ELF_hdr))
52    result = false;
53  else if (!m_pELFReader->isMyEndian(ELF_hdr))
54    result = false;
55  else if (!m_pELFReader->isMyMachine(ELF_hdr))
56    result = false;
57  else if (MCLDFile::DynObj != m_pELFReader->fileType(ELF_hdr))
58    result = false;
59  pInput.memArea()->release(region);
60  return result;
61}
62
63/// readDSO
64bool ELFDynObjReader::readDSO(Input& pInput)
65{
66  assert(pInput.hasMemArea());
67
68  size_t hdr_size = m_pELFReader->getELFHeaderSize();
69  MemoryRegion* region = pInput.memArea()->request(0, hdr_size);
70  uint8_t* ELF_hdr = region->start();
71
72  bool shdr_result = m_pELFReader->readSectionHeaders(pInput, m_Linker, ELF_hdr);
73  pInput.memArea()->release(region);
74
75  // read .dynamic to get the correct SONAME
76  bool dyn_result = m_pELFReader->readDynamic(pInput);
77
78  return (shdr_result && dyn_result);
79}
80
81/// readSymbols
82bool ELFDynObjReader::readSymbols(Input& pInput)
83{
84  assert(pInput.hasMemArea());
85
86  LDSection* symtab_shdr = pInput.context()->getSection(".dynsym");
87  if (NULL == symtab_shdr) {
88    note(diag::note_has_no_symtab) << pInput.name()
89                                   << pInput.path()
90                                   << ".dynsym";
91    return true;
92  }
93
94  LDSection* strtab_shdr = symtab_shdr->getLink();
95  if (NULL == strtab_shdr) {
96    fatal(diag::fatal_cannot_read_strtab) << pInput.name()
97                                          << pInput.path()
98                                          << ".dynsym";
99    return false;
100  }
101
102  MemoryRegion* symtab_region = pInput.memArea()->request(symtab_shdr->offset(),
103                                                          symtab_shdr->size());
104
105  MemoryRegion* strtab_region = pInput.memArea()->request(strtab_shdr->offset(),
106                                                          strtab_shdr->size());
107  char* strtab = reinterpret_cast<char*>(strtab_region->start());
108  bool result = m_pELFReader->readSymbols(pInput, m_Linker, *symtab_region, strtab);
109  pInput.memArea()->release(symtab_region);
110  pInput.memArea()->release(strtab_region);
111
112  return result;
113}
114
115