Esempio n. 1
0
_Unwind_VRS_Result _Unwind_VRS_Get(
    _Unwind_Context *context,
    _Unwind_VRS_RegClass regclass,
    uint32_t regno,
    _Unwind_VRS_DataRepresentation representation,
    void *valuep) {
  _LIBUNWIND_TRACE_API("_Unwind_SetGR(context=%p, regclass=%d reg=%d, rep=%d, "
                             "value=0x%0llX)\n", context, regclass,
                             regno, representation, *((uint32_t*)valuep));
  unw_cursor_t *cursor = (unw_cursor_t *)context;
  switch (regclass) {
    case _UVRSC_CORE: {
      if (representation != _UVRSD_UINT32)
        _LIBUNWIND_ABORT("Core register representation must be _UVRSD_UINT32.");
      return unw_get_reg(cursor, regno, (unw_word_t*)valuep) == UNW_ESUCCESS ?
          _UVRSR_OK : _UVRSR_FAILED;
    }
    // FIXME: Are these right? See 4.7 on lazy-saving
    case _UVRSC_WMMXD:
    case _UVRSC_WMMXC:
    case _UVRSC_VFP: {
      unw_fpreg_t value;
      if (unw_get_fpreg(cursor, regno, &value) != UNW_ESUCCESS)
        return _UVRSR_FAILED;
      switch (representation) {
        case _UVRSD_VFPX:
          // TODO(ajwong): What does this mean?
          break;
        case _UVRSD_UINT64: {
          uint64_t tmp;
          memcpy(&tmp, &value, sizeof(tmp));
          *(uint64_t*)valuep = tmp;
          break;
        }
        case _UVRSD_FLOAT: {
          float tmp;
          memcpy(&tmp, &value, sizeof(tmp));
          *(float*)valuep = tmp;
          break;
        }
        case _UVRSD_DOUBLE: {
          double tmp;
          memcpy(&tmp, &value, sizeof(tmp));
          *(double*)valuep = tmp;
          break;
        }
        case _UVRSD_UINT32: {
          uint32_t tmp;
          memcpy(&tmp, &value, sizeof(tmp));
          *(uint32_t*)valuep = tmp;
          break;
        }
        default:
          _LIBUNWIND_ABORT("Invalid VFP data representation.");
      }
      return _UVRSR_OK;
    }
  }
  return _UVRSR_NOT_IMPLEMENTED;
}
typename A::pint_t DwarfInstructions<A, R>::getSavedRegister(
    A &addressSpace, const R &registers, pint_t cfa,
    const RegisterLocation &savedReg) {
  switch (savedReg.location) {
  case CFI_Parser<A>::kRegisterInCFA:
    return addressSpace.getP(cfa + (pint_t)savedReg.value);

  case CFI_Parser<A>::kRegisterAtExpression:
    return addressSpace.getP(
        evaluateExpression((pint_t)savedReg.value, addressSpace,
                            registers, cfa));

  case CFI_Parser<A>::kRegisterIsExpression:
    return evaluateExpression((pint_t)savedReg.value, addressSpace,
                              registers, cfa);

  case CFI_Parser<A>::kRegisterInRegister:
    return registers.getRegister((int)savedReg.value);

  case CFI_Parser<A>::kRegisterUnused:
  case CFI_Parser<A>::kRegisterOffsetFromCFA:
    // FIX ME
    break;
  }
  _LIBUNWIND_ABORT("unsupported restore location for register");
}
Esempio n. 3
0
/// Called by personality handler during phase 2 to get base address for text
/// relative encodings.
_LIBUNWIND_EXPORT uintptr_t
_Unwind_GetTextRelBase(struct _Unwind_Context *context) {
  // Not supported or needed for sjlj based unwinding
  (void)context;
  _LIBUNWIND_TRACE_API("_Unwind_GetTextRelBase(context=%p)\n", context);
  _LIBUNWIND_ABORT("_Unwind_GetTextRelBase() not implemented");
}
Esempio n. 4
0
///  Called by __cxa_rethrow().
_LIBUNWIND_EXPORT _Unwind_Reason_Code
_Unwind_Resume_or_Rethrow(_Unwind_Exception *exception_object) {
#if LIBCXXABI_ARM_EHABI
  _LIBUNWIND_TRACE_API("_Unwind_Resume_or_Rethrow(ex_obj=%p), "
                       "private_1=%ld\n",
                       exception_object,
                       (long)exception_object->unwinder_cache.reserved1);
#else
  _LIBUNWIND_TRACE_API("_Unwind_Resume_or_Rethrow(ex_obj=%p), "
                       "private_1=%ld\n",
                       exception_object,
                       (long)exception_object->private_1);
#endif

#if LIBCXXABI_ARM_EHABI
  // _Unwind_RaiseException on EHABI will always set the reserved1 field to 0,
  // which is in the same position as private_1 below.
  return _Unwind_RaiseException(exception_object);
#else
  // If this is non-forced and a stopping place was found, then this is a
  // re-throw.
  // Call _Unwind_RaiseException() as if this was a new exception
  if (exception_object->private_1 == 0) {
    return _Unwind_RaiseException(exception_object);
    // Will return if there is no catch clause, so that __cxa_rethrow can call
    // std::terminate().
  }

  // Call through to _Unwind_Resume() which distiguishes between forced and
  // regular exceptions.
  _Unwind_Resume(exception_object);
  _LIBUNWIND_ABORT("_Unwind_Resume_or_Rethrow() called _Unwind_RaiseException()"
                   " which unexpectedly returned");
#endif
}
Esempio n. 5
0
size_t EHHeaderParser<A>::getTableEntrySize(uint8_t tableEnc) {
  switch (tableEnc & 0x0f) {
  case DW_EH_PE_sdata2:
  case DW_EH_PE_udata2:
    return 4;
  case DW_EH_PE_sdata4:
  case DW_EH_PE_udata4:
    return 8;
  case DW_EH_PE_sdata8:
  case DW_EH_PE_udata8:
    return 16;
  case DW_EH_PE_sleb128:
  case DW_EH_PE_uleb128:
    _LIBUNWIND_ABORT("Can't binary search on variable length encoded data.");
  case DW_EH_PE_omit:
    return 0;
  default:
    _LIBUNWIND_ABORT("Unknown DWARF encoding for search table.");
  }
}
Esempio n. 6
0
/// When _Unwind_RaiseException() is in phase2, it hands control
/// to the personality function at each frame.  The personality
/// may force a jump to a landing pad in that function, the landing
/// pad code may then call _Unwind_Resume() to continue with the
/// unwinding.  Note: the call to _Unwind_Resume() is from compiler
/// geneated user code.  All other _Unwind_* routines are called
/// by the C++ runtime __cxa_* routines.
///
/// Re-throwing an exception is implemented by having the code call
/// __cxa_rethrow() which in turn calls _Unwind_Resume_or_Rethrow()
_LIBUNWIND_EXPORT void
_Unwind_SjLj_Resume(struct _Unwind_Exception *exception_object) {
  _LIBUNWIND_TRACE_API("_Unwind_SjLj_Resume(ex_obj=%p)\n", exception_object);

  if (exception_object->private_1 != 0)
    unwind_phase2_forced(exception_object,
                         (_Unwind_Stop_Fn) exception_object->private_1,
                         (void *)exception_object->private_2);
  else
    unwind_phase2(exception_object);

  // clients assume _Unwind_Resume() does not return, so all we can do is abort.
  _LIBUNWIND_ABORT("_Unwind_SjLj_Resume() can't return");
}
Esempio n. 7
0
/// When _Unwind_RaiseException() is in phase2, it hands control
/// to the personality function at each frame.  The personality
/// may force a jump to a landing pad in that function, the landing
/// pad code may then call _Unwind_Resume() to continue with the
/// unwinding.  Note: the call to _Unwind_Resume() is from compiler
/// geneated user code.  All other _Unwind_* routines are called
/// by the C++ runtime __cxa_* routines.
///
/// Note: re-throwing an exception (as opposed to continuing the unwind)
/// is implemented by having the code call __cxa_rethrow() which
/// in turn calls _Unwind_Resume_or_Rethrow().
_LIBUNWIND_EXPORT void
_Unwind_Resume(_Unwind_Exception *exception_object) {
  _LIBUNWIND_TRACE_API("_Unwind_Resume(ex_obj=%p)\n", (void *)exception_object);
  unw_context_t uc;
  unw_getcontext(&uc);

  if (exception_object->private_1 != 0)
    unwind_phase2_forced(&uc, exception_object,
                         (_Unwind_Stop_Fn) exception_object->private_1,
                         (void *)exception_object->private_2);
  else
    unwind_phase2(&uc, exception_object);

  // Clients assume _Unwind_Resume() does not return, so all we can do is abort.
  _LIBUNWIND_ABORT("_Unwind_Resume() can't return");
}
Esempio n. 8
0
///  Called by __cxa_rethrow().
_LIBUNWIND_EXPORT _Unwind_Reason_Code
_Unwind_SjLj_Resume_or_Rethrow(struct _Unwind_Exception *exception_object) {
  _LIBUNWIND_TRACE_API("__Unwind_SjLj_Resume_or_Rethrow(ex_obj=%p), "
                             "private_1=%ld\n",
                              exception_object, exception_object->private_1);
  // If this is non-forced and a stopping place was found, then this is a
  // re-throw.
  // Call _Unwind_RaiseException() as if this was a new exception.
  if (exception_object->private_1 == 0) {
    return _Unwind_SjLj_RaiseException(exception_object);
    // should return if there is no catch clause, so that __cxa_rethrow can call
    // std::terminate()
  }

  // Call through to _Unwind_Resume() which distiguishes between forced and
  // regular exceptions.
  _Unwind_SjLj_Resume(exception_object);
  _LIBUNWIND_ABORT("__Unwind_SjLj_Resume_or_Rethrow() called "
                    "_Unwind_SjLj_Resume() which unexpectedly returned");
}
Esempio n. 9
0
/// When _Unwind_RaiseException() is in phase2, it hands control
/// to the personality function at each frame.  The personality
/// may force a jump to a landing pad in that function, the landing
/// pad code may then call _Unwind_Resume() to continue with the
/// unwinding.  Note: the call to _Unwind_Resume() is from compiler
/// geneated user code.  All other _Unwind_* routines are called
/// by the C++ runtime __cxa_* routines.
///
/// Note: re-throwing an exception (as opposed to continuing the unwind)
/// is implemented by having the code call __cxa_rethrow() which
/// in turn calls _Unwind_Resume_or_Rethrow().
_LIBUNWIND_EXPORT void
_Unwind_Resume(struct _Unwind_Exception *exception_object) {
  _LIBUNWIND_TRACE_API("_Unwind_Resume(ex_obj=%p)\n", exception_object);
  unw_context_t uc;
  unw_getcontext(&uc);

#ifdef __arm__
  // TODO(piman): Do we need a "force unwind" mechanism?
#else
  if (exception_object->private_1 != 0)
    unwind_phase2_forced(&uc, exception_object,
                         (_Unwind_Stop_Fn) exception_object->private_1,
                         (void *)exception_object->private_2);
  else
#endif
    unwind_phase2(&uc, exception_object, true);

  // Clients assume _Unwind_Resume() does not return, so all we can do is abort.
  _LIBUNWIND_ABORT("_Unwind_Resume() can't return");
}
Esempio n. 10
0
_Unwind_VRS_Result _Unwind_VRS_Pop(
    _Unwind_Context *context,
    _Unwind_VRS_RegClass regclass,
    uint32_t discriminator,
    _Unwind_VRS_DataRepresentation representation) {
  if (regclass != _UVRSC_CORE || representation != _UVRSD_UINT32) {
    // TODO(piman): VFP, ...
    _LIBUNWIND_ABORT("during phase1 personality function said it would "
                     "stop here, but now if phase2 it did not stop here");
    return _UVRSR_NOT_IMPLEMENTED;
  }
  bool do13 = false;
  uint32_t reg13Value = 0;
  uint32_t* sp;
  if (_Unwind_VRS_Get(context, _UVRSC_CORE, UNW_ARM_SP,
                      _UVRSD_UINT32, &sp) != _UVRSR_OK) {
    return _UVRSR_FAILED;
  }
  for (int i = 0; i < 16; ++i) {
    if (!(discriminator & (1<<i)))
      continue;
    uint32_t value = *sp++;
    if (i == 13) {
      reg13Value = value;
      do13 = true;
    } else {
      if (_Unwind_VRS_Set(context, _UVRSC_CORE, UNW_ARM_R0 + i,
                          _UVRSD_UINT32, &value) != _UVRSR_OK) {
        return _UVRSR_FAILED;
      }
    }
  }
  if (do13) {
    return _Unwind_VRS_Set(context, _UVRSC_CORE, UNW_ARM_SP,
                           _UVRSD_UINT32, &reg13Value);
  } else {
    return _Unwind_VRS_Set(context, _UVRSC_CORE, UNW_ARM_SP,
                        _UVRSD_UINT32, &sp);
  }
}
typename A::pint_t
DwarfInstructions<A, R>::evaluateExpression(pint_t expression, A &addressSpace,
                                            const R &registers,
                                            pint_t initialStackValue) {
  const bool log = false;
  pint_t p = expression;
  pint_t expressionEnd = expression + 20; // temp, until len read
  pint_t length = (pint_t)addressSpace.getULEB128(p, expressionEnd);
  expressionEnd = p + length;
  if (log)
    fprintf(stderr, "evaluateExpression(): length=%llu\n", (uint64_t)length);
  pint_t stack[100];
  pint_t *sp = stack;
  *(++sp) = initialStackValue;

  while (p < expressionEnd) {
    if (log) {
      for (pint_t *t = sp; t > stack; --t) {
        fprintf(stderr, "sp[] = 0x%llX\n", (uint64_t)(*t));
      }
    }
    uint8_t opcode = addressSpace.get8(p++);
    sint_t svalue, svalue2;
    pint_t value;
    uint32_t reg;
    switch (opcode) {
    case DW_OP_addr:
      // push immediate address sized value
      value = addressSpace.getP(p);
      p += sizeof(pint_t);
      *(++sp) = value;
      if (log)
        fprintf(stderr, "push 0x%llX\n", (uint64_t) value);
      break;

    case DW_OP_deref:
      // pop stack, dereference, push result
      value = *sp--;
      *(++sp) = addressSpace.getP(value);
      if (log)
        fprintf(stderr, "dereference 0x%llX\n", (uint64_t) value);
      break;

    case DW_OP_const1u:
      // push immediate 1 byte value
      value = addressSpace.get8(p);
      p += 1;
      *(++sp) = value;
      if (log)
        fprintf(stderr, "push 0x%llX\n", (uint64_t) value);
      break;

    case DW_OP_const1s:
      // push immediate 1 byte signed value
      svalue = (int8_t) addressSpace.get8(p);
      p += 1;
      *(++sp) = (pint_t)svalue;
      if (log)
        fprintf(stderr, "push 0x%llX\n", (uint64_t) svalue);
      break;

    case DW_OP_const2u:
      // push immediate 2 byte value
      value = addressSpace.get16(p);
      p += 2;
      *(++sp) = value;
      if (log)
        fprintf(stderr, "push 0x%llX\n", (uint64_t) value);
      break;

    case DW_OP_const2s:
      // push immediate 2 byte signed value
      svalue = (int16_t) addressSpace.get16(p);
      p += 2;
      *(++sp) = (pint_t)svalue;
      if (log)
        fprintf(stderr, "push 0x%llX\n", (uint64_t) svalue);
      break;

    case DW_OP_const4u:
      // push immediate 4 byte value
      value = addressSpace.get32(p);
      p += 4;
      *(++sp) = value;
      if (log)
        fprintf(stderr, "push 0x%llX\n", (uint64_t) value);
      break;

    case DW_OP_const4s:
      // push immediate 4 byte signed value
      svalue = (int32_t)addressSpace.get32(p);
      p += 4;
      *(++sp) = (pint_t)svalue;
      if (log)
        fprintf(stderr, "push 0x%llX\n", (uint64_t) svalue);
      break;

    case DW_OP_const8u:
      // push immediate 8 byte value
      value = (pint_t)addressSpace.get64(p);
      p += 8;
      *(++sp) = value;
      if (log)
        fprintf(stderr, "push 0x%llX\n", (uint64_t) value);
      break;

    case DW_OP_const8s:
      // push immediate 8 byte signed value
      value = (pint_t)addressSpace.get64(p);
      p += 8;
      *(++sp) = value;
      if (log)
        fprintf(stderr, "push 0x%llX\n", (uint64_t) value);
      break;

    case DW_OP_constu:
      // push immediate ULEB128 value
      value = (pint_t)addressSpace.getULEB128(p, expressionEnd);
      *(++sp) = value;
      if (log)
        fprintf(stderr, "push 0x%llX\n", (uint64_t) value);
      break;

    case DW_OP_consts:
      // push immediate SLEB128 value
      svalue = (sint_t)addressSpace.getSLEB128(p, expressionEnd);
      *(++sp) = (pint_t)svalue;
      if (log)
        fprintf(stderr, "push 0x%llX\n", (uint64_t) svalue);
      break;

    case DW_OP_dup:
      // push top of stack
      value = *sp;
      *(++sp) = value;
      if (log)
        fprintf(stderr, "duplicate top of stack\n");
      break;

    case DW_OP_drop:
      // pop
      --sp;
      if (log)
        fprintf(stderr, "pop top of stack\n");
      break;

    case DW_OP_over:
      // dup second
      value = sp[-1];
      *(++sp) = value;
      if (log)
        fprintf(stderr, "duplicate second in stack\n");
      break;

    case DW_OP_pick:
      // pick from
      reg = addressSpace.get8(p);
      p += 1;
      value = sp[-reg];
      *(++sp) = value;
      if (log)
        fprintf(stderr, "duplicate %d in stack\n", reg);
      break;

    case DW_OP_swap:
      // swap top two
      value = sp[0];
      sp[0] = sp[-1];
      sp[-1] = value;
      if (log)
        fprintf(stderr, "swap top of stack\n");
      break;

    case DW_OP_rot:
      // rotate top three
      value = sp[0];
      sp[0] = sp[-1];
      sp[-1] = sp[-2];
      sp[-2] = value;
      if (log)
        fprintf(stderr, "rotate top three of stack\n");
      break;

    case DW_OP_xderef:
      // pop stack, dereference, push result
      value = *sp--;
      *sp = *((pint_t*)value);
      if (log)
        fprintf(stderr, "x-dereference 0x%llX\n", (uint64_t) value);
      break;

    case DW_OP_abs:
      svalue = (sint_t)*sp;
      if (svalue < 0)
        *sp = (pint_t)(-svalue);
      if (log)
        fprintf(stderr, "abs\n");
      break;

    case DW_OP_and:
      value = *sp--;
      *sp &= value;
      if (log)
        fprintf(stderr, "and\n");
      break;

    case DW_OP_div:
      svalue = (sint_t)(*sp--);
      svalue2 = (sint_t)*sp;
      *sp = (pint_t)(svalue2 / svalue);
      if (log)
        fprintf(stderr, "div\n");
      break;

    case DW_OP_minus:
      value = *sp--;
      *sp = *sp - value;
      if (log)
        fprintf(stderr, "minus\n");
      break;

    case DW_OP_mod:
      svalue = (sint_t)(*sp--);
      svalue2 = (sint_t)*sp;
      *sp = (pint_t)(svalue2 % svalue);
      if (log)
        fprintf(stderr, "module\n");
      break;

    case DW_OP_mul:
      svalue = (sint_t)(*sp--);
      svalue2 = (sint_t)*sp;
      *sp = (pint_t)(svalue2 * svalue);
      if (log)
        fprintf(stderr, "mul\n");
      break;

    case DW_OP_neg:
      *sp = 0 - *sp;
      if (log)
        fprintf(stderr, "neg\n");
      break;

    case DW_OP_not:
      svalue = (sint_t)(*sp);
      *sp = (pint_t)(~svalue);
      if (log)
        fprintf(stderr, "not\n");
      break;

    case DW_OP_or:
      value = *sp--;
      *sp |= value;
      if (log)
        fprintf(stderr, "or\n");
      break;

    case DW_OP_plus:
      value = *sp--;
      *sp += value;
      if (log)
        fprintf(stderr, "plus\n");
      break;

    case DW_OP_plus_uconst:
      // pop stack, add uelb128 constant, push result
      *sp += addressSpace.getULEB128(p, expressionEnd);
      if (log)
        fprintf(stderr, "add constant\n");
      break;

    case DW_OP_shl:
      value = *sp--;
      *sp = *sp << value;
      if (log)
        fprintf(stderr, "shift left\n");
      break;

    case DW_OP_shr:
      value = *sp--;
      *sp = *sp >> value;
      if (log)
        fprintf(stderr, "shift left\n");
      break;

    case DW_OP_shra:
      value = *sp--;
      svalue = (sint_t)*sp;
      *sp = (pint_t)(svalue >> value);
      if (log)
        fprintf(stderr, "shift left arithmetric\n");
      break;

    case DW_OP_xor:
      value = *sp--;
      *sp ^= value;
      if (log)
        fprintf(stderr, "xor\n");
      break;

    case DW_OP_skip:
      svalue = (int16_t) addressSpace.get16(p);
      p += 2;
      p = (pint_t)((sint_t)p + svalue);
      if (log)
        fprintf(stderr, "skip %lld\n", (uint64_t) svalue);
      break;

    case DW_OP_bra:
      svalue = (int16_t) addressSpace.get16(p);
      p += 2;
      if (*sp--)
        p = (pint_t)((sint_t)p + svalue);
      if (log)
        fprintf(stderr, "bra %lld\n", (uint64_t) svalue);
      break;

    case DW_OP_eq:
      value = *sp--;
      *sp = (*sp == value);
      if (log)
        fprintf(stderr, "eq\n");
      break;

    case DW_OP_ge:
      value = *sp--;
      *sp = (*sp >= value);
      if (log)
        fprintf(stderr, "ge\n");
      break;

    case DW_OP_gt:
      value = *sp--;
      *sp = (*sp > value);
      if (log)
        fprintf(stderr, "gt\n");
      break;

    case DW_OP_le:
      value = *sp--;
      *sp = (*sp <= value);
      if (log)
        fprintf(stderr, "le\n");
      break;

    case DW_OP_lt:
      value = *sp--;
      *sp = (*sp < value);
      if (log)
        fprintf(stderr, "lt\n");
      break;

    case DW_OP_ne:
      value = *sp--;
      *sp = (*sp != value);
      if (log)
        fprintf(stderr, "ne\n");
      break;

    case DW_OP_lit0:
    case DW_OP_lit1:
    case DW_OP_lit2:
    case DW_OP_lit3:
    case DW_OP_lit4:
    case DW_OP_lit5:
    case DW_OP_lit6:
    case DW_OP_lit7:
    case DW_OP_lit8:
    case DW_OP_lit9:
    case DW_OP_lit10:
    case DW_OP_lit11:
    case DW_OP_lit12:
    case DW_OP_lit13:
    case DW_OP_lit14:
    case DW_OP_lit15:
    case DW_OP_lit16:
    case DW_OP_lit17:
    case DW_OP_lit18:
    case DW_OP_lit19:
    case DW_OP_lit20:
    case DW_OP_lit21:
    case DW_OP_lit22:
    case DW_OP_lit23:
    case DW_OP_lit24:
    case DW_OP_lit25:
    case DW_OP_lit26:
    case DW_OP_lit27:
    case DW_OP_lit28:
    case DW_OP_lit29:
    case DW_OP_lit30:
    case DW_OP_lit31:
      value = opcode - DW_OP_lit0;
      *(++sp) = value;
      if (log)
        fprintf(stderr, "push literal 0x%llX\n", (uint64_t) value);
      break;

    case DW_OP_reg0:
    case DW_OP_reg1:
    case DW_OP_reg2:
    case DW_OP_reg3:
    case DW_OP_reg4:
    case DW_OP_reg5:
    case DW_OP_reg6:
    case DW_OP_reg7:
    case DW_OP_reg8:
    case DW_OP_reg9:
    case DW_OP_reg10:
    case DW_OP_reg11:
    case DW_OP_reg12:
    case DW_OP_reg13:
    case DW_OP_reg14:
    case DW_OP_reg15:
    case DW_OP_reg16:
    case DW_OP_reg17:
    case DW_OP_reg18:
    case DW_OP_reg19:
    case DW_OP_reg20:
    case DW_OP_reg21:
    case DW_OP_reg22:
    case DW_OP_reg23:
    case DW_OP_reg24:
    case DW_OP_reg25:
    case DW_OP_reg26:
    case DW_OP_reg27:
    case DW_OP_reg28:
    case DW_OP_reg29:
    case DW_OP_reg30:
    case DW_OP_reg31:
      reg = opcode - DW_OP_reg0;
      *(++sp) = registers.getRegister((int)reg);
      if (log)
        fprintf(stderr, "push reg %d\n", reg);
      break;

    case DW_OP_regx:
      reg = (uint32_t)addressSpace.getULEB128(p, expressionEnd);
      *(++sp) = registers.getRegister((int)reg);
      if (log)
        fprintf(stderr, "push reg %d + 0x%llX\n", reg, (uint64_t) svalue);
      break;

    case DW_OP_breg0:
    case DW_OP_breg1:
    case DW_OP_breg2:
    case DW_OP_breg3:
    case DW_OP_breg4:
    case DW_OP_breg5:
    case DW_OP_breg6:
    case DW_OP_breg7:
    case DW_OP_breg8:
    case DW_OP_breg9:
    case DW_OP_breg10:
    case DW_OP_breg11:
    case DW_OP_breg12:
    case DW_OP_breg13:
    case DW_OP_breg14:
    case DW_OP_breg15:
    case DW_OP_breg16:
    case DW_OP_breg17:
    case DW_OP_breg18:
    case DW_OP_breg19:
    case DW_OP_breg20:
    case DW_OP_breg21:
    case DW_OP_breg22:
    case DW_OP_breg23:
    case DW_OP_breg24:
    case DW_OP_breg25:
    case DW_OP_breg26:
    case DW_OP_breg27:
    case DW_OP_breg28:
    case DW_OP_breg29:
    case DW_OP_breg30:
    case DW_OP_breg31:
      reg = opcode - DW_OP_breg0;
      svalue = (sint_t)addressSpace.getSLEB128(p, expressionEnd);
      svalue += registers.getRegister((int)reg);
      *(++sp) = (pint_t)(svalue);
      if (log)
        fprintf(stderr, "push reg %d + 0x%llX\n", reg, (uint64_t) svalue);
      break;

    case DW_OP_bregx:
      reg = (uint32_t)addressSpace.getULEB128(p, expressionEnd);
      svalue = (sint_t)addressSpace.getSLEB128(p, expressionEnd);
      svalue += registers.getRegister((int)reg);
      *(++sp) = (pint_t)(svalue);
      if (log)
        fprintf(stderr, "push reg %d + 0x%llX\n", reg, (uint64_t) svalue);
      break;

    case DW_OP_fbreg:
      _LIBUNWIND_ABORT("DW_OP_fbreg not implemented");
      break;

    case DW_OP_piece:
      _LIBUNWIND_ABORT("DW_OP_piece not implemented");
      break;

    case DW_OP_deref_size:
      // pop stack, dereference, push result
      value = *sp--;
      switch (addressSpace.get8(p++)) {
      case 1:
        value = addressSpace.get8(value);
        break;
      case 2:
        value = addressSpace.get16(value);
        break;
      case 4:
        value = addressSpace.get32(value);
        break;
      case 8:
        value = (pint_t)addressSpace.get64(value);
        break;
      default:
        _LIBUNWIND_ABORT("DW_OP_deref_size with bad size");
      }
      *(++sp) = value;
      if (log)
        fprintf(stderr, "sized dereference 0x%llX\n", (uint64_t) value);
      break;

    case DW_OP_xderef_size:
    case DW_OP_nop:
    case DW_OP_push_object_addres:
    case DW_OP_call2:
    case DW_OP_call4:
    case DW_OP_call_ref:
    default:
      _LIBUNWIND_ABORT("dwarf opcode not implemented");
    }

  }
  if (log)
    fprintf(stderr, "expression evaluates to 0x%llX\n", (uint64_t) * sp);
  return *sp;
}
Esempio n. 12
0
static _Unwind_Reason_Code
unwind_phase2(struct _Unwind_Exception *exception_object) {
  _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p)\n", exception_object);

  // walk each frame until we reach where search phase said to stop
  _Unwind_FunctionContext_t c = __Unwind_SjLj_GetTopOfFunctionStack();
  while (true) {
    _LIBUNWIND_TRACE_UNWINDING("unwind_phase2s(ex_ojb=%p): context=%p\n",
                              exception_object, c);

    // check for no more frames
    if (c == NULL) {
      _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): unw_step() reached "
                                "bottom => _URC_END_OF_STACK\n",
                                 exception_object);
      return _URC_END_OF_STACK;
    }

    // if there is a personality routine, tell it we are unwinding
    if (c->personality != NULL) {
      _Unwind_Action action = _UA_CLEANUP_PHASE;
      if ((uintptr_t) c == exception_object->private_2)
        action = (_Unwind_Action)(
            _UA_CLEANUP_PHASE |
            _UA_HANDLER_FRAME); // tell personality this was the frame it marked
                                // in phase 1
      _Unwind_Reason_Code personalityResult =
          (*c->personality)(1, action, exception_object->exception_class,
                            exception_object, (struct _Unwind_Context *)c);
      switch (personalityResult) {
      case _URC_CONTINUE_UNWIND:
        // continue unwinding
        _LIBUNWIND_TRACE_UNWINDING(
            "unwind_phase2(ex_ojb=%p): _URC_CONTINUE_UNWIND\n",
            exception_object);
        if ((uintptr_t) c == exception_object->private_2) {
          // phase 1 said we would stop at this frame, but we did not...
          _LIBUNWIND_ABORT("during phase1 personality function said it would "
                           "stop here, but now if phase2 it did not stop here");
        }
        break;
      case _URC_INSTALL_CONTEXT:
        _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): "
                                  "_URC_INSTALL_CONTEXT, will resume at "
                                  "landing pad %p\n",
                                  exception_object, c->jbuf[1]);
        // personality routine says to transfer control to landing pad
        // we may get control back if landing pad calls _Unwind_Resume()
        __Unwind_SjLj_SetTopOfFunctionStack(c);
        __builtin_longjmp(c->jbuf, 1);
        // unw_resume() only returns if there was an error
        return _URC_FATAL_PHASE2_ERROR;
      default:
        // something went wrong
        _LIBUNWIND_DEBUG_LOG("personality function returned unknown result %d",
                      personalityResult);
        return _URC_FATAL_PHASE2_ERROR;
      }
    }
    c = c->prev;
  }

  // clean up phase did not resume at the frame that the search phase said it
  // would
  return _URC_FATAL_PHASE2_ERROR;
}
Esempio n. 13
0
static _Unwind_Reason_Code
unwind_phase2(unw_context_t *uc, struct _Unwind_Exception *exception_object, bool resume) {
  // See comment at the start of unwind_phase1 regarding VRS integrity.
  unw_cursor_t cursor2;
  unw_init_local(&cursor2, uc);

  _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p)\n", exception_object);
  int frame_count = 0;

  // Walk each frame until we reach where search phase said to stop.
  while (true) {
    // Ask libuwind to get next frame (skip over first which is
    // _Unwind_RaiseException or _Unwind_Resume).
    //
    // Resume only ever makes sense for 1 frame.
    _Unwind_State state =
        resume ? _US_UNWIND_FRAME_RESUME : _US_UNWIND_FRAME_STARTING;
    if (resume && frame_count == 1) {
      // On a resume, first unwind the _Unwind_Resume() frame. The next frame
      // is now the landing pad for the cleanup from a previous execution of
      // phase2. To continue unwindingly correctly, replace VRS[15] with the
      // IP of the frame that the previous run of phase2 installed the context
      // for. After this, continue unwinding as if normal.
      //
      // See #7.4.6 for details.
      unw_set_reg(&cursor2, UNW_REG_IP, exception_object->unwinder_cache.reserved2);
      resume = false;
    }
    int stepResult = unw_step(&cursor2);
    if (stepResult == 0) {
      _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): unw_step() reached "
                            "bottom => _URC_END_OF_STACK\n",
                            exception_object);
      return _URC_END_OF_STACK;
    } else if (stepResult < 0) {
      _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): unw_step failed => "
                            "_URC_FATAL_PHASE1_ERROR\n",
                            exception_object);
      return _URC_FATAL_PHASE2_ERROR;
    }

    // Get info about this frame.
    unw_word_t sp;
    unw_proc_info_t frameInfo;
    unw_get_reg(&cursor2, UNW_REG_SP, &sp);
    if (unw_get_proc_info(&cursor2, &frameInfo) != UNW_ESUCCESS) {
      _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): unw_get_proc_info "
                            "failed => _URC_FATAL_PHASE1_ERROR\n",
                            exception_object);
      return _URC_FATAL_PHASE2_ERROR;
    }

    // When tracing, print state information.
    if (_LIBUNWIND_TRACING_UNWINDING) {
      char functionName[512];
      unw_word_t offset;
      if ((unw_get_proc_name(&cursor2, functionName, 512, &offset) !=
           UNW_ESUCCESS) || (frameInfo.start_ip + offset > frameInfo.end_ip))
        strcpy(functionName, ".anonymous.");
      _LIBUNWIND_TRACE_UNWINDING(
          "unwind_phase2(ex_ojb=%p): start_ip=0x%llX, func=%s, sp=0x%llX, "
          "lsda=0x%llX, personality=0x%llX\n",
          exception_object, frameInfo.start_ip, functionName, sp,
          frameInfo.lsda, frameInfo.handler);
    }

    // If there is a personality routine, tell it we are unwinding.
    if (frameInfo.handler != 0) {
      __personality_routine p =
          (__personality_routine)(long)(frameInfo.handler);
      struct _Unwind_Context *context = (struct _Unwind_Context *)(&cursor2);
#ifdef __arm__
      exception_object->pr_cache.fnstart = frameInfo.start_ip;
      exception_object->pr_cache.ehtp = (_Unwind_EHT_Header *)frameInfo.unwind_info;
      exception_object->pr_cache.additional = frameInfo.flags;
      _Unwind_Reason_Code personalityResult =
          (*p)(state, exception_object, context);
#else
      _Unwind_Action action = _UA_CLEANUP_PHASE;
      if (sp == exception_object->private_2) {
        // Tell personality this was the frame it marked in phase 1.
        action = (_Unwind_Action)(_UA_CLEANUP_PHASE | _UA_HANDLER_FRAME);
      }
       _Unwind_Reason_Code personalityResult =
          (*p)(1, action, exception_object->exception_class, exception_object,
               context);
#endif
      switch (personalityResult) {
      case _URC_CONTINUE_UNWIND:
        // Continue unwinding
        _LIBUNWIND_TRACE_UNWINDING(
            "unwind_phase2(ex_ojb=%p): _URC_CONTINUE_UNWIND\n",
            exception_object);
#ifdef __arm__
        if (sp == exception_object->barrier_cache.sp) {
#else
        if (sp == exception_object->private_2) {
#endif
          // Phase 1 said we would stop at this frame, but we did not...
          _LIBUNWIND_ABORT("during phase1 personality function said it would "
                           "stop here, but now in phase2 it did not stop here");
        }
        break;
      case _URC_INSTALL_CONTEXT:
        _LIBUNWIND_TRACE_UNWINDING(
            "unwind_phase2(ex_ojb=%p): _URC_INSTALL_CONTEXT\n",
            exception_object);
        // Personality routine says to transfer control to landing pad.
        // We may get control back if landing pad calls _Unwind_Resume().
        if (_LIBUNWIND_TRACING_UNWINDING) {
          unw_word_t pc;
          unw_get_reg(&cursor2, UNW_REG_IP, &pc);
          unw_get_reg(&cursor2, UNW_REG_SP, &sp);
          _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): re-entering  "
                                     "user code with ip=0x%llX, sp=0x%llX\n",
                                    exception_object, pc, sp);
        }

#ifdef __arm__
        // #7.4.1 says we need to preserve pc for when _Unwind_Resume is called
        // back, to find this same frame.
        unw_word_t pc;
        unw_get_reg(&cursor2, UNW_REG_IP, &pc);
        exception_object->unwinder_cache.reserved2 = (uint32_t)pc;
#endif
        unw_resume(&cursor2);
        // unw_resume() only returns if there was an error.
        return _URC_FATAL_PHASE2_ERROR;
#ifdef __arm__
      // # 7.4.3
      case _URC_FAILURE:
        abort();
#endif
      default:
        // Personality routine returned an unknown result code.
        _LIBUNWIND_DEBUG_LOG("personality function returned unknown result %d",
                      personalityResult);
        return _URC_FATAL_PHASE2_ERROR;
      }
    }
    frame_count++;
  }

  // Clean up phase did not resume at the frame that the search phase
  // said it would...
  return _URC_FATAL_PHASE2_ERROR;
}

#ifndef __arm__
static _Unwind_Reason_Code
unwind_phase2_forced(unw_context_t *uc,
                     struct _Unwind_Exception *exception_object,
                     _Unwind_Stop_Fn stop, void *stop_parameter) {
  unw_cursor_t cursor2;
  unw_init_local(&cursor2, uc);

  // Walk each frame until we reach where search phase said to stop
  while (unw_step(&cursor2) > 0) {

    // Update info about this frame.
    unw_proc_info_t frameInfo;
    if (unw_get_proc_info(&cursor2, &frameInfo) != UNW_ESUCCESS) {
      _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): unw_step "
                                 "failed => _URC_END_OF_STACK\n",
                                 exception_object);
      return _URC_FATAL_PHASE2_ERROR;
    }

    // When tracing, print state information.
    if (_LIBUNWIND_TRACING_UNWINDING) {
      char functionName[512];
      unw_word_t offset;
      if ((unw_get_proc_name(&cursor2, functionName, 512, &offset) !=
           UNW_ESUCCESS) || (frameInfo.start_ip + offset > frameInfo.end_ip))
        strcpy(functionName, ".anonymous.");
      _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p):  "
                                 "start_ip=0x%llX, func=%s, lsda=0x%llX, "
                                 " personality=0x%llX\n",
                                 exception_object, frameInfo.start_ip,
                                 functionName, frameInfo.lsda,
                                 frameInfo.handler);
    }

    // Call stop function at each frame.
    _Unwind_Action action =
        (_Unwind_Action)(_UA_FORCE_UNWIND | _UA_CLEANUP_PHASE);
    _Unwind_Reason_Code stopResult =
        (*stop)(1, action, exception_object->exception_class, exception_object,
                (struct _Unwind_Context *)(&cursor2), stop_parameter);
    _LIBUNWIND_TRACE_UNWINDING(
        "unwind_phase2_forced(ex_ojb=%p): stop function returned %d\n",
        exception_object, stopResult);
    if (stopResult != _URC_NO_REASON) {
      _LIBUNWIND_TRACE_UNWINDING(
          "unwind_phase2_forced(ex_ojb=%p): stopped by stop function\n",
          exception_object);
      return _URC_FATAL_PHASE2_ERROR;
    }

    // If there is a personality routine, tell it we are unwinding.
    if (frameInfo.handler != 0) {
      __personality_routine p =
          (__personality_routine)(long)(frameInfo.handler);
      _LIBUNWIND_TRACE_UNWINDING(
          "unwind_phase2_forced(ex_ojb=%p): calling personality function %p\n",
          exception_object, p);
      _Unwind_Reason_Code personalityResult =
          (*p)(1, action, exception_object->exception_class, exception_object,
               (struct _Unwind_Context *)(&cursor2));
      switch (personalityResult) {
      case _URC_CONTINUE_UNWIND:
        _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): "
                                "personality  returned _URC_CONTINUE_UNWIND\n",
                                 exception_object);
        // Destructors called, continue unwinding
        break;
      case _URC_INSTALL_CONTEXT:
        _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): "
                                  "personality returned _URC_INSTALL_CONTEXT\n",
                                   exception_object);
        // We may get control back if landing pad calls _Unwind_Resume().
        unw_resume(&cursor2);
        break;
      default:
        // Personality routine returned an unknown result code.
        _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): "
                                   "personality returned %d, "
                                   "_URC_FATAL_PHASE2_ERROR\n",
                                   exception_object, personalityResult);
        return _URC_FATAL_PHASE2_ERROR;
      }
    }
  }

  // Call stop function one last time and tell it we've reached the end
  // of the stack.
  _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): calling stop "
                        "function with _UA_END_OF_STACK\n",
                        exception_object);
  _Unwind_Action lastAction =
      (_Unwind_Action)(_UA_FORCE_UNWIND | _UA_CLEANUP_PHASE | _UA_END_OF_STACK);
  (*stop)(1, lastAction, exception_object->exception_class, exception_object,
          (struct _Unwind_Context *)(&cursor2), stop_parameter);

  // Clean up phase did not resume at the frame that the search phase said it
  // would.
  return _URC_FATAL_PHASE2_ERROR;
}
Esempio n. 14
0
static _Unwind_Reason_Code
unwind_phase2(unw_context_t *uc, _Unwind_Exception *exception_object) {
    unw_cursor_t cursor2;
    unw_init_local(&cursor2, uc);

    _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p)\n", exception_object);

    // Walk each frame until we reach where search phase said to stop.
    while (true) {

        // Ask libuwind to get next frame (skip over first which is
        // _Unwind_RaiseException).
        int stepResult = unw_step(&cursor2);
        if (stepResult == 0) {
            _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): unw_step() reached "
                                       "bottom => _URC_END_OF_STACK\n",
                                       exception_object);
            return _URC_END_OF_STACK;
        } else if (stepResult < 0) {
            _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): unw_step failed => "
                                       "_URC_FATAL_PHASE1_ERROR\n",
                                       exception_object);
            return _URC_FATAL_PHASE2_ERROR;
        }

        // Get info about this frame.
        unw_word_t sp;
        unw_proc_info_t frameInfo;
        unw_get_reg(&cursor2, UNW_REG_SP, &sp);
        if (unw_get_proc_info(&cursor2, &frameInfo) != UNW_ESUCCESS) {
            _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): unw_get_proc_info "
                                       "failed => _URC_FATAL_PHASE1_ERROR\n",
                                       exception_object);
            return _URC_FATAL_PHASE2_ERROR;
        }

        // When tracing, print state information.
        if (_LIBUNWIND_TRACING_UNWINDING) {
            char functionName[512];
            unw_word_t offset;
            if ((unw_get_proc_name(&cursor2, functionName, 512, &offset) !=
                    UNW_ESUCCESS) || (frameInfo.start_ip + offset > frameInfo.end_ip))
                strcpy(functionName, ".anonymous.");
            _LIBUNWIND_TRACE_UNWINDING(
                "unwind_phase2(ex_ojb=%p): start_ip=0x%llX, func=%s, sp=0x%llX, "
                "lsda=0x%llX, personality=0x%llX\n",
                exception_object, frameInfo.start_ip, functionName, sp,
                frameInfo.lsda, frameInfo.handler);
        }

        // If there is a personality routine, tell it we are unwinding.
        if (frameInfo.handler != 0) {
            __personality_routine p =
                (__personality_routine)(long)(frameInfo.handler);
            _Unwind_Action action = _UA_CLEANUP_PHASE;
            if (sp == exception_object->private_2) {
                // Tell personality this was the frame it marked in phase 1.
                action = (_Unwind_Action)(_UA_CLEANUP_PHASE | _UA_HANDLER_FRAME);
            }
            _Unwind_Reason_Code personalityResult =
                (*p)(1, action, exception_object->exception_class, exception_object,
                     (struct _Unwind_Context *)(&cursor2));
            switch (personalityResult) {
            case _URC_CONTINUE_UNWIND:
                // Continue unwinding
                _LIBUNWIND_TRACE_UNWINDING(
                    "unwind_phase2(ex_ojb=%p): _URC_CONTINUE_UNWIND\n",
                    exception_object);
                if (sp == exception_object->private_2) {
                    // Phase 1 said we would stop at this frame, but we did not...
                    _LIBUNWIND_ABORT("during phase1 personality function said it would "
                                     "stop here, but now in phase2 it did not stop here");
                }
                break;
            case _URC_INSTALL_CONTEXT:
                _LIBUNWIND_TRACE_UNWINDING(
                    "unwind_phase2(ex_ojb=%p): _URC_INSTALL_CONTEXT\n",
                    exception_object);
                // Personality routine says to transfer control to landing pad.
                // We may get control back if landing pad calls _Unwind_Resume().
                if (_LIBUNWIND_TRACING_UNWINDING) {
                    unw_word_t pc;
                    unw_get_reg(&cursor2, UNW_REG_IP, &pc);
                    unw_get_reg(&cursor2, UNW_REG_SP, &sp);
                    _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): re-entering  "
                                               "user code with ip=0x%llX, sp=0x%llX\n",
                                               exception_object, pc, sp);
                }
                unw_resume(&cursor2);
                // unw_resume() only returns if there was an error.
                return _URC_FATAL_PHASE2_ERROR;
            default:
                // Personality routine returned an unknown result code.
                _LIBUNWIND_DEBUG_LOG("personality function returned unknown result %d",
                                     personalityResult);
                return _URC_FATAL_PHASE2_ERROR;
            }
        }
    }

    // Clean up phase did not resume at the frame that the search phase
    // said it would...
    return _URC_FATAL_PHASE2_ERROR;
}
Esempio n. 15
0
/// Called by personality handler during phase 2 to get base address for text
/// relative encodings.
_LIBUNWIND_EXPORT uintptr_t
_Unwind_GetTextRelBase(struct _Unwind_Context *context) {
  (void)context;
  _LIBUNWIND_TRACE_API("_Unwind_GetTextRelBase(context=%p)\n", context);
  _LIBUNWIND_ABORT("_Unwind_GetTextRelBase() not implemented");
}