1 /* $OpenBSD: exidx.c,v 1.2 2016/09/18 00:19:37 jsg Exp $ */ 2 /* 3 * Copyright (c) 2016 Mark Kettenis <kettenis@openbsd.org> 4 * 5 * Permission to use, copy, modify, and distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18 #include <sys/types.h> 19 #include <link.h> 20 #include <stddef.h> 21 22 void *dl_unwind_find_exidx(const void *pc, int *pcount) __attribute__((weak)); 23 24 struct exidx_data { 25 u_long pc; 26 void *exidx; 27 int *pcount; 28 }; 29 30 struct exidx_entry { 31 uint32_t data[2]; 32 }; 33 34 static int 35 find_exidx(struct dl_phdr_info *info, size_t size, void *p) 36 { 37 struct exidx_data *data = p; 38 const Elf_Phdr *phdr; 39 void *exidx; 40 int count = 0; 41 int found = 0; 42 int i; 43 44 for (i = 0; i < info->dlpi_phnum; i++) { 45 phdr = &info->dlpi_phdr[i]; 46 if (data->pc >= info->dlpi_addr + phdr->p_vaddr && 47 data->pc < info->dlpi_addr + phdr->p_vaddr + phdr->p_memsz) 48 found = 1; 49 if (phdr->p_type == PT_ARM_EXIDX) { 50 exidx = (void *)(info->dlpi_addr + phdr->p_vaddr); 51 count = phdr->p_memsz / sizeof(struct exidx_entry); 52 } 53 } 54 55 if (found && count > 0) { 56 data->exidx = exidx; 57 *data->pcount = count; 58 return 1; 59 } 60 61 return 0; 62 } 63 64 void * 65 dl_unwind_find_exidx(const void *pc, int *pcount) 66 { 67 struct exidx_data data; 68 69 data.pc = (u_long)pc; 70 data.pcount = pcount; 71 if (dl_iterate_phdr(find_exidx, &data)) 72 return data.exidx; 73 return NULL; 74 } 75 76 __strong_alias(__gnu_Unwind_Find_exidx, dl_unwind_find_exidx); 77