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