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