// demand_interval: Given a PC 'pc', return an interval.  Note that
// 'pc' may be bogus (i.e, not even point to a text segment) and in this
// case UNW_INTERVAL_NULL should be returned.
UNW_INTERVAL_t
demand_interval(void* pc, bool isTopFrame)
{
#if (HPC_UNW_LITE)
  void* proc_beg = NULL, *mod_beg = NULL;
  dylib_find_proc(pc, &proc_beg, &mod_beg);

  if (!proc_beg && mod_beg && !isTopFrame) {
    // The procedure begin could not be found but pc is valid (since
    // the module begin was found).
    proc_beg = mips_find_proc(pc, mod_beg);
  }
  
  if (proc_beg) {
    uint32_t* beg = (uint32_t*)proc_beg; // [insn_beg, insn_end)
    uint32_t* end = (uint32_t*)pc; 
    return mips_build_intervals(beg, end, false/*retFirst*/, 0);
  }
  else {
    return UNW_INTERVAL_NULL;
  }
#else
  // N.B.: calls build_intervals() if necessary
  return (UNW_INTERVAL_t)hpcrun_addr_to_interval(pc, NULL, NULL);
#endif
}
Esempio n. 2
0
static void
update_cursor_with_troll(hpcrun_unw_cursor_t* cursor, int offset)
{
  if (ENABLED(NO_TROLLING)){
    TMSG(TROLL, "Trolling disabled");
    hpcrun_unw_throw();
  }

  unsigned int tmp_ra_offset;

  int ret = stack_troll(cursor->sp, &tmp_ra_offset, &deep_validate_return_addr,
			(void *)cursor);

  if (ret != TROLL_INVALID) {
    void  **next_sp = ((void **)((unsigned long) cursor->sp + tmp_ra_offset));
    void *next_pc   = *next_sp;
    void *ra_loc    = (void*) next_sp;

    // the current base pointer is a good assumption for the caller's BP
    void **next_bp = (void **) cursor->bp; 

    next_sp += 1;
    if ( next_sp <= cursor->sp){
      TMSG(TROLL,"Something weird happened! trolling from %p"
	   " resulted in sp not advancing", cursor->pc_unnorm);
      hpcrun_unw_throw();
    }

    ip_normalized_t next_pc_norm = ip_normalized_NULL;
    cursor->intvl = hpcrun_addr_to_interval(((char *)next_pc) + offset,
					    next_pc, &next_pc_norm);
    if (cursor->intvl) {
      TMSG(TROLL,"Trolling advances cursor to pc = %p, sp = %p", 
	   next_pc, next_sp);
      TMSG(TROLL,"TROLL SUCCESS pc = %p", cursor->pc_unnorm);

      cursor->pc_unnorm = next_pc;
      cursor->bp        = next_bp;
      cursor->sp        = next_sp;
      cursor->ra_loc    = ra_loc;
      cursor->pc_norm   = next_pc_norm;

      cursor->flags = 1; // trolling_used

      return; // success!
    }
    TMSG(TROLL, "No interval found for trolled pc, dropping sample,"
	 " cursor pc = %p", cursor->pc_unnorm);
    // fall through for error handling
  }
  else {
    TMSG(TROLL, "Troll failed: dropping sample, cursor pc = %p", 
	 cursor->pc_unnorm);
    TMSG(TROLL,"TROLL FAILURE pc = %p", cursor->pc_unnorm);
    // fall through for error handling
  }
  // assert(0);
  hpcrun_unw_throw();
}
Esempio n. 3
0
void 
hpcrun_unw_init_cursor(hpcrun_unw_cursor_t* cursor, void* context)
{
  mcontext_t *mc = GET_MCONTEXT(context);

  cursor->pc_unnorm = MCONTEXT_PC(mc); 
  cursor->bp 	    = MCONTEXT_BP(mc);
  cursor->sp 	    = MCONTEXT_SP(mc);
  cursor->ra_loc    = NULL;

  TMSG(UNW, "unw_init: pc=%p, ra_loc=%p, sp=%p, bp=%p", 
       cursor->pc_unnorm, cursor->ra_loc, cursor->sp, cursor->bp);

  cursor->flags = 0; // trolling_used
  cursor->intvl = hpcrun_addr_to_interval(cursor->pc_unnorm,
					  cursor->pc_unnorm, &cursor->pc_norm);
  if (!cursor->intvl) {
    EMSG("unw_init: cursor could NOT build an interval for initial pc = %p",
	 cursor->pc_unnorm);
    cursor->pc_norm = hpcrun_normalize_ip(cursor->pc_unnorm, NULL);
  }

  if (MYDBG) { dump_ui((unwind_interval *)cursor->intvl, 0); }
}
Esempio n. 4
0
static step_state
unw_step_bp(hpcrun_unw_cursor_t* cursor)
{
  void *sp, **bp, *pc; 
  void **next_sp, **next_bp, *next_pc;

  unwind_interval *uw;

  TMSG(UNW_STRATEGY,"Using BP step");
  // current frame
  bp = cursor->bp;
  sp = cursor->sp;
  pc = cursor->pc_unnorm;
  uw = (unwind_interval *)cursor->intvl;

  TMSG(UNW,"step_bp: cursor { bp=%p, sp=%p, pc=%p }", bp, sp, pc);
  if (MYDBG) { dump_ui(uw, 0); }

  if (!(sp <= (void*) bp)) {
    TMSG(UNW,"  step_bp: STEP_ERROR, unwind attempted, but incoming bp(%p) was not"
	 " >= sp(%p)", bp, sp);
    return STEP_ERROR;
  }
  if (DISABLED(OMP_SKIP_MSB)) {
    if (!((void *)bp < monitor_stack_bottom())) {
      TMSG(UNW,"  step_bp: STEP_ERROR, unwind attempted, but incoming bp(%p) was not"
	   " between sp (%p) and monitor stack bottom (%p)", 
	   bp, sp, monitor_stack_bottom());
      return STEP_ERROR;
    }
  }
  // bp relative
  next_sp  = (void **)((void *)bp + uw->bp_bp_pos);
  next_bp  = *next_sp;
  next_sp  = (void **)((void *)bp + uw->bp_ra_pos);
  void* ra_loc = (void*) next_sp;
  next_pc  = *next_sp;
  next_sp += 1;
  if ((void *)next_sp > sp) {
    // this condition is a weak correctness check. only
    // try building an interval for the return address again if it succeeds
    ip_normalized_t next_pc_norm = ip_normalized_NULL;
    uw = (unwind_interval *)hpcrun_addr_to_interval(((char *)next_pc) - 1, 
						    next_pc, &next_pc_norm);
    if (! uw){
      if (((void *)next_sp) >= monitor_stack_bottom()) {
        TMSG(UNW,"  step_bp: STEP_STOP_WEAK, next_sp >= monitor_stack_bottom,"
	     " next_sp = %p", next_sp);
        return STEP_STOP_WEAK;
      }
      TMSG(UNW,"  step_bp: STEP_ERROR, cannot build interval for next_pc(%p)", next_pc);
      return STEP_ERROR;
    }
    else {
      cursor->pc_unnorm = next_pc;
      cursor->bp        = next_bp;
      cursor->sp        = next_sp;
      cursor->ra_loc    = ra_loc;
      cursor->pc_norm   = next_pc_norm;
      
      cursor->intvl = (splay_interval_t *)uw;
      TMSG(UNW,"  step_bp: STEP_OK, has_intvl=%d, bp=%p, sp=%p, pc=%p",
	   cursor->intvl != NULL, next_bp, next_sp, next_pc);
      return STEP_OK;
    }
  }
  else {
    TMSG(UNW_STRATEGY,"BP unwind fails: bp (%p) < sp (%p)", bp, sp);
    return STEP_ERROR;
  }
  EMSG("FALL Through BP unwind: shouldn't happen");
  return STEP_ERROR;
}
Esempio n. 5
0
static step_state
unw_step_sp(hpcrun_unw_cursor_t* cursor)
{
  TMSG(UNW_STRATEGY,"Using SP step");

  // void *stack_bottom = monitor_stack_bottom();

  // current frame
  void** bp = cursor->bp;
  void*  sp = cursor->sp;
  void*  pc = cursor->pc_unnorm;
  unwind_interval* uw = (unwind_interval *)cursor->intvl;
  
  TMSG(UNW,"step_sp: cursor { bp=%p, sp=%p, pc=%p }", bp, sp, pc);
  if (MYDBG) { dump_ui(uw, 0); }

  void** next_bp = NULL;
  void** next_sp = (void **)(sp + uw->sp_ra_pos);
  void*  ra_loc  = (void*) next_sp;
  void*  next_pc  = *next_sp;

  TMSG(UNW,"  step_sp: potential next cursor next_sp=%p ==> next_pc = %p",
       next_sp, next_pc);

  if (uw->bp_status == BP_UNCHANGED){
    next_bp = bp;
    TMSG(UNW,"  step_sp: unwind step has BP_UNCHANGED ==> next_bp=%p", next_bp);
  }
  else {
    //-----------------------------------------------------------
    // reload the candidate value for the caller's BP from the 
    // save area in the activation frame according to the unwind 
    // information produced by binary analysis
    //-----------------------------------------------------------
    next_bp = (void **)(sp + uw->sp_bp_pos);
    TMSG(UNW,"  step_sp: unwind next_bp loc = %p", next_bp);
    next_bp  = *next_bp; 
    TMSG(UNW,"  step_sp: sp unwind next_bp val = %p", next_bp);

  }
  next_sp += 1;
  ip_normalized_t next_pc_norm = ip_normalized_NULL;
  cursor->intvl = hpcrun_addr_to_interval(((char *)next_pc) - 1,
					  next_pc, &next_pc_norm);

  if (! cursor->intvl){
    if (((void *)next_sp) >= monitor_stack_bottom()){
      TMSG(UNW,"  step_sp: STEP_STOP_WEAK, no next interval and next_sp >= stack bottom,"
	   " so stop unwind ...");
      return STEP_STOP_WEAK;
    }
    else {
      TMSG(UNW,"  sp STEP_ERROR: no next interval, step fails");
      return STEP_ERROR;
    }
  }
  else {
    // sanity check to avoid infinite unwind loop
    if (next_sp <= cursor->sp){
      TMSG(INTV_ERR,"@ pc = %p. sp unwind does not advance stack." 
	   " New sp = %p, old sp = %p", cursor->pc_unnorm, next_sp,
	   cursor->sp);
      
      return STEP_ERROR;
    }
    unwind_interval* uw = (unwind_interval *)cursor->intvl;
    if ((RA_BP_FRAME == uw->ra_status) ||
	(RA_STD_FRAME == uw->ra_status)) { // Makes sense to sanity check BP, do it
      //-----------------------------------------------------------
      // if value of BP reloaded from the save area does not point 
      // into the stack, then it cannot possibly be useful as a frame 
      // pointer in the caller or any of its ancesters.
      //
      // if the value in the BP register points into the stack, then 
      // it might be useful as a frame pointer. in this case, we have 
      // nothing to lose by assuming that our binary analysis for 
      // unwinding might have been mistaken and that the value in 
      // the register is the one we might want. 
      //
      // 19 December 2007 - John Mellor-Crummey
      //-----------------------------------------------------------
    
      if (((unsigned long) next_bp < (unsigned long) sp) && 
	  ((unsigned long) bp > (unsigned long) sp)){
	next_bp = bp;
	TMSG(UNW,"  step_sp: unwind bp sanity check fails."
	     " Resetting next_bp to current bp = %p", next_bp);
      }
    }
    cursor->pc_unnorm = next_pc;
    cursor->bp 	      = next_bp;
    cursor->sp 	      = next_sp;
    cursor->ra_loc    = ra_loc;
    cursor->pc_norm   = next_pc_norm;
  }

  TMSG(UNW,"  step_sp: STEP_OK, has_intvl=%d, bp=%p, sp=%p, pc=%p",
	   cursor->intvl != NULL, next_bp, next_sp, next_pc);
  return STEP_OK;
}