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