Exemple #1
0
static inline void
computeNext_FPFrame(void** * nxt_sp, void** * nxt_fp,
		    unw_interval_t* intvl, void** fp)
{
  if (intvl->sp_arg != unwarg_NULL) {
    if (frameflg_isset(intvl->flgs, FrmFlg_FPOfstPos)) {
      *nxt_sp = getPtrFromPtr(fp, intvl->sp_arg);
    }
    else {
      *nxt_sp = getValFromPtr(fp, intvl->sp_arg);
    }
  }
  else {
    *nxt_sp = fp;
  }
  
  if (intvl->fp_arg != unwarg_NULL) {
    *nxt_fp = getValFromPtr(fp, intvl->fp_arg);
  }
}
// mips_build_intervals: build intervals for the range [beg_insn,
// end_insn).  Returns the first interval if retFirst is true,
// otherwise returns the last.
static UNW_INTERVAL_t
mips_build_intervals(uint32_t* beg_insn, uint32_t* end_insn, 
		     bool retFirst, int verbose)
{
  UNW_INTERVAL_t beg_ui = NEW_UI(INSN(beg_insn), FrmTy_SP, FrmFlg_RAReg,
				 0, unwarg_NULL, MIPS_REG_RA, NULL);
  UNW_INTERVAL_t ui = beg_ui;
  UNW_INTERVAL_t nxt_ui = UNW_INTERVAL_NULL;

  // canonical intervals
  UNW_INTERVAL_t canon_ui   = beg_ui;
  UNW_INTERVAL_t canonSP_ui = beg_ui;
  UNW_INTERVAL_t canonFP_ui = UNW_INTERVAL_NULL; // currently not needed

  int fp_saved_reg = 0;

  uint32_t* cur_insn = beg_insn;
  while (cur_insn < end_insn) {
    //TMSG(INTV, "insn: 0x%x [%p,%p)", *cur_insn, cur_insn, end_insn);

    //--------------------------------------------------
    // 1. SP-frames
    // 
    // SP-frame --> SP-frame: alloc/dealloc constant-sized frame
    // FP-frame --> FP-frame: additional storage [UNCOMMON]
    //--------------------------------------------------
    if (isAdjustSPByConst(*cur_insn)) {
      int sp_arg, ra_arg;
      
      if (UI_FLD(ui,ty) == FrmTy_SP) {
	//checkUI(UI_ARG(ui), FrmTy_SP, cur_insn);
	int amnt = getAdjustSPByConstAmnt(*cur_insn);
	
	sp_arg = UI_FLD(ui,sp_arg) + amnt;
	checkSPOfst(&sp_arg, UI_FLD(ui,sp_arg));
	
	ra_arg = UI_FLD(ui,ra_arg);
	if (!frameflg_isset(UI_FLD(ui,flgs), FrmFlg_RAReg)) {
	  ra_arg += amnt;
	  checkSPOfst(&ra_arg, UI_FLD(ui,ra_arg));
	}
      }
      else {
	sp_arg = UI_FLD(ui,sp_arg);
	ra_arg = UI_FLD(ui,ra_arg);
      }

      nxt_ui = NEW_UI(nextInsn(cur_insn), UI_FLD(ui,ty), UI_FLD(ui,flgs), 
		      sp_arg, UI_FLD(ui,fp_arg), ra_arg, ui);
      ui = nxt_ui;
    }

    //--------------------------------------------------
    // SP-frame --> SP-frame: store RA/FP
    // *** canonical frame ***
    //--------------------------------------------------
    else if (isStoreRegInFrame(*cur_insn, MIPS_REG_SP, MIPS_REG_RA)) {
      checkUI(UI_ARG(ui), FrmTy_SP, cur_insn);

      // store return address
      int ra_arg = getStoreRegInFrameOffset(*cur_insn);
      int16_t flgs = UI_FLD(ui,flgs);
      frameflg_unset(&flgs, FrmFlg_RAReg);

      nxt_ui = NEW_UI(nextInsn(cur_insn), FrmTy_SP, flgs,
		      UI_FLD(ui,sp_arg), UI_FLD(ui,fp_arg), ra_arg, ui);
      ui = nxt_ui;

      canon_ui = canonSP_ui = nxt_ui;
    }
    else if (isStoreRegInFrame(*cur_insn, MIPS_REG_SP, MIPS_REG_FP)) {
      checkUI(UI_ARG(ui), FrmTy_SP, cur_insn);

      // store frame pointer (N.B. fp may be used as saved reg s8)
      int fp_arg = getStoreRegInFrameOffset(*cur_insn);
      nxt_ui = NEW_UI(nextInsn(cur_insn), FrmTy_SP, UI_FLD(ui,flgs),
		      UI_FLD(ui,sp_arg), fp_arg, UI_FLD(ui,ra_arg), ui);
      ui = nxt_ui;

      canon_ui = canonSP_ui = nxt_ui;
    }

    //--------------------------------------------------
    // SP-frame --> SP-frame: load RA by SP
    //--------------------------------------------------
    else if (isLoadRegFromFrame(*cur_insn, MIPS_REG_SP, MIPS_REG_RA)) {
      checkUI(UI_ARG(ui), FrmTy_SP, cur_insn);

      // sanity check: sp_arg must be positive!
      // TODO: apply this check to other SP-relative ops.  Fix prior intervals
      int sp_arg = UI_FLD(ui,sp_arg);
      if ( !(sp_arg > 0) ) {
	sp_arg = UI_FLD(canonSP_ui,sp_arg);
      }

      nxt_ui = NEW_UI(nextInsn(cur_insn), FrmTy_SP, FrmFlg_RAReg,
		      sp_arg, UI_FLD(ui,fp_arg), MIPS_REG_RA, ui);
      ui = nxt_ui;
    }


    //--------------------------------------------------
    // 2. General: interior epilogues before returns
    //--------------------------------------------------
    else if (isJumpToReg(*cur_insn, MIPS_REG_RA)
	     && ((cur_insn + 1/*delay slot*/ + 1) < end_insn)) {
      // An interior return.  Restore the canonical interval if necessary.
      // 
      // N.B.: Although the delay slot instruction may affect the
      // frame, because of the return, we will never see its effect
      // within this procedure.  Therefore, it is harmless to skip
      // processing of this delay slot.
      if (!ui_cmp(UI_ARG(ui), UI_ARG(canon_ui))) {
	nxt_ui = NEW_UI(nextInsn(cur_insn + 1/*delay slot*/),
			UI_FLD(canon_ui,ty), UI_FLD(canon_ui,flgs), 
			UI_FLD(canon_ui,sp_arg), UI_FLD(canon_ui,fp_arg),
			UI_FLD(canon_ui,ra_arg), ui);
	ui = nxt_ui;
	cur_insn++; // skip delay slot and align new interval
      }
    }

    //--------------------------------------------------
    // General: interior epilogues before callsites
    //--------------------------------------------------
    else if (isCall(*cur_insn)
	     && frameflg_isset(UI_FLD(ui,flgs), FrmFlg_RAReg)) {
      // The callsite (jalr) is clobbering r31, but RA is in r31.  We
      // assume this is an inconsistency arising from control flow
      // jumping around an interior epilogue before the callsite.
      // Restore the canonical interval.
      if (!ui_cmp(UI_ARG(ui), UI_ARG(canon_ui))) {
	nxt_ui = NEW_UI(nextInsn(cur_insn),
			UI_FLD(canon_ui,ty), UI_FLD(canon_ui,flgs), 
			UI_FLD(canon_ui,sp_arg), UI_FLD(canon_ui,fp_arg),
			UI_FLD(canon_ui,ra_arg), ui);
	ui = nxt_ui;
      }
    }


    //--------------------------------------------------
    // 3. Basic support for FP frames.
    // 
    // *-frame --> FP-frame: store RA by FP
    // *** canonical frame ***
    //--------------------------------------------------
    else if (isStoreRegInFrame(*cur_insn, MIPS_REG_FP, MIPS_REG_RA)) {
      int sp_arg, fp_arg;
      if (UI_FLD(ui,ty) == FrmTy_SP) {
	sp_arg = unwarg_NULL;
	fp_arg = convertSPToFPOfst(UI_FLD(ui,sp_arg), UI_FLD(ui,fp_arg));
      }
      else {
	sp_arg = UI_FLD(ui,sp_arg);
	fp_arg = UI_FLD(ui,fp_arg);
      }
      int ra_arg = getStoreRegInFrameOffset(*cur_insn);

      int16_t flgs = UI_FLD(ui,flgs);
      frameflg_unset(&flgs, FrmFlg_RAReg);

      nxt_ui = NEW_UI(nextInsn(cur_insn), FrmTy_FP, flgs,
		      sp_arg, fp_arg, ra_arg, ui);
      ui = nxt_ui;
      
      canon_ui = canonFP_ui = nxt_ui;
    }

    //--------------------------------------------------
    // *-frame --> FP-frame: store parent FP (saved in reg) by FP
    // *** canonical frame ***
    //--------------------------------------------------
    else if (isMoveReg(*cur_insn, MIPS_REG_V0, MIPS_REG_FP)) {
      frameflg_set(&UI_FLD(ui,flgs), FrmFlg_FPInV);
      fp_saved_reg = MIPS_REG_V0;
    }
    else if (isMoveReg(*cur_insn, MIPS_REG_V1, MIPS_REG_FP)) {
      frameflg_set(&UI_FLD(ui,flgs), FrmFlg_FPInV);
      fp_saved_reg = MIPS_REG_V1;
    }
    else if (frameflg_isset(UI_FLD(ui,flgs), FrmFlg_FPInV) &&
	     isStoreRegInFrame(*cur_insn, MIPS_REG_FP, fp_saved_reg)) {
      int sp_arg, ra_arg;
      if (UI_FLD(ui,ty) == FrmTy_SP) {
	sp_arg = unwarg_NULL;
	ra_arg = convertSPToFPOfst(UI_FLD(ui,sp_arg), UI_FLD(ui,ra_arg));
      }
      else {
	sp_arg = UI_FLD(ui,sp_arg);
	ra_arg = UI_FLD(ui,ra_arg);
      }
      int fp_arg = getStoreRegInFrameOffset(*cur_insn);

      nxt_ui = NEW_UI(nextInsn(cur_insn), FrmTy_FP, UI_FLD(ui,flgs),
		      sp_arg, fp_arg, ra_arg, ui);
      ui = nxt_ui;
      
      canon_ui = canonFP_ui = nxt_ui;
    }
    /* else if (store-parent's-SP): useless */

    //--------------------------------------------------
    // *-frame --> FP-frame: allocate variable-sized frame
    // *** canonical frame ***
    //--------------------------------------------------
    else if (isMoveReg(*cur_insn, MIPS_REG_FP, MIPS_REG_SP)) {
      // FP is set to SP, likely meaning it will point to the middle
      // of the frame (pos. offsets) rather than the top (neg. offsets)
      // ??? test that the canonical FP frame has not been set ???
      frameflg_set(&UI_FLD(ui,flgs), FrmFlg_FPOfstPos);
    }
    else if (isAdjustSPByVar(*cur_insn)) {
      // TODO: ensure "daddu sp,sp,v0" is allocation rather than deallocation

      // if canonical interval has been set and it is an SP-frame...
      if (!UI_CMP_OPT(canon_ui, beg_ui) && UI_FLD(canon_ui,ty) == FrmTy_SP) {
	int16_t flgs = UI_FLD(ui,flgs);
	int sp_arg, fp_arg, ra_arg;

	if (frameflg_isset(flgs, FrmFlg_FPOfstPos)) {
	  sp_arg = UI_FLD(canon_ui,sp_arg);
	  fp_arg = UI_FLD(canon_ui,fp_arg);
	  ra_arg = UI_FLD(canon_ui,ra_arg);
	}
	else {
	  sp_arg = unwarg_NULL;
	  fp_arg = convertSPToFPOfst(UI_FLD(canon_ui,sp_arg), 
				     UI_FLD(canon_ui,fp_arg));
	  ra_arg = convertSPToFPOfst(UI_FLD(canon_ui,sp_arg), 
				     UI_FLD(canon_ui,ra_arg));
	}
	  
	frameflg_set(&flgs, FrmFlg_FrmSzUnk);
	
	nxt_ui = NEW_UI(nextInsn(cur_insn), FrmTy_FP, flgs,
			sp_arg, fp_arg, ra_arg, ui);
	ui = nxt_ui;

	canon_ui = canonFP_ui = nxt_ui;
      }
    }

    //--------------------------------------------------
    // FP-frame --> FP-frame: load RA by FP
    //--------------------------------------------------
    else if (isLoadRegFromFrame(*cur_insn, MIPS_REG_FP, MIPS_REG_RA)) {
      checkUI(UI_ARG(ui), FrmTy_FP, cur_insn);
      nxt_ui = NEW_UI(nextInsn(cur_insn), FrmTy_FP, FrmFlg_RAReg,
		      UI_FLD(ui,sp_arg), UI_FLD(ui,fp_arg), MIPS_REG_RA, ui);
      ui = nxt_ui;
    }
    /* else if (load-parent's-FP): not needed */
    /* else if (load-parent's-SP): useless */

    //--------------------------------------------------
    // FP-frame --> SP-frame: deallocate (all/part of) frame by restoring SP
    //--------------------------------------------------
    else if (isMoveReg(*cur_insn, MIPS_REG_SP, MIPS_REG_FP)) {
      if (UI_FLD(ui,ty) == FrmTy_FP) {
	bool isFullDealloc = 
	  (!frameflg_isset(UI_FLD(canon_ui,flgs), FrmFlg_RAReg)
	   && frameflg_isset(UI_FLD(ui,flgs), FrmFlg_RAReg));
	
	int flgs = (isFullDealloc) ? FrmFlg_RAReg : UI_FLD(canonSP_ui,flgs);
	int sp_arg, fp_arg, ra_arg;
	sp_arg = (isFullDealloc) ? 0           : UI_FLD(canonSP_ui,sp_arg);
	fp_arg = (isFullDealloc) ? unwarg_NULL : UI_FLD(canonSP_ui,fp_arg);
	ra_arg = (isFullDealloc) ? MIPS_REG_RA : UI_FLD(canonSP_ui,ra_arg);
	nxt_ui = NEW_UI(nextInsn(cur_insn), FrmTy_SP, flgs,
			sp_arg, fp_arg, ra_arg, ui);
	ui = nxt_ui;
      }
      else {
	// wierd code, e.g., monitor_main! Assume rest of frame will
	// be deallocated normally.  Could restore a canonical frame
	// (FIXME).
      }
    }
    
    cur_insn++;
  }

  HPC_IFNO_UNW_LITE( UI_FLD(ui,common).end = INSN(end_insn); )

#if (!HPC_UNW_LITE)
  if (verbose) {