ELFObject.hxx revision e4742793dcba49887f90011fc7a3a858cf70a8cf
1/*
2 * Copyright 2011, 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#ifndef ELF_OBJECT_HXX
18#define ELF_OBJECT_HXX
19
20#include "ELFHeader.h"
21#include "ELFReloc.h"
22#include "ELFSection.h"
23#include "ELFSectionHeaderTable.h"
24#include "StubLayout.h"
25#include "ELF.h"
26
27#include <llvm/ADT/SmallVector.h>
28
29#include "utils/rsl_assert.h"
30
31template <unsigned Bitwidth>
32template <typename Archiver>
33inline ELFObject<Bitwidth> *
34ELFObject<Bitwidth>::read(Archiver &AR) {
35  llvm::OwningPtr<ELFObjectTy> object(new ELFObjectTy());
36
37  // Read header
38  object->header.reset(ELFHeaderTy::read(AR));
39  if (!object->header) {
40    return 0;
41  }
42
43  // Read section table
44  object->shtab.reset(ELFSectionHeaderTableTy::read(AR, object.get()));
45  if (!object->shtab) {
46    return 0;
47  }
48
49  // Read each section
50  llvm::SmallVector<size_t, 4> progbits_ndx;
51  for (size_t i = 0; i < object->header->getSectionHeaderNum(); ++i) {
52    if ((*object->shtab)[i]->getType() == SHT_PROGBITS) {
53      object->stab.push_back(NULL);
54      progbits_ndx.push_back(i);
55    } else {
56      llvm::OwningPtr<ELFSectionTy> sec(
57        ELFSectionTy::read(AR, object.get(), (*object->shtab)[i]));
58      object->stab.push_back(sec.take());
59    }
60  }
61
62  object->shtab->buildNameMap();
63  ELFSectionSymTabTy *symtab =
64    static_cast<ELFSectionSymTabTy *>(object->getSectionByName(".symtab"));
65  rsl_assert(symtab && "Symtab is required.");
66  symtab->buildNameMap();
67
68  for (size_t i = 0; i < progbits_ndx.size(); ++i) {
69    size_t index = progbits_ndx[i];
70
71    llvm::OwningPtr<ELFSectionTy> sec(
72      ELFSectionTy::read(AR, object.get(), (*object->shtab)[index]));
73    object->stab[index] = sec.take();
74  }
75
76  return object.take();
77}
78
79template <unsigned Bitwidth>
80inline char const *ELFObject<Bitwidth>::getSectionName(size_t i) const {
81  ELFSectionTy const *sec = stab[header->getStringSectionIndex()];
82
83  if (sec) {
84    ELFSectionStrTabTy const &st =
85      static_cast<ELFSectionStrTabTy const &>(*sec);
86    return st[i];
87  }
88
89  return NULL;
90}
91
92template <unsigned Bitwidth>
93inline ELFSection<Bitwidth> const *
94ELFObject<Bitwidth>::getSectionByIndex(size_t i) const {
95  return stab[i];
96}
97
98template <unsigned Bitwidth>
99inline ELFSection<Bitwidth> *
100ELFObject<Bitwidth>::getSectionByIndex(size_t i) {
101  return stab[i];
102}
103
104template <unsigned Bitwidth>
105inline ELFSection<Bitwidth> const *
106ELFObject<Bitwidth>::getSectionByName(std::string const &str) const {
107  size_t idx = getSectionHeaderTable()->getByName(str)->getIndex();
108  return stab[idx];
109}
110
111template <unsigned Bitwidth>
112inline ELFSection<Bitwidth> *
113ELFObject<Bitwidth>::getSectionByName(std::string const &str) {
114  ELFObjectTy const *const_this = this;
115  ELFSectionTy const *sptr = const_this->getSectionByName(str);
116  // Const cast for the same API's const and non-const versions.
117  return const_cast<ELFSectionTy *>(sptr);
118}
119
120
121template <unsigned Bitwidth>
122inline void ELFObject<Bitwidth>::
123relocateARM(void *(*find_sym)(void *context, char const *name),
124            void *context,
125            ELFSectionRelTableTy *reltab,
126            ELFSectionProgBitsTy *text) {
127  // FIXME: Should be implement in independent files.
128  rsl_assert(Bitwidth == 32 && "ARM only have 32 bits.");
129
130  ELFSectionSymTabTy *symtab =
131    static_cast<ELFSectionSymTabTy *>(getSectionByName(".symtab"));
132  rsl_assert(symtab && "Symtab is required.");
133
134  for (size_t i = 0; i < reltab->size(); ++i) {
135    // FIXME: Can not implement here, use Fixup!
136    ELFRelocTy *rel = (*reltab)[i];
137    ELFSymbolTy *sym = (*symtab)[rel->getSymTabIndex()];
138
139    // FIXME: May be not uint32_t *.
140    typedef int32_t Inst_t;
141    Inst_t *inst = (Inst_t *)&(*text)[rel->getOffset()];
142    Inst_t P = (Inst_t)(int64_t)inst;
143    Inst_t A = 0;
144    Inst_t S = (Inst_t)(int64_t)sym->getAddress();
145
146    switch (rel->getType()) {
147    default:
148      rsl_assert(0 && "Not implemented relocation type.");
149      break;
150
151    case R_ARM_ABS32:
152      {
153        A = *inst;
154        *inst = (S+A);
155      }
156      break;
157
158      // FIXME: Predefine relocation codes.
159    case R_ARM_CALL:
160      {
161#define SIGN_EXTEND(x, l) (((x)^(1<<((l)-1)))-(1<<(l-1)))
162        A = (Inst_t)(int64_t)SIGN_EXTEND(*inst & 0xFFFFFF, 24);
163#undef SIGN_EXTEND
164
165        switch (sym->getType()) {
166        default:
167          rsl_assert(0 && "Wrong type for R_ARM_CALL relocation.");
168          abort();
169          break;
170
171        case STT_FUNC:
172          if (S == 0) {
173            rsl_assert(0 && "We should get function address at previous "
174                   "sym->getAddress() function call.");
175            abort();
176          }
177          break;
178
179        case STT_NOTYPE:
180          if (S == 0) {
181            void *ext_func = find_sym(context, sym->getName());
182#ifdef SUPPORT_NEAR_JUMP_EVEN_IF_BLc2BLX_NEEDED
183            S = (Inst_t)(uintptr_t)ext_func;
184            sym->setAddress(ext_func);
185
186            uint32_t result = (S >> 2) - (P >> 2) + A;
187            if (result > 0x007fffff && result < 0xff800000) {
188#endif
189#ifndef __arm__
190              // We have not implement function stub in this runtime env
191              rsl_assert(0 && "Target address is far from call instruction");
192              abort();
193#else
194              void *stub = getStubLayout()->allocateStub(ext_func);
195              if (!stub) {
196                llvm::errs() << "unable to allocate stub." << "\n";
197                exit(EXIT_FAILURE);
198              }
199
200              //out() << "stub: for " << ext_func << " at " << stub << "\n";
201              sym->setAddress(stub);
202              S = (uint32_t)stub;
203#endif
204#ifdef SUPPORT_NEAR_JUMP_EVEN_IF_BLc2BLX_NEEDED
205            }
206#endif
207          }
208          break;
209        }
210
211        uint32_t result = (S >> 2) - (P >> 2) + A;
212
213        if (result > 0x007fffff && result < 0xff800000) {
214          rsl_assert(0 && "Stub is still too far");
215          abort();
216        }
217
218        *inst = ((result) & 0x00FFFFFF) | (*inst & 0xFF000000);
219      }
220      break;
221    case R_ARM_MOVT_ABS:
222      S >>= 16;
223    case R_ARM_MOVW_ABS_NC:
224      {
225        // No need sign extend.
226        A = ((*inst & 0xF0000) >> 4) | (*inst & 0xFFF);
227        uint32_t result = (S+A);
228        *inst = (((result) & 0xF000) << 4) |
229          ((result) & 0xFFF) |
230          (*inst & 0xFFF0F000);
231      }
232      break;
233    }
234    //llvm::errs() << "S:     " << (void *)S << '\n';
235    //llvm::errs() << "A:     " << (void *)A << '\n';
236    //llvm::errs() << "P:     " << (void *)P << '\n';
237    //llvm::errs() << "S+A:   " << (void *)(S+A) << '\n';
238    //llvm::errs() << "S+A-P: " << (void *)(S+A-P) << '\n';
239  }
240}
241
242template <unsigned Bitwidth>
243inline void ELFObject<Bitwidth>::
244relocateX86_64(void *(*find_sym)(void *context, char const *name),
245               void *context,
246               ELFSectionRelTableTy *reltab,
247               ELFSectionProgBitsTy *text) {
248  rsl_assert(Bitwidth == 64 && "Only support X86_64.");
249
250  ELFSectionSymTabTy *symtab =
251    static_cast<ELFSectionSymTabTy *>(getSectionByName(".symtab"));
252  rsl_assert(symtab && "Symtab is required.");
253
254  for (size_t i = 0; i < reltab->size(); ++i) {
255    // FIXME: Can not implement here, use Fixup!
256    ELFRelocTy *rel = (*reltab)[i];
257    ELFSymbolTy *sym = (*symtab)[rel->getSymTabIndex()];
258
259    //typedef uint64_t Inst_t;
260    typedef int32_t Inst_t;
261    Inst_t *inst = (Inst_t *)&(*text)[rel->getOffset()];
262    Inst_t P = (Inst_t)(int64_t)inst;
263    Inst_t A = (Inst_t)(int64_t)rel->getAddend();
264    Inst_t S = (Inst_t)(int64_t)sym->getAddress();
265
266    if (S == 0) {
267      S = (Inst_t)(int64_t)find_sym(context, sym->getName());
268      sym->setAddress((void *)S);
269    }
270
271    switch (rel->getType()) {
272      default:
273        rsl_assert(0 && "Not implemented relocation type.");
274        break;
275
276      // FIXME: XXX: R_X86_64_64 is 64 bit, there is a big problem here.
277      case 1: // R_X86_64_64
278        *inst = (S+A);
279        break;
280
281      case 2: // R_X86_64_PC32
282        *inst = (S+A-P);
283        break;
284
285      case 10: // R_X86_64_32
286      case 11: // R_X86_64_32S
287        *inst = (S+A);
288        break;
289    }
290  }
291}
292
293template <unsigned Bitwidth>
294inline void ELFObject<Bitwidth>::
295relocateX86_32(void *(*find_sym)(void *context, char const *name),
296               void *context,
297               ELFSectionRelTableTy *reltab,
298               ELFSectionProgBitsTy *text) {
299  rsl_assert(Bitwidth == 32 && "Only support X86.");
300
301  ELFSectionSymTabTy *symtab =
302    static_cast<ELFSectionSymTabTy *>(getSectionByName(".symtab"));
303  rsl_assert(symtab && "Symtab is required.");
304
305  for (size_t i = 0; i < reltab->size(); ++i) {
306    // FIXME: Can not implement here, use Fixup!
307    ELFRelocTy *rel = (*reltab)[i];
308    ELFSymbolTy *sym = (*symtab)[rel->getSymTabIndex()];
309
310    //typedef uint64_t Inst_t;
311    typedef int32_t Inst_t;
312    Inst_t *inst = (Inst_t *)&(*text)[rel->getOffset()];
313    Inst_t P = (Inst_t)(uintptr_t)inst;
314    Inst_t A = (Inst_t)(uintptr_t)*inst;
315    Inst_t S = (Inst_t)(uintptr_t)sym->getAddress();
316
317    if (S == 0) {
318      S = (Inst_t)(uintptr_t)find_sym(context, sym->getName());
319      sym->setAddress((void *)S);
320    }
321
322    switch (rel->getType()) {
323    default:
324      rsl_assert(0 && "Not implemented relocation type.");
325      break;
326
327    case R_386_PC32:
328      *inst = (S+A-P);
329      break;
330
331    case R_386_32:
332      *inst = (S+A);
333      break;
334    }
335  }
336}
337
338template <unsigned Bitwidth>
339inline void ELFObject<Bitwidth>::
340relocate(void *(*find_sym)(void *context, char const *name), void *context) {
341
342  for (size_t i = 0; i < stab.size(); ++i) {
343    ELFSectionHeaderTy *sh = (*shtab)[i];
344    if (sh->getType() != SHT_REL && sh->getType() != SHT_RELA) {
345      continue;
346    }
347    ELFSectionRelTableTy *reltab =
348      static_cast<ELFSectionRelTableTy *>(stab[i]);
349    rsl_assert(reltab && "Relocation section can't be NULL.");
350
351    const char *reltab_name = sh->getName();
352    const char *need_rel_name;
353    if (sh->getType() == SHT_REL) {
354      need_rel_name = reltab_name + 4;
355      // ".rel.xxxx"
356      //      ^ start from here.
357    } else {
358      need_rel_name = reltab_name + 5;
359    }
360
361    ELFSectionProgBitsTy *need_rel =
362      static_cast<ELFSectionProgBitsTy *>(getSectionByName(need_rel_name));
363    rsl_assert(need_rel && "Need be relocated section can't be NULL.");
364
365    switch (getHeader()->getMachine()) {
366      case EM_ARM:
367        relocateARM(find_sym, context, reltab, need_rel);
368        break;
369      case EM_386:
370        relocateX86_32(find_sym, context, reltab, need_rel);
371        break;
372      case EM_X86_64:
373        relocateX86_64(find_sym, context, reltab, need_rel);
374        break;
375
376      default:
377        rsl_assert(0 && "Only support ARM, X86, and X86_64 relocation.");
378        break;
379    }
380  }
381
382  for (size_t i = 0; i < stab.size(); ++i) {
383    ELFSectionHeaderTy *sh = (*shtab)[i];
384    if (sh->getType() == SHT_PROGBITS || sh->getType() == SHT_NOBITS) {
385      if (stab[i]) {
386        static_cast<ELFSectionBitsTy *>(stab[i])->protect();
387      }
388    }
389  }
390}
391
392template <unsigned Bitwidth>
393inline void ELFObject<Bitwidth>::print() const {
394  header->print();
395  shtab->print();
396
397  for (size_t i = 0; i < stab.size(); ++i) {
398    ELFSectionTy *sec = stab[i];
399    if (sec) {
400      sec->print();
401    }
402  }
403}
404
405#endif // ELF_OBJECT_HXX
406