find_exidx.c 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. /* Copyright (C) 2005 Free Software Foundation, Inc.
  2. This file is part of the GNU C Library.
  3. The GNU C Library is free software; you can redistribute it and/or
  4. modify it under the terms of the GNU Lesser General Public
  5. License as published by the Free Software Foundation; either
  6. version 2.1 of the License, or (at your option) any later version.
  7. The GNU C Library is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  10. Lesser General Public License for more details.
  11. You should have received a copy of the GNU Lesser General Public
  12. License along with the GNU C Library; if not, see
  13. <http://www.gnu.org/licenses/>. */
  14. #include <link.h>
  15. #include <unwind.h>
  16. #if __FDPIC__
  17. #include <bits/elf-fdpic.h>
  18. static __always_inline int
  19. __dl_addr_in_loadaddr(void *p, struct elf32_fdpic_loadaddr loadaddr)
  20. {
  21. struct elf32_fdpic_loadmap *map = loadaddr.map;
  22. int c;
  23. for (c = 0; c < map->nsegs; c++)
  24. if ((void *)map->segs[c].addr <= p &&
  25. (char *)p < (char *)map->segs[c].addr + map->segs[c].p_memsz)
  26. return 1;
  27. return 0;
  28. }
  29. #endif
  30. struct unw_eh_callback_data
  31. {
  32. _Unwind_Ptr pc;
  33. _Unwind_Ptr exidx_start;
  34. int exidx_len;
  35. };
  36. /* Callback to determins if the PC lies within an object, and remember the
  37. location of the exception index table if it does. */
  38. static int
  39. find_exidx_callback (struct dl_phdr_info * info, size_t size, void * ptr)
  40. {
  41. #if __FDPIC__
  42. struct unw_eh_callback_data * data;
  43. const ElfW(Phdr) *phdr;
  44. int i;
  45. int match = 0;
  46. data = (struct unw_eh_callback_data *) ptr;
  47. if (__dl_addr_in_loadaddr((void *) data->pc, info->dlpi_addr)) {
  48. match = 1;
  49. phdr = info->dlpi_phdr;
  50. for (i = info->dlpi_phnum; i > 0; i--, phdr++) {
  51. if (phdr->p_type == PT_ARM_EXIDX) {
  52. data->exidx_start = (_Unwind_Ptr) __RELOC_POINTER(phdr->p_vaddr, info->dlpi_addr);
  53. data->exidx_len = phdr->p_memsz;
  54. }
  55. }
  56. }
  57. return match;
  58. #else
  59. struct unw_eh_callback_data * data;
  60. const ElfW(Phdr) *phdr;
  61. int i;
  62. int match;
  63. _Unwind_Ptr load_base;
  64. data = (struct unw_eh_callback_data *) ptr;
  65. load_base = info->dlpi_addr;
  66. phdr = info->dlpi_phdr;
  67. match = 0;
  68. for (i = info->dlpi_phnum; i > 0; i--, phdr++)
  69. {
  70. if (phdr->p_type == PT_LOAD)
  71. {
  72. _Unwind_Ptr vaddr = phdr->p_vaddr + load_base;
  73. if (data->pc >= vaddr && data->pc < vaddr + phdr->p_memsz)
  74. match = 1;
  75. }
  76. else if (phdr->p_type == PT_ARM_EXIDX)
  77. {
  78. data->exidx_start = (_Unwind_Ptr) (phdr->p_vaddr + load_base);
  79. data->exidx_len = phdr->p_memsz;
  80. }
  81. }
  82. return match;
  83. #endif
  84. }
  85. /* Find the exception index table containing PC. */
  86. _Unwind_Ptr __gnu_Unwind_Find_exidx (_Unwind_Ptr pc, int * pcount);
  87. _Unwind_Ptr __gnu_Unwind_Find_exidx (_Unwind_Ptr pc, int * pcount)
  88. {
  89. struct unw_eh_callback_data data;
  90. data.pc = pc;
  91. data.exidx_start = 0;
  92. if (dl_iterate_phdr (find_exidx_callback, &data) <= 0)
  93. return 0;
  94. *pcount = data.exidx_len / 8;
  95. return data.exidx_start;
  96. }