ELFObject.hxx revision 2061b057e0922ac33b9314c1ccaa50eb7286b847
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 <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 // FIXME: Should be implement in independent files. 104 assert(Bitwidth == 32 && "ARM only have 32 bits."); 105 106 // FIXME: Can not only relocate .rel.text! 107 ELFSectionRelTableTy *reltab = 108 static_cast<ELFSectionRelTableTy *>(getSectionByName(".rel.text")); 109 ELFSectionProgBitsTy *text = 110 static_cast<ELFSectionProgBitsTy *>(getSectionByName(".text")); 111 ELFSectionSymTabTy *symtab = 112 static_cast<ELFSectionSymTabTy *>(getSectionByName(".symtab")); 113 114 for (size_t i = 0; i < reltab->size(); ++i) { 115 // FIXME: Can not implement here, use Fixup! 116 ELFRelocTy *rel = (*reltab)[i]; 117 ELFSymbolTy *sym = (*symtab)[rel->getSymTabIndex()]; 118 119 // FIXME: May be not uint32_t *. 120 typedef int32_t Inst_t; 121 Inst_t *inst = (Inst_t *)&(*text)[rel->getOffset()]; 122 Inst_t P = (Inst_t)(int64_t)inst; 123 Inst_t A = 0; 124 Inst_t S = (Inst_t)(int64_t)sym->getAddress(); 125 126 switch (rel->getType()) { 127 default: 128 assert(0 && "Not implemented relocation type."); 129 break; 130 131 // FIXME: Predefine relocation codes. 132 case 28: // R_ARM_CALL 133 { 134#define SIGN_EXTEND(x, l) (((x)^(1<<((l)-1)))-(1<<(l-1))) 135 A = (Inst_t)(int64_t)SIGN_EXTEND(*inst & 0xFFFFFF, 24); 136#undef SIGN_EXTEND 137 138 switch (sym->getType()) { 139 default: 140 assert(0 && "Wrong type for R_ARM_CALL relocation."); 141 abort(); 142 break; 143 144 case STT_FUNC: 145 if (S == 0) { 146 assert(0 && "We should get function address at previous " 147 "sym->getAddress() function call."); 148 abort(); 149 } 150 break; 151 152 case STT_NOTYPE: 153 if (S == 0) { 154 void *ext_func = find_sym(context, sym->getName()); 155 S = (Inst_t)(uintptr_t)ext_func; 156 sym->setAddress(ext_func); 157 158 uint32_t result = (S >> 2) - (P >> 2) + A; 159 if (result > 0x007fffff && result < 0xff800000) { 160#ifndef __arm__ 161 // We have not implement function stub in this runtime env 162 assert(0 && "Target address is far from call instruction"); 163 abort(); 164#else 165 void *stub = getStubLayout()->allocateStub(ext_func); 166 if (!stub) { 167 llvm::errs() << "unable to allocate stub." << "\n"; 168 exit(EXIT_FAILURE); 169 } 170 171 //out() << "stub: for " << ext_func << " at " << stub << "\n"; 172 sym->setAddress(stub); 173 S = (uint32_t)stub; 174#endif 175 } 176 } 177 break; 178 } 179 180 uint32_t result = (S >> 2) - (P >> 2) + A; 181 182 if (result > 0x007fffff && result < 0xff800000) { 183 assert(0 && "Stub is still too far"); 184 abort(); 185 } 186 187 *inst = ((result) & 0x00FFFFFF) | (*inst & 0xFF000000); 188 } 189 break; 190 case 44: // R_ARM_MOVT_ABS 191 S >>= 16; 192 case 43: // R_ARM_MOVW_ABS_NC 193 { 194 // No need sign extend. 195 A = ((*inst & 0xF0000) >> 4) | (*inst & 0xFFF); 196 uint32_t result = (S+A); 197 *inst = (((result) & 0xF000) << 4) | 198 ((result) & 0xFFF) | 199 (*inst & 0xFFF0F000); 200 } 201 break; 202 } 203 //llvm::errs() << "S: " << (void *)S << '\n'; 204 //llvm::errs() << "A: " << (void *)A << '\n'; 205 //llvm::errs() << "P: " << (void *)P << '\n'; 206 //llvm::errs() << "S+A: " << (void *)(S+A) << '\n'; 207 //llvm::errs() << "S+A-P: " << (void *)(S+A-P) << '\n'; 208 } 209} 210 211template <unsigned Bitwidth> 212inline void ELFObject<Bitwidth>:: 213relocateX86_64(void *(*find_sym)(void *context, char const *name), 214 void *context) { 215 assert(Bitwidth == 64 && "Only support X86_64."); 216 217 ELFSectionSymTabTy *symtab = 218 static_cast<ELFSectionSymTabTy *>(getSectionByName(".symtab")); 219 220 char const *name[] = {".text", ".eh_frame"}; 221 size_t size = sizeof(name) / sizeof(char const *); 222 223 for (size_t i = 0; i < size; ++i) { 224 ELFSectionRelTableTy *relatab = 225 static_cast<ELFSectionRelTableTy *>( 226 getSectionByName((std::string(".rela") + name[i]).c_str())); 227 ELFSectionProgBitsTy *text = 228 static_cast<ELFSectionProgBitsTy *>(getSectionByName(name[i])); 229 230 for (size_t i = 0; i < relatab->size(); ++i) { 231 // FIXME: Can not implement here, use Fixup! 232 ELFRelocTy *rela = (*relatab)[i]; 233 ELFSymbolTy *sym = (*symtab)[rela->getSymTabIndex()]; 234 235 //typedef uint64_t Inst_t; 236 typedef int32_t Inst_t; 237 Inst_t *inst = (Inst_t *)&(*text)[rela->getOffset()]; 238 Inst_t P = (Inst_t)(int64_t)inst; 239 Inst_t A = (Inst_t)(int64_t)rela->getAddend(); 240 Inst_t S = (Inst_t)(int64_t)sym->getAddress(); 241 242 if (S == 0) { 243 S = (Inst_t)(int64_t)find_sym(context, sym->getName()); 244 sym->setAddress((void *)S); 245 } 246 247 switch (rela->getType()) { 248 default: 249 assert(0 && "Not implemented relocation type."); 250 break; 251 252 case 2: // R_X86_64_PC32 253 *inst = (S+A-P); 254 break; 255 256 case 10: // R_X86_64_32 257 case 11: // R_X86_64_32S 258 *inst = (S+A); 259 break; 260 } 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 assert(Bitwidth == 32 && "Only support X86."); 270 271 ELFSectionSymTabTy *symtab = 272 static_cast<ELFSectionSymTabTy *>(getSectionByName(".symtab")); 273 274 char const *name[] = {".text"}; 275 size_t const size = sizeof(name) / sizeof(char const *); 276 277 for (size_t i = 0; i < size; ++i) { 278 ELFSectionRelTableTy *reltab = 279 static_cast<ELFSectionRelTableTy *>( 280 getSectionByName((std::string(".rel") + name[i]).c_str())); 281 282 ELFSectionProgBitsTy *text = 283 static_cast<ELFSectionProgBitsTy *>(getSectionByName(name[i])); 284 285 for (size_t i = 0; i < reltab->size(); ++i) { 286 // FIXME: Can not implement here, use Fixup! 287 ELFRelocTy *rel = (*reltab)[i]; 288 ELFSymbolTy *sym = (*symtab)[rel->getSymTabIndex()]; 289 290 //typedef uint64_t Inst_t; 291 typedef int32_t Inst_t; 292 Inst_t *inst = (Inst_t *)&(*text)[rel->getOffset()]; 293 Inst_t P = (Inst_t)(uintptr_t)inst; 294 Inst_t A = (Inst_t)(uintptr_t)*inst; 295 Inst_t S = (Inst_t)(uintptr_t)sym->getAddress(); 296 297 if (S == 0) { 298 S = (Inst_t)(uintptr_t)find_sym(context, sym->getName()); 299 sym->setAddress((void *)S); 300 } 301 302 switch (rel->getType()) { 303 default: 304 assert(0 && "Not implemented relocation type."); 305 break; 306 307 case R_386_PC32: 308 *inst = (S+A-P); 309 break; 310 311 case R_386_32: 312 *inst = (S+A); 313 break; 314 } 315 } 316 } 317} 318 319template <unsigned Bitwidth> 320inline void ELFObject<Bitwidth>:: 321relocate(void *(*find_sym)(void *context, char const *name), void *context) { 322 switch (getHeader()->getMachine()) { 323 case EM_ARM: relocateARM(find_sym, context); break; 324 case EM_386: relocateX86_32(find_sym, context); break; 325 case EM_X86_64: relocateX86_64(find_sym, context); break; 326 327 default: 328 assert(0 && "Only support ARM and X86_64 relocation."); 329 break; 330 } 331 332 for (size_t i = 0; i < stab.size(); ++i) { 333 ELFSectionHeaderTy *sh = (*shtab)[i]; 334 if (sh->getType() == SHT_PROGBITS || sh->getType() == SHT_NOBITS) { 335 if (stab[i]) { 336 static_cast<ELFSectionBitsTy *>(stab[i])->protect(); 337 } 338 } 339 } 340} 341 342template <unsigned Bitwidth> 343inline void ELFObject<Bitwidth>::print() const { 344 header->print(); 345 shtab->print(); 346 347 for (size_t i = 0; i < stab.size(); ++i) { 348 ELFSectionTy *sec = stab[i]; 349 if (sec) { 350 sec->print(); 351 } 352 } 353} 354 355#endif // ELF_OBJECT_HXX 356