Index: fusl/arch/arm/src/find_exidx.c |
diff --git a/fusl/arch/arm/src/find_exidx.c b/fusl/arch/arm/src/find_exidx.c |
new file mode 100644 |
index 0000000000000000000000000000000000000000..77c4472bf60f8690d46ab81284168aa178c29482 |
--- /dev/null |
+++ b/fusl/arch/arm/src/find_exidx.c |
@@ -0,0 +1,42 @@ |
+#define _GNU_SOURCE |
+#include <link.h> |
+#include <stdint.h> |
+ |
+struct find_exidx_data { |
+ uintptr_t pc, exidx_start; |
+ int exidx_len; |
+}; |
+ |
+static int find_exidx(struct dl_phdr_info *info, size_t size, void *ptr) |
+{ |
+ struct find_exidx_data *data = ptr; |
+ const ElfW(Phdr) *phdr = info->dlpi_phdr; |
+ uintptr_t addr, exidx_start = 0; |
+ int i, match = 0, exidx_len = 0; |
+ |
+ for (i = info->dlpi_phnum; i > 0; i--, phdr++) { |
+ addr = info->dlpi_addr + phdr->p_vaddr; |
+ switch (phdr->p_type) { |
+ case PT_LOAD: |
+ match |= data->pc >= addr && data->pc < addr + phdr->p_memsz; |
+ break; |
+ case PT_ARM_EXIDX: |
+ exidx_start = addr; |
+ exidx_len = phdr->p_memsz; |
+ break; |
+ } |
+ } |
+ data->exidx_start = exidx_start; |
+ data->exidx_len = exidx_len; |
+ return match; |
+} |
+ |
+uintptr_t __gnu_Unwind_Find_exidx(uintptr_t pc, int *pcount) |
+{ |
+ struct find_exidx_data data; |
+ data.pc = pc; |
+ if (dl_iterate_phdr(find_exidx, &data) <= 0) |
+ return 0; |
+ *pcount = data.exidx_len / 8; |
+ return data.exidx_start; |
+} |