ELFDynObjReader.cpp revision f33f6de54db174aa679a4b6d1e040d37e95541c0
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 <mcld/LD/ELFDynObjReader.h> 10 11#include <mcld/LinkerConfig.h> 12#include <mcld/IRBuilder.h> 13#include <mcld/LD/ELFReader.h> 14#include <mcld/MC/Input.h> 15#include <mcld/Target/GNULDBackend.h> 16#include <mcld/Support/MemoryArea.h> 17 18#include <llvm/ADT/StringRef.h> 19#include <llvm/ADT/Twine.h> 20#include <llvm/ADT/OwningPtr.h> 21#include <llvm/Support/ErrorHandling.h> 22 23#include <string> 24 25using namespace mcld; 26 27//===----------------------------------------------------------------------===// 28// ELFDynObjReader 29//===----------------------------------------------------------------------===// 30ELFDynObjReader::ELFDynObjReader(GNULDBackend& pBackend, 31 IRBuilder& pBuilder, 32 const LinkerConfig& pConfig) 33 : DynObjReader(), 34 m_pELFReader(0), 35 m_Builder(pBuilder) { 36 if (pConfig.targets().is32Bits() && pConfig.targets().isLittleEndian()) 37 m_pELFReader = new ELFReader<32, true>(pBackend); 38 else if (pConfig.targets().is64Bits() && pConfig.targets().isLittleEndian()) 39 m_pELFReader = new ELFReader<64, true>(pBackend); 40} 41 42ELFDynObjReader::~ELFDynObjReader() 43{ 44 delete m_pELFReader; 45} 46 47/// isMyFormat 48bool ELFDynObjReader::isMyFormat(Input &pInput, bool &pContinue) const 49{ 50 assert(pInput.hasMemArea()); 51 52 // Don't warning about the frequently requests. 53 // MemoryArea has a list of cache to handle this. 54 size_t hdr_size = m_pELFReader->getELFHeaderSize(); 55 if (pInput.memArea()->size() < hdr_size) 56 return false; 57 58 llvm::StringRef region = pInput.memArea()->request(pInput.fileOffset(), 59 hdr_size); 60 61 const char* ELF_hdr = region.begin(); 62 bool result = true; 63 if (!m_pELFReader->isELF(ELF_hdr)) { 64 pContinue = true; 65 result = false; 66 } else if (Input::DynObj != m_pELFReader->fileType(ELF_hdr)) { 67 pContinue = true; 68 result = false; 69 } else if (!m_pELFReader->isMyEndian(ELF_hdr)) { 70 pContinue = false; 71 result = false; 72 } else if (!m_pELFReader->isMyMachine(ELF_hdr)) { 73 pContinue = false; 74 result = false; 75 } 76 return result; 77} 78 79/// readHeader 80bool ELFDynObjReader::readHeader(Input& pInput) 81{ 82 assert(pInput.hasMemArea()); 83 84 size_t hdr_size = m_pELFReader->getELFHeaderSize(); 85 llvm::StringRef region = pInput.memArea()->request(pInput.fileOffset(), 86 hdr_size); 87 const char* ELF_hdr = region.begin(); 88 89 bool shdr_result = m_pELFReader->readSectionHeaders(pInput, ELF_hdr); 90 91 // read .dynamic to get the correct SONAME 92 bool dyn_result = m_pELFReader->readDynamic(pInput); 93 94 return (shdr_result && dyn_result); 95} 96 97/// readSymbols 98bool ELFDynObjReader::readSymbols(Input& pInput) 99{ 100 assert(pInput.hasMemArea()); 101 102 LDSection* symtab_shdr = pInput.context()->getSection(".dynsym"); 103 if (NULL == symtab_shdr) { 104 note(diag::note_has_no_symtab) << pInput.name() 105 << pInput.path() 106 << ".dynsym"; 107 return true; 108 } 109 110 LDSection* strtab_shdr = symtab_shdr->getLink(); 111 if (NULL == strtab_shdr) { 112 fatal(diag::fatal_cannot_read_strtab) << pInput.name() 113 << pInput.path() 114 << ".dynsym"; 115 return false; 116 } 117 118 llvm::StringRef symtab_region = pInput.memArea()->request( 119 pInput.fileOffset() + symtab_shdr->offset(), symtab_shdr->size()); 120 121 llvm::StringRef strtab_region = pInput.memArea()->request( 122 pInput.fileOffset() + strtab_shdr->offset(), strtab_shdr->size()); 123 const char* strtab = strtab_region.begin(); 124 bool result = m_pELFReader->readSymbols(pInput, m_Builder, 125 symtab_region, strtab); 126 return result; 127} 128 129