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