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