📄 toir.c
字号:
/*--------------------------------------------------------------------*//*--- ---*//*--- This file (guest-arm/toIR.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.*//* Translates ARM(v4) code to IR. */#include "libvex_basictypes.h"#include "libvex_ir.h"#include "libvex.h"#include "libvex_guest_arm.h"#include "main/vex_util.h"#include "main/vex_globals.h"#include "guest-arm/gdefs.h"/*------------------------------------------------------------*//*--- Globals ---*//*------------------------------------------------------------*//* These are set at the start of the translation of a BB, so that we don't have to pass them around endlessly. CONST means does not change during translation of a bb. *//* We need to know this to do sub-register accesses correctly. *//* CONST */static Bool host_is_bigendian;/* Pointer to the guest code area. *//* CONST */static UChar* guest_code;/* The guest address corresponding to guest_code[0]. *//* CONST */static Addr32 guest_pc_bbstart;/* The IRBB* into which we're generating code. */static IRBB* irbb;/*------------------------------------------------------------*//*--- Debugging output ---*//*------------------------------------------------------------*/#define DIP(format, args...) \ if (vex_traceflags & VEX_TRACE_FE) \ vex_printf(format, ## args)#define DIS(buf, format, args...) \ if (vex_traceflags & VEX_TRACE_FE) \ vex_sprintf(buf, format, ## args)/*------------------------------------------------------------*//*--- Offsets of various parts of the arm guest state. ---*//*------------------------------------------------------------*/#define OFFB_R0 offsetof(VexGuestARMState,guest_R0)#define OFFB_R1 offsetof(VexGuestARMState,guest_R1)#define OFFB_R2 offsetof(VexGuestARMState,guest_R2)#define OFFB_R3 offsetof(VexGuestARMState,guest_R3)#define OFFB_R4 offsetof(VexGuestARMState,guest_R4)#define OFFB_R5 offsetof(VexGuestARMState,guest_R5)#define OFFB_R6 offsetof(VexGuestARMState,guest_R6)#define OFFB_R7 offsetof(VexGuestARMState,guest_R7)#define OFFB_R8 offsetof(VexGuestARMState,guest_R8)#define OFFB_R9 offsetof(VexGuestARMState,guest_R9)#define OFFB_R10 offsetof(VexGuestARMState,guest_R10)#define OFFB_R11 offsetof(VexGuestARMState,guest_R11)#define OFFB_R12 offsetof(VexGuestARMState,guest_R12)#define OFFB_R13 offsetof(VexGuestARMState,guest_R13)#define OFFB_R14 offsetof(VexGuestARMState,guest_R14)#define OFFB_R15 offsetof(VexGuestARMState,guest_R15)// CAB: ? guest_SYSCALLNO;#define OFFB_CC_OP offsetof(VexGuestARMState,guest_CC_OP)#define OFFB_CC_DEP1 offsetof(VexGuestARMState,guest_CC_DEP1)#define OFFB_CC_DEP2 offsetof(VexGuestARMState,guest_CC_DEP2)// CAB: ? guest_EMWARN;/*------------------------------------------------------------*//*--- Disassemble an entire basic block ---*//*------------------------------------------------------------*//* The results of disassembling an instruction. There are three possible outcomes. For Dis_Resteer, the disassembler _must_ continue at the specified address. For Dis_StopHere, the disassembler _must_ terminate the BB. For Dis_Continue, we may at our option either disassemble the next insn, or terminate the BB; but in the latter case we must set the bb's ->next field to point to the next instruction. */typedef enum { Dis_StopHere, /* this insn terminates the BB; we must stop. */ Dis_Continue, /* we can optionally continue into the next insn */ Dis_Resteer /* followed a branch; continue at the spec'd addr */ } DisResult;/* forward decls .. */static IRExpr* mkU32 ( UInt i );static void stmt ( IRStmt* st );/* disInstr disassembles an instruction located at &guest_code[delta], and sets *size to its size. If the returned value is Dis_Resteer, the next guest address is assigned to *whereNext. disInstr is not permitted to return Dis_Resteer if either (1) resteerOK is False, or (2) resteerOkFn, when applied to the address which it wishes to resteer into, returns False. */ static DisResult disInstr ( /*IN*/ Bool resteerOK, /*IN*/ Bool (*resteerOkFn) ( Addr64 ), /*IN*/ Long delta, /*OUT*/ Int* size, /*OUT*/ Addr64* whereNext );/* This is the main (only, in fact) entry point for this module. *//* Disassemble a complete basic block, starting at guest_pc_start, and dumping the IR into global irbb. Returns the size, in bytes, of the basic block. */IRBB* bbToIR_ARM ( UChar* armCode, Addr64 guest_pc_start, VexGuestExtents* vge, Bool (*byte_accessible)(Addr64), Bool (*chase_into_ok)(Addr64), Bool host_bigendian, VexArchInfo* archinfo_guest ){ Long delta; Int i, n_instrs, size, first_stmt_idx; Addr64 guest_next; Bool resteerOK; DisResult dres; static Int n_resteers = 0; Int d_resteers = 0; /* check sanity .. */ vassert(vex_control.guest_max_insns >= 1); vassert(vex_control.guest_max_insns < 500); vassert(vex_control.guest_chase_thresh >= 0); vassert(vex_control.guest_chase_thresh < vex_control.guest_max_insns); vassert(archinfo_guest->subarch == VexSubArchARM_v4); /* Start a new, empty extent. */ vge->n_used = 1; vge->base[0] = guest_pc_start; vge->len[0] = 0; /* Set up globals. */ host_is_bigendian = host_bigendian; guest_code = armCode; guest_pc_bbstart = (Addr32)guest_pc_start; irbb = emptyIRBB(); vassert((guest_pc_start >> 32) == 0); /* Delta keeps track of how far along the armCode array we have so far gone. */ delta = 0; n_instrs = 0; while (True) { vassert(n_instrs < vex_control.guest_max_insns); guest_next = 0; resteerOK = toBool(n_instrs < vex_control.guest_chase_thresh); first_stmt_idx = irbb->stmts_used; if (n_instrs > 0) { /* for the first insn, the dispatch loop will have set R15, but for all the others we have to do it ourselves. */ stmt( IRStmt_Put( OFFB_R15, mkU32(toUInt(guest_pc_bbstart + delta))) ); } dres = disInstr( resteerOK, chase_into_ok, delta, &size, &guest_next ); /* Print the resulting IR, if needed. */ if (vex_traceflags & VEX_TRACE_FE) { for (i = first_stmt_idx; i < irbb->stmts_used; i++) { vex_printf(" "); ppIRStmt(irbb->stmts[i]); vex_printf("\n"); } } if (dres == Dis_StopHere) { vassert(irbb->next != NULL); if (vex_traceflags & VEX_TRACE_FE) { vex_printf(" "); vex_printf( "goto {"); ppIRJumpKind(irbb->jumpkind); vex_printf( "} "); ppIRExpr( irbb->next ); vex_printf( "\n"); } } delta += size; vge->len[vge->n_used-1] = toUShort(vge->len[vge->n_used-1] + size); n_instrs++; DIP("\n"); vassert(size > 0 && size <= 18); if (!resteerOK) vassert(dres != Dis_Resteer); if (dres != Dis_Resteer) vassert(guest_next == 0); switch (dres) { case Dis_Continue: vassert(irbb->next == NULL); if (n_instrs < vex_control.guest_max_insns) { /* keep going */ } else { irbb->next = mkU32(toUInt(guest_pc_start+delta)); return irbb; } break; case Dis_StopHere: vassert(irbb->next != NULL); return irbb; case Dis_Resteer: vpanic("bbToIR_ARM: Dis_Resteer: fixme"); /* need to add code here to start a new extent ... */ vassert(irbb->next == NULL); /* figure out a new delta to continue at. */ vassert(chase_into_ok(guest_next)); delta = guest_next - guest_pc_start; n_resteers++; d_resteers++; if (0 && (n_resteers & 0xFF) == 0) vex_printf("resteer[%d,%d] to %p (delta = %lld)\n", n_resteers, d_resteers, ULong_to_Ptr(guest_next), delta); break; } }}/*------------------------------------------------------------*//*--- Helper bits and pieces for deconstructing the ---*//*--- ARM insn stream. ---*//*------------------------------------------------------------*//* Add a statement to the list held by "irbb". */static void stmt ( IRStmt* st ){ addStmtToIRBB( irbb, st );}/* Generate a new temporary of the given type. */static IRTemp newTemp ( IRType ty ){ vassert(isPlausibleIRType(ty)); return newIRTemp( irbb->tyenv, ty );}#if 0/* Bomb out if we can't handle something. */__attribute__ ((noreturn))static void unimplemented ( Char* str ){ vex_printf("armToIR: unimplemented feature\n"); vpanic(str);}#endif/* Various simple conversions */#if 0static UInt extend_s_8to32( UInt x ){ return (UInt)((((Int)x) << 24) >> 24);}static UInt extend_s_16to32 ( UInt x ){ return (UInt)((((Int)x) << 16) >> 16);}#endifstatic UInt extend_s_24to32 ( UInt x ){ return (UInt)((((Int)x) << 8) >> 8);}#if 0/* Fetch a byte from the guest insn stream. */static UChar getIByte ( UInt delta ){ return guest_code[delta];}#endif/* Get a 8/16/32-bit unsigned value out of the insn stream. */#if 0static UInt getUChar ( UInt delta ){ UInt v = guest_code[delta+0]; return v & 0xFF;}#endif#if 0static UInt getUDisp16 ( UInt delta ){ UInt v = guest_code[delta+1]; v <<= 8; v |= guest_code[delta+0]; return v & 0xFFFF;}#endif#if 0static UInt getUDisp32 ( UInt delta ){ UInt v = guest_code[delta+3]; v <<= 8; v |= guest_code[delta+2]; v <<= 8; v |= guest_code[delta+1]; v <<= 8; v |= guest_code[delta+0]; return v;}#endif#if 0static UInt getUDisp ( Int size, UInt delta ){ switch (size) { case 4: return getUDisp32(delta); case 2: return getUDisp16(delta); case 1: return getUChar(delta); default: vpanic("getUDisp(ARM)"); } return 0; /*notreached*/}#endif#if 0/* Get a byte value out of the insn stream and sign-extend to 32 bits. */static UInt getSDisp8 ( UInt delta ){ return extend_s_8to32( (UInt) (guest_code[delta]) );}#endif#if 0static UInt getSDisp16 ( UInt delta0 ){ UChar* eip = (UChar*)(&guest_code[delta0]); UInt d = *eip++; d |= ((*eip++) << 8); return extend_s_16to32(d);}#endif#if 0static UInt getSDisp ( Int size, UInt delta )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -