ELFObject.hxx revision 4e4356b34f9751070ac8ccb1bb74bb44e9232661
1a02fdf1ba03fad71cc80a89dfc74b17456d5b4a5Adam Cohen#ifndef ELF_OBJECT_HXX 2a02fdf1ba03fad71cc80a89dfc74b17456d5b4a5Adam Cohen#define ELF_OBJECT_HXX 3a02fdf1ba03fad71cc80a89dfc74b17456d5b4a5Adam Cohen 4a02fdf1ba03fad71cc80a89dfc74b17456d5b4a5Adam Cohen#include "ELFHeader.h" 5a02fdf1ba03fad71cc80a89dfc74b17456d5b4a5Adam Cohen#include "ELFReloc.h" 6a02fdf1ba03fad71cc80a89dfc74b17456d5b4a5Adam Cohen#include "ELFSection.h" 7a02fdf1ba03fad71cc80a89dfc74b17456d5b4a5Adam Cohen#include "ELFSectionHeaderTable.h" 8a02fdf1ba03fad71cc80a89dfc74b17456d5b4a5Adam Cohen#include "StubLayout.h" 9a02fdf1ba03fad71cc80a89dfc74b17456d5b4a5Adam Cohen 10a02fdf1ba03fad71cc80a89dfc74b17456d5b4a5Adam Cohen#include <assert.h> 11a02fdf1ba03fad71cc80a89dfc74b17456d5b4a5Adam Cohen#include <elf.h> 12a02fdf1ba03fad71cc80a89dfc74b17456d5b4a5Adam Cohen 13a02fdf1ba03fad71cc80a89dfc74b17456d5b4a5Adam Cohen#ifdef __arm__ 14a02fdf1ba03fad71cc80a89dfc74b17456d5b4a5Adam Cohentemplate <unsigned Bitwidth> 15a02fdf1ba03fad71cc80a89dfc74b17456d5b4a5Adam Coheninline StubLayout *ELFObject<Bitwidth>::getStubLayout() { 16a02fdf1ba03fad71cc80a89dfc74b17456d5b4a5Adam Cohen if (!stubs) { 17a02fdf1ba03fad71cc80a89dfc74b17456d5b4a5Adam Cohen stubs.reset(new StubLayout()); 18a02fdf1ba03fad71cc80a89dfc74b17456d5b4a5Adam Cohen } 19a02fdf1ba03fad71cc80a89dfc74b17456d5b4a5Adam Cohen return stubs.get(); 20a02fdf1ba03fad71cc80a89dfc74b17456d5b4a5Adam Cohen} 21a02fdf1ba03fad71cc80a89dfc74b17456d5b4a5Adam Cohen#endif 22a02fdf1ba03fad71cc80a89dfc74b17456d5b4a5Adam Cohen 23a02fdf1ba03fad71cc80a89dfc74b17456d5b4a5Adam Cohentemplate <unsigned Bitwidth> 24a02fdf1ba03fad71cc80a89dfc74b17456d5b4a5Adam Cohentemplate <typename Archiver> 25a02fdf1ba03fad71cc80a89dfc74b17456d5b4a5Adam Coheninline ELFObject<Bitwidth> * 26a02fdf1ba03fad71cc80a89dfc74b17456d5b4a5Adam CohenELFObject<Bitwidth>::read(Archiver &AR) { 27a02fdf1ba03fad71cc80a89dfc74b17456d5b4a5Adam Cohen llvm::OwningPtr<ELFObjectTy> object(new ELFObjectTy()); 28a02fdf1ba03fad71cc80a89dfc74b17456d5b4a5Adam Cohen 29a02fdf1ba03fad71cc80a89dfc74b17456d5b4a5Adam Cohen // Read header 30a02fdf1ba03fad71cc80a89dfc74b17456d5b4a5Adam Cohen object->header.reset(ELFHeaderTy::read(AR)); 31a02fdf1ba03fad71cc80a89dfc74b17456d5b4a5Adam Cohen if (!object->header) { 32a02fdf1ba03fad71cc80a89dfc74b17456d5b4a5Adam Cohen return 0; 33a02fdf1ba03fad71cc80a89dfc74b17456d5b4a5Adam Cohen } 34a02fdf1ba03fad71cc80a89dfc74b17456d5b4a5Adam Cohen 35a02fdf1ba03fad71cc80a89dfc74b17456d5b4a5Adam Cohen // Read section table 360e2de6d7187ef67ec00a2f2544450caa4a239c39Adam Cohen object->shtab.reset(ELFSectionHeaderTableTy::read(AR, object.get())); 37a02fdf1ba03fad71cc80a89dfc74b17456d5b4a5Adam Cohen 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#ifdef __arm__ 157 if ((result & 0xFF000000) != 0) { 158 out() << "far stub for: " << sym->getAddress() << " "; 159 void *stub = getStubLayout()->allocateStub((void *)sym->getAddress()); 160 if (!stub) { 161 out() << "unable to allocate stub." << "\n"; 162 exit(EXIT_FAILURE); 163 } 164 out() << "is at " << stub << "\n"; 165 S = ((uint32_t)stub) >> 2; 166 result = (S+A-P); 167 } 168#else 169 // TODO: Stub. 170 assert(((result & 0xFF000000) == 0) && "Too far, need stub."); 171#endif 172 *inst = ((result) & 0x00FFFFFF) | (*inst & 0xFF000000); 173 } 174 break; 175 case 44: // R_ARM_MOVT_ABS 176 S >>= 16; 177 case 43: // R_ARM_MOVW_ABS_NC 178 { 179 // No need sign extend. 180 A = ((*inst & 0xF0000) >> 4) | (*inst & 0xFFF); 181 uint32_t result = (S+A); 182 *inst = (((result) & 0xF000) << 4) | 183 ((result) & 0xFFF) | 184 (*inst & 0xFFF0F000); 185 } 186 break; 187 } 188 //llvm::errs() << "S: " << (void *)S << '\n'; 189 //llvm::errs() << "A: " << (void *)A << '\n'; 190 //llvm::errs() << "P: " << (void *)P << '\n'; 191 //llvm::errs() << "S+A: " << (void *)(S+A) << '\n'; 192 //llvm::errs() << "S+A-P: " << (void *)(S+A-P) << '\n'; 193 } 194} 195 196template <unsigned Bitwidth> 197inline void ELFObject<Bitwidth>:: 198relocateX86_64(void *(*find_sym)(void *context, char const *name), 199 void *context) { 200 assert(Bitwidth == 64 && "Only support X86_64."); 201 202 ELFSectionSymTabTy *symtab = 203 static_cast<ELFSectionSymTabTy *>(getSectionByName(".symtab")); 204 205 char const *name[] = {".text", ".eh_frame"}; 206 size_t size = sizeof(name) / sizeof(char const *); 207 208 for (size_t i = 0; i < size; ++i) { 209 ELFSectionRelTableTy *relatab = 210 static_cast<ELFSectionRelTableTy *>( 211 getSectionByName((std::string(".rela") + name[i]).c_str())); 212 ELFSectionProgBitsTy *text = 213 static_cast<ELFSectionProgBitsTy *>(getSectionByName(name[i])); 214 215 for (size_t i = 0; i < relatab->size(); ++i) { 216 // FIXME: Can not implement here, use Fixup! 217 ELFRelocTy *rela = (*relatab)[i]; 218 ELFSymbolTy *sym = (*symtab)[rela->getSymTabIndex()]; 219 220 //typedef uint64_t Inst_t; 221 typedef int32_t Inst_t; 222 Inst_t *inst = (Inst_t *)&(*text)[rela->getOffset()]; 223 Inst_t P = (Inst_t)(int64_t)inst; 224 Inst_t A = (Inst_t)(int64_t)rela->getAddend(); 225 Inst_t S = (Inst_t)(int64_t)sym->getAddress(); 226 227 if (S == 0) { 228 S = (Inst_t)(int64_t)find_sym(context, sym->getName()); 229 sym->setAddress((void *)S); 230 } 231 232 switch (rela->getType()) { 233 default: 234 assert(0 && "Not implemented relocation type."); 235 break; 236 237 case 2: // R_X86_64_PC32 238 *inst = (S+A-P); 239 break; 240 241 case 10: // R_X86_64_32 242 case 11: // R_X86_64_32S 243 *inst = (S+A); 244 break; 245 } 246 } 247 } 248} 249 250template <unsigned Bitwidth> 251inline void ELFObject<Bitwidth>:: 252relocateX86_32(void *(*find_sym)(void *context, char const *name), 253 void *context) { 254 assert(Bitwidth == 32 && "Only support X86."); 255 256 ELFSectionSymTabTy *symtab = 257 static_cast<ELFSectionSymTabTy *>(getSectionByName(".symtab")); 258 259 char const *name[] = {".text"}; 260 size_t const size = sizeof(name) / sizeof(char const *); 261 262 for (size_t i = 0; i < size; ++i) { 263 ELFSectionRelTableTy *reltab = 264 static_cast<ELFSectionRelTableTy *>( 265 getSectionByName((std::string(".rel") + name[i]).c_str())); 266 267 ELFSectionProgBitsTy *text = 268 static_cast<ELFSectionProgBitsTy *>(getSectionByName(name[i])); 269 270 for (size_t i = 0; i < reltab->size(); ++i) { 271 // FIXME: Can not implement here, use Fixup! 272 ELFRelocTy *rel = (*reltab)[i]; 273 ELFSymbolTy *sym = (*symtab)[rel->getSymTabIndex()]; 274 275 //typedef uint64_t Inst_t; 276 typedef int32_t Inst_t; 277 Inst_t *inst = (Inst_t *)&(*text)[rel->getOffset()]; 278 Inst_t P = (Inst_t)(uintptr_t)inst; 279 Inst_t A = (Inst_t)(uintptr_t)*inst; 280 Inst_t S = (Inst_t)(uintptr_t)sym->getAddress(); 281 282 if (S == 0) { 283 S = (Inst_t)(uintptr_t)find_sym(context, sym->getName()); 284 sym->setAddress((void *)S); 285 } 286 287 switch (rel->getType()) { 288 default: 289 assert(0 && "Not implemented relocation type."); 290 break; 291 292 case R_386_PC32: 293 *inst = (S+A-P); 294 break; 295 296 case R_386_32: 297 *inst = (S+A); 298 break; 299 } 300 } 301 } 302} 303 304template <unsigned Bitwidth> 305inline void ELFObject<Bitwidth>:: 306relocate(void *(*find_sym)(void *context, char const *name), void *context) { 307 switch (getHeader()->getMachine()) { 308 case EM_ARM: relocateARM(find_sym, context); break; 309 case EM_386: relocateX86_32(find_sym, context); break; 310 case EM_X86_64: relocateX86_64(find_sym, context); break; 311 312 default: 313 assert(0 && "Only support ARM and X86_64 relocation."); 314 break; 315 } 316 317 for (size_t i = 0; i < stab.size(); ++i) { 318 ELFSectionHeaderTy *sh = (*shtab)[i]; 319 if (sh && (sh->getType() == SHT_PROGBITS || 320 sh->getType() == SHT_NOBITS)) { 321 static_cast<ELFSectionBitsTy *>(stab[i])->memory_protect(); 322 } 323 } 324} 325 326template <unsigned Bitwidth> 327inline void ELFObject<Bitwidth>::print() const { 328 header->print(); 329 shtab->print(); 330 331 for (size_t i = 0; i < stab.size(); ++i) { 332 ELFSectionTy *sec = stab[i]; 333 if (sec) { 334 sec->print(); 335 } 336 } 337} 338 339#endif // ELF_OBJECT_HXX 340