コード例 #1
0
ファイル: pyvex_deepcopy.c プロジェクト: CRYPTOlab/pyvex
IRSB* pyvex_deepCopyIRSBExceptStmts ( IRSB* bb )
{
   IRSB* bb2     = emptyIRSB();
   bb2->tyenv    = pyvex_deepCopyIRTypeEnv(bb->tyenv);
   bb2->next = NULL; if (bb->next) bb2->next     = pyvex_deepCopyIRExpr(bb->next);
   bb2->jumpkind = bb->jumpkind;
   bb2->offsIP   = bb->offsIP;
   return bb2;
}
コード例 #2
0
ファイル: pyvex_irsb.c プロジェクト: rmallof/pyvex
static int
pyIRSB_init(pyIRSB *self, PyObject *args, PyObject *kwargs)
{
	if (!kwargs) { self->wrapped = PYVEX_COPYOUT(IRSB, emptyIRSB()); return 0; }
	PYVEX_WRAP_CONSTRUCTOR(IRSB);

#ifdef PYVEX_STATIC
	unsigned char *bytes = NULL;
	unsigned int mem_addr = 0;
	int num_inst = -1;
	int num_bytes = -1;

	static char *kwlist[] = {"bytes", "mem_addr", "num_inst", NULL};
	if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|s#ii", kwlist, &bytes, &num_bytes, &mem_addr, &num_inst)) return -1;

	if (num_bytes == 0)
	{
		PyErr_SetString(VexException, "No bytes provided");
		return -1;
	}

	if (num_bytes > 0)
	{
		vex_init();
		if (num_inst > -1) self->wrapped = vex_block_inst(VexArchAMD64, bytes, mem_addr, num_inst);
		else self->wrapped = vex_block_bytes(VexArchAMD64, bytes, mem_addr, num_bytes);

		self->wrapped = PYVEX_COPYOUT(IRSB, self->wrapped);

		if (self->wrapped == NULL) { PyErr_SetString(VexException, "Error creating IR."); return -1; }
		return 0;
	}

	PyErr_SetString(VexException, "Not enough arguments provided.");
	return -1;
#else
	PyErr_SetString(VexException, "Statically creating IRSBs is disabled.");
	return -1;
#endif
}
コード例 #3
0
ファイル: drd_main.c プロジェクト: svn2github/valgrind-3
static
IRSB* drd_instrument(VgCallbackClosure* const closure,
                     IRSB* const bb_in,
                     VexGuestLayout* const layout,
                     VexGuestExtents* const vge, 
                     IRType const gWordTy,
                     IRType const hWordTy)
{
  IRDirty* di;
  Int      i;
  IRSB*    bb;
  IRExpr** argv;
  Bool     instrument = True;
  Bool     bus_locked = False;

  /* Set up BB */
  bb           = emptyIRSB();
  bb->tyenv    = deepCopyIRTypeEnv(bb_in->tyenv);
  bb->next     = deepCopyIRExpr(bb_in->next);
  bb->jumpkind = bb_in->jumpkind;

  for (i = 0; i < bb_in->stmts_used; i++)
  {
    IRStmt* const st = bb_in->stmts[i];
    tl_assert(st);
    if (st->tag == Ist_NoOp)
      continue;

    switch (st->tag)
    {
    /* Note: the code for not instrumenting the code in .plt          */
    /* sections is only necessary on CentOS 3.0 x86 (kernel 2.4.21    */
    /* + glibc 2.3.2 + NPTL 0.60 + binutils 2.14.90.0.4).             */
    /* This is because on this platform dynamic library symbols are   */
    /* relocated in another way than by later binutils versions. The  */
    /* linker e.g. does not generate .got.plt sections on CentOS 3.0. */
    case Ist_IMark:
      instrument = VG_(seginfo_sect_kind)(NULL, 0, st->Ist.IMark.addr)
        != Vg_SectPLT;
      addStmtToIRSB(bb, st);
      break;

    case Ist_MBE:
      switch (st->Ist.MBE.event)
      {
      case Imbe_Fence:
        break; /* not interesting */
      case Imbe_BusLock:
      case Imbe_SnoopedStoreBegin:
        tl_assert(! bus_locked);
        bus_locked = True;
        break;
      case Imbe_BusUnlock:
      case Imbe_SnoopedStoreEnd:
        tl_assert(bus_locked);
        bus_locked = False;
        break;
      default:
        tl_assert(0);
      }
      addStmtToIRSB(bb, st);
      break;

    case Ist_Store:
      if (instrument && ! bus_locked)
      {
        instrument_store(bb,
                         st->Ist.Store.addr,
                         sizeofIRType(typeOfIRExpr(bb->tyenv,
                                                   st->Ist.Store.data)));
      }
      addStmtToIRSB(bb, st);
      break;

    case Ist_WrTmp:
      if (instrument)
      {
        const IRExpr* const data = st->Ist.WrTmp.data;
        if (data->tag == Iex_Load)
        {
          instrument_load(bb,
                          data->Iex.Load.addr,
                          sizeofIRType(data->Iex.Load.ty));
        }
      }
      addStmtToIRSB(bb, st);
      break;

    case Ist_Dirty:
      if (instrument)
      {
        IRDirty* d = st->Ist.Dirty.details;
        IREffect const mFx = d->mFx;
        switch (mFx) {
        case Ifx_None:
          break;
        case Ifx_Read:
        case Ifx_Write:
        case Ifx_Modify:
          tl_assert(d->mAddr);
          tl_assert(d->mSize > 0);
          argv = mkIRExprVec_2(d->mAddr, mkIRExpr_HWord(d->mSize));
          if (mFx == Ifx_Read || mFx == Ifx_Modify) {
            di = unsafeIRDirty_0_N(
                                   /*regparms*/2,
                                   "drd_trace_load",
                                   VG_(fnptr_to_fnentry)(drd_trace_load),
                                   argv);
            addStmtToIRSB(bb, IRStmt_Dirty(di));
          }
          if ((mFx == Ifx_Write || mFx == Ifx_Modify)
              && ! bus_locked)
          {
            di = unsafeIRDirty_0_N(
                                   /*regparms*/2,
                                   "drd_trace_store",
                                   VG_(fnptr_to_fnentry)(drd_trace_store),
                                   argv);
            addStmtToIRSB(bb, IRStmt_Dirty(di));
          }
          break;
        default:
          tl_assert(0);
        }
      }
      addStmtToIRSB(bb, st);
      break;

    default:
      addStmtToIRSB(bb, st);
      break;
    }
  }

  tl_assert(! bus_locked);

  return bb;
}
コード例 #4
0
ファイル: ca_main.c プロジェクト: cherry-wb/SmartFuzz
static
IRSB* ca_instrument( VgCallbackClosure * closure, 
		     IRSB* bb_in, 
		     VexGuestLayout* layout, 
                     VexGuestExtents* vge,
                     IRType gWordTy, IRType hWordTy )
{
   Int      i;
   IRSB*    bb;
   Int      count1;
   Int      count2;
   Int      count3;
   Int      count4;
   Int      count5;
   Int      count6;
   Int      count7;
   Int      count8;
   Int      count9;
   Int      sum; 
   findRepMovContext * repMovContext; 

  // do not instrument block if we have not yet read from tainted data
    if (run_prefix_task == 0)
    {

      /* Update count of BBs instrumented. Do it here to agree with */
      /* Valgrind core numbering of BBs instrumented.               */ 
      /* NOTE: our numbering of BBs executed does not agree w/core! */
      caMainBBCounter++; 
      return bb_in;
    }



   /* Counting the number of entries in a hash table */
   count1 = ca_count_hashtable(ogVarOf);
   count2 = ca_count_hashtable(ogTypeOf);
   count3 = ca_count_hashtable(cgPathCond);
   count4 = ca_count_hashtable(isIsSymbolic);
   count5 = ca_count_hashtable(caIntervalTable);
   count6 = ca_count_hashtable(cgIsDeclared);
   count7 = ca_count_hashtable(cgITEWriteStackMemSt);
   count8 = ca_count_hashtable(cgITEWriteStackMaSt);
   count9 = ca_count_hashtable(tmAddrToVar);

   // debugging option
   if (ca_output_comment) {
     VG_(printf)("XXX The number of has entries in hash tables 1-9 are %d %d %d %d %d %d %d %d %d\n",
	       count1, count2, count3, count4, count5, count6, count7, count8, count9);

     sum = count1 + count2 + count3 + count4 + count5 + count6 + count7 + count8 + count9;
     VG_(printf)("XXX The total number of hash entries in all the tables is %d\n", sum);

     VG_(printf)("XXX The size of each entry for the hash tables 1-9 are %d %d %d %d %d %d %d %d %d\n", 
	       sizeof(OgVarOfHashNode), sizeof(ogTypeOf), sizeof(cgPathCond),
	       sizeof(isIsSymbolic), sizeof(caIntervalTable), sizeof(cgIsDeclared), 
	       sizeof(cgITEWriteStackMemSt), sizeof(cgITEWriteStackMaSt), sizeof(tmAddrToVar));
   }

   if (gWordTy != hWordTy) {
	VG_(printf)("MISMATCH: "); 
	ppIRType(gWordTy);
	VG_(printf)(" "); 
	ppIRType(hWordTy);
	VG_(printf)("\n"); 
      /* We don't currently support this case. */
      VG_(tool_panic)("host/guest word size mismatch");
   }


   /* Set up BB */
   bb           = emptyIRSB();
   bb->tyenv    = deepCopyIRTypeEnv(bb_in->tyenv);
   bb->next     = deepCopyIRExpr(bb_in->next);
   bb->jumpkind = bb_in->jumpkind;

   /* Set up context for finding rep mov instructions */
   /* assume at most 400 tmp vars per basic block     */ 
   repMovContext = createRepMovContext(bb->tyenv->types_used); 


   // Copy verbatim any IR preamble preceding the first IMark
   i = 0;
   while (i < bb_in->stmts_used && bb_in->stmts[i]->tag != Ist_IMark) {
      addStmtToIRSB( bb, bb_in->stmts[i] );
      i++;
   }

     cgAddPreamble(bb,caMainBBCounter); 

   for (/*use current i*/; i < bb_in->stmts_used; i++) {
      IRStmt* st = bb_in->stmts[i];
      if (!st || st->tag == Ist_NoOp) continue;

      
      if (st->tag == Ist_Exit)
	{
	  cgAddExitPre(bb,st);
	}

      addStmtToIRSB(bb, st );
      if (ca_type_inference)
      {
	ogIRStmt(bb, st, caMainBBCounter);
      }
      
      ufInstOgIRStmt(bb, st, caMainBBCounter); 
      findRepMovIRStmt(bb, st, repMovContext, caMainBBCounter); 
      isIRStmt(bb, st, caMainBBCounter); 
      tmIRStmt(bb, st, caMainBBCounter);
      cgIRStmt(bb, st, caMainBBCounter); 
     
      if (st->tag == Ist_Exit)
      {
	cgAddExitPost(bb,st);  
      }
      
   }


   /* Update count of BBs instrumented. Do it here to agree with */
   /* Valgrind core numbering of BBs instrumented.               */ 
   caMainBBCounter++; 

   /* Destroy the rep mov context */ 
   destroyRepMovContext(repMovContext); 

   /* Return the new bb */ 
    return bb;
}
コード例 #5
0
IRSB* DRD_(instrument)(VgCallbackClosure* const closure,
                       IRSB* const bb_in,
                       VexGuestLayout* const layout,
                       VexGuestExtents* const vge, 
                       IRType const gWordTy,
                       IRType const hWordTy)
{
   IRDirty* di;
   Int      i;
   IRSB*    bb;
   IRExpr** argv;
   Bool     instrument = True;

   /* Set up BB */
   bb           = emptyIRSB();
   bb->tyenv    = deepCopyIRTypeEnv(bb_in->tyenv);
   bb->next     = deepCopyIRExpr(bb_in->next);
   bb->jumpkind = bb_in->jumpkind;

   for (i = 0; i < bb_in->stmts_used; i++)
   {
      IRStmt* const st = bb_in->stmts[i];
      tl_assert(st);
      if (st->tag == Ist_NoOp)
         continue;

      switch (st->tag)
      {
         /* Note: the code for not instrumenting the code in .plt          */
         /* sections is only necessary on CentOS 3.0 x86 (kernel 2.4.21    */
         /* + glibc 2.3.2 + NPTL 0.60 + binutils 2.14.90.0.4).             */
         /* This is because on this platform dynamic library symbols are   */
         /* relocated in another way than by later binutils versions. The  */
         /* linker e.g. does not generate .got.plt sections on CentOS 3.0. */
      case Ist_IMark:
         instrument = VG_(seginfo_sect_kind)(NULL, 0, st->Ist.IMark.addr)
            != Vg_SectPLT;
         addStmtToIRSB(bb, st);
         break;

      case Ist_MBE:
         switch (st->Ist.MBE.event)
         {
         case Imbe_Fence:
            break; /* not interesting */
         default:
            tl_assert(0);
         }
         addStmtToIRSB(bb, st);
         break;

      case Ist_Store:
         if (instrument && /* ignore stores resulting from st{d,w}cx. */
                           st->Ist.Store.resSC == IRTemp_INVALID)
         {
            instrument_store(bb,
                             st->Ist.Store.addr,
                             sizeofIRType(typeOfIRExpr(bb->tyenv,
                                                       st->Ist.Store.data)));
         }
         addStmtToIRSB(bb, st);
         break;

      case Ist_WrTmp:
         if (instrument)
         {
            const IRExpr* const data = st->Ist.WrTmp.data;
            if (data->tag == Iex_Load)
            {
               instrument_load(bb,
                               data->Iex.Load.addr,
                               sizeofIRType(data->Iex.Load.ty));
            }
         }
         addStmtToIRSB(bb, st);
         break;

      case Ist_Dirty:
         if (instrument)
         {
            IRDirty* d = st->Ist.Dirty.details;
            IREffect const mFx = d->mFx;
            switch (mFx) {
            case Ifx_None:
               break;
            case Ifx_Read:
            case Ifx_Write:
            case Ifx_Modify:
               tl_assert(d->mAddr);
               tl_assert(d->mSize > 0);
               argv = mkIRExprVec_2(d->mAddr, mkIRExpr_HWord(d->mSize));
               if (mFx == Ifx_Read || mFx == Ifx_Modify) {
                  di = unsafeIRDirty_0_N(
                          /*regparms*/2,
                          "drd_trace_load",
                          VG_(fnptr_to_fnentry)(DRD_(trace_load)),
                          argv);
                  addStmtToIRSB(bb, IRStmt_Dirty(di));
               }
               if (mFx == Ifx_Write || mFx == Ifx_Modify)
               {
                  di = unsafeIRDirty_0_N(
                          /*regparms*/2,
                          "drd_trace_store",
                          VG_(fnptr_to_fnentry)(DRD_(trace_store)),
                          argv);
                  addStmtToIRSB(bb, IRStmt_Dirty(di));
               }
               break;
            default:
               tl_assert(0);
            }
         }
         addStmtToIRSB(bb, st);
         break;

      case Ist_CAS:
         if (instrument)
         {
            /*
             * Treat compare-and-swap as a read. By handling atomic
             * instructions as read instructions no data races are reported
             * between conflicting atomic operations nor between atomic
             * operations and non-atomic reads. Conflicts between atomic
             * operations and non-atomic write operations are still reported
             * however.
             */
            Int    dataSize;
            IRCAS* cas = st->Ist.CAS.details;
            tl_assert(cas->addr != NULL);
            tl_assert(cas->dataLo != NULL);
            dataSize = sizeofIRType(typeOfIRExpr(bb->tyenv, cas->dataLo));
            if (cas->dataHi != NULL)
               dataSize *= 2; /* since it's a doubleword-CAS */
            instrument_load(bb, cas->addr, dataSize);
         }
         addStmtToIRSB(bb, st);
         break;

      default:
         addStmtToIRSB(bb, st);
         break;
      }
   }

   return bb;
}
コード例 #6
0
ファイル: m_translate.c プロジェクト: svn2github/valgrind-3
/* For tools that want to know about SP changes, this pass adds
   in the appropriate hooks.  We have to do it after the tool's
   instrumentation, so the tool doesn't have to worry about the C calls
   it adds in, and we must do it before register allocation because
   spilled temps make it much harder to work out the SP deltas.
   This it is done with Vex's "second instrumentation" pass.

   Basically, we look for GET(SP)/PUT(SP) pairs and track constant
   increments/decrements of SP between them.  (This requires tracking one or
   more "aliases", which are not exact aliases but instead are tempregs
   whose value is equal to the SP's plus or minus a known constant.)
   If all the changes to SP leading up to a PUT(SP) are by known, small
   constants, we can do a specific call to eg. new_mem_stack_4, otherwise
   we fall back to the case that handles an unknown SP change.
*/
static
IRSB* vg_SP_update_pass ( void*             closureV,
                          IRSB*             sb_in, 
                          VexGuestLayout*   layout, 
                          VexGuestExtents*  vge,
                          IRType            gWordTy, 
                          IRType            hWordTy )
{
   Int         i, j, minoff_ST, maxoff_ST, sizeof_SP, offset_SP;
   IRDirty     *dcall, *d;
   IRStmt*     st;
   IRExpr*     e;
   IRRegArray* descr;
   IRType      typeof_SP;
   Long        delta, con;

   /* Set up BB */
   IRSB* bb     = emptyIRSB();
   bb->tyenv    = deepCopyIRTypeEnv(sb_in->tyenv);
   bb->next     = deepCopyIRExpr(sb_in->next);
   bb->jumpkind = sb_in->jumpkind;

   delta = 0;

   sizeof_SP = layout->sizeof_SP;
   offset_SP = layout->offset_SP;
   typeof_SP = sizeof_SP==4 ? Ity_I32 : Ity_I64;
   vg_assert(sizeof_SP == 4 || sizeof_SP == 8);

#  define IS_ADD(op) (sizeof_SP==4 ? ((op)==Iop_Add32) : ((op)==Iop_Add64))
#  define IS_SUB(op) (sizeof_SP==4 ? ((op)==Iop_Sub32) : ((op)==Iop_Sub64))

#  define IS_ADD_OR_SUB(op) (IS_ADD(op) || IS_SUB(op))

#  define GET_CONST(con)                                                \
       (sizeof_SP==4 ? (Long)(Int)(con->Ico.U32)                        \
                     : (Long)(con->Ico.U64))

// XXX: convert this to a function
#  define DO(kind, syze, tmpp)                                          \
      do {                                                              \
         if (!VG_(tdict).track_##kind##_mem_stack_##syze)               \
            goto generic;                                               \
                                                                        \
         /* I don't know if it's really necessary to say that the */    \
         /* call reads the stack pointer.  But anyway, we do. */        \
         dcall = unsafeIRDirty_0_N(                                     \
                    1/*regparms*/,                                      \
                    "track_" #kind "_mem_stack_" #syze,                 \
                    VG_(fnptr_to_fnentry)(                              \
                       VG_(tdict).track_##kind##_mem_stack_##syze ),    \
                    mkIRExprVec_1(IRExpr_RdTmp(tmpp))                   \
                 );                                                     \
         dcall->nFxState = 1;                                           \
         dcall->fxState[0].fx     = Ifx_Read;                           \
         dcall->fxState[0].offset = layout->offset_SP;                  \
         dcall->fxState[0].size   = layout->sizeof_SP;                  \
                                                                        \
         addStmtToIRSB( bb, IRStmt_Dirty(dcall) );                      \
                                                                        \
         update_SP_aliases(-delta);                                     \
                                                                        \
         n_SP_updates_fast++;                                           \
                                                                        \
      } while (0)

   clear_SP_aliases();

   for (i = 0; i <  sb_in->stmts_used; i++) {

      st = sb_in->stmts[i];

      /* t = Get(sp):   curr = t, delta = 0 */
      if (st->tag != Ist_WrTmp) goto case2;
      e = st->Ist.WrTmp.data;
      if (e->tag != Iex_Get)              goto case2;
      if (e->Iex.Get.offset != offset_SP) goto case2;
      if (e->Iex.Get.ty != typeof_SP)     goto case2;
      add_SP_alias(st->Ist.WrTmp.tmp, 0);
      addStmtToIRSB( bb, st );
      continue;

     case2:
      /* t' = curr +/- const:   curr = t',  delta +=/-= const */
      if (st->tag != Ist_WrTmp) goto case3;
      e = st->Ist.WrTmp.data;
      if (e->tag != Iex_Binop) goto case3;
      if (e->Iex.Binop.arg1->tag != Iex_RdTmp) goto case3;
      if (!get_SP_delta(e->Iex.Binop.arg1->Iex.RdTmp.tmp, &delta)) goto case3;
      if (e->Iex.Binop.arg2->tag != Iex_Const) goto case3;
      if (!IS_ADD_OR_SUB(e->Iex.Binop.op)) goto case3;
      con = GET_CONST(e->Iex.Binop.arg2->Iex.Const.con);
      if (IS_ADD(e->Iex.Binop.op)) {
         add_SP_alias(st->Ist.WrTmp.tmp, delta + con);
      } else {
         add_SP_alias(st->Ist.WrTmp.tmp, delta - con);
      }
      addStmtToIRSB( bb, st );
      continue;

     case3:
      /* t' = curr:   curr = t' */
      if (st->tag != Ist_WrTmp) goto case4;
      e = st->Ist.WrTmp.data;
      if (e->tag != Iex_RdTmp) goto case4;
      if (!get_SP_delta(e->Iex.RdTmp.tmp, &delta)) goto case4;
      add_SP_alias(st->Ist.WrTmp.tmp, delta);
      addStmtToIRSB( bb, st );
      continue;

     case4:
      /* Put(sp) = curr */
      if (st->tag != Ist_Put) goto case5;
      if (st->Ist.Put.offset != offset_SP) goto case5;
      if (st->Ist.Put.data->tag != Iex_RdTmp) goto case5;
      if (get_SP_delta(st->Ist.Put.data->Iex.RdTmp.tmp, &delta)) {
         IRTemp tttmp = st->Ist.Put.data->Iex.RdTmp.tmp;
         switch (delta) {
            case    0:                      addStmtToIRSB(bb,st); continue;
            case    4: DO(die,  4,  tttmp); addStmtToIRSB(bb,st); continue;
            case   -4: DO(new,  4,  tttmp); addStmtToIRSB(bb,st); continue;
            case    8: DO(die,  8,  tttmp); addStmtToIRSB(bb,st); continue;
            case   -8: DO(new,  8,  tttmp); addStmtToIRSB(bb,st); continue;
            case   12: DO(die,  12, tttmp); addStmtToIRSB(bb,st); continue;
            case  -12: DO(new,  12, tttmp); addStmtToIRSB(bb,st); continue;
            case   16: DO(die,  16, tttmp); addStmtToIRSB(bb,st); continue;
            case  -16: DO(new,  16, tttmp); addStmtToIRSB(bb,st); continue;
            case   32: DO(die,  32, tttmp); addStmtToIRSB(bb,st); continue;
            case  -32: DO(new,  32, tttmp); addStmtToIRSB(bb,st); continue;
            case  112: DO(die, 112, tttmp); addStmtToIRSB(bb,st); continue;
            case -112: DO(new, 112, tttmp); addStmtToIRSB(bb,st); continue;
            case  128: DO(die, 128, tttmp); addStmtToIRSB(bb,st); continue;
            case -128: DO(new, 128, tttmp); addStmtToIRSB(bb,st); continue;
            case  144: DO(die, 144, tttmp); addStmtToIRSB(bb,st); continue;
            case -144: DO(new, 144, tttmp); addStmtToIRSB(bb,st); continue;
            case  160: DO(die, 160, tttmp); addStmtToIRSB(bb,st); continue;
            case -160: DO(new, 160, tttmp); addStmtToIRSB(bb,st); continue;
            default:  
               /* common values for ppc64: 144 128 160 112 176 */
               n_SP_updates_generic_known++;
               goto generic;
         }
      } else {
コード例 #7
0
ファイル: drd_main.c プロジェクト: svn2github/valgrind-3
static
IRSB* drd_instrument(VgCallbackClosure* const closure,
                     IRSB* const bb_in,
                     VexGuestLayout* const layout,
                     VexGuestExtents* const vge,
                     IRType const gWordTy,
                     IRType const hWordTy)
{
    IRDirty* di;
    Int      i;
    IRSB*    bb;
    IRExpr** argv;
    Bool     instrument = True;
    Bool     bus_locked = False;

    /* Set up BB */
    bb           = emptyIRSB();
    bb->tyenv    = deepCopyIRTypeEnv(bb_in->tyenv);
    bb->next     = deepCopyIRExpr(bb_in->next);
    bb->jumpkind = bb_in->jumpkind;

    for (i = 0; i < bb_in->stmts_used; i++)
    {
        IRStmt* const st = bb_in->stmts[i];
        tl_assert(st);
        if (st->tag == Ist_NoOp)
            continue;

        switch (st->tag)
        {
        case Ist_MBE:
            switch (st->Ist.MBE.event)
            {
            case Imbe_Fence:
                break; /* not interesting */
            case Imbe_BusLock:
                tl_assert(! bus_locked);
                bus_locked = True;
                break;
            case Imbe_BusUnlock:
                tl_assert(bus_locked);
                bus_locked = False;
                break;
            default:
                tl_assert(0);
            }
            addStmtToIRSB(bb, st);
            break;

        case Ist_Store:
            if (instrument && ! bus_locked)
            {
                instrument_store(bb,
                                 st->Ist.Store.addr,
                                 sizeofIRType(typeOfIRExpr(bb->tyenv,
                                              st->Ist.Store.data)));
            }
            addStmtToIRSB(bb, st);
            break;

        case Ist_WrTmp:
            if (instrument)
            {
                const IRExpr* const data = st->Ist.WrTmp.data;
                if (data->tag == Iex_Load)
                {
                    instrument_load(bb,
                                    data->Iex.Load.addr,
                                    sizeofIRType(data->Iex.Load.ty));
                }
            }
            addStmtToIRSB(bb, st);
            break;

        case Ist_Dirty:
            if (instrument)
            {
                IRDirty* d = st->Ist.Dirty.details;
                IREffect const mFx = d->mFx;
                switch (mFx) {
                case Ifx_None:
                    break;
                case Ifx_Read:
                case Ifx_Write:
                case Ifx_Modify:
                    tl_assert(d->mAddr);
                    tl_assert(d->mSize > 0);
                    argv = mkIRExprVec_2(d->mAddr, mkIRExpr_HWord(d->mSize));
                    if (mFx == Ifx_Read || mFx == Ifx_Modify) {
                        di = unsafeIRDirty_0_N(
                                 /*regparms*/2,
                                 "drd_trace_load",
                                 VG_(fnptr_to_fnentry)(drd_trace_load),
                                 argv);
                        addStmtToIRSB(bb, IRStmt_Dirty(di));
                    }
                    if ((mFx == Ifx_Write || mFx == Ifx_Modify)
                            && ! bus_locked)
                    {
                        di = unsafeIRDirty_0_N(
                                 /*regparms*/2,
                                 "drd_trace_store",
                                 VG_(fnptr_to_fnentry)(drd_trace_store),
                                 argv);
                        addStmtToIRSB(bb, IRStmt_Dirty(di));
                    }
                    break;
                default:
                    tl_assert(0);
                }
            }
            addStmtToIRSB(bb, st);
            break;

        default:
            addStmtToIRSB(bb, st);
            break;
        }
    }

    tl_assert(! bus_locked);

    return bb;
}
コード例 #8
0
ファイル: bb_to_IR.c プロジェクト: bengheng/Expose
IRSB* bb_to_IR ( /*OUT*/VexGuestExtents* vge,
                 /*IN*/ void*            callback_opaque,
                 /*IN*/ DisOneInstrFn    dis_instr_fn,
                 /*IN*/ UChar*           guest_code,
                 /*IN*/ Addr64           guest_IP_bbstart,
                 /*IN*/ Bool             (*chase_into_ok)(void*,Addr64),
                 /*IN*/ Bool             host_bigendian,
                 /*IN*/ VexArch          arch_guest,
                 /*IN*/ VexArchInfo*     archinfo_guest,
                 /*IN*/ VexAbiInfo*      abiinfo_both,
                 /*IN*/ IRType           guest_word_type,
                 /*IN*/ Bool             do_self_check,
                 /*IN*/ Bool             (*preamble_function)(void*,IRSB*),
                 /*IN*/ Int              offB_TISTART,
                 /*IN*/ Int              offB_TILEN )
{
   Long       delta;
   Int        i, n_instrs, first_stmt_idx;
   Bool       resteerOK, need_to_put_IP, debug_print;
   DisResult  dres;
   IRStmt*    imark;
   static Int n_resteers = 0;
   Int        d_resteers = 0;
   Int        selfcheck_idx = 0;
   IRSB*      irsb;
   Addr64     guest_IP_curr_instr;
   IRConst*   guest_IP_bbstart_IRConst = NULL;

   Bool (*resteerOKfn)(void*,Addr64) = NULL;

   debug_print = toBool(vex_traceflags & VEX_TRACE_FE);

   /* Note: for adler32 to work without % operation for the self
      check, need to limit length of stuff it scans to 5552 bytes.
      Therefore limiting the max bb len to 100 insns seems generously
      conservative. */

   /* check sanity .. */
   vassert(sizeof(HWord) == sizeof(void*));
   vassert(vex_control.guest_max_insns >= 1);
   vassert(vex_control.guest_max_insns < 100);
   vassert(vex_control.guest_chase_thresh >= 0);
   vassert(vex_control.guest_chase_thresh < vex_control.guest_max_insns);
   vassert(guest_word_type == Ity_I32 || guest_word_type == Ity_I64);

   /* Start a new, empty extent. */
   vge->n_used  = 1;
   vge->base[0] = guest_IP_bbstart;
   vge->len[0]  = 0;

   /* And a new IR superblock to dump the result into. */
   irsb = emptyIRSB();

   /* Delta keeps track of how far along the guest_code array we have
      so far gone. */
   delta    = 0;
   n_instrs = 0;

   /* Guest addresses as IRConsts.  Used in the two self-checks
      generated. */
   if (do_self_check) {
      guest_IP_bbstart_IRConst
         = guest_word_type==Ity_I32 
              ? IRConst_U32(toUInt(guest_IP_bbstart))
              : IRConst_U64(guest_IP_bbstart);
   }

   /* If asked to make a self-checking translation, leave 5 spaces
      in which to put the check statements.  We'll fill them in later
      when we know the length and adler32 of the area to check. */
   if (do_self_check) {
      selfcheck_idx = irsb->stmts_used;
      addStmtToIRSB( irsb, IRStmt_NoOp() );
      addStmtToIRSB( irsb, IRStmt_NoOp() );
      addStmtToIRSB( irsb, IRStmt_NoOp() );
      addStmtToIRSB( irsb, IRStmt_NoOp() );
      addStmtToIRSB( irsb, IRStmt_NoOp() );
   }

   /* If the caller supplied a function to add its own preamble, use
      it now. */
   if (preamble_function) {
      Bool stopNow = preamble_function( callback_opaque, irsb );
      if (stopNow) {
         /* The callback has completed the IR block without any guest
            insns being disassembled into it, so just return it at
            this point, even if a self-check was requested - as there
            is nothing to self-check.  The five self-check no-ops will
            still be in place, but they are harmless. */
         return irsb;
      }
   }

   /* Process instructions. */
   while (True) {
      vassert(n_instrs < vex_control.guest_max_insns);

      /* Regardless of what chase_into_ok says, is chasing permissible
         at all right now?  Set resteerOKfn accordingly. */
      resteerOK 
         = toBool(
              n_instrs < vex_control.guest_chase_thresh
              /* If making self-checking translations, don't chase
                 .. it makes the checks too complicated.  We only want
                 to scan just one sequence of bytes in the check, not
                 a whole bunch. */
              && !do_self_check
              /* we can't afford to have a resteer once we're on the
                 last extent slot. */
              && vge->n_used < 3
           );

      resteerOKfn
         = resteerOK ? chase_into_ok : const_False;

      /* This is the IP of the instruction we're just about to deal
         with. */
      guest_IP_curr_instr = guest_IP_bbstart + delta;

      /* This is the irsb statement array index of the first stmt in
         this insn.  That will always be the instruction-mark
         descriptor. */
      first_stmt_idx = irsb->stmts_used;

      /* Add an instruction-mark statement.  We won't know until after
         disassembling the instruction how long it instruction is, so
         just put in a zero length and we'll fix it up later. */
      addStmtToIRSB( irsb, IRStmt_IMark( guest_IP_curr_instr, 0 ));

      /* for the first insn, the dispatch loop will have set
         %IP, but for all the others we have to do it ourselves. */
      need_to_put_IP = toBool(n_instrs > 0);

      /* Finally, actually disassemble an instruction. */
      dres = dis_instr_fn ( irsb,
                            need_to_put_IP,
                            resteerOKfn,
                            callback_opaque,
                            guest_code,
                            delta,
                            guest_IP_curr_instr,
                            arch_guest,
                            archinfo_guest,
                            abiinfo_both,
                            host_bigendian );

      /* stay sane ... */
      vassert(dres.whatNext == Dis_StopHere
              || dres.whatNext == Dis_Continue
              || dres.whatNext == Dis_Resteer);
      vassert(dres.len >= 0 && dres.len <= 20);
      if (dres.whatNext != Dis_Resteer)
         vassert(dres.continueAt == 0);

      /* Fill in the insn-mark length field. */
      vassert(first_stmt_idx >= 0 && first_stmt_idx < irsb->stmts_used);
      imark = irsb->stmts[first_stmt_idx];
      vassert(imark);
      vassert(imark->tag == Ist_IMark);
      vassert(imark->Ist.IMark.len == 0);
      imark->Ist.IMark.len = toUInt(dres.len);

      /* Print the resulting IR, if needed. */
      if (vex_traceflags & VEX_TRACE_FE) {
         for (i = first_stmt_idx; i < irsb->stmts_used; i++) {
            vex_printf("              ");
            ppIRStmt(irsb->stmts[i]);
            vex_printf("\n");
         }
      }

      /* If dis_instr_fn terminated the BB at this point, check it
	 also filled in the irsb->next field. */
      if (dres.whatNext == Dis_StopHere) {
         vassert(irsb->next != NULL);
         if (debug_print) {
            vex_printf("              ");
            vex_printf( "goto {");
            ppIRJumpKind(irsb->jumpkind);
            vex_printf( "} ");
            ppIRExpr( irsb->next );
            vex_printf( "\n");
         }
      }

      /* Update the VexGuestExtents we are constructing. */
      /* If vex_control.guest_max_insns is required to be < 100 and
	 each insn is at max 20 bytes long, this limit of 5000 then
	 seems reasonable since the max possible extent length will be
	 100 * 20 == 2000. */
      vassert(vge->len[vge->n_used-1] < 5000);
      vge->len[vge->n_used-1] 
         = toUShort(toUInt( vge->len[vge->n_used-1] + dres.len ));
      n_instrs++;
      if (debug_print) 
         vex_printf("\n");

      /* Advance delta (inconspicuous but very important :-) */
      delta += (Long)dres.len;

      switch (dres.whatNext) {
         case Dis_Continue:
            vassert(irsb->next == NULL);
            if (n_instrs < vex_control.guest_max_insns) {
               /* keep going */
            } else {
               /* We have to stop. */
               irsb->next 
                  = IRExpr_Const(
                       guest_word_type == Ity_I32
                          ? IRConst_U32(toUInt(guest_IP_bbstart+delta))
                          : IRConst_U64(guest_IP_bbstart+delta)
                    );
               goto done;
            }
            break;
         case Dis_StopHere:
            vassert(irsb->next != NULL);
            goto done;
         case Dis_Resteer:
            /* Check that we actually allowed a resteer .. */
            vassert(resteerOK);
            vassert(irsb->next == NULL);
            /* figure out a new delta to continue at. */
            vassert(resteerOKfn(callback_opaque,dres.continueAt));
            delta = dres.continueAt - guest_IP_bbstart;
            /* we now have to start a new extent slot. */
            vge->n_used++;
            vassert(vge->n_used <= 3);
            vge->base[vge->n_used-1] = dres.continueAt;
            vge->len[vge->n_used-1] = 0;
            n_resteers++;
            d_resteers++;
            if (0 && (n_resteers & 0xFF) == 0)
            vex_printf("resteer[%d,%d] to 0x%llx (delta = %lld)\n",
                       n_resteers, d_resteers,
                       dres.continueAt, delta);
            break;
         default:
            vpanic("bb_to_IR");
      }
   }
   /*NOTREACHED*/
   vassert(0);

  done:
   /* We're done.  The only thing that might need attending to is that
      a self-checking preamble may need to be created. */
   if (do_self_check) {

      UInt     len2check, adler32;
      IRTemp   tistart_tmp, tilen_tmp;
      HWord    p_adler_helper;

      vassert(vge->n_used == 1);
      len2check = vge->len[0];
      if (len2check == 0) 
         len2check = 1;

     adler32 = genericg_compute_adler32( (HWord)guest_code, len2check );

     /* Set TISTART and TILEN.  These will describe to the despatcher
        the area of guest code to invalidate should we exit with a
        self-check failure. */

     tistart_tmp = newIRTemp(irsb->tyenv, guest_word_type);
     tilen_tmp   = newIRTemp(irsb->tyenv, guest_word_type);

     irsb->stmts[selfcheck_idx+0]
        = IRStmt_WrTmp(tistart_tmp, IRExpr_Const(guest_IP_bbstart_IRConst) );

     irsb->stmts[selfcheck_idx+1]
        = IRStmt_WrTmp(tilen_tmp,
                       guest_word_type==Ity_I32 
                          ? IRExpr_Const(IRConst_U32(len2check)) 
                          : IRExpr_Const(IRConst_U64(len2check))
          );

     irsb->stmts[selfcheck_idx+2]
        = IRStmt_Put( offB_TISTART, IRExpr_RdTmp(tistart_tmp) );

     irsb->stmts[selfcheck_idx+3]
        = IRStmt_Put( offB_TILEN, IRExpr_RdTmp(tilen_tmp) );

     p_adler_helper = abiinfo_both->host_ppc_calls_use_fndescrs
                      ? ((HWord*)(&genericg_compute_adler32))[0]
                      : (HWord)&genericg_compute_adler32;

     irsb->stmts[selfcheck_idx+4]
        = IRStmt_Exit( 
             IRExpr_Binop( 
                Iop_CmpNE32, 
                mkIRExprCCall( 
                   Ity_I32, 
                   2/*regparms*/, 
                   "genericg_compute_adler32",
                   (void*)p_adler_helper,
                   mkIRExprVec_2( 
                      mkIRExpr_HWord( (HWord)guest_code ), 
                      mkIRExpr_HWord( (HWord)len2check )
                   )
                ),
                IRExpr_Const(IRConst_U32(adler32))
             ),
             Ijk_TInval,
             guest_IP_bbstart_IRConst
          );
   }

   return irsb;
}