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

📄 isel.c

📁 unix下调试内存泄露的工具源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/*---------------------------------------------------------------*//*---                                                         ---*//*--- This file (host-x86/isel.c) is                          ---*//*--- Copyright (C) OpenWorks LLP.  All rights reserved.      ---*//*---                                                         ---*//*---------------------------------------------------------------*//*   This file is part of LibVEX, a library for dynamic binary   instrumentation and translation.   Copyright (C) 2004-2005 OpenWorks LLP.  All rights reserved.   This library is made available under a dual licensing scheme.   If you link LibVEX against other code all of which is itself   licensed under the GNU General Public License, version 2 dated June   1991 ("GPL v2"), then you may use LibVEX under the terms of the GPL   v2, as appearing in the file LICENSE.GPL.  If the file LICENSE.GPL   is missing, you can obtain a copy of the GPL v2 from the Free   Software Foundation Inc., 51 Franklin St, Fifth Floor, Boston, MA   02110-1301, USA.   For any other uses of LibVEX, you must first obtain a commercial   license from OpenWorks LLP.  Please contact info@open-works.co.uk   for information about commercial licensing.   This software is provided by OpenWorks LLP "as is" and any express   or implied warranties, including, but not limited to, the implied   warranties of merchantability and fitness for a particular purpose   are disclaimed.  In no event shall OpenWorks LLP be liable for any   direct, indirect, incidental, special, exemplary, or consequential   damages (including, but not limited to, procurement of substitute   goods or services; loss of use, data, or profits; or business   interruption) however caused and on any theory of liability,   whether in contract, strict liability, or tort (including   negligence or otherwise) arising in any way out of the use of this   software, even if advised of the possibility of such damage.   Neither the names of the U.S. Department of Energy nor the   University of California nor the names of its contributors may be   used to endorse or promote products derived from this software   without prior written permission.*/#include "libvex_basictypes.h"#include "libvex_ir.h"#include "libvex.h"#include "main/vex_util.h"#include "main/vex_globals.h"#include "host-generic/h_generic_regs.h"#include "host-arm/hdefs.h"/*---------------------------------------------------------*//*--- ISelEnv                                           ---*//*---------------------------------------------------------*//* This carries around:   - A mapping from IRTemp to IRType, giving the type of any IRTemp we     might encounter.  This is computed before insn selection starts,     and does not change.   - A mapping from IRTemp to HReg.  This tells the insn selector     which virtual register(s) are associated with each IRTemp     temporary.  This is computed before insn selection starts, and     does not change.  We expect this mapping to map precisely the     same set of IRTemps as the type mapping does.        - vregmap   holds the primary register for the IRTemp.   - The code array, that is, the insns selected so far.   - A counter, for generating new virtual registers.   Note, this is all host-independent.  */typedef   struct {      IRTypeEnv*   type_env;      HReg*        vregmap;      Int          n_vregmap;      HInstrArray* code;      Int          vreg_ctr;   }   ISelEnv;static HReg lookupIRTemp ( ISelEnv* env, IRTemp tmp ){   vassert(tmp >= 0);   vassert(tmp < env->n_vregmap);   return env->vregmap[tmp];}static void addInstr ( ISelEnv* env, ARMInstr* instr ){   addHInstr(env->code, instr);   if (vex_traceflags & VEX_TRACE_VCODE) {      ppARMInstr(instr);      vex_printf("\n");   }}static HReg newVRegI ( ISelEnv* env ){   HReg reg = mkHReg(env->vreg_ctr, HRcInt32, True/*virtual reg*/);   env->vreg_ctr++;   return reg;}/*---------------------------------------------------------*//*--- ISEL: Forward declarations                        ---*//*---------------------------------------------------------*//* These are organised as iselXXX and iselXXX_wrk pairs.  The   iselXXX_wrk do the real work, but are not to be called directly.   For each XXX, iselXXX calls its iselXXX_wrk counterpart, then   checks that all returned registers are virtual.  You should not   call the _wrk version directly.*/static ARMAMode1*     iselIntExpr_AMode1_wrk ( ISelEnv* env, IRExpr* e );static ARMAMode1*     iselIntExpr_AMode1     ( ISelEnv* env, IRExpr* e );static ARMAMode2*     iselIntExpr_AMode2_wrk ( ISelEnv* env, IRExpr* e );static ARMAMode2*     iselIntExpr_AMode2     ( ISelEnv* env, IRExpr* e );static ARMAMode3*     iselIntExpr_AMode3_wrk ( ISelEnv* env, IRExpr* e );static ARMAMode3*     iselIntExpr_AMode3     ( ISelEnv* env, IRExpr* e );static ARMBranchDest* iselIntExpr_BD_wrk ( ISelEnv* env, IRExpr* e );static ARMBranchDest* iselIntExpr_BD     ( ISelEnv* env, IRExpr* e );static ARMCondCode    iselCondCode_wrk ( ISelEnv* env, IRExpr* e );static ARMCondCode    iselCondCode     ( ISelEnv* env, IRExpr* e );static HReg           iselIntExpr_R_wrk ( ISelEnv* env, IRExpr* e );static HReg           iselIntExpr_R     ( ISelEnv* env, IRExpr* e );#if 0static void        iselInt64Expr_wrk ( HReg* rHi, HReg* rLo,                                        ISelEnv* env, IRExpr* e );static void        iselInt64Expr     ( HReg* rHi, HReg* rLo,                                        ISelEnv* env, IRExpr* e );#endif/*---------------------------------------------------------*//*--- ISEL: Misc helpers                                ---*//*---------------------------------------------------------*/#if 0/* Is this a 32-bit zero expression? */static Bool isZero32 ( IRExpr* e ){   return e->tag == Iex_Const          && e->Iex.Const.con->tag == Ico_U32          && e->Iex.Const.con->Ico.U32 == 0;}#endif/* Make a int reg-reg move. */static ARMInstr* mk_iMOVsd_RR ( HReg src, HReg dst ){   vassert(hregClass(src) == HRcInt32);   vassert(hregClass(dst) == HRcInt32);   return ARMInstr_DPInstr1(ARMalu_MOV, dst, ARMAMode1_ShlI(src, 0));}#if 0/* Advance/retreat stack pointer by n. */static void add_to_sp ( ISelEnv* env, Int n ){    HReg tmp;    ARMImm12A imm12a;    vassert(n > 0 && n < 256 && (n%4) == 0);    if ( mk_ARMImm12A( (UInt)n, &imm12a ) ) {	addInstr(env, ARMInstr_DPInstr2(ARMalu_ADD,					GET_SP_REG(), GET_SP_REG(),					ARMAMode1_I12A( imm12a )));    } else {        tmp  = newVRegI(env);        addInstr(env, ARMInstr_Literal( tmp, (UInt)n ));	addInstr(env, ARMInstr_DPInstr2(ARMalu_ADD,					GET_SP_REG(), GET_SP_REG(),					ARMAMode1_ShlI( tmp, 0 )));    }    }static void sub_from_sp ( ISelEnv* env, Int n ){    HReg tmp;    ARMImm12A imm12a;    vassert(n > 0 && n < 256 && (n%4) == 0);    if ( mk_ARMImm12A( (UInt)n, &imm12a ) ) {	addInstr(env, ARMInstr_DPInstr2(ARMalu_SUB,					GET_SP_REG(), GET_SP_REG(),					ARMAMode1_I12A( imm12a )));    } else {        tmp  = newVRegI(env);        addInstr(env, ARMInstr_Literal( tmp, (UInt)n ));	addInstr(env, ARMInstr_DPInstr2(ARMalu_SUB,					GET_SP_REG(), GET_SP_REG(),					ARMAMode1_ShlI( tmp, 0 )));    }    }#endif#if 0/* Push an arg onto the host stack, in preparation for a call to a   helper function of some kind.  Returns the number of 32-bit words   pushed. */static Int pushArg ( ISelEnv* env, IRExpr* arg ){    IRType arg_ty = typeOfIRExpr(env->type_env, arg);    if (arg_ty == Ity_I32) {		// CAB: This right?	addInstr(env, ARMInstr_StoreW( GET_SP_REG(), iselIntExpr_AMode2(env, arg) ) );	return 1;    }#if 0    else    if (arg_ty == Ity_I64) {      HReg rHi, rLo;      iselInt64Expr(&rHi, &rLo, env, arg);      addInstr(env, X86Instr_Push(X86RMI_Reg(rHi)));      addInstr(env, X86Instr_Push(X86RMI_Reg(rLo)));      return 2;   }#endif   ppIRExpr(arg);   vpanic("pushArg(arm): can't handle arg of this type");}#endif#if 0/* Complete the call to a helper function, by calling the    helper and clearing the args off the stack. */static void callHelperAndClearArgs ( ISelEnv* env, ARMCondCode cc,                               IRCallee* cee, Int n_arg_ws ){   /* Complication.  Need to decide which reg to use as the fn address      pointer, in a way that doesn't trash regparm-passed      parameters. */   vassert(sizeof(void*) == 4);// CAB: cee->regparms ?//   addInstr(env, X86Instr_Call( cc, (UInt)cee->addr, cee->regparms));   ARMBranchDest* dst = ARMBranchDest_Imm( (UInt)cee->addr );   addInstr(env, ARMInstr_BranchL(cc, dst));   if (n_arg_ws > 0)      add_to_sp(env, 4*n_arg_ws);}#endif#if 0/* Used only in doHelperCall.  See big comment in doHelperCall re   handling of regparm args.  This function figures out whether   evaluation of an expression might require use of a fixed register.   If in doubt return True (safe but suboptimal).  */staticBool mightRequireFixedRegs ( IRExpr* e ){   switch (e->tag) {      case Iex_Tmp: case Iex_Const: case Iex_Get:          return False;      default:         return True;   }}#endif/* Do a complete function call.  guard is a Ity_Bit expression   indicating whether or not the call happens.  If guard==NULL, the   call is unconditional. */staticvoid doHelperCall ( ISelEnv* env,                     Bool passBBP,                     IRExpr* guard, IRCallee* cee, IRExpr** args ){#if 0   ARMCondCode cc;   HReg        argregs[3];   HReg        tmpregs[3];   Bool        danger;   Int         not_done_yet, n_args, n_arg_ws, stack_limit,                i, argreg, argregX;   /* Marshal args for a call, do the call, and clear the stack.      Complexities to consider:      * if passBBP is True, %ebp (the baseblock pointer) is to be        passed as the first arg.      * If the callee claims regparmness of 1, 2 or 3, we must pass the        first 1, 2 or 3 args in registers (EAX, EDX, and ECX        respectively).  To keep things relatively simple, only args of        type I32 may be passed as regparms -- just bomb out if anything        else turns up.  Clearly this depends on the front ends not        trying to pass any other types as regparms.     */   /* 16 Nov 2004: the regparm handling is complicated by the      following problem.      Consider a call two a function with two regparm parameters:      f(e1,e2).  We need to compute e1 into %eax and e2 into %edx.      Suppose code is first generated to compute e1 into %eax.  Then,      code is generated to compute e2 into %edx.  Unfortunately, if      the latter code sequence uses %eax, it will trash the value of      e1 computed by the former sequence.  This could happen if (for      example) e2 itself involved a function call.  In the code below,      args are evaluated right-to-left, not left-to-right, but the      principle and the problem are the same.      One solution is to compute all regparm-bound args into vregs      first, and once they are all done, move them to the relevant      real regs.  This always gives correct code, but it also gives      a bunch of vreg-to-rreg moves which are usually redundant but       are hard for the register allocator to get rid of.      A compromise is to first examine all regparm'd argument       expressions.  If they are all so simple that it is clear       they will be evaluated without use of any fixed registers,      use the old compute-directly-to-fixed-target scheme.  If not,      be safe and use the via-vregs scheme.      Note this requires being able to examine an expression and      determine whether or not evaluation of it might use a fixed      register.  That requires knowledge of how the rest of this      insn selector works.  Currently just the following 3 are       regarded as safe -- hopefully they cover the majority of      arguments in practice: IRExpr_Tmp IRExpr_Const IRExpr_Get.   */   vassert(cee->regparms >= 0 && cee->regparms <= 3);   n_args = n_arg_ws = 0;   while (args[n_args]) n_args++;   not_done_yet = n_args;   if (passBBP)      not_done_yet++;   stack_limit = cee->regparms;   if (cee->regparms > 0 && passBBP) stack_limit--;   /* ------ BEGIN marshall all arguments ------ */   /* Push (R to L) the stack-passed args, [n_args-1 .. stack_limit] */   for (i = n_args-1; i >= stack_limit; i--) {      n_arg_ws += pushArg(env, args[i]);      not_done_yet--;   }   /* args [stack_limit-1 .. 0] and possibly %ebp are to be passed in      registers. */   if (cee->regparms > 0) {      /* ------ BEGIN deal with regparms ------ */      /* deal with regparms, not forgetting %ebp if needed. */      argregs[0] = hregX86_EAX();      argregs[1] = hregX86_EDX();      argregs[2] = hregX86_ECX();      tmpregs[0] = tmpregs[1] = tmpregs[2] = INVALID_HREG;      argreg = cee->regparms;      /* In keeping with big comment above, detect potential danger         and use the via-vregs scheme if needed. */      danger = False;      for (i = stack_limit-1; i >= 0; i--) {         if (mightRequireFixedRegs(args[i])) {            danger = True;            break;         }      }      if (danger) {         /* Move via temporaries */         argregX = argreg;         for (i = stack_limit-1; i >= 0; i--) {            if (0) {               vex_printf("x86 host: register param is complex: ");               ppIRExpr(args[i]);               vex_printf("\n");            }            argreg--;            vassert(argreg >= 0);            vassert(typeOfIRExpr(env->type_env, args[i]) == Ity_I32);            tmpregs[argreg] = iselIntExpr_R(env, args[i]);            not_done_yet--;         }         for (i = stack_limit-1; i >= 0; i--) {            argregX--;            vassert(argregX >= 0);            addInstr( env, mk_iMOVsd_RR( tmpregs[argregX], argregs[argregX] ) );         }      } else {         /* It's safe to compute all regparm args directly into their            target registers. */         for (i = stack_limit-1; i >= 0; i--) {            argreg--;            vassert(argreg >= 0);            vassert(typeOfIRExpr(env->type_env, args[i]) == Ity_I32);            addInstr(env, X86Instr_Alu32R(Xalu_MOV,                                           iselIntExpr_RMI(env, args[i]),                                          argregs[argreg]));            not_done_yet--;         }      }      /* Not forgetting %ebp if needed. */      if (passBBP) {         vassert(argreg == 1);         addInstr(env, mk_iMOVsd_RR( hregX86_EBP(), argregs[0]));         not_done_yet--;      }      /* ------ END deal with regparms ------ */   } else {      /* No regparms.  Heave %ebp on the stack if needed. */      if (passBBP) {         addInstr(env, X86Instr_Push(X86RMI_Reg(hregX86_EBP())));         n_arg_ws++;         not_done_yet--;      }   }   vassert(not_done_yet == 0);   /* ------ END marshall all arguments ------ */   /* Now we can compute the condition.  We can't do it earlier      because the argument computations could trash the condition      codes.  Be a bit clever to handle the common case where the      guard is 1:Bit. */   cc = Xcc_ALWAYS;   if (guard) {      if (guard->tag == Iex_Const           && guard->Iex.Const.con->tag == Ico_U1          && guard->Iex.Const.con->Ico.U1 == True) {         /* unconditional -- do nothing */      } else {         cc = iselCondCode( env, guard );      }   }   /* call the helper, and get the args off the stack afterwards. */   callHelperAndClearArgs( env, cc, cee, n_arg_ws );#endif}// CAB: Do we need to deal with elemSz != 8 ?/* Given a guest-state array descriptor, an index expression and a   bias, generate an ARMAMode holding the relevant guest state   offset. */static

⌨️ 快捷键说明

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