1a4e5f360d91ca11fc12b322d1a2bb25609b214d1Shih-wei Liao/*
2a4e5f360d91ca11fc12b322d1a2bb25609b214d1Shih-wei Liao * Copyright 2011, The Android Open Source Project
3a4e5f360d91ca11fc12b322d1a2bb25609b214d1Shih-wei Liao *
4a4e5f360d91ca11fc12b322d1a2bb25609b214d1Shih-wei Liao * Licensed under the Apache License, Version 2.0 (the "License");
5a4e5f360d91ca11fc12b322d1a2bb25609b214d1Shih-wei Liao * you may not use this file except in compliance with the License.
6a4e5f360d91ca11fc12b322d1a2bb25609b214d1Shih-wei Liao * You may obtain a copy of the License at
7a4e5f360d91ca11fc12b322d1a2bb25609b214d1Shih-wei Liao *
8a4e5f360d91ca11fc12b322d1a2bb25609b214d1Shih-wei Liao *     http://www.apache.org/licenses/LICENSE-2.0
9a4e5f360d91ca11fc12b322d1a2bb25609b214d1Shih-wei Liao *
10a4e5f360d91ca11fc12b322d1a2bb25609b214d1Shih-wei Liao * Unless required by applicable law or agreed to in writing, software
11a4e5f360d91ca11fc12b322d1a2bb25609b214d1Shih-wei Liao * distributed under the License is distributed on an "AS IS" BASIS,
12a4e5f360d91ca11fc12b322d1a2bb25609b214d1Shih-wei Liao * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13a4e5f360d91ca11fc12b322d1a2bb25609b214d1Shih-wei Liao * See the License for the specific language governing permissions and
14a4e5f360d91ca11fc12b322d1a2bb25609b214d1Shih-wei Liao * limitations under the License.
15a4e5f360d91ca11fc12b322d1a2bb25609b214d1Shih-wei Liao */
16a4e5f360d91ca11fc12b322d1a2bb25609b214d1Shih-wei Liao
1758ed8bce80acd10ea103dc9c94f83466fa500ac9Logan Chien#include "librsloader.h"
1858ed8bce80acd10ea103dc9c94f83466fa500ac9Logan Chien
1958ed8bce80acd10ea103dc9c94f83466fa500ac9Logan Chien#include "ELFObject.h"
2058ed8bce80acd10ea103dc9c94f83466fa500ac9Logan Chien#include "ELFSectionSymTab.h"
2158ed8bce80acd10ea103dc9c94f83466fa500ac9Logan Chien#include "ELFSymbol.h"
2258ed8bce80acd10ea103dc9c94f83466fa500ac9Logan Chien
2358ed8bce80acd10ea103dc9c94f83466fa500ac9Logan Chien#include "utils/serialize.h"
2458ed8bce80acd10ea103dc9c94f83466fa500ac9Logan Chien
2558ed8bce80acd10ea103dc9c94f83466fa500ac9Logan Chien#define LOG_TAG "bcc"
2658ed8bce80acd10ea103dc9c94f83466fa500ac9Logan Chien#include "cutils/log.h"
2758ed8bce80acd10ea103dc9c94f83466fa500ac9Logan Chien
2858ed8bce80acd10ea103dc9c94f83466fa500ac9Logan Chien#include <llvm/ADT/OwningPtr.h>
2958ed8bce80acd10ea103dc9c94f83466fa500ac9Logan Chien
3058ed8bce80acd10ea103dc9c94f83466fa500ac9Logan Chienstatic inline RSExecRef wrap(ELFObject<32> *object) {
3158ed8bce80acd10ea103dc9c94f83466fa500ac9Logan Chien  return reinterpret_cast<RSExecRef>(object);
3258ed8bce80acd10ea103dc9c94f83466fa500ac9Logan Chien}
3358ed8bce80acd10ea103dc9c94f83466fa500ac9Logan Chien
3458ed8bce80acd10ea103dc9c94f83466fa500ac9Logan Chienstatic inline ELFObject<32> *unwrap(RSExecRef object) {
3558ed8bce80acd10ea103dc9c94f83466fa500ac9Logan Chien  return reinterpret_cast<ELFObject<32> *>(object);
3658ed8bce80acd10ea103dc9c94f83466fa500ac9Logan Chien}
3758ed8bce80acd10ea103dc9c94f83466fa500ac9Logan Chien
3858ed8bce80acd10ea103dc9c94f83466fa500ac9Logan Chienextern "C" RSExecRef
3958ed8bce80acd10ea103dc9c94f83466fa500ac9Logan ChienrsloaderCreateExec(unsigned char const *buf,
4058ed8bce80acd10ea103dc9c94f83466fa500ac9Logan Chien                   size_t buf_size,
4158ed8bce80acd10ea103dc9c94f83466fa500ac9Logan Chien                   void *(*find_symbol)(void *, char const *),
4258ed8bce80acd10ea103dc9c94f83466fa500ac9Logan Chien                   void *find_symbol_context) {
4358ed8bce80acd10ea103dc9c94f83466fa500ac9Logan Chien
4458ed8bce80acd10ea103dc9c94f83466fa500ac9Logan Chien  ArchiveReaderLE AR(buf, buf_size);
4558ed8bce80acd10ea103dc9c94f83466fa500ac9Logan Chien
4658ed8bce80acd10ea103dc9c94f83466fa500ac9Logan Chien  llvm::OwningPtr<ELFObject<32> > object(ELFObject<32>::read(AR));
4758ed8bce80acd10ea103dc9c94f83466fa500ac9Logan Chien  if (!object) {
4858ed8bce80acd10ea103dc9c94f83466fa500ac9Logan Chien    LOGE("Unable to load the ELF object.");
4958ed8bce80acd10ea103dc9c94f83466fa500ac9Logan Chien    return NULL;
5058ed8bce80acd10ea103dc9c94f83466fa500ac9Logan Chien  }
5158ed8bce80acd10ea103dc9c94f83466fa500ac9Logan Chien
5258ed8bce80acd10ea103dc9c94f83466fa500ac9Logan Chien  //object->print();
5358ed8bce80acd10ea103dc9c94f83466fa500ac9Logan Chien  object->relocate(find_symbol, find_symbol_context);
5458ed8bce80acd10ea103dc9c94f83466fa500ac9Logan Chien
5558ed8bce80acd10ea103dc9c94f83466fa500ac9Logan Chien  return wrap(object.take());
5658ed8bce80acd10ea103dc9c94f83466fa500ac9Logan Chien}
5758ed8bce80acd10ea103dc9c94f83466fa500ac9Logan Chien
5858ed8bce80acd10ea103dc9c94f83466fa500ac9Logan Chienextern "C" void rsloaderDisposeExec(RSExecRef object) {
5958ed8bce80acd10ea103dc9c94f83466fa500ac9Logan Chien  delete unwrap(object);
6058ed8bce80acd10ea103dc9c94f83466fa500ac9Logan Chien}
6158ed8bce80acd10ea103dc9c94f83466fa500ac9Logan Chien
6258ed8bce80acd10ea103dc9c94f83466fa500ac9Logan Chienextern "C" void *rsloaderGetSymbolAddress(RSExecRef object_,
6358ed8bce80acd10ea103dc9c94f83466fa500ac9Logan Chien                                          char const *name) {
6458ed8bce80acd10ea103dc9c94f83466fa500ac9Logan Chien  ELFObject<32> *object = unwrap(object_);
6558ed8bce80acd10ea103dc9c94f83466fa500ac9Logan Chien
6658ed8bce80acd10ea103dc9c94f83466fa500ac9Logan Chien  ELFSectionSymTab<32> *symtab =
6758ed8bce80acd10ea103dc9c94f83466fa500ac9Logan Chien    static_cast<ELFSectionSymTab<32> *>(object->getSectionByName(".symtab"));
6858ed8bce80acd10ea103dc9c94f83466fa500ac9Logan Chien
6921ca257e99974ac0044012180ace2b833525e45dLogan Chien  if (!symtab) {
7021ca257e99974ac0044012180ace2b833525e45dLogan Chien    return NULL;
7121ca257e99974ac0044012180ace2b833525e45dLogan Chien  }
7221ca257e99974ac0044012180ace2b833525e45dLogan Chien
7321ca257e99974ac0044012180ace2b833525e45dLogan Chien  ELFSymbol<32> *symbol = symtab->getByName(name);
7421ca257e99974ac0044012180ace2b833525e45dLogan Chien
7521ca257e99974ac0044012180ace2b833525e45dLogan Chien  if (!symbol) {
7621ca257e99974ac0044012180ace2b833525e45dLogan Chien    LOGE("Symbol not found: %s\n", name);
7721ca257e99974ac0044012180ace2b833525e45dLogan Chien    return NULL;
7821ca257e99974ac0044012180ace2b833525e45dLogan Chien  }
7921ca257e99974ac0044012180ace2b833525e45dLogan Chien
80b2584ebd9eff677283b23ab762ef411fe16ba22dLogan Chien  return symbol->getAddress(false);
8158ed8bce80acd10ea103dc9c94f83466fa500ac9Logan Chien}
8211b53125c58adc902c1e2a60cbe667ba2344ecceLogan Chien
8311b53125c58adc902c1e2a60cbe667ba2344ecceLogan Chienextern "C" size_t rsloaderGetSymbolSize(RSExecRef object_, char const *name) {
8411b53125c58adc902c1e2a60cbe667ba2344ecceLogan Chien  ELFObject<32> *object = unwrap(object_);
8511b53125c58adc902c1e2a60cbe667ba2344ecceLogan Chien
8611b53125c58adc902c1e2a60cbe667ba2344ecceLogan Chien  ELFSectionSymTab<32> *symtab =
8711b53125c58adc902c1e2a60cbe667ba2344ecceLogan Chien    static_cast<ELFSectionSymTab<32> *>(object->getSectionByName(".symtab"));
8811b53125c58adc902c1e2a60cbe667ba2344ecceLogan Chien
8911b53125c58adc902c1e2a60cbe667ba2344ecceLogan Chien  if (!symtab) {
9011b53125c58adc902c1e2a60cbe667ba2344ecceLogan Chien    return NULL;
9111b53125c58adc902c1e2a60cbe667ba2344ecceLogan Chien  }
9211b53125c58adc902c1e2a60cbe667ba2344ecceLogan Chien
9311b53125c58adc902c1e2a60cbe667ba2344ecceLogan Chien  ELFSymbol<32> *symbol = symtab->getByName(name);
9411b53125c58adc902c1e2a60cbe667ba2344ecceLogan Chien
9511b53125c58adc902c1e2a60cbe667ba2344ecceLogan Chien  if (!symbol) {
9611b53125c58adc902c1e2a60cbe667ba2344ecceLogan Chien    LOGE("Symbol not found: %s\n", name);
9711b53125c58adc902c1e2a60cbe667ba2344ecceLogan Chien    return NULL;
9811b53125c58adc902c1e2a60cbe667ba2344ecceLogan Chien  }
9911b53125c58adc902c1e2a60cbe667ba2344ecceLogan Chien
10011b53125c58adc902c1e2a60cbe667ba2344ecceLogan Chien  return (size_t)symbol->getSize();
10111b53125c58adc902c1e2a60cbe667ba2344ecceLogan Chien}
102388f443ba0c474ffcc2e06f8d2a668c4488c3c1bLogan Chien
103388f443ba0c474ffcc2e06f8d2a668c4488c3c1bLogan Chienextern "C" size_t rsloaderGetFuncCount(RSExecRef object) {
104388f443ba0c474ffcc2e06f8d2a668c4488c3c1bLogan Chien  ELFSectionSymTab<32> *symtab = static_cast<ELFSectionSymTab<32> *>(
105388f443ba0c474ffcc2e06f8d2a668c4488c3c1bLogan Chien    unwrap(object)->getSectionByName(".symtab"));
106388f443ba0c474ffcc2e06f8d2a668c4488c3c1bLogan Chien
107388f443ba0c474ffcc2e06f8d2a668c4488c3c1bLogan Chien  if (!symtab) {
108388f443ba0c474ffcc2e06f8d2a668c4488c3c1bLogan Chien    return 0;
109388f443ba0c474ffcc2e06f8d2a668c4488c3c1bLogan Chien  }
110388f443ba0c474ffcc2e06f8d2a668c4488c3c1bLogan Chien
111388f443ba0c474ffcc2e06f8d2a668c4488c3c1bLogan Chien  return symtab->getFuncCount();
112388f443ba0c474ffcc2e06f8d2a668c4488c3c1bLogan Chien}
113388f443ba0c474ffcc2e06f8d2a668c4488c3c1bLogan Chien
114388f443ba0c474ffcc2e06f8d2a668c4488c3c1bLogan Chienextern "C" void rsloaderGetFuncNameList(RSExecRef object,
115388f443ba0c474ffcc2e06f8d2a668c4488c3c1bLogan Chien                                        size_t size,
116388f443ba0c474ffcc2e06f8d2a668c4488c3c1bLogan Chien                                        char const **list) {
117388f443ba0c474ffcc2e06f8d2a668c4488c3c1bLogan Chien  ELFSectionSymTab<32> *symtab = static_cast<ELFSectionSymTab<32> *>(
118388f443ba0c474ffcc2e06f8d2a668c4488c3c1bLogan Chien    unwrap(object)->getSectionByName(".symtab"));
119388f443ba0c474ffcc2e06f8d2a668c4488c3c1bLogan Chien
120388f443ba0c474ffcc2e06f8d2a668c4488c3c1bLogan Chien  if (symtab) {
121388f443ba0c474ffcc2e06f8d2a668c4488c3c1bLogan Chien    symtab->getFuncNameList(size, list);
122388f443ba0c474ffcc2e06f8d2a668c4488c3c1bLogan Chien  }
123388f443ba0c474ffcc2e06f8d2a668c4488c3c1bLogan Chien}
124