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