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#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 "GOT.h"
26#include "ELF.h"
27
28#include <llvm/ADT/SmallVector.h>
29
30#include "utils/rsl_assert.h"
31
32template <unsigned Bitwidth>
33template <typename Archiver>
34inline ELFObject<Bitwidth> *
35ELFObject<Bitwidth>::read(Archiver &AR) {
36  llvm::OwningPtr<ELFObjectTy> object(new ELFObjectTy());
37
38  // Read header
39  object->header.reset(ELFHeaderTy::read(AR));
40  if (!object->header) {
41    return 0;
42  }
43
44  // Read section table
45  object->shtab.reset(ELFSectionHeaderTableTy::read(AR, object.get()));
46  if (!object->shtab) {
47    return 0;
48  }
49
50  // Read each section
51  llvm::SmallVector<size_t, 4> progbits_ndx;
52  for (size_t i = 0; i < object->header->getSectionHeaderNum(); ++i) {
53    if ((*object->shtab)[i]->getType() == SHT_PROGBITS) {
54      object->stab.push_back(NULL);
55      progbits_ndx.push_back(i);
56    } else {
57      llvm::OwningPtr<ELFSectionTy> sec(
58        ELFSectionTy::read(AR, object.get(), (*object->shtab)[i]));
59      object->stab.push_back(sec.take());
60    }
61  }
62
63  object->shtab->buildNameMap();
64  ELFSectionSymTabTy *symtab =
65    static_cast<ELFSectionSymTabTy *>(object->getSectionByName(".symtab"));
66  rsl_assert(symtab && "Symtab is required.");
67  symtab->buildNameMap();
68
69  for (size_t i = 0; i < progbits_ndx.size(); ++i) {
70    size_t index = progbits_ndx[i];
71
72    llvm::OwningPtr<ELFSectionTy> sec(
73      ELFSectionTy::read(AR, object.get(), (*object->shtab)[index]));
74    object->stab[index] = sec.take();
75  }
76
77  return object.take();
78}
79
80template <unsigned Bitwidth>
81inline char const *ELFObject<Bitwidth>::getSectionName(size_t i) const {
82  ELFSectionTy const *sec = stab[header->getStringSectionIndex()];
83
84  if (sec) {
85    ELFSectionStrTabTy const &st =
86      static_cast<ELFSectionStrTabTy const &>(*sec);
87    return st[i];
88  }
89
90  return NULL;
91}
92
93template <unsigned Bitwidth>
94inline ELFSection<Bitwidth> const *
95ELFObject<Bitwidth>::getSectionByIndex(size_t i) const {
96  return stab[i];
97}
98
99template <unsigned Bitwidth>
100inline ELFSection<Bitwidth> *
101ELFObject<Bitwidth>::getSectionByIndex(size_t i) {
102  return stab[i];
103}
104
105template <unsigned Bitwidth>
106inline ELFSection<Bitwidth> const *
107ELFObject<Bitwidth>::getSectionByName(std::string const &str) const {
108  size_t idx = getSectionHeaderTable()->getByName(str)->getIndex();
109  return stab[idx];
110}
111
112template <unsigned Bitwidth>
113inline ELFSection<Bitwidth> *
114ELFObject<Bitwidth>::getSectionByName(std::string const &str) {
115  ELFObjectTy const *const_this = this;
116  ELFSectionTy const *sptr = const_this->getSectionByName(str);
117  // Const cast for the same API's const and non-const versions.
118  return const_cast<ELFSectionTy *>(sptr);
119}
120
121
122template <unsigned Bitwidth>
123inline void ELFObject<Bitwidth>::
124relocateARM(void *(*find_sym)(void *context, char const *name),
125            void *context,
126            ELFSectionRelTableTy *reltab,
127            ELFSectionProgBitsTy *text) {
128  // FIXME: Should be implement in independent files.
129  rsl_assert(Bitwidth == 32 && "ARM only have 32 bits.");
130
131  ELFSectionSymTabTy *symtab =
132    static_cast<ELFSectionSymTabTy *>(getSectionByName(".symtab"));
133  rsl_assert(symtab && "Symtab is required.");
134
135  for (size_t i = 0; i < reltab->size(); ++i) {
136    // FIXME: Can not implement here, use Fixup!
137    ELFRelocTy *rel = (*reltab)[i];
138    ELFSymbolTy *sym = (*symtab)[rel->getSymTabIndex()];
139
140    // FIXME: May be not uint32_t *.
141    typedef int32_t Inst_t;
142    Inst_t *inst = (Inst_t *)&(*text)[rel->getOffset()];
143    Inst_t P = (Inst_t)(int64_t)inst;
144    Inst_t A = 0;
145    Inst_t S = (Inst_t)(int64_t)sym->getAddress(EM_ARM);
146    Inst_t T = 0;
147
148    if (sym->isConcreteFunc() && (sym->getValue() & 0x1)) {
149      T = 1;
150    }
151
152    word_t reltype = rel->getType();
153    switch (reltype) {
154    default:
155      rsl_assert(0 && "Not implemented relocation type.");
156      break;
157
158    case R_ARM_ABS32:
159      {
160        if (S == 0 && sym->getType() == STT_NOTYPE) {
161          void *ext_sym = find_sym(context, sym->getName());
162          if (!ext_sym) {
163            missingSymbols = true;
164          }
165          S = (Inst_t)(uintptr_t)ext_sym;
166          sym->setAddress(ext_sym);
167        }
168        A = *inst;
169        *inst = (S + A) | T;
170      }
171      break;
172
173      // FIXME: Predefine relocation codes.
174    case R_ARM_CALL:
175    case R_ARM_THM_CALL:
176    case R_ARM_JUMP24:
177    case R_ARM_THM_JUMP24:
178      {
179#define SIGN_EXTEND(x, l) (((x)^(1<<((l)-1)))-(1<<(l-1)))
180        if (reltype == R_ARM_CALL || reltype == R_ARM_JUMP24) {
181          A = (Inst_t)(int64_t)SIGN_EXTEND(*inst & 0xFFFFFF, 24);
182          A <<= 2;
183        } else {
184          // Hack for two 16bit.
185          *inst = ((*inst >> 16) & 0xFFFF) | (*inst << 16);
186          Inst_t s  = (*inst >> 26) & 0x1u,    // 26
187                 u  = (*inst >> 16) & 0x3FFu,  // 25-16
188                 l  =  *inst        & 0x7FFu, // 10-0
189                 j1 = (*inst >> 13) & 0x1u,    // 13
190                 j2 = (*inst >> 11) & 0x1u;    // 11
191          Inst_t i1 = (~(j1 ^ s)) & 0x1u,
192                 i2 = (~(j2 ^ s)) & 0x1u;
193          // [31-25][24][23][22][21-12][11-1][0]
194          //      0   s  i1  i2      u     l  0
195          A = SIGN_EXTEND((s << 23) | (i1 << 22) | (i2 << 21) | (u << 11) | l, 24);
196          A <<= 1;
197        }
198#undef SIGN_EXTEND
199
200        void *callee_addr = sym->getAddress(EM_ARM);
201
202        switch (sym->getType()) {
203        default:
204          rsl_assert(0 && "Wrong type for R_ARM_CALL relocation.");
205          abort();
206          break;
207
208        case STT_FUNC:
209          // NOTE: Callee function is in the object file, but it may be
210          // in different PROGBITS section (which may be far call).
211
212          if (callee_addr == 0) {
213            rsl_assert(0 && "We should get function address at previous "
214                   "sym->getAddress(EM_ARM) function call.");
215            abort();
216          }
217          break;
218
219        case STT_NOTYPE:
220          // NOTE: Callee function is an external function.  Call find_sym
221          // if it has not resolved yet.
222
223          if (callee_addr == 0) {
224            callee_addr = find_sym(context, sym->getName());
225            if (!callee_addr) {
226              missingSymbols = true;
227            }
228            sym->setAddress(callee_addr);
229          }
230          break;
231        }
232
233        // Get the stub for this function
234        StubLayout *stub_layout = text->getStubLayout();
235
236        if (!stub_layout) {
237          llvm::errs() << "unable to get stub layout." << "\n";
238          abort();
239        }
240
241        void *stub = stub_layout->allocateStub(callee_addr);
242
243        if (!stub) {
244          llvm::errs() << "unable to allocate stub." << "\n";
245          abort();
246        }
247
248        //LOGI("Function %s: using stub %p\n", sym->getName(), stub);
249        S = (uint32_t)(uintptr_t)stub;
250
251        if (reltype == R_ARM_CALL || reltype == R_ARM_JUMP24) {
252          // Relocate the R_ARM_CALL relocation type
253          uint32_t result = (S + A - P) >> 2;
254
255          if (result > 0x007FFFFF && result < 0xFF800000) {
256            rsl_assert(0 && "Stub is still too far");
257            abort();
258          }
259
260          *inst = ((result) & 0x00FFFFFF) | (*inst & 0xFF000000);
261        } else {
262          P &= ~0x3;  // Base address align to 4 bytes.  (For BLX.)
263
264          // Relocate the R_ARM_THM_CALL relocation type
265          uint32_t result = (S + A - P) >> 1;
266
267          if (result > 0x007FFFFF && result < 0xFF800000) {
268            rsl_assert(0 && "Stub is still too far");
269            abort();
270          }
271
272          //*inst &= 0xF800D000u;
273          // Rewrite instruction to BLX.  (Stub is always ARM.)
274          *inst &= 0xF800C000u;
275          // [31-25][24][23][22][21-12][11-1][0]
276          //      0   s  i1  i2      u     l  0
277          Inst_t s  = (result >> 23) & 0x1u,   // 26
278                 u  = (result >> 11) & 0x3FFu, // 25-16
279                 // For BLX, bit [0] is 0.
280                 l  =  result        & 0x7FEu, // 10-0
281                 i1 = (result >> 22) & 0x1u,
282                 i2 = (result >> 21) & 0x1u;
283          Inst_t j1 = ((~i1) ^ s) & 0x01u,       // 13
284                 j2 = ((~i2) ^ s) & 0x01u;       // 11
285          *inst |= s << 26;
286          *inst |= u << 16;
287          *inst |= l;
288          *inst |= j1 << 13;
289          *inst |= j2 << 11;
290          // Hack for two 16bit.
291          *inst = ((*inst >> 16) & 0xFFFF) | (*inst << 16);
292        }
293      }
294      break;
295    case R_ARM_MOVT_ABS:
296    case R_ARM_MOVW_ABS_NC:
297    case R_ARM_THM_MOVW_ABS_NC:
298    case R_ARM_THM_MOVT_ABS:
299      {
300        if (S == 0 && sym->getType() == STT_NOTYPE) {
301          void *ext_sym = find_sym(context, sym->getName());
302          if (!ext_sym) {
303            missingSymbols = true;
304          }
305          S = (Inst_t)(uintptr_t)ext_sym;
306          sym->setAddress(ext_sym);
307        }
308        if (reltype == R_ARM_MOVT_ABS
309            || reltype == R_ARM_THM_MOVT_ABS) {
310          S >>= 16;
311        }
312
313        if (reltype == R_ARM_MOVT_ABS
314            || reltype == R_ARM_MOVW_ABS_NC) {
315          // No need sign extend.
316          A = ((*inst & 0xF0000) >> 4) | (*inst & 0xFFF);
317          uint32_t result = (S + A);
318          *inst = (((result) & 0xF000) << 4) |
319            ((result) & 0xFFF) |
320            (*inst & 0xFFF0F000);
321        } else {
322          // Hack for two 16bit.
323          *inst = ((*inst >> 16) & 0xFFFF) | (*inst << 16);
324          // imm16: [19-16][26][14-12][7-0]
325          A = (((*inst >>  4) & 0xF000u) |
326               ((*inst >> 15) & 0x0800u) |
327               ((*inst >>  4) & 0x0700u) |
328               ( *inst        & 0x00FFu));
329          uint32_t result;
330          if (reltype == R_ARM_THM_MOVT_ABS) {
331            result = (S + A);
332          } else {
333            result = (S + A) | T;
334          }
335          // imm16: [19-16][26][14-12][7-0]
336          *inst &= 0xFBF08F00u;
337          *inst |= (result & 0xF000u) << 4;
338          *inst |= (result & 0x0800u) << 15;
339          *inst |= (result & 0x0700u) << 4;
340          *inst |= (result & 0x00FFu);
341          // Hack for two 16bit.
342          *inst = ((*inst >> 16) & 0xFFFF) | (*inst << 16);
343        }
344      }
345      break;
346    }
347    //llvm::errs() << "S:     " << (void *)S << '\n';
348    //llvm::errs() << "A:     " << (void *)A << '\n';
349    //llvm::errs() << "P:     " << (void *)P << '\n';
350    //llvm::errs() << "S+A:   " << (void *)(S+A) << '\n';
351    //llvm::errs() << "S+A-P: " << (void *)(S+A-P) << '\n';
352  }
353}
354
355template <unsigned Bitwidth>
356inline void ELFObject<Bitwidth>::
357relocateX86_64(void *(*find_sym)(void *context, char const *name),
358               void *context,
359               ELFSectionRelTableTy *reltab,
360               ELFSectionProgBitsTy *text) {
361  rsl_assert(Bitwidth == 64 && "Only support X86_64.");
362
363  ELFSectionSymTabTy *symtab =
364    static_cast<ELFSectionSymTabTy *>(getSectionByName(".symtab"));
365  rsl_assert(symtab && "Symtab is required.");
366
367  for (size_t i = 0; i < reltab->size(); ++i) {
368    // FIXME: Can not implement here, use Fixup!
369    ELFRelocTy *rel = (*reltab)[i];
370    ELFSymbolTy *sym = (*symtab)[rel->getSymTabIndex()];
371
372    //typedef uint64_t Inst_t;
373    typedef int32_t Inst_t;
374    Inst_t *inst = (Inst_t *)&(*text)[rel->getOffset()];
375    Inst_t P = (Inst_t)(int64_t)inst;
376    Inst_t A = (Inst_t)(int64_t)rel->getAddend();
377    Inst_t S = (Inst_t)(int64_t)sym->getAddress(EM_X86_64);
378
379    if (S == 0) {
380      S = (Inst_t)(int64_t)find_sym(context, sym->getName());
381      if (!S) {
382        missingSymbols = true;
383      }
384      sym->setAddress((void *)S);
385    }
386
387    switch (rel->getType()) {
388      default:
389        rsl_assert(0 && "Not implemented relocation type.");
390        break;
391
392      // FIXME: XXX: R_X86_64_64 is 64 bit, there is a big problem here.
393      case 1: // R_X86_64_64
394        *inst = (S+A);
395        break;
396
397      case 2: // R_X86_64_PC32
398        *inst = (S+A-P);
399        break;
400
401      case 10: // R_X86_64_32
402      case 11: // R_X86_64_32S
403        *inst = (S+A);
404        break;
405    }
406  }
407}
408
409template <unsigned Bitwidth>
410inline void ELFObject<Bitwidth>::
411relocateX86_32(void *(*find_sym)(void *context, char const *name),
412               void *context,
413               ELFSectionRelTableTy *reltab,
414               ELFSectionProgBitsTy *text) {
415  rsl_assert(Bitwidth == 32 && "Only support X86.");
416
417  ELFSectionSymTabTy *symtab =
418    static_cast<ELFSectionSymTabTy *>(getSectionByName(".symtab"));
419  rsl_assert(symtab && "Symtab is required.");
420
421  for (size_t i = 0; i < reltab->size(); ++i) {
422    // FIXME: Can not implement here, use Fixup!
423    ELFRelocTy *rel = (*reltab)[i];
424    ELFSymbolTy *sym = (*symtab)[rel->getSymTabIndex()];
425
426    //typedef uint64_t Inst_t;
427    typedef int32_t Inst_t;
428    Inst_t *inst = (Inst_t *)&(*text)[rel->getOffset()];
429    Inst_t P = (Inst_t)(uintptr_t)inst;
430    Inst_t A = (Inst_t)(uintptr_t)*inst;
431    Inst_t S = (Inst_t)(uintptr_t)sym->getAddress(EM_386);
432
433    if (S == 0) {
434      S = (Inst_t)(uintptr_t)find_sym(context, sym->getName());
435      if (!S) {
436        missingSymbols = true;
437      }
438      sym->setAddress((void *)S);
439    }
440
441    switch (rel->getType()) {
442    default:
443      rsl_assert(0 && "Not implemented relocation type.");
444      break;
445
446    case R_386_PC32:
447      *inst = (S+A-P);
448      break;
449
450    case R_386_32:
451      *inst = (S+A);
452      break;
453    }
454  }
455}
456
457template <unsigned Bitwidth>
458inline void ELFObject<Bitwidth>::
459relocateMIPS(void *(*find_sym)(void *context, char const *name),
460             void *context,
461             ELFSectionRelTableTy *reltab,
462             ELFSectionProgBitsTy *text) {
463  rsl_assert(Bitwidth == 32 && "Only support 32-bit MIPS.");
464
465  ELFSectionSymTabTy *symtab =
466    static_cast<ELFSectionSymTabTy *>(getSectionByName(".symtab"));
467  rsl_assert(symtab && "Symtab is required.");
468
469  for (size_t i = 0; i < reltab->size(); ++i) {
470    // FIXME: Can not implement here, use Fixup!
471    ELFRelocTy *rel = (*reltab)[i];
472    ELFSymbolTy *sym = (*symtab)[rel->getSymTabIndex()];
473
474    typedef int32_t Inst_t;
475    Inst_t *inst = (Inst_t *)&(*text)[rel->getOffset()];
476    Inst_t P = (Inst_t)(uintptr_t)inst;
477    Inst_t A = (Inst_t)(uintptr_t)*inst;
478    Inst_t S = (Inst_t)(uintptr_t)sym->getAddress(EM_MIPS);
479
480    bool need_stub = false;
481
482    if (S == 0 && strcmp (sym->getName(), "_gp_disp") != 0) {
483      need_stub = true;
484      S = (Inst_t)(uintptr_t)find_sym(context, sym->getName());
485      if (!S) {
486        missingSymbols = true;
487      }
488      sym->setAddress((void *)S);
489    }
490
491    switch (rel->getType()) {
492    default:
493      rsl_assert(0 && "Not implemented relocation type.");
494      break;
495
496    case R_MIPS_NONE:
497    case R_MIPS_JALR: // ignore this
498      break;
499
500    case R_MIPS_16:
501      *inst &= 0xFFFF0000;
502      A = A & 0xFFFF;
503      A = S + (short)A;
504      rsl_assert(A >= -32768 && A <= 32767 && "R_MIPS_16 overflow.");
505      *inst |= (A & 0xFFFF);
506      break;
507
508    case R_MIPS_32:
509      *inst = S + A;
510      break;
511
512    case R_MIPS_26:
513      *inst &= 0xFC000000;
514      if (need_stub == false) {
515        A = (A & 0x3FFFFFF) << 2;
516        if (sym->getBindingAttribute() == STB_LOCAL) { // local binding
517          A |= ((P + 4) & 0xF0000000);
518          A += S;
519          *inst |= ((A >> 2) & 0x3FFFFFF);
520        } else { // external binding
521          if (A & 0x08000000) // Sign extend from bit 27
522            A |= 0xF0000000;
523          A += S;
524          *inst |= ((A >> 2) & 0x3FFFFFF);
525          if (((P + 4) >> 28) != (A >> 28)) { // far local call
526            void *stub = text->getStubLayout()->allocateStub((void *)A);
527            rsl_assert(stub && "cannot allocate stub.");
528            sym->setAddress(stub);
529            S = (int32_t)(intptr_t)stub;
530            *inst |= ((S >> 2) & 0x3FFFFFF);
531            rsl_assert(((P + 4) >> 28) == (S >> 28) && "stub is too far.");
532          }
533        }
534      } else { // shared-library call
535        A = (A & 0x3FFFFFF) << 2;
536        rsl_assert(A == 0 && "R_MIPS_26 addend is not zero.");
537        void *stub = text->getStubLayout()->allocateStub((void *)S);
538        rsl_assert(stub && "cannot allocate stub.");
539        sym->setAddress(stub);
540        S = (int32_t)(intptr_t)stub;
541        *inst |= ((S >> 2) & 0x3FFFFFF);
542        rsl_assert(((P + 4) >> 28) == (S >> 28) && "stub is too far.");
543      }
544      break;
545
546    case R_MIPS_HI16:
547      *inst &= 0xFFFF0000;
548      A = (A & 0xFFFF) << 16;
549      // Find the nearest LO16 relocation type after this entry
550      for (size_t j = i + 1; j < reltab->size(); j++) {
551        ELFRelocTy *this_rel = (*reltab)[j];
552        ELFSymbolTy *this_sym = (*symtab)[this_rel->getSymTabIndex()];
553        if (this_rel->getType() == R_MIPS_LO16 && this_sym == sym) {
554          Inst_t *this_inst = (Inst_t *)&(*text)[this_rel->getOffset()];
555          Inst_t this_A = (Inst_t)(uintptr_t)*this_inst;
556          this_A = this_A & 0xFFFF;
557          A += (short)this_A;
558          break;
559        }
560      }
561      if (strcmp (sym->getName(), "_gp_disp") == 0) {
562          S = (int)(intptr_t)got_address() + GP_OFFSET - (int)P;
563          sym->setAddress((void *)S);
564      }
565      *inst |= (((S + A + (int)0x8000) >> 16) & 0xFFFF);
566      break;
567
568    case R_MIPS_LO16:
569      *inst &= 0xFFFF0000;
570      A = A & 0xFFFF;
571      if (strcmp (sym->getName(), "_gp_disp") == 0) {
572          S = (Inst_t)(intptr_t)sym->getAddress(EM_MIPS);
573      }
574      *inst |= ((S + A) & 0xFFFF);
575      break;
576
577    case R_MIPS_GOT16:
578    case R_MIPS_CALL16:
579      {
580        *inst &= 0xFFFF0000;
581        A = A & 0xFFFF;
582        if (rel->getType() == R_MIPS_GOT16) {
583          if (sym->getBindingAttribute() == STB_LOCAL) {
584            A <<= 16;
585
586            // Find the nearest LO16 relocation type after this entry
587            for (size_t j = i + 1; j < reltab->size(); j++) {
588              ELFRelocTy *this_rel = (*reltab)[j];
589              ELFSymbolTy *this_sym = (*symtab)[this_rel->getSymTabIndex()];
590              if (this_rel->getType() == R_MIPS_LO16 && this_sym == sym) {
591                Inst_t *this_inst = (Inst_t *)&(*text)[this_rel->getOffset()];
592                Inst_t this_A = (Inst_t)(uintptr_t)*this_inst;
593                this_A = this_A & 0xFFFF;
594                A += (short)this_A;
595                break;
596              }
597            }
598          } else {
599            rsl_assert(A == 0 && "R_MIPS_GOT16 addend is not 0.");
600          }
601        } else { // R_MIPS_CALL16
602          rsl_assert(A == 0 && "R_MIPS_CALL16 addend is not 0.");
603        }
604        int got_index = search_got((int)rel->getSymTabIndex(), (void *)(S + A),
605                                   sym->getBindingAttribute());
606        int got_offset = (got_index << 2) - GP_OFFSET;
607        *inst |= (got_offset & 0xFFFF);
608      }
609      break;
610
611    case R_MIPS_GPREL32:
612      *inst = A + S - ((int)(intptr_t)got_address() + GP_OFFSET);
613      break;
614    }
615  }
616}
617
618
619// TODO: Refactor all relocations.
620template <unsigned Bitwidth>
621inline void ELFObject<Bitwidth>::
622relocate(void *(*find_sym)(void *context, char const *name), void *context) {
623  // Init SHNCommonDataSize.
624  // Need refactoring
625  size_t SHNCommonDataSize = 0;
626
627  ELFSectionSymTabTy *symtab =
628    static_cast<ELFSectionSymTabTy *>(getSectionByName(".symtab"));
629  rsl_assert(symtab && "Symtab is required.");
630
631  for (size_t i = 0; i < symtab->size(); ++i) {
632    ELFSymbolTy *sym = (*symtab)[i];
633
634    if (sym->getType() != STT_OBJECT) {
635      continue;
636    }
637
638    size_t idx = (size_t)sym->getSectionIndex();
639    switch (idx) {
640    default:
641      if ((*shtab)[idx]->getType() == SHT_NOBITS) {
642        // FIXME(logan): This is a workaround for .lcomm directives
643        // bug of LLVM ARM MC code generator.  Remove this when the
644        // LLVM bug is fixed.
645
646        size_t align = 16;
647        SHNCommonDataSize += (size_t)sym->getSize() + align;
648      }
649      break;
650
651    case SHN_COMMON:
652      {
653        size_t align = (size_t)sym->getValue();
654        SHNCommonDataSize += (size_t)sym->getSize() + align;
655      }
656      break;
657
658    case SHN_ABS:
659    case SHN_UNDEF:
660    case SHN_XINDEX:
661      break;
662    }
663  }
664  if (!initSHNCommonDataSize(SHNCommonDataSize)) {
665    rsl_assert("Allocate memory for common variable fail!");
666  }
667
668  for (size_t i = 0; i < stab.size(); ++i) {
669    ELFSectionHeaderTy *sh = (*shtab)[i];
670    if (sh->getType() != SHT_REL && sh->getType() != SHT_RELA) {
671      continue;
672    }
673    ELFSectionRelTableTy *reltab =
674      static_cast<ELFSectionRelTableTy *>(stab[i]);
675    rsl_assert(reltab && "Relocation section can't be NULL.");
676
677    const char *reltab_name = sh->getName();
678    const char *need_rel_name;
679    if (sh->getType() == SHT_REL) {
680      need_rel_name = reltab_name + 4;
681      // ".rel.xxxx"
682      //      ^ start from here.
683    } else {
684      need_rel_name = reltab_name + 5;
685    }
686
687    ELFSectionProgBitsTy *need_rel =
688      static_cast<ELFSectionProgBitsTy *>(getSectionByName(need_rel_name));
689    rsl_assert(need_rel && "Need be relocated section can't be NULL.");
690
691    switch (getHeader()->getMachine()) {
692      case EM_ARM:
693        relocateARM(find_sym, context, reltab, need_rel);
694        break;
695      case EM_386:
696        relocateX86_32(find_sym, context, reltab, need_rel);
697        break;
698      case EM_X86_64:
699        relocateX86_64(find_sym, context, reltab, need_rel);
700        break;
701      case EM_MIPS:
702        relocateMIPS(find_sym, context, reltab, need_rel);
703        break;
704
705      default:
706        rsl_assert(0 && "Only support ARM, MIPS, X86, and X86_64 relocation.");
707        break;
708    }
709  }
710
711  for (size_t i = 0; i < stab.size(); ++i) {
712    ELFSectionHeaderTy *sh = (*shtab)[i];
713    if (sh->getType() == SHT_PROGBITS || sh->getType() == SHT_NOBITS) {
714      if (stab[i]) {
715        static_cast<ELFSectionBitsTy *>(stab[i])->protect();
716      }
717    }
718  }
719}
720
721template <unsigned Bitwidth>
722inline void ELFObject<Bitwidth>::print() const {
723  header->print();
724  shtab->print();
725
726  for (size_t i = 0; i < stab.size(); ++i) {
727    ELFSectionTy *sec = stab[i];
728    if (sec) {
729      sec->print();
730    }
731  }
732}
733
734#endif // ELF_OBJECT_HXX
735