⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 iropt.c

📁 unix下调试内存泄露的工具源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
         break;      case Ist_PutI:         e1 = flatten_Expr(bb, st->Ist.PutI.ix);         e2 = flatten_Expr(bb, st->Ist.PutI.data);         addStmtToIRBB(bb, IRStmt_PutI(st->Ist.PutI.descr,                                       e1,                                       st->Ist.PutI.bias,                                       e2));         break;      case Ist_Tmp:         if (isFlat(st->Ist.Tmp.data)) {            /* optimisation, to reduce the number of tmp-tmp               copies generated */            addStmtToIRBB(bb, st);         } else {            /* general case, always correct */            e1 = flatten_Expr(bb, st->Ist.Tmp.data);            addStmtToIRBB(bb, IRStmt_Tmp(st->Ist.Tmp.tmp, e1));         }         break;      case Ist_Store:         e1 = flatten_Expr(bb, st->Ist.Store.addr);         e2 = flatten_Expr(bb, st->Ist.Store.data);         addStmtToIRBB(bb, IRStmt_Store(st->Ist.Store.end, e1,e2));         break;      case Ist_Dirty:         d = st->Ist.Dirty.details;         d2 = emptyIRDirty();         *d2 = *d;         d2->args = sopyIRExprVec(d2->args);         if (d2->mFx != Ifx_None) {            d2->mAddr = flatten_Expr(bb, d2->mAddr);         } else {            vassert(d2->mAddr == NULL);         }         d2->guard = flatten_Expr(bb, d2->guard);         for (i = 0; d2->args[i]; i++)            d2->args[i] = flatten_Expr(bb, d2->args[i]);         addStmtToIRBB(bb, IRStmt_Dirty(d2));         break;      case Ist_NoOp:      case Ist_MFence:      case Ist_IMark:         addStmtToIRBB(bb, st);         break;      case Ist_AbiHint:         e1 = flatten_Expr(bb, st->Ist.AbiHint.base);         addStmtToIRBB(bb, IRStmt_AbiHint(e1, st->Ist.AbiHint.len));         break;      case Ist_Exit:         e1 = flatten_Expr(bb, st->Ist.Exit.guard);         addStmtToIRBB(bb, IRStmt_Exit(e1, st->Ist.Exit.jk,                                           st->Ist.Exit.dst));         break;      default:         vex_printf("\n");         ppIRStmt(st);          vex_printf("\n");         vpanic("flatten_Stmt");   }}static IRBB* flatten_BB ( IRBB* in ){   Int   i;   IRBB* out;   out = emptyIRBB();   out->tyenv = dopyIRTypeEnv( in->tyenv );   for (i = 0; i < in->stmts_used; i++)      if (in->stmts[i])         flatten_Stmt( out, in->stmts[i] );   out->next     = flatten_Expr( out, in->next );   out->jumpkind = in->jumpkind;   return out;}/*---------------------------------------------------------------*//*--- In-place removal of redundant GETs                      ---*//*---------------------------------------------------------------*//* Scan forwards, building up an environment binding (min offset, max   offset) pairs to values, which will either be temps or constants.   On seeing 't = Get(minoff,maxoff)', look up (minoff,maxoff) in the   env and if it matches, replace the Get with the stored value.  If   there is no match, add a (minoff,maxoff) :-> t binding.   On seeing 'Put (minoff,maxoff) = t or c', first remove in the env   any binding which fully or partially overlaps with (minoff,maxoff).   Then add a new (minoff,maxoff) :-> t or c binding.  *//* Extract the min/max offsets from a guest state array descriptor. */inlinestatic void getArrayBounds ( IRArray* descr, UInt* minoff, UInt* maxoff ){   *minoff = descr->base;   *maxoff = *minoff + descr->nElems*sizeofIRType(descr->elemTy) - 1;   vassert((*minoff & ~0xFFFF) == 0);   vassert((*maxoff & ~0xFFFF) == 0);   vassert(*minoff <= *maxoff);}/* Create keys, of the form ((minoffset << 16) | maxoffset). */static UInt mk_key_GetPut ( Int offset, IRType ty ){   /* offset should fit in 16 bits. */   UInt minoff = offset;   UInt maxoff = minoff + sizeofIRType(ty) - 1;   vassert((minoff & ~0xFFFF) == 0);   vassert((maxoff & ~0xFFFF) == 0);   return (minoff << 16) | maxoff;}static UInt mk_key_GetIPutI ( IRArray* descr ){   UInt minoff, maxoff;   getArrayBounds( descr, &minoff, &maxoff );   vassert((minoff & ~0xFFFF) == 0);   vassert((maxoff & ~0xFFFF) == 0);   return (minoff << 16) | maxoff;}/* Supposing h has keys of the form generated by mk_key_GetPut and   mk_key_GetIPutI, invalidate any key which overlaps (k_lo   .. k_hi). */static void invalidateOverlaps ( HashHW* h, UInt k_lo, UInt k_hi ){   Int  j;   UInt e_lo, e_hi;   vassert(k_lo <= k_hi);   /* invalidate any env entries which in any way overlap (k_lo      .. k_hi) */   /* vex_printf("invalidate %d .. %d\n", k_lo, k_hi ); */   for (j = 0; j < h->used; j++) {      if (!h->inuse[j])          continue;      e_lo = (((UInt)h->key[j]) >> 16) & 0xFFFF;      e_hi = ((UInt)h->key[j]) & 0xFFFF;      vassert(e_lo <= e_hi);      if (e_hi < k_lo || k_hi < e_lo)         continue; /* no overlap possible */      else         /* overlap; invalidate */         h->inuse[j] = False;   }}static void redundant_get_removal_BB ( IRBB* bb ){   HashHW* env = newHHW();   UInt    key = 0; /* keep gcc -O happy */   Int     i, j;   HWord   val;   for (i = 0; i < bb->stmts_used; i++) {      IRStmt* st = bb->stmts[i];      if (st->tag == Ist_NoOp)         continue;      /* Deal with Gets */      if (st->tag == Ist_Tmp          && st->Ist.Tmp.data->tag == Iex_Get) {         /* st is 't = Get(...)'.  Look up in the environment and see            if the Get can be replaced. */         IRExpr* get = st->Ist.Tmp.data;         key = (HWord)mk_key_GetPut( get->Iex.Get.offset,                                      get->Iex.Get.ty );         if (lookupHHW(env, &val, (HWord)key)) {            /* found it */            /* Note, we could do better here.  If the types are               different we don't do the substitution, since doing so               could lead to invalidly-typed IR.  An improvement would               be to stick in a reinterpret-style cast, although that               would make maintaining flatness more difficult. */            IRExpr* valE    = (IRExpr*)val;            Bool    typesOK = toBool( typeOfIRExpr(bb->tyenv,valE)                                       == st->Ist.Tmp.data->Iex.Get.ty );            if (typesOK && DEBUG_IROPT) {               vex_printf("rGET: "); ppIRExpr(get);               vex_printf("  ->  "); ppIRExpr(valE);               vex_printf("\n");            }            if (typesOK)               bb->stmts[i] = IRStmt_Tmp(st->Ist.Tmp.tmp, valE);         } else {            /* Not found, but at least we know that t and the Get(...)               are now associated.  So add a binding to reflect that               fact. */            addToHHW( env, (HWord)key,                            (HWord)(void*)(IRExpr_Tmp(st->Ist.Tmp.tmp)) );         }      }      /* Deal with Puts: invalidate any env entries overlapped by this         Put */      if (st->tag == Ist_Put || st->tag == Ist_PutI) {         UInt k_lo, k_hi;         if (st->tag == Ist_Put) {            key = mk_key_GetPut( st->Ist.Put.offset,                                  typeOfIRExpr(bb->tyenv,st->Ist.Put.data) );         } else {            vassert(st->tag == Ist_PutI);            key = mk_key_GetIPutI( st->Ist.PutI.descr );         }         k_lo = (key >> 16) & 0xFFFF;         k_hi = key & 0xFFFF;         invalidateOverlaps(env, k_lo, k_hi);      }      else      if (st->tag == Ist_Dirty) {         /* Deal with dirty helpers which write or modify guest state.            Invalidate the entire env.  We could do a lot better            here. */         IRDirty* d      = st->Ist.Dirty.details;         Bool     writes = False;         for (j = 0; j < d->nFxState; j++) {            if (d->fxState[j].fx == Ifx_Modify                 || d->fxState[j].fx == Ifx_Write)            writes = True;         }         if (writes) {            /* dump the entire env (not clever, but correct ...) */            for (j = 0; j < env->used; j++)               env->inuse[j] = False;            if (0) vex_printf("rGET: trash env due to dirty helper\n");         }      }      /* add this one to the env, if appropriate */      if (st->tag == Ist_Put) {         vassert(isIRAtom(st->Ist.Put.data));         addToHHW( env, (HWord)key, (HWord)(st->Ist.Put.data));      }   } /* for (i = 0; i < bb->stmts_used; i++) */}/*---------------------------------------------------------------*//*--- In-place removal of redundant PUTs                      ---*//*---------------------------------------------------------------*//* Find any Get uses in st and invalidate any partially or fully   overlapping ranges listed in env.  Due to the flattening phase, the   only stmt kind we expect to find a Get on is IRStmt_Tmp. */static void handle_gets_Stmt (                HashHW* env,                IRStmt* st,               Bool (*preciseMemExnsFn)(Int,Int)            ){   Int     j;   UInt    key = 0; /* keep gcc -O happy */   Bool    isGet;   Bool    memRW = False;   IRExpr* e;   switch (st->tag) {      /* This is the only interesting case.  Deal with Gets in the RHS         expression. */      case Ist_Tmp:         e = st->Ist.Tmp.data;         switch (e->tag) {            case Iex_Get:               isGet = True;               key = mk_key_GetPut ( e->Iex.Get.offset, e->Iex.Get.ty );               break;            case Iex_GetI:               isGet = True;               key = mk_key_GetIPutI ( e->Iex.GetI.descr );               break;            case Iex_Load:               isGet = False;               memRW = True;               break;            default:                isGet = False;         }         if (isGet) {            UInt k_lo, k_hi;            k_lo = (key >> 16) & 0xFFFF;            k_hi = key & 0xFFFF;            invalidateOverlaps(env, k_lo, k_hi);         }         break;      /* Be very conservative for dirty helper calls; dump the entire         environment.  The helper might read guest state, in which         case it needs to be flushed first.  Also, the helper might         access guest memory, in which case all parts of the guest         state requiring precise exceptions needs to be flushed.  The         crude solution is just to flush everything; we could easily         enough do a lot better if needed. */      /* Probably also overly-conservative, but also dump everything         if we hit a memory fence.  Ditto AbiHints.*/      case Ist_AbiHint:         vassert(isIRAtom(st->Ist.AbiHint.base));         /* fall through */      case Ist_MFence:      case Ist_Dirty:         for (j = 0; j < env->used; j++)            env->inuse[j] = False;         break;      /* all other cases are boring. */      case Ist_Store:         vassert(isIRAtom(st->Ist.Store.addr));         vassert(isIRAtom(st->Ist.Store.data));         memRW = True;         break;      case Ist_Exit:         vassert(isIRAtom(st->Ist.Exit.guard));         break;      case Ist_PutI:         vassert(isIRAtom(st->Ist.PutI.ix));         vassert(isIRAtom(st->Ist.PutI.data));         break;      case Ist_NoOp:      case Ist_IMark:         break;      default:         vex_printf("\n");         ppIRStmt(st);         vex_printf("\n");         vpanic("handle_gets_Stmt");   }   if (memRW) {      /* This statement accesses memory.  So we need to dump all parts         of the environment corresponding to guest state that may not         be reordered with respect to memory references.  That means         at least the stack pointer. */      for (j = 0; j < env->used; j++) {         if (!env->inuse[j])            continue;         if (vex_control.iropt_precise_memory_exns) {            /* Precise exceptions required.  Flush all guest state. */            env->inuse[j] = False;         } else {            /* Just flush the minimal amount required, as computed by               preciseMemExnsFn. */            HWord k_lo = (env->key[j] >> 16) & 0xFFFF;            HWord k_hi = env->key[j] & 0xFFFF;            if (preciseMemExnsFn( k_lo, k_hi ))               env->inuse[j] = False;         }      }   } /* if (memRW) */}/* Scan backwards, building up a set of (min offset, max   offset) pairs, indicating those parts of the guest state   for which the next event is a write.   On seeing a conditional exit, empty the set.   On seeing 'Put (minoff,maxoff) = t or c', if (minoff,maxoff) is   completely within the set, remove the Put.  Otherwise, add   (minoff,maxoff) to the set.   On seeing 'Get (minoff,maxoff)', remove any part of the set   overlapping (minoff,maxoff).  The same has to happen for any events   which implicitly read parts of the guest state: dirty helper calls   and loads/stores.*/

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -