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