]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Add a field 'UChar delta' to IRStmt_IMark, and use it to carry around
authorJulian Seward <jseward@acm.org>
Fri, 27 May 2011 13:20:56 +0000 (13:20 +0000)
committerJulian Seward <jseward@acm.org>
Fri, 27 May 2011 13:20:56 +0000 (13:20 +0000)
the T bit for the instruction when the instruction is a ARM/Thumb.
This more or less avoids introducing Thumb specific hacks in the IR,
yet makes it possible to identify, from an IMark, whether it refers to
a Thumb or ARM instruction.  This is important for the GDB server
integration to work properly on Thumb code.

Patch from bug 214909 comment 99 (vex part).
(Philippe Waroquiers, philippe.waroquiers@skynet.be)

git-svn-id: svn://svn.valgrind.org/vex/trunk@2153

VEX/priv/guest_generic_bb_to_IR.c
VEX/priv/ir_defs.c
VEX/priv/ir_opt.c
VEX/pub/libvex_ir.h

index 1e59c70e0d1d978b91aaf8f1cd1d2b6bc62c104d..4ce4e781cac3fd83bb41b328b4605f147d7971fc 100644 (file)
@@ -267,15 +267,30 @@ IRSB* bb_to_IR ( /*OUT*/VexGuestExtents* vge,
          distinguishes ARM vs Thumb instructions.  All instructions
          actually start on at least 2-aligned addresses.  So we need
          to ignore the bottom bit of the insn address when forming the
-         IMark.  For more details of this convention, see comments on
-         definition of guest_R15 in libvex_guest_arm.h. */
-      addStmtToIRSB( irsb,
-                     IRStmt_IMark( arch_guest == VexArchARM
-                                      ? (guest_IP_curr_instr & ~(Addr64)1)
-                                      : guest_IP_curr_instr,
-                                   0
-                     )
-      );
+         IMark's address field, but put that bottom bit in the delta
+         field, so that comparisons against guest_R15T for Thumb can
+         be done correctly.  By inspecting the delta field,
+         instruction processors can determine whether the instruction
+         was originally Thumb or ARM.  For more details of this
+         convention, see comments on definition of guest_R15T in
+         libvex_guest_arm.h. */
+      if (arch_guest == VexArchARM && (guest_IP_curr_instr & (Addr64)1)) {
+         /* Thumb insn => mask out the T bit, but put it in delta */
+         addStmtToIRSB( irsb,
+                        IRStmt_IMark(guest_IP_curr_instr & ~(Addr64)1,
+                                     0, /* len */
+                                     1  /* delta */
+                        )
+         );
+      } else {
+         /* All other targets: store IP as-is, and set delta to zero. */
+         addStmtToIRSB( irsb,
+                        IRStmt_IMark(guest_IP_curr_instr,
+                                     0, /* len */
+                                     0  /* delta */
+                        )
+         );
+      }
 
       /* for the first insn, the dispatch loop will have set
          %IP, but for all the others we have to do it ourselves. */
index ad12dec95c7500163223bb35ee333530774beb35..566187ad34a40d51b3aa460807e516535d20e433 100644 (file)
@@ -1148,8 +1148,9 @@ void ppIRStmt ( IRStmt* s )
          vex_printf("IR-NoOp");
          break;
       case Ist_IMark:
-         vex_printf( "------ IMark(0x%llx, %d) ------", 
-                     s->Ist.IMark.addr, s->Ist.IMark.len);
+         vex_printf( "------ IMark(0x%llx, %d, %u) ------", 
+                     s->Ist.IMark.addr, s->Ist.IMark.len,
+                     (UInt)s->Ist.IMark.delta);
          break;
       case Ist_AbiHint:
          vex_printf("====== AbiHint(");
@@ -1604,11 +1605,12 @@ IRStmt* IRStmt_NoOp ( void )
    static_closure.tag = Ist_NoOp;
    return &static_closure;
 }
-IRStmt* IRStmt_IMark ( Addr64 addr, Int len ) {
-   IRStmt* s         = LibVEX_Alloc(sizeof(IRStmt));
-   s->tag            = Ist_IMark;
-   s->Ist.IMark.addr = addr;
-   s->Ist.IMark.len  = len;
+IRStmt* IRStmt_IMark ( Addr64 addr, Int len, UChar delta ) {
+   IRStmt* s          = LibVEX_Alloc(sizeof(IRStmt));
+   s->tag             = Ist_IMark;
+   s->Ist.IMark.addr  = addr;
+   s->Ist.IMark.len   = len;
+   s->Ist.IMark.delta = delta;
    return s;
 }
 IRStmt* IRStmt_AbiHint ( IRExpr* base, Int len, IRExpr* nia ) {
@@ -1871,7 +1873,9 @@ IRStmt* deepCopyIRStmt ( IRStmt* s )
                                s->Ist.AbiHint.len,
                                deepCopyIRExpr(s->Ist.AbiHint.nia));
       case Ist_IMark:
-         return IRStmt_IMark(s->Ist.IMark.addr, s->Ist.IMark.len);
+         return IRStmt_IMark(s->Ist.IMark.addr,
+                             s->Ist.IMark.len,
+                             s->Ist.IMark.delta);
       case Ist_Put: 
          return IRStmt_Put(s->Ist.Put.offset, 
                            deepCopyIRExpr(s->Ist.Put.data));
@@ -3214,9 +3218,11 @@ void tcStmt ( IRSB* bb, IRStmt* stmt, IRType gWordTy )
    switch (stmt->tag) {
       case Ist_IMark:
          /* Somewhat heuristic, but rule out totally implausible
-            instruction sizes. */
+            instruction sizes and deltas. */
          if (stmt->Ist.IMark.len < 0 || stmt->Ist.IMark.len > 20)
             sanityCheckFail(bb,stmt,"IRStmt.IMark.len: implausible");
+         if (stmt->Ist.IMark.delta > 1)
+            sanityCheckFail(bb,stmt,"IRStmt.IMark.delta: implausible");
          break;
       case Ist_AbiHint:
          if (typeOfIRExpr(tyenv, stmt->Ist.AbiHint.base) != gWordTy)
index 5cf91dc456303a91a733980291c7899342b00396..b7746458a34272c37737690f7ab734db81ec4655 100644 (file)
@@ -1997,7 +1997,9 @@ static IRStmt* subst_and_fold_Stmt ( IRExpr** env, IRStmt* st )
       }
 
       case Ist_IMark:
-         return IRStmt_IMark(st->Ist.IMark.addr, st->Ist.IMark.len);
+         return IRStmt_IMark(st->Ist.IMark.addr,
+                             st->Ist.IMark.len,
+                             st->Ist.IMark.delta);
 
       case Ist_NoOp:
          return IRStmt_NoOp();
@@ -4269,7 +4271,9 @@ static IRStmt* atbSubst_Stmt ( ATmpInfo* env, IRStmt* st )
                    st->Ist.Exit.dst
                 );
       case Ist_IMark:
-         return IRStmt_IMark(st->Ist.IMark.addr, st->Ist.IMark.len);
+         return IRStmt_IMark(st->Ist.IMark.addr,
+                             st->Ist.IMark.len,
+                             st->Ist.IMark.delta);
       case Ist_NoOp:
          return IRStmt_NoOp();
       case Ist_MBE:
index 2ec39acf7fb8d1c24870050f807b3b20679ae1a6..1479cd73827b6de2adcc331529e99441529c37f6 100644 (file)
 
    One Vex IR translation for this code would be this:
 
-     ------ IMark(0x24F275, 7) ------
+     ------ IMark(0x24F275, 7, 0) ------
      t3 = GET:I32(0)             # get %eax, a 32-bit integer
      t2 = GET:I32(12)            # get %ebx, a 32-bit integer
      t1 = Add32(t3,t2)           # addl
    This becomes (again ignoring condition code and instruction pointer
    updates):
 
-     ------ IMark(0x4000ABA, 3) ------
+     ------ IMark(0x4000ABA, 3, 0) ------
      t3 = Add32(GET:I32(0),0x4:I32)
      t2 = LDle:I32(t3)
      t1 = GET:I32(8)
@@ -1894,12 +1894,27 @@ typedef
             the IRSB).  Contains the address and length of the
             instruction.
 
-            ppIRStmt output: ------ IMark(<addr>, <len>) ------,
-                         eg. ------ IMark(0x4000792, 5) ------,
+            It also contains a delta value.  The delta must be
+            subtracted from a guest program counter value before
+            attempting to establish, by comparison with the address
+            and length values, whether or not that program counter
+            value refers to this instruction.  For x86, amd64, ppc32,
+            ppc64 and arm, the delta value is zero.  For Thumb
+            instructions, the delta value is one.  This is because, on
+            Thumb, guest PC values (guest_R15T) are encoded using the
+            top 31 bits of the instruction address and a 1 in the lsb;
+            hence they appear to be (numerically) 1 past the start of
+            the instruction they refer to.  IOW, guest_R15T on ARM
+            holds a standard ARM interworking address.
+
+            ppIRStmt output: ------ IMark(<addr>, <len>, <delta>) ------,
+                         eg. ------ IMark(0x4000792, 5, 0) ------,
          */
          struct {
             Addr64 addr;   /* instruction address */
             Int    len;    /* instruction length */
+            UChar  delta;  /* addr = program counter as encoded in guest state
+                                     - delta */
          } IMark;
 
          /* META: An ABI hint, which says something about this
@@ -2076,7 +2091,7 @@ typedef
 
 /* Statement constructors. */
 extern IRStmt* IRStmt_NoOp    ( void );
-extern IRStmt* IRStmt_IMark   ( Addr64 addr, Int len );
+extern IRStmt* IRStmt_IMark   ( Addr64 addr, Int len, UChar delta );
 extern IRStmt* IRStmt_AbiHint ( IRExpr* base, Int len, IRExpr* nia );
 extern IRStmt* IRStmt_Put     ( Int off, IRExpr* data );
 extern IRStmt* IRStmt_PutI    ( IRRegArray* descr, IRExpr* ix, Int bias,