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