ELFObject.h revision 52c59da013c4cf0d0779de201d1c88b15f762a08
1#ifndef ELF_OBJECT_H 2#define ELF_OBJECT_H 3 4#include <llvm/ADT/OwningPtr.h> 5 6#include <vector> 7#include <string> 8 9#include <assert.h> 10#include <elf.h> 11 12class StubLayout; 13 14template <unsigned Bitwidth> class ELFHeader; 15template <unsigned Bitwidth> class ELFSection; 16template <unsigned Bitwidth> class ELFSectionHeaderTable; 17 18template <unsigned Bitwidth> 19class ELFObject { 20private: 21 llvm::OwningPtr<ELFHeader<Bitwidth> > header; 22 llvm::OwningPtr<ELFSectionHeaderTable<Bitwidth> > shtab; 23 std::vector<ELFSection<Bitwidth> *> stab; 24 25#ifdef __arm__ 26 llvm::OwningPtr<StubLayout> stubs; 27#endif 28 29private: 30 ELFObject() { } 31 32public: 33 template <typename Archiver> 34 static ELFObject *read(Archiver &AR); 35 36 ELFHeader<Bitwidth> const *getHeader() const { 37 return header.get(); 38 } 39 40 ELFSectionHeaderTable<Bitwidth> const *getSectionHeaderTable() const { 41 return shtab.get(); 42 } 43 44 char const *getSectionName(size_t i) const; 45 ELFSection<Bitwidth> const *getSectionByIndex(size_t i) const; 46 ELFSection<Bitwidth> *getSectionByIndex(size_t i); 47 ELFSection<Bitwidth> const *getSectionByName(std::string const &str) const; 48 ELFSection<Bitwidth> *getSectionByName(std::string const &str); 49 50#ifdef __arm__ 51 StubLayout *getStubLayout(); 52#endif 53 54 void relocate(void *(*find_sym)(char const *name, void *context), 55 void *context); 56 57 void print() const; 58 59 ~ELFObject() { 60 for (size_t i = 0; i < stab.size(); ++i) { 61 // Delete will check the pointer is nullptr or not by himself. 62 delete stab[i]; 63 } 64 } 65 66private: 67 void relocateARM(void *(*find_sym)(char const *name, void *context), 68 void *context); 69 70 void relocateX86_32(void *(*find_sym)(char const *name, void *context), 71 void *context); 72 73 void relocateX86_64(void *(*find_sym)(char const *name, void *context), 74 void *context); 75 76}; 77 78//==================Inline Member Function Definition========================== 79 80#include "ELFHeader.h" 81#include "ELFReloc.h" 82#include "ELFSection.h" 83#include "ELFSectionHeaderTable.h" 84#include "StubLayout.h" 85 86#ifdef __arm__ 87template <unsigned Bitwidth> 88inline StubLayout *ELFObject<Bitwidth>::getStubLayout() { 89 if (!stubs) { 90 stubs.reset(new StubLayout()); 91 } 92 return stubs.get(); 93} 94#endif 95 96template <unsigned Bitwidth> 97template <typename Archiver> 98inline ELFObject<Bitwidth> * 99ELFObject<Bitwidth>::read(Archiver &AR) { 100 llvm::OwningPtr<ELFObject<Bitwidth> > object(new ELFObject<Bitwidth>()); 101 102 // Read header 103 object->header.reset(ELFHeader<Bitwidth>::read(AR)); 104 if (!object->header) { 105 return 0; 106 } 107 108 // Read section table 109 object->shtab.reset(ELFSectionHeaderTable<Bitwidth>::read(AR, object.get())); 110 if (!object->shtab) { 111 return 0; 112 } 113 114 // Read each section 115 for (size_t i = 0; i < object->header->getSectionHeaderNum(); ++i) { 116 llvm::OwningPtr<ELFSection<Bitwidth> > sec( 117 ELFSection<Bitwidth>::read(AR, object.get(), (*object->shtab)[i])); 118 object->stab.push_back(sec.take()); 119 } 120 121 return object.take(); 122} 123 124template <unsigned Bitwidth> 125inline char const *ELFObject<Bitwidth>::getSectionName(size_t i) const { 126 ELFSection<Bitwidth> const *sec = 127 stab[header->getStringSectionIndex()]; 128 129 if (sec) { 130 ELFSectionStrTab<Bitwidth> const &st = 131 static_cast<ELFSectionStrTab<Bitwidth> const &>(*sec); 132 return st[i]; 133 } 134 135 return NULL; 136} 137 138template <unsigned Bitwidth> 139inline ELFSection<Bitwidth> const * 140ELFObject<Bitwidth>::getSectionByIndex(size_t i) const { 141 return stab[i]; 142} 143 144template <unsigned Bitwidth> 145inline ELFSection<Bitwidth> * 146ELFObject<Bitwidth>::getSectionByIndex(size_t i) { 147 return stab[i]; 148} 149 150template <unsigned Bitwidth> 151inline ELFSection<Bitwidth> const * 152ELFObject<Bitwidth>::getSectionByName(std::string const &str) const { 153 size_t idx = getSectionHeaderTable()->getByName(str)->getIndex(); 154 return stab[idx]; 155} 156 157template <unsigned Bitwidth> 158inline ELFSection<Bitwidth> * 159ELFObject<Bitwidth>::getSectionByName(std::string const &str) { 160 ELFObject<Bitwidth> const *const_this = this; 161 ELFSection<Bitwidth> const *sptr = const_this->getSectionByName(str); 162 // Const cast for the same API's const and non-const versions. 163 return const_cast<ELFSection<Bitwidth> *>(sptr); 164} 165 166 167template <unsigned Bitwidth> 168inline void ELFObject<Bitwidth>:: 169relocateARM(void *(*find_sym)(char const *name, void *context), 170 void *context) { 171 // FIXME: Should be implement in independent files. 172 assert(Bitwidth == 32 && "ARM only have 32 bits."); 173 174 // FIXME: Can not only relocate .rel.text! 175 ELFSectionRelTable<Bitwidth> *reltab = 176 static_cast<ELFSectionRelTable<Bitwidth> *>(getSectionByName(".rel.text")); 177 ELFSectionProgBits<Bitwidth> *text = 178 static_cast<ELFSectionProgBits<Bitwidth> *>(getSectionByName(".text")); 179 ELFSectionSymTab<Bitwidth> *symtab = 180 static_cast<ELFSectionSymTab<Bitwidth> *>(getSectionByName(".symtab")); 181 182 for (size_t i = 0; i < reltab->size(); ++i) { 183 // FIXME: Can not implement here, use Fixup! 184 ELFReloc<Bitwidth> *rel = (*reltab)[i]; 185 ELFSymbol<Bitwidth> *sym = (*symtab)[rel->getSymTabIndex()]; 186 187 // FIXME: May be not uint32_t *. 188 typedef int32_t Inst_t; 189 Inst_t *inst = (Inst_t *)&(*text)[rel->getOffset()]; 190 Inst_t P = (Inst_t)(int64_t)inst; 191 Inst_t A = 0; 192 Inst_t S = (Inst_t)(int64_t)sym->getAddress(); 193 194 switch ((uint32_t)rel->getType()) { 195 default: 196 assert(0 && "Not implemented relocation type."); 197 break; 198 199 // FIXME: Predefine relocation codes. 200 case 28: // R_ARM_CALL 201 { 202#define SIGN_EXTEND(x, l) (((x)^(1<<((l)-1)))-(1<<(l-1))) 203 A = (Inst_t)(int64_t)SIGN_EXTEND(*inst & 0xFFFFFF, 24); 204#undef SIGN_EXTEND 205 if (S == 0) { 206 S = (Inst_t)(int64_t)find_sym(sym->getName(), context); 207 sym->setAddress((void *)S); 208 } 209 //switch (sym->getType()) { 210 // default: 211 // assert(0 && "Wrong type for R_ARM_CALL relocation."); 212 // break; 213 // case STT_FUNC: 214 // { 215 // S = (uint32_t)sym->getAddress(); 216 // } 217 // break; 218 // case STT_NOTYPE: 219 // { 220 // if (sym->getAddress() == 0) { 221 // sym->setAddress(find_sym(sym->getName(), context)); 222 // } 223 // S = (uint32_t)sym->getAddress(); 224 // } 225 // break; 226 //} 227 S >>= 2; 228 P >>= 2; 229 uint32_t result = (S+A-P); 230#ifdef __arm__ 231 if ((result & 0xFF000000) != 0) { 232 out() << "far stub for: " << sym->getAddress() << " "; 233 void *stub = getStubLayout()->allocateStub((void *)sym->getAddress()); 234 if (!stub) { 235 out() << "unable to allocate stub." << "\n"; 236 exit(EXIT_FAILURE); 237 } 238 out() << "is at " << stub << "\n"; 239 S = ((uint32_t)stub) >> 2; 240 result = (S+A-P); 241 } 242#else 243 // TODO: Stub. 244 assert(((result & 0xFF000000) == 0) && "Too far, need stub."); 245#endif 246 *inst = ((result) & 0x00FFFFFF) | (*inst & 0xFF000000); 247 } 248 break; 249 case 44: // R_ARM_MOVT_ABS 250 S >>= 16; 251 case 43: // R_ARM_MOVW_ABS_NC 252 { 253 // No need sign extend. 254 A = ((*inst & 0xF0000) >> 4) | (*inst & 0xFFF); 255 uint32_t result = (S+A); 256 *inst = (((result) & 0xF000) << 4) | 257 ((result) & 0xFFF) | 258 (*inst & 0xFFF0F000); 259 } 260 break; 261 } 262 //llvm::errs() << "S: " << (void *)S << '\n'; 263 //llvm::errs() << "A: " << (void *)A << '\n'; 264 //llvm::errs() << "P: " << (void *)P << '\n'; 265 //llvm::errs() << "S+A: " << (void *)(S+A) << '\n'; 266 //llvm::errs() << "S+A-P: " << (void *)(S+A-P) << '\n'; 267 } 268} 269 270template <unsigned Bitwidth> 271inline void ELFObject<Bitwidth>:: 272relocateX86_64(void *(*find_sym)(char const *name, void *context), 273 void *context) { 274 assert(Bitwidth == 64 && "Only support X86_64."); 275 276 ELFSectionSymTab<Bitwidth> *symtab = 277 static_cast<ELFSectionSymTab<Bitwidth> *>(getSectionByName(".symtab")); 278 279 char const *name[] = {".text", ".eh_frame"}; 280 size_t size = sizeof(name) / sizeof(char const *); 281 282 for (size_t i = 0; i < size; ++i) { 283 ELFSectionRelTable<Bitwidth> *relatab = 284 static_cast<ELFSectionRelTable<Bitwidth> *>( 285 getSectionByName((std::string(".rela") + name[i]).c_str())); 286 ELFSectionProgBits<Bitwidth> *text = 287 static_cast<ELFSectionProgBits<Bitwidth> *>(getSectionByName(name[i])); 288 289 for (size_t i = 0; i < relatab->size(); ++i) { 290 // FIXME: Can not implement here, use Fixup! 291 ELFReloc<Bitwidth> *rela = (*relatab)[i]; 292 ELFSymbol<Bitwidth> *sym = (*symtab)[rela->getSymTabIndex()]; 293 294 //typedef uint64_t Inst_t; 295 typedef int32_t Inst_t; 296 Inst_t *inst = (Inst_t *)&(*text)[rela->getOffset()]; 297 Inst_t P = (Inst_t)(int64_t)inst; 298 Inst_t A = (Inst_t)(int64_t)rela->getAddend(); 299 Inst_t S = (Inst_t)(int64_t)sym->getAddress(); 300 301 if (S == 0) { 302 S = (Inst_t)(int64_t)find_sym(sym->getName(), context); 303 sym->setAddress((void *)S); 304 } 305 306 switch ((uint32_t)rela->getType()) { 307 default: 308 assert(0 && "Not implemented relocation type."); 309 break; 310 311 case 2: // R_X86_64_PC32 312 *inst = (S+A-P); 313 break; 314 315 case 10: // R_X86_64_32 316 case 11: // R_X86_64_32S 317 *inst = (S+A); 318 break; 319 } 320 } 321 } 322} 323 324template <unsigned Bitwidth> 325inline void ELFObject<Bitwidth>:: 326relocateX86_32(void *(*find_sym)(char const *name, void *context), 327 void *context) { 328 assert(Bitwidth == 32 && "Only support X86."); 329 330 ELFSectionSymTab<Bitwidth> *symtab = 331 static_cast<ELFSectionSymTab<Bitwidth> *>( 332 getSectionByName(".symtab")); 333 334 char const *name[] = {".text"}; 335 size_t const size = sizeof(name) / sizeof(char const *); 336 337 for (size_t i = 0; i < size; ++i) { 338 ELFSectionRelTable<Bitwidth> *reltab = 339 static_cast<ELFSectionRelTable<Bitwidth> *>( 340 getSectionByName((std::string(".rel") + name[i]).c_str())); 341 342 ELFSectionProgBits<Bitwidth> *text = 343 static_cast<ELFSectionProgBits<Bitwidth> *>( 344 getSectionByName(name[i])); 345 346 for (size_t i = 0; i < reltab->size(); ++i) { 347 // FIXME: Can not implement here, use Fixup! 348 ELFReloc<Bitwidth> *rel = (*reltab)[i]; 349 ELFSymbol<Bitwidth> *sym = (*symtab)[rel->getSymTabIndex()]; 350 351 //typedef uint64_t Inst_t; 352 typedef int32_t Inst_t; 353 Inst_t *inst = (Inst_t *)&(*text)[rel->getOffset()]; 354 Inst_t P = (Inst_t)(uintptr_t)inst; 355 Inst_t A = (Inst_t)(uintptr_t)*inst; 356 Inst_t S = (Inst_t)(uintptr_t)sym->getAddress(); 357 358 if (S == 0) { 359 S = (Inst_t)(uintptr_t)find_sym(sym->getName(), context); 360 sym->setAddress((void *)S); 361 } 362 363 switch ((uint32_t)rel->getType()) { 364 default: 365 assert(0 && "Not implemented relocation type."); 366 break; 367 368 case R_386_PC32: 369 *inst = (S+A-P); 370 break; 371 372 case R_386_32: 373 *inst = (S+A); 374 break; 375 } 376 } 377 } 378} 379 380template <unsigned Bitwidth> 381inline void ELFObject<Bitwidth>:: 382relocate(void *(*find_sym)(char const *name, void *context), void *context) { 383 switch ((uint32_t)getHeader()->getMachine()) { 384 case EM_ARM: relocateARM(find_sym, context); break; 385 case EM_386: relocateX86_32(find_sym, context); break; 386 case EM_X86_64: relocateX86_64(find_sym, context); break; 387 388 default: 389 assert(0 && "Only support ARM and X86_64 relocation."); 390 break; 391 } 392 393 for (size_t i = 0; i < stab.size(); ++i) { 394 ELFSectionHeader<Bitwidth> *sh = (*shtab)[i]; 395 if (sh && (sh->getType() == SHT_PROGBITS || 396 sh->getType() == SHT_NOBITS)) { 397 static_cast<ELFSectionBits<Bitwidth> *>(stab[i])->memory_protect(); 398 } 399 } 400} 401 402template <unsigned Bitwidth> 403inline void ELFObject<Bitwidth>::print() const { 404 header->print(); 405 shtab->print(); 406 407 for (size_t i = 0; i < stab.size(); ++i) { 408 ELFSection<Bitwidth> *sec = stab[i]; 409 if (sec) { 410 sec->print(); 411 } 412 } 413} 414 415#endif // ELF_OBJECT_H 416