1 /*
2  * Copyright 2011-2012, The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "librsloader.h"
18 
19 #include "ELFObject.h"
20 #include "ELFSectionSymTab.h"
21 #include "ELFSymbol.h"
22 
23 #include "utils/serialize.h"
24 
25 #define LOG_TAG "bcc"
26 #include "cutils/log.h"
27 
28 #include <llvm/Support/ELF.h>
29 
30 #if defined(__LP64__) || defined(__x86_64__)
wrap(ELFObject<64> * object)31 static inline RSExecRef wrap(ELFObject<64> *object) {
32   return reinterpret_cast<RSExecRef>(object);
33 }
34 #else
wrap(ELFObject<32> * object)35 static inline RSExecRef wrap(ELFObject<32> *object) {
36   return reinterpret_cast<RSExecRef>(object);
37 }
38 #endif
39 
40 #if defined(__LP64__) || defined(__x86_64__)
unwrap(RSExecRef object)41 static inline ELFObject<64> *unwrap(RSExecRef object) {
42   return reinterpret_cast<ELFObject<64> *>(object);
43 }
44 #else
unwrap(RSExecRef object)45 static inline ELFObject<32> *unwrap(RSExecRef object) {
46   return reinterpret_cast<ELFObject<32> *>(object);
47 }
48 #endif
49 
rsloaderCreateExec(unsigned char const * buf,size_t buf_size,RSFindSymbolFn find_symbol,void * find_symbol_context)50 extern "C" RSExecRef rsloaderCreateExec(unsigned char const *buf,
51                                         size_t buf_size,
52                                         RSFindSymbolFn find_symbol,
53                                         void *find_symbol_context) {
54   RSExecRef object = rsloaderLoadExecutable(buf, buf_size);
55   if (!object) {
56     return NULL;
57   }
58 
59   if (!rsloaderRelocateExecutable(object, find_symbol, find_symbol_context)) {
60     rsloaderDisposeExec(object);
61     return NULL;
62   }
63 
64   return object;
65 }
66 
rsloaderLoadExecutable(unsigned char const * buf,size_t buf_size)67 extern "C" RSExecRef rsloaderLoadExecutable(unsigned char const *buf,
68                                             size_t buf_size) {
69   ArchiveReaderLE AR(buf, buf_size);
70 
71 #if defined(__LP64__) || defined(__x86_64__)
72   std::unique_ptr<ELFObject<64> > object(ELFObject<64>::read(AR));
73 #else
74   std::unique_ptr<ELFObject<32> > object(ELFObject<32>::read(AR));
75 #endif
76   if (!object) {
77     ALOGE("Unable to load the ELF object.");
78     return NULL;
79   }
80 
81   return wrap(object.release());
82 }
83 
rsloaderRelocateExecutable(RSExecRef object_,RSFindSymbolFn find_symbol,void * find_symbol_context)84 extern "C" int rsloaderRelocateExecutable(RSExecRef object_,
85                                           RSFindSymbolFn find_symbol,
86                                           void *find_symbol_context) {
87 #if defined(__LP64__) || defined(__x86_64__)
88   ELFObject<64>* object = unwrap(object_);
89 #else
90   ELFObject<32>* object = unwrap(object_);
91 #endif
92   object->relocate(find_symbol, find_symbol_context);
93   return (object->getMissingSymbols() == 0);
94 }
95 
rsloaderUpdateSectionHeaders(RSExecRef object_,unsigned char * buf)96 extern "C" void rsloaderUpdateSectionHeaders(RSExecRef object_,
97                                              unsigned char *buf) {
98 #if defined(__LP64__) || defined(__x86_64__)
99   ELFObject<64> *object = unwrap(object_);
100 #else
101   ELFObject<32> *object = unwrap(object_);
102 #endif
103 
104   // Remap the section header addresses to match the loaded code
105 #if defined(__LP64__) || defined(__x86_64__)
106   llvm::ELF::Elf64_Ehdr* header = reinterpret_cast<llvm::ELF::Elf64_Ehdr*>(buf);
107 #else
108   llvm::ELF::Elf32_Ehdr* header = reinterpret_cast<llvm::ELF::Elf32_Ehdr*>(buf);
109 #endif
110 
111 #if defined(__LP64__) || defined(__x86_64__)
112   llvm::ELF::Elf64_Shdr* shtab =
113       reinterpret_cast<llvm::ELF::Elf64_Shdr*>(buf + header->e_shoff);
114 #else
115   llvm::ELF::Elf32_Shdr* shtab =
116       reinterpret_cast<llvm::ELF::Elf32_Shdr*>(buf + header->e_shoff);
117 #endif
118 
119   for (int i = 0; i < header->e_shnum; i++) {
120     if (shtab[i].sh_flags & SHF_ALLOC) {
121 #if defined(__LP64__) || defined(__x86_64__)
122       ELFSectionBits<64>* bits =
123           static_cast<ELFSectionBits<64>*>(object->getSectionByIndex(i));
124 #else
125       ELFSectionBits<32>* bits =
126           static_cast<ELFSectionBits<32>*>(object->getSectionByIndex(i));
127 #endif
128       if (bits) {
129         const unsigned char* addr = bits->getBuffer();
130 #if defined(__LP64__) || defined(__x86_64__)
131         shtab[i].sh_addr = reinterpret_cast<llvm::ELF::Elf64_Addr>(addr);
132 #else
133         shtab[i].sh_addr = reinterpret_cast<llvm::ELF::Elf32_Addr>(addr);
134 #endif
135       }
136     }
137   }
138 }
139 
rsloaderDisposeExec(RSExecRef object)140 extern "C" void rsloaderDisposeExec(RSExecRef object) {
141   delete unwrap(object);
142 }
143 
rsloaderGetSymbolAddress(RSExecRef object_,char const * name)144 extern "C" void *rsloaderGetSymbolAddress(RSExecRef object_,
145                                           char const *name) {
146 #if defined(__LP64__) || defined(__x86_64__)
147   ELFObject<64> *object = unwrap(object_);
148 
149   ELFSectionSymTab<64> *symtab =
150     static_cast<ELFSectionSymTab<64> *>(object->getSectionByName(".symtab"));
151 #else
152   ELFObject<32> *object = unwrap(object_);
153 
154   ELFSectionSymTab<32> *symtab =
155     static_cast<ELFSectionSymTab<32> *>(object->getSectionByName(".symtab"));
156 #endif
157 
158   if (!symtab) {
159     return NULL;
160   }
161 
162 #if defined(__LP64__) || defined(__x86_64__)
163   ELFSymbol<64> *symbol = symtab->getByName(name);
164 #else
165   ELFSymbol<32> *symbol = symtab->getByName(name);
166 #endif
167 
168   if (!symbol) {
169     ALOGV("Symbol not found: %s\n", name);
170     return NULL;
171   }
172 
173   int machine = object->getHeader()->getMachine();
174 
175   return symbol->getAddress(machine, false);
176 }
177 
rsloaderGetSymbolSize(RSExecRef object_,char const * name)178 extern "C" size_t rsloaderGetSymbolSize(RSExecRef object_, char const *name) {
179 #if defined(__LP64__) || defined(__x86_64__)
180   ELFObject<64> *object = unwrap(object_);
181 
182   ELFSectionSymTab<64> *symtab =
183     static_cast<ELFSectionSymTab<64> *>(object->getSectionByName(".symtab"));
184 #else
185   ELFObject<32> *object = unwrap(object_);
186 
187   ELFSectionSymTab<32> *symtab =
188     static_cast<ELFSectionSymTab<32> *>(object->getSectionByName(".symtab"));
189 #endif
190   if (!symtab) {
191     return 0;
192   }
193 
194 #if defined(__LP64__) || defined(__x86_64__)
195   ELFSymbol<64> *symbol = symtab->getByName(name);
196 #else
197   ELFSymbol<32> *symbol = symtab->getByName(name);
198 #endif
199 
200   if (!symbol) {
201     ALOGV("Symbol not found: %s\n", name);
202     return 0;
203   }
204 
205   return (size_t)symbol->getSize();
206 }
207 
rsloaderGetFuncCount(RSExecRef object)208 extern "C" size_t rsloaderGetFuncCount(RSExecRef object) {
209 #if defined(__LP64__) || defined(__x86_64__)
210   ELFSectionSymTab<64> *symtab = static_cast<ELFSectionSymTab<64> *>(
211 #else
212   ELFSectionSymTab<32> *symtab = static_cast<ELFSectionSymTab<32> *>(
213 #endif
214     unwrap(object)->getSectionByName(".symtab"));
215 
216   if (!symtab) {
217     return 0;
218   }
219 
220   return symtab->getFuncCount();
221 }
222 
rsloaderGetFuncNameList(RSExecRef object,size_t size,char const ** list)223 extern "C" void rsloaderGetFuncNameList(RSExecRef object,
224                                         size_t size,
225                                         char const **list) {
226 #if defined(__LP64__) || defined(__x86_64__)
227   ELFSectionSymTab<64> *symtab = static_cast<ELFSectionSymTab<64> *>(
228 #else
229   ELFSectionSymTab<32> *symtab = static_cast<ELFSectionSymTab<32> *>(
230 #endif
231     unwrap(object)->getSectionByName(".symtab"));
232 
233   if (symtab) {
234     symtab->getFuncNameList(size, list);
235   }
236 }
237