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