15460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//===- ELFDynObjReader.cpp ------------------------------------------------===// 25460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// 35460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// The MCLinker Project 45460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// 55460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// This file is distributed under the University of Illinois Open Source 65460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// License. See LICENSE.TXT for details. 75460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// 85460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//===----------------------------------------------------------------------===// 937b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/LD/ELFDynObjReader.h" 10d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao 1137b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/IRBuilder.h" 1237b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/LinkerConfig.h" 1337b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/LD/ELFReader.h" 1437b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/LD/LDContext.h" 1537b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/MC/Input.h" 1637b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Support/MemoryArea.h" 1737b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Target/GNULDBackend.h" 18d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao 1987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines#include <llvm/ADT/StringRef.h> 20d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao#include <llvm/ADT/Twine.h> 21d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao#include <llvm/Support/ErrorHandling.h> 225460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <string> 245460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2537b74a387bb3993387029859c2d9d051c41c724eStephen Hinesnamespace mcld { 265460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao//===----------------------------------------------------------------------===// 285460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// ELFDynObjReader 2922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao//===----------------------------------------------------------------------===// 30d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoELFDynObjReader::ELFDynObjReader(GNULDBackend& pBackend, 31d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao IRBuilder& pBuilder, 32d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao const LinkerConfig& pConfig) 3337b74a387bb3993387029859c2d9d051c41c724eStephen Hines : DynObjReader(), m_pELFReader(0), m_Builder(pBuilder) { 34d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao if (pConfig.targets().is32Bits() && pConfig.targets().isLittleEndian()) 355460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao m_pELFReader = new ELFReader<32, true>(pBackend); 366f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines else if (pConfig.targets().is64Bits() && pConfig.targets().isLittleEndian()) 376f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines m_pELFReader = new ELFReader<64, true>(pBackend); 385460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 395460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 4037b74a387bb3993387029859c2d9d051c41c724eStephen HinesELFDynObjReader::~ELFDynObjReader() { 415460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao delete m_pELFReader; 425460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 435460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 445460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao/// isMyFormat 4537b74a387bb3993387029859c2d9d051c41c724eStephen Hinesbool ELFDynObjReader::isMyFormat(Input& pInput, bool& pContinue) const { 465460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao assert(pInput.hasMemArea()); 475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // Don't warning about the frequently requests. 495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // MemoryArea has a list of cache to handle this. 505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao size_t hdr_size = m_pELFReader->getELFHeaderSize(); 5187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines if (pInput.memArea()->size() < hdr_size) 5287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines return false; 5387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines 5437b74a387bb3993387029859c2d9d051c41c724eStephen Hines llvm::StringRef region = 5537b74a387bb3993387029859c2d9d051c41c724eStephen Hines pInput.memArea()->request(pInput.fileOffset(), hdr_size); 565460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 5787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines const char* ELF_hdr = region.begin(); 585460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao bool result = true; 5987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines if (!m_pELFReader->isELF(ELF_hdr)) { 6087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines pContinue = true; 615460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao result = false; 6287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines } else if (Input::DynObj != m_pELFReader->fileType(ELF_hdr)) { 6387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines pContinue = true; 645460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao result = false; 6587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines } else if (!m_pELFReader->isMyEndian(ELF_hdr)) { 6687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines pContinue = false; 675460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao result = false; 6887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines } else if (!m_pELFReader->isMyMachine(ELF_hdr)) { 6987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines pContinue = false; 705460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao result = false; 7187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines } 725460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return result; 735460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 745460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 7522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/// readHeader 7637b74a387bb3993387029859c2d9d051c41c724eStephen Hinesbool ELFDynObjReader::readHeader(Input& pInput) { 775460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao assert(pInput.hasMemArea()); 785460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 795460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao size_t hdr_size = m_pELFReader->getELFHeaderSize(); 8037b74a387bb3993387029859c2d9d051c41c724eStephen Hines llvm::StringRef region = 8137b74a387bb3993387029859c2d9d051c41c724eStephen Hines pInput.memArea()->request(pInput.fileOffset(), hdr_size); 8287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines const char* ELF_hdr = region.begin(); 835460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 8422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao bool shdr_result = m_pELFReader->readSectionHeaders(pInput, ELF_hdr); 85affc150dc44fab1911775a49636d0ce85333b634Zonr Chang 86affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // read .dynamic to get the correct SONAME 87affc150dc44fab1911775a49636d0ce85333b634Zonr Chang bool dyn_result = m_pELFReader->readDynamic(pInput); 88affc150dc44fab1911775a49636d0ce85333b634Zonr Chang 89affc150dc44fab1911775a49636d0ce85333b634Zonr Chang return (shdr_result && dyn_result); 905460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 915460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 925460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao/// readSymbols 9337b74a387bb3993387029859c2d9d051c41c724eStephen Hinesbool ELFDynObjReader::readSymbols(Input& pInput) { 945460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao assert(pInput.hasMemArea()); 955460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 965460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao LDSection* symtab_shdr = pInput.context()->getSection(".dynsym"); 9737b74a387bb3993387029859c2d9d051c41c724eStephen Hines if (symtab_shdr == NULL) { 9837b74a387bb3993387029859c2d9d051c41c724eStephen Hines note(diag::note_has_no_symtab) << pInput.name() << pInput.path() 99affc150dc44fab1911775a49636d0ce85333b634Zonr Chang << ".dynsym"; 100affc150dc44fab1911775a49636d0ce85333b634Zonr Chang return true; 101affc150dc44fab1911775a49636d0ce85333b634Zonr Chang } 102affc150dc44fab1911775a49636d0ce85333b634Zonr Chang 1035460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao LDSection* strtab_shdr = symtab_shdr->getLink(); 10437b74a387bb3993387029859c2d9d051c41c724eStephen Hines if (strtab_shdr == NULL) { 10537b74a387bb3993387029859c2d9d051c41c724eStephen Hines fatal(diag::fatal_cannot_read_strtab) << pInput.name() << pInput.path() 106affc150dc44fab1911775a49636d0ce85333b634Zonr Chang << ".dynsym"; 1075460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return false; 108affc150dc44fab1911775a49636d0ce85333b634Zonr Chang } 1095460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 11087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines llvm::StringRef symtab_region = pInput.memArea()->request( 11187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines pInput.fileOffset() + symtab_shdr->offset(), symtab_shdr->size()); 1125460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 11387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines llvm::StringRef strtab_region = pInput.memArea()->request( 11487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines pInput.fileOffset() + strtab_shdr->offset(), strtab_shdr->size()); 11587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines const char* strtab = strtab_region.begin(); 11637b74a387bb3993387029859c2d9d051c41c724eStephen Hines bool result = 11737b74a387bb3993387029859c2d9d051c41c724eStephen Hines m_pELFReader->readSymbols(pInput, m_Builder, symtab_region, strtab); 1185460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return result; 1195460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 1205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 12137b74a387bb3993387029859c2d9d051c41c724eStephen Hines} // namespace mcld 122