10f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang/*
20f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang * Copyright 2012, The Android Open Source Project
30f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang *
40f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang * Licensed under the Apache License, Version 2.0 (the "License");
50f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang * you may not use this file except in compliance with the License.
60f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang * You may obtain a copy of the License at
70f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang *
80f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang *     http://www.apache.org/licenses/LICENSE-2.0
90f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang *
100f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang * Unless required by applicable law or agreed to in writing, software
110f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang * distributed under the License is distributed on an "AS IS" BASIS,
120f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
130f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang * See the License for the specific language governing permissions and
140f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang * limitations under the License.
150f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang */
160f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang
170f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang#include "ELFObjectLoaderImpl.h"
180f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang
190f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang#include <llvm/Support/ELF.h>
200f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang
210f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang// The following files are included from librsloader.
220f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang#include "ELFObject.h"
230f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang#include "ELFSectionSymTab.h"
240f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang#include "ELFSymbol.h"
250f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang#include "utils/serialize.h"
260f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang
27c72c4ddfcd79c74f70713da91a69569451b5c19eZonr Chang#include "bcc/ExecutionEngine/SymbolResolverInterface.h"
28ef73a242762bcd8113b9b65ceccbe7d909b5acbcZonr Chang#include "bcc/Support/Log.h"
290f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang
300f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Changusing namespace bcc;
310f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang
320f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Changbool ELFObjectLoaderImpl::load(const void *pMem, size_t pMemSize) {
330f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang  ArchiveReaderLE reader(reinterpret_cast<const unsigned char *>(pMem),
340f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang                         pMemSize);
350f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang
360f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang  mObject = ELFObject<32>::read(reader);
370f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang  if (mObject == NULL) {
380f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang    ALOGE("Unable to load the ELF object!");
390f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang    return false;
400f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang  }
410f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang
420f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang  // Retrive the pointer to the symbol table.
430f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang  mSymTab = static_cast<ELFSectionSymTab<32> *>(
440f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang                mObject->getSectionByName(".symtab"));
450f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang  if (mSymTab == NULL) {
460f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang    ALOGW("Object doesn't contain any symbol table.");
470f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang  }
480f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang
490f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang  return true;
500f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang}
510f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang
520f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Changbool ELFObjectLoaderImpl::relocate(SymbolResolverInterface &pResolver) {
530f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang  mObject->relocate(SymbolResolverInterface::LookupFunction, &pResolver);
540f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang
550f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang  if (mObject->getMissingSymbols()) {
560f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang    ALOGE("Some symbols are found to be undefined during relocation!");
570f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang    return false;
580f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang  }
590f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang
600f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang  return true;
610f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang}
620f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang
630f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Changbool ELFObjectLoaderImpl::prepareDebugImage(void *pDebugImg,
640f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang                                            size_t pDebugImgSize) {
650f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang  // Update the value of sh_addr in pDebugImg to its corresponding section in
660f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang  // the mObject.
670f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang  llvm::ELF::Elf32_Ehdr *elf_header =
680f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang      reinterpret_cast<llvm::ELF::Elf32_Ehdr *>(pDebugImg);
690f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang
700f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang  if (elf_header->e_shoff > pDebugImgSize) {
710f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang    ALOGE("Invalid section header table offset found! (e_shoff = %d)",
720f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang          elf_header->e_shoff);
730f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang    return false;
740f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang  }
750f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang
760f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang  if ((elf_header->e_shoff +
770f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang       sizeof(llvm::ELF::Elf32_Shdr) * elf_header->e_shnum) > pDebugImgSize) {
780f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang    ALOGE("Invalid image supplied (debug image doesn't contain all the section"
790f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang          "header or corrupted image)! (e_shoff = %d, e_shnum = %d)",
800f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang          elf_header->e_shoff, elf_header->e_shnum);
810f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang    return false;
820f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang  }
830f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang
840f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang  llvm::ELF::Elf32_Shdr *section_header_table =
850f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang      reinterpret_cast<llvm::ELF::Elf32_Shdr *>(
860f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang          reinterpret_cast<uint8_t*>(pDebugImg) + elf_header->e_shoff);
870f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang
880f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang  for (unsigned i = 0; i < elf_header->e_shnum; i++) {
890f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang    if (section_header_table[i].sh_flags & llvm::ELF::SHF_ALLOC) {
900f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang      ELFSectionBits<32> *section =
910f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang          static_cast<ELFSectionBits<32> *>(mObject->getSectionByIndex(i));
920f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang      if (section != NULL) {
930f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang        section_header_table[i].sh_addr =
940f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang            reinterpret_cast<llvm::ELF::Elf32_Addr>(section->getBuffer());
950f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang      }
960f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang    }
970f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang  }
980f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang
990f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang  return true;
1000f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang}
1010f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang
1020f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Changvoid *ELFObjectLoaderImpl::getSymbolAddress(const char *pName) const {
1030f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang  if (mSymTab == NULL) {
1040f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang    return NULL;
1050f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang  }
1060f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang
1079795754a34648d962f00ced51183b759b9eaf2b2Shih-wei Liao  const ELFSymbol<32> *symbol = mSymTab->getByName(pName);
1080f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang  if (symbol == NULL) {
1090f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang    ALOGV("Request symbol '%s' is not found in the object!", pName);
1100f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang    return NULL;
1110f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang  }
1120f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang
1130f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang  return symbol->getAddress(mObject->getHeader()->getMachine(),
1140f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang                            /* autoAlloc */false);
1150f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang}
1160f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang
1179795754a34648d962f00ced51183b759b9eaf2b2Shih-wei Liaosize_t ELFObjectLoaderImpl::getSymbolSize(const char *pName) const {
1189795754a34648d962f00ced51183b759b9eaf2b2Shih-wei Liao  if (mSymTab == NULL) {
1199795754a34648d962f00ced51183b759b9eaf2b2Shih-wei Liao    return 0;
1209795754a34648d962f00ced51183b759b9eaf2b2Shih-wei Liao  }
1219795754a34648d962f00ced51183b759b9eaf2b2Shih-wei Liao
1229795754a34648d962f00ced51183b759b9eaf2b2Shih-wei Liao  const ELFSymbol<32> *symbol = mSymTab->getByName(pName);
1239795754a34648d962f00ced51183b759b9eaf2b2Shih-wei Liao
1249795754a34648d962f00ced51183b759b9eaf2b2Shih-wei Liao  if (symbol == NULL) {
1259795754a34648d962f00ced51183b759b9eaf2b2Shih-wei Liao    ALOGV("Request symbol '%s' is not found in the object!", pName);
1269795754a34648d962f00ced51183b759b9eaf2b2Shih-wei Liao    return 0;
1279795754a34648d962f00ced51183b759b9eaf2b2Shih-wei Liao  }
1289795754a34648d962f00ced51183b759b9eaf2b2Shih-wei Liao
1299795754a34648d962f00ced51183b759b9eaf2b2Shih-wei Liao  return static_cast<size_t>(symbol->getSize());
1309795754a34648d962f00ced51183b759b9eaf2b2Shih-wei Liao
1319795754a34648d962f00ced51183b759b9eaf2b2Shih-wei Liao}
1329795754a34648d962f00ced51183b759b9eaf2b2Shih-wei Liao
1339795754a34648d962f00ced51183b759b9eaf2b2Shih-wei Liaobool
1349795754a34648d962f00ced51183b759b9eaf2b2Shih-wei LiaoELFObjectLoaderImpl::getSymbolNameList(android::Vector<const char *>& pNameList,
1359795754a34648d962f00ced51183b759b9eaf2b2Shih-wei Liao                                       ObjectLoader::SymbolType pType) const {
1369795754a34648d962f00ced51183b759b9eaf2b2Shih-wei Liao  if (mSymTab == NULL) {
1379795754a34648d962f00ced51183b759b9eaf2b2Shih-wei Liao    return false;
1389795754a34648d962f00ced51183b759b9eaf2b2Shih-wei Liao  }
1399795754a34648d962f00ced51183b759b9eaf2b2Shih-wei Liao
1409795754a34648d962f00ced51183b759b9eaf2b2Shih-wei Liao  unsigned elf_type;
1419795754a34648d962f00ced51183b759b9eaf2b2Shih-wei Liao  switch (pType) {
1429795754a34648d962f00ced51183b759b9eaf2b2Shih-wei Liao    case ObjectLoader::kFunctionType: {
1439795754a34648d962f00ced51183b759b9eaf2b2Shih-wei Liao      elf_type = llvm::ELF::STT_FUNC;
1449795754a34648d962f00ced51183b759b9eaf2b2Shih-wei Liao      break;
1459795754a34648d962f00ced51183b759b9eaf2b2Shih-wei Liao    }
1469795754a34648d962f00ced51183b759b9eaf2b2Shih-wei Liao    case ObjectLoader::kUnknownType: {
1479795754a34648d962f00ced51183b759b9eaf2b2Shih-wei Liao      break;
1489795754a34648d962f00ced51183b759b9eaf2b2Shih-wei Liao    }
1499795754a34648d962f00ced51183b759b9eaf2b2Shih-wei Liao    default: {
1509795754a34648d962f00ced51183b759b9eaf2b2Shih-wei Liao      assert(false && "Invalid symbol type given!");
1519795754a34648d962f00ced51183b759b9eaf2b2Shih-wei Liao      return false;
1529795754a34648d962f00ced51183b759b9eaf2b2Shih-wei Liao    }
1539795754a34648d962f00ced51183b759b9eaf2b2Shih-wei Liao  }
1549795754a34648d962f00ced51183b759b9eaf2b2Shih-wei Liao
1559795754a34648d962f00ced51183b759b9eaf2b2Shih-wei Liao  for (size_t i = 0, e = mSymTab->size(); i != e; i++) {
1569795754a34648d962f00ced51183b759b9eaf2b2Shih-wei Liao    ELFSymbol<32> *symbol = (*mSymTab)[i];
1579795754a34648d962f00ced51183b759b9eaf2b2Shih-wei Liao    if (symbol == NULL) {
1589795754a34648d962f00ced51183b759b9eaf2b2Shih-wei Liao      continue;
1599795754a34648d962f00ced51183b759b9eaf2b2Shih-wei Liao    }
1609795754a34648d962f00ced51183b759b9eaf2b2Shih-wei Liao
1619795754a34648d962f00ced51183b759b9eaf2b2Shih-wei Liao    if ((pType == ObjectLoader::kUnknownType) ||
1629795754a34648d962f00ced51183b759b9eaf2b2Shih-wei Liao        (symbol->getType() == elf_type)) {
1639795754a34648d962f00ced51183b759b9eaf2b2Shih-wei Liao      const char *symbol_name = symbol->getName();
1649795754a34648d962f00ced51183b759b9eaf2b2Shih-wei Liao      if (symbol_name != NULL) {
1659795754a34648d962f00ced51183b759b9eaf2b2Shih-wei Liao        pNameList.push_back(symbol_name);
1669795754a34648d962f00ced51183b759b9eaf2b2Shih-wei Liao      }
1679795754a34648d962f00ced51183b759b9eaf2b2Shih-wei Liao    }
1689795754a34648d962f00ced51183b759b9eaf2b2Shih-wei Liao  }
1699795754a34648d962f00ced51183b759b9eaf2b2Shih-wei Liao
1709795754a34648d962f00ced51183b759b9eaf2b2Shih-wei Liao  return true;
1719795754a34648d962f00ced51183b759b9eaf2b2Shih-wei Liao}
1729795754a34648d962f00ced51183b759b9eaf2b2Shih-wei Liao
1730f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr ChangELFObjectLoaderImpl::~ELFObjectLoaderImpl() {
1740f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang  delete mObject;
1750f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang  return;
1760f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang}
177