/* * Copyright 2012, The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "ELFObjectLoaderImpl.h" #include <llvm/Support/ELF.h> // The following files are included from librsloader. #include "ELFObject.h" #include "ELFSectionSymTab.h" #include "ELFSymbol.h" #include "utils/serialize.h" #include "bcc/ExecutionEngine/SymbolResolverInterface.h" #include "bcc/Support/Log.h" using namespace bcc; bool ELFObjectLoaderImpl::load(const void *pMem, size_t pMemSize) { ArchiveReaderLE reader(reinterpret_cast<const unsigned char *>(pMem), pMemSize); mObject = ELFObject<32>::read(reader); if (mObject == NULL) { ALOGE("Unable to load the ELF object!"); return false; } // Retrive the pointer to the symbol table. mSymTab = static_cast<ELFSectionSymTab<32> *>( mObject->getSectionByName(".symtab")); if (mSymTab == NULL) { ALOGW("Object doesn't contain any symbol table."); } return true; } bool ELFObjectLoaderImpl::relocate(SymbolResolverInterface &pResolver) { mObject->relocate(SymbolResolverInterface::LookupFunction, &pResolver); if (mObject->getMissingSymbols()) { ALOGE("Some symbols are found to be undefined during relocation!"); return false; } return true; } bool ELFObjectLoaderImpl::prepareDebugImage(void *pDebugImg, size_t pDebugImgSize) { // Update the value of sh_addr in pDebugImg to its corresponding section in // the mObject. llvm::ELF::Elf32_Ehdr *elf_header = reinterpret_cast<llvm::ELF::Elf32_Ehdr *>(pDebugImg); if (elf_header->e_shoff > pDebugImgSize) { ALOGE("Invalid section header table offset found! (e_shoff = %d)", elf_header->e_shoff); return false; } if ((elf_header->e_shoff + sizeof(llvm::ELF::Elf32_Shdr) * elf_header->e_shnum) > pDebugImgSize) { ALOGE("Invalid image supplied (debug image doesn't contain all the section" "header or corrupted image)! (e_shoff = %d, e_shnum = %d)", elf_header->e_shoff, elf_header->e_shnum); return false; } llvm::ELF::Elf32_Shdr *section_header_table = reinterpret_cast<llvm::ELF::Elf32_Shdr *>( reinterpret_cast<uint8_t*>(pDebugImg) + elf_header->e_shoff); for (unsigned i = 0; i < elf_header->e_shnum; i++) { if (section_header_table[i].sh_flags & llvm::ELF::SHF_ALLOC) { ELFSectionBits<32> *section = static_cast<ELFSectionBits<32> *>(mObject->getSectionByIndex(i)); if (section != NULL) { section_header_table[i].sh_addr = reinterpret_cast<llvm::ELF::Elf32_Addr>(section->getBuffer()); } } } return true; } void *ELFObjectLoaderImpl::getSymbolAddress(const char *pName) const { if (mSymTab == NULL) { return NULL; } const ELFSymbol<32> *symbol = mSymTab->getByName(pName); if (symbol == NULL) { ALOGV("Request symbol '%s' is not found in the object!", pName); return NULL; } return symbol->getAddress(mObject->getHeader()->getMachine(), /* autoAlloc */false); } size_t ELFObjectLoaderImpl::getSymbolSize(const char *pName) const { if (mSymTab == NULL) { return 0; } const ELFSymbol<32> *symbol = mSymTab->getByName(pName); if (symbol == NULL) { ALOGV("Request symbol '%s' is not found in the object!", pName); return 0; } return static_cast<size_t>(symbol->getSize()); } bool ELFObjectLoaderImpl::getSymbolNameList(android::Vector<const char *>& pNameList, ObjectLoader::SymbolType pType) const { if (mSymTab == NULL) { return false; } unsigned elf_type; switch (pType) { case ObjectLoader::kFunctionType: { elf_type = llvm::ELF::STT_FUNC; break; } case ObjectLoader::kUnknownType: { break; } default: { assert(false && "Invalid symbol type given!"); return false; } } for (size_t i = 0, e = mSymTab->size(); i != e; i++) { ELFSymbol<32> *symbol = (*mSymTab)[i]; if (symbol == NULL) { continue; } if ((pType == ObjectLoader::kUnknownType) || (symbol->getType() == elf_type)) { const char *symbol_name = symbol->getName(); if (symbol_name != NULL) { pNameList.push_back(symbol_name); } } } return true; } ELFObjectLoaderImpl::~ELFObjectLoaderImpl() { delete mObject; return; }