find_exidx.c 963 B

123456789101112131415161718192021222324252627282930313233343536373839404142
  1. #define _GNU_SOURCE
  2. #include <link.h>
  3. #include <stdint.h>
  4. struct find_exidx_data {
  5. uintptr_t pc, exidx_start;
  6. int exidx_len;
  7. };
  8. static int find_exidx(struct dl_phdr_info *info, size_t size, void *ptr)
  9. {
  10. struct find_exidx_data *data = ptr;
  11. const ElfW(Phdr) *phdr = info->dlpi_phdr;
  12. uintptr_t addr, exidx_start = 0;
  13. int i, match = 0, exidx_len = 0;
  14. for (i = info->dlpi_phnum; i > 0; i--, phdr++) {
  15. addr = info->dlpi_addr + phdr->p_vaddr;
  16. switch (phdr->p_type) {
  17. case PT_LOAD:
  18. match |= data->pc >= addr && data->pc < addr + phdr->p_memsz;
  19. break;
  20. case PT_ARM_EXIDX:
  21. exidx_start = addr;
  22. exidx_len = phdr->p_memsz;
  23. break;
  24. }
  25. }
  26. data->exidx_start = exidx_start;
  27. data->exidx_len = exidx_len;
  28. return match;
  29. }
  30. uintptr_t __gnu_Unwind_Find_exidx(uintptr_t pc, int *pcount)
  31. {
  32. struct find_exidx_data data;
  33. data.pc = pc;
  34. if (dl_iterate_phdr(find_exidx, &data) <= 0)
  35. return 0;
  36. *pcount = data.exidx_len / 8;
  37. return data.exidx_start;
  38. }