1ee6cdb95525abc8c7766798148302306a100b774Shih-wei Liao/*
2aaf2b9cdd3b76565d5f194ce52032d38849e0a17Shih-wei Liao * Copyright 2011-2012, The Android Open Source Project
3ee6cdb95525abc8c7766798148302306a100b774Shih-wei Liao *
4ee6cdb95525abc8c7766798148302306a100b774Shih-wei Liao * Licensed under the Apache License, Version 2.0 (the "License");
5ee6cdb95525abc8c7766798148302306a100b774Shih-wei Liao * you may not use this file except in compliance with the License.
6ee6cdb95525abc8c7766798148302306a100b774Shih-wei Liao * You may obtain a copy of the License at
7ee6cdb95525abc8c7766798148302306a100b774Shih-wei Liao *
8ee6cdb95525abc8c7766798148302306a100b774Shih-wei Liao *     http://www.apache.org/licenses/LICENSE-2.0
9ee6cdb95525abc8c7766798148302306a100b774Shih-wei Liao *
10ee6cdb95525abc8c7766798148302306a100b774Shih-wei Liao * Unless required by applicable law or agreed to in writing, software
11ee6cdb95525abc8c7766798148302306a100b774Shih-wei Liao * distributed under the License is distributed on an "AS IS" BASIS,
12ee6cdb95525abc8c7766798148302306a100b774Shih-wei Liao * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13ee6cdb95525abc8c7766798148302306a100b774Shih-wei Liao * See the License for the specific language governing permissions and
14ee6cdb95525abc8c7766798148302306a100b774Shih-wei Liao * limitations under the License.
15ee6cdb95525abc8c7766798148302306a100b774Shih-wei Liao */
16ee6cdb95525abc8c7766798148302306a100b774Shih-wei Liao
17919742fa8a24a869172e6cb6ac09301cbf753532Logan Chien#ifndef ELF_OBJECT_HXX
18919742fa8a24a869172e6cb6ac09301cbf753532Logan Chien#define ELF_OBJECT_HXX
19919742fa8a24a869172e6cb6ac09301cbf753532Logan Chien
20919742fa8a24a869172e6cb6ac09301cbf753532Logan Chien#include "ELFHeader.h"
21919742fa8a24a869172e6cb6ac09301cbf753532Logan Chien#include "ELFReloc.h"
22919742fa8a24a869172e6cb6ac09301cbf753532Logan Chien#include "ELFSection.h"
23919742fa8a24a869172e6cb6ac09301cbf753532Logan Chien#include "ELFSectionHeaderTable.h"
24919742fa8a24a869172e6cb6ac09301cbf753532Logan Chien#include "StubLayout.h"
250a2be45c942a83bb70a7cf1b7355db73cd30f9b9Chao-ying Fu#include "GOT.h"
26404833ada8caa7027105bd52bd36ab7822030369TDYa#include "ELF.h"
27919742fa8a24a869172e6cb6ac09301cbf753532Logan Chien
282061b057e0922ac33b9314c1ccaa50eb7286b847Logan Chien#include <llvm/ADT/SmallVector.h>
292061b057e0922ac33b9314c1ccaa50eb7286b847Logan Chien
30c40d8a8b26547ab9c51792d9d9b3aca13fb5cdf9TDYa#include "utils/rsl_assert.h"
31919742fa8a24a869172e6cb6ac09301cbf753532Logan Chien
32919742fa8a24a869172e6cb6ac09301cbf753532Logan Chientemplate <unsigned Bitwidth>
33919742fa8a24a869172e6cb6ac09301cbf753532Logan Chientemplate <typename Archiver>
34919742fa8a24a869172e6cb6ac09301cbf753532Logan Chieninline ELFObject<Bitwidth> *
35919742fa8a24a869172e6cb6ac09301cbf753532Logan ChienELFObject<Bitwidth>::read(Archiver &AR) {
3658611fc8193e7386698178f167a2e0cbdd6a4f6fLogan Chien  llvm::OwningPtr<ELFObjectTy> object(new ELFObjectTy());
37919742fa8a24a869172e6cb6ac09301cbf753532Logan Chien
38919742fa8a24a869172e6cb6ac09301cbf753532Logan Chien  // Read header
3958611fc8193e7386698178f167a2e0cbdd6a4f6fLogan Chien  object->header.reset(ELFHeaderTy::read(AR));
40919742fa8a24a869172e6cb6ac09301cbf753532Logan Chien  if (!object->header) {
41919742fa8a24a869172e6cb6ac09301cbf753532Logan Chien    return 0;
42919742fa8a24a869172e6cb6ac09301cbf753532Logan Chien  }
43919742fa8a24a869172e6cb6ac09301cbf753532Logan Chien
44919742fa8a24a869172e6cb6ac09301cbf753532Logan Chien  // Read section table
4558611fc8193e7386698178f167a2e0cbdd6a4f6fLogan Chien  object->shtab.reset(ELFSectionHeaderTableTy::read(AR, object.get()));
46919742fa8a24a869172e6cb6ac09301cbf753532Logan Chien  if (!object->shtab) {
47919742fa8a24a869172e6cb6ac09301cbf753532Logan Chien    return 0;
48919742fa8a24a869172e6cb6ac09301cbf753532Logan Chien  }
49919742fa8a24a869172e6cb6ac09301cbf753532Logan Chien
50919742fa8a24a869172e6cb6ac09301cbf753532Logan Chien  // Read each section
512061b057e0922ac33b9314c1ccaa50eb7286b847Logan Chien  llvm::SmallVector<size_t, 4> progbits_ndx;
52919742fa8a24a869172e6cb6ac09301cbf753532Logan Chien  for (size_t i = 0; i < object->header->getSectionHeaderNum(); ++i) {
532061b057e0922ac33b9314c1ccaa50eb7286b847Logan Chien    if ((*object->shtab)[i]->getType() == SHT_PROGBITS) {
542061b057e0922ac33b9314c1ccaa50eb7286b847Logan Chien      object->stab.push_back(NULL);
552061b057e0922ac33b9314c1ccaa50eb7286b847Logan Chien      progbits_ndx.push_back(i);
562061b057e0922ac33b9314c1ccaa50eb7286b847Logan Chien    } else {
572061b057e0922ac33b9314c1ccaa50eb7286b847Logan Chien      llvm::OwningPtr<ELFSectionTy> sec(
582061b057e0922ac33b9314c1ccaa50eb7286b847Logan Chien        ELFSectionTy::read(AR, object.get(), (*object->shtab)[i]));
592061b057e0922ac33b9314c1ccaa50eb7286b847Logan Chien      object->stab.push_back(sec.take());
602061b057e0922ac33b9314c1ccaa50eb7286b847Logan Chien    }
612061b057e0922ac33b9314c1ccaa50eb7286b847Logan Chien  }
622061b057e0922ac33b9314c1ccaa50eb7286b847Logan Chien
63aa989ef2e7e983ee09d0b4e02f6189da26117198Shih-wei Liao  object->shtab->buildNameMap();
64aa989ef2e7e983ee09d0b4e02f6189da26117198Shih-wei Liao  ELFSectionSymTabTy *symtab =
65aa989ef2e7e983ee09d0b4e02f6189da26117198Shih-wei Liao    static_cast<ELFSectionSymTabTy *>(object->getSectionByName(".symtab"));
66aa989ef2e7e983ee09d0b4e02f6189da26117198Shih-wei Liao  rsl_assert(symtab && "Symtab is required.");
67aa989ef2e7e983ee09d0b4e02f6189da26117198Shih-wei Liao  symtab->buildNameMap();
68aa989ef2e7e983ee09d0b4e02f6189da26117198Shih-wei Liao
692061b057e0922ac33b9314c1ccaa50eb7286b847Logan Chien  for (size_t i = 0; i < progbits_ndx.size(); ++i) {
702061b057e0922ac33b9314c1ccaa50eb7286b847Logan Chien    size_t index = progbits_ndx[i];
712061b057e0922ac33b9314c1ccaa50eb7286b847Logan Chien
7258611fc8193e7386698178f167a2e0cbdd6a4f6fLogan Chien    llvm::OwningPtr<ELFSectionTy> sec(
732061b057e0922ac33b9314c1ccaa50eb7286b847Logan Chien      ELFSectionTy::read(AR, object.get(), (*object->shtab)[index]));
742061b057e0922ac33b9314c1ccaa50eb7286b847Logan Chien    object->stab[index] = sec.take();
75919742fa8a24a869172e6cb6ac09301cbf753532Logan Chien  }
76919742fa8a24a869172e6cb6ac09301cbf753532Logan Chien
77919742fa8a24a869172e6cb6ac09301cbf753532Logan Chien  return object.take();
78919742fa8a24a869172e6cb6ac09301cbf753532Logan Chien}
79919742fa8a24a869172e6cb6ac09301cbf753532Logan Chien
80919742fa8a24a869172e6cb6ac09301cbf753532Logan Chientemplate <unsigned Bitwidth>
81919742fa8a24a869172e6cb6ac09301cbf753532Logan Chieninline char const *ELFObject<Bitwidth>::getSectionName(size_t i) const {
8258611fc8193e7386698178f167a2e0cbdd6a4f6fLogan Chien  ELFSectionTy const *sec = stab[header->getStringSectionIndex()];
83919742fa8a24a869172e6cb6ac09301cbf753532Logan Chien
84919742fa8a24a869172e6cb6ac09301cbf753532Logan Chien  if (sec) {
8558611fc8193e7386698178f167a2e0cbdd6a4f6fLogan Chien    ELFSectionStrTabTy const &st =
8658611fc8193e7386698178f167a2e0cbdd6a4f6fLogan Chien      static_cast<ELFSectionStrTabTy const &>(*sec);
87919742fa8a24a869172e6cb6ac09301cbf753532Logan Chien    return st[i];
88919742fa8a24a869172e6cb6ac09301cbf753532Logan Chien  }
89919742fa8a24a869172e6cb6ac09301cbf753532Logan Chien
90919742fa8a24a869172e6cb6ac09301cbf753532Logan Chien  return NULL;
91919742fa8a24a869172e6cb6ac09301cbf753532Logan Chien}
92919742fa8a24a869172e6cb6ac09301cbf753532Logan Chien
93919742fa8a24a869172e6cb6ac09301cbf753532Logan Chientemplate <unsigned Bitwidth>
94919742fa8a24a869172e6cb6ac09301cbf753532Logan Chieninline ELFSection<Bitwidth> const *
95919742fa8a24a869172e6cb6ac09301cbf753532Logan ChienELFObject<Bitwidth>::getSectionByIndex(size_t i) const {
96919742fa8a24a869172e6cb6ac09301cbf753532Logan Chien  return stab[i];
97919742fa8a24a869172e6cb6ac09301cbf753532Logan Chien}
98919742fa8a24a869172e6cb6ac09301cbf753532Logan Chien
99919742fa8a24a869172e6cb6ac09301cbf753532Logan Chientemplate <unsigned Bitwidth>
100919742fa8a24a869172e6cb6ac09301cbf753532Logan Chieninline ELFSection<Bitwidth> *
101919742fa8a24a869172e6cb6ac09301cbf753532Logan ChienELFObject<Bitwidth>::getSectionByIndex(size_t i) {
102919742fa8a24a869172e6cb6ac09301cbf753532Logan Chien  return stab[i];
103919742fa8a24a869172e6cb6ac09301cbf753532Logan Chien}
104919742fa8a24a869172e6cb6ac09301cbf753532Logan Chien
105919742fa8a24a869172e6cb6ac09301cbf753532Logan Chientemplate <unsigned Bitwidth>
106919742fa8a24a869172e6cb6ac09301cbf753532Logan Chieninline ELFSection<Bitwidth> const *
107919742fa8a24a869172e6cb6ac09301cbf753532Logan ChienELFObject<Bitwidth>::getSectionByName(std::string const &str) const {
108919742fa8a24a869172e6cb6ac09301cbf753532Logan Chien  size_t idx = getSectionHeaderTable()->getByName(str)->getIndex();
109919742fa8a24a869172e6cb6ac09301cbf753532Logan Chien  return stab[idx];
110919742fa8a24a869172e6cb6ac09301cbf753532Logan Chien}
111919742fa8a24a869172e6cb6ac09301cbf753532Logan Chien
112919742fa8a24a869172e6cb6ac09301cbf753532Logan Chientemplate <unsigned Bitwidth>
113919742fa8a24a869172e6cb6ac09301cbf753532Logan Chieninline ELFSection<Bitwidth> *
114919742fa8a24a869172e6cb6ac09301cbf753532Logan ChienELFObject<Bitwidth>::getSectionByName(std::string const &str) {
11558611fc8193e7386698178f167a2e0cbdd6a4f6fLogan Chien  ELFObjectTy const *const_this = this;
11658611fc8193e7386698178f167a2e0cbdd6a4f6fLogan Chien  ELFSectionTy const *sptr = const_this->getSectionByName(str);
117919742fa8a24a869172e6cb6ac09301cbf753532Logan Chien  // Const cast for the same API's const and non-const versions.
11858611fc8193e7386698178f167a2e0cbdd6a4f6fLogan Chien  return const_cast<ELFSectionTy *>(sptr);
119919742fa8a24a869172e6cb6ac09301cbf753532Logan Chien}
120919742fa8a24a869172e6cb6ac09301cbf753532Logan Chien
121919742fa8a24a869172e6cb6ac09301cbf753532Logan Chien
122919742fa8a24a869172e6cb6ac09301cbf753532Logan Chientemplate <unsigned Bitwidth>
123919742fa8a24a869172e6cb6ac09301cbf753532Logan Chieninline void ELFObject<Bitwidth>::
1244e4356b34f9751070ac8ccb1bb74bb44e9232661Logan ChienrelocateARM(void *(*find_sym)(void *context, char const *name),
125a13b6909c66260aabbcd32b6519d05e469881141TDYa            void *context,
126a13b6909c66260aabbcd32b6519d05e469881141TDYa            ELFSectionRelTableTy *reltab,
127a13b6909c66260aabbcd32b6519d05e469881141TDYa            ELFSectionProgBitsTy *text) {
128919742fa8a24a869172e6cb6ac09301cbf753532Logan Chien  // FIXME: Should be implement in independent files.
129c40d8a8b26547ab9c51792d9d9b3aca13fb5cdf9TDYa  rsl_assert(Bitwidth == 32 && "ARM only have 32 bits.");
130919742fa8a24a869172e6cb6ac09301cbf753532Logan Chien
13158611fc8193e7386698178f167a2e0cbdd6a4f6fLogan Chien  ELFSectionSymTabTy *symtab =
13258611fc8193e7386698178f167a2e0cbdd6a4f6fLogan Chien    static_cast<ELFSectionSymTabTy *>(getSectionByName(".symtab"));
1331afb83e8507d8285b12826c7693821e3f25d8d8bTDYa  rsl_assert(symtab && "Symtab is required.");
134919742fa8a24a869172e6cb6ac09301cbf753532Logan Chien
135919742fa8a24a869172e6cb6ac09301cbf753532Logan Chien  for (size_t i = 0; i < reltab->size(); ++i) {
136919742fa8a24a869172e6cb6ac09301cbf753532Logan Chien    // FIXME: Can not implement here, use Fixup!
13758611fc8193e7386698178f167a2e0cbdd6a4f6fLogan Chien    ELFRelocTy *rel = (*reltab)[i];
13858611fc8193e7386698178f167a2e0cbdd6a4f6fLogan Chien    ELFSymbolTy *sym = (*symtab)[rel->getSymTabIndex()];
139919742fa8a24a869172e6cb6ac09301cbf753532Logan Chien
140919742fa8a24a869172e6cb6ac09301cbf753532Logan Chien    // FIXME: May be not uint32_t *.
141919742fa8a24a869172e6cb6ac09301cbf753532Logan Chien    typedef int32_t Inst_t;
142919742fa8a24a869172e6cb6ac09301cbf753532Logan Chien    Inst_t *inst = (Inst_t *)&(*text)[rel->getOffset()];
143919742fa8a24a869172e6cb6ac09301cbf753532Logan Chien    Inst_t P = (Inst_t)(int64_t)inst;
144919742fa8a24a869172e6cb6ac09301cbf753532Logan Chien    Inst_t A = 0;
1459ed73923af9db7283a8c76b5dfa2dda5b732a852Andrew Hsieh    Inst_t S = (Inst_t)(int64_t)sym->getAddress(EM_ARM);
1462a7f249060179fdcb49f240bdf349c4e7b896084Shih-wei Liao    Inst_t T = 0;
1472a7f249060179fdcb49f240bdf349c4e7b896084Shih-wei Liao
1482a7f249060179fdcb49f240bdf349c4e7b896084Shih-wei Liao    if (sym->isConcreteFunc() && (sym->getValue() & 0x1)) {
1492a7f249060179fdcb49f240bdf349c4e7b896084Shih-wei Liao      T = 1;
1502a7f249060179fdcb49f240bdf349c4e7b896084Shih-wei Liao    }
151919742fa8a24a869172e6cb6ac09301cbf753532Logan Chien
15271e5a4a2fa18ff55b1e04e73b70b2938150a143cLogan Chien    switch (rel->getType()) {
153919742fa8a24a869172e6cb6ac09301cbf753532Logan Chien    default:
154c40d8a8b26547ab9c51792d9d9b3aca13fb5cdf9TDYa      rsl_assert(0 && "Not implemented relocation type.");
155919742fa8a24a869172e6cb6ac09301cbf753532Logan Chien      break;
156919742fa8a24a869172e6cb6ac09301cbf753532Logan Chien
157404833ada8caa7027105bd52bd36ab7822030369TDYa    case R_ARM_ABS32:
158f1bac53ec8d1c561bb9c0d82577f8afb51cfc6b0TDYa      {
1596cf155a77c693c51ab9d4b1cf29f0fa898afd1c9Logan Chien        if (S == 0 && sym->getType() == STT_NOTYPE) {
1606cf155a77c693c51ab9d4b1cf29f0fa898afd1c9Logan Chien          void *ext_sym = find_sym(context, sym->getName());
1616cf155a77c693c51ab9d4b1cf29f0fa898afd1c9Logan Chien          if (!ext_sym) {
1626cf155a77c693c51ab9d4b1cf29f0fa898afd1c9Logan Chien            missingSymbols = true;
1636cf155a77c693c51ab9d4b1cf29f0fa898afd1c9Logan Chien          }
1646cf155a77c693c51ab9d4b1cf29f0fa898afd1c9Logan Chien          S = (Inst_t)(uintptr_t)ext_sym;
1656cf155a77c693c51ab9d4b1cf29f0fa898afd1c9Logan Chien          sym->setAddress(ext_sym);
1666cf155a77c693c51ab9d4b1cf29f0fa898afd1c9Logan Chien        }
167f1bac53ec8d1c561bb9c0d82577f8afb51cfc6b0TDYa        A = *inst;
1682a7f249060179fdcb49f240bdf349c4e7b896084Shih-wei Liao        *inst = (S + A) | T;
169f1bac53ec8d1c561bb9c0d82577f8afb51cfc6b0TDYa      }
170f1bac53ec8d1c561bb9c0d82577f8afb51cfc6b0TDYa      break;
171f1bac53ec8d1c561bb9c0d82577f8afb51cfc6b0TDYa
172919742fa8a24a869172e6cb6ac09301cbf753532Logan Chien      // FIXME: Predefine relocation codes.
173404833ada8caa7027105bd52bd36ab7822030369TDYa    case R_ARM_CALL:
1742a7f249060179fdcb49f240bdf349c4e7b896084Shih-wei Liao    case R_ARM_THM_CALL:
175919742fa8a24a869172e6cb6ac09301cbf753532Logan Chien      {
176919742fa8a24a869172e6cb6ac09301cbf753532Logan Chien#define SIGN_EXTEND(x, l) (((x)^(1<<((l)-1)))-(1<<(l-1)))
1772a7f249060179fdcb49f240bdf349c4e7b896084Shih-wei Liao        if (rel->getType() == R_ARM_CALL) {
1782a7f249060179fdcb49f240bdf349c4e7b896084Shih-wei Liao          A = (Inst_t)(int64_t)SIGN_EXTEND(*inst & 0xFFFFFF, 24);
1792a7f249060179fdcb49f240bdf349c4e7b896084Shih-wei Liao          A <<= 2;
18056ca447beb2f9d893d9c3dbee5c46090e929529bShih-wei Liao        } else {
1812a7f249060179fdcb49f240bdf349c4e7b896084Shih-wei Liao          // Hack for two 16bit.
1822a7f249060179fdcb49f240bdf349c4e7b896084Shih-wei Liao          *inst = ((*inst >> 16) & 0xFFFF) | (*inst << 16);
1832a7f249060179fdcb49f240bdf349c4e7b896084Shih-wei Liao          Inst_t s  = (*inst >> 26) & 0x1u,    // 26
1842a7f249060179fdcb49f240bdf349c4e7b896084Shih-wei Liao                 u  = (*inst >> 16) & 0x3FFu,  // 25-16
1852a7f249060179fdcb49f240bdf349c4e7b896084Shih-wei Liao                 l  =  *inst        & 0x7FFu, // 10-0
1862a7f249060179fdcb49f240bdf349c4e7b896084Shih-wei Liao                 j1 = (*inst >> 13) & 0x1u,    // 13
1872a7f249060179fdcb49f240bdf349c4e7b896084Shih-wei Liao                 j2 = (*inst >> 11) & 0x1u;    // 11
1882a7f249060179fdcb49f240bdf349c4e7b896084Shih-wei Liao          Inst_t i1 = (~(j1 ^ s)) & 0x1u,
1892a7f249060179fdcb49f240bdf349c4e7b896084Shih-wei Liao                 i2 = (~(j2 ^ s)) & 0x1u;
1902a7f249060179fdcb49f240bdf349c4e7b896084Shih-wei Liao          // [31-25][24][23][22][21-12][11-1][0]
1912a7f249060179fdcb49f240bdf349c4e7b896084Shih-wei Liao          //      0   s  i1  i2      u     l  0
1922a7f249060179fdcb49f240bdf349c4e7b896084Shih-wei Liao          A = SIGN_EXTEND((s << 23) | (i1 << 22) | (i2 << 21) | (u << 11) | l, 24);
1932a7f249060179fdcb49f240bdf349c4e7b896084Shih-wei Liao          A <<= 1;
1942a7f249060179fdcb49f240bdf349c4e7b896084Shih-wei Liao        }
195919742fa8a24a869172e6cb6ac09301cbf753532Logan Chien#undef SIGN_EXTEND
196ddd3e1ce7bddc792b89cd23cbe0150c57c97e70aLogan Chien
1979ed73923af9db7283a8c76b5dfa2dda5b732a852Andrew Hsieh        void *callee_addr = sym->getAddress(EM_ARM);
1987cea0a041b87afe2c5ad5f26e6a89494d0819bd1Logan Chien
1998fd2076f982ce042731a965a2e62309c51713814Logan Chien        switch (sym->getType()) {
2008fd2076f982ce042731a965a2e62309c51713814Logan Chien        default:
201c40d8a8b26547ab9c51792d9d9b3aca13fb5cdf9TDYa          rsl_assert(0 && "Wrong type for R_ARM_CALL relocation.");
202ddd3e1ce7bddc792b89cd23cbe0150c57c97e70aLogan Chien          abort();
2038fd2076f982ce042731a965a2e62309c51713814Logan Chien          break;
2048fd2076f982ce042731a965a2e62309c51713814Logan Chien
2058fd2076f982ce042731a965a2e62309c51713814Logan Chien        case STT_FUNC:
2067cea0a041b87afe2c5ad5f26e6a89494d0819bd1Logan Chien          // NOTE: Callee function is in the object file, but it may be
2077cea0a041b87afe2c5ad5f26e6a89494d0819bd1Logan Chien          // in different PROGBITS section (which may be far call).
2087cea0a041b87afe2c5ad5f26e6a89494d0819bd1Logan Chien
2097cea0a041b87afe2c5ad5f26e6a89494d0819bd1Logan Chien          if (callee_addr == 0) {
210c40d8a8b26547ab9c51792d9d9b3aca13fb5cdf9TDYa            rsl_assert(0 && "We should get function address at previous "
2119ed73923af9db7283a8c76b5dfa2dda5b732a852Andrew Hsieh                   "sym->getAddress(EM_ARM) function call.");
212ddd3e1ce7bddc792b89cd23cbe0150c57c97e70aLogan Chien            abort();
213ddd3e1ce7bddc792b89cd23cbe0150c57c97e70aLogan Chien          }
2148fd2076f982ce042731a965a2e62309c51713814Logan Chien          break;
2158fd2076f982ce042731a965a2e62309c51713814Logan Chien
2168fd2076f982ce042731a965a2e62309c51713814Logan Chien        case STT_NOTYPE:
2177cea0a041b87afe2c5ad5f26e6a89494d0819bd1Logan Chien          // NOTE: Callee function is an external function.  Call find_sym
2187cea0a041b87afe2c5ad5f26e6a89494d0819bd1Logan Chien          // if it has not resolved yet.
2197cea0a041b87afe2c5ad5f26e6a89494d0819bd1Logan Chien
2207cea0a041b87afe2c5ad5f26e6a89494d0819bd1Logan Chien          if (callee_addr == 0) {
2217cea0a041b87afe2c5ad5f26e6a89494d0819bd1Logan Chien            callee_addr = find_sym(context, sym->getName());
22250b814ae8797a929bc0416d6a97e3551b24eaf30Stephen Hines            if (!callee_addr) {
22350b814ae8797a929bc0416d6a97e3551b24eaf30Stephen Hines              missingSymbols = true;
22450b814ae8797a929bc0416d6a97e3551b24eaf30Stephen Hines            }
2257cea0a041b87afe2c5ad5f26e6a89494d0819bd1Logan Chien            sym->setAddress(callee_addr);
2268fd2076f982ce042731a965a2e62309c51713814Logan Chien          }
2278fd2076f982ce042731a965a2e62309c51713814Logan Chien          break;
2288fd2076f982ce042731a965a2e62309c51713814Logan Chien        }
2298fd2076f982ce042731a965a2e62309c51713814Logan Chien
2307cea0a041b87afe2c5ad5f26e6a89494d0819bd1Logan Chien        // Get the stub for this function
23172dca268900fa25946bade332f0fbdc2c2ff9487Andrew Hsieh        StubLayout *stub_layout = text->getStubLayout();
23272dca268900fa25946bade332f0fbdc2c2ff9487Andrew Hsieh
23372dca268900fa25946bade332f0fbdc2c2ff9487Andrew Hsieh        if (!stub_layout) {
23472dca268900fa25946bade332f0fbdc2c2ff9487Andrew Hsieh          llvm::errs() << "unable to get stub layout." << "\n";
23572dca268900fa25946bade332f0fbdc2c2ff9487Andrew Hsieh          abort();
23672dca268900fa25946bade332f0fbdc2c2ff9487Andrew Hsieh        }
23772dca268900fa25946bade332f0fbdc2c2ff9487Andrew Hsieh
23872dca268900fa25946bade332f0fbdc2c2ff9487Andrew Hsieh        void *stub = stub_layout->allocateStub(callee_addr);
2397cea0a041b87afe2c5ad5f26e6a89494d0819bd1Logan Chien
2407cea0a041b87afe2c5ad5f26e6a89494d0819bd1Logan Chien        if (!stub) {
2417cea0a041b87afe2c5ad5f26e6a89494d0819bd1Logan Chien          llvm::errs() << "unable to allocate stub." << "\n";
2427cea0a041b87afe2c5ad5f26e6a89494d0819bd1Logan Chien          abort();
2437cea0a041b87afe2c5ad5f26e6a89494d0819bd1Logan Chien        }
2447cea0a041b87afe2c5ad5f26e6a89494d0819bd1Logan Chien
2457cea0a041b87afe2c5ad5f26e6a89494d0819bd1Logan Chien        //LOGI("Function %s: using stub %p\n", sym->getName(), stub);
246ec5d468bb925d7fe1aaa47b0cc4f084017531746Logan Chien        S = (uint32_t)(uintptr_t)stub;
2477cea0a041b87afe2c5ad5f26e6a89494d0819bd1Logan Chien
2482a7f249060179fdcb49f240bdf349c4e7b896084Shih-wei Liao        if (rel->getType() == R_ARM_CALL) {
2492a7f249060179fdcb49f240bdf349c4e7b896084Shih-wei Liao          // Relocate the R_ARM_CALL relocation type
2502a7f249060179fdcb49f240bdf349c4e7b896084Shih-wei Liao          uint32_t result = (S + A - P) >> 2;
2518fd2076f982ce042731a965a2e62309c51713814Logan Chien
2522a7f249060179fdcb49f240bdf349c4e7b896084Shih-wei Liao          if (result > 0x007FFFFF && result < 0xFF800000) {
2532a7f249060179fdcb49f240bdf349c4e7b896084Shih-wei Liao            rsl_assert(0 && "Stub is still too far");
2542a7f249060179fdcb49f240bdf349c4e7b896084Shih-wei Liao            abort();
2552a7f249060179fdcb49f240bdf349c4e7b896084Shih-wei Liao          }
2562a7f249060179fdcb49f240bdf349c4e7b896084Shih-wei Liao
2572a7f249060179fdcb49f240bdf349c4e7b896084Shih-wei Liao          *inst = ((result) & 0x00FFFFFF) | (*inst & 0xFF000000);
25856ca447beb2f9d893d9c3dbee5c46090e929529bShih-wei Liao        } else {
25956ca447beb2f9d893d9c3dbee5c46090e929529bShih-wei Liao          P &= ~0x3;  // Base address align to 4 bytes.  (For BLX.)
26059411237b1aacabd1dbe36cb4b073a4ac9caab6dShih-wei Liao
2612a7f249060179fdcb49f240bdf349c4e7b896084Shih-wei Liao          // Relocate the R_ARM_THM_CALL relocation type
2622a7f249060179fdcb49f240bdf349c4e7b896084Shih-wei Liao          uint32_t result = (S + A - P) >> 1;
2632a7f249060179fdcb49f240bdf349c4e7b896084Shih-wei Liao
2642a7f249060179fdcb49f240bdf349c4e7b896084Shih-wei Liao          if (result > 0x007FFFFF && result < 0xFF800000) {
2652a7f249060179fdcb49f240bdf349c4e7b896084Shih-wei Liao            rsl_assert(0 && "Stub is still too far");
2662a7f249060179fdcb49f240bdf349c4e7b896084Shih-wei Liao            abort();
2672a7f249060179fdcb49f240bdf349c4e7b896084Shih-wei Liao          }
268ddd3e1ce7bddc792b89cd23cbe0150c57c97e70aLogan Chien
26959411237b1aacabd1dbe36cb4b073a4ac9caab6dShih-wei Liao          //*inst &= 0xF800D000u;
27056ca447beb2f9d893d9c3dbee5c46090e929529bShih-wei Liao          // Rewrite instruction to BLX.  (Stub is always ARM.)
2712a7f249060179fdcb49f240bdf349c4e7b896084Shih-wei Liao          *inst &= 0xF800C000u;
2722a7f249060179fdcb49f240bdf349c4e7b896084Shih-wei Liao          // [31-25][24][23][22][21-12][11-1][0]
2732a7f249060179fdcb49f240bdf349c4e7b896084Shih-wei Liao          //      0   s  i1  i2      u     l  0
2742a7f249060179fdcb49f240bdf349c4e7b896084Shih-wei Liao          Inst_t s  = (result >> 23) & 0x1u,   // 26
2752a7f249060179fdcb49f240bdf349c4e7b896084Shih-wei Liao                 u  = (result >> 11) & 0x3FFu, // 25-16
2762a7f249060179fdcb49f240bdf349c4e7b896084Shih-wei Liao                 // For BLX, bit [0] is 0.
2772a7f249060179fdcb49f240bdf349c4e7b896084Shih-wei Liao                 l  =  result        & 0x7FEu, // 10-0
2782a7f249060179fdcb49f240bdf349c4e7b896084Shih-wei Liao                 i1 = (result >> 22) & 0x1u,
2792a7f249060179fdcb49f240bdf349c4e7b896084Shih-wei Liao                 i2 = (result >> 21) & 0x1u;
2802a7f249060179fdcb49f240bdf349c4e7b896084Shih-wei Liao          Inst_t j1 = ((~i1) ^ s) & 0x01u,       // 13
2812a7f249060179fdcb49f240bdf349c4e7b896084Shih-wei Liao                 j2 = ((~i2) ^ s) & 0x01u;       // 11
2822a7f249060179fdcb49f240bdf349c4e7b896084Shih-wei Liao          *inst |= s << 26;
2832a7f249060179fdcb49f240bdf349c4e7b896084Shih-wei Liao          *inst |= u << 16;
2842a7f249060179fdcb49f240bdf349c4e7b896084Shih-wei Liao          *inst |= l;
2852a7f249060179fdcb49f240bdf349c4e7b896084Shih-wei Liao          *inst |= j1 << 13;
2862a7f249060179fdcb49f240bdf349c4e7b896084Shih-wei Liao          *inst |= j2 << 11;
2872a7f249060179fdcb49f240bdf349c4e7b896084Shih-wei Liao          // Hack for two 16bit.
2882a7f249060179fdcb49f240bdf349c4e7b896084Shih-wei Liao          *inst = ((*inst >> 16) & 0xFFFF) | (*inst << 16);
2892a7f249060179fdcb49f240bdf349c4e7b896084Shih-wei Liao        }
290919742fa8a24a869172e6cb6ac09301cbf753532Logan Chien      }
291919742fa8a24a869172e6cb6ac09301cbf753532Logan Chien      break;
292404833ada8caa7027105bd52bd36ab7822030369TDYa    case R_ARM_MOVT_ABS:
293404833ada8caa7027105bd52bd36ab7822030369TDYa    case R_ARM_MOVW_ABS_NC:
2942a7f249060179fdcb49f240bdf349c4e7b896084Shih-wei Liao    case R_ARM_THM_MOVW_ABS_NC:
2952a7f249060179fdcb49f240bdf349c4e7b896084Shih-wei Liao    case R_ARM_THM_MOVT_ABS:
296919742fa8a24a869172e6cb6ac09301cbf753532Logan Chien      {
2976cf155a77c693c51ab9d4b1cf29f0fa898afd1c9Logan Chien        if (S == 0 && sym->getType() == STT_NOTYPE) {
29852b519a2d1b0a29b8e76230ee7f9625fd25dda2aAndrew Hsieh          void *ext_sym = find_sym(context, sym->getName());
29950b814ae8797a929bc0416d6a97e3551b24eaf30Stephen Hines          if (!ext_sym) {
30050b814ae8797a929bc0416d6a97e3551b24eaf30Stephen Hines            missingSymbols = true;
30150b814ae8797a929bc0416d6a97e3551b24eaf30Stephen Hines          }
30252b519a2d1b0a29b8e76230ee7f9625fd25dda2aAndrew Hsieh          S = (Inst_t)(uintptr_t)ext_sym;
30352b519a2d1b0a29b8e76230ee7f9625fd25dda2aAndrew Hsieh          sym->setAddress(ext_sym);
30452b519a2d1b0a29b8e76230ee7f9625fd25dda2aAndrew Hsieh        }
3052a7f249060179fdcb49f240bdf349c4e7b896084Shih-wei Liao        if (rel->getType() == R_ARM_MOVT_ABS
3062a7f249060179fdcb49f240bdf349c4e7b896084Shih-wei Liao            || rel->getType() == R_ARM_THM_MOVT_ABS) {
30752b519a2d1b0a29b8e76230ee7f9625fd25dda2aAndrew Hsieh          S >>= 16;
30852b519a2d1b0a29b8e76230ee7f9625fd25dda2aAndrew Hsieh        }
30952b519a2d1b0a29b8e76230ee7f9625fd25dda2aAndrew Hsieh
3102a7f249060179fdcb49f240bdf349c4e7b896084Shih-wei Liao        if (rel->getType() == R_ARM_MOVT_ABS
3112a7f249060179fdcb49f240bdf349c4e7b896084Shih-wei Liao            || rel->getType() == R_ARM_MOVW_ABS_NC) {
3122a7f249060179fdcb49f240bdf349c4e7b896084Shih-wei Liao          // No need sign extend.
3132a7f249060179fdcb49f240bdf349c4e7b896084Shih-wei Liao          A = ((*inst & 0xF0000) >> 4) | (*inst & 0xFFF);
3142a7f249060179fdcb49f240bdf349c4e7b896084Shih-wei Liao          uint32_t result = (S + A);
3152a7f249060179fdcb49f240bdf349c4e7b896084Shih-wei Liao          *inst = (((result) & 0xF000) << 4) |
3162a7f249060179fdcb49f240bdf349c4e7b896084Shih-wei Liao            ((result) & 0xFFF) |
3172a7f249060179fdcb49f240bdf349c4e7b896084Shih-wei Liao            (*inst & 0xFFF0F000);
31856ca447beb2f9d893d9c3dbee5c46090e929529bShih-wei Liao        } else {
3192a7f249060179fdcb49f240bdf349c4e7b896084Shih-wei Liao          // Hack for two 16bit.
3202a7f249060179fdcb49f240bdf349c4e7b896084Shih-wei Liao          *inst = ((*inst >> 16) & 0xFFFF) | (*inst << 16);
3212a7f249060179fdcb49f240bdf349c4e7b896084Shih-wei Liao          // imm16: [19-16][26][14-12][7-0]
3222a7f249060179fdcb49f240bdf349c4e7b896084Shih-wei Liao          A = (((*inst >>  4) & 0xF000u) |
3232a7f249060179fdcb49f240bdf349c4e7b896084Shih-wei Liao               ((*inst >> 15) & 0x0800u) |
3242a7f249060179fdcb49f240bdf349c4e7b896084Shih-wei Liao               ((*inst >>  4) & 0x0700u) |
3252a7f249060179fdcb49f240bdf349c4e7b896084Shih-wei Liao               ( *inst        & 0x00FFu));
3262a7f249060179fdcb49f240bdf349c4e7b896084Shih-wei Liao          uint32_t result;
3272a7f249060179fdcb49f240bdf349c4e7b896084Shih-wei Liao          if (rel->getType() == R_ARM_THM_MOVT_ABS) {
3282a7f249060179fdcb49f240bdf349c4e7b896084Shih-wei Liao            result = (S + A);
3292a7f249060179fdcb49f240bdf349c4e7b896084Shih-wei Liao          } else {
3302a7f249060179fdcb49f240bdf349c4e7b896084Shih-wei Liao            result = (S + A) | T;
3312a7f249060179fdcb49f240bdf349c4e7b896084Shih-wei Liao          }
3322a7f249060179fdcb49f240bdf349c4e7b896084Shih-wei Liao          // imm16: [19-16][26][14-12][7-0]
3332a7f249060179fdcb49f240bdf349c4e7b896084Shih-wei Liao          *inst &= 0xFBF08F00u;
3342a7f249060179fdcb49f240bdf349c4e7b896084Shih-wei Liao          *inst |= (result & 0xF000u) << 4;
3352a7f249060179fdcb49f240bdf349c4e7b896084Shih-wei Liao          *inst |= (result & 0x0800u) << 15;
3362a7f249060179fdcb49f240bdf349c4e7b896084Shih-wei Liao          *inst |= (result & 0x0700u) << 4;
3372a7f249060179fdcb49f240bdf349c4e7b896084Shih-wei Liao          *inst |= (result & 0x00FFu);
3382a7f249060179fdcb49f240bdf349c4e7b896084Shih-wei Liao          // Hack for two 16bit.
3392a7f249060179fdcb49f240bdf349c4e7b896084Shih-wei Liao          *inst = ((*inst >> 16) & 0xFFFF) | (*inst << 16);
3402a7f249060179fdcb49f240bdf349c4e7b896084Shih-wei Liao        }
341919742fa8a24a869172e6cb6ac09301cbf753532Logan Chien      }
342919742fa8a24a869172e6cb6ac09301cbf753532Logan Chien      break;
343919742fa8a24a869172e6cb6ac09301cbf753532Logan Chien    }
344919742fa8a24a869172e6cb6ac09301cbf753532Logan Chien    //llvm::errs() << "S:     " << (void *)S << '\n';
345919742fa8a24a869172e6cb6ac09301cbf753532Logan Chien    //llvm::errs() << "A:     " << (void *)A << '\n';
346919742fa8a24a869172e6cb6ac09301cbf753532Logan Chien    //llvm::errs() << "P:     " << (void *)P << '\n';
347919742fa8a24a869172e6cb6ac09301cbf753532Logan Chien    //llvm::errs() << "S+A:   " << (void *)(S+A) << '\n';
348919742fa8a24a869172e6cb6ac09301cbf753532Logan Chien    //llvm::errs() << "S+A-P: " << (void *)(S+A-P) << '\n';
349919742fa8a24a869172e6cb6ac09301cbf753532Logan Chien  }
350919742fa8a24a869172e6cb6ac09301cbf753532Logan Chien}
351919742fa8a24a869172e6cb6ac09301cbf753532Logan Chien
352919742fa8a24a869172e6cb6ac09301cbf753532Logan Chientemplate <unsigned Bitwidth>
353919742fa8a24a869172e6cb6ac09301cbf753532Logan Chieninline void ELFObject<Bitwidth>::
3544e4356b34f9751070ac8ccb1bb74bb44e9232661Logan ChienrelocateX86_64(void *(*find_sym)(void *context, char const *name),
355a13b6909c66260aabbcd32b6519d05e469881141TDYa               void *context,
356a13b6909c66260aabbcd32b6519d05e469881141TDYa               ELFSectionRelTableTy *reltab,
357a13b6909c66260aabbcd32b6519d05e469881141TDYa               ELFSectionProgBitsTy *text) {
358c40d8a8b26547ab9c51792d9d9b3aca13fb5cdf9TDYa  rsl_assert(Bitwidth == 64 && "Only support X86_64.");
359919742fa8a24a869172e6cb6ac09301cbf753532Logan Chien
36058611fc8193e7386698178f167a2e0cbdd6a4f6fLogan Chien  ELFSectionSymTabTy *symtab =
36158611fc8193e7386698178f167a2e0cbdd6a4f6fLogan Chien    static_cast<ELFSectionSymTabTy *>(getSectionByName(".symtab"));
3621afb83e8507d8285b12826c7693821e3f25d8d8bTDYa  rsl_assert(symtab && "Symtab is required.");
363919742fa8a24a869172e6cb6ac09301cbf753532Logan Chien
364a13b6909c66260aabbcd32b6519d05e469881141TDYa  for (size_t i = 0; i < reltab->size(); ++i) {
365a13b6909c66260aabbcd32b6519d05e469881141TDYa    // FIXME: Can not implement here, use Fixup!
366a13b6909c66260aabbcd32b6519d05e469881141TDYa    ELFRelocTy *rel = (*reltab)[i];
367a13b6909c66260aabbcd32b6519d05e469881141TDYa    ELFSymbolTy *sym = (*symtab)[rel->getSymTabIndex()];
368919742fa8a24a869172e6cb6ac09301cbf753532Logan Chien
369a13b6909c66260aabbcd32b6519d05e469881141TDYa    //typedef uint64_t Inst_t;
370a13b6909c66260aabbcd32b6519d05e469881141TDYa    typedef int32_t Inst_t;
371a13b6909c66260aabbcd32b6519d05e469881141TDYa    Inst_t *inst = (Inst_t *)&(*text)[rel->getOffset()];
372a13b6909c66260aabbcd32b6519d05e469881141TDYa    Inst_t P = (Inst_t)(int64_t)inst;
373a13b6909c66260aabbcd32b6519d05e469881141TDYa    Inst_t A = (Inst_t)(int64_t)rel->getAddend();
3749ed73923af9db7283a8c76b5dfa2dda5b732a852Andrew Hsieh    Inst_t S = (Inst_t)(int64_t)sym->getAddress(EM_X86_64);
375919742fa8a24a869172e6cb6ac09301cbf753532Logan Chien
376a13b6909c66260aabbcd32b6519d05e469881141TDYa    if (S == 0) {
377a13b6909c66260aabbcd32b6519d05e469881141TDYa      S = (Inst_t)(int64_t)find_sym(context, sym->getName());
37850b814ae8797a929bc0416d6a97e3551b24eaf30Stephen Hines      if (!S) {
37950b814ae8797a929bc0416d6a97e3551b24eaf30Stephen Hines        missingSymbols = true;
38050b814ae8797a929bc0416d6a97e3551b24eaf30Stephen Hines      }
381a13b6909c66260aabbcd32b6519d05e469881141TDYa      sym->setAddress((void *)S);
382a13b6909c66260aabbcd32b6519d05e469881141TDYa    }
383919742fa8a24a869172e6cb6ac09301cbf753532Logan Chien
384a13b6909c66260aabbcd32b6519d05e469881141TDYa    switch (rel->getType()) {
385a13b6909c66260aabbcd32b6519d05e469881141TDYa      default:
386a13b6909c66260aabbcd32b6519d05e469881141TDYa        rsl_assert(0 && "Not implemented relocation type.");
387a13b6909c66260aabbcd32b6519d05e469881141TDYa        break;
388a13b6909c66260aabbcd32b6519d05e469881141TDYa
389f3f63d6ded54ea520f5066979b53c2356092692dTDYa      // FIXME: XXX: R_X86_64_64 is 64 bit, there is a big problem here.
390f3f63d6ded54ea520f5066979b53c2356092692dTDYa      case 1: // R_X86_64_64
391f3f63d6ded54ea520f5066979b53c2356092692dTDYa        *inst = (S+A);
392f3f63d6ded54ea520f5066979b53c2356092692dTDYa        break;
393f3f63d6ded54ea520f5066979b53c2356092692dTDYa
394a13b6909c66260aabbcd32b6519d05e469881141TDYa      case 2: // R_X86_64_PC32
395a13b6909c66260aabbcd32b6519d05e469881141TDYa        *inst = (S+A-P);
396a13b6909c66260aabbcd32b6519d05e469881141TDYa        break;
397a13b6909c66260aabbcd32b6519d05e469881141TDYa
398a13b6909c66260aabbcd32b6519d05e469881141TDYa      case 10: // R_X86_64_32
399a13b6909c66260aabbcd32b6519d05e469881141TDYa      case 11: // R_X86_64_32S
400a13b6909c66260aabbcd32b6519d05e469881141TDYa        *inst = (S+A);
401a13b6909c66260aabbcd32b6519d05e469881141TDYa        break;
402919742fa8a24a869172e6cb6ac09301cbf753532Logan Chien    }
403919742fa8a24a869172e6cb6ac09301cbf753532Logan Chien  }
404919742fa8a24a869172e6cb6ac09301cbf753532Logan Chien}
405919742fa8a24a869172e6cb6ac09301cbf753532Logan Chien
406919742fa8a24a869172e6cb6ac09301cbf753532Logan Chientemplate <unsigned Bitwidth>
407919742fa8a24a869172e6cb6ac09301cbf753532Logan Chieninline void ELFObject<Bitwidth>::
4084e4356b34f9751070ac8ccb1bb74bb44e9232661Logan ChienrelocateX86_32(void *(*find_sym)(void *context, char const *name),
409a13b6909c66260aabbcd32b6519d05e469881141TDYa               void *context,
410a13b6909c66260aabbcd32b6519d05e469881141TDYa               ELFSectionRelTableTy *reltab,
411a13b6909c66260aabbcd32b6519d05e469881141TDYa               ELFSectionProgBitsTy *text) {
412c40d8a8b26547ab9c51792d9d9b3aca13fb5cdf9TDYa  rsl_assert(Bitwidth == 32 && "Only support X86.");
413919742fa8a24a869172e6cb6ac09301cbf753532Logan Chien
41458611fc8193e7386698178f167a2e0cbdd6a4f6fLogan Chien  ELFSectionSymTabTy *symtab =
41558611fc8193e7386698178f167a2e0cbdd6a4f6fLogan Chien    static_cast<ELFSectionSymTabTy *>(getSectionByName(".symtab"));
4161afb83e8507d8285b12826c7693821e3f25d8d8bTDYa  rsl_assert(symtab && "Symtab is required.");
417919742fa8a24a869172e6cb6ac09301cbf753532Logan Chien
418a13b6909c66260aabbcd32b6519d05e469881141TDYa  for (size_t i = 0; i < reltab->size(); ++i) {
419a13b6909c66260aabbcd32b6519d05e469881141TDYa    // FIXME: Can not implement here, use Fixup!
420a13b6909c66260aabbcd32b6519d05e469881141TDYa    ELFRelocTy *rel = (*reltab)[i];
421a13b6909c66260aabbcd32b6519d05e469881141TDYa    ELFSymbolTy *sym = (*symtab)[rel->getSymTabIndex()];
422919742fa8a24a869172e6cb6ac09301cbf753532Logan Chien
423a13b6909c66260aabbcd32b6519d05e469881141TDYa    //typedef uint64_t Inst_t;
424a13b6909c66260aabbcd32b6519d05e469881141TDYa    typedef int32_t Inst_t;
425a13b6909c66260aabbcd32b6519d05e469881141TDYa    Inst_t *inst = (Inst_t *)&(*text)[rel->getOffset()];
426a13b6909c66260aabbcd32b6519d05e469881141TDYa    Inst_t P = (Inst_t)(uintptr_t)inst;
427a13b6909c66260aabbcd32b6519d05e469881141TDYa    Inst_t A = (Inst_t)(uintptr_t)*inst;
4289ed73923af9db7283a8c76b5dfa2dda5b732a852Andrew Hsieh    Inst_t S = (Inst_t)(uintptr_t)sym->getAddress(EM_386);
429919742fa8a24a869172e6cb6ac09301cbf753532Logan Chien
430a13b6909c66260aabbcd32b6519d05e469881141TDYa    if (S == 0) {
431a13b6909c66260aabbcd32b6519d05e469881141TDYa      S = (Inst_t)(uintptr_t)find_sym(context, sym->getName());
43250b814ae8797a929bc0416d6a97e3551b24eaf30Stephen Hines      if (!S) {
43350b814ae8797a929bc0416d6a97e3551b24eaf30Stephen Hines        missingSymbols = true;
43450b814ae8797a929bc0416d6a97e3551b24eaf30Stephen Hines      }
435a13b6909c66260aabbcd32b6519d05e469881141TDYa      sym->setAddress((void *)S);
436a13b6909c66260aabbcd32b6519d05e469881141TDYa    }
437919742fa8a24a869172e6cb6ac09301cbf753532Logan Chien
438a13b6909c66260aabbcd32b6519d05e469881141TDYa    switch (rel->getType()) {
439a13b6909c66260aabbcd32b6519d05e469881141TDYa    default:
440a13b6909c66260aabbcd32b6519d05e469881141TDYa      rsl_assert(0 && "Not implemented relocation type.");
441a13b6909c66260aabbcd32b6519d05e469881141TDYa      break;
442919742fa8a24a869172e6cb6ac09301cbf753532Logan Chien
443a13b6909c66260aabbcd32b6519d05e469881141TDYa    case R_386_PC32:
444a13b6909c66260aabbcd32b6519d05e469881141TDYa      *inst = (S+A-P);
445a13b6909c66260aabbcd32b6519d05e469881141TDYa      break;
446a13b6909c66260aabbcd32b6519d05e469881141TDYa
447a13b6909c66260aabbcd32b6519d05e469881141TDYa    case R_386_32:
448a13b6909c66260aabbcd32b6519d05e469881141TDYa      *inst = (S+A);
449a13b6909c66260aabbcd32b6519d05e469881141TDYa      break;
450919742fa8a24a869172e6cb6ac09301cbf753532Logan Chien    }
451919742fa8a24a869172e6cb6ac09301cbf753532Logan Chien  }
452919742fa8a24a869172e6cb6ac09301cbf753532Logan Chien}
453919742fa8a24a869172e6cb6ac09301cbf753532Logan Chien
4542ffd160f255552e33f4b393d3097a3525e204634Shih-wei Liaotemplate <unsigned Bitwidth>
4552ffd160f255552e33f4b393d3097a3525e204634Shih-wei Liaoinline void ELFObject<Bitwidth>::
4562ffd160f255552e33f4b393d3097a3525e204634Shih-wei LiaorelocateMIPS(void *(*find_sym)(void *context, char const *name),
4572ffd160f255552e33f4b393d3097a3525e204634Shih-wei Liao             void *context,
4582ffd160f255552e33f4b393d3097a3525e204634Shih-wei Liao             ELFSectionRelTableTy *reltab,
4592ffd160f255552e33f4b393d3097a3525e204634Shih-wei Liao             ELFSectionProgBitsTy *text) {
4602ffd160f255552e33f4b393d3097a3525e204634Shih-wei Liao  rsl_assert(Bitwidth == 32 && "Only support 32-bit MIPS.");
4612ffd160f255552e33f4b393d3097a3525e204634Shih-wei Liao
4622ffd160f255552e33f4b393d3097a3525e204634Shih-wei Liao  ELFSectionSymTabTy *symtab =
4632ffd160f255552e33f4b393d3097a3525e204634Shih-wei Liao    static_cast<ELFSectionSymTabTy *>(getSectionByName(".symtab"));
4642ffd160f255552e33f4b393d3097a3525e204634Shih-wei Liao  rsl_assert(symtab && "Symtab is required.");
4652ffd160f255552e33f4b393d3097a3525e204634Shih-wei Liao
4662ffd160f255552e33f4b393d3097a3525e204634Shih-wei Liao  for (size_t i = 0; i < reltab->size(); ++i) {
4672ffd160f255552e33f4b393d3097a3525e204634Shih-wei Liao    // FIXME: Can not implement here, use Fixup!
4682ffd160f255552e33f4b393d3097a3525e204634Shih-wei Liao    ELFRelocTy *rel = (*reltab)[i];
4692ffd160f255552e33f4b393d3097a3525e204634Shih-wei Liao    ELFSymbolTy *sym = (*symtab)[rel->getSymTabIndex()];
4702ffd160f255552e33f4b393d3097a3525e204634Shih-wei Liao
4712ffd160f255552e33f4b393d3097a3525e204634Shih-wei Liao    typedef int32_t Inst_t;
4722ffd160f255552e33f4b393d3097a3525e204634Shih-wei Liao    Inst_t *inst = (Inst_t *)&(*text)[rel->getOffset()];
4732ffd160f255552e33f4b393d3097a3525e204634Shih-wei Liao    Inst_t P = (Inst_t)(uintptr_t)inst;
4742ffd160f255552e33f4b393d3097a3525e204634Shih-wei Liao    Inst_t A = (Inst_t)(uintptr_t)*inst;
4759ed73923af9db7283a8c76b5dfa2dda5b732a852Andrew Hsieh    Inst_t S = (Inst_t)(uintptr_t)sym->getAddress(EM_MIPS);
4762ffd160f255552e33f4b393d3097a3525e204634Shih-wei Liao
4770a2be45c942a83bb70a7cf1b7355db73cd30f9b9Chao-ying Fu    bool need_stub = false;
4780a2be45c942a83bb70a7cf1b7355db73cd30f9b9Chao-ying Fu
4790a2be45c942a83bb70a7cf1b7355db73cd30f9b9Chao-ying Fu    if (S == 0 && strcmp (sym->getName(), "_gp_disp") != 0) {
4800a2be45c942a83bb70a7cf1b7355db73cd30f9b9Chao-ying Fu      need_stub = true;
4812ffd160f255552e33f4b393d3097a3525e204634Shih-wei Liao      S = (Inst_t)(uintptr_t)find_sym(context, sym->getName());
48250b814ae8797a929bc0416d6a97e3551b24eaf30Stephen Hines      if (!S) {
48350b814ae8797a929bc0416d6a97e3551b24eaf30Stephen Hines        missingSymbols = true;
48450b814ae8797a929bc0416d6a97e3551b24eaf30Stephen Hines      }
4852ffd160f255552e33f4b393d3097a3525e204634Shih-wei Liao      sym->setAddress((void *)S);
4862ffd160f255552e33f4b393d3097a3525e204634Shih-wei Liao    }
4872ffd160f255552e33f4b393d3097a3525e204634Shih-wei Liao
4882ffd160f255552e33f4b393d3097a3525e204634Shih-wei Liao    switch (rel->getType()) {
4892ffd160f255552e33f4b393d3097a3525e204634Shih-wei Liao    default:
4902ffd160f255552e33f4b393d3097a3525e204634Shih-wei Liao      rsl_assert(0 && "Not implemented relocation type.");
4912ffd160f255552e33f4b393d3097a3525e204634Shih-wei Liao      break;
4922ffd160f255552e33f4b393d3097a3525e204634Shih-wei Liao
4930a2be45c942a83bb70a7cf1b7355db73cd30f9b9Chao-ying Fu    case R_MIPS_NONE:
4940a2be45c942a83bb70a7cf1b7355db73cd30f9b9Chao-ying Fu    case R_MIPS_JALR: // ignore this
4950a2be45c942a83bb70a7cf1b7355db73cd30f9b9Chao-ying Fu      break;
4960a2be45c942a83bb70a7cf1b7355db73cd30f9b9Chao-ying Fu
4970a2be45c942a83bb70a7cf1b7355db73cd30f9b9Chao-ying Fu    case R_MIPS_16:
4980a2be45c942a83bb70a7cf1b7355db73cd30f9b9Chao-ying Fu      *inst &= 0xFFFF0000;
4990a2be45c942a83bb70a7cf1b7355db73cd30f9b9Chao-ying Fu      A = A & 0xFFFF;
5000a2be45c942a83bb70a7cf1b7355db73cd30f9b9Chao-ying Fu      A = S + (short)A;
5010a2be45c942a83bb70a7cf1b7355db73cd30f9b9Chao-ying Fu      rsl_assert(A >= -32768 && A <= 32767 && "R_MIPS_16 overflow.");
5020a2be45c942a83bb70a7cf1b7355db73cd30f9b9Chao-ying Fu      *inst |= (A & 0xFFFF);
5030a2be45c942a83bb70a7cf1b7355db73cd30f9b9Chao-ying Fu      break;
5040a2be45c942a83bb70a7cf1b7355db73cd30f9b9Chao-ying Fu
5050a2be45c942a83bb70a7cf1b7355db73cd30f9b9Chao-ying Fu    case R_MIPS_32:
5060a2be45c942a83bb70a7cf1b7355db73cd30f9b9Chao-ying Fu      *inst = S + A;
5070a2be45c942a83bb70a7cf1b7355db73cd30f9b9Chao-ying Fu      break;
5080a2be45c942a83bb70a7cf1b7355db73cd30f9b9Chao-ying Fu
5090a2be45c942a83bb70a7cf1b7355db73cd30f9b9Chao-ying Fu    case R_MIPS_26:
5100a2be45c942a83bb70a7cf1b7355db73cd30f9b9Chao-ying Fu      *inst &= 0xFC000000;
5110a2be45c942a83bb70a7cf1b7355db73cd30f9b9Chao-ying Fu      if (need_stub == false) {
5120a2be45c942a83bb70a7cf1b7355db73cd30f9b9Chao-ying Fu        A = (A & 0x3FFFFFF) << 2;
5130a2be45c942a83bb70a7cf1b7355db73cd30f9b9Chao-ying Fu        if (sym->getBindingAttribute() == STB_LOCAL) { // local binding
5140a2be45c942a83bb70a7cf1b7355db73cd30f9b9Chao-ying Fu          A |= ((P + 4) & 0xF0000000);
5150a2be45c942a83bb70a7cf1b7355db73cd30f9b9Chao-ying Fu          A += S;
5160a2be45c942a83bb70a7cf1b7355db73cd30f9b9Chao-ying Fu          *inst |= ((A >> 2) & 0x3FFFFFF);
51756ca447beb2f9d893d9c3dbee5c46090e929529bShih-wei Liao        } else { // external binding
5180a2be45c942a83bb70a7cf1b7355db73cd30f9b9Chao-ying Fu          if (A & 0x08000000) // Sign extend from bit 27
5190a2be45c942a83bb70a7cf1b7355db73cd30f9b9Chao-ying Fu            A |= 0xF0000000;
5200a2be45c942a83bb70a7cf1b7355db73cd30f9b9Chao-ying Fu          A += S;
5210a2be45c942a83bb70a7cf1b7355db73cd30f9b9Chao-ying Fu          *inst |= ((A >> 2) & 0x3FFFFFF);
5220a2be45c942a83bb70a7cf1b7355db73cd30f9b9Chao-ying Fu          if (((P + 4) >> 28) != (A >> 28)) { // far local call
5230a2be45c942a83bb70a7cf1b7355db73cd30f9b9Chao-ying Fu            void *stub = text->getStubLayout()->allocateStub((void *)A);
5240a2be45c942a83bb70a7cf1b7355db73cd30f9b9Chao-ying Fu            rsl_assert(stub && "cannot allocate stub.");
5250a2be45c942a83bb70a7cf1b7355db73cd30f9b9Chao-ying Fu            sym->setAddress(stub);
5268d2a1230eae323981b4f6e03406e801a51018432Logan Chien            S = (int32_t)(intptr_t)stub;
5270a2be45c942a83bb70a7cf1b7355db73cd30f9b9Chao-ying Fu            *inst |= ((S >> 2) & 0x3FFFFFF);
5280a2be45c942a83bb70a7cf1b7355db73cd30f9b9Chao-ying Fu            rsl_assert(((P + 4) >> 28) == (S >> 28) && "stub is too far.");
5290a2be45c942a83bb70a7cf1b7355db73cd30f9b9Chao-ying Fu          }
5300a2be45c942a83bb70a7cf1b7355db73cd30f9b9Chao-ying Fu        }
53156ca447beb2f9d893d9c3dbee5c46090e929529bShih-wei Liao      } else { // shared-library call
5320a2be45c942a83bb70a7cf1b7355db73cd30f9b9Chao-ying Fu        A = (A & 0x3FFFFFF) << 2;
5330a2be45c942a83bb70a7cf1b7355db73cd30f9b9Chao-ying Fu        rsl_assert(A == 0 && "R_MIPS_26 addend is not zero.");
5340a2be45c942a83bb70a7cf1b7355db73cd30f9b9Chao-ying Fu        void *stub = text->getStubLayout()->allocateStub((void *)S);
5350a2be45c942a83bb70a7cf1b7355db73cd30f9b9Chao-ying Fu        rsl_assert(stub && "cannot allocate stub.");
5360a2be45c942a83bb70a7cf1b7355db73cd30f9b9Chao-ying Fu        sym->setAddress(stub);
5378d2a1230eae323981b4f6e03406e801a51018432Logan Chien        S = (int32_t)(intptr_t)stub;
5380a2be45c942a83bb70a7cf1b7355db73cd30f9b9Chao-ying Fu        *inst |= ((S >> 2) & 0x3FFFFFF);
5390a2be45c942a83bb70a7cf1b7355db73cd30f9b9Chao-ying Fu        rsl_assert(((P + 4) >> 28) == (S >> 28) && "stub is too far.");
5400a2be45c942a83bb70a7cf1b7355db73cd30f9b9Chao-ying Fu      }
5410a2be45c942a83bb70a7cf1b7355db73cd30f9b9Chao-ying Fu      break;
5420a2be45c942a83bb70a7cf1b7355db73cd30f9b9Chao-ying Fu
5432ffd160f255552e33f4b393d3097a3525e204634Shih-wei Liao    case R_MIPS_HI16:
5440a2be45c942a83bb70a7cf1b7355db73cd30f9b9Chao-ying Fu      *inst &= 0xFFFF0000;
5454584cb1a038895f1a9a144bbdb293613373b24adChao-ying Fu      A = (A & 0xFFFF) << 16;
5464584cb1a038895f1a9a144bbdb293613373b24adChao-ying Fu      // Find the nearest LO16 relocation type after this entry
5474584cb1a038895f1a9a144bbdb293613373b24adChao-ying Fu      for (size_t j = i + 1; j < reltab->size(); j++) {
5484584cb1a038895f1a9a144bbdb293613373b24adChao-ying Fu        ELFRelocTy *this_rel = (*reltab)[j];
5494584cb1a038895f1a9a144bbdb293613373b24adChao-ying Fu        ELFSymbolTy *this_sym = (*symtab)[this_rel->getSymTabIndex()];
5504584cb1a038895f1a9a144bbdb293613373b24adChao-ying Fu        if (this_rel->getType() == R_MIPS_LO16 && this_sym == sym) {
5514584cb1a038895f1a9a144bbdb293613373b24adChao-ying Fu          Inst_t *this_inst = (Inst_t *)&(*text)[this_rel->getOffset()];
5524584cb1a038895f1a9a144bbdb293613373b24adChao-ying Fu          Inst_t this_A = (Inst_t)(uintptr_t)*this_inst;
5534584cb1a038895f1a9a144bbdb293613373b24adChao-ying Fu          this_A = this_A & 0xFFFF;
5544584cb1a038895f1a9a144bbdb293613373b24adChao-ying Fu          A += (short)this_A;
5554584cb1a038895f1a9a144bbdb293613373b24adChao-ying Fu          break;
5564584cb1a038895f1a9a144bbdb293613373b24adChao-ying Fu        }
5574584cb1a038895f1a9a144bbdb293613373b24adChao-ying Fu      }
5580a2be45c942a83bb70a7cf1b7355db73cd30f9b9Chao-ying Fu      if (strcmp (sym->getName(), "_gp_disp") == 0) {
5598d2a1230eae323981b4f6e03406e801a51018432Logan Chien          S = (int)(intptr_t)got_address() + GP_OFFSET - (int)P;
5600a2be45c942a83bb70a7cf1b7355db73cd30f9b9Chao-ying Fu          sym->setAddress((void *)S);
5610a2be45c942a83bb70a7cf1b7355db73cd30f9b9Chao-ying Fu      }
5624584cb1a038895f1a9a144bbdb293613373b24adChao-ying Fu      *inst |= (((S + A + (int)0x8000) >> 16) & 0xFFFF);
5632ffd160f255552e33f4b393d3097a3525e204634Shih-wei Liao      break;
5642ffd160f255552e33f4b393d3097a3525e204634Shih-wei Liao
5652ffd160f255552e33f4b393d3097a3525e204634Shih-wei Liao    case R_MIPS_LO16:
5660a2be45c942a83bb70a7cf1b7355db73cd30f9b9Chao-ying Fu      *inst &= 0xFFFF0000;
5672ffd160f255552e33f4b393d3097a3525e204634Shih-wei Liao      A = A & 0xFFFF;
5680a2be45c942a83bb70a7cf1b7355db73cd30f9b9Chao-ying Fu      if (strcmp (sym->getName(), "_gp_disp") == 0) {
5698d2a1230eae323981b4f6e03406e801a51018432Logan Chien          S = (Inst_t)(intptr_t)sym->getAddress(EM_MIPS);
5700a2be45c942a83bb70a7cf1b7355db73cd30f9b9Chao-ying Fu      }
5710a2be45c942a83bb70a7cf1b7355db73cd30f9b9Chao-ying Fu      *inst |= ((S + A) & 0xFFFF);
5722ffd160f255552e33f4b393d3097a3525e204634Shih-wei Liao      break;
5732ffd160f255552e33f4b393d3097a3525e204634Shih-wei Liao
5740a2be45c942a83bb70a7cf1b7355db73cd30f9b9Chao-ying Fu    case R_MIPS_GOT16:
5750a2be45c942a83bb70a7cf1b7355db73cd30f9b9Chao-ying Fu    case R_MIPS_CALL16:
5760a2be45c942a83bb70a7cf1b7355db73cd30f9b9Chao-ying Fu      {
5770a2be45c942a83bb70a7cf1b7355db73cd30f9b9Chao-ying Fu        *inst &= 0xFFFF0000;
5780a2be45c942a83bb70a7cf1b7355db73cd30f9b9Chao-ying Fu        A = A & 0xFFFF;
5794584cb1a038895f1a9a144bbdb293613373b24adChao-ying Fu        if (rel->getType() == R_MIPS_GOT16) {
5804584cb1a038895f1a9a144bbdb293613373b24adChao-ying Fu          if (sym->getBindingAttribute() == STB_LOCAL) {
5814584cb1a038895f1a9a144bbdb293613373b24adChao-ying Fu            A <<= 16;
5824584cb1a038895f1a9a144bbdb293613373b24adChao-ying Fu
5834584cb1a038895f1a9a144bbdb293613373b24adChao-ying Fu            // Find the nearest LO16 relocation type after this entry
5844584cb1a038895f1a9a144bbdb293613373b24adChao-ying Fu            for (size_t j = i + 1; j < reltab->size(); j++) {
5854584cb1a038895f1a9a144bbdb293613373b24adChao-ying Fu              ELFRelocTy *this_rel = (*reltab)[j];
5864584cb1a038895f1a9a144bbdb293613373b24adChao-ying Fu              ELFSymbolTy *this_sym = (*symtab)[this_rel->getSymTabIndex()];
5874584cb1a038895f1a9a144bbdb293613373b24adChao-ying Fu              if (this_rel->getType() == R_MIPS_LO16 && this_sym == sym) {
5884584cb1a038895f1a9a144bbdb293613373b24adChao-ying Fu                Inst_t *this_inst = (Inst_t *)&(*text)[this_rel->getOffset()];
5894584cb1a038895f1a9a144bbdb293613373b24adChao-ying Fu                Inst_t this_A = (Inst_t)(uintptr_t)*this_inst;
5904584cb1a038895f1a9a144bbdb293613373b24adChao-ying Fu                this_A = this_A & 0xFFFF;
5914584cb1a038895f1a9a144bbdb293613373b24adChao-ying Fu                A += (short)this_A;
5924584cb1a038895f1a9a144bbdb293613373b24adChao-ying Fu                break;
5934584cb1a038895f1a9a144bbdb293613373b24adChao-ying Fu              }
5944584cb1a038895f1a9a144bbdb293613373b24adChao-ying Fu            }
59556ca447beb2f9d893d9c3dbee5c46090e929529bShih-wei Liao          } else {
5964584cb1a038895f1a9a144bbdb293613373b24adChao-ying Fu            rsl_assert(A == 0 && "R_MIPS_GOT16 addend is not 0.");
5974584cb1a038895f1a9a144bbdb293613373b24adChao-ying Fu          }
59856ca447beb2f9d893d9c3dbee5c46090e929529bShih-wei Liao        } else { // R_MIPS_CALL16
5994584cb1a038895f1a9a144bbdb293613373b24adChao-ying Fu          rsl_assert(A == 0 && "R_MIPS_CALL16 addend is not 0.");
6004584cb1a038895f1a9a144bbdb293613373b24adChao-ying Fu        }
6014584cb1a038895f1a9a144bbdb293613373b24adChao-ying Fu        int got_index = search_got((int)rel->getSymTabIndex(), (void *)(S + A),
6020a2be45c942a83bb70a7cf1b7355db73cd30f9b9Chao-ying Fu                                   sym->getBindingAttribute());
6030a2be45c942a83bb70a7cf1b7355db73cd30f9b9Chao-ying Fu        int got_offset = (got_index << 2) - GP_OFFSET;
6040a2be45c942a83bb70a7cf1b7355db73cd30f9b9Chao-ying Fu        *inst |= (got_offset & 0xFFFF);
6050a2be45c942a83bb70a7cf1b7355db73cd30f9b9Chao-ying Fu      }
6062ffd160f255552e33f4b393d3097a3525e204634Shih-wei Liao      break;
6072ffd160f255552e33f4b393d3097a3525e204634Shih-wei Liao
6080a2be45c942a83bb70a7cf1b7355db73cd30f9b9Chao-ying Fu    case R_MIPS_GPREL32:
6098d2a1230eae323981b4f6e03406e801a51018432Logan Chien      *inst = A + S - ((int)(intptr_t)got_address() + GP_OFFSET);
6102ffd160f255552e33f4b393d3097a3525e204634Shih-wei Liao      break;
6112ffd160f255552e33f4b393d3097a3525e204634Shih-wei Liao    }
6122ffd160f255552e33f4b393d3097a3525e204634Shih-wei Liao  }
6132ffd160f255552e33f4b393d3097a3525e204634Shih-wei Liao}
6142ffd160f255552e33f4b393d3097a3525e204634Shih-wei Liao
6152ffd160f255552e33f4b393d3097a3525e204634Shih-wei Liao
616768a6e8961ae16a5bcf6cab2b21405306b259a0bShih-wei Liao// TODO: Refactor all relocations.
617919742fa8a24a869172e6cb6ac09301cbf753532Logan Chientemplate <unsigned Bitwidth>
618919742fa8a24a869172e6cb6ac09301cbf753532Logan Chieninline void ELFObject<Bitwidth>::
6194e4356b34f9751070ac8ccb1bb74bb44e9232661Logan Chienrelocate(void *(*find_sym)(void *context, char const *name), void *context) {
620768a6e8961ae16a5bcf6cab2b21405306b259a0bShih-wei Liao  // Init SHNCommonDataSize.
621768a6e8961ae16a5bcf6cab2b21405306b259a0bShih-wei Liao  // Need refactoring
622768a6e8961ae16a5bcf6cab2b21405306b259a0bShih-wei Liao  size_t SHNCommonDataSize = 0;
623768a6e8961ae16a5bcf6cab2b21405306b259a0bShih-wei Liao
624768a6e8961ae16a5bcf6cab2b21405306b259a0bShih-wei Liao  ELFSectionSymTabTy *symtab =
625768a6e8961ae16a5bcf6cab2b21405306b259a0bShih-wei Liao    static_cast<ELFSectionSymTabTy *>(getSectionByName(".symtab"));
626768a6e8961ae16a5bcf6cab2b21405306b259a0bShih-wei Liao  rsl_assert(symtab && "Symtab is required.");
627768a6e8961ae16a5bcf6cab2b21405306b259a0bShih-wei Liao
628768a6e8961ae16a5bcf6cab2b21405306b259a0bShih-wei Liao  for (size_t i = 0; i < symtab->size(); ++i) {
629768a6e8961ae16a5bcf6cab2b21405306b259a0bShih-wei Liao    ELFSymbolTy *sym = (*symtab)[i];
630768a6e8961ae16a5bcf6cab2b21405306b259a0bShih-wei Liao
631768a6e8961ae16a5bcf6cab2b21405306b259a0bShih-wei Liao    if (sym->getType() != STT_OBJECT) {
632768a6e8961ae16a5bcf6cab2b21405306b259a0bShih-wei Liao      continue;
633768a6e8961ae16a5bcf6cab2b21405306b259a0bShih-wei Liao    }
634768a6e8961ae16a5bcf6cab2b21405306b259a0bShih-wei Liao
635768a6e8961ae16a5bcf6cab2b21405306b259a0bShih-wei Liao    size_t idx = (size_t)sym->getSectionIndex();
636768a6e8961ae16a5bcf6cab2b21405306b259a0bShih-wei Liao    switch (idx) {
637768a6e8961ae16a5bcf6cab2b21405306b259a0bShih-wei Liao    default:
638768a6e8961ae16a5bcf6cab2b21405306b259a0bShih-wei Liao      if ((*shtab)[idx]->getType() == SHT_NOBITS) {
639768a6e8961ae16a5bcf6cab2b21405306b259a0bShih-wei Liao        // FIXME(logan): This is a workaround for .lcomm directives
640768a6e8961ae16a5bcf6cab2b21405306b259a0bShih-wei Liao        // bug of LLVM ARM MC code generator.  Remove this when the
641768a6e8961ae16a5bcf6cab2b21405306b259a0bShih-wei Liao        // LLVM bug is fixed.
642768a6e8961ae16a5bcf6cab2b21405306b259a0bShih-wei Liao
643768a6e8961ae16a5bcf6cab2b21405306b259a0bShih-wei Liao        size_t align = 16;
644768a6e8961ae16a5bcf6cab2b21405306b259a0bShih-wei Liao        SHNCommonDataSize += (size_t)sym->getSize() + align;
645768a6e8961ae16a5bcf6cab2b21405306b259a0bShih-wei Liao      }
646768a6e8961ae16a5bcf6cab2b21405306b259a0bShih-wei Liao      break;
647768a6e8961ae16a5bcf6cab2b21405306b259a0bShih-wei Liao
648768a6e8961ae16a5bcf6cab2b21405306b259a0bShih-wei Liao    case SHN_COMMON:
649768a6e8961ae16a5bcf6cab2b21405306b259a0bShih-wei Liao      {
650b1a853b0e8639be08bc06594e092f3697c1ddd06Shih-wei Liao        size_t align = (size_t)sym->getValue();
651768a6e8961ae16a5bcf6cab2b21405306b259a0bShih-wei Liao        SHNCommonDataSize += (size_t)sym->getSize() + align;
652768a6e8961ae16a5bcf6cab2b21405306b259a0bShih-wei Liao      }
653768a6e8961ae16a5bcf6cab2b21405306b259a0bShih-wei Liao      break;
654768a6e8961ae16a5bcf6cab2b21405306b259a0bShih-wei Liao
655768a6e8961ae16a5bcf6cab2b21405306b259a0bShih-wei Liao    case SHN_ABS:
656768a6e8961ae16a5bcf6cab2b21405306b259a0bShih-wei Liao    case SHN_UNDEF:
657768a6e8961ae16a5bcf6cab2b21405306b259a0bShih-wei Liao    case SHN_XINDEX:
658768a6e8961ae16a5bcf6cab2b21405306b259a0bShih-wei Liao      break;
659768a6e8961ae16a5bcf6cab2b21405306b259a0bShih-wei Liao    }
660768a6e8961ae16a5bcf6cab2b21405306b259a0bShih-wei Liao  }
661768a6e8961ae16a5bcf6cab2b21405306b259a0bShih-wei Liao  if (!initSHNCommonDataSize(SHNCommonDataSize)) {
662768a6e8961ae16a5bcf6cab2b21405306b259a0bShih-wei Liao    rsl_assert("Allocate memory for common variable fail!");
663768a6e8961ae16a5bcf6cab2b21405306b259a0bShih-wei Liao  }
664919742fa8a24a869172e6cb6ac09301cbf753532Logan Chien
665a13b6909c66260aabbcd32b6519d05e469881141TDYa  for (size_t i = 0; i < stab.size(); ++i) {
666a13b6909c66260aabbcd32b6519d05e469881141TDYa    ELFSectionHeaderTy *sh = (*shtab)[i];
667a13b6909c66260aabbcd32b6519d05e469881141TDYa    if (sh->getType() != SHT_REL && sh->getType() != SHT_RELA) {
668a13b6909c66260aabbcd32b6519d05e469881141TDYa      continue;
669a13b6909c66260aabbcd32b6519d05e469881141TDYa    }
670a13b6909c66260aabbcd32b6519d05e469881141TDYa    ELFSectionRelTableTy *reltab =
671a13b6909c66260aabbcd32b6519d05e469881141TDYa      static_cast<ELFSectionRelTableTy *>(stab[i]);
672a13b6909c66260aabbcd32b6519d05e469881141TDYa    rsl_assert(reltab && "Relocation section can't be NULL.");
673a13b6909c66260aabbcd32b6519d05e469881141TDYa
674a13b6909c66260aabbcd32b6519d05e469881141TDYa    const char *reltab_name = sh->getName();
675a13b6909c66260aabbcd32b6519d05e469881141TDYa    const char *need_rel_name;
676a13b6909c66260aabbcd32b6519d05e469881141TDYa    if (sh->getType() == SHT_REL) {
677a13b6909c66260aabbcd32b6519d05e469881141TDYa      need_rel_name = reltab_name + 4;
678a13b6909c66260aabbcd32b6519d05e469881141TDYa      // ".rel.xxxx"
679a13b6909c66260aabbcd32b6519d05e469881141TDYa      //      ^ start from here.
680a13b6909c66260aabbcd32b6519d05e469881141TDYa    } else {
681a13b6909c66260aabbcd32b6519d05e469881141TDYa      need_rel_name = reltab_name + 5;
682a13b6909c66260aabbcd32b6519d05e469881141TDYa    }
683a13b6909c66260aabbcd32b6519d05e469881141TDYa
684a13b6909c66260aabbcd32b6519d05e469881141TDYa    ELFSectionProgBitsTy *need_rel =
685a13b6909c66260aabbcd32b6519d05e469881141TDYa      static_cast<ELFSectionProgBitsTy *>(getSectionByName(need_rel_name));
686a13b6909c66260aabbcd32b6519d05e469881141TDYa    rsl_assert(need_rel && "Need be relocated section can't be NULL.");
687a13b6909c66260aabbcd32b6519d05e469881141TDYa
688a13b6909c66260aabbcd32b6519d05e469881141TDYa    switch (getHeader()->getMachine()) {
689a13b6909c66260aabbcd32b6519d05e469881141TDYa      case EM_ARM:
690a13b6909c66260aabbcd32b6519d05e469881141TDYa        relocateARM(find_sym, context, reltab, need_rel);
691a13b6909c66260aabbcd32b6519d05e469881141TDYa        break;
692a13b6909c66260aabbcd32b6519d05e469881141TDYa      case EM_386:
693a13b6909c66260aabbcd32b6519d05e469881141TDYa        relocateX86_32(find_sym, context, reltab, need_rel);
694a13b6909c66260aabbcd32b6519d05e469881141TDYa        break;
695a13b6909c66260aabbcd32b6519d05e469881141TDYa      case EM_X86_64:
696a13b6909c66260aabbcd32b6519d05e469881141TDYa        relocateX86_64(find_sym, context, reltab, need_rel);
697a13b6909c66260aabbcd32b6519d05e469881141TDYa        break;
6982ffd160f255552e33f4b393d3097a3525e204634Shih-wei Liao      case EM_MIPS:
6992ffd160f255552e33f4b393d3097a3525e204634Shih-wei Liao        relocateMIPS(find_sym, context, reltab, need_rel);
7002ffd160f255552e33f4b393d3097a3525e204634Shih-wei Liao        break;
701a13b6909c66260aabbcd32b6519d05e469881141TDYa
702a13b6909c66260aabbcd32b6519d05e469881141TDYa      default:
7032ffd160f255552e33f4b393d3097a3525e204634Shih-wei Liao        rsl_assert(0 && "Only support ARM, MIPS, X86, and X86_64 relocation.");
704a13b6909c66260aabbcd32b6519d05e469881141TDYa        break;
705a13b6909c66260aabbcd32b6519d05e469881141TDYa    }
706919742fa8a24a869172e6cb6ac09301cbf753532Logan Chien  }
707919742fa8a24a869172e6cb6ac09301cbf753532Logan Chien
708919742fa8a24a869172e6cb6ac09301cbf753532Logan Chien  for (size_t i = 0; i < stab.size(); ++i) {
70958611fc8193e7386698178f167a2e0cbdd6a4f6fLogan Chien    ELFSectionHeaderTy *sh = (*shtab)[i];
7102061b057e0922ac33b9314c1ccaa50eb7286b847Logan Chien    if (sh->getType() == SHT_PROGBITS || sh->getType() == SHT_NOBITS) {
7112061b057e0922ac33b9314c1ccaa50eb7286b847Logan Chien      if (stab[i]) {
7122061b057e0922ac33b9314c1ccaa50eb7286b847Logan Chien        static_cast<ELFSectionBitsTy *>(stab[i])->protect();
7132061b057e0922ac33b9314c1ccaa50eb7286b847Logan Chien      }
714919742fa8a24a869172e6cb6ac09301cbf753532Logan Chien    }
715919742fa8a24a869172e6cb6ac09301cbf753532Logan Chien  }
716919742fa8a24a869172e6cb6ac09301cbf753532Logan Chien}
717919742fa8a24a869172e6cb6ac09301cbf753532Logan Chien
718919742fa8a24a869172e6cb6ac09301cbf753532Logan Chientemplate <unsigned Bitwidth>
719919742fa8a24a869172e6cb6ac09301cbf753532Logan Chieninline void ELFObject<Bitwidth>::print() const {
720919742fa8a24a869172e6cb6ac09301cbf753532Logan Chien  header->print();
721919742fa8a24a869172e6cb6ac09301cbf753532Logan Chien  shtab->print();
722919742fa8a24a869172e6cb6ac09301cbf753532Logan Chien
723919742fa8a24a869172e6cb6ac09301cbf753532Logan Chien  for (size_t i = 0; i < stab.size(); ++i) {
72458611fc8193e7386698178f167a2e0cbdd6a4f6fLogan Chien    ELFSectionTy *sec = stab[i];
725919742fa8a24a869172e6cb6ac09301cbf753532Logan Chien    if (sec) {
726919742fa8a24a869172e6cb6ac09301cbf753532Logan Chien      sec->print();
727919742fa8a24a869172e6cb6ac09301cbf753532Logan Chien    }
728919742fa8a24a869172e6cb6ac09301cbf753532Logan Chien  }
729919742fa8a24a869172e6cb6ac09301cbf753532Logan Chien}
730919742fa8a24a869172e6cb6ac09301cbf753532Logan Chien
731919742fa8a24a869172e6cb6ac09301cbf753532Logan Chien#endif // ELF_OBJECT_HXX
732