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