static _Unwind_Ptr get_ttype_entry_for (region_descriptor *region, long filter) { _Unwind_Ptr ttype_entry; filter *= size_of_encoded_value (region->ttype_encoding); read_encoded_value_with_base (region->ttype_encoding, region->ttype_base, region->ttype_table - filter, &ttype_entry); return ttype_entry; }
static int get_cie_encoding (const struct dwarf_cie *cie) { const unsigned char *aug, *p; _Unwind_Ptr dummy; _uleb128_t utmp; _sleb128_t stmp; aug = cie->augmentation; p = aug + strlen ((const char *)aug) + 1; /* Skip the augmentation string. */ if (__builtin_expect (cie->version >= 4, 0)) { if (p[0] != sizeof (void *) || p[1] != 0) return DW_EH_PE_omit; /* We are not prepared to handle unexpected address sizes or segment selectors. */ p += 2; /* Skip address size and segment size. */ } if (aug[0] != 'z') return DW_EH_PE_absptr; p = read_uleb128 (p, &utmp); /* Skip code alignment. */ p = read_sleb128 (p, &stmp); /* Skip data alignment. */ if (cie->version == 1) /* Skip return address column. */ p++; else p = read_uleb128 (p, &utmp); aug++; /* Skip 'z' */ p = read_uleb128 (p, &utmp); /* Skip augmentation length. */ while (1) { /* This is what we're looking for. */ if (*aug == 'R') return *p; /* Personality encoding and pointer. */ else if (*aug == 'P') { /* ??? Avoid dereferencing indirect pointers, since we're faking the base address. Gotta keep DW_EH_PE_aligned intact, however. */ p = read_encoded_value_with_base (*p & 0x7F, 0, p + 1, &dummy); } /* LSDA encoding. */ else if (*aug == 'L') p++; /* Otherwise end of string, or unknown augmentation. */ else return DW_EH_PE_absptr; aug++; } }
static Class get_ttype_entry (struct lsda_header_info *info, _Unwind_Word i) { _Unwind_Ptr ptr; i *= size_of_encoded_value (info->ttype_encoding); read_encoded_value_with_base (info->ttype_encoding, info->ttype_base, info->TType - i, &ptr); /* NULL ptr means catch-all. */ if (ptr) return objc_get_class ((const char *) ptr); else return 0; }
static Class get_ttype_entry (struct lsda_header_info *info, _Unwind_Word i) { _Unwind_Ptr ptr; i *= size_of_encoded_value (info->ttype_encoding); read_encoded_value_with_base (info->ttype_encoding, info->ttype_base, info->TType - i, &ptr); /* NULL ptr means catch-all. Note that if the class is not found, this will abort the program. */ if (ptr) return objc_getRequiredClass ((const char *) ptr); else return 0; }
static int get_cie_encoding (struct dwarf_cie *cie) { const unsigned char *aug, *p; _Unwind_Ptr dummy; _Unwind_Word utmp; _Unwind_Sword stmp; aug = cie->augmentation; if (aug[0] != 'z') return DW_EH_PE_absptr; /* Skip the augmentation string. */ p = aug + strlen ((const char *) aug) + 1; p = read_uleb128 (p, &utmp); /* Skip code alignment. */ p = read_sleb128 (p, &stmp); /* Skip data alignment. */ p++; /* Skip return address column. */ aug++; /* Skip 'z' */ p = read_uleb128 (p, &utmp); /* Skip augmentation length. */ while (1) { /* This is what we're looking for. */ if (*aug == 'R') return *p; /* Personality encoding and pointer. */ else if (*aug == 'P') { /* ??? Avoid dereferencing indirect pointers, since we're faking the base address. Gotta keep DW_EH_PE_aligned intact, however. */ p = read_encoded_value_with_base (*p & 0x7F, 0, p + 1, &dummy); } /* LSDA encoding. */ else if (*aug == 'L') p++; /* Otherwise end of string, or unknown augmentation. */ else return DW_EH_PE_absptr; aug++; } }
static inline const fde * examine_objects (void *pc, struct dwarf_eh_bases *bases, int dont_alloc) { const fde *result = NULL; struct live_images *image; image = _keymgr_get_and_lock_processwide_ptr (KEYMGR_GCC3_LIVE_IMAGE_LIST); for (; image != NULL; image = image->next) if ((image->examined_p & EXAMINED_IMAGE_MASK) == 0) { char *fde = NULL; unsigned long sz; /* For ppc only check whether or not we have __DATA eh frames. */ #ifdef __ppc__ fde = getsectdatafromheader (image->mh, "__DATA", "__eh_frame", &sz); #endif if (fde == NULL) { #if __LP64__ fde = getsectdatafromheader_64 ((struct mach_header_64 *) image->mh, "__TEXT", "__eh_frame", &sz); #else fde = getsectdatafromheader (image->mh, "__TEXT", "__eh_frame", &sz); #endif if (fde != NULL) image->examined_p |= IMAGE_IS_TEXT_MASK; } /* If .eh_frame is empty, don't register at all. */ if (fde != NULL && sz > 0) { char *real_fde = (fde + image->vm_slide); struct object *ob = NULL; struct object panicob; if (! dont_alloc) ob = calloc (1, sizeof (struct object)); dont_alloc |= ob == NULL; if (dont_alloc) ob = &panicob; ob->pc_begin = (void *)-1; ob->tbase = 0; ob->dbase = 0; ob->u.single = (struct dwarf_fde *)real_fde; ob->s.i = 0; ob->s.b.encoding = DW_EH_PE_omit; ob->fde_end = real_fde + sz; image->fde = real_fde; result = search_object (ob, pc); if (! dont_alloc) { struct object **p; image->destructor = live_image_destructor; image->object_info = ob; image->examined_p |= (EXAMINED_IMAGE_MASK | DESTRUCTOR_MAY_BE_CALLED_LIVE); /* Insert the object into the classified list. */ for (p = &seen_objects; *p ; p = &(*p)->next) if ((*p)->pc_begin < ob->pc_begin) break; ob->next = *p; *p = ob; } if (result) { int encoding; _Unwind_Ptr func; bases->tbase = ob->tbase; bases->dbase = ob->dbase; encoding = ob->s.b.encoding; if (ob->s.b.mixed_encoding) encoding = get_fde_encoding (result); read_encoded_value_with_base (encoding, base_from_object (encoding, ob), result->pc_begin, &func); bases->func = (void *) func; break; } } else image->examined_p |= EXAMINED_IMAGE_MASK; } _keymgr_unlock_processwide_ptr (KEYMGR_GCC3_LIVE_IMAGE_LIST); return result; }
static inline const unsigned char * read_encoded_value(struct _Unwind_Context *context, unsigned char encoding, const unsigned char *p, _Unwind_Ptr *val) { return read_encoded_value_with_base(encoding, base_of_encoded_value(encoding, context), p, val); }
enum compact_entry_type _Unwind_Search_Compact_eh_hdr (void *pc, const unsigned char *hdr, struct compact_eh_bases *bases) { int lo, hi, mid; _Unwind_Ptr p; _Unwind_Ptr nrec; const struct compact_eh_index *ind; bases->eh_encoding = hdr[1]; read_encoded_value_with_base (DW_EH_PE_absptr | DW_EH_PE_udata4, 0, hdr + 4, &nrec); if (nrec == 0) return CET_not_found; ind = (const struct compact_eh_index *)(hdr + 8); lo = 0; hi = nrec - 1; while (1) { mid = (lo + hi) / 2; p = decode_index_ptr (&ind[mid].fn); if ((_Unwind_Ptr)pc < p) { if (mid == 0) return CET_not_found; hi = mid - 1; } else { if (mid == hi) break; p = decode_index_ptr (&ind[mid + 1].fn); if ((_Unwind_Ptr)pc < p) break; lo = mid + 1; } } p = decode_index_ptr (&ind[mid].fn); bases->func = (void *)p; if ((ind[mid].fn & 1) == 0) { bases->entry = &ind[mid].data; /* If we hit the terminating CANTUNWIND entry then assume we're looking in the wrong table. */ if (mid == (int)nrec - 1 && ind[mid].data == 0x015d5d01) return CET_not_found; return CET_inline; } else { p = decode_index_ptr (&ind[mid].data); bases->entry = (const void *)p; if (ind[mid].data & 1) return CET_FDE; else return CET_outline; } }