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