]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Proper support for translation cache management: when a translation is
authorJulian Seward <jseward@acm.org>
Wed, 19 Jan 2005 11:49:45 +0000 (11:49 +0000)
committerJulian Seward <jseward@acm.org>
Wed, 19 Jan 2005 11:49:45 +0000 (11:49 +0000)
made, record precisely the areas of guest address space from which the
translation was made.  This is needed to be sure we can later discard
translations accurately.  The new info is record in a structure called
VexGuestExtents.

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

VEX/priv/guest-arm/gdefs.h
VEX/priv/guest-arm/toIR.c
VEX/priv/guest-x86/gdefs.h
VEX/priv/guest-x86/toIR.c
VEX/priv/main/vex_main.c
VEX/pub/libvex.h
VEX/test_main.c

index 2d74e908b770b126721915662f231e7574465ac3..7377fcf8279b75e721d739138117f395aa6e1c22 100644 (file)
 /*---------------------------------------------------------*/
 
 extern
-IRBB* bbToIR_ARM ( UChar*     armCode, 
-                   Addr64     eip, 
-                   Int*       guest_bytes_read, 
-                   Bool       (*byte_accessible)(Addr64),
-                   Bool       (*resteerOkFn)(Addr64),
-                   Bool       host_bigendian,
-                   VexSubArch subarch_guest );
+IRBB* bbToIR_ARM ( UChar*           armCode, 
+                   Addr64           eip, 
+                   VexGuestExtents* vge,
+                   Bool             (*byte_accessible)(Addr64),
+                   Bool             (*resteerOkFn)(Addr64),
+                   Bool             host_bigendian,
+                   VexSubArch       subarch_guest );
 
 /* Used by the optimiser to specialise calls to helpers. */
 extern
index e48361f844bd0bb750dbfee98c72dbd1caf1a7d6..f107fd4ba32ef22fed9121d0a385f828d2c66416 100644 (file)
@@ -161,13 +161,13 @@ static DisResult disInstr ( /*IN*/  Bool    resteerOK,
    dumping the IR into global irbb.  Returns the size, in bytes, of
    the basic block.  
 */
-IRBB* bbToIR_ARM ( UChar*     armCode, 
-                   Addr64     guest_pc_start, 
-                   Int*       guest_bytes_read, 
-                   Bool       (*byte_accessible)(Addr64),
-                   Bool       (*chase_into_ok)(Addr64),
-                   Bool       host_bigendian,
-                   VexSubArch subarch_guest )
+IRBB* bbToIR_ARM ( UChar*           armCode, 
+                   Addr64           guest_pc_start, 
+                   VexGuestExtents* vge,
+                   Bool             (*byte_accessible)(Addr64),
+                   Bool             (*chase_into_ok)(Addr64),
+                   Bool             host_bigendian,
+                   VexSubArch       subarch_guest )
 {
    UInt       delta;
    Int        i, n_instrs, size, first_stmt_idx;
@@ -179,12 +179,17 @@ IRBB* bbToIR_ARM ( UChar*     armCode,
 
    /* check sanity .. */
    vassert(vex_control.guest_max_insns >= 1);
-   vassert(vex_control.guest_max_insns < 1000);
+   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(subarch_guest == 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;
@@ -197,7 +202,6 @@ IRBB* bbToIR_ARM ( UChar*     armCode,
       have so far gone. */
    delta             = 0;
    n_instrs          = 0;
-   *guest_bytes_read = 0;
 
    while (True) {
       vassert(n_instrs < vex_control.guest_max_insns);
@@ -237,7 +241,7 @@ IRBB* bbToIR_ARM ( UChar*     armCode,
       }
 
       delta += size;
-      *guest_bytes_read += size;
+      vge->len[vge->n_used-1] += size;
       n_instrs++;
       DIP("\n");
 
@@ -261,6 +265,8 @@ IRBB* bbToIR_ARM ( UChar*     armCode,
             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));
@@ -279,7 +285,7 @@ IRBB* bbToIR_ARM ( UChar*     armCode,
 
 /*------------------------------------------------------------*/
 /*--- Helper bits and pieces for deconstructing the        ---*/
-/*--- x86 insn stream.                                     ---*/
+/*--- ARM insn stream.                                     ---*/
 /*------------------------------------------------------------*/
 
 /* Add a statement to the list held by "irbb". */
index 7d3312a669cf2831a77422490a9f0517ad51d529..deb5e61175b9dff92dea12041d6f2849f4d09cf1 100644 (file)
 /*---------------------------------------------------------*/
 
 extern
-IRBB* bbToIR_X86 ( UChar*     x86code, 
-                   Addr64     eip, 
-                   Int*       guest_bytes_read, 
-                   Bool       (*byte_accessible)(Addr64),
-                   Bool       (*resteerOkFn)(Addr64),
-                   Bool       host_bigendian,
-                   VexSubArch subarch_guest );
+IRBB* bbToIR_X86 ( UChar*           x86code, 
+                   Addr64           eip, 
+                   VexGuestExtents* vge,
+                   Bool             (*byte_accessible)(Addr64),
+                   Bool             (*resteerOkFn)(Addr64),
+                   Bool             host_bigendian,
+                   VexSubArch       subarch_guest );
 
 /* Used by the optimiser to specialise calls to helpers. */
 extern
index 004bdf849d4bb4589cccf876bffca596c619c526..0bac7382b389cef556115365eb27c2e8898cdcb7 100644 (file)
@@ -227,13 +227,13 @@ DisResult disInstr ( /*IN*/  Bool       resteerOK,
 /* Disassemble a complete basic block, starting at eip, and dumping
    the ucode into cb.  Returns the size, in bytes, of the basic
    block. */
-IRBB* bbToIR_X86 ( UChar*     x86code, 
-                   Addr64     guest_eip_start, 
-                   Int*       guest_bytes_read
-                   Bool       (*byte_accessible)(Addr64),
-                   Bool       (*chase_into_ok)(Addr64),
-                   Bool       host_bigendian,
-                   VexSubArch subarch_guest )
+IRBB* bbToIR_X86 ( UChar*           x86code, 
+                   Addr64           guest_eip_start, 
+                   VexGuestExtents* vge
+                   Bool             (*byte_accessible)(Addr64),
+                   Bool             (*chase_into_ok)(Addr64),
+                   Bool             host_bigendian,
+                   VexSubArch       subarch_guest )
 {
    UInt       delta;
    Int        i, n_instrs, size, first_stmt_idx;
@@ -245,7 +245,7 @@ IRBB* bbToIR_X86 ( UChar*     x86code,
 
    /* check sanity .. */
    vassert(vex_control.guest_max_insns >= 1);
-   vassert(vex_control.guest_max_insns < 1000);
+   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);
 
@@ -255,6 +255,11 @@ IRBB* bbToIR_X86 ( UChar*     x86code,
 
    vassert((guest_eip_start >> 32) == 0);
 
+   /* Start a new, empty extent. */
+   vge->n_used  = 1;
+   vge->base[0] = guest_eip_start;
+   vge->len[0]  = 0;
+
    /* Set up globals. */
    host_is_bigendian = host_bigendian;
    guest_code        = x86code;
@@ -266,13 +271,17 @@ IRBB* bbToIR_X86 ( UChar*     x86code,
       have so far gone. */
    delta             = 0;
    n_instrs          = 0;
-   *guest_bytes_read = 0;
 
    while (True) {
       vassert(n_instrs < vex_control.guest_max_insns);
 
       guest_next = 0;
-      resteerOK = n_instrs < vex_control.guest_chase_thresh;
+      resteerOK 
+         = n_instrs < vex_control.guest_chase_thresh
+           /* we can't afford to have a resteer once we're on the last
+              extent slot. */
+           && vge->n_used < 3;
+
       first_stmt_idx = irbb->stmts_used;
 
       if (n_instrs > 0) {
@@ -309,7 +318,7 @@ IRBB* bbToIR_X86 ( UChar*     x86code,
       }
 
       delta += size;
-      *guest_bytes_read += size;
+      vge->len[vge->n_used-1] += size;
       n_instrs++;
       DIP("\n");
 
@@ -337,6 +346,11 @@ IRBB* bbToIR_X86 ( UChar*     x86code,
             /* figure out a new delta to continue at. */
             vassert(chase_into_ok(guest_next));
             delta = (UInt)(guest_next - guest_eip_start);
+            /* we now have to start a new extent slot. */
+           vge->n_used++;
+           vassert(vge->n_used <= 3);
+            vge->base[vge->n_used-1] = guest_next;
+            vge->len[vge->n_used-1] = 0;
             n_resteers++;
             d_resteers++;
             if (0 && (n_resteers & 0xFF) == 0)
index 9cacd13381e5ab8fd3c7259b1db15fe07c744942..c8feac46d33784d8f338bfdec56d7dfb17bdeb39 100644 (file)
@@ -164,8 +164,8 @@ VexTranslateResult LibVEX_Translate (
    UChar*  guest_bytes,
    Addr64  guest_bytes_addr,
    Bool    (*chase_into_ok) ( Addr64 ),
-   /* OUT: the number of bytes actually read */
-   Int*    guest_bytes_read,
+   /* OUT: which bits of guest code actually got translated */
+   VexGuestExtents* guest_extents,
    /* IN: a place to put the resulting code, and its size */
    UChar*  host_bytes,
    Int     host_bytes_size,
@@ -194,9 +194,11 @@ VexTranslateResult LibVEX_Translate (
    void         (*ppInstr)     ( HInstr* );
    void         (*ppReg)       ( HReg );
    HInstrArray* (*iselBB)      ( IRBB*, VexSubArch );
-   IRBB*        (*bbToIR)      ( UChar*, Addr64, Int*, 
+   IRBB*        (*bbToIR)      ( UChar*, Addr64, 
+                                 VexGuestExtents*, 
                                  Bool(*)(Addr64), 
-                                 Bool(*)(Addr64), Bool, VexSubArch );
+                                 Bool(*)(Addr64), 
+                                 Bool, VexSubArch );
    Int          (*emit)        ( UChar*, Int, HInstr* );
    IRExpr*      (*specHelper)  ( Char*, IRExpr** );
    Bool         (*preciseMemExnsFn) ( Int, Int );
@@ -252,7 +254,7 @@ VexTranslateResult LibVEX_Translate (
          ppReg       = (void(*)(HReg)) ppHRegX86;
          iselBB      = iselBB_X86;
          emit        = (Int(*)(UChar*,Int,HInstr*)) emit_X86Instr;
-        host_is_bigendian = False;
+         host_is_bigendian = False;
          host_word_type    = Ity_I32;
          vassert(subarch_host == VexSubArchX86_sse0
                  || subarch_host == VexSubArchX86_sse1
@@ -305,11 +307,11 @@ VexTranslateResult LibVEX_Translate (
                    "------------------------\n\n");
 
    irbb = bbToIR ( guest_bytes, 
-                  guest_bytes_addr,
-                  guest_bytes_read,
-                  byte_accessible,
+                   guest_bytes_addr,
+                   guest_extents,
+                   byte_accessible,
                    chase_into_ok,
-                  host_is_bigendian,
+                   host_is_bigendian,
                    subarch_guest );
 
    if (irbb == NULL) {
@@ -319,13 +321,25 @@ VexTranslateResult LibVEX_Translate (
       return VexTransAccessFail;
    }
 
+   vassert(guest_extents->n_used >= 1 && guest_extents->n_used <= 3);
+   vassert(guest_extents->base[0] == guest_bytes_addr);
+   for (i = 0; i < guest_extents->n_used; i++) {
+      vassert(guest_extents->len[i] < 10000); /* sanity */
+   }
+
    /* If debugging, show the raw guest bytes for this bb. */
    if (0 || (vex_traceflags & VEX_TRACE_FE)) {
-      UChar* p = guest_bytes;
-      vex_printf(". 0 %llx %d\n.", guest_bytes_addr, *guest_bytes_read );
-      for (i = 0; i < *guest_bytes_read; i++)
+      if (guest_extents->n_used > 1) {
+         vex_printf("can't show code due to extents > 1\n");
+      } else {
+         /* HACK */
+         UChar* p = (UChar*)guest_bytes;
+         UInt   guest_bytes_read = (UInt)guest_extents->len[0];
+         vex_printf(". 0 %llx %d\n.", guest_bytes_addr, guest_bytes_read );
+         for (i = 0; i < guest_bytes_read; i++)
          vex_printf(" %02x", (Int)p[i] );
-      vex_printf("\n\n");
+         vex_printf("\n\n");
+      }
    }
 
    /* Sanity check the initial IR. */
@@ -414,10 +428,10 @@ VexTranslateResult LibVEX_Translate (
 
    /* Register allocate. */
    rcode = doRegisterAllocation ( vcode, available_real_regs,
-                                 n_available_real_regs,
-                                 isMove, getRegUsage, mapRegs, 
-                                 genSpill, genReload, guest_sizeB,
-                                 ppInstr, ppReg );
+                                           n_available_real_regs,
+                                  isMove, getRegUsage, mapRegs, 
+                                  genSpill, genReload, guest_sizeB,
+                                  ppInstr, ppReg );
 
    if (vex_traceflags & VEX_TRACE_RCODE) {
       vex_printf("\n------------------------" 
@@ -447,7 +461,7 @@ VexTranslateResult LibVEX_Translate (
       j = (*emit)( insn_bytes, 32, rcode->arr[i] );
       if (vex_traceflags & VEX_TRACE_ASM) {
          for (k = 0; k < j; k++)
-           if (insn_bytes[k] < 16)
+            if (insn_bytes[k] < 16)
                vex_printf("0%x ",  (UInt)insn_bytes[k]);
             else
                vex_printf("%x ", (UInt)insn_bytes[k]);
index 84960e82ff07a3e886563fb137a99bd97853bf5b..ead8076b4d3d31c55a9c52baa7e3948b35e46e4a 100644 (file)
@@ -214,6 +214,7 @@ extern void LibVEX_Init (
 /*--- Make a translation                              ---*/
 /*-------------------------------------------------------*/
 
+/* Describes the outcome of a translation attempt. */
 typedef
    enum { 
       VexTransOK, 
@@ -222,6 +223,24 @@ typedef
    }
    VexTranslateResult;
 
+
+/* Describes precisely the pieces of guest code that a translation
+   covers.  Now that Vex can chase across BB boundaries, the old
+   scheme of describing a chunk of guest code merely by its start
+   address and length is inadequate.
+
+   Hopefully this struct is only 32 bytes long.  Space is important as
+   clients will have to store one of these for each translation made.
+*/
+typedef
+   struct {
+      Addr64 base[3];
+      UShort len[3];
+      UShort n_used;
+   }
+   VexGuestExtents;
+
+
 extern 
 VexTranslateResult LibVEX_Translate (
    /* The instruction sets we are translating from and to. */
@@ -233,8 +252,8 @@ VexTranslateResult LibVEX_Translate (
    UChar*  guest_bytes,
    Addr64  guest_bytes_addr,
    Bool    (*chase_into_ok) ( Addr64 ),
-   /* OUT: the number of bytes actually read */
-   Int*    guest_bytes_read,
+   /* OUT: which bits of guest code actually got translated */
+   VexGuestExtents* guest_extents,
    /* IN: a place to put the resulting code, and its size */
    UChar*  host_bytes,
    Int     host_bytes_size,
index c588551432dad282010ef96da323d8e62fd188e9..68869a1e09c082d5545eb695fec8eaa6910e2069 100644 (file)
@@ -60,9 +60,10 @@ int main ( int argc, char** argv )
    UInt u, sum;
    Addr32 orig_addr;
    Int bb_number, n_bbs_done = 0;
-   Int orig_nbytes, trans_used, orig_used;
+   Int orig_nbytes, trans_used;
    VexTranslateResult tres;
    VexControl vcon;
+   VexGuestExtents vge;
 
    if (argc != 2) {
       fprintf(stderr, "usage: vex file.org\n");
@@ -124,7 +125,7 @@ int main ( int argc, char** argv )
                  VexArchX86, VexSubArchX86_sse2, 
                  VexArchX86, VexSubArchX86_sse2,
                  origbuf, (Addr64)orig_addr, chase_into_not_ok,
-                 &orig_used,
+                 &vge,
                  transbuf, N_TRANSBUF, &trans_used,
 #if 1 /* no instrumentation */
                  NULL,          /* instrument1 */
@@ -148,12 +149,13 @@ int main ( int argc, char** argv )
       if (tres != VexTransOK)
          printf("\ntres = %d\n", (Int)tres);
       assert(tres == VexTransOK);
-      assert(orig_used == orig_nbytes);
+      assert(vge.n_used == 1);
+      assert((UInt)(vge.len[0]) == orig_nbytes);
 
       sum = 0;
       for (i = 0; i < trans_used; i++)
          sum += (UInt)transbuf[i];
-      printf ( " %6.2f ... %d\n", (double)trans_used / (double)orig_used, sum );
+      printf ( " %6.2f ... %d\n", (double)trans_used / (double)vge.len[0], sum );
    }
 
    fclose(f);