ELFObject.hxx revision 9ed73923af9db7283a8c76b5dfa2dda5b732a852
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#include "GOT.h" 26#include "ELF.h" 27 28#include <llvm/ADT/SmallVector.h> 29 30#include "utils/rsl_assert.h" 31 32template <unsigned Bitwidth> 33template <typename Archiver> 34inline ELFObject<Bitwidth> * 35ELFObject<Bitwidth>::read(Archiver &AR) { 36 llvm::OwningPtr<ELFObjectTy> object(new ELFObjectTy()); 37 38 // Read header 39 object->header.reset(ELFHeaderTy::read(AR)); 40 if (!object->header) { 41 return 0; 42 } 43 44 // Read section table 45 object->shtab.reset(ELFSectionHeaderTableTy::read(AR, object.get())); 46 if (!object->shtab) { 47 return 0; 48 } 49 50 // Read each section 51 llvm::SmallVector<size_t, 4> progbits_ndx; 52 for (size_t i = 0; i < object->header->getSectionHeaderNum(); ++i) { 53 if ((*object->shtab)[i]->getType() == SHT_PROGBITS) { 54 object->stab.push_back(NULL); 55 progbits_ndx.push_back(i); 56 } else { 57 llvm::OwningPtr<ELFSectionTy> sec( 58 ELFSectionTy::read(AR, object.get(), (*object->shtab)[i])); 59 object->stab.push_back(sec.take()); 60 } 61 } 62 63 object->shtab->buildNameMap(); 64 ELFSectionSymTabTy *symtab = 65 static_cast<ELFSectionSymTabTy *>(object->getSectionByName(".symtab")); 66 rsl_assert(symtab && "Symtab is required."); 67 symtab->buildNameMap(); 68 69 for (size_t i = 0; i < progbits_ndx.size(); ++i) { 70 size_t index = progbits_ndx[i]; 71 72 llvm::OwningPtr<ELFSectionTy> sec( 73 ELFSectionTy::read(AR, object.get(), (*object->shtab)[index])); 74 object->stab[index] = sec.take(); 75 } 76 77 return object.take(); 78} 79 80template <unsigned Bitwidth> 81inline char const *ELFObject<Bitwidth>::getSectionName(size_t i) const { 82 ELFSectionTy const *sec = stab[header->getStringSectionIndex()]; 83 84 if (sec) { 85 ELFSectionStrTabTy const &st = 86 static_cast<ELFSectionStrTabTy const &>(*sec); 87 return st[i]; 88 } 89 90 return NULL; 91} 92 93template <unsigned Bitwidth> 94inline ELFSection<Bitwidth> const * 95ELFObject<Bitwidth>::getSectionByIndex(size_t i) const { 96 return stab[i]; 97} 98 99template <unsigned Bitwidth> 100inline ELFSection<Bitwidth> * 101ELFObject<Bitwidth>::getSectionByIndex(size_t i) { 102 return stab[i]; 103} 104 105template <unsigned Bitwidth> 106inline ELFSection<Bitwidth> const * 107ELFObject<Bitwidth>::getSectionByName(std::string const &str) const { 108 size_t idx = getSectionHeaderTable()->getByName(str)->getIndex(); 109 return stab[idx]; 110} 111 112template <unsigned Bitwidth> 113inline ELFSection<Bitwidth> * 114ELFObject<Bitwidth>::getSectionByName(std::string const &str) { 115 ELFObjectTy const *const_this = this; 116 ELFSectionTy const *sptr = const_this->getSectionByName(str); 117 // Const cast for the same API's const and non-const versions. 118 return const_cast<ELFSectionTy *>(sptr); 119} 120 121 122template <unsigned Bitwidth> 123inline void ELFObject<Bitwidth>:: 124relocateARM(void *(*find_sym)(void *context, char const *name), 125 void *context, 126 ELFSectionRelTableTy *reltab, 127 ELFSectionProgBitsTy *text) { 128 // FIXME: Should be implement in independent files. 129 rsl_assert(Bitwidth == 32 && "ARM only have 32 bits."); 130 131 ELFSectionSymTabTy *symtab = 132 static_cast<ELFSectionSymTabTy *>(getSectionByName(".symtab")); 133 rsl_assert(symtab && "Symtab is required."); 134 135 for (size_t i = 0; i < reltab->size(); ++i) { 136 // FIXME: Can not implement here, use Fixup! 137 ELFRelocTy *rel = (*reltab)[i]; 138 ELFSymbolTy *sym = (*symtab)[rel->getSymTabIndex()]; 139 140 // FIXME: May be not uint32_t *. 141 typedef int32_t Inst_t; 142 Inst_t *inst = (Inst_t *)&(*text)[rel->getOffset()]; 143 Inst_t P = (Inst_t)(int64_t)inst; 144 Inst_t A = 0; 145 Inst_t S = (Inst_t)(int64_t)sym->getAddress(EM_ARM); 146 147 switch (rel->getType()) { 148 default: 149 rsl_assert(0 && "Not implemented relocation type."); 150 break; 151 152 case R_ARM_ABS32: 153 { 154 A = *inst; 155 *inst = (S+A); 156 } 157 break; 158 159 // FIXME: Predefine relocation codes. 160 case R_ARM_CALL: 161 { 162#define SIGN_EXTEND(x, l) (((x)^(1<<((l)-1)))-(1<<(l-1))) 163 A = (Inst_t)(int64_t)SIGN_EXTEND(*inst & 0xFFFFFF, 24); 164#undef SIGN_EXTEND 165 166 void *callee_addr = sym->getAddress(EM_ARM); 167 168 switch (sym->getType()) { 169 default: 170 rsl_assert(0 && "Wrong type for R_ARM_CALL relocation."); 171 abort(); 172 break; 173 174 case STT_FUNC: 175 // NOTE: Callee function is in the object file, but it may be 176 // in different PROGBITS section (which may be far call). 177 178 if (callee_addr == 0) { 179 rsl_assert(0 && "We should get function address at previous " 180 "sym->getAddress(EM_ARM) function call."); 181 abort(); 182 } 183 break; 184 185 case STT_NOTYPE: 186 // NOTE: Callee function is an external function. Call find_sym 187 // if it has not resolved yet. 188 189 if (callee_addr == 0) { 190 callee_addr = find_sym(context, sym->getName()); 191 sym->setAddress(callee_addr); 192 } 193 break; 194 } 195 196 // Get the stub for this function 197 StubLayout *stub_layout = text->getStubLayout(); 198 199 if (!stub_layout) { 200 llvm::errs() << "unable to get stub layout." << "\n"; 201 abort(); 202 } 203 204 void *stub = stub_layout->allocateStub(callee_addr); 205 206 if (!stub) { 207 llvm::errs() << "unable to allocate stub." << "\n"; 208 abort(); 209 } 210 211 //LOGI("Function %s: using stub %p\n", sym->getName(), stub); 212 S = (uint32_t)(uintptr_t)stub; 213 214 // Relocate the R_ARM_CALL relocation type 215 uint32_t result = (S >> 2) - (P >> 2) + A; 216 217 if (result > 0x007fffff && result < 0xff800000) { 218 rsl_assert(0 && "Stub is still too far"); 219 abort(); 220 } 221 222 *inst = ((result) & 0x00FFFFFF) | (*inst & 0xFF000000); 223 } 224 break; 225 case R_ARM_MOVT_ABS: 226 case R_ARM_MOVW_ABS_NC: 227 { 228 if (S==0 && sym->getType() == STT_NOTYPE) 229 { 230 void *ext_sym = find_sym(context, sym->getName()); 231 S = (Inst_t)(uintptr_t)ext_sym; 232 sym->setAddress(ext_sym); 233 } 234 if (rel->getType() == R_ARM_MOVT_ABS) { 235 S >>= 16; 236 } 237 238 // No need sign extend. 239 A = ((*inst & 0xF0000) >> 4) | (*inst & 0xFFF); 240 uint32_t result = (S+A); 241 *inst = (((result) & 0xF000) << 4) | 242 ((result) & 0xFFF) | 243 (*inst & 0xFFF0F000); 244 } 245 break; 246 } 247 //llvm::errs() << "S: " << (void *)S << '\n'; 248 //llvm::errs() << "A: " << (void *)A << '\n'; 249 //llvm::errs() << "P: " << (void *)P << '\n'; 250 //llvm::errs() << "S+A: " << (void *)(S+A) << '\n'; 251 //llvm::errs() << "S+A-P: " << (void *)(S+A-P) << '\n'; 252 } 253} 254 255template <unsigned Bitwidth> 256inline void ELFObject<Bitwidth>:: 257relocateX86_64(void *(*find_sym)(void *context, char const *name), 258 void *context, 259 ELFSectionRelTableTy *reltab, 260 ELFSectionProgBitsTy *text) { 261 rsl_assert(Bitwidth == 64 && "Only support X86_64."); 262 263 ELFSectionSymTabTy *symtab = 264 static_cast<ELFSectionSymTabTy *>(getSectionByName(".symtab")); 265 rsl_assert(symtab && "Symtab is required."); 266 267 for (size_t i = 0; i < reltab->size(); ++i) { 268 // FIXME: Can not implement here, use Fixup! 269 ELFRelocTy *rel = (*reltab)[i]; 270 ELFSymbolTy *sym = (*symtab)[rel->getSymTabIndex()]; 271 272 //typedef uint64_t Inst_t; 273 typedef int32_t Inst_t; 274 Inst_t *inst = (Inst_t *)&(*text)[rel->getOffset()]; 275 Inst_t P = (Inst_t)(int64_t)inst; 276 Inst_t A = (Inst_t)(int64_t)rel->getAddend(); 277 Inst_t S = (Inst_t)(int64_t)sym->getAddress(EM_X86_64); 278 279 if (S == 0) { 280 S = (Inst_t)(int64_t)find_sym(context, sym->getName()); 281 sym->setAddress((void *)S); 282 } 283 284 switch (rel->getType()) { 285 default: 286 rsl_assert(0 && "Not implemented relocation type."); 287 break; 288 289 // FIXME: XXX: R_X86_64_64 is 64 bit, there is a big problem here. 290 case 1: // R_X86_64_64 291 *inst = (S+A); 292 break; 293 294 case 2: // R_X86_64_PC32 295 *inst = (S+A-P); 296 break; 297 298 case 10: // R_X86_64_32 299 case 11: // R_X86_64_32S 300 *inst = (S+A); 301 break; 302 } 303 } 304} 305 306template <unsigned Bitwidth> 307inline void ELFObject<Bitwidth>:: 308relocateX86_32(void *(*find_sym)(void *context, char const *name), 309 void *context, 310 ELFSectionRelTableTy *reltab, 311 ELFSectionProgBitsTy *text) { 312 rsl_assert(Bitwidth == 32 && "Only support X86."); 313 314 ELFSectionSymTabTy *symtab = 315 static_cast<ELFSectionSymTabTy *>(getSectionByName(".symtab")); 316 rsl_assert(symtab && "Symtab is required."); 317 318 for (size_t i = 0; i < reltab->size(); ++i) { 319 // FIXME: Can not implement here, use Fixup! 320 ELFRelocTy *rel = (*reltab)[i]; 321 ELFSymbolTy *sym = (*symtab)[rel->getSymTabIndex()]; 322 323 //typedef uint64_t Inst_t; 324 typedef int32_t Inst_t; 325 Inst_t *inst = (Inst_t *)&(*text)[rel->getOffset()]; 326 Inst_t P = (Inst_t)(uintptr_t)inst; 327 Inst_t A = (Inst_t)(uintptr_t)*inst; 328 Inst_t S = (Inst_t)(uintptr_t)sym->getAddress(EM_386); 329 330 if (S == 0) { 331 S = (Inst_t)(uintptr_t)find_sym(context, sym->getName()); 332 sym->setAddress((void *)S); 333 } 334 335 switch (rel->getType()) { 336 default: 337 rsl_assert(0 && "Not implemented relocation type."); 338 break; 339 340 case R_386_PC32: 341 *inst = (S+A-P); 342 break; 343 344 case R_386_32: 345 *inst = (S+A); 346 break; 347 } 348 } 349} 350 351template <unsigned Bitwidth> 352inline void ELFObject<Bitwidth>:: 353relocateMIPS(void *(*find_sym)(void *context, char const *name), 354 void *context, 355 ELFSectionRelTableTy *reltab, 356 ELFSectionProgBitsTy *text) { 357 rsl_assert(Bitwidth == 32 && "Only support 32-bit MIPS."); 358 359 ELFSectionSymTabTy *symtab = 360 static_cast<ELFSectionSymTabTy *>(getSectionByName(".symtab")); 361 rsl_assert(symtab && "Symtab is required."); 362 363 for (size_t i = 0; i < reltab->size(); ++i) { 364 // FIXME: Can not implement here, use Fixup! 365 ELFRelocTy *rel = (*reltab)[i]; 366 ELFSymbolTy *sym = (*symtab)[rel->getSymTabIndex()]; 367 368 typedef int32_t Inst_t; 369 Inst_t *inst = (Inst_t *)&(*text)[rel->getOffset()]; 370 Inst_t P = (Inst_t)(uintptr_t)inst; 371 Inst_t A = (Inst_t)(uintptr_t)*inst; 372 Inst_t S = (Inst_t)(uintptr_t)sym->getAddress(EM_MIPS); 373 374 bool need_stub = false; 375 376 if (S == 0 && strcmp (sym->getName(), "_gp_disp") != 0) { 377 need_stub = true; 378 S = (Inst_t)(uintptr_t)find_sym(context, sym->getName()); 379 sym->setAddress((void *)S); 380 } 381 382 switch (rel->getType()) { 383 default: 384 rsl_assert(0 && "Not implemented relocation type."); 385 break; 386 387 case R_MIPS_NONE: 388 case R_MIPS_JALR: // ignore this 389 break; 390 391 case R_MIPS_16: 392 *inst &= 0xFFFF0000; 393 A = A & 0xFFFF; 394 A = S + (short)A; 395 rsl_assert(A >= -32768 && A <= 32767 && "R_MIPS_16 overflow."); 396 *inst |= (A & 0xFFFF); 397 break; 398 399 case R_MIPS_32: 400 *inst = S + A; 401 break; 402 403 case R_MIPS_26: 404 *inst &= 0xFC000000; 405 if (need_stub == false) { 406 A = (A & 0x3FFFFFF) << 2; 407 if (sym->getBindingAttribute() == STB_LOCAL) { // local binding 408 A |= ((P + 4) & 0xF0000000); 409 A += S; 410 *inst |= ((A >> 2) & 0x3FFFFFF); 411 } 412 else { // external binding 413 if (A & 0x08000000) // Sign extend from bit 27 414 A |= 0xF0000000; 415 A += S; 416 *inst |= ((A >> 2) & 0x3FFFFFF); 417 if (((P + 4) >> 28) != (A >> 28)) { // far local call 418 void *stub = text->getStubLayout()->allocateStub((void *)A); 419 rsl_assert(stub && "cannot allocate stub."); 420 sym->setAddress(stub); 421 S = (int32_t)stub; 422 *inst |= ((S >> 2) & 0x3FFFFFF); 423 rsl_assert(((P + 4) >> 28) == (S >> 28) && "stub is too far."); 424 } 425 } 426 } 427 else { // shared-library call 428 A = (A & 0x3FFFFFF) << 2; 429 rsl_assert(A == 0 && "R_MIPS_26 addend is not zero."); 430 void *stub = text->getStubLayout()->allocateStub((void *)S); 431 rsl_assert(stub && "cannot allocate stub."); 432 sym->setAddress(stub); 433 S = (int32_t)stub; 434 *inst |= ((S >> 2) & 0x3FFFFFF); 435 rsl_assert(((P + 4) >> 28) == (S >> 28) && "stub is too far."); 436 } 437 break; 438 439 case R_MIPS_HI16: 440 *inst &= 0xFFFF0000; 441 A = (A & 0xFFFF) << 16; 442 // Find the nearest LO16 relocation type after this entry 443 for (size_t j = i + 1; j < reltab->size(); j++) { 444 ELFRelocTy *this_rel = (*reltab)[j]; 445 ELFSymbolTy *this_sym = (*symtab)[this_rel->getSymTabIndex()]; 446 if (this_rel->getType() == R_MIPS_LO16 && this_sym == sym) { 447 Inst_t *this_inst = (Inst_t *)&(*text)[this_rel->getOffset()]; 448 Inst_t this_A = (Inst_t)(uintptr_t)*this_inst; 449 this_A = this_A & 0xFFFF; 450 A += (short)this_A; 451 break; 452 } 453 } 454 if (strcmp (sym->getName(), "_gp_disp") == 0) { 455 S = (int)got_address() + GP_OFFSET - (int)P; 456 sym->setAddress((void *)S); 457 } 458 *inst |= (((S + A + (int)0x8000) >> 16) & 0xFFFF); 459 break; 460 461 case R_MIPS_LO16: 462 *inst &= 0xFFFF0000; 463 A = A & 0xFFFF; 464 if (strcmp (sym->getName(), "_gp_disp") == 0) { 465 S = (Inst_t)sym->getAddress(EM_MIPS); 466 } 467 *inst |= ((S + A) & 0xFFFF); 468 break; 469 470 case R_MIPS_GOT16: 471 case R_MIPS_CALL16: 472 { 473 *inst &= 0xFFFF0000; 474 A = A & 0xFFFF; 475 if (rel->getType() == R_MIPS_GOT16) { 476 if (sym->getBindingAttribute() == STB_LOCAL) { 477 A <<= 16; 478 479 // Find the nearest LO16 relocation type after this entry 480 for (size_t j = i + 1; j < reltab->size(); j++) { 481 ELFRelocTy *this_rel = (*reltab)[j]; 482 ELFSymbolTy *this_sym = (*symtab)[this_rel->getSymTabIndex()]; 483 if (this_rel->getType() == R_MIPS_LO16 && this_sym == sym) { 484 Inst_t *this_inst = (Inst_t *)&(*text)[this_rel->getOffset()]; 485 Inst_t this_A = (Inst_t)(uintptr_t)*this_inst; 486 this_A = this_A & 0xFFFF; 487 A += (short)this_A; 488 break; 489 } 490 } 491 } 492 else { 493 rsl_assert(A == 0 && "R_MIPS_GOT16 addend is not 0."); 494 } 495 } 496 else { // R_MIPS_CALL16 497 rsl_assert(A == 0 && "R_MIPS_CALL16 addend is not 0."); 498 } 499 int got_index = search_got((int)rel->getSymTabIndex(), (void *)(S + A), 500 sym->getBindingAttribute()); 501 int got_offset = (got_index << 2) - GP_OFFSET; 502 *inst |= (got_offset & 0xFFFF); 503 } 504 break; 505 506 case R_MIPS_GPREL32: 507 *inst = A + S - ((int)got_address() + GP_OFFSET); 508 break; 509 } 510 } 511} 512 513 514// TODO: Refactor all relocations. 515template <unsigned Bitwidth> 516inline void ELFObject<Bitwidth>:: 517relocate(void *(*find_sym)(void *context, char const *name), void *context) { 518 // Init SHNCommonDataSize. 519 // Need refactoring 520 size_t SHNCommonDataSize = 0; 521 522 ELFSectionSymTabTy *symtab = 523 static_cast<ELFSectionSymTabTy *>(getSectionByName(".symtab")); 524 rsl_assert(symtab && "Symtab is required."); 525 526 for (size_t i = 0; i < symtab->size(); ++i) { 527 ELFSymbolTy *sym = (*symtab)[i]; 528 529 if (sym->getType() != STT_OBJECT) { 530 continue; 531 } 532 533 size_t idx = (size_t)sym->getSectionIndex(); 534 switch (idx) { 535 default: 536 if ((*shtab)[idx]->getType() == SHT_NOBITS) { 537 // FIXME(logan): This is a workaround for .lcomm directives 538 // bug of LLVM ARM MC code generator. Remove this when the 539 // LLVM bug is fixed. 540 541 size_t align = 16; 542 SHNCommonDataSize += (size_t)sym->getSize() + align; 543 } 544 break; 545 546 case SHN_COMMON: 547 { 548 size_t align = (size_t)sym->getValue(); 549 SHNCommonDataSize += (size_t)sym->getSize() + align; 550 } 551 break; 552 553 case SHN_ABS: 554 case SHN_UNDEF: 555 case SHN_XINDEX: 556 break; 557 } 558 } 559 if (!initSHNCommonDataSize(SHNCommonDataSize)) { 560 rsl_assert("Allocate memory for common variable fail!"); 561 } 562 563 for (size_t i = 0; i < stab.size(); ++i) { 564 ELFSectionHeaderTy *sh = (*shtab)[i]; 565 if (sh->getType() != SHT_REL && sh->getType() != SHT_RELA) { 566 continue; 567 } 568 ELFSectionRelTableTy *reltab = 569 static_cast<ELFSectionRelTableTy *>(stab[i]); 570 rsl_assert(reltab && "Relocation section can't be NULL."); 571 572 const char *reltab_name = sh->getName(); 573 const char *need_rel_name; 574 if (sh->getType() == SHT_REL) { 575 need_rel_name = reltab_name + 4; 576 // ".rel.xxxx" 577 // ^ start from here. 578 } else { 579 need_rel_name = reltab_name + 5; 580 } 581 582 ELFSectionProgBitsTy *need_rel = 583 static_cast<ELFSectionProgBitsTy *>(getSectionByName(need_rel_name)); 584 rsl_assert(need_rel && "Need be relocated section can't be NULL."); 585 586 switch (getHeader()->getMachine()) { 587 case EM_ARM: 588 relocateARM(find_sym, context, reltab, need_rel); 589 break; 590 case EM_386: 591 relocateX86_32(find_sym, context, reltab, need_rel); 592 break; 593 case EM_X86_64: 594 relocateX86_64(find_sym, context, reltab, need_rel); 595 break; 596 case EM_MIPS: 597 relocateMIPS(find_sym, context, reltab, need_rel); 598 break; 599 600 default: 601 rsl_assert(0 && "Only support ARM, MIPS, X86, and X86_64 relocation."); 602 break; 603 } 604 } 605 606 for (size_t i = 0; i < stab.size(); ++i) { 607 ELFSectionHeaderTy *sh = (*shtab)[i]; 608 if (sh->getType() == SHT_PROGBITS || sh->getType() == SHT_NOBITS) { 609 if (stab[i]) { 610 static_cast<ELFSectionBitsTy *>(stab[i])->protect(); 611 } 612 } 613 } 614} 615 616template <unsigned Bitwidth> 617inline void ELFObject<Bitwidth>::print() const { 618 header->print(); 619 shtab->print(); 620 621 for (size_t i = 0; i < stab.size(); ++i) { 622 ELFSectionTy *sec = stab[i]; 623 if (sec) { 624 sec->print(); 625 } 626 } 627} 628 629#endif // ELF_OBJECT_HXX 630