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