Ejemplo n.º 1
0
static _Unwind_Reason_Code
unwind_phase1(struct _Unwind_Exception *exception_object) {
  _Unwind_FunctionContext_t c = __Unwind_SjLj_GetTopOfFunctionStack();
  _LIBUNWIND_TRACE_UNWINDING("unwind_phase1: initial function-context=%p\n", c);

  // walk each frame looking for a place to stop
  for (bool handlerNotFound = true; handlerNotFound; c = c->prev) {

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

    _LIBUNWIND_TRACE_UNWINDING("unwind_phase1: function-context=%p\n", c);
    // if there is a personality routine, ask it if it will want to stop at this
    // frame
    if (c->personality != NULL) {
      _LIBUNWIND_TRACE_UNWINDING("unwind_phase1(ex_ojb=%p): calling "
                                "personality function %p\n",
                                 exception_object, c->personality);
      _Unwind_Reason_Code personalityResult = (*c->personality)(
          1, _UA_SEARCH_PHASE, exception_object->exception_class,
          exception_object, (struct _Unwind_Context *)c);
      switch (personalityResult) {
      case _URC_HANDLER_FOUND:
        // found a catch clause or locals that need destructing in this frame
        // stop search and remember function context
        handlerNotFound = false;
        exception_object->private_2 = (uintptr_t) c;
        _LIBUNWIND_TRACE_UNWINDING("unwind_phase1(ex_ojb=%p): "
                                   "_URC_HANDLER_FOUND\n", exception_object);
        return _URC_NO_REASON;

      case _URC_CONTINUE_UNWIND:
        _LIBUNWIND_TRACE_UNWINDING("unwind_phase1(ex_ojb=%p): "
                                   "_URC_CONTINUE_UNWIND\n", exception_object);
        // continue unwinding
        break;

      default:
        // something went wrong
        _LIBUNWIND_TRACE_UNWINDING(
            "unwind_phase1(ex_ojb=%p): _URC_FATAL_PHASE1_ERROR\n",
            exception_object);
        return _URC_FATAL_PHASE1_ERROR;
      }
    }
  }
  return _URC_NO_REASON;
}
Ejemplo n.º 2
0
static _Unwind_Reason_Code
unwind_phase2_forced(struct _Unwind_Exception *exception_object,
                     _Unwind_Stop_Fn stop, void *stop_parameter) {
  // walk each frame until we reach where search phase said to stop
  _Unwind_FunctionContext_t c = __Unwind_SjLj_GetTopOfFunctionStack();
  while (true) {

    // get next frame (skip over first which is _Unwind_RaiseException)
    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;
    }

    // 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 *)c, 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 (c->personality != NULL) {
      __personality_routine p = (__personality_routine) c->personality;
      _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 *)c);
      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()
        __Unwind_SjLj_SetTopOfFunctionStack(c);
        __builtin_longjmp(c->jbuf, 1);
        break;
      default:
        // something went wrong
        _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;
      }
    }
    c = c->prev;
  }

  // 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 *)c, stop_parameter);

  // clean up phase did not resume at the frame that the search phase said it
  // would
  return _URC_FATAL_PHASE2_ERROR;
}
Ejemplo n.º 3
0
void __Unwind_SjLj_SetTopOfFunctionStack(struct _Unwind_FunctionContext *fc) {
    _LIBUNWIND_TRACE_UNWINDING("__Unwind_SjLj_GetTopOfFunctionStack: %p\n", fc);
  pthread_setspecific(PTHREAD_KEY_LIBCXX_SJLJ, fc);
}
Ejemplo n.º 4
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;
}
Ejemplo n.º 5
0
static _Unwind_Reason_Code
unwind_phase1(unw_context_t *uc, struct _Unwind_Exception *exception_object) {
  // EHABI #7.3 discusses preserving the VRS in a "temporary VRS" during
  // phase 1 and then restoring it to the "primary VRS" for phase 2. The
  // effect is phase 2 doesn't see any of the VRS manipulations from phase 1.
  // In this implementation, the phases don't share the VRS backing store.
  // Instead, they are passed the original |uc| and they create a new VRS
  // from scratch thus achieving the same effect.
  unw_cursor_t cursor1;
  unw_init_local(&cursor1, uc);

  // Walk each frame looking for a place to stop.
  for (bool handlerNotFound = true; handlerNotFound;) {

    // Ask libuwind to get next frame (skip over first which is
    // _Unwind_RaiseException).
    int stepResult = unw_step(&cursor1);
    if (stepResult == 0) {
      _LIBUNWIND_TRACE_UNWINDING("unwind_phase1(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_phase1(ex_ojb=%p): unw_step failed => "
                            "_URC_FATAL_PHASE1_ERROR\n",
                            exception_object);
      return _URC_FATAL_PHASE1_ERROR;
    }

    // See if frame has code to run (has personality routine).
    unw_proc_info_t frameInfo;
    unw_word_t sp;
    if (unw_get_proc_info(&cursor1, &frameInfo) != UNW_ESUCCESS) {
      _LIBUNWIND_TRACE_UNWINDING("unwind_phase1(ex_ojb=%p): unw_get_proc_info "
                            "failed => _URC_FATAL_PHASE1_ERROR\n",
                            exception_object);
      return _URC_FATAL_PHASE1_ERROR;
    }

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

    // If there is a personality routine, ask it if it will want to stop at
    // this frame.
    if (frameInfo.handler != 0) {
      __personality_routine p =
          (__personality_routine)(long)(frameInfo.handler);
      _LIBUNWIND_TRACE_UNWINDING(
          "unwind_phase1(ex_ojb=%p): calling personality function %p\n",
          exception_object, p);
      struct _Unwind_Context *context = (struct _Unwind_Context *)(&cursor1);
#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)(_US_VIRTUAL_UNWIND_FRAME, exception_object, context);
#else
      _Unwind_Reason_Code personalityResult =
          (*p)(1, _UA_SEARCH_PHASE, exception_object->exception_class,
               exception_object, context);
#endif
      switch (personalityResult) {
      case _URC_HANDLER_FOUND:
        // found a catch clause or locals that need destructing in this frame
        // stop search and remember stack pointer at the frame
        handlerNotFound = false;
#ifndef __arm__
        unw_get_reg(&cursor1, UNW_REG_SP, &sp);
        exception_object->private_2 = (uintptr_t)sp;
#else
        // p should have initialized barrier_cache. #7.3.5
#endif
        _LIBUNWIND_TRACE_UNWINDING("unwind_phase1(ex_ojb=%p): "
                                   "_URC_HANDLER_FOUND \n",
                                   exception_object);
        return _URC_NO_REASON;

      case _URC_CONTINUE_UNWIND:
        _LIBUNWIND_TRACE_UNWINDING(
            "unwind_phase1(ex_ojb=%p): _URC_CONTINUE_UNWIND\n",
            exception_object);
        // continue unwinding
        break;

#ifdef __arm__
      // # 7.3.3
      case _URC_FAILURE:
        return _URC_FAILURE;
#endif

      default:
        // something went wrong
        _LIBUNWIND_TRACE_UNWINDING(
            "unwind_phase1(ex_ojb=%p): _URC_FATAL_PHASE1_ERROR\n",
            exception_object);
        return _URC_FATAL_PHASE1_ERROR;
      }
    }
  }
  return _URC_NO_REASON;
}
Ejemplo n.º 6
0
struct _Unwind_FunctionContext *__Unwind_SjLj_GetTopOfFunctionStack(void) {
    _LIBUNWIND_TRACE_UNWINDING("__Unwind_SjLj_GetTopOfFunctionStack\n");
  return (struct _Unwind_FunctionContext *) pthread_getspecific(PTHREAD_KEY_LIBCXX_SJLJ);
}
Ejemplo n.º 7
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;
}
Ejemplo n.º 8
0
static _Unwind_Reason_Code
unwind_phase1(unw_context_t *uc, _Unwind_Exception *exception_object) {
    unw_cursor_t cursor1;
    unw_init_local(&cursor1, uc);

    // Walk each frame looking for a place to stop.
    for (bool handlerNotFound = true; handlerNotFound;) {

        // Ask libuwind to get next frame (skip over first which is
        // _Unwind_RaiseException).
        int stepResult = unw_step(&cursor1);
        if (stepResult == 0) {
            _LIBUNWIND_TRACE_UNWINDING("unwind_phase1(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_phase1(ex_ojb=%p): unw_step failed => "
                                       "_URC_FATAL_PHASE1_ERROR\n",
                                       exception_object);
            return _URC_FATAL_PHASE1_ERROR;
        }

        // See if frame has code to run (has personality routine).
        unw_proc_info_t frameInfo;
        unw_word_t sp;
        if (unw_get_proc_info(&cursor1, &frameInfo) != UNW_ESUCCESS) {
            _LIBUNWIND_TRACE_UNWINDING("unwind_phase1(ex_ojb=%p): unw_get_proc_info "
                                       "failed => _URC_FATAL_PHASE1_ERROR\n",
                                       exception_object);
            return _URC_FATAL_PHASE1_ERROR;
        }

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

        // If there is a personality routine, ask it if it will want to stop at
        // this frame.
        if (frameInfo.handler != 0) {
            __personality_routine p =
                (__personality_routine)(long)(frameInfo.handler);
            _LIBUNWIND_TRACE_UNWINDING(
                "unwind_phase1(ex_ojb=%p): calling personality function %p\n",
                exception_object, p);
            _Unwind_Reason_Code personalityResult =
                (*p)(1, _UA_SEARCH_PHASE, exception_object->exception_class,
                     exception_object, (struct _Unwind_Context *)(&cursor1));
            switch (personalityResult) {
            case _URC_HANDLER_FOUND:
                // found a catch clause or locals that need destructing in this frame
                // stop search and remember stack pointer at the frame
                handlerNotFound = false;
                unw_get_reg(&cursor1, UNW_REG_SP, &sp);
                exception_object->private_2 = (uintptr_t)sp;
                _LIBUNWIND_TRACE_UNWINDING("unwind_phase1(ex_ojb=%p): "
                                           "_URC_HANDLER_FOUND \n",
                                           exception_object);
                return _URC_NO_REASON;

            case _URC_CONTINUE_UNWIND:
                _LIBUNWIND_TRACE_UNWINDING(
                    "unwind_phase1(ex_ojb=%p): _URC_CONTINUE_UNWIND\n",
                    exception_object);
                // continue unwinding
                break;

            default:
                // something went wrong
                _LIBUNWIND_TRACE_UNWINDING(
                    "unwind_phase1(ex_ojb=%p): _URC_FATAL_PHASE1_ERROR\n",
                    exception_object);
                return _URC_FATAL_PHASE1_ERROR;
            }
        }
    }
    return _URC_NO_REASON;
}
Ejemplo n.º 9
0
static _Unwind_Reason_Code
unwind_phase2_forced(unw_context_t *uc,
                     _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;
}
Ejemplo n.º 10
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;
}
Ejemplo n.º 11
0
/// Walk every frame and call trace function at each one.  If trace function
/// returns anything other than _URC_NO_REASON, then walk is terminated.
_LIBUNWIND_EXPORT _Unwind_Reason_Code
_Unwind_Backtrace(_Unwind_Trace_Fn callback, void *ref) {
  unw_cursor_t cursor;
  unw_context_t uc;
  unw_getcontext(&uc);
  unw_init_local(&cursor, &uc);

  _LIBUNWIND_TRACE_API("_Unwind_Backtrace(callback=%p)\n", callback);

  // walk each frame
  while (true) {
    _Unwind_Reason_Code result;

    // ask libuwind to get next frame (skip over first frame which is
    // _Unwind_Backtrace())
    if (unw_step(&cursor) <= 0) {
      _LIBUNWIND_TRACE_UNWINDING(" _backtrace: ended because cursor reached "
                                 "bottom of stack, returning %d\n",
                                 _URC_END_OF_STACK);
      return _URC_END_OF_STACK;
    }

#if LIBCXXABI_ARM_EHABI
    // Get the information for this frame.
    unw_proc_info_t frameInfo;
    if (unw_get_proc_info(&cursor, &frameInfo) != UNW_ESUCCESS) {
      return _URC_END_OF_STACK;
    }

    struct _Unwind_Context *context = (struct _Unwind_Context *)&cursor;
    const uint32_t* unwindInfo = (uint32_t *) frameInfo.unwind_info;
    if ((*unwindInfo & 0x80000000) == 0) {
      // 6.2: Generic Model
      // EHT entry is a prel31 pointing to the PR, followed by data understood
      // only by the personality routine. Since EHABI doesn't guarantee the
      // location or availability of the unwind opcodes in the generic model,
      // we have to call personality functions with (_US_VIRTUAL_UNWIND_FRAME |
      // _US_FORCE_UNWIND) state.

      // Create a mock exception object for force unwinding.
      _Unwind_Exception ex;
      ex.exception_class = 0x434C4E47554E5700; // CLNGUNW\0
      ex.pr_cache.fnstart = frameInfo.start_ip;
      ex.pr_cache.ehtp = (_Unwind_EHT_Header *) unwindInfo;
      ex.pr_cache.additional= frameInfo.flags;

      // Get and call the personality function to unwind the frame.
      __personality_routine pr = (__personality_routine) readPrel31(unwindInfo);
      if (pr(_US_VIRTUAL_UNWIND_FRAME | _US_FORCE_UNWIND, &ex, context) !=
              _URC_CONTINUE_UNWIND) {
        return _URC_END_OF_STACK;
      }
    } else {
      size_t off, len;
      unwindInfo = decode_eht_entry(unwindInfo, &off, &len);
      if (unwindInfo == NULL) {
        return _URC_FAILURE;
      }

      result = _Unwind_VRS_Interpret(context, unwindInfo, off, len);
      if (result != _URC_CONTINUE_UNWIND) {
        return _URC_END_OF_STACK;
      }
    }
#endif // LIBCXXABI_ARM_EHABI

    // debugging
    if (_LIBUNWIND_TRACING_UNWINDING) {
      char functionName[512];
      unw_proc_info_t frame;
      unw_word_t offset;
      unw_get_proc_name(&cursor, functionName, 512, &offset);
      unw_get_proc_info(&cursor, &frame);
      _LIBUNWIND_TRACE_UNWINDING(
          " _backtrace: start_ip=0x%llX, func=%s, lsda=0x%llX, context=%p\n",
          (long long)frame.start_ip, functionName,
          (long long)frame.lsda, &cursor);
    }

    // call trace function with this frame
    result = (*callback)((struct _Unwind_Context *)(&cursor), ref);
    if (result != _URC_NO_REASON) {
      _LIBUNWIND_TRACE_UNWINDING(" _backtrace: ended because callback "
                                 "returned %d\n",
                                 result);
      return result;
    }
  }
}