| xf.li | bdd93d5 | 2023-05-12 07:10:14 -0700 | [diff] [blame] | 1 | /* DWARF2 exception handling and frame unwind runtime interface routines. | 
|  | 2 | Copyright (C) 1997-2016 Free Software Foundation, Inc. | 
|  | 3 |  | 
|  | 4 | This file is part of the GNU C Library. | 
|  | 5 |  | 
|  | 6 | The GNU C Library is free software; you can redistribute it and/or | 
|  | 7 | modify it under the terms of the GNU Lesser General Public | 
|  | 8 | License as published by the Free Software Foundation; either | 
|  | 9 | version 2.1 of the License, or (at your option) any later version. | 
|  | 10 |  | 
|  | 11 | The GNU C Library is distributed in the hope that it will be useful, | 
|  | 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | 
|  | 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | 
|  | 14 | Lesser General Public License for more details. | 
|  | 15 |  | 
|  | 16 | You should have received a copy of the GNU Lesser General Public | 
|  | 17 | License along with the GNU C Library; if not, see | 
|  | 18 | <http://www.gnu.org/licenses/>.  */ | 
|  | 19 |  | 
|  | 20 | #ifdef _LIBC | 
|  | 21 | #include <stdlib.h> | 
|  | 22 | #include <string.h> | 
|  | 23 | #include <error.h> | 
|  | 24 | #include <libintl.h> | 
|  | 25 | #include <dwarf2.h> | 
|  | 26 | #include <stdio.h> | 
|  | 27 | #include <unwind.h> | 
|  | 28 | #include <unwind-pe.h> | 
|  | 29 | #include <unwind-dw2-fde.h> | 
|  | 30 | #else | 
|  | 31 | #include "tconfig.h" | 
|  | 32 | #include "tsystem.h" | 
|  | 33 | #include "dwarf2.h" | 
|  | 34 | #include "unwind.h" | 
|  | 35 | #include "unwind-pe.h" | 
|  | 36 | #include "unwind-dw2-fde.h" | 
|  | 37 | #include "gthr.h" | 
|  | 38 | #endif | 
|  | 39 |  | 
|  | 40 |  | 
|  | 41 |  | 
|  | 42 | #ifndef STACK_GROWS_DOWNWARD | 
|  | 43 | #define STACK_GROWS_DOWNWARD 0 | 
|  | 44 | #else | 
|  | 45 | #undef STACK_GROWS_DOWNWARD | 
|  | 46 | #define STACK_GROWS_DOWNWARD 1 | 
|  | 47 | #endif | 
|  | 48 |  | 
|  | 49 | /* A target can override (perhaps for backward compatibility) how | 
|  | 50 | many dwarf2 columns are unwound.  */ | 
|  | 51 | #ifndef DWARF_FRAME_REGISTERS | 
|  | 52 | #define DWARF_FRAME_REGISTERS FIRST_PSEUDO_REGISTER | 
|  | 53 | #endif | 
|  | 54 |  | 
|  | 55 | /* Dwarf frame registers used for pre gcc 3.0 compiled glibc.  */ | 
|  | 56 | #ifndef PRE_GCC3_DWARF_FRAME_REGISTERS | 
|  | 57 | #define PRE_GCC3_DWARF_FRAME_REGISTERS DWARF_FRAME_REGISTERS | 
|  | 58 | #endif | 
|  | 59 |  | 
|  | 60 | /* This is the register and unwind state for a particular frame.  This | 
|  | 61 | provides the information necessary to unwind up past a frame and return | 
|  | 62 | to its caller.  */ | 
|  | 63 | struct _Unwind_Context | 
|  | 64 | { | 
|  | 65 | void *reg[DWARF_FRAME_REGISTERS+1]; | 
|  | 66 | void *cfa; | 
|  | 67 | void *ra; | 
|  | 68 | void *lsda; | 
|  | 69 | struct dwarf_eh_bases bases; | 
|  | 70 | _Unwind_Word args_size; | 
|  | 71 | }; | 
|  | 72 |  | 
|  | 73 | #ifndef _LIBC | 
|  | 74 | /* Byte size of every register managed by these routines.  */ | 
|  | 75 | static unsigned char dwarf_reg_size_table[DWARF_FRAME_REGISTERS]; | 
|  | 76 | #endif | 
|  | 77 |  | 
|  | 78 |  | 
|  | 79 | /* The result of interpreting the frame unwind info for a frame. | 
|  | 80 | This is all symbolic at this point, as none of the values can | 
|  | 81 | be resolved until the target pc is located.  */ | 
|  | 82 | typedef struct | 
|  | 83 | { | 
|  | 84 | /* Each register save state can be described in terms of a CFA slot, | 
|  | 85 | another register, or a location expression.  */ | 
|  | 86 | struct frame_state_reg_info | 
|  | 87 | { | 
|  | 88 | struct { | 
|  | 89 | union { | 
|  | 90 | _Unwind_Word reg; | 
|  | 91 | _Unwind_Sword offset; | 
|  | 92 | const unsigned char *exp; | 
|  | 93 | } loc; | 
|  | 94 | enum { | 
|  | 95 | REG_UNSAVED, | 
|  | 96 | REG_SAVED_OFFSET, | 
|  | 97 | REG_SAVED_REG, | 
|  | 98 | REG_SAVED_EXP, | 
|  | 99 | } how; | 
|  | 100 | } reg[DWARF_FRAME_REGISTERS+1]; | 
|  | 101 |  | 
|  | 102 | /* Used to implement DW_CFA_remember_state.  */ | 
|  | 103 | struct frame_state_reg_info *prev; | 
|  | 104 | } regs; | 
|  | 105 |  | 
|  | 106 | /* The CFA can be described in terms of a reg+offset or a | 
|  | 107 | location expression.  */ | 
|  | 108 | _Unwind_Sword cfa_offset; | 
|  | 109 | _Unwind_Word cfa_reg; | 
|  | 110 | const unsigned char *cfa_exp; | 
|  | 111 | enum { | 
|  | 112 | CFA_UNSET, | 
|  | 113 | CFA_REG_OFFSET, | 
|  | 114 | CFA_EXP, | 
|  | 115 | } cfa_how; | 
|  | 116 |  | 
|  | 117 | /* The PC described by the current frame state.  */ | 
|  | 118 | void *pc; | 
|  | 119 |  | 
|  | 120 | /* The information we care about from the CIE/FDE.  */ | 
|  | 121 | _Unwind_Personality_Fn personality; | 
|  | 122 | _Unwind_Sword data_align; | 
|  | 123 | _Unwind_Word code_align; | 
|  | 124 | unsigned char retaddr_column; | 
|  | 125 | unsigned char fde_encoding; | 
|  | 126 | unsigned char lsda_encoding; | 
|  | 127 | unsigned char saw_z; | 
|  | 128 | void *eh_ptr; | 
|  | 129 | } _Unwind_FrameState; | 
|  | 130 |  | 
|  | 131 | /* Read unaligned data from the instruction buffer.  */ | 
|  | 132 |  | 
|  | 133 | union unaligned | 
|  | 134 | { | 
|  | 135 | void *p; | 
|  | 136 | unsigned u2 __attribute__ ((mode (HI))); | 
|  | 137 | unsigned u4 __attribute__ ((mode (SI))); | 
|  | 138 | unsigned u8 __attribute__ ((mode (DI))); | 
|  | 139 | signed s2 __attribute__ ((mode (HI))); | 
|  | 140 | signed s4 __attribute__ ((mode (SI))); | 
|  | 141 | signed s8 __attribute__ ((mode (DI))); | 
|  | 142 | } __attribute__ ((packed)); | 
|  | 143 |  | 
|  | 144 | static inline void * | 
|  | 145 | read_pointer (const void *p) { const union unaligned *up = p; return up->p; } | 
|  | 146 |  | 
|  | 147 | static inline int | 
|  | 148 | read_1u (const void *p) { return *(const unsigned char *) p; } | 
|  | 149 |  | 
|  | 150 | static inline int | 
|  | 151 | read_1s (const void *p) { return *(const signed char *) p; } | 
|  | 152 |  | 
|  | 153 | static inline int | 
|  | 154 | read_2u (const void *p) { const union unaligned *up = p; return up->u2; } | 
|  | 155 |  | 
|  | 156 | static inline int | 
|  | 157 | read_2s (const void *p) { const union unaligned *up = p; return up->s2; } | 
|  | 158 |  | 
|  | 159 | static inline unsigned int | 
|  | 160 | read_4u (const void *p) { const union unaligned *up = p; return up->u4; } | 
|  | 161 |  | 
|  | 162 | static inline int | 
|  | 163 | read_4s (const void *p) { const union unaligned *up = p; return up->s4; } | 
|  | 164 |  | 
|  | 165 | static inline unsigned long | 
|  | 166 | read_8u (const void *p) { const union unaligned *up = p; return up->u8; } | 
|  | 167 |  | 
|  | 168 | static inline unsigned long | 
|  | 169 | read_8s (const void *p) { const union unaligned *up = p; return up->s8; } | 
|  | 170 |  | 
|  | 171 | /* Get the value of register REG as saved in CONTEXT.  */ | 
|  | 172 |  | 
|  | 173 | inline _Unwind_Word | 
|  | 174 | _Unwind_GetGR (struct _Unwind_Context *context, int index) | 
|  | 175 | { | 
|  | 176 | /* This will segfault if the register hasn't been saved.  */ | 
|  | 177 | return * (_Unwind_Word *) context->reg[index]; | 
|  | 178 | } | 
|  | 179 |  | 
|  | 180 | /* Get the value of the CFA as saved in CONTEXT.  */ | 
|  | 181 |  | 
|  | 182 | _Unwind_Word | 
|  | 183 | _Unwind_GetCFA (struct _Unwind_Context *context) | 
|  | 184 | { | 
|  | 185 | return (_Unwind_Ptr) context->cfa; | 
|  | 186 | } | 
|  | 187 |  | 
|  | 188 | /* Overwrite the saved value for register REG in CONTEXT with VAL.  */ | 
|  | 189 |  | 
|  | 190 | inline void | 
|  | 191 | _Unwind_SetGR (struct _Unwind_Context *context, int index, _Unwind_Word val) | 
|  | 192 | { | 
|  | 193 | * (_Unwind_Word *) context->reg[index] = val; | 
|  | 194 | } | 
|  | 195 |  | 
|  | 196 | /* Retrieve the return address for CONTEXT.  */ | 
|  | 197 |  | 
|  | 198 | inline _Unwind_Ptr | 
|  | 199 | _Unwind_GetIP (struct _Unwind_Context *context) | 
|  | 200 | { | 
|  | 201 | return (_Unwind_Ptr) context->ra; | 
|  | 202 | } | 
|  | 203 |  | 
|  | 204 | /* Overwrite the return address for CONTEXT with VAL.  */ | 
|  | 205 |  | 
|  | 206 | inline void | 
|  | 207 | _Unwind_SetIP (struct _Unwind_Context *context, _Unwind_Ptr val) | 
|  | 208 | { | 
|  | 209 | context->ra = (void *) val; | 
|  | 210 | } | 
|  | 211 |  | 
|  | 212 | void * | 
|  | 213 | _Unwind_GetLanguageSpecificData (struct _Unwind_Context *context) | 
|  | 214 | { | 
|  | 215 | return context->lsda; | 
|  | 216 | } | 
|  | 217 |  | 
|  | 218 | _Unwind_Ptr | 
|  | 219 | _Unwind_GetRegionStart (struct _Unwind_Context *context) | 
|  | 220 | { | 
|  | 221 | return (_Unwind_Ptr) context->bases.func; | 
|  | 222 | } | 
|  | 223 |  | 
|  | 224 | void * | 
|  | 225 | _Unwind_FindEnclosingFunction (void *pc) | 
|  | 226 | { | 
|  | 227 | struct dwarf_eh_bases bases; | 
|  | 228 | struct dwarf_fde *fde = _Unwind_Find_FDE (pc-1, &bases); | 
|  | 229 | if (fde) | 
|  | 230 | return bases.func; | 
|  | 231 | else | 
|  | 232 | return NULL; | 
|  | 233 | } | 
|  | 234 |  | 
|  | 235 | #ifndef __ia64__ | 
|  | 236 | _Unwind_Ptr | 
|  | 237 | _Unwind_GetDataRelBase (struct _Unwind_Context *context) | 
|  | 238 | { | 
|  | 239 | return (_Unwind_Ptr) context->bases.dbase; | 
|  | 240 | } | 
|  | 241 |  | 
|  | 242 | _Unwind_Ptr | 
|  | 243 | _Unwind_GetTextRelBase (struct _Unwind_Context *context) | 
|  | 244 | { | 
|  | 245 | return (_Unwind_Ptr) context->bases.tbase; | 
|  | 246 | } | 
|  | 247 | #endif | 
|  | 248 |  | 
|  | 249 | /* Extract any interesting information from the CIE for the translation | 
|  | 250 | unit F belongs to.  Return a pointer to the byte after the augmentation, | 
|  | 251 | or NULL if we encountered an undecipherable augmentation.  */ | 
|  | 252 |  | 
|  | 253 | static const unsigned char * | 
|  | 254 | extract_cie_info (struct dwarf_cie *cie, struct _Unwind_Context *context, | 
|  | 255 | _Unwind_FrameState *fs) | 
|  | 256 | { | 
|  | 257 | const unsigned char *aug = cie->augmentation; | 
|  | 258 | const unsigned char *p = aug + strlen ((const char *) aug) + 1; | 
|  | 259 | const unsigned char *ret = NULL; | 
|  | 260 | _Unwind_Word utmp; | 
|  | 261 |  | 
|  | 262 | /* g++ v2 "eh" has pointer immediately following augmentation string, | 
|  | 263 | so it must be handled first.  */ | 
|  | 264 | if (aug[0] == 'e' && aug[1] == 'h') | 
|  | 265 | { | 
|  | 266 | fs->eh_ptr = read_pointer (p); | 
|  | 267 | p += sizeof (void *); | 
|  | 268 | aug += 2; | 
|  | 269 | } | 
|  | 270 |  | 
|  | 271 | /* Immediately following the augmentation are the code and | 
|  | 272 | data alignment and return address column.  */ | 
|  | 273 | p = read_uleb128 (p, &fs->code_align); | 
|  | 274 | p = read_sleb128 (p, &fs->data_align); | 
|  | 275 | fs->retaddr_column = *p++; | 
|  | 276 | fs->lsda_encoding = DW_EH_PE_omit; | 
|  | 277 |  | 
|  | 278 | /* If the augmentation starts with 'z', then a uleb128 immediately | 
|  | 279 | follows containing the length of the augmentation field following | 
|  | 280 | the size.  */ | 
|  | 281 | if (*aug == 'z') | 
|  | 282 | { | 
|  | 283 | p = read_uleb128 (p, &utmp); | 
|  | 284 | ret = p + utmp; | 
|  | 285 |  | 
|  | 286 | fs->saw_z = 1; | 
|  | 287 | ++aug; | 
|  | 288 | } | 
|  | 289 |  | 
|  | 290 | /* Iterate over recognized augmentation subsequences.  */ | 
|  | 291 | while (*aug != '\0') | 
|  | 292 | { | 
|  | 293 | /* "L" indicates a byte showing how the LSDA pointer is encoded.  */ | 
|  | 294 | if (aug[0] == 'L') | 
|  | 295 | { | 
|  | 296 | fs->lsda_encoding = *p++; | 
|  | 297 | aug += 1; | 
|  | 298 | } | 
|  | 299 |  | 
|  | 300 | /* "R" indicates a byte indicating how FDE addresses are encoded.  */ | 
|  | 301 | else if (aug[0] == 'R') | 
|  | 302 | { | 
|  | 303 | fs->fde_encoding = *p++; | 
|  | 304 | aug += 1; | 
|  | 305 | } | 
|  | 306 |  | 
|  | 307 | /* "P" indicates a personality routine in the CIE augmentation.  */ | 
|  | 308 | else if (aug[0] == 'P') | 
|  | 309 | { | 
|  | 310 | _Unwind_Ptr personality; | 
|  | 311 | p = read_encoded_value (context, *p, p + 1, &personality); | 
|  | 312 | fs->personality = (_Unwind_Personality_Fn) personality; | 
|  | 313 | aug += 1; | 
|  | 314 | } | 
|  | 315 |  | 
|  | 316 | /* Otherwise we have an unknown augmentation string. | 
|  | 317 | Bail unless we saw a 'z' prefix.  */ | 
|  | 318 | else | 
|  | 319 | return ret; | 
|  | 320 | } | 
|  | 321 |  | 
|  | 322 | return ret ? ret : p; | 
|  | 323 | } | 
|  | 324 |  | 
|  | 325 | #ifndef _LIBC | 
|  | 326 | /* Decode a DW_OP stack program.  Return the top of stack.  Push INITIAL | 
|  | 327 | onto the stack to start.  */ | 
|  | 328 |  | 
|  | 329 | static _Unwind_Word | 
|  | 330 | execute_stack_op (const unsigned char *op_ptr, const unsigned char *op_end, | 
|  | 331 | struct _Unwind_Context *context, _Unwind_Word initial) | 
|  | 332 | { | 
|  | 333 | _Unwind_Word stack[64];	/* ??? Assume this is enough.  */ | 
|  | 334 | int stack_elt; | 
|  | 335 |  | 
|  | 336 | stack[0] = initial; | 
|  | 337 | stack_elt = 1; | 
|  | 338 |  | 
|  | 339 | while (op_ptr < op_end) | 
|  | 340 | { | 
|  | 341 | enum dwarf_location_atom op = *op_ptr++; | 
|  | 342 | _Unwind_Word result, reg, utmp; | 
|  | 343 | _Unwind_Sword offset, stmp; | 
|  | 344 |  | 
|  | 345 | switch (op) | 
|  | 346 | { | 
|  | 347 | case DW_OP_lit0: | 
|  | 348 | case DW_OP_lit1: | 
|  | 349 | case DW_OP_lit2: | 
|  | 350 | case DW_OP_lit3: | 
|  | 351 | case DW_OP_lit4: | 
|  | 352 | case DW_OP_lit5: | 
|  | 353 | case DW_OP_lit6: | 
|  | 354 | case DW_OP_lit7: | 
|  | 355 | case DW_OP_lit8: | 
|  | 356 | case DW_OP_lit9: | 
|  | 357 | case DW_OP_lit10: | 
|  | 358 | case DW_OP_lit11: | 
|  | 359 | case DW_OP_lit12: | 
|  | 360 | case DW_OP_lit13: | 
|  | 361 | case DW_OP_lit14: | 
|  | 362 | case DW_OP_lit15: | 
|  | 363 | case DW_OP_lit16: | 
|  | 364 | case DW_OP_lit17: | 
|  | 365 | case DW_OP_lit18: | 
|  | 366 | case DW_OP_lit19: | 
|  | 367 | case DW_OP_lit20: | 
|  | 368 | case DW_OP_lit21: | 
|  | 369 | case DW_OP_lit22: | 
|  | 370 | case DW_OP_lit23: | 
|  | 371 | case DW_OP_lit24: | 
|  | 372 | case DW_OP_lit25: | 
|  | 373 | case DW_OP_lit26: | 
|  | 374 | case DW_OP_lit27: | 
|  | 375 | case DW_OP_lit28: | 
|  | 376 | case DW_OP_lit29: | 
|  | 377 | case DW_OP_lit30: | 
|  | 378 | case DW_OP_lit31: | 
|  | 379 | result = op - DW_OP_lit0; | 
|  | 380 | break; | 
|  | 381 |  | 
|  | 382 | case DW_OP_addr: | 
|  | 383 | result = (_Unwind_Word) (_Unwind_Ptr) read_pointer (op_ptr); | 
|  | 384 | op_ptr += sizeof (void *); | 
|  | 385 | break; | 
|  | 386 |  | 
|  | 387 | case DW_OP_const1u: | 
|  | 388 | result = read_1u (op_ptr); | 
|  | 389 | op_ptr += 1; | 
|  | 390 | break; | 
|  | 391 | case DW_OP_const1s: | 
|  | 392 | result = read_1s (op_ptr); | 
|  | 393 | op_ptr += 1; | 
|  | 394 | break; | 
|  | 395 | case DW_OP_const2u: | 
|  | 396 | result = read_2u (op_ptr); | 
|  | 397 | op_ptr += 2; | 
|  | 398 | break; | 
|  | 399 | case DW_OP_const2s: | 
|  | 400 | result = read_2s (op_ptr); | 
|  | 401 | op_ptr += 2; | 
|  | 402 | break; | 
|  | 403 | case DW_OP_const4u: | 
|  | 404 | result = read_4u (op_ptr); | 
|  | 405 | op_ptr += 4; | 
|  | 406 | break; | 
|  | 407 | case DW_OP_const4s: | 
|  | 408 | result = read_4s (op_ptr); | 
|  | 409 | op_ptr += 4; | 
|  | 410 | break; | 
|  | 411 | case DW_OP_const8u: | 
|  | 412 | result = read_8u (op_ptr); | 
|  | 413 | op_ptr += 8; | 
|  | 414 | break; | 
|  | 415 | case DW_OP_const8s: | 
|  | 416 | result = read_8s (op_ptr); | 
|  | 417 | op_ptr += 8; | 
|  | 418 | break; | 
|  | 419 | case DW_OP_constu: | 
|  | 420 | op_ptr = read_uleb128 (op_ptr, &result); | 
|  | 421 | break; | 
|  | 422 | case DW_OP_consts: | 
|  | 423 | op_ptr = read_sleb128 (op_ptr, &stmp); | 
|  | 424 | result = stmp; | 
|  | 425 | break; | 
|  | 426 |  | 
|  | 427 | case DW_OP_reg0: | 
|  | 428 | case DW_OP_reg1: | 
|  | 429 | case DW_OP_reg2: | 
|  | 430 | case DW_OP_reg3: | 
|  | 431 | case DW_OP_reg4: | 
|  | 432 | case DW_OP_reg5: | 
|  | 433 | case DW_OP_reg6: | 
|  | 434 | case DW_OP_reg7: | 
|  | 435 | case DW_OP_reg8: | 
|  | 436 | case DW_OP_reg9: | 
|  | 437 | case DW_OP_reg10: | 
|  | 438 | case DW_OP_reg11: | 
|  | 439 | case DW_OP_reg12: | 
|  | 440 | case DW_OP_reg13: | 
|  | 441 | case DW_OP_reg14: | 
|  | 442 | case DW_OP_reg15: | 
|  | 443 | case DW_OP_reg16: | 
|  | 444 | case DW_OP_reg17: | 
|  | 445 | case DW_OP_reg18: | 
|  | 446 | case DW_OP_reg19: | 
|  | 447 | case DW_OP_reg20: | 
|  | 448 | case DW_OP_reg21: | 
|  | 449 | case DW_OP_reg22: | 
|  | 450 | case DW_OP_reg23: | 
|  | 451 | case DW_OP_reg24: | 
|  | 452 | case DW_OP_reg25: | 
|  | 453 | case DW_OP_reg26: | 
|  | 454 | case DW_OP_reg27: | 
|  | 455 | case DW_OP_reg28: | 
|  | 456 | case DW_OP_reg29: | 
|  | 457 | case DW_OP_reg30: | 
|  | 458 | case DW_OP_reg31: | 
|  | 459 | result = _Unwind_GetGR (context, op - DW_OP_reg0); | 
|  | 460 | break; | 
|  | 461 | case DW_OP_regx: | 
|  | 462 | op_ptr = read_uleb128 (op_ptr, ®); | 
|  | 463 | result = _Unwind_GetGR (context, reg); | 
|  | 464 | break; | 
|  | 465 |  | 
|  | 466 | case DW_OP_breg0: | 
|  | 467 | case DW_OP_breg1: | 
|  | 468 | case DW_OP_breg2: | 
|  | 469 | case DW_OP_breg3: | 
|  | 470 | case DW_OP_breg4: | 
|  | 471 | case DW_OP_breg5: | 
|  | 472 | case DW_OP_breg6: | 
|  | 473 | case DW_OP_breg7: | 
|  | 474 | case DW_OP_breg8: | 
|  | 475 | case DW_OP_breg9: | 
|  | 476 | case DW_OP_breg10: | 
|  | 477 | case DW_OP_breg11: | 
|  | 478 | case DW_OP_breg12: | 
|  | 479 | case DW_OP_breg13: | 
|  | 480 | case DW_OP_breg14: | 
|  | 481 | case DW_OP_breg15: | 
|  | 482 | case DW_OP_breg16: | 
|  | 483 | case DW_OP_breg17: | 
|  | 484 | case DW_OP_breg18: | 
|  | 485 | case DW_OP_breg19: | 
|  | 486 | case DW_OP_breg20: | 
|  | 487 | case DW_OP_breg21: | 
|  | 488 | case DW_OP_breg22: | 
|  | 489 | case DW_OP_breg23: | 
|  | 490 | case DW_OP_breg24: | 
|  | 491 | case DW_OP_breg25: | 
|  | 492 | case DW_OP_breg26: | 
|  | 493 | case DW_OP_breg27: | 
|  | 494 | case DW_OP_breg28: | 
|  | 495 | case DW_OP_breg29: | 
|  | 496 | case DW_OP_breg30: | 
|  | 497 | case DW_OP_breg31: | 
|  | 498 | op_ptr = read_sleb128 (op_ptr, &offset); | 
|  | 499 | result = _Unwind_GetGR (context, op - DW_OP_breg0) + offset; | 
|  | 500 | break; | 
|  | 501 | case DW_OP_bregx: | 
|  | 502 | op_ptr = read_uleb128 (op_ptr, ®); | 
|  | 503 | op_ptr = read_sleb128 (op_ptr, &offset); | 
|  | 504 | result = _Unwind_GetGR (context, reg) + offset; | 
|  | 505 | break; | 
|  | 506 |  | 
|  | 507 | case DW_OP_dup: | 
|  | 508 | if (stack_elt < 1) | 
|  | 509 | abort (); | 
|  | 510 | result = stack[stack_elt - 1]; | 
|  | 511 | break; | 
|  | 512 |  | 
|  | 513 | case DW_OP_drop: | 
|  | 514 | if (--stack_elt < 0) | 
|  | 515 | abort (); | 
|  | 516 | goto no_push; | 
|  | 517 |  | 
|  | 518 | case DW_OP_pick: | 
|  | 519 | offset = *op_ptr++; | 
|  | 520 | if (offset >= stack_elt - 1) | 
|  | 521 | abort (); | 
|  | 522 | result = stack[stack_elt - 1 - offset]; | 
|  | 523 | break; | 
|  | 524 |  | 
|  | 525 | case DW_OP_over: | 
|  | 526 | if (stack_elt < 2) | 
|  | 527 | abort (); | 
|  | 528 | result = stack[stack_elt - 2]; | 
|  | 529 | break; | 
|  | 530 |  | 
|  | 531 | case DW_OP_rot: | 
|  | 532 | { | 
|  | 533 | _Unwind_Word t1, t2, t3; | 
|  | 534 |  | 
|  | 535 | if (stack_elt < 3) | 
|  | 536 | abort (); | 
|  | 537 | t1 = stack[stack_elt - 1]; | 
|  | 538 | t2 = stack[stack_elt - 2]; | 
|  | 539 | t3 = stack[stack_elt - 3]; | 
|  | 540 | stack[stack_elt - 1] = t2; | 
|  | 541 | stack[stack_elt - 2] = t3; | 
|  | 542 | stack[stack_elt - 3] = t1; | 
|  | 543 | goto no_push; | 
|  | 544 | } | 
|  | 545 |  | 
|  | 546 | case DW_OP_deref: | 
|  | 547 | case DW_OP_deref_size: | 
|  | 548 | case DW_OP_abs: | 
|  | 549 | case DW_OP_neg: | 
|  | 550 | case DW_OP_not: | 
|  | 551 | case DW_OP_plus_uconst: | 
|  | 552 | /* Unary operations.  */ | 
|  | 553 | if (--stack_elt < 0) | 
|  | 554 | abort (); | 
|  | 555 | result = stack[stack_elt]; | 
|  | 556 |  | 
|  | 557 | switch (op) | 
|  | 558 | { | 
|  | 559 | case DW_OP_deref: | 
|  | 560 | { | 
|  | 561 | void *ptr = (void *) (_Unwind_Ptr) result; | 
|  | 562 | result = (_Unwind_Ptr) read_pointer (ptr); | 
|  | 563 | } | 
|  | 564 | break; | 
|  | 565 |  | 
|  | 566 | case DW_OP_deref_size: | 
|  | 567 | { | 
|  | 568 | void *ptr = (void *) (_Unwind_Ptr) result; | 
|  | 569 | switch (*op_ptr++) | 
|  | 570 | { | 
|  | 571 | case 1: | 
|  | 572 | result = read_1u (ptr); | 
|  | 573 | break; | 
|  | 574 | case 2: | 
|  | 575 | result = read_2u (ptr); | 
|  | 576 | break; | 
|  | 577 | case 4: | 
|  | 578 | result = read_4u (ptr); | 
|  | 579 | break; | 
|  | 580 | case 8: | 
|  | 581 | result = read_8u (ptr); | 
|  | 582 | break; | 
|  | 583 | default: | 
|  | 584 | abort (); | 
|  | 585 | } | 
|  | 586 | } | 
|  | 587 | break; | 
|  | 588 |  | 
|  | 589 | case DW_OP_abs: | 
|  | 590 | if ((_Unwind_Sword) result < 0) | 
|  | 591 | result = -result; | 
|  | 592 | break; | 
|  | 593 | case DW_OP_neg: | 
|  | 594 | result = -result; | 
|  | 595 | break; | 
|  | 596 | case DW_OP_not: | 
|  | 597 | result = ~result; | 
|  | 598 | break; | 
|  | 599 | case DW_OP_plus_uconst: | 
|  | 600 | op_ptr = read_uleb128 (op_ptr, &utmp); | 
|  | 601 | result += utmp; | 
|  | 602 | break; | 
|  | 603 |  | 
|  | 604 | default: | 
|  | 605 | abort (); | 
|  | 606 | } | 
|  | 607 | break; | 
|  | 608 |  | 
|  | 609 | case DW_OP_and: | 
|  | 610 | case DW_OP_div: | 
|  | 611 | case DW_OP_minus: | 
|  | 612 | case DW_OP_mod: | 
|  | 613 | case DW_OP_mul: | 
|  | 614 | case DW_OP_or: | 
|  | 615 | case DW_OP_plus: | 
|  | 616 | case DW_OP_le: | 
|  | 617 | case DW_OP_ge: | 
|  | 618 | case DW_OP_eq: | 
|  | 619 | case DW_OP_lt: | 
|  | 620 | case DW_OP_gt: | 
|  | 621 | case DW_OP_ne: | 
|  | 622 | { | 
|  | 623 | /* Binary operations.  */ | 
|  | 624 | _Unwind_Word first, second; | 
|  | 625 | if ((stack_elt -= 2) < 0) | 
|  | 626 | abort (); | 
|  | 627 | second = stack[stack_elt]; | 
|  | 628 | first = stack[stack_elt + 1]; | 
|  | 629 |  | 
|  | 630 | switch (op) | 
|  | 631 | { | 
|  | 632 | case DW_OP_and: | 
|  | 633 | result = second & first; | 
|  | 634 | break; | 
|  | 635 | case DW_OP_div: | 
|  | 636 | result = (_Unwind_Sword) second / (_Unwind_Sword) first; | 
|  | 637 | break; | 
|  | 638 | case DW_OP_minus: | 
|  | 639 | result = second - first; | 
|  | 640 | break; | 
|  | 641 | case DW_OP_mod: | 
|  | 642 | result = (_Unwind_Sword) second % (_Unwind_Sword) first; | 
|  | 643 | break; | 
|  | 644 | case DW_OP_mul: | 
|  | 645 | result = second * first; | 
|  | 646 | break; | 
|  | 647 | case DW_OP_or: | 
|  | 648 | result = second | first; | 
|  | 649 | break; | 
|  | 650 | case DW_OP_plus: | 
|  | 651 | result = second + first; | 
|  | 652 | break; | 
|  | 653 | case DW_OP_shl: | 
|  | 654 | result = second << first; | 
|  | 655 | break; | 
|  | 656 | case DW_OP_shr: | 
|  | 657 | result = second >> first; | 
|  | 658 | break; | 
|  | 659 | case DW_OP_shra: | 
|  | 660 | result = (_Unwind_Sword) second >> first; | 
|  | 661 | break; | 
|  | 662 | case DW_OP_xor: | 
|  | 663 | result = second ^ first; | 
|  | 664 | break; | 
|  | 665 | case DW_OP_le: | 
|  | 666 | result = (_Unwind_Sword) first <= (_Unwind_Sword) second; | 
|  | 667 | break; | 
|  | 668 | case DW_OP_ge: | 
|  | 669 | result = (_Unwind_Sword) first >= (_Unwind_Sword) second; | 
|  | 670 | break; | 
|  | 671 | case DW_OP_eq: | 
|  | 672 | result = (_Unwind_Sword) first == (_Unwind_Sword) second; | 
|  | 673 | break; | 
|  | 674 | case DW_OP_lt: | 
|  | 675 | result = (_Unwind_Sword) first < (_Unwind_Sword) second; | 
|  | 676 | break; | 
|  | 677 | case DW_OP_gt: | 
|  | 678 | result = (_Unwind_Sword) first > (_Unwind_Sword) second; | 
|  | 679 | break; | 
|  | 680 | case DW_OP_ne: | 
|  | 681 | result = (_Unwind_Sword) first != (_Unwind_Sword) second; | 
|  | 682 | break; | 
|  | 683 |  | 
|  | 684 | default: | 
|  | 685 | abort (); | 
|  | 686 | } | 
|  | 687 | } | 
|  | 688 | break; | 
|  | 689 |  | 
|  | 690 | case DW_OP_skip: | 
|  | 691 | offset = read_2s (op_ptr); | 
|  | 692 | op_ptr += 2; | 
|  | 693 | op_ptr += offset; | 
|  | 694 | goto no_push; | 
|  | 695 |  | 
|  | 696 | case DW_OP_bra: | 
|  | 697 | if (--stack_elt < 0) | 
|  | 698 | abort (); | 
|  | 699 | offset = read_2s (op_ptr); | 
|  | 700 | op_ptr += 2; | 
|  | 701 | if (stack[stack_elt] != 0) | 
|  | 702 | op_ptr += offset; | 
|  | 703 | goto no_push; | 
|  | 704 |  | 
|  | 705 | case DW_OP_nop: | 
|  | 706 | goto no_push; | 
|  | 707 |  | 
|  | 708 | default: | 
|  | 709 | abort (); | 
|  | 710 | } | 
|  | 711 |  | 
|  | 712 | /* Most things push a result value.  */ | 
|  | 713 | if ((size_t) stack_elt >= sizeof(stack)/sizeof(*stack)) | 
|  | 714 | abort (); | 
|  | 715 | stack[stack_elt++] = result; | 
|  | 716 | no_push:; | 
|  | 717 | } | 
|  | 718 |  | 
|  | 719 | /* We were executing this program to get a value.  It should be | 
|  | 720 | at top of stack.  */ | 
|  | 721 | if (--stack_elt < 0) | 
|  | 722 | abort (); | 
|  | 723 | return stack[stack_elt]; | 
|  | 724 | } | 
|  | 725 | #endif | 
|  | 726 |  | 
|  | 727 | /* Decode DWARF 2 call frame information. Takes pointers the | 
|  | 728 | instruction sequence to decode, current register information and | 
|  | 729 | CIE info, and the PC range to evaluate.  */ | 
|  | 730 |  | 
|  | 731 | static void | 
|  | 732 | execute_cfa_program (const unsigned char *insn_ptr, | 
|  | 733 | const unsigned char *insn_end, | 
|  | 734 | struct _Unwind_Context *context, | 
|  | 735 | _Unwind_FrameState *fs) | 
|  | 736 | { | 
|  | 737 | struct frame_state_reg_info *unused_rs = NULL; | 
|  | 738 |  | 
|  | 739 | /* Don't allow remember/restore between CIE and FDE programs.  */ | 
|  | 740 | fs->regs.prev = NULL; | 
|  | 741 |  | 
|  | 742 | /* The comparison with the return address uses < rather than <= because | 
|  | 743 | we are only interested in the effects of code before the call; for a | 
|  | 744 | noreturn function, the return address may point to unrelated code with | 
|  | 745 | a different stack configuration that we are not interested in.  We | 
|  | 746 | assume that the call itself is unwind info-neutral; if not, or if | 
|  | 747 | there are delay instructions that adjust the stack, these must be | 
|  | 748 | reflected at the point immediately before the call insn.  */ | 
|  | 749 | while (insn_ptr < insn_end && fs->pc < context->ra) | 
|  | 750 | { | 
|  | 751 | unsigned char insn = *insn_ptr++; | 
|  | 752 | _Unwind_Word reg, utmp; | 
|  | 753 | _Unwind_Sword offset, stmp; | 
|  | 754 |  | 
|  | 755 | if ((insn & 0xc0) == DW_CFA_advance_loc) | 
|  | 756 | fs->pc += (insn & 0x3f) * fs->code_align; | 
|  | 757 | else if ((insn & 0xc0) == DW_CFA_offset) | 
|  | 758 | { | 
|  | 759 | reg = insn & 0x3f; | 
|  | 760 | insn_ptr = read_uleb128 (insn_ptr, &utmp); | 
|  | 761 | offset = (_Unwind_Sword) utmp * fs->data_align; | 
|  | 762 | fs->regs.reg[reg].how = REG_SAVED_OFFSET; | 
|  | 763 | fs->regs.reg[reg].loc.offset = offset; | 
|  | 764 | } | 
|  | 765 | else if ((insn & 0xc0) == DW_CFA_restore) | 
|  | 766 | { | 
|  | 767 | reg = insn & 0x3f; | 
|  | 768 | fs->regs.reg[reg].how = REG_UNSAVED; | 
|  | 769 | } | 
|  | 770 | else switch (insn) | 
|  | 771 | { | 
|  | 772 | case DW_CFA_set_loc: | 
|  | 773 | { | 
|  | 774 | _Unwind_Ptr pc; | 
|  | 775 | insn_ptr = read_encoded_value (context, fs->fde_encoding, | 
|  | 776 | insn_ptr, &pc); | 
|  | 777 | fs->pc = (void *) pc; | 
|  | 778 | } | 
|  | 779 | break; | 
|  | 780 |  | 
|  | 781 | case DW_CFA_advance_loc1: | 
|  | 782 | fs->pc += read_1u (insn_ptr) * fs->code_align; | 
|  | 783 | insn_ptr += 1; | 
|  | 784 | break; | 
|  | 785 | case DW_CFA_advance_loc2: | 
|  | 786 | fs->pc += read_2u (insn_ptr) * fs->code_align; | 
|  | 787 | insn_ptr += 2; | 
|  | 788 | break; | 
|  | 789 | case DW_CFA_advance_loc4: | 
|  | 790 | fs->pc += read_4u (insn_ptr) * fs->code_align; | 
|  | 791 | insn_ptr += 4; | 
|  | 792 | break; | 
|  | 793 |  | 
|  | 794 | case DW_CFA_offset_extended: | 
|  | 795 | insn_ptr = read_uleb128 (insn_ptr, ®); | 
|  | 796 | insn_ptr = read_uleb128 (insn_ptr, &utmp); | 
|  | 797 | offset = (_Unwind_Sword) utmp * fs->data_align; | 
|  | 798 | fs->regs.reg[reg].how = REG_SAVED_OFFSET; | 
|  | 799 | fs->regs.reg[reg].loc.offset = offset; | 
|  | 800 | break; | 
|  | 801 |  | 
|  | 802 | case DW_CFA_restore_extended: | 
|  | 803 | insn_ptr = read_uleb128 (insn_ptr, ®); | 
|  | 804 | fs->regs.reg[reg].how = REG_UNSAVED; | 
|  | 805 | break; | 
|  | 806 |  | 
|  | 807 | case DW_CFA_undefined: | 
|  | 808 | case DW_CFA_same_value: | 
|  | 809 | insn_ptr = read_uleb128 (insn_ptr, ®); | 
|  | 810 | break; | 
|  | 811 |  | 
|  | 812 | case DW_CFA_nop: | 
|  | 813 | break; | 
|  | 814 |  | 
|  | 815 | case DW_CFA_register: | 
|  | 816 | { | 
|  | 817 | _Unwind_Word reg2; | 
|  | 818 | insn_ptr = read_uleb128 (insn_ptr, ®); | 
|  | 819 | insn_ptr = read_uleb128 (insn_ptr, ®2); | 
|  | 820 | fs->regs.reg[reg].how = REG_SAVED_REG; | 
|  | 821 | fs->regs.reg[reg].loc.reg = reg2; | 
|  | 822 | } | 
|  | 823 | break; | 
|  | 824 |  | 
|  | 825 | case DW_CFA_remember_state: | 
|  | 826 | { | 
|  | 827 | struct frame_state_reg_info *new_rs; | 
|  | 828 | if (unused_rs) | 
|  | 829 | { | 
|  | 830 | new_rs = unused_rs; | 
|  | 831 | unused_rs = unused_rs->prev; | 
|  | 832 | } | 
|  | 833 | else | 
|  | 834 | new_rs = __builtin_alloca (sizeof (struct frame_state_reg_info)); | 
|  | 835 |  | 
|  | 836 | *new_rs = fs->regs; | 
|  | 837 | fs->regs.prev = new_rs; | 
|  | 838 | } | 
|  | 839 | break; | 
|  | 840 |  | 
|  | 841 | case DW_CFA_restore_state: | 
|  | 842 | { | 
|  | 843 | struct frame_state_reg_info *old_rs = fs->regs.prev; | 
|  | 844 | #ifdef _LIBC | 
|  | 845 | if (old_rs == NULL) | 
|  | 846 | __libc_fatal ("invalid DWARF unwind data"); | 
|  | 847 | else | 
|  | 848 | #endif | 
|  | 849 | { | 
|  | 850 | fs->regs = *old_rs; | 
|  | 851 | old_rs->prev = unused_rs; | 
|  | 852 | unused_rs = old_rs; | 
|  | 853 | } | 
|  | 854 | } | 
|  | 855 | break; | 
|  | 856 |  | 
|  | 857 | case DW_CFA_def_cfa: | 
|  | 858 | insn_ptr = read_uleb128 (insn_ptr, &fs->cfa_reg); | 
|  | 859 | insn_ptr = read_uleb128 (insn_ptr, &utmp); | 
|  | 860 | fs->cfa_offset = utmp; | 
|  | 861 | fs->cfa_how = CFA_REG_OFFSET; | 
|  | 862 | break; | 
|  | 863 |  | 
|  | 864 | case DW_CFA_def_cfa_register: | 
|  | 865 | insn_ptr = read_uleb128 (insn_ptr, &fs->cfa_reg); | 
|  | 866 | fs->cfa_how = CFA_REG_OFFSET; | 
|  | 867 | break; | 
|  | 868 |  | 
|  | 869 | case DW_CFA_def_cfa_offset: | 
|  | 870 | insn_ptr = read_uleb128 (insn_ptr, &utmp); | 
|  | 871 | fs->cfa_offset = utmp; | 
|  | 872 | /* cfa_how deliberately not set.  */ | 
|  | 873 | break; | 
|  | 874 |  | 
|  | 875 | case DW_CFA_def_cfa_expression: | 
|  | 876 | fs->cfa_exp = insn_ptr; | 
|  | 877 | fs->cfa_how = CFA_EXP; | 
|  | 878 | insn_ptr = read_uleb128 (insn_ptr, &utmp); | 
|  | 879 | insn_ptr += utmp; | 
|  | 880 | break; | 
|  | 881 |  | 
|  | 882 | case DW_CFA_expression: | 
|  | 883 | insn_ptr = read_uleb128 (insn_ptr, ®); | 
|  | 884 | fs->regs.reg[reg].how = REG_SAVED_EXP; | 
|  | 885 | fs->regs.reg[reg].loc.exp = insn_ptr; | 
|  | 886 | insn_ptr = read_uleb128 (insn_ptr, &utmp); | 
|  | 887 | insn_ptr += utmp; | 
|  | 888 | break; | 
|  | 889 |  | 
|  | 890 | /* From the 2.1 draft.  */ | 
|  | 891 | case DW_CFA_offset_extended_sf: | 
|  | 892 | insn_ptr = read_uleb128 (insn_ptr, ®); | 
|  | 893 | insn_ptr = read_sleb128 (insn_ptr, &stmp); | 
|  | 894 | offset = stmp * fs->data_align; | 
|  | 895 | fs->regs.reg[reg].how = REG_SAVED_OFFSET; | 
|  | 896 | fs->regs.reg[reg].loc.offset = offset; | 
|  | 897 | break; | 
|  | 898 |  | 
|  | 899 | case DW_CFA_def_cfa_sf: | 
|  | 900 | insn_ptr = read_uleb128 (insn_ptr, &fs->cfa_reg); | 
|  | 901 | insn_ptr = read_sleb128 (insn_ptr, &fs->cfa_offset); | 
|  | 902 | fs->cfa_how = CFA_REG_OFFSET; | 
|  | 903 | break; | 
|  | 904 |  | 
|  | 905 | case DW_CFA_def_cfa_offset_sf: | 
|  | 906 | insn_ptr = read_sleb128 (insn_ptr, &fs->cfa_offset); | 
|  | 907 | /* cfa_how deliberately not set.  */ | 
|  | 908 | break; | 
|  | 909 |  | 
|  | 910 | case DW_CFA_GNU_window_save: | 
|  | 911 | /* ??? Hardcoded for SPARC register window configuration. | 
|  | 912 | At least do not do anything for archs which explicitly | 
|  | 913 | define a lower register number.  */ | 
|  | 914 | #if DWARF_FRAME_REGISTERS >= 32 | 
|  | 915 | for (reg = 16; reg < 32; ++reg) | 
|  | 916 | { | 
|  | 917 | fs->regs.reg[reg].how = REG_SAVED_OFFSET; | 
|  | 918 | fs->regs.reg[reg].loc.offset = (reg - 16) * sizeof (void *); | 
|  | 919 | } | 
|  | 920 | #endif | 
|  | 921 | break; | 
|  | 922 |  | 
|  | 923 | case DW_CFA_GNU_args_size: | 
|  | 924 | insn_ptr = read_uleb128 (insn_ptr, &context->args_size); | 
|  | 925 | break; | 
|  | 926 |  | 
|  | 927 | case DW_CFA_GNU_negative_offset_extended: | 
|  | 928 | /* Obsoleted by DW_CFA_offset_extended_sf, but used by | 
|  | 929 | older PowerPC code.  */ | 
|  | 930 | insn_ptr = read_uleb128 (insn_ptr, ®); | 
|  | 931 | insn_ptr = read_uleb128 (insn_ptr, &utmp); | 
|  | 932 | offset = (_Unwind_Word) utmp * fs->data_align; | 
|  | 933 | fs->regs.reg[reg].how = REG_SAVED_OFFSET; | 
|  | 934 | fs->regs.reg[reg].loc.offset = -offset; | 
|  | 935 | break; | 
|  | 936 |  | 
|  | 937 | default: | 
|  | 938 | abort (); | 
|  | 939 | } | 
|  | 940 | } | 
|  | 941 | } | 
|  | 942 |  | 
|  | 943 | /* Given the _Unwind_Context CONTEXT for a stack frame, look up the FDE for | 
|  | 944 | its caller and decode it into FS.  This function also sets the | 
|  | 945 | args_size and lsda members of CONTEXT, as they are really information | 
|  | 946 | about the caller's frame.  */ | 
|  | 947 |  | 
|  | 948 | static _Unwind_Reason_Code | 
|  | 949 | uw_frame_state_for (struct _Unwind_Context *context, _Unwind_FrameState *fs) | 
|  | 950 | { | 
|  | 951 | struct dwarf_fde *fde; | 
|  | 952 | struct dwarf_cie *cie; | 
|  | 953 | const unsigned char *aug, *insn, *end; | 
|  | 954 |  | 
|  | 955 | memset (fs, 0, sizeof (*fs)); | 
|  | 956 | context->args_size = 0; | 
|  | 957 | context->lsda = 0; | 
|  | 958 |  | 
|  | 959 | fde = _Unwind_Find_FDE (context->ra - 1, &context->bases); | 
|  | 960 | if (fde == NULL) | 
|  | 961 | { | 
|  | 962 | /* Couldn't find frame unwind info for this function.  Try a | 
|  | 963 | target-specific fallback mechanism.  This will necessarily | 
|  | 964 | not provide a personality routine or LSDA.  */ | 
|  | 965 | #ifdef MD_FALLBACK_FRAME_STATE_FOR | 
|  | 966 | MD_FALLBACK_FRAME_STATE_FOR (context, fs, success); | 
|  | 967 | return _URC_END_OF_STACK; | 
|  | 968 | success: | 
|  | 969 | return _URC_NO_REASON; | 
|  | 970 | #else | 
|  | 971 | return _URC_END_OF_STACK; | 
|  | 972 | #endif | 
|  | 973 | } | 
|  | 974 |  | 
|  | 975 | fs->pc = context->bases.func; | 
|  | 976 |  | 
|  | 977 | cie = get_cie (fde); | 
|  | 978 | insn = extract_cie_info (cie, context, fs); | 
|  | 979 | if (insn == NULL) | 
|  | 980 | /* CIE contained unknown augmentation.  */ | 
|  | 981 | return _URC_FATAL_PHASE1_ERROR; | 
|  | 982 |  | 
|  | 983 | /* First decode all the insns in the CIE.  */ | 
|  | 984 | end = (unsigned char *) next_fde ((struct dwarf_fde *) cie); | 
|  | 985 | execute_cfa_program (insn, end, context, fs); | 
|  | 986 |  | 
|  | 987 | /* Locate augmentation for the fde.  */ | 
|  | 988 | aug = (unsigned char *) fde + sizeof (*fde); | 
|  | 989 | aug += 2 * size_of_encoded_value (fs->fde_encoding); | 
|  | 990 | insn = NULL; | 
|  | 991 | if (fs->saw_z) | 
|  | 992 | { | 
|  | 993 | _Unwind_Word i; | 
|  | 994 | aug = read_uleb128 (aug, &i); | 
|  | 995 | insn = aug + i; | 
|  | 996 | } | 
|  | 997 | if (fs->lsda_encoding != DW_EH_PE_omit) | 
|  | 998 | { | 
|  | 999 | _Unwind_Ptr lsda; | 
|  | 1000 | aug = read_encoded_value (context, fs->lsda_encoding, aug, &lsda); | 
|  | 1001 | context->lsda = (void *) lsda; | 
|  | 1002 | } | 
|  | 1003 |  | 
|  | 1004 | /* Then the insns in the FDE up to our target PC.  */ | 
|  | 1005 | if (insn == NULL) | 
|  | 1006 | insn = aug; | 
|  | 1007 | end = (unsigned char *) next_fde (fde); | 
|  | 1008 | execute_cfa_program (insn, end, context, fs); | 
|  | 1009 |  | 
|  | 1010 | return _URC_NO_REASON; | 
|  | 1011 | } | 
|  | 1012 |  | 
|  | 1013 | typedef struct frame_state | 
|  | 1014 | { | 
|  | 1015 | void *cfa; | 
|  | 1016 | void *eh_ptr; | 
|  | 1017 | long cfa_offset; | 
|  | 1018 | long args_size; | 
|  | 1019 | long reg_or_offset[PRE_GCC3_DWARF_FRAME_REGISTERS+1]; | 
|  | 1020 | unsigned short cfa_reg; | 
|  | 1021 | unsigned short retaddr_column; | 
|  | 1022 | char saved[PRE_GCC3_DWARF_FRAME_REGISTERS+1]; | 
|  | 1023 | } frame_state; | 
|  | 1024 |  | 
|  | 1025 | #ifndef STATIC | 
|  | 1026 | # define STATIC | 
|  | 1027 | #endif | 
|  | 1028 |  | 
|  | 1029 | STATIC | 
|  | 1030 | struct frame_state * __frame_state_for (void *, struct frame_state *); | 
|  | 1031 |  | 
|  | 1032 | /* Called from pre-G++ 3.0 __throw to find the registers to restore for | 
|  | 1033 | a given PC_TARGET.  The caller should allocate a local variable of | 
|  | 1034 | `struct frame_state' and pass its address to STATE_IN.  */ | 
|  | 1035 |  | 
|  | 1036 | STATIC | 
|  | 1037 | struct frame_state * | 
|  | 1038 | __frame_state_for (void *pc_target, struct frame_state *state_in) | 
|  | 1039 | { | 
|  | 1040 | struct _Unwind_Context context; | 
|  | 1041 | _Unwind_FrameState fs; | 
|  | 1042 | int reg; | 
|  | 1043 |  | 
|  | 1044 | memset (&context, 0, sizeof (struct _Unwind_Context)); | 
|  | 1045 | context.ra = pc_target + 1; | 
|  | 1046 |  | 
|  | 1047 | if (uw_frame_state_for (&context, &fs) != _URC_NO_REASON) | 
|  | 1048 | return 0; | 
|  | 1049 |  | 
|  | 1050 | /* We have no way to pass a location expression for the CFA to our | 
|  | 1051 | caller.  It wouldn't understand it anyway.  */ | 
|  | 1052 | if (fs.cfa_how == CFA_EXP) | 
|  | 1053 | return 0; | 
|  | 1054 |  | 
|  | 1055 | for (reg = 0; reg < PRE_GCC3_DWARF_FRAME_REGISTERS + 1; reg++) | 
|  | 1056 | { | 
|  | 1057 | state_in->saved[reg] = fs.regs.reg[reg].how; | 
|  | 1058 | switch (state_in->saved[reg]) | 
|  | 1059 | { | 
|  | 1060 | case REG_SAVED_REG: | 
|  | 1061 | state_in->reg_or_offset[reg] = fs.regs.reg[reg].loc.reg; | 
|  | 1062 | break; | 
|  | 1063 | case REG_SAVED_OFFSET: | 
|  | 1064 | state_in->reg_or_offset[reg] = fs.regs.reg[reg].loc.offset; | 
|  | 1065 | break; | 
|  | 1066 | default: | 
|  | 1067 | state_in->reg_or_offset[reg] = 0; | 
|  | 1068 | break; | 
|  | 1069 | } | 
|  | 1070 | } | 
|  | 1071 |  | 
|  | 1072 | state_in->cfa_offset = fs.cfa_offset; | 
|  | 1073 | state_in->cfa_reg = fs.cfa_reg; | 
|  | 1074 | state_in->retaddr_column = fs.retaddr_column; | 
|  | 1075 | state_in->args_size = context.args_size; | 
|  | 1076 | state_in->eh_ptr = fs.eh_ptr; | 
|  | 1077 |  | 
|  | 1078 | return state_in; | 
|  | 1079 | } | 
|  | 1080 |  | 
|  | 1081 | #ifndef _LIBC | 
|  | 1082 |  | 
|  | 1083 | static void | 
|  | 1084 | uw_update_context_1 (struct _Unwind_Context *context, _Unwind_FrameState *fs) | 
|  | 1085 | { | 
|  | 1086 | struct _Unwind_Context orig_context = *context; | 
|  | 1087 | void *cfa; | 
|  | 1088 | long i; | 
|  | 1089 |  | 
|  | 1090 | #ifdef EH_RETURN_STACKADJ_RTX | 
|  | 1091 | /* Special handling here: Many machines do not use a frame pointer, | 
|  | 1092 | and track the CFA only through offsets from the stack pointer from | 
|  | 1093 | one frame to the next.  In this case, the stack pointer is never | 
|  | 1094 | stored, so it has no saved address in the context.  What we do | 
|  | 1095 | have is the CFA from the previous stack frame. | 
|  | 1096 |  | 
|  | 1097 | In very special situations (such as unwind info for signal return), | 
|  | 1098 | there may be location expressions that use the stack pointer as well. | 
|  | 1099 |  | 
|  | 1100 | Do this conditionally for one frame.  This allows the unwind info | 
|  | 1101 | for one frame to save a copy of the stack pointer from the previous | 
|  | 1102 | frame, and be able to use much easier CFA mechanisms to do it. | 
|  | 1103 | Always zap the saved stack pointer value for the next frame; carrying | 
|  | 1104 | the value over from one frame to another doesn't make sense.  */ | 
|  | 1105 |  | 
|  | 1106 | _Unwind_Word tmp_sp; | 
|  | 1107 |  | 
|  | 1108 | if (!orig_context.reg[__builtin_dwarf_sp_column ()]) | 
|  | 1109 | { | 
|  | 1110 | tmp_sp = (_Unwind_Ptr) context->cfa; | 
|  | 1111 | orig_context.reg[__builtin_dwarf_sp_column ()] = &tmp_sp; | 
|  | 1112 | } | 
|  | 1113 | context->reg[__builtin_dwarf_sp_column ()] = NULL; | 
|  | 1114 | #endif | 
|  | 1115 |  | 
|  | 1116 | /* Compute this frame's CFA.  */ | 
|  | 1117 | switch (fs->cfa_how) | 
|  | 1118 | { | 
|  | 1119 | case CFA_REG_OFFSET: | 
|  | 1120 | cfa = (void *) (_Unwind_Ptr) _Unwind_GetGR (&orig_context, fs->cfa_reg); | 
|  | 1121 | cfa += fs->cfa_offset; | 
|  | 1122 | break; | 
|  | 1123 |  | 
|  | 1124 | case CFA_EXP: | 
|  | 1125 | { | 
|  | 1126 | const unsigned char *exp = fs->cfa_exp; | 
|  | 1127 | _Unwind_Word len; | 
|  | 1128 |  | 
|  | 1129 | exp = read_uleb128 (exp, &len); | 
|  | 1130 | cfa = (void *) (_Unwind_Ptr) | 
|  | 1131 | execute_stack_op (exp, exp + len, &orig_context, 0); | 
|  | 1132 | break; | 
|  | 1133 | } | 
|  | 1134 |  | 
|  | 1135 | default: | 
|  | 1136 | abort (); | 
|  | 1137 | } | 
|  | 1138 | context->cfa = cfa; | 
|  | 1139 |  | 
|  | 1140 | /* Compute the addresses of all registers saved in this frame.  */ | 
|  | 1141 | for (i = 0; i < DWARF_FRAME_REGISTERS + 1; ++i) | 
|  | 1142 | switch (fs->regs.reg[i].how) | 
|  | 1143 | { | 
|  | 1144 | case REG_UNSAVED: | 
|  | 1145 | break; | 
|  | 1146 |  | 
|  | 1147 | case REG_SAVED_OFFSET: | 
|  | 1148 | context->reg[i] = cfa + fs->regs.reg[i].loc.offset; | 
|  | 1149 | break; | 
|  | 1150 |  | 
|  | 1151 | case REG_SAVED_REG: | 
|  | 1152 | context->reg[i] = orig_context.reg[fs->regs.reg[i].loc.reg]; | 
|  | 1153 | break; | 
|  | 1154 |  | 
|  | 1155 | case REG_SAVED_EXP: | 
|  | 1156 | { | 
|  | 1157 | const unsigned char *exp = fs->regs.reg[i].loc.exp; | 
|  | 1158 | _Unwind_Word len; | 
|  | 1159 | _Unwind_Ptr val; | 
|  | 1160 |  | 
|  | 1161 | exp = read_uleb128 (exp, &len); | 
|  | 1162 | val = execute_stack_op (exp, exp + len, &orig_context, | 
|  | 1163 | (_Unwind_Ptr) cfa); | 
|  | 1164 | context->reg[i] = (void *) val; | 
|  | 1165 | } | 
|  | 1166 | break; | 
|  | 1167 | } | 
|  | 1168 | } | 
|  | 1169 |  | 
|  | 1170 | /* CONTEXT describes the unwind state for a frame, and FS describes the FDE | 
|  | 1171 | of its caller.  Update CONTEXT to refer to the caller as well.  Note | 
|  | 1172 | that the args_size and lsda members are not updated here, but later in | 
|  | 1173 | uw_frame_state_for.  */ | 
|  | 1174 |  | 
|  | 1175 | static void | 
|  | 1176 | uw_update_context (struct _Unwind_Context *context, _Unwind_FrameState *fs) | 
|  | 1177 | { | 
|  | 1178 | uw_update_context_1 (context, fs); | 
|  | 1179 |  | 
|  | 1180 | /* Compute the return address now, since the return address column | 
|  | 1181 | can change from frame to frame.  */ | 
|  | 1182 | context->ra = __builtin_extract_return_addr | 
|  | 1183 | ((void *) (_Unwind_Ptr) _Unwind_GetGR (context, fs->retaddr_column)); | 
|  | 1184 | } | 
|  | 1185 |  | 
|  | 1186 | /* Fill in CONTEXT for top-of-stack.  The only valid registers at this | 
|  | 1187 | level will be the return address and the CFA.  */ | 
|  | 1188 |  | 
|  | 1189 | #define uw_init_context(CONTEXT)					   \ | 
|  | 1190 | do									   \ | 
|  | 1191 | {									   \ | 
|  | 1192 | /* Do any necessary initialization to access arbitrary stack frames. \ | 
|  | 1193 | On the SPARC, this means flushing the register windows.  */	   \ | 
|  | 1194 | __builtin_unwind_init ();						   \ | 
|  | 1195 | uw_init_context_1 (CONTEXT, __builtin_dwarf_cfa (),		   \ | 
|  | 1196 | __builtin_return_address (0));			   \ | 
|  | 1197 | }									   \ | 
|  | 1198 | while (0) | 
|  | 1199 |  | 
|  | 1200 | static void | 
|  | 1201 | uw_init_context_1 (struct _Unwind_Context *context, | 
|  | 1202 | void *outer_cfa, void *outer_ra) | 
|  | 1203 | { | 
|  | 1204 | void *ra = __builtin_extract_return_addr (__builtin_return_address (0)); | 
|  | 1205 | _Unwind_FrameState fs; | 
|  | 1206 | _Unwind_Word sp_slot; | 
|  | 1207 |  | 
|  | 1208 | memset (context, 0, sizeof (struct _Unwind_Context)); | 
|  | 1209 | context->ra = ra; | 
|  | 1210 |  | 
|  | 1211 | if (uw_frame_state_for (context, &fs) != _URC_NO_REASON) | 
|  | 1212 | abort (); | 
|  | 1213 |  | 
|  | 1214 | /* Force the frame state to use the known cfa value.  */ | 
|  | 1215 | sp_slot = (_Unwind_Ptr) outer_cfa; | 
|  | 1216 | context->reg[__builtin_dwarf_sp_column ()] = &sp_slot; | 
|  | 1217 | fs.cfa_how = CFA_REG_OFFSET; | 
|  | 1218 | fs.cfa_reg = __builtin_dwarf_sp_column (); | 
|  | 1219 | fs.cfa_offset = 0; | 
|  | 1220 |  | 
|  | 1221 | uw_update_context_1 (context, &fs); | 
|  | 1222 |  | 
|  | 1223 | /* If the return address column was saved in a register in the | 
|  | 1224 | initialization context, then we can't see it in the given | 
|  | 1225 | call frame data.  So have the initialization context tell us.  */ | 
|  | 1226 | context->ra = __builtin_extract_return_addr (outer_ra); | 
|  | 1227 | } | 
|  | 1228 |  | 
|  | 1229 |  | 
|  | 1230 | /* Install TARGET into CURRENT so that we can return to it.  This is a | 
|  | 1231 | macro because __builtin_eh_return must be invoked in the context of | 
|  | 1232 | our caller.  */ | 
|  | 1233 |  | 
|  | 1234 | #define uw_install_context(CURRENT, TARGET)				 \ | 
|  | 1235 | do									 \ | 
|  | 1236 | {									 \ | 
|  | 1237 | long offset = uw_install_context_1 ((CURRENT), (TARGET));		 \ | 
|  | 1238 | void *handler = __builtin_frob_return_addr ((TARGET)->ra);	 \ | 
|  | 1239 | __builtin_eh_return (offset, handler);				 \ | 
|  | 1240 | }									 \ | 
|  | 1241 | while (0) | 
|  | 1242 |  | 
|  | 1243 | static inline void | 
|  | 1244 | init_dwarf_reg_size_table (void) | 
|  | 1245 | { | 
|  | 1246 | __builtin_init_dwarf_reg_size_table (dwarf_reg_size_table); | 
|  | 1247 | } | 
|  | 1248 |  | 
|  | 1249 | static long | 
|  | 1250 | uw_install_context_1 (struct _Unwind_Context *current, | 
|  | 1251 | struct _Unwind_Context *target) | 
|  | 1252 | { | 
|  | 1253 | long i; | 
|  | 1254 |  | 
|  | 1255 | #if __GTHREADS | 
|  | 1256 | { | 
|  | 1257 | static __gthread_once_t once_regsizes = __GTHREAD_ONCE_INIT; | 
|  | 1258 | if (__gthread_once (&once_regsizes, init_dwarf_reg_size_table) != 0 | 
|  | 1259 | || dwarf_reg_size_table[0] == 0) | 
|  | 1260 | init_dwarf_reg_size_table (); | 
|  | 1261 | } | 
|  | 1262 | #else | 
|  | 1263 | if (dwarf_reg_size_table[0] == 0) | 
|  | 1264 | init_dwarf_reg_size_table (); | 
|  | 1265 | #endif | 
|  | 1266 |  | 
|  | 1267 | for (i = 0; i < DWARF_FRAME_REGISTERS; ++i) | 
|  | 1268 | { | 
|  | 1269 | void *c = current->reg[i]; | 
|  | 1270 | void *t = target->reg[i]; | 
|  | 1271 | if (t && c && t != c) | 
|  | 1272 | memcpy (c, t, dwarf_reg_size_table[i]); | 
|  | 1273 | } | 
|  | 1274 |  | 
|  | 1275 | #ifdef EH_RETURN_STACKADJ_RTX | 
|  | 1276 | { | 
|  | 1277 | void *target_cfa; | 
|  | 1278 |  | 
|  | 1279 | /* If the last frame records a saved stack pointer, use it.  */ | 
|  | 1280 | if (target->reg[__builtin_dwarf_sp_column ()]) | 
|  | 1281 | target_cfa = (void *)(_Unwind_Ptr) | 
|  | 1282 | _Unwind_GetGR (target, __builtin_dwarf_sp_column ()); | 
|  | 1283 | else | 
|  | 1284 | target_cfa = target->cfa; | 
|  | 1285 |  | 
|  | 1286 | /* We adjust SP by the difference between CURRENT and TARGET's CFA.  */ | 
|  | 1287 | if (STACK_GROWS_DOWNWARD) | 
|  | 1288 | return target_cfa - current->cfa + target->args_size; | 
|  | 1289 | else | 
|  | 1290 | return current->cfa - target_cfa - target->args_size; | 
|  | 1291 | } | 
|  | 1292 | #else | 
|  | 1293 | return 0; | 
|  | 1294 | #endif | 
|  | 1295 | } | 
|  | 1296 |  | 
|  | 1297 | static inline _Unwind_Ptr | 
|  | 1298 | uw_identify_context (struct _Unwind_Context *context) | 
|  | 1299 | { | 
|  | 1300 | return _Unwind_GetIP (context); | 
|  | 1301 | } | 
|  | 1302 |  | 
|  | 1303 |  | 
|  | 1304 | #include "unwind.inc" | 
|  | 1305 |  | 
|  | 1306 | #endif /* _LIBC */ |