ELFObject.hxx revision ee6cdb95525abc8c7766798148302306a100b774
1/* 2 * Copyright 2011, The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#ifndef ELF_OBJECT_HXX 18#define ELF_OBJECT_HXX 19 20#include "ELFHeader.h" 21#include "ELFReloc.h" 22#include "ELFSection.h" 23#include "ELFSectionHeaderTable.h" 24#include "StubLayout.h" 25 26#include <llvm/ADT/SmallVector.h> 27 28#include "utils/rsl_assert.h" 29#include <elf.h> 30 31template <unsigned Bitwidth> 32template <typename Archiver> 33inline ELFObject<Bitwidth> * 34ELFObject<Bitwidth>::read(Archiver &AR) { 35 llvm::OwningPtr<ELFObjectTy> object(new ELFObjectTy()); 36 37 // Read header 38 object->header.reset(ELFHeaderTy::read(AR)); 39 if (!object->header) { 40 return 0; 41 } 42 43 // Read section table 44 object->shtab.reset(ELFSectionHeaderTableTy::read(AR, object.get())); 45 if (!object->shtab) { 46 return 0; 47 } 48 49 // Read each section 50 llvm::SmallVector<size_t, 4> progbits_ndx; 51 for (size_t i = 0; i < object->header->getSectionHeaderNum(); ++i) { 52 if ((*object->shtab)[i]->getType() == SHT_PROGBITS) { 53 object->stab.push_back(NULL); 54 progbits_ndx.push_back(i); 55 } else { 56 llvm::OwningPtr<ELFSectionTy> sec( 57 ELFSectionTy::read(AR, object.get(), (*object->shtab)[i])); 58 object->stab.push_back(sec.take()); 59 } 60 } 61 62 for (size_t i = 0; i < progbits_ndx.size(); ++i) { 63 size_t index = progbits_ndx[i]; 64 65 llvm::OwningPtr<ELFSectionTy> sec( 66 ELFSectionTy::read(AR, object.get(), (*object->shtab)[index])); 67 object->stab[index] = sec.take(); 68 } 69 70 return object.take(); 71} 72 73template <unsigned Bitwidth> 74inline char const *ELFObject<Bitwidth>::getSectionName(size_t i) const { 75 ELFSectionTy const *sec = stab[header->getStringSectionIndex()]; 76 77 if (sec) { 78 ELFSectionStrTabTy const &st = 79 static_cast<ELFSectionStrTabTy const &>(*sec); 80 return st[i]; 81 } 82 83 return NULL; 84} 85 86template <unsigned Bitwidth> 87inline ELFSection<Bitwidth> const * 88ELFObject<Bitwidth>::getSectionByIndex(size_t i) const { 89 return stab[i]; 90} 91 92template <unsigned Bitwidth> 93inline ELFSection<Bitwidth> * 94ELFObject<Bitwidth>::getSectionByIndex(size_t i) { 95 return stab[i]; 96} 97 98template <unsigned Bitwidth> 99inline ELFSection<Bitwidth> const * 100ELFObject<Bitwidth>::getSectionByName(std::string const &str) const { 101 size_t idx = getSectionHeaderTable()->getByName(str)->getIndex(); 102 return stab[idx]; 103} 104 105template <unsigned Bitwidth> 106inline ELFSection<Bitwidth> * 107ELFObject<Bitwidth>::getSectionByName(std::string const &str) { 108 ELFObjectTy const *const_this = this; 109 ELFSectionTy const *sptr = const_this->getSectionByName(str); 110 // Const cast for the same API's const and non-const versions. 111 return const_cast<ELFSectionTy *>(sptr); 112} 113 114 115template <unsigned Bitwidth> 116inline void ELFObject<Bitwidth>:: 117relocateARM(void *(*find_sym)(void *context, char const *name), 118 void *context, 119 ELFSectionRelTableTy *reltab, 120 ELFSectionProgBitsTy *text) { 121 // FIXME: Should be implement in independent files. 122 rsl_assert(Bitwidth == 32 && "ARM only have 32 bits."); 123 124 ELFSectionSymTabTy *symtab = 125 static_cast<ELFSectionSymTabTy *>(getSectionByName(".symtab")); 126 127 for (size_t i = 0; i < reltab->size(); ++i) { 128 // FIXME: Can not implement here, use Fixup! 129 ELFRelocTy *rel = (*reltab)[i]; 130 ELFSymbolTy *sym = (*symtab)[rel->getSymTabIndex()]; 131 132 // FIXME: May be not uint32_t *. 133 typedef int32_t Inst_t; 134 Inst_t *inst = (Inst_t *)&(*text)[rel->getOffset()]; 135 Inst_t P = (Inst_t)(int64_t)inst; 136 Inst_t A = 0; 137 Inst_t S = (Inst_t)(int64_t)sym->getAddress(); 138 139 switch (rel->getType()) { 140 default: 141 rsl_assert(0 && "Not implemented relocation type."); 142 break; 143 144 case 2: // R_ARM_ABS32 145 { 146 A = *inst; 147 *inst = (S+A); 148 } 149 break; 150 151 // FIXME: Predefine relocation codes. 152 case 28: // R_ARM_CALL 153 { 154#define SIGN_EXTEND(x, l) (((x)^(1<<((l)-1)))-(1<<(l-1))) 155 A = (Inst_t)(int64_t)SIGN_EXTEND(*inst & 0xFFFFFF, 24); 156#undef SIGN_EXTEND 157 158 switch (sym->getType()) { 159 default: 160 rsl_assert(0 && "Wrong type for R_ARM_CALL relocation."); 161 abort(); 162 break; 163 164 case STT_FUNC: 165 if (S == 0) { 166 rsl_assert(0 && "We should get function address at previous " 167 "sym->getAddress() function call."); 168 abort(); 169 } 170 break; 171 172 case STT_NOTYPE: 173 if (S == 0) { 174 void *ext_func = find_sym(context, sym->getName()); 175 S = (Inst_t)(uintptr_t)ext_func; 176 sym->setAddress(ext_func); 177 178 uint32_t result = (S >> 2) - (P >> 2) + A; 179 if (result > 0x007fffff && result < 0xff800000) { 180#ifndef __arm__ 181 // We have not implement function stub in this runtime env 182 rsl_assert(0 && "Target address is far from call instruction"); 183 abort(); 184#else 185 void *stub = getStubLayout()->allocateStub(ext_func); 186 if (!stub) { 187 llvm::errs() << "unable to allocate stub." << "\n"; 188 exit(EXIT_FAILURE); 189 } 190 191 //out() << "stub: for " << ext_func << " at " << stub << "\n"; 192 sym->setAddress(stub); 193 S = (uint32_t)stub; 194#endif 195 } 196 } 197 break; 198 } 199 200 uint32_t result = (S >> 2) - (P >> 2) + A; 201 202 if (result > 0x007fffff && result < 0xff800000) { 203 rsl_assert(0 && "Stub is still too far"); 204 abort(); 205 } 206 207 *inst = ((result) & 0x00FFFFFF) | (*inst & 0xFF000000); 208 } 209 break; 210 case 44: // R_ARM_MOVT_ABS 211 S >>= 16; 212 case 43: // R_ARM_MOVW_ABS_NC 213 { 214 // No need sign extend. 215 A = ((*inst & 0xF0000) >> 4) | (*inst & 0xFFF); 216 uint32_t result = (S+A); 217 *inst = (((result) & 0xF000) << 4) | 218 ((result) & 0xFFF) | 219 (*inst & 0xFFF0F000); 220 } 221 break; 222 } 223 //llvm::errs() << "S: " << (void *)S << '\n'; 224 //llvm::errs() << "A: " << (void *)A << '\n'; 225 //llvm::errs() << "P: " << (void *)P << '\n'; 226 //llvm::errs() << "S+A: " << (void *)(S+A) << '\n'; 227 //llvm::errs() << "S+A-P: " << (void *)(S+A-P) << '\n'; 228 } 229} 230 231template <unsigned Bitwidth> 232inline void ELFObject<Bitwidth>:: 233relocateX86_64(void *(*find_sym)(void *context, char const *name), 234 void *context, 235 ELFSectionRelTableTy *reltab, 236 ELFSectionProgBitsTy *text) { 237 rsl_assert(Bitwidth == 64 && "Only support X86_64."); 238 239 ELFSectionSymTabTy *symtab = 240 static_cast<ELFSectionSymTabTy *>(getSectionByName(".symtab")); 241 242 for (size_t i = 0; i < reltab->size(); ++i) { 243 // FIXME: Can not implement here, use Fixup! 244 ELFRelocTy *rel = (*reltab)[i]; 245 ELFSymbolTy *sym = (*symtab)[rel->getSymTabIndex()]; 246 247 //typedef uint64_t Inst_t; 248 typedef int32_t Inst_t; 249 Inst_t *inst = (Inst_t *)&(*text)[rel->getOffset()]; 250 Inst_t P = (Inst_t)(int64_t)inst; 251 Inst_t A = (Inst_t)(int64_t)rel->getAddend(); 252 Inst_t S = (Inst_t)(int64_t)sym->getAddress(); 253 254 if (S == 0) { 255 S = (Inst_t)(int64_t)find_sym(context, sym->getName()); 256 sym->setAddress((void *)S); 257 } 258 259 switch (rel->getType()) { 260 default: 261 rsl_assert(0 && "Not implemented relocation type."); 262 break; 263 264 // FIXME: XXX: R_X86_64_64 is 64 bit, there is a big problem here. 265 case 1: // R_X86_64_64 266 *inst = (S+A); 267 break; 268 269 case 2: // R_X86_64_PC32 270 *inst = (S+A-P); 271 break; 272 273 case 10: // R_X86_64_32 274 case 11: // R_X86_64_32S 275 *inst = (S+A); 276 break; 277 } 278 } 279} 280 281template <unsigned Bitwidth> 282inline void ELFObject<Bitwidth>:: 283relocateX86_32(void *(*find_sym)(void *context, char const *name), 284 void *context, 285 ELFSectionRelTableTy *reltab, 286 ELFSectionProgBitsTy *text) { 287 rsl_assert(Bitwidth == 32 && "Only support X86."); 288 289 ELFSectionSymTabTy *symtab = 290 static_cast<ELFSectionSymTabTy *>(getSectionByName(".symtab")); 291 292 for (size_t i = 0; i < reltab->size(); ++i) { 293 // FIXME: Can not implement here, use Fixup! 294 ELFRelocTy *rel = (*reltab)[i]; 295 ELFSymbolTy *sym = (*symtab)[rel->getSymTabIndex()]; 296 297 //typedef uint64_t Inst_t; 298 typedef int32_t Inst_t; 299 Inst_t *inst = (Inst_t *)&(*text)[rel->getOffset()]; 300 Inst_t P = (Inst_t)(uintptr_t)inst; 301 Inst_t A = (Inst_t)(uintptr_t)*inst; 302 Inst_t S = (Inst_t)(uintptr_t)sym->getAddress(); 303 304 if (S == 0) { 305 S = (Inst_t)(uintptr_t)find_sym(context, sym->getName()); 306 sym->setAddress((void *)S); 307 } 308 309 switch (rel->getType()) { 310 default: 311 rsl_assert(0 && "Not implemented relocation type."); 312 break; 313 314 case R_386_PC32: 315 *inst = (S+A-P); 316 break; 317 318 case R_386_32: 319 *inst = (S+A); 320 break; 321 } 322 } 323} 324 325template <unsigned Bitwidth> 326inline void ELFObject<Bitwidth>:: 327relocate(void *(*find_sym)(void *context, char const *name), void *context) { 328 329 for (size_t i = 0; i < stab.size(); ++i) { 330 ELFSectionHeaderTy *sh = (*shtab)[i]; 331 if (sh->getType() != SHT_REL && sh->getType() != SHT_RELA) { 332 continue; 333 } 334 ELFSectionRelTableTy *reltab = 335 static_cast<ELFSectionRelTableTy *>(stab[i]); 336 rsl_assert(reltab && "Relocation section can't be NULL."); 337 338 const char *reltab_name = sh->getName(); 339 const char *need_rel_name; 340 if (sh->getType() == SHT_REL) { 341 need_rel_name = reltab_name + 4; 342 // ".rel.xxxx" 343 // ^ start from here. 344 } else { 345 need_rel_name = reltab_name + 5; 346 } 347 348 ELFSectionProgBitsTy *need_rel = 349 static_cast<ELFSectionProgBitsTy *>(getSectionByName(need_rel_name)); 350 rsl_assert(need_rel && "Need be relocated section can't be NULL."); 351 352 switch (getHeader()->getMachine()) { 353 case EM_ARM: 354 relocateARM(find_sym, context, reltab, need_rel); 355 break; 356 case EM_386: 357 relocateX86_32(find_sym, context, reltab, need_rel); 358 break; 359 case EM_X86_64: 360 relocateX86_64(find_sym, context, reltab, need_rel); 361 break; 362 363 default: 364 rsl_assert(0 && "Only support ARM, X86, and X86_64 relocation."); 365 break; 366 } 367 } 368 369 for (size_t i = 0; i < stab.size(); ++i) { 370 ELFSectionHeaderTy *sh = (*shtab)[i]; 371 if (sh->getType() == SHT_PROGBITS || sh->getType() == SHT_NOBITS) { 372 if (stab[i]) { 373 static_cast<ELFSectionBitsTy *>(stab[i])->protect(); 374 } 375 } 376 } 377} 378 379template <unsigned Bitwidth> 380inline void ELFObject<Bitwidth>::print() const { 381 header->print(); 382 shtab->print(); 383 384 for (size_t i = 0; i < stab.size(); ++i) { 385 ELFSectionTy *sec = stab[i]; 386 if (sec) { 387 sec->print(); 388 } 389 } 390} 391 392#endif // ELF_OBJECT_HXX 393