unwind-pe.h 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305
  1. /* Exception handling and frame unwind runtime interface routines.
  2. Copyright (C) 2001-2019 Free Software Foundation, Inc.
  3. This file is part of the GNU C Library.
  4. The GNU C Library is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU Lesser General Public
  6. License as published by the Free Software Foundation; either
  7. version 2.1 of the License, or (at your option) any later version.
  8. The GNU C Library is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. Lesser General Public License for more details.
  12. You should have received a copy of the GNU Lesser General Public
  13. License along with the GNU C Library; if not, see
  14. <http://www.gnu.org/licenses/>. */
  15. /* @@@ Really this should be out of line, but this also causes link
  16. compatibility problems with the base ABI. This is slightly better
  17. than duplicating code, however. */
  18. /* If using C++, references to abort have to be qualified with std::. */
  19. #ifdef __cplusplus
  20. #define __gxx_abort std::abort
  21. #else
  22. #define __gxx_abort abort
  23. #endif
  24. /* Pointer encodings, from dwarf2.h. */
  25. #define DW_EH_PE_absptr 0x00
  26. #define DW_EH_PE_omit 0xff
  27. #define DW_EH_PE_uleb128 0x01
  28. #define DW_EH_PE_udata2 0x02
  29. #define DW_EH_PE_udata4 0x03
  30. #define DW_EH_PE_udata8 0x04
  31. #define DW_EH_PE_sleb128 0x09
  32. #define DW_EH_PE_sdata2 0x0A
  33. #define DW_EH_PE_sdata4 0x0B
  34. #define DW_EH_PE_sdata8 0x0C
  35. #define DW_EH_PE_signed 0x08
  36. #define DW_EH_PE_pcrel 0x10
  37. #define DW_EH_PE_textrel 0x20
  38. #define DW_EH_PE_datarel 0x30
  39. #define DW_EH_PE_funcrel 0x40
  40. #define DW_EH_PE_aligned 0x50
  41. #define DW_EH_PE_indirect 0x80
  42. #if defined(_LIBC)
  43. /* Prototypes. */
  44. extern unsigned int size_of_encoded_value (unsigned char encoding)
  45. attribute_hidden;
  46. extern const unsigned char *read_encoded_value_with_base
  47. (unsigned char encoding, _Unwind_Ptr base,
  48. const unsigned char *p, _Unwind_Ptr *val)
  49. attribute_hidden;
  50. extern const unsigned char * read_encoded_value
  51. (struct _Unwind_Context *context, unsigned char encoding,
  52. const unsigned char *p, _Unwind_Ptr *val)
  53. attribute_hidden;
  54. extern const unsigned char * read_uleb128 (const unsigned char *p,
  55. _Unwind_Word *val)
  56. attribute_hidden;
  57. extern const unsigned char * read_sleb128 (const unsigned char *p,
  58. _Unwind_Sword *val)
  59. attribute_hidden;
  60. #endif
  61. #if defined(_LIBC) && defined(_LIBC_DEFINITIONS)
  62. #ifdef _LIBC
  63. #define STATIC
  64. #else
  65. #define STATIC static
  66. #endif
  67. /* Given an encoding, return the number of bytes the format occupies.
  68. This is only defined for fixed-size encodings, and so does not
  69. include leb128. */
  70. STATIC unsigned int
  71. size_of_encoded_value (unsigned char encoding)
  72. {
  73. if (encoding == DW_EH_PE_omit)
  74. return 0;
  75. switch (encoding & 0x07)
  76. {
  77. case DW_EH_PE_absptr:
  78. return sizeof (void *);
  79. case DW_EH_PE_udata2:
  80. return 2;
  81. case DW_EH_PE_udata4:
  82. return 4;
  83. case DW_EH_PE_udata8:
  84. return 8;
  85. }
  86. __gxx_abort ();
  87. }
  88. #ifndef NO_BASE_OF_ENCODED_VALUE
  89. /* Given an encoding and an _Unwind_Context, return the base to which
  90. the encoding is relative. This base may then be passed to
  91. read_encoded_value_with_base for use when the _Unwind_Context is
  92. not available. */
  93. STATIC _Unwind_Ptr
  94. base_of_encoded_value (unsigned char encoding, struct _Unwind_Context *context)
  95. {
  96. if (encoding == DW_EH_PE_omit)
  97. return 0;
  98. switch (encoding & 0x70)
  99. {
  100. case DW_EH_PE_absptr:
  101. case DW_EH_PE_pcrel:
  102. case DW_EH_PE_aligned:
  103. return 0;
  104. case DW_EH_PE_textrel:
  105. return _Unwind_GetTextRelBase (context);
  106. case DW_EH_PE_datarel:
  107. return _Unwind_GetDataRelBase (context);
  108. case DW_EH_PE_funcrel:
  109. return _Unwind_GetRegionStart (context);
  110. }
  111. __gxx_abort ();
  112. }
  113. #endif
  114. /* Read an unsigned leb128 value from P, store the value in VAL, return
  115. P incremented past the value. We assume that a word is large enough to
  116. hold any value so encoded; if it is smaller than a pointer on some target,
  117. pointers should not be leb128 encoded on that target. */
  118. STATIC const unsigned char *
  119. read_uleb128 (const unsigned char *p, _Unwind_Word *val)
  120. {
  121. unsigned int shift = 0;
  122. unsigned char byte;
  123. _Unwind_Word result;
  124. result = 0;
  125. do
  126. {
  127. byte = *p++;
  128. result |= (byte & 0x7f) << shift;
  129. shift += 7;
  130. }
  131. while (byte & 0x80);
  132. *val = result;
  133. return p;
  134. }
  135. /* Similar, but read a signed leb128 value. */
  136. STATIC const unsigned char *
  137. read_sleb128 (const unsigned char *p, _Unwind_Sword *val)
  138. {
  139. unsigned int shift = 0;
  140. unsigned char byte;
  141. _Unwind_Word result;
  142. result = 0;
  143. do
  144. {
  145. byte = *p++;
  146. result |= (byte & 0x7f) << shift;
  147. shift += 7;
  148. }
  149. while (byte & 0x80);
  150. /* Sign-extend a negative value. */
  151. if (shift < 8 * sizeof(result) && (byte & 0x40) != 0)
  152. result |= -(1L << shift);
  153. *val = (_Unwind_Sword) result;
  154. return p;
  155. }
  156. /* Load an encoded value from memory at P. The value is returned in VAL;
  157. The function returns P incremented past the value. BASE is as given
  158. by base_of_encoded_value for this encoding in the appropriate context. */
  159. STATIC const unsigned char *
  160. read_encoded_value_with_base (unsigned char encoding, _Unwind_Ptr base,
  161. const unsigned char *p, _Unwind_Ptr *val)
  162. {
  163. union unaligned
  164. {
  165. void *ptr;
  166. unsigned u2 __attribute__ ((mode (HI)));
  167. unsigned u4 __attribute__ ((mode (SI)));
  168. unsigned u8 __attribute__ ((mode (DI)));
  169. signed s2 __attribute__ ((mode (HI)));
  170. signed s4 __attribute__ ((mode (SI)));
  171. signed s8 __attribute__ ((mode (DI)));
  172. } __attribute__((__packed__));
  173. union unaligned *u = (union unaligned *) p;
  174. _Unwind_Internal_Ptr result;
  175. if (encoding == DW_EH_PE_aligned)
  176. {
  177. _Unwind_Internal_Ptr a = (_Unwind_Internal_Ptr) p;
  178. a = (a + sizeof (void *) - 1) & - sizeof(void *);
  179. result = *(_Unwind_Internal_Ptr *) a;
  180. p = (const unsigned char *) (a + sizeof (void *));
  181. }
  182. else
  183. {
  184. switch (encoding & 0x0f)
  185. {
  186. case DW_EH_PE_absptr:
  187. result = (_Unwind_Internal_Ptr) u->ptr;
  188. p += sizeof (void *);
  189. break;
  190. case DW_EH_PE_uleb128:
  191. {
  192. _Unwind_Word tmp;
  193. p = read_uleb128 (p, &tmp);
  194. result = (_Unwind_Internal_Ptr) tmp;
  195. }
  196. break;
  197. case DW_EH_PE_sleb128:
  198. {
  199. _Unwind_Sword tmp;
  200. p = read_sleb128 (p, &tmp);
  201. result = (_Unwind_Internal_Ptr) tmp;
  202. }
  203. break;
  204. case DW_EH_PE_udata2:
  205. result = u->u2;
  206. p += 2;
  207. break;
  208. case DW_EH_PE_udata4:
  209. result = u->u4;
  210. p += 4;
  211. break;
  212. case DW_EH_PE_udata8:
  213. result = u->u8;
  214. p += 8;
  215. break;
  216. case DW_EH_PE_sdata2:
  217. result = u->s2;
  218. p += 2;
  219. break;
  220. case DW_EH_PE_sdata4:
  221. result = u->s4;
  222. p += 4;
  223. break;
  224. case DW_EH_PE_sdata8:
  225. result = u->s8;
  226. p += 8;
  227. break;
  228. default:
  229. __gxx_abort ();
  230. }
  231. if (result != 0)
  232. {
  233. result += ((encoding & 0x70) == DW_EH_PE_pcrel
  234. ? (_Unwind_Internal_Ptr) u : base);
  235. if (encoding & DW_EH_PE_indirect)
  236. result = *(_Unwind_Internal_Ptr *) result;
  237. }
  238. }
  239. *val = result;
  240. return p;
  241. }
  242. #ifndef NO_BASE_OF_ENCODED_VALUE
  243. /* Like read_encoded_value_with_base, but get the base from the context
  244. rather than providing it directly. */
  245. STATIC const unsigned char *
  246. read_encoded_value (struct _Unwind_Context *context, unsigned char encoding,
  247. const unsigned char *p, _Unwind_Ptr *val)
  248. {
  249. return read_encoded_value_with_base (encoding,
  250. base_of_encoded_value (encoding, context),
  251. p, val);
  252. }
  253. #endif
  254. #endif /* _LIBC */