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 24 using namespace mcld; 25 26 //===----------------------------------------------------------------------===// 27 // ELFDynObjReader 28 //===----------------------------------------------------------------------===// 29 ELFDynObjReader::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 41 ELFDynObjReader::~ELFDynObjReader() 42 { 43 delete m_pELFReader; 44 } 45 46 /// isMyFormat 47 bool 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 79 bool 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 97 bool 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