Example #1
0
unwind_interval *
process_lea(xed_decoded_inst_t *xptr, const xed_inst_t *xi, interval_arg_t *iarg)
{
  highwatermark_t *hw_tmp = &(iarg->highwatermark);
  unwind_interval *next = iarg->current;
  const xed_operand_t *op0 =  xed_inst_operand(xi, 0);
  xed_operand_enum_t   op0_name = xed_operand_name(op0);

  if ((op0_name == XED_OPERAND_REG0)) { 
    xed_reg_enum_t regname = xed_decoded_inst_get_reg(xptr, op0_name);
    if (x86_isReg_BP(regname)) {
      //=======================================================================
      // action: clobbering the base pointer; begin a new SP_RELATIVE interval 
      // note: we don't check that BP is BP_SAVED; we might have to
      //=======================================================================
      next = new_ui(iarg->ins + xed_decoded_inst_get_length(xptr),
		    RA_SP_RELATIVE, iarg->current->sp_ra_pos, iarg->current->bp_ra_pos,
		    BP_HOSED, iarg->current->sp_bp_pos, iarg->current->bp_bp_pos,
		    iarg->current);
      if (HW_TEST_STATE(hw_tmp->state, HW_BP_SAVED,
			HW_BP_OVERWRITTEN) &&
	  (hw_tmp->uwi->sp_ra_pos == next->sp_ra_pos)) {
	hw_tmp->uwi = next;
	hw_tmp->state = 
	  HW_NEW_STATE(hw_tmp->state, HW_BP_OVERWRITTEN);
      }
    }
  }
  return next;
}
Example #2
0
void 
reset_to_canonical_interval(xed_decoded_inst_t *xptr, unwind_interval **next,
	bool irdebug, interval_arg_t *iarg, mem_alloc m_alloc)
{
  unwind_interval *current             = iarg->current;
  unwind_interval *first               = iarg->first;
  unwind_interval *hw_uwi              = iarg->highwatermark.uwi;

  // if the return is not the last instruction in the interval, 
  // set up an interval for code after the return 
  if (iarg->ins + xed_decoded_inst_get_length(xptr) < iarg->end){
    if (iarg->bp_frames_found) { 
      // look for first bp frame
      first = find_first_bp_frame(first);
      set_ui_canonical(first, iarg->canonical_interval);
      iarg->canonical_interval = first;
    } else if (iarg->canonical_interval) {
      if (hw_uwi && UWI_RECIPE(hw_uwi)->bp_status != BP_UNCHANGED)
	if ((UWI_RECIPE(iarg->canonical_interval)->bp_status == BP_UNCHANGED) ||
	    ((UWI_RECIPE(iarg->canonical_interval)->bp_status == BP_SAVED) &&
             (UWI_RECIPE(hw_uwi)->bp_status == BP_HOSED))) {
         set_ui_canonical(hw_uwi, iarg->canonical_interval);
         iarg->canonical_interval = hw_uwi;
      }
      first = iarg->canonical_interval;
    } else { 
      // look for first nondecreasing with no jmp
      first = find_first_non_decr(first, hw_uwi);
      set_ui_canonical(first, iarg->canonical_interval);
      iarg->canonical_interval = first;
    }
    {
      ra_loc ra_status = UWI_RECIPE(first)->ra_status;
      bp_loc bp_status =
    	  (UWI_RECIPE(current)->bp_status == BP_HOSED) ? BP_HOSED : UWI_RECIPE(first)->bp_status;
#ifndef FIX_INTERVALS_AT_RETURN
      if ((UWI_RECIPE(current)->ra_status != ra_status) ||
	  (UWI_RECIPE(current)->bp_status != bp_status) ||
	  (UWI_RECIPE(current)->sp_ra_pos != UWI_RECIPE(first)->sp_ra_pos) ||
	  (UWI_RECIPE(current)->bp_ra_pos != UWI_RECIPE(first)->bp_ra_pos) ||
	  (UWI_RECIPE(current)->bp_bp_pos != UWI_RECIPE(first)->bp_bp_pos) ||
	  (UWI_RECIPE(current)->sp_bp_pos != UWI_RECIPE(first)->sp_bp_pos))
#endif
	{
	*next = new_ui(iarg->ins + xed_decoded_inst_get_length(xptr),
		       ra_status, UWI_RECIPE(first)->sp_ra_pos, UWI_RECIPE(first)->bp_ra_pos,
		       bp_status, UWI_RECIPE(first)->sp_bp_pos, UWI_RECIPE(first)->bp_bp_pos,
		       current, m_alloc);
        set_ui_restored_canonical(*next, UWI_RECIPE(iarg->canonical_interval)->prev_canonical);
        if (UWI_RECIPE(first)->bp_status != BP_HOSED && bp_status == BP_HOSED) {
          set_ui_canonical(*next, iarg->canonical_interval);
          iarg->canonical_interval = *next;
        }
	return;
      }
    }
  }
  *next = current; 
}
Example #3
0
unwind_interval *
process_leave(xed_decoded_inst_t *xptr, const xed_inst_t *xi,
              interval_arg_t *iarg)
{
  unwind_interval *next;
  next = new_ui(iarg->ins + xed_decoded_inst_get_length(xptr), 
		RA_SP_RELATIVE, 0, 0, BP_UNCHANGED, 0, 0, iarg->current);
  return next;
}
Example #4
0
unwind_interval *
process_and(xed_decoded_inst_t *xptr, const xed_inst_t *xi, interval_arg_t *iarg,
	mem_alloc m_alloc)
{
  unwind_interval *next = iarg->current;
  const xed_operand_t* op0 = xed_inst_operand(xi,0);
  xed_operand_enum_t   op0_name = xed_operand_name(op0);

  if (op0_name == XED_OPERAND_REG0) {
	xed_reg_enum_t reg0 = xed_decoded_inst_get_reg(xptr, op0_name);
	if (x86_isReg_SP(reg0) && UWI_RECIPE(iarg->current)->bp_status != BP_UNCHANGED) {
	  //-----------------------------------------------------------------------
	  // we are adjusting the stack pointer via 'and' instruction
	  //-----------------------------------------------------------------------
	  next = new_ui(iarg->ins + xed_decoded_inst_get_length(xptr),
		  RA_BP_FRAME, UWI_RECIPE(iarg->current)->sp_ra_pos, UWI_RECIPE(iarg->current)->bp_ra_pos,
		  UWI_RECIPE(iarg->current)->bp_status, UWI_RECIPE(iarg->current)->sp_bp_pos,
		  UWI_RECIPE(iarg->current)->bp_bp_pos, iarg->current, m_alloc);
	}
  }
  return next;
}
Example #5
0
unwind_interval *
process_addsub(xed_decoded_inst_t *xptr, const xed_inst_t *xi, interval_arg_t *iarg)
{
  highwatermark_t *hw_tmp = &(iarg->highwatermark);

  unwind_interval *next = iarg->current;
  const xed_operand_t* op0 = xed_inst_operand(xi,0);
  const xed_operand_t* op1 = xed_inst_operand(xi,1);
  xed_operand_enum_t   op0_name = xed_operand_name(op0);

  if (op0_name == XED_OPERAND_REG0) {
    xed_reg_enum_t reg0 = xed_decoded_inst_get_reg(xptr, op0_name);
    if (x86_isReg_SP(reg0)) {
      //-----------------------------------------------------------------------
      // we are adjusting the stack pointer
      //-----------------------------------------------------------------------

      if (xed_operand_name(op1) == XED_OPERAND_IMM0) {
	int sign = (iclass_eq(xptr, XED_ICLASS_ADD)) ? -1 : 1;
	long immedv = sign * xed_decoded_inst_get_signed_immediate(xptr);
	ra_loc istatus = iarg->current->ra_status;
	if ((istatus == RA_STD_FRAME) && (immedv > 0) &&
	    (hw_tmp->state & HW_SP_DECREMENTED)) {
	  //-------------------------------------------------------------------
	  // if we are in a standard frame and we see a second subtract,
	  // it is time to convert interval to a BP frame to minimize
	  // the chance we get the wrong offset for the return address
	  // in a routine that manipulates SP frequently (as in
	  // leapfrog_mod_leapfrog_ in the SPEC CPU2006 benchmark
	  // 459.GemsFDTD, when compiled with PGI 7.0.3 with high levels
	  // of optimization).
	  //
	  // 9 December 2007 -- John Mellor-Crummey
	  //-------------------------------------------------------------------
	}
	next = new_ui(iarg->ins + xed_decoded_inst_get_length(xptr), 
		      istatus, iarg->current->sp_ra_pos + immedv, iarg->current->bp_ra_pos, 
		      iarg->current->bp_status, iarg->current->sp_bp_pos + immedv, 
		      iarg->current->bp_bp_pos, iarg->current);

	if (immedv > 0) {
	  if (HW_TEST_STATE(hw_tmp->state, 0, HW_SP_DECREMENTED)) {
	    //-----------------------------------------------------------------
	    // set the highwatermark and canonical interval upon seeing
	    // the FIRST subtract from SP; take no action on subsequent
	    // subtracts.
	    //
	    // test case: main in SPEC CPU2006 benchmark 470.lbm
	    // contains multiple subtracts from SP when compiled with
	    // PGI 7.0.3 with high levels of optimization. the first
	    // subtract from SP is to set up the frame; subsequent ones
	    // are to reserve space for arguments passed to functions.
	    //
	    // 9 December 2007 -- John Mellor-Crummey
	    //-----------------------------------------------------------------
	    hw_tmp->uwi = next;
	    hw_tmp->succ_inst_ptr = 
	      iarg->ins + xed_decoded_inst_get_length(xptr);
	    hw_tmp->state = 
	      HW_NEW_STATE(hw_tmp->state, HW_SP_DECREMENTED);
	    iarg->canonical_interval = next;
	  }
	}
      } else {
	if (iarg->current->ra_status != RA_BP_FRAME){
	  //-------------------------------------------------------------------
	  // no immediate in add/subtract from stack pointer; switch to
	  // BP_FRAME
	  //
	  // 9 December 2007 -- John Mellor-Crummey
	  //-------------------------------------------------------------------
	  next = new_ui(iarg->ins + xed_decoded_inst_get_length(xptr), RA_BP_FRAME, 
			iarg->current->sp_ra_pos, iarg->current->bp_ra_pos, 
			iarg->current->bp_status, iarg->current->sp_bp_pos, 
			iarg->current->bp_bp_pos, iarg->current);
	  iarg->bp_frames_found = true;
	}
      }
    }
  }
  return next;
}