1a4e5f360d91ca11fc12b322d1a2bb25609b214d1Shih-wei Liao/*
2ce2e754ed4b1aefe607bbbddd8ce0e6cba824e8fStephen Hines * Copyright 2011-2012, 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>
29ce2e754ed4b1aefe607bbbddd8ce0e6cba824e8fStephen Hines#include <llvm/Support/ELF.h>
3058ed8bce80acd10ea103dc9c94f83466fa500ac9Logan Chien
3158ed8bce80acd10ea103dc9c94f83466fa500ac9Logan Chienstatic inline RSExecRef wrap(ELFObject<32> *object) {
3258ed8bce80acd10ea103dc9c94f83466fa500ac9Logan Chien  return reinterpret_cast<RSExecRef>(object);
3358ed8bce80acd10ea103dc9c94f83466fa500ac9Logan Chien}
3458ed8bce80acd10ea103dc9c94f83466fa500ac9Logan Chien
3558ed8bce80acd10ea103dc9c94f83466fa500ac9Logan Chienstatic inline ELFObject<32> *unwrap(RSExecRef object) {
3658ed8bce80acd10ea103dc9c94f83466fa500ac9Logan Chien  return reinterpret_cast<ELFObject<32> *>(object);
3758ed8bce80acd10ea103dc9c94f83466fa500ac9Logan Chien}
3858ed8bce80acd10ea103dc9c94f83466fa500ac9Logan Chien
395cfca93f7c7279365114e8feded33b94dbcd38c6Logan Chienextern "C" RSExecRef rsloaderCreateExec(unsigned char const *buf,
405cfca93f7c7279365114e8feded33b94dbcd38c6Logan Chien                                        size_t buf_size,
415cfca93f7c7279365114e8feded33b94dbcd38c6Logan Chien                                        RSFindSymbolFn find_symbol,
425cfca93f7c7279365114e8feded33b94dbcd38c6Logan Chien                                        void *find_symbol_context) {
435cfca93f7c7279365114e8feded33b94dbcd38c6Logan Chien  RSExecRef object = rsloaderLoadExecutable(buf, buf_size);
445cfca93f7c7279365114e8feded33b94dbcd38c6Logan Chien  if (!object) {
455cfca93f7c7279365114e8feded33b94dbcd38c6Logan Chien    return NULL;
465cfca93f7c7279365114e8feded33b94dbcd38c6Logan Chien  }
475cfca93f7c7279365114e8feded33b94dbcd38c6Logan Chien
485cfca93f7c7279365114e8feded33b94dbcd38c6Logan Chien  if (!rsloaderRelocateExecutable(object, find_symbol, find_symbol_context)) {
495cfca93f7c7279365114e8feded33b94dbcd38c6Logan Chien    rsloaderDisposeExec(object);
505cfca93f7c7279365114e8feded33b94dbcd38c6Logan Chien    return NULL;
515cfca93f7c7279365114e8feded33b94dbcd38c6Logan Chien  }
525cfca93f7c7279365114e8feded33b94dbcd38c6Logan Chien
535cfca93f7c7279365114e8feded33b94dbcd38c6Logan Chien  return object;
545cfca93f7c7279365114e8feded33b94dbcd38c6Logan Chien}
5558ed8bce80acd10ea103dc9c94f83466fa500ac9Logan Chien
565cfca93f7c7279365114e8feded33b94dbcd38c6Logan Chienextern "C" RSExecRef rsloaderLoadExecutable(unsigned char const *buf,
575cfca93f7c7279365114e8feded33b94dbcd38c6Logan Chien                                            size_t buf_size) {
5858ed8bce80acd10ea103dc9c94f83466fa500ac9Logan Chien  ArchiveReaderLE AR(buf, buf_size);
5958ed8bce80acd10ea103dc9c94f83466fa500ac9Logan Chien
6058ed8bce80acd10ea103dc9c94f83466fa500ac9Logan Chien  llvm::OwningPtr<ELFObject<32> > object(ELFObject<32>::read(AR));
6158ed8bce80acd10ea103dc9c94f83466fa500ac9Logan Chien  if (!object) {
62c9acf1fd2d58985b95793374b15cc3bdd11e271bSteve Block    ALOGE("Unable to load the ELF object.");
6358ed8bce80acd10ea103dc9c94f83466fa500ac9Logan Chien    return NULL;
6458ed8bce80acd10ea103dc9c94f83466fa500ac9Logan Chien  }
6558ed8bce80acd10ea103dc9c94f83466fa500ac9Logan Chien
6658ed8bce80acd10ea103dc9c94f83466fa500ac9Logan Chien  return wrap(object.take());
6758ed8bce80acd10ea103dc9c94f83466fa500ac9Logan Chien}
6858ed8bce80acd10ea103dc9c94f83466fa500ac9Logan Chien
695cfca93f7c7279365114e8feded33b94dbcd38c6Logan Chienextern "C" int rsloaderRelocateExecutable(RSExecRef object_,
705cfca93f7c7279365114e8feded33b94dbcd38c6Logan Chien                                          RSFindSymbolFn find_symbol,
715cfca93f7c7279365114e8feded33b94dbcd38c6Logan Chien                                          void *find_symbol_context) {
725cfca93f7c7279365114e8feded33b94dbcd38c6Logan Chien  ELFObject<32>* object = unwrap(object_);
735cfca93f7c7279365114e8feded33b94dbcd38c6Logan Chien
745cfca93f7c7279365114e8feded33b94dbcd38c6Logan Chien  object->relocate(find_symbol, find_symbol_context);
755cfca93f7c7279365114e8feded33b94dbcd38c6Logan Chien  return (object->getMissingSymbols() == 0);
765cfca93f7c7279365114e8feded33b94dbcd38c6Logan Chien}
775cfca93f7c7279365114e8feded33b94dbcd38c6Logan Chien
78ce2e754ed4b1aefe607bbbddd8ce0e6cba824e8fStephen Hinesextern "C" void rsloaderUpdateSectionHeaders(RSExecRef object_,
79ce2e754ed4b1aefe607bbbddd8ce0e6cba824e8fStephen Hines                                             unsigned char *buf) {
80ce2e754ed4b1aefe607bbbddd8ce0e6cba824e8fStephen Hines  ELFObject<32> *object = unwrap(object_);
81ce2e754ed4b1aefe607bbbddd8ce0e6cba824e8fStephen Hines
82ce2e754ed4b1aefe607bbbddd8ce0e6cba824e8fStephen Hines  // Remap the section header addresses to match the loaded code
83ce2e754ed4b1aefe607bbbddd8ce0e6cba824e8fStephen Hines  llvm::ELF::Elf32_Ehdr* header = reinterpret_cast<llvm::ELF::Elf32_Ehdr*>(buf);
84ce2e754ed4b1aefe607bbbddd8ce0e6cba824e8fStephen Hines
85ce2e754ed4b1aefe607bbbddd8ce0e6cba824e8fStephen Hines  llvm::ELF::Elf32_Shdr* shtab =
86ce2e754ed4b1aefe607bbbddd8ce0e6cba824e8fStephen Hines      reinterpret_cast<llvm::ELF::Elf32_Shdr*>(buf + header->e_shoff);
87ce2e754ed4b1aefe607bbbddd8ce0e6cba824e8fStephen Hines
88ce2e754ed4b1aefe607bbbddd8ce0e6cba824e8fStephen Hines  for (int i = 0; i < header->e_shnum; i++) {
89ce2e754ed4b1aefe607bbbddd8ce0e6cba824e8fStephen Hines    if (shtab[i].sh_flags & SHF_ALLOC) {
90ce2e754ed4b1aefe607bbbddd8ce0e6cba824e8fStephen Hines      ELFSectionBits<32>* bits =
91ce2e754ed4b1aefe607bbbddd8ce0e6cba824e8fStephen Hines          static_cast<ELFSectionBits<32>*>(object->getSectionByIndex(i));
92ce2e754ed4b1aefe607bbbddd8ce0e6cba824e8fStephen Hines      if (bits) {
93ce2e754ed4b1aefe607bbbddd8ce0e6cba824e8fStephen Hines        const unsigned char* addr = bits->getBuffer();
94ce2e754ed4b1aefe607bbbddd8ce0e6cba824e8fStephen Hines        shtab[i].sh_addr = reinterpret_cast<llvm::ELF::Elf32_Addr>(addr);
95ce2e754ed4b1aefe607bbbddd8ce0e6cba824e8fStephen Hines      }
96ce2e754ed4b1aefe607bbbddd8ce0e6cba824e8fStephen Hines    }
97ce2e754ed4b1aefe607bbbddd8ce0e6cba824e8fStephen Hines  }
98ce2e754ed4b1aefe607bbbddd8ce0e6cba824e8fStephen Hines}
99ce2e754ed4b1aefe607bbbddd8ce0e6cba824e8fStephen Hines
10058ed8bce80acd10ea103dc9c94f83466fa500ac9Logan Chienextern "C" void rsloaderDisposeExec(RSExecRef object) {
10158ed8bce80acd10ea103dc9c94f83466fa500ac9Logan Chien  delete unwrap(object);
10258ed8bce80acd10ea103dc9c94f83466fa500ac9Logan Chien}
10358ed8bce80acd10ea103dc9c94f83466fa500ac9Logan Chien
10458ed8bce80acd10ea103dc9c94f83466fa500ac9Logan Chienextern "C" void *rsloaderGetSymbolAddress(RSExecRef object_,
10558ed8bce80acd10ea103dc9c94f83466fa500ac9Logan Chien                                          char const *name) {
10658ed8bce80acd10ea103dc9c94f83466fa500ac9Logan Chien  ELFObject<32> *object = unwrap(object_);
10758ed8bce80acd10ea103dc9c94f83466fa500ac9Logan Chien
10858ed8bce80acd10ea103dc9c94f83466fa500ac9Logan Chien  ELFSectionSymTab<32> *symtab =
10958ed8bce80acd10ea103dc9c94f83466fa500ac9Logan Chien    static_cast<ELFSectionSymTab<32> *>(object->getSectionByName(".symtab"));
11058ed8bce80acd10ea103dc9c94f83466fa500ac9Logan Chien
11121ca257e99974ac0044012180ace2b833525e45dLogan Chien  if (!symtab) {
11221ca257e99974ac0044012180ace2b833525e45dLogan Chien    return NULL;
11321ca257e99974ac0044012180ace2b833525e45dLogan Chien  }
11421ca257e99974ac0044012180ace2b833525e45dLogan Chien
11521ca257e99974ac0044012180ace2b833525e45dLogan Chien  ELFSymbol<32> *symbol = symtab->getByName(name);
11621ca257e99974ac0044012180ace2b833525e45dLogan Chien
11721ca257e99974ac0044012180ace2b833525e45dLogan Chien  if (!symbol) {
118c9ff76dbcf76753a2460e6e3887d80a196fcb9adStephen Hines    ALOGV("Symbol not found: %s\n", name);
11921ca257e99974ac0044012180ace2b833525e45dLogan Chien    return NULL;
12021ca257e99974ac0044012180ace2b833525e45dLogan Chien  }
12121ca257e99974ac0044012180ace2b833525e45dLogan Chien
1229ed73923af9db7283a8c76b5dfa2dda5b732a852Andrew Hsieh  int machine = object->getHeader()->getMachine();
1239ed73923af9db7283a8c76b5dfa2dda5b732a852Andrew Hsieh
1249ed73923af9db7283a8c76b5dfa2dda5b732a852Andrew Hsieh  return symbol->getAddress(machine, false);
12558ed8bce80acd10ea103dc9c94f83466fa500ac9Logan Chien}
12611b53125c58adc902c1e2a60cbe667ba2344ecceLogan Chien
12711b53125c58adc902c1e2a60cbe667ba2344ecceLogan Chienextern "C" size_t rsloaderGetSymbolSize(RSExecRef object_, char const *name) {
12811b53125c58adc902c1e2a60cbe667ba2344ecceLogan Chien  ELFObject<32> *object = unwrap(object_);
12911b53125c58adc902c1e2a60cbe667ba2344ecceLogan Chien
13011b53125c58adc902c1e2a60cbe667ba2344ecceLogan Chien  ELFSectionSymTab<32> *symtab =
13111b53125c58adc902c1e2a60cbe667ba2344ecceLogan Chien    static_cast<ELFSectionSymTab<32> *>(object->getSectionByName(".symtab"));
13211b53125c58adc902c1e2a60cbe667ba2344ecceLogan Chien
13311b53125c58adc902c1e2a60cbe667ba2344ecceLogan Chien  if (!symtab) {
13411b53125c58adc902c1e2a60cbe667ba2344ecceLogan Chien    return NULL;
13511b53125c58adc902c1e2a60cbe667ba2344ecceLogan Chien  }
13611b53125c58adc902c1e2a60cbe667ba2344ecceLogan Chien
13711b53125c58adc902c1e2a60cbe667ba2344ecceLogan Chien  ELFSymbol<32> *symbol = symtab->getByName(name);
13811b53125c58adc902c1e2a60cbe667ba2344ecceLogan Chien
13911b53125c58adc902c1e2a60cbe667ba2344ecceLogan Chien  if (!symbol) {
140c9ff76dbcf76753a2460e6e3887d80a196fcb9adStephen Hines    ALOGV("Symbol not found: %s\n", name);
14111b53125c58adc902c1e2a60cbe667ba2344ecceLogan Chien    return NULL;
14211b53125c58adc902c1e2a60cbe667ba2344ecceLogan Chien  }
14311b53125c58adc902c1e2a60cbe667ba2344ecceLogan Chien
14411b53125c58adc902c1e2a60cbe667ba2344ecceLogan Chien  return (size_t)symbol->getSize();
14511b53125c58adc902c1e2a60cbe667ba2344ecceLogan Chien}
146388f443ba0c474ffcc2e06f8d2a668c4488c3c1bLogan Chien
147388f443ba0c474ffcc2e06f8d2a668c4488c3c1bLogan Chienextern "C" size_t rsloaderGetFuncCount(RSExecRef object) {
148388f443ba0c474ffcc2e06f8d2a668c4488c3c1bLogan Chien  ELFSectionSymTab<32> *symtab = static_cast<ELFSectionSymTab<32> *>(
149388f443ba0c474ffcc2e06f8d2a668c4488c3c1bLogan Chien    unwrap(object)->getSectionByName(".symtab"));
150388f443ba0c474ffcc2e06f8d2a668c4488c3c1bLogan Chien
151388f443ba0c474ffcc2e06f8d2a668c4488c3c1bLogan Chien  if (!symtab) {
152388f443ba0c474ffcc2e06f8d2a668c4488c3c1bLogan Chien    return 0;
153388f443ba0c474ffcc2e06f8d2a668c4488c3c1bLogan Chien  }
154388f443ba0c474ffcc2e06f8d2a668c4488c3c1bLogan Chien
155388f443ba0c474ffcc2e06f8d2a668c4488c3c1bLogan Chien  return symtab->getFuncCount();
156388f443ba0c474ffcc2e06f8d2a668c4488c3c1bLogan Chien}
157388f443ba0c474ffcc2e06f8d2a668c4488c3c1bLogan Chien
158388f443ba0c474ffcc2e06f8d2a668c4488c3c1bLogan Chienextern "C" void rsloaderGetFuncNameList(RSExecRef object,
159388f443ba0c474ffcc2e06f8d2a668c4488c3c1bLogan Chien                                        size_t size,
160388f443ba0c474ffcc2e06f8d2a668c4488c3c1bLogan Chien                                        char const **list) {
161388f443ba0c474ffcc2e06f8d2a668c4488c3c1bLogan Chien  ELFSectionSymTab<32> *symtab = static_cast<ELFSectionSymTab<32> *>(
162388f443ba0c474ffcc2e06f8d2a668c4488c3c1bLogan Chien    unwrap(object)->getSectionByName(".symtab"));
163388f443ba0c474ffcc2e06f8d2a668c4488c3c1bLogan Chien
164388f443ba0c474ffcc2e06f8d2a668c4488c3c1bLogan Chien  if (symtab) {
165388f443ba0c474ffcc2e06f8d2a668c4488c3c1bLogan Chien    symtab->getFuncNameList(size, list);
166388f443ba0c474ffcc2e06f8d2a668c4488c3c1bLogan Chien  }
167388f443ba0c474ffcc2e06f8d2a668c4488c3c1bLogan Chien}
168