reloc.h 1.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556
  1. #include <string.h>
  2. #include <elf.h>
  3. #define LDSO_ARCH "powerpc"
  4. #define IS_COPY(x) ((x)==R_PPC_COPY)
  5. #define IS_PLT(x) ((x)==R_PPC_JMP_SLOT)
  6. // see linux' arch/powerpc/include/asm/elf.h
  7. static inline int do_single_reloc(
  8. struct dso *self, unsigned char *base_addr,
  9. size_t *reloc_addr, int type, size_t addend,
  10. Sym *sym, size_t sym_size,
  11. struct symdef def, size_t sym_val)
  12. {
  13. switch(type) {
  14. case R_PPC_GLOB_DAT:
  15. case R_PPC_JMP_SLOT:
  16. case R_PPC_ADDR32:
  17. *reloc_addr = sym_val + addend;
  18. break;
  19. case R_PPC_COPY:
  20. memcpy(reloc_addr, (void *)sym_val, sym_size);
  21. break;
  22. case R_PPC_RELATIVE:
  23. *reloc_addr = (size_t)base_addr + addend;
  24. break;
  25. case R_PPC_DTPMOD32:
  26. *reloc_addr = def.dso ? def.dso->tls_id : self->tls_id;
  27. break;
  28. case R_PPC_DTPREL32:
  29. *reloc_addr = def.sym->st_value + addend;
  30. break;
  31. case R_PPC_TPREL32:
  32. *reloc_addr += def.sym
  33. ? def.sym->st_value + def.dso->tls_offset - 0x7000
  34. : self->tls_offset - 0x7000;
  35. break;
  36. }
  37. return 0;
  38. }
  39. void __reloc_self(int c, size_t *a, size_t *dynv)
  40. {
  41. char *base;
  42. size_t t[20], n;
  43. for (a+=c+1; *a; a++);
  44. for (a++; *a; a+=2) if (*a<20) t[*a] = a[1];
  45. base = (char *)t[AT_BASE];
  46. if (!base) base = (char *)(t[AT_PHDR] & -t[AT_PAGESZ]);
  47. for (a=dynv; *a; a+=2) if (*a<20) t[*a] = a[1];
  48. n = t[DT_RELASZ];
  49. for (a=(void *)(base+t[DT_RELA]); n; a+=3, n-=12)
  50. if (a[1]%256 == R_PPC_RELATIVE)
  51. *(size_t *)(base+a[0]) = (size_t)base + a[2];
  52. }