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__)
31static inline RSExecRef wrap(ELFObject<64> *object) {
32  return reinterpret_cast<RSExecRef>(object);
33}
34#else
35static inline RSExecRef wrap(ELFObject<32> *object) {
36  return reinterpret_cast<RSExecRef>(object);
37}
38#endif
39
40#if defined(__LP64__) || defined(__x86_64__)
41static inline ELFObject<64> *unwrap(RSExecRef object) {
42  return reinterpret_cast<ELFObject<64> *>(object);
43}
44#else
45static inline ELFObject<32> *unwrap(RSExecRef object) {
46  return reinterpret_cast<ELFObject<32> *>(object);
47}
48#endif
49
50extern "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
67extern "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
84extern "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
96extern "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
140extern "C" void rsloaderDisposeExec(RSExecRef object) {
141  delete unwrap(object);
142}
143
144extern "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
178extern "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
208extern "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
223extern "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