Rev 4383 | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 4383 | Rev 5963 | ||
---|---|---|---|
Line 1... | Line 1... | ||
1 | /* DWARF2 exception handling and frame unwind runtime interface routines. |
1 | /* DWARF2 exception handling and frame unwind runtime interface routines. |
2 | Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, |
- | |
3 | 2008, 2009, 2010 Free Software Foundation, Inc. |
2 | Copyright (C) 1997-2013 Free Software Foundation, Inc. |
Line 4... | Line 3... | ||
4 | 3 | ||
Line 5... | Line 4... | ||
5 | This file is part of GCC. |
4 | This file is part of GCC. |
6 | 5 | ||
Line 53... | Line 52... | ||
53 | 52 | ||
54 | #ifndef DWARF_REG_TO_UNWIND_COLUMN |
53 | #ifndef DWARF_REG_TO_UNWIND_COLUMN |
55 | #define DWARF_REG_TO_UNWIND_COLUMN(REGNO) (REGNO) |
54 | #define DWARF_REG_TO_UNWIND_COLUMN(REGNO) (REGNO) |
Line -... | Line 55... | ||
- | 55 | #endif |
|
- | 56 | ||
- | 57 | /* ??? For the public function interfaces, we tend to gcc_assert that the |
|
- | 58 | column numbers are in range. For the dwarf2 unwind info this does happen, |
|
- | 59 | although so far in a case that doesn't actually matter. |
|
- | 60 | ||
- | 61 | See PR49146, in which a call from x86_64 ms abi to x86_64 unix abi stores |
|
- | 62 | the call-saved xmm registers and annotates them. We havn't bothered |
|
- | 63 | providing support for the xmm registers for the x86_64 port primarily |
|
- | 64 | because the 64-bit windows targets don't use dwarf2 unwind, using sjlj or |
|
- | 65 | SEH instead. Adding the support for unix targets would generally be a |
|
- | 66 | waste. However, some runtime libraries supplied with ICC do contain such |
|
- | 67 | an unorthodox transition, as well as the unwind info to match. This loss |
|
- | 68 | of register restoration doesn't matter in practice, because the exception |
|
- | 69 | is caught in the native unix abi, where all of the xmm registers are |
|
- | 70 | call clobbered. |
|
- | 71 | ||
- | 72 | Ideally, we'd record some bit to notice when we're failing to restore some |
|
- | 73 | register recorded in the unwind info, but to do that we need annotation on |
|
- | 74 | the unix->ms abi edge, so that we know when the register data may be |
|
- | 75 | discarded. And since this edge is also within the ICC library, we're |
|
- | 76 | unlikely to be able to get the new annotation. |
|
- | 77 | ||
- | 78 | Barring a magic solution to restore the ms abi defined 128-bit xmm registers |
|
- | 79 | (as distictly opposed to the full runtime width) without causing extra |
|
- | 80 | overhead for normal unix abis, the best solution seems to be to simply |
|
- | 81 | ignore unwind data for unknown columns. */ |
|
- | 82 | ||
- | 83 | #define UNWIND_COLUMN_IN_RANGE(x) \ |
|
- | 84 | __builtin_expect((x) <= DWARF_FRAME_REGISTERS, 1) |
|
- | 85 | ||
- | 86 | #ifdef REG_VALUE_IN_UNWIND_CONTEXT |
|
- | 87 | typedef _Unwind_Word _Unwind_Context_Reg_Val; |
|
- | 88 | ||
- | 89 | #ifndef ASSUME_EXTENDED_UNWIND_CONTEXT |
|
- | 90 | #define ASSUME_EXTENDED_UNWIND_CONTEXT 1 |
|
- | 91 | #endif |
|
- | 92 | ||
- | 93 | static inline _Unwind_Word |
|
- | 94 | _Unwind_Get_Unwind_Word (_Unwind_Context_Reg_Val val) |
|
- | 95 | { |
|
- | 96 | return val; |
|
- | 97 | } |
|
- | 98 | ||
- | 99 | static inline _Unwind_Context_Reg_Val |
|
- | 100 | _Unwind_Get_Unwind_Context_Reg_Val (_Unwind_Word val) |
|
- | 101 | { |
|
- | 102 | return val; |
|
- | 103 | } |
|
- | 104 | #else |
|
- | 105 | typedef void *_Unwind_Context_Reg_Val; |
|
- | 106 | ||
- | 107 | static inline _Unwind_Word |
|
- | 108 | _Unwind_Get_Unwind_Word (_Unwind_Context_Reg_Val val) |
|
- | 109 | { |
|
- | 110 | return (_Unwind_Word) (_Unwind_Internal_Ptr) val; |
|
- | 111 | } |
|
- | 112 | ||
- | 113 | static inline _Unwind_Context_Reg_Val |
|
- | 114 | _Unwind_Get_Unwind_Context_Reg_Val (_Unwind_Word val) |
|
- | 115 | { |
|
- | 116 | return (_Unwind_Context_Reg_Val) (_Unwind_Internal_Ptr) val; |
|
- | 117 | } |
|
- | 118 | #endif |
|
- | 119 | ||
- | 120 | #ifndef ASSUME_EXTENDED_UNWIND_CONTEXT |
|
- | 121 | #define ASSUME_EXTENDED_UNWIND_CONTEXT 0 |
|
56 | #endif |
122 | #endif |
57 | 123 | ||
58 | /* This is the register and unwind state for a particular frame. This |
124 | /* This is the register and unwind state for a particular frame. This |
59 | provides the information necessary to unwind up past a frame and return |
125 | provides the information necessary to unwind up past a frame and return |
60 | to its caller. */ |
126 | to its caller. */ |
61 | struct _Unwind_Context |
127 | struct _Unwind_Context |
62 | { |
128 | { |
63 | void *reg[DWARF_FRAME_REGISTERS+1]; |
129 | _Unwind_Context_Reg_Val reg[DWARF_FRAME_REGISTERS+1]; |
64 | void *cfa; |
130 | void *cfa; |
65 | void *ra; |
131 | void *ra; |
66 | void *lsda; |
132 | void *lsda; |
Line 141... | Line 207... | ||
141 | } |
207 | } |
Line 142... | Line 208... | ||
142 | 208 | ||
143 | static inline _Unwind_Word |
209 | static inline _Unwind_Word |
144 | _Unwind_IsExtendedContext (struct _Unwind_Context *context) |
210 | _Unwind_IsExtendedContext (struct _Unwind_Context *context) |
- | 211 | { |
|
145 | { |
212 | return (ASSUME_EXTENDED_UNWIND_CONTEXT |
146 | return context->flags & EXTENDED_CONTEXT_BIT; |
213 | || (context->flags & EXTENDED_CONTEXT_BIT)); |
147 | } |
214 | } |
148 | 215 | ||
Line 149... | Line 216... | ||
149 | /* Get the value of register INDEX as saved in CONTEXT. */ |
216 | /* Get the value of register INDEX as saved in CONTEXT. */ |
150 | 217 | ||
151 | inline _Unwind_Word |
218 | inline _Unwind_Word |
152 | _Unwind_GetGR (struct _Unwind_Context *context, int index) |
219 | _Unwind_GetGR (struct _Unwind_Context *context, int index) |
153 | { |
220 | { |
Line 154... | Line 221... | ||
154 | int size; |
221 | int size; |
155 | void *ptr; |
222 | _Unwind_Context_Reg_Val val; |
156 | 223 | ||
157 | #ifdef DWARF_ZERO_REG |
224 | #ifdef DWARF_ZERO_REG |
Line 158... | Line 225... | ||
158 | if (index == DWARF_ZERO_REG) |
225 | if (index == DWARF_ZERO_REG) |
159 | return 0; |
226 | return 0; |
160 | #endif |
227 | #endif |
161 | 228 | ||
Line 162... | Line 229... | ||
162 | index = DWARF_REG_TO_UNWIND_COLUMN (index); |
229 | index = DWARF_REG_TO_UNWIND_COLUMN (index); |
163 | gcc_assert (index < (int) sizeof(dwarf_reg_size_table)); |
230 | gcc_assert (index < (int) sizeof(dwarf_reg_size_table)); |
Line 164... | Line 231... | ||
164 | size = dwarf_reg_size_table[index]; |
231 | size = dwarf_reg_size_table[index]; |
165 | ptr = context->reg[index]; |
232 | val = context->reg[index]; |
166 | 233 | ||
167 | if (_Unwind_IsExtendedContext (context) && context->by_value[index]) |
234 | if (_Unwind_IsExtendedContext (context) && context->by_value[index]) |
168 | return (_Unwind_Word) (_Unwind_Internal_Ptr) ptr; |
235 | return _Unwind_Get_Unwind_Word (val); |
169 | 236 | ||
170 | /* This will segfault if the register hasn't been saved. */ |
237 | /* This will segfault if the register hasn't been saved. */ |
171 | if (size == sizeof(_Unwind_Ptr)) |
238 | if (size == sizeof(_Unwind_Ptr)) |
172 | return * (_Unwind_Ptr *) ptr; |
239 | return * (_Unwind_Ptr *) (_Unwind_Internal_Ptr) val; |
Line 173... | Line 240... | ||
173 | else |
240 | else |
174 | { |
241 | { |
Line 203... | Line 270... | ||
203 | gcc_assert (index < (int) sizeof(dwarf_reg_size_table)); |
270 | gcc_assert (index < (int) sizeof(dwarf_reg_size_table)); |
204 | size = dwarf_reg_size_table[index]; |
271 | size = dwarf_reg_size_table[index]; |
Line 205... | Line 272... | ||
205 | 272 | ||
206 | if (_Unwind_IsExtendedContext (context) && context->by_value[index]) |
273 | if (_Unwind_IsExtendedContext (context) && context->by_value[index]) |
207 | { |
274 | { |
208 | context->reg[index] = (void *) (_Unwind_Internal_Ptr) val; |
275 | context->reg[index] = _Unwind_Get_Unwind_Context_Reg_Val (val); |
209 | return; |
276 | return; |
Line 210... | Line 277... | ||
210 | } |
277 | } |
Line 211... | Line 278... | ||
211 | 278 | ||
212 | ptr = context->reg[index]; |
279 | ptr = (void *) (_Unwind_Internal_Ptr) context->reg[index]; |
213 | 280 | ||
214 | if (size == sizeof(_Unwind_Ptr)) |
281 | if (size == sizeof(_Unwind_Ptr)) |
Line 226... | Line 293... | ||
226 | _Unwind_GetGRPtr (struct _Unwind_Context *context, int index) |
293 | _Unwind_GetGRPtr (struct _Unwind_Context *context, int index) |
227 | { |
294 | { |
228 | index = DWARF_REG_TO_UNWIND_COLUMN (index); |
295 | index = DWARF_REG_TO_UNWIND_COLUMN (index); |
229 | if (_Unwind_IsExtendedContext (context) && context->by_value[index]) |
296 | if (_Unwind_IsExtendedContext (context) && context->by_value[index]) |
230 | return &context->reg[index]; |
297 | return &context->reg[index]; |
231 | return context->reg[index]; |
298 | return (void *) (_Unwind_Internal_Ptr) context->reg[index]; |
232 | } |
299 | } |
Line 233... | Line 300... | ||
233 | 300 | ||
Line 234... | Line 301... | ||
234 | /* Set the pointer to a register INDEX as saved in CONTEXT. */ |
301 | /* Set the pointer to a register INDEX as saved in CONTEXT. */ |
235 | 302 | ||
236 | static inline void |
303 | static inline void |
237 | _Unwind_SetGRPtr (struct _Unwind_Context *context, int index, void *p) |
304 | _Unwind_SetGRPtr (struct _Unwind_Context *context, int index, void *p) |
238 | { |
305 | { |
239 | index = DWARF_REG_TO_UNWIND_COLUMN (index); |
306 | index = DWARF_REG_TO_UNWIND_COLUMN (index); |
240 | if (_Unwind_IsExtendedContext (context)) |
307 | if (_Unwind_IsExtendedContext (context)) |
241 | context->by_value[index] = 0; |
308 | context->by_value[index] = 0; |
Line 242... | Line 309... | ||
242 | context->reg[index] = p; |
309 | context->reg[index] = (_Unwind_Context_Reg_Val) (_Unwind_Internal_Ptr) p; |
Line 243... | Line 310... | ||
243 | } |
310 | } |
244 | 311 | ||
245 | /* Overwrite the saved value for register INDEX in CONTEXT with VAL. */ |
312 | /* Overwrite the saved value for register INDEX in CONTEXT with VAL. */ |
246 | 313 | ||
247 | static inline void |
314 | static inline void |
248 | _Unwind_SetGRValue (struct _Unwind_Context *context, int index, |
315 | _Unwind_SetGRValue (struct _Unwind_Context *context, int index, |
- | 316 | _Unwind_Word val) |
|
249 | _Unwind_Word val) |
317 | { |
Line 250... | Line 318... | ||
250 | { |
318 | index = DWARF_REG_TO_UNWIND_COLUMN (index); |
251 | index = DWARF_REG_TO_UNWIND_COLUMN (index); |
319 | gcc_assert (index < (int) sizeof(dwarf_reg_size_table)); |
252 | gcc_assert (index < (int) sizeof(dwarf_reg_size_table)); |
320 | /* Return column size may be smaller than _Unwind_Context_Reg_Val. */ |
Line 253... | Line 321... | ||
253 | gcc_assert (dwarf_reg_size_table[index] == sizeof (_Unwind_Ptr)); |
321 | gcc_assert (dwarf_reg_size_table[index] <= sizeof (_Unwind_Context_Reg_Val)); |
254 | 322 | ||
Line 354... | Line 422... | ||
354 | fs->eh_ptr = read_pointer (p); |
422 | fs->eh_ptr = read_pointer (p); |
355 | p += sizeof (void *); |
423 | p += sizeof (void *); |
356 | aug += 2; |
424 | aug += 2; |
357 | } |
425 | } |
Line -... | Line 426... | ||
- | 426 | ||
- | 427 | /* After the augmentation resp. pointer for "eh" augmentation |
|
- | 428 | follows for CIE version >= 4 address size byte and |
|
- | 429 | segment size byte. */ |
|
- | 430 | if (__builtin_expect (cie->version >= 4, 0)) |
|
- | 431 | { |
|
- | 432 | if (p[0] != sizeof (void *) || p[1] != 0) |
|
- | 433 | return NULL; |
|
- | 434 | p += 2; |
|
358 | 435 | } |
|
359 | /* Immediately following the augmentation are the code and |
436 | /* Immediately following this are the code and |
360 | data alignment and return address column. */ |
437 | data alignment and return address column. */ |
361 | p = read_uleb128 (p, &utmp); |
438 | p = read_uleb128 (p, &utmp); |
362 | fs->code_align = (_Unwind_Word)utmp; |
439 | fs->code_align = (_Unwind_Word)utmp; |
363 | p = read_sleb128 (p, &stmp); |
440 | p = read_sleb128 (p, &stmp); |
Line 886... | Line 963... | ||
886 | else if ((insn & 0xc0) == DW_CFA_offset) |
963 | else if ((insn & 0xc0) == DW_CFA_offset) |
887 | { |
964 | { |
888 | reg = insn & 0x3f; |
965 | reg = insn & 0x3f; |
889 | insn_ptr = read_uleb128 (insn_ptr, &utmp); |
966 | insn_ptr = read_uleb128 (insn_ptr, &utmp); |
890 | offset = (_Unwind_Sword) utmp * fs->data_align; |
967 | offset = (_Unwind_Sword) utmp * fs->data_align; |
891 | fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].how |
968 | reg = DWARF_REG_TO_UNWIND_COLUMN (reg); |
- | 969 | if (UNWIND_COLUMN_IN_RANGE (reg)) |
|
- | 970 | { |
|
892 | = REG_SAVED_OFFSET; |
971 | fs->regs.reg[reg].how = REG_SAVED_OFFSET; |
893 | fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].loc.offset = offset; |
972 | fs->regs.reg[reg].loc.offset = offset; |
- | 973 | } |
|
894 | } |
974 | } |
895 | else if ((insn & 0xc0) == DW_CFA_restore) |
975 | else if ((insn & 0xc0) == DW_CFA_restore) |
896 | { |
976 | { |
897 | reg = insn & 0x3f; |
977 | reg = insn & 0x3f; |
898 | fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].how = REG_UNSAVED; |
978 | reg = DWARF_REG_TO_UNWIND_COLUMN (reg); |
- | 979 | if (UNWIND_COLUMN_IN_RANGE (reg)) |
|
- | 980 | fs->regs.reg[reg].how = REG_UNSAVED; |
|
899 | } |
981 | } |
900 | else switch (insn) |
982 | else switch (insn) |
901 | { |
983 | { |
902 | case DW_CFA_set_loc: |
984 | case DW_CFA_set_loc: |
903 | { |
985 | { |
Line 924... | Line 1006... | ||
924 | 1006 | ||
925 | case DW_CFA_offset_extended: |
1007 | case DW_CFA_offset_extended: |
926 | insn_ptr = read_uleb128 (insn_ptr, ®); |
1008 | insn_ptr = read_uleb128 (insn_ptr, ®); |
927 | insn_ptr = read_uleb128 (insn_ptr, &utmp); |
1009 | insn_ptr = read_uleb128 (insn_ptr, &utmp); |
928 | offset = (_Unwind_Sword) utmp * fs->data_align; |
1010 | offset = (_Unwind_Sword) utmp * fs->data_align; |
- | 1011 | reg = DWARF_REG_TO_UNWIND_COLUMN (reg); |
|
- | 1012 | if (UNWIND_COLUMN_IN_RANGE (reg)) |
|
929 | fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].how |
1013 | { |
930 | = REG_SAVED_OFFSET; |
1014 | fs->regs.reg[reg].how = REG_SAVED_OFFSET; |
- | 1015 | fs->regs.reg[reg].loc.offset = offset; |
|
931 | fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].loc.offset = offset; |
1016 | } |
Line 932... | Line 1017... | ||
932 | break; |
1017 | break; |
933 | 1018 | ||
934 | case DW_CFA_restore_extended: |
1019 | case DW_CFA_restore_extended: |
935 | insn_ptr = read_uleb128 (insn_ptr, ®); |
1020 | insn_ptr = read_uleb128 (insn_ptr, ®); |
936 | /* FIXME, this is wrong; the CIE might have said that the |
1021 | /* FIXME, this is wrong; the CIE might have said that the |
- | 1022 | register was saved somewhere. */ |
|
- | 1023 | reg = DWARF_REG_TO_UNWIND_COLUMN (reg); |
|
937 | register was saved somewhere. */ |
1024 | if (UNWIND_COLUMN_IN_RANGE (reg)) |
Line 938... | Line 1025... | ||
938 | fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN(reg)].how = REG_UNSAVED; |
1025 | fs->regs.reg[reg].how = REG_UNSAVED; |
939 | break; |
1026 | break; |
940 | 1027 | ||
- | 1028 | case DW_CFA_same_value: |
|
- | 1029 | insn_ptr = read_uleb128 (insn_ptr, ®); |
|
941 | case DW_CFA_same_value: |
1030 | reg = DWARF_REG_TO_UNWIND_COLUMN (reg); |
Line 942... | Line 1031... | ||
942 | insn_ptr = read_uleb128 (insn_ptr, ®); |
1031 | if (UNWIND_COLUMN_IN_RANGE (reg)) |
943 | fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN(reg)].how = REG_UNSAVED; |
1032 | fs->regs.reg[reg].how = REG_UNSAVED; |
- | 1033 | break; |
|
- | 1034 | ||
944 | break; |
1035 | case DW_CFA_undefined: |
945 | 1036 | insn_ptr = read_uleb128 (insn_ptr, ®); |
|
Line 946... | Line 1037... | ||
946 | case DW_CFA_undefined: |
1037 | reg = DWARF_REG_TO_UNWIND_COLUMN (reg); |
947 | insn_ptr = read_uleb128 (insn_ptr, ®); |
1038 | if (UNWIND_COLUMN_IN_RANGE (reg)) |
Line 948... | Line 1039... | ||
948 | fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN(reg)].how = REG_UNDEFINED; |
1039 | fs->regs.reg[reg].how = REG_UNDEFINED; |
949 | break; |
1040 | break; |
950 | 1041 | ||
951 | case DW_CFA_nop: |
1042 | case DW_CFA_nop: |
952 | break; |
1043 | break; |
953 | 1044 | ||
954 | case DW_CFA_register: |
1045 | case DW_CFA_register: |
- | 1046 | { |
|
- | 1047 | _uleb128_t reg2; |
|
955 | { |
1048 | insn_ptr = read_uleb128 (insn_ptr, ®); |
- | 1049 | insn_ptr = read_uleb128 (insn_ptr, ®2); |
|
956 | _uleb128_t reg2; |
1050 | reg = DWARF_REG_TO_UNWIND_COLUMN (reg); |
957 | insn_ptr = read_uleb128 (insn_ptr, ®); |
1051 | if (UNWIND_COLUMN_IN_RANGE (reg)) |
Line 958... | Line 1052... | ||
958 | insn_ptr = read_uleb128 (insn_ptr, ®2); |
1052 | { |
959 | fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].how = REG_SAVED_REG; |
1053 | fs->regs.reg[reg].how = REG_SAVED_REG; |
Line 1014... | Line 1108... | ||
1014 | insn_ptr += utmp; |
1108 | insn_ptr += utmp; |
1015 | break; |
1109 | break; |
Line 1016... | Line 1110... | ||
1016 | 1110 | ||
1017 | case DW_CFA_expression: |
1111 | case DW_CFA_expression: |
1018 | insn_ptr = read_uleb128 (insn_ptr, ®); |
1112 | insn_ptr = read_uleb128 (insn_ptr, ®); |
- | 1113 | reg = DWARF_REG_TO_UNWIND_COLUMN (reg); |
|
- | 1114 | if (UNWIND_COLUMN_IN_RANGE (reg)) |
|
- | 1115 | { |
|
1019 | fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].how = REG_SAVED_EXP; |
1116 | fs->regs.reg[reg].how = REG_SAVED_EXP; |
- | 1117 | fs->regs.reg[reg].loc.exp = insn_ptr; |
|
1020 | fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].loc.exp = insn_ptr; |
1118 | } |
1021 | insn_ptr = read_uleb128 (insn_ptr, &utmp); |
1119 | insn_ptr = read_uleb128 (insn_ptr, &utmp); |
1022 | insn_ptr += utmp; |
1120 | insn_ptr += utmp; |
Line 1023... | Line 1121... | ||
1023 | break; |
1121 | break; |
1024 | 1122 | ||
1025 | /* Dwarf3. */ |
1123 | /* Dwarf3. */ |
1026 | case DW_CFA_offset_extended_sf: |
1124 | case DW_CFA_offset_extended_sf: |
1027 | insn_ptr = read_uleb128 (insn_ptr, ®); |
1125 | insn_ptr = read_uleb128 (insn_ptr, ®); |
1028 | insn_ptr = read_sleb128 (insn_ptr, &stmp); |
1126 | insn_ptr = read_sleb128 (insn_ptr, &stmp); |
- | 1127 | offset = stmp * fs->data_align; |
|
- | 1128 | reg = DWARF_REG_TO_UNWIND_COLUMN (reg); |
|
1029 | offset = stmp * fs->data_align; |
1129 | if (UNWIND_COLUMN_IN_RANGE (reg)) |
1030 | fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].how |
1130 | { |
- | 1131 | fs->regs.reg[reg].how = REG_SAVED_OFFSET; |
|
1031 | = REG_SAVED_OFFSET; |
1132 | fs->regs.reg[reg].loc.offset = offset; |
Line 1032... | Line 1133... | ||
1032 | fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].loc.offset = offset; |
1133 | } |
1033 | break; |
1134 | break; |
1034 | 1135 | ||
Line 1050... | Line 1151... | ||
1050 | 1151 | ||
1051 | case DW_CFA_val_offset: |
1152 | case DW_CFA_val_offset: |
1052 | insn_ptr = read_uleb128 (insn_ptr, ®); |
1153 | insn_ptr = read_uleb128 (insn_ptr, ®); |
1053 | insn_ptr = read_uleb128 (insn_ptr, &utmp); |
1154 | insn_ptr = read_uleb128 (insn_ptr, &utmp); |
1054 | offset = (_Unwind_Sword) utmp * fs->data_align; |
1155 | offset = (_Unwind_Sword) utmp * fs->data_align; |
- | 1156 | reg = DWARF_REG_TO_UNWIND_COLUMN (reg); |
|
- | 1157 | if (UNWIND_COLUMN_IN_RANGE (reg)) |
|
1055 | fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].how |
1158 | { |
1056 | = REG_SAVED_VAL_OFFSET; |
1159 | fs->regs.reg[reg].how = REG_SAVED_VAL_OFFSET; |
- | 1160 | fs->regs.reg[reg].loc.offset = offset; |
|
1057 | fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].loc.offset = offset; |
1161 | } |
Line 1058... | Line 1162... | ||
1058 | break; |
1162 | break; |
1059 | 1163 | ||
1060 | case DW_CFA_val_offset_sf: |
1164 | case DW_CFA_val_offset_sf: |
1061 | insn_ptr = read_uleb128 (insn_ptr, ®); |
1165 | insn_ptr = read_uleb128 (insn_ptr, ®); |
1062 | insn_ptr = read_sleb128 (insn_ptr, &stmp); |
1166 | insn_ptr = read_sleb128 (insn_ptr, &stmp); |
- | 1167 | offset = stmp * fs->data_align; |
|
- | 1168 | reg = DWARF_REG_TO_UNWIND_COLUMN (reg); |
|
1063 | offset = stmp * fs->data_align; |
1169 | if (UNWIND_COLUMN_IN_RANGE (reg)) |
1064 | fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].how |
1170 | { |
- | 1171 | fs->regs.reg[reg].how = REG_SAVED_VAL_OFFSET; |
|
1065 | = REG_SAVED_VAL_OFFSET; |
1172 | fs->regs.reg[reg].loc.offset = offset; |
Line 1066... | Line 1173... | ||
1066 | fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].loc.offset = offset; |
1173 | } |
1067 | break; |
1174 | break; |
1068 | 1175 | ||
- | 1176 | case DW_CFA_val_expression: |
|
- | 1177 | insn_ptr = read_uleb128 (insn_ptr, ®); |
|
1069 | case DW_CFA_val_expression: |
1178 | reg = DWARF_REG_TO_UNWIND_COLUMN (reg); |
1070 | insn_ptr = read_uleb128 (insn_ptr, ®); |
1179 | if (UNWIND_COLUMN_IN_RANGE (reg)) |
- | 1180 | { |
|
1071 | fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].how |
1181 | fs->regs.reg[reg].how = REG_SAVED_VAL_EXP; |
1072 | = REG_SAVED_VAL_EXP; |
1182 | fs->regs.reg[reg].loc.exp = insn_ptr; |
1073 | fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].loc.exp = insn_ptr; |
1183 | } |
Line 1074... | Line 1184... | ||
1074 | insn_ptr = read_uleb128 (insn_ptr, &utmp); |
1184 | insn_ptr = read_uleb128 (insn_ptr, &utmp); |
1075 | insn_ptr += utmp; |
1185 | insn_ptr += utmp; |
- | 1186 | break; |
|
1076 | break; |
1187 | |
1077 | 1188 | case DW_CFA_GNU_window_save: |
|
1078 | case DW_CFA_GNU_window_save: |
1189 | /* ??? Hardcoded for SPARC register window configuration. */ |
1079 | /* ??? Hardcoded for SPARC register window configuration. */ |
1190 | if (DWARF_FRAME_REGISTERS >= 32) |
1080 | for (reg = 16; reg < 32; ++reg) |
1191 | for (reg = 16; reg < 32; ++reg) |
Line 1093... | Line 1204... | ||
1093 | /* Obsoleted by DW_CFA_offset_extended_sf, but used by |
1204 | /* Obsoleted by DW_CFA_offset_extended_sf, but used by |
1094 | older PowerPC code. */ |
1205 | older PowerPC code. */ |
1095 | insn_ptr = read_uleb128 (insn_ptr, ®); |
1206 | insn_ptr = read_uleb128 (insn_ptr, ®); |
1096 | insn_ptr = read_uleb128 (insn_ptr, &utmp); |
1207 | insn_ptr = read_uleb128 (insn_ptr, &utmp); |
1097 | offset = (_Unwind_Word) utmp * fs->data_align; |
1208 | offset = (_Unwind_Word) utmp * fs->data_align; |
1098 | fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].how |
1209 | reg = DWARF_REG_TO_UNWIND_COLUMN (reg); |
- | 1210 | if (UNWIND_COLUMN_IN_RANGE (reg)) |
|
- | 1211 | { |
|
1099 | = REG_SAVED_OFFSET; |
1212 | fs->regs.reg[reg].how = REG_SAVED_OFFSET; |
1100 | fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN (reg)].loc.offset = -offset; |
1213 | fs->regs.reg[reg].loc.offset = -offset; |
- | 1214 | } |
|
1101 | break; |
1215 | break; |
Line 1102... | Line 1216... | ||
1102 | 1216 | ||
1103 | default: |
1217 | default: |
1104 | gcc_unreachable (); |
1218 | gcc_unreachable (); |
Line 1202... | Line 1316... | ||
1202 | struct _Unwind_Context context; |
1316 | struct _Unwind_Context context; |
1203 | _Unwind_FrameState fs; |
1317 | _Unwind_FrameState fs; |
1204 | int reg; |
1318 | int reg; |
Line 1205... | Line 1319... | ||
1205 | 1319 | ||
- | 1320 | memset (&context, 0, sizeof (struct _Unwind_Context)); |
|
1206 | memset (&context, 0, sizeof (struct _Unwind_Context)); |
1321 | if (!ASSUME_EXTENDED_UNWIND_CONTEXT) |
1207 | context.flags = EXTENDED_CONTEXT_BIT; |
1322 | context.flags = EXTENDED_CONTEXT_BIT; |
Line 1208... | Line 1323... | ||
1208 | context.ra = pc_target + 1; |
1323 | context.ra = pc_target + 1; |
1209 | 1324 | ||
Line 1440... | Line 1555... | ||
1440 | _Unwind_SpTmp sp_slot; |
1555 | _Unwind_SpTmp sp_slot; |
1441 | _Unwind_Reason_Code code; |
1556 | _Unwind_Reason_Code code; |
Line 1442... | Line 1557... | ||
1442 | 1557 | ||
1443 | memset (context, 0, sizeof (struct _Unwind_Context)); |
1558 | memset (context, 0, sizeof (struct _Unwind_Context)); |
- | 1559 | context->ra = ra; |
|
1444 | context->ra = ra; |
1560 | if (!ASSUME_EXTENDED_UNWIND_CONTEXT) |
Line 1445... | Line 1561... | ||
1445 | context->flags = EXTENDED_CONTEXT_BIT; |
1561 | context->flags = EXTENDED_CONTEXT_BIT; |
1446 | 1562 | ||
Line 1482... | Line 1598... | ||
1482 | transferred. */ |
1598 | transferred. */ |
1483 | static void |
1599 | static void |
1484 | _Unwind_DebugHook (void *cfa __attribute__ ((__unused__)), |
1600 | _Unwind_DebugHook (void *cfa __attribute__ ((__unused__)), |
1485 | void *handler __attribute__ ((__unused__))) |
1601 | void *handler __attribute__ ((__unused__))) |
1486 | { |
1602 | { |
- | 1603 | /* We only want to use stap probes starting with v3. Earlier |
|
- | 1604 | versions added too much startup cost. */ |
|
- | 1605 | #if defined (HAVE_SYS_SDT_H) && defined (STAP_PROBE2) && _SDT_NOTE_TYPE >= 3 |
|
- | 1606 | STAP_PROBE2 (libgcc, unwind, cfa, handler); |
|
- | 1607 | #else |
|
1487 | asm (""); |
1608 | asm (""); |
- | 1609 | #endif |
|
1488 | } |
1610 | } |
Line 1489... | Line 1611... | ||
1489 | 1611 | ||
1490 | /* Install TARGET into CURRENT so that we can return to it. This is a |
1612 | /* Install TARGET into CURRENT so that we can return to it. This is a |
1491 | macro because __builtin_eh_return must be invoked in the context of |
1613 | macro because __builtin_eh_return must be invoked in the context of |
Line 1513... | Line 1635... | ||
1513 | if (!_Unwind_GetGRPtr (target, __builtin_dwarf_sp_column ())) |
1635 | if (!_Unwind_GetGRPtr (target, __builtin_dwarf_sp_column ())) |
1514 | _Unwind_SetSpColumn (target, target->cfa, &sp_slot); |
1636 | _Unwind_SetSpColumn (target, target->cfa, &sp_slot); |
Line 1515... | Line 1637... | ||
1515 | 1637 | ||
1516 | for (i = 0; i < DWARF_FRAME_REGISTERS; ++i) |
1638 | for (i = 0; i < DWARF_FRAME_REGISTERS; ++i) |
1517 | { |
1639 | { |
1518 | void *c = current->reg[i]; |
1640 | void *c = (void *) (_Unwind_Internal_Ptr) current->reg[i]; |
Line 1519... | Line 1641... | ||
1519 | void *t = target->reg[i]; |
1641 | void *t = (void *) (_Unwind_Internal_Ptr)target->reg[i]; |
1520 | 1642 | ||
1521 | gcc_assert (current->by_value[i] == 0); |
1643 | gcc_assert (current->by_value[i] == 0); |
1522 | if (target->by_value[i] && c) |
1644 | if (target->by_value[i] && c) |