]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Lots of changes to future-proof the core/skin interface, making it less likely
authorNicholas Nethercote <njn@valgrind.org>
Thu, 14 Nov 2002 12:42:47 +0000 (12:42 +0000)
committerNicholas Nethercote <njn@valgrind.org>
Thu, 14 Nov 2002 12:42:47 +0000 (12:42 +0000)
that changes will cause binary incompatibilities.  Mostly done by hiding naked
structs with function calls.

Structs hidden in this way were: UCodeBlock, SkinSupp and SkinError (which were
merged back with CoreSupp and CoreError into single types Supp and Error),
ShadowChunk, VgDetails, VgNeeds and VgTrackEvents.  The last three are the most
important ones, as they are (I think) the most likely to change.

Suitable get()/set() methods were defined for each one.  The way UCodeBlocks
are copied for instrumentation by skins is a little different now, using
setup_UCodeBlock.  Had to add a few other functions here n there.  Changed
how SK_(complete_shadow_chunk) works a bit.

Added a file coregrind/vg_needs.c which contains all the get/set functions.
It's pretty simple.

The changes are not totally ideal -- eg. ShadowChunks has get()/set() methods
for its `next' field which arguably shouldn't be exposed (betraying the fact
that it's a linked list), and the get()/set() methods are a bit cumbersome at
times, esp. for `Error' because the fields are accessed quite a few times, and
the treatment of Supps and Errors is a bit inconsistent (but they are used in
different ways), and sizeof_shadow_blocks is still a hack.  But still better
than naked structs.  And one advantage is that a bit of sanity checking can be
performed by the get()/set() methods, as is done for VG_({get,set}_sc_extra)()
to make sure no reading/writing occurs outside the allowed area.

I didn't do it for UInstr, because its fields are accessed directly in lots and
lots of spots, which would have been a great big pain and I was a little
worried about overhead of calling lots of extra functions, although in practice
translation times are small enough that it probably doesn't matter.

Updated the example skin and the docs, too, hurrah.

git-svn-id: svn://svn.valgrind.org/valgrind/trunk@1314

20 files changed:
addrcheck/ac_main.c
cachegrind/cg_main.c
corecheck/cc_main.c
coregrind/Makefile.am
coregrind/docs/coregrind_skins.html
coregrind/vg_default.c
coregrind/vg_errcontext.c
coregrind/vg_include.h
coregrind/vg_main.c
coregrind/vg_needs.c [new file with mode: 0644]
coregrind/vg_to_ucode.c
coregrind/vg_translate.c
example/ex_main.c
helgrind/hg_main.c
include/vg_skin.h
lackey/lk_main.c
memcheck/mc_errcontext.c
memcheck/mc_main.c
memcheck/mc_translate.c
none/nl_main.c

index 984cc15a01a4d144a3787b944c1dffe4ff122307..e026c48af1477b94749e29b7ff16c5d0dbbf7887 100644 (file)
@@ -129,27 +129,29 @@ static Bool eq_AcAddrInfo ( VgRes res, AcAddrInfo* ai1, AcAddrInfo* ai2 )
    are otherwise the same, the faulting addrs and associated rwoffsets
    are allowed to be different.  */
 
-Bool SK_(eq_SkinError) ( VgRes res,
-                         SkinError* e1, SkinError* e2 )
+Bool SK_(eq_SkinError) ( VgRes res, Error* e1, Error* e2 )
 {
-   AddrCheckError* e1_extra = e1->extra;
-   AddrCheckError* e2_extra = e2->extra;
+   AddrCheckError* e1_extra = VG_(get_error_extra)(e1);
+   AddrCheckError* e2_extra = VG_(get_error_extra)(e2);
    
-   switch (e1->ekind) {
-      case CoreMemErr:
+   switch (VG_(get_error_kind)(e1)) {
+      case CoreMemErr: {
+         Char *e1s, *e2s;
          if (e1_extra->isWrite != e2_extra->isWrite)   return False;
-         if (e2->ekind != CoreMemErr)                  return False; 
-         if (e1->string == e2->string)                 return True;
-         if (0 == VG_(strcmp)(e1->string, e2->string)) return True;
+         if (VG_(get_error_kind)(e2) != CoreMemErr)    return False; 
+         e1s = VG_(get_error_string)(e1);
+         e2s = VG_(get_error_string)(e2);
+         if (e1s == e2s)                               return True;
+         if (0 == VG_(strcmp)(e1s, e2s))               return True;
          return False;
+      }
 
       case UserErr:
       case ParamErr:
-         if (e1_extra->isWrite != e2_extra->isWrite)
-            return False;
-         if (e1->ekind == ParamErr 
-             && 0 != VG_(strcmp)(e1->string, e2->string))
-            return False;
+         if (e1_extra->isWrite != e2_extra->isWrite)           return False;
+         if (VG_(get_error_kind)(e1) == ParamErr 
+             && 0 != VG_(strcmp)(VG_(get_error_string)(e1),
+                                 VG_(get_error_string)(e2)))   return False;
          return True;
 
       case FreeErr:
@@ -174,7 +176,8 @@ Bool SK_(eq_SkinError) ( VgRes res,
          return True;
 
       default: 
-         VG_(printf)("Error:\n  unknown AddrCheck error code %d\n", e1->ekind);
+         VG_(printf)("Error:\n  unknown AddrCheck error code %d\n",
+                     VG_(get_error_kind)(e1));
          VG_(skin_panic)("unknown error code in SK_(eq_SkinError)");
    }
 }
@@ -229,18 +232,18 @@ static void pp_AcAddrInfo ( Addr a, AcAddrInfo* ai )
    }
 }
 
-void SK_(pp_SkinError) ( SkinError* err, void (*pp_ExeContext)(void) )
+void SK_(pp_SkinError) ( Error* err, void (*pp_ExeContext)(void) )
 {
-   AddrCheckError* err_extra = err->extra;
+   AddrCheckError* err_extra = VG_(get_error_extra)(err);
 
-   switch (err->ekind) {
+   switch (VG_(get_error_kind)(err)) {
       case CoreMemErr:
          if (err_extra->isWrite) {
             VG_(message)(Vg_UserMsg, 
-               "%s contains unaddressable byte(s)", err->string );
+               "%s contains unaddressable byte(s)", VG_(get_error_string)(err));
          } else {
             VG_(message)(Vg_UserMsg, 
-               "%s contains unaddressable byte(s)", err->string );
+               "%s contains unaddressable byte(s)", VG_(get_error_string)(err));
          }
          pp_ExeContext();
          break;
@@ -261,33 +264,33 @@ void SK_(pp_SkinError) ( SkinError* err, void (*pp_ExeContext)(void) )
                VG_(skin_panic)("pp_SkinError(axskind)");
          }
          pp_ExeContext();
-         pp_AcAddrInfo(err->addr, &err_extra->addrinfo);
+         pp_AcAddrInfo(VG_(get_error_address)(err), &err_extra->addrinfo);
          break;
 
       case FreeErr:
          VG_(message)(Vg_UserMsg,"Invalid free() / delete / delete[]");
          /* fall through */
       case FreeMismatchErr:
-         if (err->ekind == FreeMismatchErr)
+         if (VG_(get_error_kind)(err) == FreeMismatchErr)
             VG_(message)(Vg_UserMsg, 
                          "Mismatched free() / delete / delete []");
          pp_ExeContext();
-         pp_AcAddrInfo(err->addr, &err_extra->addrinfo);
+         pp_AcAddrInfo(VG_(get_error_address)(err), &err_extra->addrinfo);
          break;
 
       case ParamErr:
          if (err_extra->isWrite) {
             VG_(message)(Vg_UserMsg, 
-               "Syscall param %s contains unaddressable byte(s)",
-                err->string );
+                         "Syscall param %s contains unaddressable byte(s)",
+                         VG_(get_error_string)(err) );
          } else {
             VG_(message)(Vg_UserMsg, 
                 "Syscall param %s contains uninitialised or "
                 "unaddressable byte(s)",
-            err->string);
+                VG_(get_error_string)(err));
          }
          pp_ExeContext();
-         pp_AcAddrInfo(err->addr, &err_extra->addrinfo);
+         pp_AcAddrInfo(VG_(get_error_address)(err), &err_extra->addrinfo);
          break;
 
       case UserErr:
@@ -300,11 +303,12 @@ void SK_(pp_SkinError) ( SkinError* err, void (*pp_ExeContext)(void) )
                "unaddressable byte(s) found during client check request");
          }
          pp_ExeContext();
-         pp_AcAddrInfo(err->addr, &err_extra->addrinfo);
+         pp_AcAddrInfo(VG_(get_error_address)(err), &err_extra->addrinfo);
          break;
 
       default: 
-         VG_(printf)("Error:\n  unknown AddrCheck error code %d\n", err->ekind);
+         VG_(printf)("Error:\n  unknown AddrCheck error code %d\n",
+                     VG_(get_error_kind)(err));
          VG_(skin_panic)("unknown error code in SK_(pp_SkinError)");
    }
 }
@@ -331,7 +335,8 @@ static void describe_addr ( Addr a, AcAddrInfo* ai )
    /* Closure for searching malloc'd and free'd lists */
    Bool addr_is_in_block(ShadowChunk *sh_ch)
    {
-      return VG_(addr_is_in_block) ( a, sh_ch->data, sh_ch->size );
+      return VG_(addr_is_in_block) ( a, VG_(get_sc_data)(sh_ch),
+                                        VG_(get_sc_size)(sh_ch) );
    }
    /* Perhaps it's on a thread's stack? */
    tid = VG_(any_matching_thread_stack)(addr_is_in_bounds);
@@ -344,18 +349,18 @@ static void describe_addr ( Addr a, AcAddrInfo* ai )
    sc = SK_(any_matching_freed_ShadowChunks)(addr_is_in_block);
    if (NULL != sc) {
       ai->akind      = Freed;
-      ai->blksize    = sc->size;
-      ai->rwoffset   = (Int)(a) - (Int)(sc->data);
-      ai->lastchange = (ExeContext*)sc->skin_extra[0];
+      ai->blksize    = VG_(get_sc_size)(sc);
+      ai->rwoffset   = (Int)(a) - (Int)(VG_(get_sc_data)(sc));
+      ai->lastchange = (ExeContext*)( VG_(get_sc_extra)(sc, 0) );
       return;
    }
    /* Search for a currently malloc'd block which might bracket it. */
    sc = VG_(any_matching_mallocd_ShadowChunks)(addr_is_in_block);
    if (NULL != sc) {
       ai->akind      = Mallocd;
-      ai->blksize    = sc->size;
-      ai->rwoffset   = (Int)(a) - (Int)(sc->data);
-      ai->lastchange = (ExeContext*)sc->skin_extra[0];
+      ai->blksize    = VG_(get_sc_size)(sc);
+      ai->rwoffset   = (Int)(a) - (Int)(VG_(get_sc_data)(sc));
+      ai->lastchange = (ExeContext*)( VG_(get_sc_extra)(sc, 0) );
       return;
    } 
    /* Clueless ... */
@@ -364,19 +369,19 @@ static void describe_addr ( Addr a, AcAddrInfo* ai )
 }
 
 
-/* Creates a copy of the err_extra, updates the copy with address info if
-   necessary, sticks the copy into the SkinError. */
-void SK_(dup_extra_and_update)(SkinError* err)
+/* Creates a copy of the `extra' part, updates the copy with address info if
+   necessary, and returns the copy. */
+void* SK_(dup_extra_and_update)(Error* err)
 {
-   AddrCheckError* err_extra;
+   AddrCheckError* new_extra;
 
-   err_extra  = VG_(malloc)(sizeof(AddrCheckError));
-   *err_extra = *((AddrCheckError*)err->extra);
+   new_extra  = VG_(malloc)(sizeof(AddrCheckError));
+   *new_extra = *((AddrCheckError*)VG_(get_error_extra)(err));
 
-   if (err_extra->addrinfo.akind == Undescribed)
-      describe_addr ( err->addr, &(err_extra->addrinfo) );
+   if (new_extra->addrinfo.akind == Undescribed)
+      describe_addr ( VG_(get_error_address)(err), &(new_extra->addrinfo) );
 
-   err->extra = err_extra;
+   return new_extra;
 }
 
 /* Is this address within some small distance below %ESP?  Used only
@@ -491,59 +496,65 @@ void SK_(record_user_error) ( ThreadState* tst, Addr a, Bool isWrite )
 #define STREQ(s1,s2) (s1 != NULL && s2 != NULL \
                       && VG_(strcmp)((s1),(s2))==0)
 
-Bool SK_(recognised_suppression) ( Char* name, SuppKind *skind )
+Bool SK_(recognised_suppression) ( Char* name, Supp* su )
 {
-   if      (STREQ(name, "Param"))   *skind = ParamSupp;
-   else if (STREQ(name, "CoreMem")) *skind = CoreMemSupp;
-   else if (STREQ(name, "Addr1"))   *skind = Addr1Supp;
-   else if (STREQ(name, "Addr2"))   *skind = Addr2Supp;
-   else if (STREQ(name, "Addr4"))   *skind = Addr4Supp;
-   else if (STREQ(name, "Addr8"))   *skind = Addr8Supp;
-   else if (STREQ(name, "Free"))    *skind = FreeSupp;
+   SuppKind skind;
+   
+   if      (STREQ(name, "Param"))   skind = ParamSupp;
+   else if (STREQ(name, "CoreMem")) skind = CoreMemSupp;
+   else if (STREQ(name, "Addr1"))   skind = Addr1Supp;
+   else if (STREQ(name, "Addr2"))   skind = Addr2Supp;
+   else if (STREQ(name, "Addr4"))   skind = Addr4Supp;
+   else if (STREQ(name, "Addr8"))   skind = Addr8Supp;
+   else if (STREQ(name, "Free"))    skind = FreeSupp;
    else 
       return False;
 
+   VG_(set_supp_kind)(su, skind);
    return True;
 }
 
-Bool SK_(read_extra_suppression_info) ( Int fd, Char* buf, Int nBuf, 
-                                         SkinSupp *s )
+Bool SK_(read_extra_suppression_info) ( Int fd, Char* buf, Int nBuf, Supp *su )
 {
    Bool eof;
 
-   if (s->skind == ParamSupp) {
+   if (VG_(get_supp_kind)(su) == ParamSupp) {
       eof = VG_(get_line) ( fd, buf, nBuf );
       if (eof) return False;
-      s->string = VG_(strdup)(buf);
+      VG_(set_supp_string)(su, VG_(strdup)(buf));
    }
    return True;
 }
 
-extern Bool SK_(error_matches_suppression)(SkinError* err, SkinSupp* su)
+extern Bool SK_(error_matches_suppression)(Error* err, Supp* su)
 {
    UInt su_size;
-   AddrCheckError* err_extra = err->extra;
+   AddrCheckError* err_extra = VG_(get_error_extra)(err);
+   ErrorKind ekind = VG_(get_error_kind)(err);
 
-   switch (su->skind) {
+   switch (VG_(get_supp_kind)(su)) {
       case ParamSupp:
-         return (err->ekind == ParamErr && STREQ(su->string, err->string));
+         return (ekind == ParamErr
+              && STREQ(VG_(get_error_string)(err), VG_(get_supp_string)(su)));
 
       case CoreMemSupp:
-         return (err->ekind == CoreMemErr && STREQ(su->string, err->string));
+         return (ekind == CoreMemErr
+              && STREQ(VG_(get_error_string)(err), VG_(get_supp_string)(su)));
 
       case Addr1Supp: su_size = 1; goto addr_case;
       case Addr2Supp: su_size = 2; goto addr_case;
       case Addr4Supp: su_size = 4; goto addr_case;
       case Addr8Supp: su_size = 8; goto addr_case;
       addr_case:
-         return (err->ekind == AddrErr && err_extra->size == su_size);
+         return (ekind == AddrErr && err_extra->size == su_size);
 
       case FreeSupp:
-         return (err->ekind == FreeErr || err->ekind == FreeMismatchErr);
+         return (ekind == FreeErr || ekind == FreeMismatchErr);
 
       default:
          VG_(printf)("Error:\n"
-                     "  unknown AddrCheck suppression type %d\n", su->skind);
+                     "  unknown AddrCheck suppression type %d\n",
+                     VG_(get_supp_kind)(su));
          VG_(skin_panic)("unknown suppression type in "
                          "SK_(error_matches_suppression)");
    }
@@ -1618,20 +1629,21 @@ void fpu_ACCESS_check_SLOWLY ( Addr addr, Int size )
 static __inline__
 void set_where( ShadowChunk* sc, ExeContext* ec )
 {
-   sc->skin_extra[0] = (UInt)ec;
+   VG_(set_sc_extra)( sc, 0, (UInt)ec );
 }
 
 static __inline__
 ExeContext *get_where( ShadowChunk* sc )
 {
-   return (ExeContext*)sc->skin_extra[0];
+   return (ExeContext*)VG_(get_sc_extra)(sc, 0);
 }
 
 void SK_(complete_shadow_chunk) ( ShadowChunk* sc, ThreadState* tst )
 {
-   set_where( sc, VG_(get_ExeContext) ( tst ) );
+   VG_(set_sc_extra) ( sc, 0, (UInt)VG_(get_ExeContext)(tst) );
 }
 
+
 /*------------------------------------------------------------*/
 /*--- Postponing free()ing                                 ---*/
 /*------------------------------------------------------------*/
@@ -1646,7 +1658,7 @@ static __attribute__ ((unused))
 {
    ShadowChunk* sc;
    Int n = 0;
-   for (sc = vg_freed_list_start; sc != NULL; sc = sc->next)
+   for (sc = vg_freed_list_start; sc != NULL; sc = VG_(get_sc_next)(sc))
       n++;
    return n;
 }
@@ -1657,8 +1669,8 @@ static __attribute__ ((unused))
    ShadowChunk* sc;
    Int n = 0;
    /* VG_(printf)("freelist sanity\n"); */
-   for (sc = vg_freed_list_start; sc != NULL; sc = sc->next)
-      n += sc->size;
+   for (sc = vg_freed_list_start; sc != NULL; sc = VG_(get_sc_next)(sc))
+      n += VG_(get_sc_size)(sc);
    sk_assert(n == vg_freed_list_volume);
 }
 
@@ -1672,14 +1684,14 @@ static void add_to_freed_queue ( ShadowChunk* sc )
    if (vg_freed_list_end == NULL) {
       sk_assert(vg_freed_list_start == NULL);
       vg_freed_list_end = vg_freed_list_start = sc;
-      vg_freed_list_volume = sc->size;
+      vg_freed_list_volume = VG_(get_sc_size)(sc);
    } else {    
-      sk_assert(vg_freed_list_end->next == NULL);
-      vg_freed_list_end->next = sc;
+      sk_assert(VG_(get_sc_next)(vg_freed_list_end) == NULL);
+      VG_(set_sc_next)(vg_freed_list_end, sc);
       vg_freed_list_end = sc;
-      vg_freed_list_volume += sc->size;
+      vg_freed_list_volume += VG_(get_sc_size)(sc);
    }
-   sc->next = NULL;
+   VG_(set_sc_next)(sc, NULL);
 
    /* Release enough of the oldest blocks to bring the free queue
       volume below vg_clo_freelist_vol. */
@@ -1690,16 +1702,16 @@ static void add_to_freed_queue ( ShadowChunk* sc )
       sk_assert(vg_freed_list_end != NULL);
 
       sc1 = vg_freed_list_start;
-      vg_freed_list_volume -= sc1->size;
+      vg_freed_list_volume -= VG_(get_sc_size)(sc1);
       /* VG_(printf)("volume now %d\n", vg_freed_list_volume); */
       sk_assert(vg_freed_list_volume >= 0);
 
       if (vg_freed_list_start == vg_freed_list_end) {
          vg_freed_list_start = vg_freed_list_end = NULL;
       } else {
-         vg_freed_list_start = sc1->next;
+         vg_freed_list_start = VG_(get_sc_next)(sc1);
       }
-      sc1->next = NULL; /* just paranoia */
+      VG_(set_sc_next)(sc1, NULL); /* just paranoia */
       VG_(free_ShadowChunk) ( sc1 );
    }
 }
@@ -1712,7 +1724,7 @@ ShadowChunk* SK_(any_matching_freed_ShadowChunks)
 
    /* No point looking through freed blocks if we're not keeping
       them around for a while... */
-   for (sc = vg_freed_list_start; sc != NULL; sc = sc->next)
+   for (sc = vg_freed_list_start; sc != NULL; sc = VG_(get_sc_next)(sc))
       if (p(sc))
          return sc;
 
@@ -1743,13 +1755,12 @@ UCodeBlock* SK_(instrument)(UCodeBlock* cb_in, Addr orig_addr)
    UInstr*     u_in;
    Int         t_addr, t_size;
 
-   cb = VG_(alloc_UCodeBlock)();
-   cb->nextTemp = cb_in->nextTemp;
+   cb = VG_(setup_UCodeBlock)(cb_in);
 
-   for (i = 0; i < cb_in->used; i++) {
+   for (i = 0; i < VG_(get_num_instrs)(cb_in); i++) {
 
       t_addr = t_size = INVALID_TEMPREG;
-      u_in = &cb_in->instrs[i];
+      u_in = VG_(get_instr)(cb_in, i);
 
       switch (u_in->opcode) {
          case NOP:  case LOCK:  case CALLM_E:  case CALLM_S:
@@ -2090,57 +2101,54 @@ Char* SK_(usage)(void)
 /*--- Setup                                                ---*/
 /*------------------------------------------------------------*/
 
-void SK_(pre_clo_init)(VgDetails* details, VgNeeds* needs, VgTrackEvents* track)
-{
-   details->name             = "Addrcheck";
-   details->version          = NULL;
-   details->description      = "a fine-grained address checker";
-   details->copyright_author =
-      "Copyright (C) 2002, and GNU GPL'd, by Julian Seward.";
-   details->bug_reports_to   = "jseward@acm.org";
-
-   needs->core_errors          = True;
-   needs->skin_errors          = True;
-   needs->libc_freeres         = True;
-   needs->sizeof_shadow_block  = 1;
-   needs->basic_block_discards = False;
-   needs->shadow_regs          = False;
-   needs->command_line_options = True;
-   needs->client_requests      = True;
-   needs->extended_UCode       = False;
-   needs->syscall_wrapper      = True;
-   needs->alternative_free     = True;
-   needs->sanity_checks        = True;
-
-   track->new_mem_startup       = & addrcheck_new_mem_startup;
-   track->new_mem_heap          = & addrcheck_new_mem_heap;
-   track->new_mem_stack         = & SK_(make_accessible);
-   track->new_mem_stack_aligned = & make_writable_aligned;
-   track->new_mem_stack_signal  = & SK_(make_accessible);
-   track->new_mem_brk           = & SK_(make_accessible);
-   track->new_mem_mmap          = & addrcheck_set_perms;
+void SK_(pre_clo_init)(void)
+{
+   VG_(details_name)            ("Addrcheck");
+   VG_(details_version)         (NULL);
+   VG_(details_description)     ("a fine-grained address checker");
+   VG_(details_copyright_author)(
+      "Copyright (C) 2002, and GNU GPL'd, by Julian Seward.");
+   VG_(details_bug_reports_to)  ("jseward@acm.org");
+
+   VG_(needs_core_errors)         ();
+   VG_(needs_skin_errors)         ();
+   VG_(needs_libc_freeres)        ();
+   VG_(needs_sizeof_shadow_block) ( 1 );
+   VG_(needs_command_line_options)();
+   VG_(needs_client_requests)     ();
+   VG_(needs_syscall_wrapper)     ();
+   VG_(needs_alternative_free)    ();
+   VG_(needs_sanity_checks)       ();
+
+   VG_(track_new_mem_startup)      ( & addrcheck_new_mem_startup );
+   VG_(track_new_mem_heap)         ( & addrcheck_new_mem_heap );
+   VG_(track_new_mem_stack)        ( & SK_(make_accessible) );
+   VG_(track_new_mem_stack_aligned)( & make_writable_aligned );
+   VG_(track_new_mem_stack_signal) ( & SK_(make_accessible) );
+   VG_(track_new_mem_brk)          ( & SK_(make_accessible) );
+   VG_(track_new_mem_mmap)         ( & addrcheck_set_perms );
    
-   track->copy_mem_heap         = & copy_address_range_state;
-   track->copy_mem_remap        = & copy_address_range_state;
-   track->change_mem_mprotect   = & addrcheck_set_perms;
+   VG_(track_copy_mem_heap)        ( & copy_address_range_state );
+   VG_(track_copy_mem_remap)       ( & copy_address_range_state );
+   VG_(track_change_mem_mprotect)  ( & addrcheck_set_perms );
       
-   track->ban_mem_heap          = & SK_(make_noaccess);
-   track->ban_mem_stack         = & SK_(make_noaccess);
-
-   track->die_mem_heap          = & SK_(make_noaccess);
-   track->die_mem_stack         = & SK_(make_noaccess);
-   track->die_mem_stack_aligned = & make_noaccess_aligned
-   track->die_mem_stack_signal  = & SK_(make_noaccess); 
-   track->die_mem_brk           = & SK_(make_noaccess);
-   track->die_mem_munmap        = & SK_(make_noaccess); 
-
-   track->bad_free              = & SK_(record_free_error);
-   track->mismatched_free       = & SK_(record_freemismatch_error);
-
-   track->pre_mem_read          = & check_is_readable;
-   track->pre_mem_read_asciiz   = & check_is_readable_asciiz;
-   track->pre_mem_write         = & check_is_writable;
-   track->post_mem_write        = & SK_(make_accessible);
+   VG_(track_ban_mem_heap)         ( & SK_(make_noaccess) );
+   VG_(track_ban_mem_stack)        ( & SK_(make_noaccess) );
+
+   VG_(track_die_mem_heap)         ( & SK_(make_noaccess) );
+   VG_(track_die_mem_stack)        ( & SK_(make_noaccess) );
+   VG_(track_die_mem_stack_aligned)( & make_noaccess_aligned )
+   VG_(track_die_mem_stack_signal) ( & SK_(make_noaccess) ); 
+   VG_(track_die_mem_brk)          ( & SK_(make_noaccess) );
+   VG_(track_die_mem_munmap)       ( & SK_(make_noaccess) ); 
+
+   VG_(track_bad_free)             ( & SK_(record_free_error) );
+   VG_(track_mismatched_free)      ( & SK_(record_freemismatch_error) );
+
+   VG_(track_pre_mem_read)         ( & check_is_readable );
+   VG_(track_pre_mem_read_asciiz)  ( & check_is_readable_asciiz );
+   VG_(track_pre_mem_write)        ( & check_is_writable );
+   VG_(track_post_mem_write)       ( & SK_(make_accessible) );
 
    VG_(register_compact_helper)((Addr) & SK_(helperc_ACCESS4));
    VG_(register_compact_helper)((Addr) & SK_(helperc_ACCESS2));
index 7a93fc29294a3b3363b01efec981500a9fb205db..134dc4ae4fdec27b00a8e588c4110b9696c05ac2 100644 (file)
@@ -495,8 +495,8 @@ static Int compute_BBCC_array_size(UCodeBlock* cb)
    is_LOAD = is_STORE = is_FPU_R = is_FPU_W = False;
    t_read = t_write = INVALID_TEMPREG;
 
-   for (i = 0; i < cb->used; i++) {
-      u_in = &cb->instrs[i];
+   for (i = 0; i < VG_(get_num_instrs)(cb); i++) {
+      u_in = VG_(get_instr)(cb, i);
       switch(u_in->opcode) {
 
          case INCEIP: 
@@ -695,14 +695,13 @@ UCodeBlock* SK_(instrument)(UCodeBlock* cb_in, Addr orig_addr)
    BBCC_node = get_BBCC(orig_addr, cb_in, /*remove=*/False, &BB_seen_before);
    BBCC_ptr0 = BBCC_ptr = (Addr)(BBCC_node->array);
 
-   cb = VG_(alloc_UCodeBlock)();
-   cb->nextTemp = cb_in->nextTemp;
+   cb = VG_(setup_UCodeBlock)(cb_in);
 
    t_CC_addr = t_read_addr = t_write_addr = t_data_addr1 = t_data_addr2 =
                t_read = t_write = INVALID_TEMPREG;
 
-   for (i = 0; i < cb_in->used; i++) {
-      u_in = &cb_in->instrs[i];
+   for (i = 0; i < VG_(get_num_instrs)(cb_in); i++) {
+      u_in = VG_(get_instr)(cb_in, i);
 
       /* What this is all about:  we want to instrument each x86 instruction 
        * translation.  The end of these are marked in three ways.  The three
@@ -802,21 +801,22 @@ UCodeBlock* SK_(instrument)(UCodeBlock* cb_in, Addr orig_addr)
          case JMP:
             if (instrumented_Jcond) {
                sk_assert(CondAlways == u_in->cond);
-               sk_assert(i+1 == cb_in->used);
+               sk_assert(i+1 == VG_(get_num_instrs)(cb_in));
                VG_(copy_UInstr)(cb, u_in);
                instrumented_Jcond = False;    /* reset */
                break;
             }
             /* The first JMP... instrument. */
             if (CondAlways != u_in->cond) {
-               sk_assert(i+2 == cb_in->used);
+               sk_assert(i+2 == VG_(get_num_instrs)(cb_in));
                instrumented_Jcond = True;
             } else {
-               sk_assert(i+1 == cb_in->used);
+               sk_assert(i+1 == VG_(get_num_instrs)(cb_in));
             }
 
             /* Get x86 instr size from final JMP. */
-            x86_instr_size = LAST_UINSTR(cb_in).extra4b;
+            x86_instr_size = VG_(get_last_instr)(cb_in)->extra4b;
+
             goto instrument_x86_instr;
 
 
@@ -1916,18 +1916,17 @@ Char* SK_(usage)(void)
 /*--- Setup                                                        ---*/
 /*--------------------------------------------------------------------*/
 
-void SK_(pre_clo_init)(VgDetails* details, VgNeeds* needs,
-                       VgTrackEvents* not_used)
+void SK_(pre_clo_init)(void)
 {
-   details->name             = "Cachegrind";
-   details->version          = NULL;
-   details->description      = "an I1/D1/L2 cache profiler";
-   details->copyright_author =
-      "Copyright (C) 2002, and GNU GPL'd, by Nicholas Nethercote.";
-   details->bug_reports_to   = "njn25@cam.ac.uk";
-
-   needs->basic_block_discards = True;
-   needs->command_line_options = True;
+   VG_(details_name)            ("Cachegrind");
+   VG_(details_version)         (NULL);
+   VG_(details_description)     ("an I1/D1/L2 cache profiler");
+   VG_(details_copyright_author)(
+      "Copyright (C) 2002, and GNU GPL'd, by Nicholas Nethercote.");
+   VG_(details_bug_reports_to)  ("njn25@cam.ac.uk");
+
+   VG_(needs_basic_block_discards)();
+   VG_(needs_command_line_options)();
 
    VG_(register_compact_helper)((Addr) & log_1I_0D_cache_access);
    VG_(register_compact_helper)((Addr) & log_1I_0D_cache_access_JIFZ);
index b6223f85c50edd4a2b85f368fce2f4a271469edb..b6c3e9660fc46fdd3a11e000b704305a0551498e 100644 (file)
 
 VG_DETERMINE_INTERFACE_VERSION
 
-void SK_(pre_clo_init)(VgDetails* details, VgNeeds* needs, VgTrackEvents* track)
+void SK_(pre_clo_init)(void)
 {
-   details->name             = "Coregrind";
-   details->version          = NULL;
-   details->description      = "a rudimentary error detector";
-   details->copyright_author =
-      "Copyright (C) 2002, and GNU GPL'd, by Nicholas Nethercote.";
-   details->bug_reports_to   = "njn25@cam.ac.uk";
-
-   needs->core_errors = True;
+   VG_(details_name)            ("Coregrind");
+   VG_(details_version)         (NULL);
+   VG_(details_description)     ("a rudimentary error detector");
+   VG_(details_copyright_author)(
+      "Copyright (C) 2002, and GNU GPL'd, by Nicholas Nethercote.");
+   VG_(details_bug_reports_to)  ("njn25@cam.ac.uk");
+
+   VG_(needs_core_errors)();
 
    /* No core events to track */
 }
index 7ad845ec5dd002b752a987fd7ffeeeb1c823f3cd..fd113067a65d01d1e2a0dac0e2cf8c3d6cff5a8e 100644 (file)
@@ -51,6 +51,7 @@ valgrind_so_SOURCES = \
        vg_memory.c \
        vg_messages.c \
        vg_mylibc.c \
+       vg_needs.c \
        vg_procselfmaps.c \
        vg_dummy_profile.c \
        vg_signals.c \
index a173971396cabb749ed3d5982947aa5c850be3df..ab958d7c0c71a258e6a718615e2d58c073554abf 100644 (file)
@@ -369,18 +369,18 @@ Only use <code>SK_(post_clo_init)()</code> if a skin provides command line
 options and must do some initialisation after option processing takes place
 (``<code>clo</code>'' stands for ``command line options'').<p>
 
-The first argument to <code>SK_(pre_clo_init)()</code> must be initialised with
-various ``details'' for a skin.  These are all compulsory except for
+First of all, various ``details'' need to be set for a skin, using the
+functions <code>VG_(details_*)()</code>.  These are all compulsory except for
 <code>version</code>.  They are used when constructing the startup message,
 except for <code></code> which is used if <code>VG_(skin_panic)()</code> is
 ever called, or a skin assertion fails.<p>
 
-The second argument to <code>SK_(pre_clo_init)()</code> must be initialised with
-the ``needs'' for a skin.  They are mostly booleans, and can be left untouched
-(they default to <code>False</code>).  They determine whether a skin can do
-various things such as:  record, report and suppress errors; process command
-line options;  wrap system calls;  record extra information about malloc'd
-blocks, etc.<p>
+Second, various ``needs'' can be set for a skin, using the functions
+<code>VG_(needs_*)()</code>.  They are mostly booleans, and can be left
+untouched (they default to <code>False</code>).  They determine whether a skin
+can do various things such as:  record, report and suppress errors; process
+command line options;  wrap system calls;  record extra information about
+malloc'd blocks, etc.<p>
 
 For example, if a skin wants the core's help in recording and reporting errors,
 it must set the <code>skin_errors</code> need to <code>True</code>, and then
@@ -391,18 +391,20 @@ scratch because the core is doing most of the work.  See the type
 <code>VgNeeds</code> in <code>include/vg_skin.h</code> for full details of all
 the needs.<p>
 
-The third argument to <code>SK_(pre_clo_init)()</code> must be initialised to
-indicate which events in core the skin wants to be notified about.  These
-include things such as blocks of memory being malloc'd, the stack pointer
-changing, a mutex being locked, etc.  If a skin wants to know about this,
-it should set the relevant pointer in the structure to point to a function,
-which will be called when that event happens.<p>
+Third, the skin can indicate which events in core it wants to be notified
+about, using the functions <code>VG_(track_*)()</code>.  These include things
+such as blocks of memory being malloc'd, the stack pointer changing, a mutex
+being locked, etc.  If a skin wants to know about this, it should set the
+relevant pointer in the structure to point to a function, which will be called
+when that event happens.<p>
 
 For example, if the skin want to be notified when a new block of memory is
-malloc'd, it should set the <code>new_mem_heap</code> function pointer, and the
-assigned function will be called each time this happens.  See the type
-<code>VgTrackEvents</code> in <code>include/vg_skin.h</code> for full details
-of all the trackable events.<p>
+malloc'd, it should call <code>VG_(track_new_mem_heap)()</code> with an
+appropriate function pointer, and the assigned function will be called each
+time this happens.<p>
+
+More information about ``details'', ``needs'' and ``trackable events'' can be
+found in <code>include/vg_skin.h</code>.<p>
 
 <a name="instr"></a>
 <h3>2.7&nbsp; Instrumentation</h3>
@@ -675,9 +677,8 @@ it:
   <li>If you write a skin</li><p>
   <li>If you have suggestions for new features, needs, trackable events,
       functions</li><p>
-  <li>If you have suggestions for making skins easier to write
-  </li><p>
-  <li>If you have suggestions for improving this documentation  </li><p>
+  <li>If you have suggestions for making skins easier to write</li><p>
+  <li>If you have suggestions for improving this documentation</li><p>
   <li>If you don't understand something</li><p>
 </ul>
 
index 83008d4be0f62087c13b89562d66b210dda787f1..8778b846857746e1f1f7c4876d080564b159bb67 100644 (file)
@@ -71,7 +71,7 @@ void non_fund_panic ( Char* fn )
    ------------------------------------------------------------------ */
 
 __attribute__ ((weak))
-void SK_(pre_clo_init)(VgDetails* details, VgNeeds* needs, VgTrackEvents* track)
+void SK_(pre_clo_init)( void )
 {
    fund_panic("SK_(pre_clo_init)");
 }
@@ -99,38 +99,37 @@ void SK_(fini)(void)
    ------------------------------------------------------------------ */
 
 __attribute__ ((weak))
-Bool SK_(eq_SkinError)(VgRes res, SkinError* e1, SkinError* e2)
+Bool SK_(eq_SkinError)(VgRes res, Error* e1, Error* e2)
 {
    non_fund_panic("SK_(eq_SkinError)");
 }
 
 __attribute__ ((weak))
-void SK_(pp_SkinError)(SkinError* ec, void (*pp_ExeContext)(void))
+void SK_(pp_SkinError)(Error* err, void (*pp_ExeContext)(void))
 {
    non_fund_panic("SK_(pp_SkinError)");
 }
 
 __attribute__ ((weak))
-void SK_(dup_extra_and_update)(SkinError* ec)
+void* SK_(dup_extra_and_update)(Error* err)
 {
    non_fund_panic("SK_(dup_extra_and_update)");
 }
 
 __attribute__ ((weak))
-Bool SK_(recognised_suppression)(Char* name, SuppKind* skind)
+Bool SK_(recognised_suppression)(Char* name, Supp* su)
 {
    non_fund_panic("SK_(recognised_suppression)");
 }
 
 __attribute__ ((weak))
-Bool SK_(read_extra_suppression_info)(Int fd, Char* buf, 
-                                       Int nBuf, SkinSupp *s)
+Bool SK_(read_extra_suppression_info)(Int fd, Char* buf, Int nBuf, Supp* su)
 {
    non_fund_panic("SK_(read_extra_suppression_info)");
 }
 
 __attribute__ ((weak))
-Bool SK_(error_matches_suppression)(SkinError* ec, SkinSupp* su)
+Bool SK_(error_matches_suppression)(Error* err, Supp* su)
 {
    non_fund_panic("SK_(error_matches_suppression)");
 }
@@ -213,7 +212,7 @@ void SK_(pp_XUInstr)(UInstr* u)
 }
 
 __attribute__ ((weak))
-Int SK_(get_Xreg_usage)(UInstr* u, Tag tag, RegUse* arr)
+Int SK_(get_Xreg_usage)(UInstr* u, Tag tag, Int* regs, Bool* isWrites)
 {
    non_fund_panic("SK_(get_Xreg_usage)");
 }
index b01ca574c39ee0e3c3d17c29796e612efa5ad012..4d82b50eca25f3affd533bdfb4b31fc8593a8ba2 100644 (file)
 
 /* The list of error contexts found, both suppressed and unsuppressed.
    Initially empty, and grows as errors are detected. */
-static CoreError* vg_errors = NULL;
+static Error* vg_errors = NULL;
 
 /* The list of suppression directives, as read from the specified
    suppressions file. */
-static CoreSupp* vg_suppressions = NULL;
+static Supp* vg_suppressions = NULL;
 
 /* Running count of unsuppressed errors detected. */
 static UInt vg_n_errs_found = 0;
@@ -49,7 +49,7 @@ static UInt vg_n_errs_found = 0;
 static UInt vg_n_errs_suppressed = 0;
 
 /* forwards ... */
-static CoreSupp* is_suppressible_error ( CoreError* err );
+static Supp* is_suppressible_error ( Error* err );
 
 
 /*------------------------------------------------------------*/
@@ -59,34 +59,34 @@ static CoreSupp* is_suppressible_error ( CoreError* err );
 /* Compare error contexts, to detect duplicates.  Note that if they
    are otherwise the same, the faulting addrs and associated rwoffsets
    are allowed to be different.  */
-static Bool eq_CoreError ( VgRes res, CoreError* e1, CoreError* e2 )
+static Bool eq_Error ( VgRes res, Error* e1, Error* e2 )
 {
-   if (e1->skin_err.ekind != e2->skin_err.ekind) 
+   if (e1->ekind != e2->ekind) 
       return False;
    if (!VG_(eq_ExeContext)(res, e1->where, e2->where))
       return False;
 
-   switch (e1->skin_err.ekind) {
+   switch (e1->ekind) {
       case PThreadErr:
          vg_assert(VG_(needs).core_errors);
-         if (e1->skin_err.string == e2->skin_err.string) 
+         if (e1->string == e2->string) 
             return True;
-         if (0 == VG_(strcmp)(e1->skin_err.string, e2->skin_err.string))
+         if (0 == VG_(strcmp)(e1->string, e2->string))
             return True;
          return False;
       default: 
          if (VG_(needs).skin_errors)
-            return SK_(eq_SkinError)(res, &e1->skin_err, &e2->skin_err);
+            return SK_(eq_SkinError)(res, e1, e2);
          else {
             VG_(printf)("\nUnhandled error type: %u. VG_(needs).skin_errors\n"
                         "probably needs to be set.\n",
-                        e1->skin_err.ekind);
+                        e1->ekind);
             VG_(skin_panic)("unhandled error type");
          }
    }
 }
 
-static void pp_CoreError ( CoreError* err, Bool printCount )
+static void pp_Error ( Error* err, Bool printCount )
 {
    /* Closure for printing where the error occurred.  Abstracts details
       about the `where' field away from the skin. */
@@ -100,19 +100,19 @@ static void pp_CoreError ( CoreError* err, Bool printCount )
    if (err->tid > 1)
       VG_(message)(Vg_UserMsg, "Thread %d:", err->tid );
 
-   switch (err->skin_err.ekind) {
+   switch (err->ekind) {
       case PThreadErr:
          vg_assert(VG_(needs).core_errors);
-         VG_(message)(Vg_UserMsg, "%s", err->skin_err.string );
+         VG_(message)(Vg_UserMsg, "%s", err->string );
          VG_(pp_ExeContext)(err->where);
          break;
       default: 
          if (VG_(needs).skin_errors)
-            SK_(pp_SkinError)( &err->skin_err, &pp_ExeContextClosure );
+            SK_(pp_SkinError)( err, &pp_ExeContextClosure );
          else {
             VG_(printf)("\nUnhandled error type: %u.  VG_(needs).skin_errors\n"
                         "probably needs to be set?\n",
-                        err->skin_err.ekind);
+                        err->ekind);
             VG_(skin_panic)("unhandled error type");
          }
    }
@@ -175,10 +175,10 @@ Bool vg_is_GDB_attach_requested ( void )
      stored thread state, not from VG_(baseBlock).  
 */
 static __inline__
-void construct_error ( CoreError* err, ThreadState* tst, 
+void construct_error ( Error* err, ThreadState* tst, 
                        ErrorKind ekind, Addr a, Char* s, void* extra )
 {
-   /* CoreError parts */
+   /* Core-only parts */
    err->next     = NULL;
    err->supp     = NULL;
    err->count    = 1;
@@ -200,11 +200,11 @@ void construct_error ( CoreError* err, ThreadState* tst,
       err->m_ebp = tst->m_ebp;
    }
 
-   /* SkinError parts */
-   err->skin_err.ekind  = ekind;
-   err->skin_err.addr   = a;
-   err->skin_err.string = s;
-   err->skin_err.extra  = extra;
+   /* Skin-relevant parts */
+   err->ekind  = ekind;
+   err->addr   = a;
+   err->string = s;
+   err->extra  = extra;
 
    /* sanity... */
    vg_assert(err->tid >= 0 && err->tid < VG_N_THREADS);
@@ -216,14 +216,14 @@ void construct_error ( CoreError* err, ThreadState* tst,
 void VG_(maybe_record_error) ( ThreadState* tst, 
                                ErrorKind ekind, Addr a, Char* s, void* extra )
 {
-   CoreError   err;
-   CoreError*  p;
-   CoreError*  p_prev;
-   VgRes       exe_res                = Vg_MedRes;
-   static Bool is_first_shown_context = True;
-   static Bool stopping_message       = False;
-   static Bool slowdown_message       = False;
-   static Int  vg_n_errs_shown        = 0;
+          Error  err;
+          Error* p;
+          Error* p_prev;
+          VgRes  exe_res                = Vg_MedRes;
+   static Bool   is_first_shown_context = True;
+   static Bool   stopping_message       = False;
+   static Bool   slowdown_message       = False;
+   static Int    vg_n_errs_shown        = 0;
 
    /* After M_VG_COLLECT_NO_ERRORS_AFTER_SHOWN different errors have
       been found, or M_VG_COLLECT_NO_ERRORS_AFTER_FOUND total errors
@@ -286,7 +286,7 @@ void VG_(maybe_record_error) ( ThreadState* tst,
    p      = vg_errors;
    p_prev = NULL;
    while (p != NULL) {
-      if (eq_CoreError(exe_res, p, &err)) {
+      if (eq_Error(exe_res, p, &err)) {
          /* Found it. */
          p->count++;
         if (p->supp != NULL) {
@@ -316,19 +316,19 @@ void VG_(maybe_record_error) ( ThreadState* tst,
    /* OK, we're really going to collect it.  First make a copy,
       because the error context is on the stack and will disappear shortly.
       We can duplicate the main part ourselves, but use
-      SK_(dup_extra_and_update) to duplicate the 'extra' part (unless it's
+      SK_(dup_extra_and_update) to duplicate the `extra' part (unless it's
       NULL).
      
-      SK_(dup_extra_and_update) can also update the SkinError.  This is
+      SK_(dup_extra_and_update) can also update the `extra' part.  This is
       for when there are more details to fill in which take time to work out
       but don't affect our earlier decision to include the error -- by
       postponing those details until now, we avoid the extra work in the
-      case where we ignore the error.
+      case where we ignore the error.  Ugly.
     */
-   p = VG_(arena_malloc)(VG_AR_ERRORS, sizeof(CoreError));
+   p = VG_(arena_malloc)(VG_AR_ERRORS, sizeof(Error));
    *p = err;
-   if (NULL != err.skin_err.extra)
-      SK_(dup_extra_and_update)(&p->skin_err);
+   if (NULL != err.extra)
+      p->extra = SK_(dup_extra_and_update)(p);
 
    p->next = vg_errors;
    p->supp = is_suppressible_error(&err);
@@ -337,7 +337,7 @@ void VG_(maybe_record_error) ( ThreadState* tst,
       vg_n_errs_found++;
       if (!is_first_shown_context)
          VG_(message)(Vg_UserMsg, "");
-      pp_CoreError(p, False);      
+      pp_Error(p, False);      
       is_first_shown_context = False;
       vg_n_errs_shown++;
       /* Perhaps we want a GDB attach at this point? */
@@ -369,11 +369,11 @@ void VG_(record_pthread_error) ( ThreadId tid, Char* msg )
 
 void VG_(show_all_errors) ( void )
 {
-   Int        i, n_min;
-   Int        n_err_contexts, n_supp_contexts;
-   CoreError *p, *p_min;
-   CoreSupp   *su;
-   Bool       any_supp;
+   Int    i, n_min;
+   Int    n_err_contexts, n_supp_contexts;
+   Error *p, *p_min;
+   Supp  *su;
+   Bool   any_supp;
 
    if (VG_(clo_verbosity) == 0)
       return;
@@ -416,7 +416,7 @@ void VG_(show_all_errors) ( void )
       VG_(message)(Vg_UserMsg, "%d errors in context %d of %d:",
                    p_min->count,
                    i+1, n_err_contexts);
-      pp_CoreError( p_min, False );
+      pp_Error( p_min, False );
 
       if ((i+1 == VG_(clo_dump_error))) {
        VG_(translate) ( 0 /* dummy ThreadId; irrelevant due to below NULLs */,
@@ -558,11 +558,11 @@ static void load_one_suppressions_file ( Char* filename )
 
    while (True) {
       /* Assign and initialise the two suppression halves (core and skin) */
-      CoreSupp* supp;
-      supp        = VG_(arena_malloc)(VG_AR_CORE, sizeof(CoreSupp));
+      Supp* supp;
+      supp        = VG_(arena_malloc)(VG_AR_CORE, sizeof(Supp));
       supp->count = 0;
       for (i = 0; i < VG_N_SUPP_CALLERS; i++) supp->caller[i] = NULL;
-      supp->skin_supp.string = supp->skin_supp.extra = NULL;
+      supp->string = supp->extra = NULL;
 
       eof = VG_(get_line) ( fd, buf, N_BUF );
       if (eof) break;
@@ -593,7 +593,7 @@ static void load_one_suppressions_file ( Char* filename )
       if (VG_(needs).core_errors && skin_name_present("core", skin_names))
       {
          if (STREQ(supp_name, "PThread"))
-            supp->skin_supp.skind = PThreadSupp;
+            supp->skind = PThreadSupp;
          else
             goto syntax_error;
       }
@@ -602,9 +602,9 @@ static void load_one_suppressions_file ( Char* filename )
       else if (VG_(needs).skin_errors && 
                skin_name_present(VG_(details).name, skin_names))
       {
-         if (SK_(recognised_suppression)(supp_name, & supp->skin_supp.skind)) 
+         if (SK_(recognised_suppression)(supp_name, supp)) 
          {
-            /* Do nothing, function fills in supp->skin_supp.skind */
+            /* Do nothing, function fills in supp->skind */
          } else
             goto syntax_error;
       }
@@ -621,7 +621,7 @@ static void load_one_suppressions_file ( Char* filename )
       }
 
       if (VG_(needs).skin_errors && 
-          !SK_(read_extra_suppression_info)(fd, buf, N_BUF, &supp->skin_supp)) 
+          !SK_(read_extra_suppression_info)(fd, buf, N_BUF, supp)) 
          goto syntax_error;
 
       /* "i > 0" ensures at least one caller read. */
@@ -687,28 +687,27 @@ void get_objname_fnname ( Addr a,
 }     
 
 static __inline__
-Bool supp_matches_error(CoreSupp* su, CoreError* err)
+Bool supp_matches_error(Supp* su, Error* err)
 {
-   switch (su->skin_supp.skind) {
+   switch (su->skind) {
       case PThreadSupp:
-         return (err->skin_err.ekind == PThreadErr);
+         return (err->ekind == PThreadErr);
       default:
          if (VG_(needs).skin_errors) {
-            return (SK_(error_matches_suppression)(&err->skin_err, 
-                                                    &su->skin_supp));
+            return SK_(error_matches_suppression)(err, su);
          } else {
             VG_(printf)(
                "\nUnhandled suppression type: %u.  VG_(needs).skin_errors\n"
                "probably needs to be set.\n",
-               err->skin_err.ekind);
+               err->ekind);
             VG_(skin_panic)("unhandled suppression type");
          }
    }
 }
 
 static __inline__
-Bool supp_matches_callers(CoreSupp* su, Char caller_obj[][M_VG_ERRTXT], 
-                                        Char caller_fun[][M_VG_ERRTXT])
+Bool supp_matches_callers(Supp* su, Char caller_obj[][M_VG_ERRTXT], 
+                                    Char caller_fun[][M_VG_ERRTXT])
 {
    Int i;
 
@@ -728,19 +727,18 @@ Bool supp_matches_callers(CoreSupp* su, Char caller_obj[][M_VG_ERRTXT],
    return True;
 }
 
-/* Does an error context match a suppression?  ie is this a
-   suppressible error?  If so, return a pointer to the CoreSupp
-   record, otherwise NULL.
+/* Does an error context match a suppression?  ie is this a suppressible
+   error?  If so, return a pointer to the Supp record, otherwise NULL.
    Tries to minimise the number of symbol searches since they are expensive.  
 */
-static CoreSupp* is_suppressible_error ( CoreError* err )
+static Supp* is_suppressible_error ( Error* err )
 {
    Int i;
 
    Char caller_obj[VG_N_SUPP_CALLERS][M_VG_ERRTXT];
    Char caller_fun[VG_N_SUPP_CALLERS][M_VG_ERRTXT];
 
-   CoreSupp* su;
+   Supp* su;
 
    /* get_objname_fnname() writes the function name and object name if
       it finds them in the debug info.  so the strings in the suppression
index 0db3c65c0ce11ff4a5292247a71d50015e258e1f..8b559f19122b0fa49cd07fd48aa9734f2bd72bfd 100644 (file)
@@ -278,6 +278,129 @@ extern void VGP_(done_profiling) ( void );
 #endif
 
 
+/* ---------------------------------------------------------------------
+   Skin-related types
+   ------------------------------------------------------------------ */
+/* These structs are not exposed to skins to mitigate possibility of
+   binary-incompatibilities when the core/skin interface changes.  Instead,
+   set functions are provided (see include/vg_skin.h). */
+typedef
+   struct {
+      Char* name;
+      Char* version;
+      Char* description;
+      Char* copyright_author;
+      Char* bug_reports_to;
+   }
+   VgDetails;
+
+extern VgDetails VG_(details);
+
+/* If new fields are added to this type, update:
+ *  - vg_main.c:initialisation of VG_(needs)
+ *  - vg_main.c:sanity_check_needs()
+ *
+ * If the name of this type or any of its fields change, update:
+ *  - dependent comments (just search for "VG_(needs)"). 
+ */
+typedef
+   struct {
+      Bool libc_freeres;
+      Bool core_errors;
+
+      Bool skin_errors;
+      Bool basic_block_discards;
+      Bool shadow_regs;
+      Bool command_line_options;
+      Bool client_requests;
+      Bool extended_UCode;
+      Bool syscall_wrapper;
+      UInt sizeof_shadow_block;
+      Bool alternative_free;
+      Bool sanity_checks;
+      Bool data_syms;
+   } 
+   VgNeeds;
+
+extern VgNeeds VG_(needs);
+
+/* Events happening in core to track.  To be notified, assign a function
+   to the function pointer.  To ignore an event, don't do anything
+   (default assignment is to NULL in which case the call is skipped). */
+typedef
+   struct {
+      /* Memory events */
+      void (*new_mem_startup)( Addr a, UInt len, Bool rr, Bool ww, Bool xx );
+      void (*new_mem_heap)   ( Addr a, UInt len, Bool is_inited );
+      void (*new_mem_stack)  ( Addr a, UInt len );
+      void (*new_mem_stack_aligned) ( Addr a, UInt len );
+      void (*new_mem_stack_signal)  ( Addr a, UInt len );
+      void (*new_mem_brk)    ( Addr a, UInt len );
+      void (*new_mem_mmap)   ( Addr a, UInt len, Bool rr, Bool ww, Bool xx );
+
+      void (*copy_mem_heap)  ( Addr from, Addr to, UInt len );
+      void (*copy_mem_remap) ( Addr from, Addr to, UInt len );
+      void (*change_mem_mprotect) ( Addr a, UInt len, Bool rr, Bool ww, Bool xx );
+      
+      /* Used on redzones around malloc'd blocks and at end of stack */
+      void (*ban_mem_heap)   ( Addr a, UInt len );
+      void (*ban_mem_stack)  ( Addr a, UInt len );
+
+      void (*die_mem_heap)   ( Addr a, UInt len );
+      void (*die_mem_stack)  ( Addr a, UInt len );
+      void (*die_mem_stack_aligned) ( Addr a, UInt len );
+      void (*die_mem_stack_signal)  ( Addr a, UInt len );
+      void (*die_mem_brk)    ( Addr a, UInt len );
+      void (*die_mem_munmap) ( Addr a, UInt len );
+
+      void (*bad_free)        ( ThreadState* tst, Addr a );
+      void (*mismatched_free) ( ThreadState* tst, Addr a );
+
+      void (*pre_mem_read)   ( CorePart part, ThreadState* tst,
+                               Char* s, Addr a, UInt size );
+      void (*pre_mem_read_asciiz) ( CorePart part, ThreadState* tst,
+                                    Char* s, Addr a );
+      void (*pre_mem_write)  ( CorePart part, ThreadState* tst,
+                               Char* s, Addr a, UInt size );
+      /* Not implemented yet -- have to add in lots of places, which is a
+         pain.  Won't bother unless/until there's a need. */
+      /* void (*post_mem_read)  ( ThreadState* tst, Char* s, 
+                                  Addr a, UInt size ); */
+      void (*post_mem_write) ( Addr a, UInt size );
+
+
+      /* Scheduler events (not exhaustive) */
+      void (*thread_run) ( ThreadId tid );
+
+
+      /* Thread events (not exhaustive) */
+      void (*post_thread_create) ( ThreadId tid, ThreadId child );
+      void (*post_thread_join)   ( ThreadId joiner, ThreadId joinee );
+
+
+      /* Mutex events (not exhaustive) */
+      void (*pre_mutex_lock)    ( ThreadId tid, 
+                                  void* /*pthread_mutex_t* */ mutex );
+      void (*post_mutex_lock)   ( ThreadId tid, 
+                                  void* /*pthread_mutex_t* */ mutex );
+      void (*post_mutex_unlock) ( ThreadId tid, 
+                                  void* /*pthread_mutex_t* */ mutex );
+
+      
+      /* Others... condition variable, signal events... */
+      /* ... */
+   }
+   VgTrackEvents;
+
+extern VgTrackEvents VG_(track_events);
+
+
+/* ---------------------------------------------------------------------
+   Exports of vg_needs.c
+   ------------------------------------------------------------------ */
+
+void VG_(sanity_check_needs)(void);
+
 /* ---------------------------------------------------------------------
    Exports of vg_malloc2.c
    ------------------------------------------------------------------ */
@@ -936,6 +1059,16 @@ extern Int   VG_(disBB)          ( UCodeBlock* cb, Addr eip0 );
    Exports of vg_translate.c
    ------------------------------------------------------------------ */
 
+/* Expandable arrays of uinstrs. */
+struct _UCodeBlock { 
+   Int     used; 
+   Int     size; 
+   UInstr* instrs;
+   Int     nextTemp;
+};
+
+extern UCodeBlock* VG_(alloc_UCodeBlock) ( void );
+
 extern void  VG_(translate)  ( ThreadState* tst,
                                Addr  orig_addr,
                                UInt* orig_size,
@@ -998,23 +1131,29 @@ typedef
    }
    SuppLocTy;
 
-/* Suppressions.  Skin part `SkinSupp' (which is all skins have to deal
-   with) is in vg_skin.h */
-typedef
-   struct _CoreSupp {
-      struct _CoreSupp* next;
-      /* The number of times this error has been suppressed. */
-      Int count;
-      /* The name by which the suppression is referred to. */
-      Char* sname;
-      /* First two (name of fn where err occurs, and immediate caller)
-       * are mandatory;  extra two are optional. */
-      SuppLocTy caller_ty[VG_N_SUPP_CALLERS];
-      Char*     caller   [VG_N_SUPP_CALLERS];
-      /* The skin-specific part */
-      SkinSupp  skin_supp;
-   } 
-   CoreSupp;
+/* Suppressions.  Skins can get/set skin-relevant parts with functions
+   declared in include/vg_skin.h.  Extensible via the 'extra' field. 
+   Skins can use a normal enum (with element values in the normal range
+   (0..)) for `skind'. */
+struct _Supp {
+   struct _Supp* next;
+   /* The number of times this error has been suppressed. */
+   Int count;
+   /* The name by which the suppression is referred to. */
+   Char* sname;
+   /* First two (name of fn where err occurs, and immediate caller)
+    * are mandatory;  extra two are optional. */
+   SuppLocTy caller_ty[VG_N_SUPP_CALLERS];
+   Char*     caller   [VG_N_SUPP_CALLERS];
+
+   /* The skin-specific part */
+   /* What kind of suppression.  Must use the range (0..) */
+   SuppKind skind;
+   /* String -- use is optional.  NULL by default. */
+   Char* string;
+   /* Anything else -- use is optional.  NULL by default. */
+   void* extra;
+};
 
 /* Note: it is imperative this doesn't overlap with (0..) at all, as skins
  * effectively extend it by defining their own enums in the (0..) range. */
@@ -1024,27 +1163,40 @@ typedef
    }
    CoreErrorKind;
 
-/* Errors.  Skin part `SkinError' (which is all skins have to deal
-   with) is in vg_skin.h */
-typedef
-   struct _CoreErrContext {
-      struct _CoreErrContext* next;
-      /* NULL if unsuppressed; or ptr to suppression record. */
-      CoreSupp* supp;
-      Int count;
-      ExeContext* where;
-      ThreadId tid;
-      /* These record %EIP, %ESP and %EBP at the error point.  They
-         are only used to make GDB-attaching convenient; there is no
-         other purpose; specifically they are not used to do
-         comparisons between errors. */
-      UInt m_eip;
-      UInt m_esp;
-      UInt m_ebp;
-      /* The skin-specific part */
-      SkinError skin_err;
-   } 
-   CoreError;
+/* Errors.  Extensible (via the 'extra' field).  Skins can use a normal
+   enum (with element values in the normal range (0..)) for `ekind'. 
+   Functions for getting/setting the skin-relevant fields are in
+   include/vg_skin.h.
+
+   When errors are found and recorded with VG_(maybe_record_error)(), all
+   the skin must do is pass in the four parameters;  core will
+   allocate/initialise the error record.
+*/
+struct _Error {
+   struct _Error* next;
+   /* NULL if unsuppressed; or ptr to suppression record. */
+   Supp* supp;
+   Int count;
+   ExeContext* where;
+   ThreadId tid;
+   /* These record %EIP, %ESP and %EBP at the error point.  They
+      are only used to make GDB-attaching convenient; there is no
+      other purpose; specifically they are not used to do
+      comparisons between errors. */
+   UInt m_eip;
+   UInt m_esp;
+   UInt m_ebp;
+
+   /* The skin-specific part */
+   /* Used by ALL.  Must be in the range (0..) */
+   Int ekind;
+   /* Used frequently */
+   Addr addr;
+   /* Used frequently */
+   Char* string;
+   /* For any skin-specific extras */
+   void* extra;
+};
 
 
 extern void VG_(load_suppressions)    ( void );
@@ -1087,6 +1239,26 @@ extern void VG_(mini_stack_dump)      ( ExeContext* ec );
    Exports of vg_clientmalloc.c
    ------------------------------------------------------------------ */
 
+typedef
+   enum { 
+      Vg_AllocMalloc = 0,
+      Vg_AllocNew    = 1,
+      Vg_AllocNewVec = 2 
+   }
+   VgAllocKind;
+
+/* Description of a malloc'd chunk.  Functions for extracting skin-relevant
+   parts are in include/vg_skin.h Size of skin_extra array is given by
+   VG_(needs).sizeof_shadow_chunk. */
+struct _ShadowChunk {
+   struct _ShadowChunk* next;
+   UInt          size : 30;      /* size requested                   */
+   VgAllocKind   allockind : 2;  /* which wrapper did the allocation */
+   Addr          data;           /* ptr to actual block              */
+   UInt          extra[0];       /* extra skin-specific info         */
+};
+
+
 extern void  VG_(client_malloc_init)();
 
 /* These are called from the scheduler, when it intercepts a user
index 900d3e17e91aeed8942f5450c21ffa92f0fb972d..163b64b5edbef718488c8efe4f8d1b2978ca7531 100644 (file)
@@ -443,94 +443,6 @@ UInt VG_(num_scheduling_events_MINOR) = 0;
 UInt VG_(num_scheduling_events_MAJOR) = 0;
 
 
-/* ---------------------------------------------------------------------
-   Skin data structure initialisation
-   ------------------------------------------------------------------ */
-
-/* Init with default values. */
-VgDetails VG_(details) = {
-   .name             = NULL,
-   .version          = NULL,
-   .description      = NULL,
-   .copyright_author = NULL,
-   .bug_reports_to   = NULL,
-};
-
-VgNeeds VG_(needs) = {
-   .core_errors          = False,
-   .skin_errors          = False,
-   .libc_freeres         = False,
-   .sizeof_shadow_block  = 0,
-   .basic_block_discards = False,
-   .shadow_regs          = False,
-   .command_line_options = False,
-   .client_requests      = False,
-   .extended_UCode       = False,
-   .syscall_wrapper      = False,
-   .alternative_free     = False,
-   .sanity_checks        = False,
-   .data_syms           = False,
-};
-
-VgTrackEvents VG_(track_events) = {
-   /* Memory events */
-   .new_mem_startup       = NULL,
-   .new_mem_heap          = NULL,
-   .new_mem_stack         = NULL,
-   .new_mem_stack_aligned = NULL,
-   .new_mem_stack_signal  = NULL,
-   .new_mem_brk           = NULL,
-   .new_mem_mmap          = NULL,
-
-   .copy_mem_heap         = NULL,
-   .copy_mem_remap        = NULL,
-   .change_mem_mprotect   = NULL,
-
-   .ban_mem_heap          = NULL,
-   .ban_mem_stack         = NULL,
-
-   .die_mem_heap          = NULL,
-   .die_mem_stack         = NULL,
-   .die_mem_stack_aligned = NULL,
-   .die_mem_stack_signal  = NULL,
-   .die_mem_brk           = NULL,
-   .die_mem_munmap        = NULL,
-
-   .bad_free              = NULL,
-   .mismatched_free       = NULL,
-
-   .pre_mem_read          = NULL,
-   .pre_mem_read_asciiz   = NULL,
-   .pre_mem_write         = NULL,
-   .post_mem_write        = NULL,
-
-   /* Scheduler events */
-   .thread_run            = NULL,
-
-   /* Mutex events */
-   .post_mutex_lock       = NULL,
-   .post_mutex_unlock     = NULL,
-};
-
-static void sanity_check_needs ( void )
-{
-#define CHECK_NOT(var, value)                               \
-   if ((var)==(value)) {                                    \
-      VG_(printf)("\nSkin error: `%s' not initialised\n",   \
-                  VG__STRING(var));                         \
-      VG_(skin_panic)("Uninitialised needs field\n");       \
-   }
-   
-   CHECK_NOT(VG_(details).name,             NULL);
-   /* Nb: .version can be NULL */
-   CHECK_NOT(VG_(details).description,      NULL);
-   CHECK_NOT(VG_(details).copyright_author, NULL);
-   CHECK_NOT(VG_(details).bug_reports_to,   NULL);
-
-#undef CHECK_NOT
-#undef INVALID_Bool
-}
-
 /* ---------------------------------------------------------------------
    Values derived from command-line options.
    ------------------------------------------------------------------ */
@@ -1350,8 +1262,8 @@ void VG_(main) ( void )
         and turn on/off 'command_line_options' need
       - init_memory() (to setup memory event trackers).
     */
-   SK_(pre_clo_init) ( & VG_(details), & VG_(needs), & VG_(track_events) );
-   sanity_check_needs();
+   SK_(pre_clo_init)();
+   VG_(sanity_check_needs)();
 
    /* Process Valgrind's command-line opts (from env var VG_ARGS). */
    process_cmd_line_options();
diff --git a/coregrind/vg_needs.c b/coregrind/vg_needs.c
new file mode 100644 (file)
index 0000000..5abeffd
--- /dev/null
@@ -0,0 +1,337 @@
+
+/*--------------------------------------------------------------------*/
+/*--- Stuff relating to skin data structures.                      ---*/
+/*---                                                   vg_needs.c ---*/
+/*--------------------------------------------------------------------*/
+
+/*
+   This file is part of Valgrind, an extensible x86 protected-mode
+   emulator for monitoring program execution on x86-Unixes.
+
+   Copyright (C) 2000-2002 Nicholas Nethercote
+      jseward@acm.org
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307, USA.
+
+   The GNU General Public License is contained in the file COPYING.
+*/
+
+#include "vg_include.h"
+
+
+/* ---------------------------------------------------------------------
+   Skin data structure initialisation
+   ------------------------------------------------------------------ */
+
+/* Init with default values. */
+VgDetails VG_(details) = {
+   .name             = NULL,
+   .version          = NULL,
+   .description      = NULL,
+   .copyright_author = NULL,
+   .bug_reports_to   = NULL,
+};
+
+VgNeeds VG_(needs) = {
+   .core_errors          = False,
+   .skin_errors          = False,
+   .libc_freeres         = False,
+   .sizeof_shadow_block  = 0,
+   .basic_block_discards = False,
+   .shadow_regs          = False,
+   .command_line_options = False,
+   .client_requests      = False,
+   .extended_UCode       = False,
+   .syscall_wrapper      = False,
+   .alternative_free     = False,
+   .sanity_checks        = False,
+   .data_syms           = False,
+};
+
+VgTrackEvents VG_(track_events) = {
+   /* Memory events */
+   .new_mem_startup       = NULL,
+   .new_mem_heap          = NULL,
+   .new_mem_stack         = NULL,
+   .new_mem_stack_aligned = NULL,
+   .new_mem_stack_signal  = NULL,
+   .new_mem_brk           = NULL,
+   .new_mem_mmap          = NULL,
+
+   .copy_mem_heap         = NULL,
+   .copy_mem_remap        = NULL,
+   .change_mem_mprotect   = NULL,
+
+   .ban_mem_heap          = NULL,
+   .ban_mem_stack         = NULL,
+
+   .die_mem_heap          = NULL,
+   .die_mem_stack         = NULL,
+   .die_mem_stack_aligned = NULL,
+   .die_mem_stack_signal  = NULL,
+   .die_mem_brk           = NULL,
+   .die_mem_munmap        = NULL,
+
+   .bad_free              = NULL,
+   .mismatched_free       = NULL,
+
+   .pre_mem_read          = NULL,
+   .pre_mem_read_asciiz   = NULL,
+   .pre_mem_write         = NULL,
+   .post_mem_write        = NULL,
+
+   /* Scheduler events */
+   .thread_run            = NULL,
+
+   /* Mutex events */
+   .post_mutex_lock       = NULL,
+   .post_mutex_unlock     = NULL,
+};
+
+/* static */
+void VG_(sanity_check_needs) ( void)
+{
+#define CHECK_NOT(var, value)                               \
+   if ((var)==(value)) {                                    \
+      VG_(printf)("\nSkin error: `%s' not initialised\n",   \
+                  VG__STRING(var));                         \
+      VG_(skin_panic)("Uninitialised needs field\n");       \
+   }
+   
+   CHECK_NOT(VG_(details).name,             NULL);
+   /* Nb: .version can be NULL */
+   CHECK_NOT(VG_(details).description,      NULL);
+   CHECK_NOT(VG_(details).copyright_author, NULL);
+   CHECK_NOT(VG_(details).bug_reports_to,   NULL);
+
+#undef CHECK_NOT
+#undef INVALID_Bool
+}
+
+/*--------------------------------------------------------------------*/
+/* Setting details */
+
+/* Use macro because they're so repetitive */
+#define DETAILS(detail)  \
+   extern void VG_(details_##detail)(Char* detail) \
+   {                                   \
+      VG_(details).detail = detail;          \
+   }
+
+DETAILS(name)
+DETAILS(version)
+DETAILS(description)
+DETAILS(copyright_author)
+DETAILS(bug_reports_to)
+
+/*--------------------------------------------------------------------*/
+/* Setting needs */
+
+/* Use macro because they're so repetitive */
+#define NEEDS(need)  \
+   extern void VG_(needs_##need)(void) \
+   {                                   \
+      VG_(needs).need = True;          \
+   }
+
+NEEDS(libc_freeres)
+NEEDS(core_errors)
+NEEDS(skin_errors)
+NEEDS(basic_block_discards)
+NEEDS(shadow_regs)
+NEEDS(command_line_options)
+NEEDS(client_requests)
+NEEDS(extended_UCode)
+NEEDS(syscall_wrapper)
+
+extern void VG_(needs_sizeof_shadow_block)(Int size)
+{
+   VG_(needs).sizeof_shadow_block = size;
+}
+
+NEEDS(alternative_free)
+NEEDS(sanity_checks)
+NEEDS(data_syms)
+
+/*--------------------------------------------------------------------*/
+#define TRACK(event, args...)  \
+   void VG_(track_##event)(void (*f)(args)) \
+   {                                      \
+      VG_(track_events).event = f;        \
+   }
+
+TRACK(new_mem_startup,       Addr a, UInt len, Bool rr, Bool ww, Bool xx)
+TRACK(new_mem_heap,          Addr a, UInt len, Bool is_inited)
+TRACK(new_mem_stack,         Addr a, UInt len)
+TRACK(new_mem_stack_aligned, Addr a, UInt len)
+TRACK(new_mem_stack_signal,  Addr a, UInt len)
+TRACK(new_mem_brk,           Addr a, UInt len)
+TRACK(new_mem_mmap,          Addr a, UInt len, Bool rr, Bool ww, Bool xx)
+
+TRACK(copy_mem_heap,       Addr from, Addr to, UInt len)
+TRACK(copy_mem_remap,      Addr from, Addr to, UInt len)
+TRACK(change_mem_mprotect, Addr a, UInt len, Bool rr, Bool ww, Bool xx)
+
+TRACK(ban_mem_heap,  Addr a, UInt len)
+TRACK(ban_mem_stack, Addr a, UInt len)
+
+TRACK(die_mem_heap,          Addr a, UInt len)
+TRACK(die_mem_stack,         Addr a, UInt len)
+TRACK(die_mem_stack_aligned, Addr a, UInt len)
+TRACK(die_mem_stack_signal,  Addr a, UInt len)
+TRACK(die_mem_brk,           Addr a, UInt len)
+TRACK(die_mem_munmap,        Addr a, UInt len)
+
+TRACK(bad_free,        ThreadState* tst, Addr a)
+TRACK(mismatched_free, ThreadState* tst, Addr a)
+
+TRACK(pre_mem_read,        CorePart part, ThreadState* tst, Char* s, Addr a,
+                           UInt size)
+TRACK(pre_mem_read_asciiz, CorePart part, ThreadState* tst, Char* s, Addr a)
+TRACK(pre_mem_write,       CorePart part, ThreadState* tst, Char* s, Addr a,
+                           UInt size)
+TRACK(post_mem_write,      Addr a, UInt size)
+
+TRACK(thread_run, ThreadId tid)
+
+TRACK(post_thread_create, ThreadId tid, ThreadId child)
+TRACK(post_thread_join,   ThreadId joiner, ThreadId joinee)
+
+TRACK( pre_mutex_lock,   ThreadId tid, void* /*pthread_mutex_t* */ mutex)
+TRACK(post_mutex_lock,   ThreadId tid, void* /*pthread_mutex_t* */ mutex)
+TRACK(post_mutex_unlock, ThreadId tid, void* /*pthread_mutex_t* */ mutex)
+
+/*--------------------------------------------------------------------*/
+/* UCodeBlocks */
+
+Int VG_(get_num_instrs) ( UCodeBlock* cb )
+{
+   return cb->used;
+}
+
+Int VG_(get_num_temps) ( UCodeBlock* cb )
+{
+   return cb->nextTemp;
+}
+
+UInstr* VG_(get_instr) ( UCodeBlock* cb, Int i )
+{
+   return & cb->instrs[i];
+}
+
+UInstr* VG_(get_last_instr) ( UCodeBlock* cb )
+{
+   return & cb->instrs[cb->used-1];
+}
+   
+/*--------------------------------------------------------------------*/
+/* Suppressions */
+
+SuppKind VG_(get_supp_kind) ( Supp* su )
+{
+   return su->skind;
+}
+
+Char* VG_(get_supp_string) ( Supp* su )
+{
+   return su->string;
+}
+
+void* VG_(get_supp_extra)  ( Supp* su )
+{
+   return su->extra;
+}
+
+
+void VG_(set_supp_kind)   ( Supp* su, SuppKind skind )
+{
+   su->skind = skind;
+}
+
+void VG_(set_supp_string) ( Supp* su, Char* string )
+{
+   su->string = string;
+}
+
+void VG_(set_supp_extra)  ( Supp* su, void* extra )
+{
+   su->extra = extra;
+}
+
+/*--------------------------------------------------------------------*/
+/* Errors */
+
+ErrorKind VG_(get_error_kind) ( Error* err )
+{
+   return err->ekind;
+}
+
+Addr VG_(get_error_address) ( Error* err )
+{
+   return err->addr;
+}
+
+Char* VG_(get_error_string) ( Error* err )
+{
+   return err->string;
+}
+
+void* VG_(get_error_extra)  ( Error* err )
+{
+   return err->extra;
+}
+
+/*--------------------------------------------------------------------*/
+/* ShadowChunks */
+
+UInt VG_(get_sc_size)  ( ShadowChunk* sc )
+{
+   return sc->size;
+}
+
+Addr VG_(get_sc_data)  ( ShadowChunk* sc )
+{
+   return sc->data;
+}
+
+UInt VG_(get_sc_extra) ( ShadowChunk* sc, UInt i )
+{
+   vg_assert(i < VG_(needs).sizeof_shadow_block);
+   return sc->extra[i];
+}
+
+ShadowChunk* VG_(get_sc_next)  ( ShadowChunk* sc )
+{
+   return sc->next;
+}
+
+void VG_(set_sc_extra) ( ShadowChunk* sc, UInt i, UInt word )
+{
+   vg_assert(i < VG_(needs).sizeof_shadow_block);
+   sc->extra[i] = word;
+}
+
+void VG_(set_sc_next)  ( ShadowChunk* sc, ShadowChunk* next )
+{
+   sc->next = next;
+}
+
+
+/*--------------------------------------------------------------------*/
+/*--- end                                               vg_needs.c ---*/
+/*--------------------------------------------------------------------*/
+
+
index 99bf7b124b2b8a4a035f1c5faaadac6ca52dfaea..601b2ee4a986f89e68d0403a6567422e94fb5288 100644 (file)
@@ -236,19 +236,6 @@ __inline__ static UInt getSDisp ( Int size, Addr eip )
 /*--- Flag-related helpers.                                ---*/
 /*------------------------------------------------------------*/
 
-/* For the last uinsn inserted into cb, set the read, written and
-   undefined flags.  Undefined flags are counted as written, but it
-   seems worthwhile to distinguish them. 
-*/
-static __inline__ void uFlagsRWU ( UCodeBlock* cb,
-                                   FlagSet rr, FlagSet ww, FlagSet uu )
-{
-   VG_(set_flag_RW)(
-      &LAST_UINSTR(cb), rr, VG_UNION_FLAG_SETS(ww,uu)
-   );
-}
-
-
 static void setFlagsFromUOpcode ( UCodeBlock* cb, Int uopc )
 {
    switch (uopc) {
@@ -275,7 +262,8 @@ static void setFlagsFromUOpcode ( UCodeBlock* cb, Int uopc )
    }
 }
 
-static __inline__ void uCond ( UCodeBlock* cb, Condcode cond )
+__inline__
+void VG_(set_cond_field) ( UCodeBlock* cb, Condcode cond )
 {
    LAST_UINSTR(cb).cond = cond;
 }
index 0b6175ab216b505497ffba499d94dca227147b78..8f5ac3d2b07ee0c85df42e78882b740f5d96d151 100644 (file)
@@ -42,6 +42,7 @@
 /*--- Basics                                               ---*/
 /*------------------------------------------------------------*/
 
+/* This one is called by the core */
 UCodeBlock* VG_(alloc_UCodeBlock) ( void )
 {
    UCodeBlock* cb = VG_(arena_malloc)(VG_AR_CORE, sizeof(UCodeBlock));
@@ -50,6 +51,15 @@ UCodeBlock* VG_(alloc_UCodeBlock) ( void )
    return cb;
 }
 
+/* This one is called by skins */
+UCodeBlock* VG_(setup_UCodeBlock) ( UCodeBlock* cb_in )
+{
+   UCodeBlock* cb = VG_(arena_malloc)(VG_AR_CORE, sizeof(UCodeBlock));
+   cb->used = cb->size = 0;
+   cb->nextTemp = cb_in->nextTemp;
+   cb->instrs = NULL;
+   return cb;
+}
 
 void VG_(free_UCodeBlock) ( UCodeBlock* cb )
 {
@@ -205,17 +215,6 @@ void copyAuxInfoFromTo ( UInstr* src, UInstr* dst )
 }
 
 
-/* Set the flag R/W sets on a uinstr. */
-void VG_(set_flag_RW) ( UInstr* u, FlagSet fr, FlagSet fw )
-{
-   /* VG_(pp_UInstr)(-1,u); */
-   vg_assert(fr == (fr & FlagsALL));
-   vg_assert(fw == (fw & FlagsALL));
-   u->flags_r = fr;
-   u->flags_w = fw;
-}
-
-
 /* Set the lit32 field of the most recent uinsn. */
 void VG_(set_lit_field) ( UCodeBlock* cb, UInt lit32 )
 {
@@ -235,6 +234,23 @@ void  VG_(set_ccall_fields) ( UCodeBlock* cb, Addr fn, UChar argc, UChar
    LAST_UINSTR(cb).has_ret_val = has_ret_val;
 }
 
+/* For the last uinsn inserted into cb, set the read, written and
+   undefined flags.  Undefined flags are counted as written, but it
+   seems worthwhile to distinguish them. 
+*/
+__inline__
+void VG_(set_flag_fields) ( UCodeBlock* cb,
+                             FlagSet rr, FlagSet ww, FlagSet uu )
+{
+   FlagSet uw = VG_UNION_FLAG_SETS(ww,uu);
+   
+   vg_assert(rr == (rr & FlagsALL));
+   vg_assert(uw == (uw & FlagsALL));
+   LAST_UINSTR(cb).flags_r = rr;
+   LAST_UINSTR(cb).flags_w = uw;
+}
+
+
 Bool VG_(any_flag_use) ( UInstr* u )
 {
    return (u->flags_r != FlagsEmpty 
@@ -1075,18 +1091,18 @@ void VG_(pp_UCodeBlock) ( UCodeBlock* cb, Char* title )
 /*------------------------------------------------------------*/
 
 /* Get the temp/reg use of a uinstr, parking them in an array supplied by
-   the caller, which is assumed to be big enough.  Return the number
-   of entries.  Insns which read _and_ write a register wind up
-   mentioning it twice.  Entries are placed in the array in program
-   order, so that if a reg is read-modified-written, it appears first
-   as a read and then as a write.  'tag' indicates whether we are looking at
-   TempRegs or RealRegs.
+   the caller (regs), which is assumed to be big enough.  Return the number
+   of entries.  Written regs are indicated in parallel array isWrites.
+   Insns which read _and_ write a register wind up mentioning it twice.
+   Entries are placed in the array in program order, so that if a reg is
+   read-modified-written, it appears first as a read and then as a write.
+   'tag' indicates whether we are looking at TempRegs or RealRegs.
 */
 __inline__
-Int VG_(get_reg_usage) ( UInstr* u, Tag tag, RegUse* arr )
+Int VG_(get_reg_usage) ( UInstr* u, Tag tag, Int* regs, Bool* isWrites )
 {
-#  define RD(ono)    VG_UINSTR_READS_REG(ono)
-#  define WR(ono)    VG_UINSTR_WRITES_REG(ono)
+#  define RD(ono)    VG_UINSTR_READS_REG(ono, regs, isWrites)
+#  define WR(ono)    VG_UINSTR_WRITES_REG(ono, regs, isWrites)
 
    Int n = 0;
    switch (u->opcode) {
@@ -1142,7 +1158,7 @@ Int VG_(get_reg_usage) ( UInstr* u, Tag tag, RegUse* arr )
 
       default:
          if (VG_(needs).extended_UCode)
-            return SK_(get_Xreg_usage)(u, tag, arr);
+            return SK_(get_Xreg_usage)(u, tag, regs, isWrites);
          else {
             VG_(printf)("unhandled opcode: %u.  Perhaps " 
                         "VG_(needs).extended_UCode should be set?",
@@ -1160,26 +1176,26 @@ Int VG_(get_reg_usage) ( UInstr* u, Tag tag, RegUse* arr )
 /* Change temp regs in u into real regs, as directed by the
  * temps[i]-->reals[i] mapping. */
 static __inline__
-void patchUInstr ( UInstr* u, RegUse temps[], UInt reals[], Int n_tmap )
+void patchUInstr ( UInstr* u, Int temps[], UInt reals[], Int n_tmap )
 {
    Int i;
    if (u->tag1 == TempReg) {
       for (i = 0; i < n_tmap; i++)
-         if (temps[i].num == u->val1) break;
+         if (temps[i] == u->val1) break;
       if (i == n_tmap) VG_(core_panic)("patchUInstr(1)");
       u->tag1 = RealReg;
       u->val1 = reals[i];
    }
    if (u->tag2 == TempReg) {
       for (i = 0; i < n_tmap; i++)
-         if (temps[i].num == u->val2) break;
+         if (temps[i] == u->val2) break;
       if (i == n_tmap) VG_(core_panic)("patchUInstr(2)");
       u->tag2 = RealReg;
       u->val2 = reals[i];
    }
    if (u->tag3 == TempReg) {
       for (i = 0; i < n_tmap; i++)
-         if (temps[i].num == u->val3) break;
+         if (temps[i] == u->val3) break;
       if (i == n_tmap) VG_(core_panic)("patchUInstr(3)");
       u->tag3 = RealReg;
       u->val3 = reals[i];
@@ -1255,10 +1271,12 @@ static __inline__
 Bool uInstrMentionsTempReg ( UInstr* u, Int tempreg )
 {
    Int i, k;
-   RegUse tempUse[3];
-   k = VG_(get_reg_usage) ( u, TempReg, &tempUse[0] );
+   Int tempUse[3];
+   Bool notUsed[3];
+
+   k = VG_(get_reg_usage) ( u, TempReg, &tempUse[0], &notUsed[0] );
    for (i = 0; i < k; i++)
-      if (tempUse[i].num == tempreg)
+      if (tempUse[i] == tempreg)
          return True;
    return False;
 }
@@ -1280,7 +1298,8 @@ static void vg_improve ( UCodeBlock* cb )
    Int     i, j, k, m, n, ar, tr, told, actual_areg;
    Int     areg_map[8];
    Bool    annul_put[8];
-   RegUse  tempUse[3];
+   Int     tempUse[3];
+   Bool    isWrites[3];
    UInstr* u;
    Bool    wr;
    Int*    last_live_before;
@@ -1307,12 +1326,12 @@ static void vg_improve ( UCodeBlock* cb )
    for (i = cb->used-1; i >= 0; i--) {
       u = &cb->instrs[i];
 
-      k = VG_(get_reg_usage)(u, TempReg, &tempUse[0]);
+      k = VG_(get_reg_usage)(u, TempReg, &tempUse[0], &isWrites[0]);
 
       /* For each temp usage ... bwds in program order. */
       for (j = k-1; j >= 0; j--) {
-         tr = tempUse[j].num;
-         wr = tempUse[j].isWrite;
+         tr = tempUse[j];
+         wr = isWrites[j];
          if (last_live_before[tr] == -1) {
             vg_assert(tr >= 0 && tr < cb->nextTemp);
             last_live_before[tr] = wr ? (i+1) : i;
@@ -1413,12 +1432,12 @@ static void vg_improve ( UCodeBlock* cb )
          }
 
          /* boring insn; invalidate any mappings to temps it writes */
-         k = VG_(get_reg_usage)(u, TempReg, &tempUse[0]);
+         k = VG_(get_reg_usage)(u, TempReg, &tempUse[0], &isWrites[0]);
 
          for (j = 0; j < k; j++) {
-            wr  = tempUse[j].isWrite;
+            wr  = isWrites[j];
             if (!wr) continue;
-            tr = tempUse[j].num;
+            tr = tempUse[j];
             for (m = 0; m < 8; m++)
                if (areg_map[m] == tr) areg_map[m] = -1;
          }
@@ -1621,7 +1640,8 @@ UCodeBlock* vg_do_register_allocation ( UCodeBlock* c1 )
    Int          i, j, k, m, r, tno, max_ss_no;
    Bool         wr, defer, isRead, spill_reqd;
    UInt         realUse[3];
-   RegUse       tempUse[3];
+   Int          tempUse[3];
+   Bool         isWrites[3];
    UCodeBlock*  c2;
 
    /* Used to denote ... well, "no value" in this fn. */
@@ -1646,13 +1666,14 @@ UCodeBlock* vg_do_register_allocation ( UCodeBlock* c1 )
    /* Scan fwds to establish live ranges. */
 
    for (i = 0; i < c1->used; i++) {
-      k = VG_(get_reg_usage)(&c1->instrs[i], TempReg, &tempUse[0]);
+      k = VG_(get_reg_usage)(&c1->instrs[i], TempReg, &tempUse[0],
+                             &isWrites[0]);
       vg_assert(k >= 0 && k <= 3);
 
       /* For each temp usage ... fwds in program order */
       for (j = 0; j < k; j++) {
-         tno = tempUse[j].num;
-         wr  = tempUse[j].isWrite;
+         tno = tempUse[j];
+         wr  = isWrites[j];
          if (wr) {
             /* Writes hold a reg live until after this insn. */
             if (temp_info[tno].live_after == VG_NOTHING)
@@ -1781,7 +1802,8 @@ UCodeBlock* vg_do_register_allocation ( UCodeBlock* c1 )
          generate spill stores since we may have to evict some TempRegs
          currently in real regs.  Also generates spill loads. */
 
-      k = VG_(get_reg_usage)(&c1->instrs[i], TempReg, &tempUse[0]);
+      k = VG_(get_reg_usage)(&c1->instrs[i], TempReg, &tempUse[0],
+                             &isWrites[0]);
       vg_assert(k >= 0 && k <= 3);
 
       /* For each ***different*** temp mentioned in the insn .... */
@@ -1792,14 +1814,14 @@ UCodeBlock* vg_do_register_allocation ( UCodeBlock* c1 )
             used by the insn once, even if it is mentioned more than
             once. */
          defer = False;
-         tno = tempUse[j].num;
+         tno = tempUse[j];
          for (m = j+1; m < k; m++)
-            if (tempUse[m].num == tno) 
+            if (tempUse[m] == tno) 
                defer = True;
          if (defer) 
             continue;
 
-         /* Now we're trying to find a register for tempUse[j].num.
+         /* Now we're trying to find a register for tempUse[j].
             First of all, if it already has a register assigned, we
             don't need to do anything more. */
          if (temp_info[tno].real_no != VG_NOTHING)
@@ -1825,7 +1847,7 @@ UCodeBlock* vg_do_register_allocation ( UCodeBlock* c1 )
 
             Select r in 0 .. VG_MAX_REALREGS-1 such that
             real_to_temp[r] is not mentioned in 
-            tempUse[0 .. k-1].num, since it would be just plain 
+            tempUse[0 .. k-1], since it would be just plain 
             wrong to eject some other TempReg which we need to use in 
             this insn.
 
@@ -1836,7 +1858,7 @@ UCodeBlock* vg_do_register_allocation ( UCodeBlock* c1 )
          for (r = 0; r < VG_MAX_REALREGS; r++) {
             is_spill_cand[r] = True;
             for (m = 0; m < k; m++) {
-               if (real_to_temp[r] == tempUse[m].num) {
+               if (real_to_temp[r] == tempUse[m]) {
                   is_spill_cand[r] = False;
                   break;
                }
@@ -1898,7 +1920,7 @@ UCodeBlock* vg_do_register_allocation ( UCodeBlock* c1 )
          /* Decide if tno is read. */
          isRead = False;
          for (m = 0; m < k; m++)
-            if (tempUse[m].num == tno && !tempUse[m].isWrite
+            if (tempUse[m] == tno && !isWrites[m]
                isRead = True;
 
          /* If so, generate a spill load. */
@@ -1922,7 +1944,7 @@ UCodeBlock* vg_do_register_allocation ( UCodeBlock* c1 )
          and use patchUInstr to convert its rTempRegs into
          realregs. */
       for (j = 0; j < k; j++)
-         realUse[j] = VG_(rank_to_realreg)(temp_info[tempUse[j].num].real_no);
+         realUse[j] = VG_(rank_to_realreg)(temp_info[tempUse[j]].real_no);
       VG_(copy_UInstr)(c2, &c1->instrs[i]);
       patchUInstr(&LAST_UINSTR(c2), &tempUse[0], &realUse[0], k);
 
@@ -1951,7 +1973,8 @@ static void vg_realreg_liveness_analysis ( UCodeBlock* cb )
 {        
    Int      i, j, k;
    RRegSet  rregs_live;
-   RegUse   regUse[3];
+   Int      regUse[3];
+   Bool     isWrites[3];
    UInstr*  u;
 
    /* All regs are dead at the end of the block */
@@ -1962,16 +1985,16 @@ static void vg_realreg_liveness_analysis ( UCodeBlock* cb )
 
       u->regs_live_after = rregs_live;
 
-      k = VG_(get_reg_usage)(u, RealReg, regUse);
+      k = VG_(get_reg_usage)(u, RealReg, &regUse[0], &isWrites[0]);
 
       /* For each reg usage ... bwds in program order.  Variable is live
          before this UInstr if it is read by this UInstr.
-         Note that regUse[j].num holds the Intel reg number, so we must
+         Note that regUse[j] holds the Intel reg number, so we must
          convert it to our rank number.  */
       for (j = k-1; j >= 0; j--) {
-         SET_RREG_LIVENESS ( VG_(realreg_to_rank)(regUse[j].num),
+         SET_RREG_LIVENESS ( VG_(realreg_to_rank)(regUse[j]),
                              rregs_live,
-                             !regUse[j].isWrite );
+                             !isWrites[j] );
       }
    }
 }
index 281d9803507e44c63f710510575176329a7b5e94..89cd2312191d07c85a568da2b6f6e12368b5252a 100644 (file)
@@ -9,12 +9,12 @@ VG_DETERMINE_INTERFACE_VERSION
 
 void SK_(pre_clo_init)(VgDetails* details, VgNeeds* needs, VgTrackEvents* track)
 {
-   details->name             = "Example";
-   details->version          = "0.0.1";
-   details->description      = "an example Valgrind skin";
-   details->copyright_author =
-      "Copyright (C) 2002, and put in the public domain, by Santa Claus.";
-   details->bug_reports_to   = "santa.claus@northpole.org";
+   VG_(details_name)            ("Example");
+   VG_(details_version)         ("0.0.1");
+   VG_(details_description)     ("an example Valgrind skin");
+   VG_(details_copyright_author)(
+      "Copyright (C) 2002, and put in the public domain, by Santa Claus.");
+   VG_(details_bug_reports_to)  ("santa.claus@northpole.org");
 
    /* No needs, no core events to track */
 }
index b7a849a5faefef7541a747891a66942a82f028bc..f9ed3a0f7d23b1f8ff6b7bc4327633a86d1f34ef 100644 (file)
@@ -1292,33 +1292,33 @@ static const LockSet *ls_union(const LockSet *a, const LockSet *b)
 #define SHADOW_EXTRA   2
 
 static __inline__
-void set_sc_where( ShadowChunk* sc, ExeContext* ec )
+ExeContext *get_sc_where( ShadowChunk* sc )
 {
-   sc->skin_extra[0] = (UInt)ec;
+   return (ExeContext*)VG_(get_sc_extra)(sc, 0);
 }
 
 static __inline__
-ExeContext *get_sc_where( ShadowChunk* sc )
+ThreadId get_sc_tid(ShadowChunk *sc)
 {
-   return (ExeContext*)sc->skin_extra[0];
+   return (ThreadId)VG_(get_sc_extra)(sc, 1);
 }
 
 static __inline__
-void set_sc_tid(ShadowChunk *sc, ThreadId tid)
+void set_sc_where( ShadowChunk* sc, ExeContext* ec )
 {
-   sc->skin_extra[1] = (UInt)tid;
+   VG_(set_sc_extra)(sc, 0, (UInt)ec);
 }
 
 static __inline__
-ThreadId get_sc_tid(ShadowChunk *sc)
+void set_sc_tid( ShadowChunk* sc, ThreadId tid )
 {
-   return (ThreadId)sc->skin_extra[1];
+   VG_(set_sc_extra)(sc, 1, (UInt)tid);
 }
 
 void SK_(complete_shadow_chunk) ( ShadowChunk* sc, ThreadState* tst )
 {
-   set_sc_where( sc, VG_(get_ExeContext) ( tst ) );
-   set_sc_tid(sc, VG_(get_tid_from_ThreadState(tst)));
+   set_sc_where ( sc, VG_(get_ExeContext)(tst) );
+   set_sc_tid   ( sc, VG_(get_tid_from_ThreadState)(tst) );
 }
 
 /*------------------------------------------------------------*/
@@ -1439,8 +1439,8 @@ static ShadowChunk *freechunks[N_FREED_CHUNKS];
 void SK_(alt_free) ( ShadowChunk* sc, ThreadState* tst )
 {
    ThreadId tid = VG_(get_tid_from_ThreadState)(tst);
-   Addr start = sc->data;
-   Addr end = start + sc->size;
+   Addr start = VG_(get_sc_data)(sc);
+   Addr end = start + VG_(get_sc_size)(sc);
 
    Bool deadmx(Mutex *mx) {
       if (mx->state != MxDead)
@@ -1913,19 +1913,18 @@ UCodeBlock* SK_(instrument) ( UCodeBlock* cb_in, Addr not_used )
    Bool               *stackref = NULL;
    Bool        locked = False; /* lock prefix */
 
-   cb = VG_(alloc_UCodeBlock)();
-   cb->nextTemp = cb_in->nextTemp;
+   cb = VG_(setup_UCodeBlock)(cb_in);
 
    /* stackref[] is used for super-simple value tracking to keep note
       of which tempregs currently hold a value which is derived from
       ESP or EBP, and is therefore likely stack-relative if used as
       the address for LOAD or STORE. */
-   ntemps = cb->nextTemp;
+   ntemps = VG_(get_num_temps)(cb);
    stackref = VG_(malloc)(sizeof(*stackref) * ntemps);
    VG_(memset)(stackref, 0, sizeof(*stackref) * ntemps);
 
-   for (i = 0; i < cb_in->used; i++) {
-      u_in = &cb_in->instrs[i];
+   for (i = 0; i < VG_(get_num_instrs)(cb_in); i++) {
+      u_in = VG_(get_instr)(cb_in, i);
 
       switch (u_in->opcode) {
 
@@ -2200,7 +2199,8 @@ static void describe_addr ( Addr a, AddrInfo* ai )
    /* Closure for searching malloc'd and free'd lists */
    Bool addr_is_in_block(ShadowChunk *sh_ch)
    {
-      return VG_(addr_is_in_block) ( a, sh_ch->data, sh_ch->size );
+      return VG_(addr_is_in_block) ( a, VG_(get_sc_data)(sh_ch),
+                                        VG_(get_sc_size)(sh_ch) );
    }
 
    /* Search for it in segments */
@@ -2240,8 +2240,8 @@ static void describe_addr ( Addr a, AddrInfo* ai )
    sc = VG_(any_matching_mallocd_ShadowChunks)(addr_is_in_block);
    if (NULL != sc) {
       ai->akind      = Mallocd;
-      ai->blksize    = sc->size;
-      ai->rwoffset   = (Int)(a) - (Int)(sc->data);
+      ai->blksize    = VG_(get_sc_size)(sc);
+      ai->rwoffset   = (Int)(a) - (Int)(VG_(get_sc_data)(sc));
       ai->lastchange = get_sc_where(sc);
       ai->lasttid    = get_sc_tid(sc);
       return;
@@ -2249,14 +2249,17 @@ static void describe_addr ( Addr a, AddrInfo* ai )
 
    /* Look in recently freed memory */
    for(i = 0; i < N_FREED_CHUNKS; i++) {
+      Addr sc_data = VG_(get_sc_data)(sc);
+      UInt sc_size = VG_(get_sc_size)(sc);
+      
       sc = freechunks[i];
       if (sc == NULL)
         continue;
 
-      if (a >= sc->data && a < sc->data+sc->size) {
+      if (a >= sc_data && a <  sc_data + sc_size) {
         ai->akind      = Freed;
-        ai->blksize    = sc->size;
-        ai->rwoffset   = a - sc->data;
+        ai->blksize    = sc_size;
+        ai->rwoffset   = a - sc_data;
         ai->lastchange = get_sc_where(sc);
         ai->lasttid    = get_sc_tid(sc);
         return;
@@ -2269,19 +2272,19 @@ static void describe_addr ( Addr a, AddrInfo* ai )
 }
 
 
-/* Creates a copy of the err_extra, updates the copy with address info if
-   necessary, sticks the copy into the SkinError. */
-void SK_(dup_extra_and_update)(SkinError* err)
+/* Creates a copy of the `extra' part, updates the copy with address info if
+   necessary, and returns the copy. */
+void* SK_(dup_extra_and_update)(Error* err)
 {
-   HelgrindError* err_extra;
+   HelgrindError* new_extra;
 
-   err_extra  = VG_(malloc)(sizeof(HelgrindError));
-   *err_extra = *((HelgrindError*)err->extra);
+   new_extra  = VG_(malloc)(sizeof(HelgrindError));
+   *new_extra = *((HelgrindError*)VG_(get_error_extra)(err));
 
-   if (err_extra->addrinfo.akind == Undescribed)
-      describe_addr ( err->addr, &(err_extra->addrinfo) );
+   if (new_extra->addrinfo.akind == Undescribed)
+      describe_addr ( VG_(get_error_address)(err), &(new_extra->addrinfo) );
 
-   err->extra = err_extra;
+   return new_extra;
 }
 
 static void record_eraser_error ( ThreadState *tst, Addr a, Bool is_write,
@@ -2346,21 +2349,24 @@ static void record_lockgraph_error(ThreadId tid, Mutex *mutex,
                           mutex->mutexp, "", &err_extra);
 }
 
-Bool SK_(eq_SkinError) ( VgRes not_used,
-                          SkinError* e1, SkinError* e2 )
+Bool SK_(eq_SkinError) ( VgRes not_used, Error* e1, Error* e2 )
 {
-   sk_assert(e1->ekind == e2->ekind);
+   Char *e1s, *e2s;
+
+   sk_assert(VG_(get_error_kind)(e1) == VG_(get_error_kind)(e2));
 
-   switch(e1->ekind) {
+   switch (VG_(get_error_kind)(e1)) {
    case EraserErr:
-      return e1->addr == e2->addr;
+      return VG_(get_error_address)(e1) == VG_(get_error_address)(e2);
 
    case MutexErr:
-      return e1->addr == e2->addr;
+      return VG_(get_error_address)(e1) == VG_(get_error_address)(e2);
    }
 
-   if (e1->string != e2->string) return False;
-   if (0 != VG_(strcmp)(e1->string, e2->string)) return False;
+   e1s = VG_(get_error_string)(e1);
+   e2s = VG_(get_error_string)(e2);
+   if (e1s != e2s) return False;
+   if (0 != VG_(strcmp)(e1s, e2s)) return False;
    return True;
 }
 
@@ -2443,21 +2449,23 @@ static Char *lockset_str(const Char *prefix, const LockSet *lockset)
    return buf;
 }
 
-void SK_(pp_SkinError) ( SkinError* err, void (*pp_ExeContext)(void) )
+void SK_(pp_SkinError) ( Error* err, void (*pp_ExeContext)(void) )
 {
-   HelgrindError *extra = (HelgrindError *)err->extra;
+   HelgrindError *extra = (HelgrindError *)VG_(get_error_extra)(err);
    Char buf[100];
    Char *msg = buf;
    const LockSet *ls;
 
    *msg = '\0';
 
-   switch(err->ekind) {
-   case EraserErr:
+   switch(VG_(get_error_kind)(err)) {
+   case EraserErr: {
+      Addr err_addr = VG_(get_error_address)(err);
+                      
       VG_(message)(Vg_UserMsg, "Possible data race %s variable at %p %(y",
-                  err->string, err->addr, err->addr );
+                  VG_(get_error_string)(err), err_addr, err_addr);
       pp_ExeContext();
-      pp_AddrInfo(err->addr, &extra->addrinfo);
+      pp_AddrInfo(err_addr, &extra->addrinfo);
 
       switch(extra->prevstate.state) {
       case Vge_Virgin:
@@ -2499,7 +2507,7 @@ void SK_(pp_SkinError) ( SkinError* err, void (*pp_ExeContext)(void) )
         Addr eip = extra->lasttouched.eip;
         
         VG_(message)(Vg_UserMsg, "  Word at %p last changed state from %s by thread %u",
-                     err->addr,
+                     err_addr,
                      pp_state(extra->lasttouched.state),
                      unpackTLS(extra->lasttouched.tls)->tid);
         
@@ -2514,33 +2522,36 @@ void SK_(pp_SkinError) ( SkinError* err, void (*pp_ExeContext)(void) )
         }
       } else if (clo_execontext == EC_All && extra->lasttouched.ec != NULL) {
         VG_(message)(Vg_UserMsg, "  Word at %p last changed state from %s in tid %u",
-                     err->addr,
+                     err_addr,
                      pp_state(extra->lasttouched.state),
                      unpackTLS(extra->lasttouched.tls)->tid);
         VG_(pp_ExeContext)(extra->lasttouched.ec);
       }
-
       break;
+   }
 
    case MutexErr:
       VG_(message)(Vg_UserMsg, "Mutex problem at %p%(y trying to %s",
-                  err->addr, err->addr, err->string );
+                  VG_(get_error_address)(err),
+                  VG_(get_error_address)(err),
+                  VG_(get_error_string)(err));
       pp_ExeContext();
       if (extra->lasttouched.ec != NULL) {
         VG_(message)(Vg_UserMsg, "  last touched by thread %d", extra->lasttid);
         VG_(pp_ExeContext)(extra->lasttouched.ec);
       }
-      pp_AddrInfo(err->addr, &extra->addrinfo);
+      pp_AddrInfo(VG_(get_error_address)(err), &extra->addrinfo);
       break;
 
    case LockGraphErr: {
       const LockSet *heldset = extra->held_lockset;
+      Addr err_addr = VG_(get_error_address)(err);
       Int i;
 
       msg = lockset_str(NULL, heldset);
 
       VG_(message)(Vg_UserMsg, "Mutex %p%(y locked in inconsistent order",
-                  err->addr, err->addr);
+                  err_addr, err_addr);
       pp_ExeContext();
       VG_(message)(Vg_UserMsg, " while holding locks %s", msg);
 
@@ -2568,10 +2579,10 @@ void SK_(pp_SkinError) ( SkinError* err, void (*pp_ExeContext)(void) )
 }
 
 
-Bool SK_(recognised_suppression) ( Char* name, SuppKind *skind )
+Bool SK_(recognised_suppression) ( Char* name, Supp *su )
 {
    if (0 == VG_(strcmp)(name, "Eraser")) {
-      *skind = EraserSupp;
+      VG_(set_supp_kind)(su, EraserSupp);
       return True;
    } else {
       return False;
@@ -2579,8 +2590,7 @@ Bool SK_(recognised_suppression) ( Char* name, SuppKind *skind )
 }
 
 
-Bool SK_(read_extra_suppression_info) ( Int fd, Char* buf, 
-                                        Int nBuf, SkinSupp* s )
+Bool SK_(read_extra_suppression_info) ( Int fd, Char* buf, Int nBuf, Supp* su )
 {
    /* do nothing -- no extra suppression info present.  Return True to
       indicate nothing bad happened. */
@@ -2588,10 +2598,10 @@ Bool SK_(read_extra_suppression_info) ( Int fd, Char* buf,
 }
 
 
-Bool SK_(error_matches_suppression)(SkinError* err, SkinSupp* su)
+Bool SK_(error_matches_suppression)(Error* err, Supp* su)
 {
-   sk_assert( su->skind == EraserSupp);
-   sk_assert(err->ekind == EraserErr);
+   sk_assert(VG_(get_supp_kind) (su)  == EraserSupp);
+   sk_assert(VG_(get_error_kind)(err) == EraserErr);
    return True;
 }
 
@@ -3053,58 +3063,58 @@ Bool SK_(handle_client_request)(ThreadState *tst, UInt *args, UInt *ret)
 /*--- Setup                                                        ---*/
 /*--------------------------------------------------------------------*/
 
-void SK_(pre_clo_init)(VgDetails* details, VgNeeds* needs, VgTrackEvents* track)
+void SK_(pre_clo_init)(void)
 {
    Int i;
    LockSet *empty;
 
-   details->name             = "Helgrind";
-   details->version          = NULL;
-   details->description      = "a data race detector";
-   details->copyright_author =
-      "Copyright (C) 2002, and GNU GPL'd, by Nicholas Nethercote.";
-   details->bug_reports_to   = "njn25@cam.ac.uk";
-
-   needs->core_errors           = True;
-   needs->skin_errors           = True;
-   needs->data_syms             = True;
-   needs->sizeof_shadow_block  = SHADOW_EXTRA;
-   needs->alternative_free      = True;
-   needs->client_requests       = True;
-   needs->command_line_options  = True;
-
-   track->new_mem_startup       = & eraser_new_mem_startup;
-   track->new_mem_heap          = & eraser_new_mem_heap;
-   track->new_mem_stack         = & eraser_new_mem_stack_private;
-   track->new_mem_stack_aligned = & eraser_new_mem_stack_private;
-   track->new_mem_stack_signal  = & eraser_new_mem_stack_private;
-   track->new_mem_brk           = & make_writable;
-   track->new_mem_mmap          = & eraser_new_mem_startup;
-
-   track->copy_mem_heap         = & copy_address_range_state;
-   track->change_mem_mprotect   = & eraser_set_perms;
-
-   track->ban_mem_heap          = NULL;
-   track->ban_mem_stack         = NULL;
-
-   track->die_mem_heap          = NULL;
-   track->die_mem_stack         = NULL;
-   track->die_mem_stack_aligned = NULL;
-   track->die_mem_stack_signal  = NULL;
-   track->die_mem_brk           = NULL;
-   track->die_mem_munmap        = NULL;
-
-   track->pre_mem_read          = & eraser_pre_mem_read;
-   track->pre_mem_read_asciiz   = & eraser_pre_mem_read_asciiz;
-   track->pre_mem_write         = & eraser_pre_mem_write;
-   track->post_mem_write        = NULL;
-
-   track->pre_mutex_lock        = & eraser_pre_mutex_lock;
-   track->post_mutex_lock       = & eraser_post_mutex_lock;
-   track->post_mutex_unlock     = & eraser_post_mutex_unlock;
-
-   track->post_thread_create    = & hg_thread_create;
-   track->post_thread_join      = & hg_thread_join;
+   VG_(details_name)            ("Helgrind");
+   VG_(details_version)         (NULL);
+   VG_(details_description)     ("a data race detector");
+   VG_(details_copyright_author)(
+      "Copyright (C) 2002, and GNU GPL'd, by Nicholas Nethercote.");
+   VG_(details_bug_reports_to)  ("njn25@cam.ac.uk");
+
+   VG_(needs_core_errors)();
+   VG_(needs_skin_errors)();
+   VG_(needs_data_syms)();
+   VG_(needs_sizeof_shadow_block)(SHADOW_EXTRA);
+   VG_(needs_alternative_free)();
+   VG_(needs_client_requests)();
+   VG_(needs_command_line_options)();
+
+   VG_(track_new_mem_startup)      (& eraser_new_mem_startup);
+   VG_(track_new_mem_heap)         (& eraser_new_mem_heap);
+
+   /* stack ones not decided until VG_(post_clo_init)() */
+
+   VG_(track_new_mem_brk)          (& make_writable);
+   VG_(track_new_mem_mmap)         (& eraser_new_mem_startup);
+
+   VG_(track_copy_mem_heap)        (& copy_address_range_state);
+   VG_(track_change_mem_mprotect)  (& eraser_set_perms);
+
+   VG_(track_ban_mem_heap)         (NULL);
+   VG_(track_ban_mem_stack)        (NULL);
+
+   VG_(track_die_mem_heap)         (NULL);
+   VG_(track_die_mem_stack)        (NULL);
+   VG_(track_die_mem_stack_aligned)(NULL);
+   VG_(track_die_mem_stack_signal) (NULL);
+   VG_(track_die_mem_brk)          (NULL);
+   VG_(track_die_mem_munmap)       (NULL);
+
+   VG_(track_pre_mem_read)         (& eraser_pre_mem_read);
+   VG_(track_pre_mem_read_asciiz)  (& eraser_pre_mem_read_asciiz);
+   VG_(track_pre_mem_write)        (& eraser_pre_mem_write);
+   VG_(track_post_mem_write)       (NULL);
+
+   VG_(track_post_thread_create)   (& hg_thread_create);
+   VG_(track_post_thread_join)     (& hg_thread_join);
+
+   VG_(track_post_mutex_lock)      (& eraser_pre_mutex_lock);
+   VG_(track_post_mutex_lock)      (& eraser_post_mutex_lock);
+   VG_(track_post_mutex_unlock)    (& eraser_post_mutex_unlock);
 
    VG_(register_compact_helper)((Addr) & eraser_mem_help_read_1);
    VG_(register_compact_helper)((Addr) & eraser_mem_help_read_2);
@@ -3204,18 +3214,21 @@ Char *SK_(usage)(void)
 
 void SK_(post_clo_init)(void)
 {
+   void (*stack_tracker)(Addr a, UInt len);
+   
    if (clo_execontext) {
       execontext_map = VG_(malloc)(sizeof(ExeContextMap *) * 65536);
       VG_(memset)(execontext_map, 0, sizeof(ExeContextMap *) * 65536);
    }
 
-   if (!clo_priv_stacks) {
-      VgTrackEvents *track = &VG_(track_events);
+   if (clo_priv_stacks)
+      stack_tracker = & eraser_new_mem_stack_private;
+   else
+      stack_tracker = & eraser_new_mem_stack;
 
-      track->new_mem_stack         = & eraser_new_mem_stack;
-      track->new_mem_stack_aligned = & eraser_new_mem_stack;
-      track->new_mem_stack_signal  = & eraser_new_mem_stack;
-   }
+   VG_(track_new_mem_stack)        (stack_tracker);
+   VG_(track_new_mem_stack_aligned)(stack_tracker);
+   VG_(track_new_mem_stack_signal) (stack_tracker);
 }
 
 
index 10f70e7253d5c634647eb6f5068f8b6e0e89c727..1d0e1d3221213406167838a2769ccf5917bbb05a 100644 (file)
@@ -702,36 +702,31 @@ typedef
    UInstr;
 
 
-/* Expandable arrays of uinstrs. */
 typedef 
-   struct { 
-      Int     used; 
-      Int     size; 
-      UInstr* instrs;
-      Int     nextTemp;
-   }
+   struct _UCodeBlock
    UCodeBlock;
 
+extern Int     VG_(get_num_instrs) (UCodeBlock* cb);
+extern Int     VG_(get_num_temps)  (UCodeBlock* cb);
 
+extern UInstr* VG_(get_instr)      (UCodeBlock* cb, Int i);
+extern UInstr* VG_(get_last_instr) (UCodeBlock* cb);
+   
 /*====================================================================*/
 /*=== Instrumenting UCode                                          ===*/
 /*====================================================================*/
 
-/* A structure for communicating TempReg and RealReg uses of UInstrs. */
-typedef
-   struct {
-      Int   num;
-      Bool  isWrite;
-   }
-   RegUse;
+/* Find what this instruction does to its regs.  `tag' indicates whether we're
+   considering TempRegs (pre-reg-alloc) or RealRegs (post-reg-alloc).
+   `regs' is filled with the affected register numbers, `isWrites' parallels
+   it and indicates if the reg is read or written.  If a reg is read and
+   written, it will appear twice in `regs'.  `regs' and `isWrites' must be
+   able to fit 3 elements.
 
-/* Find what this instruction does to its regs.  Tag indicates whether we're
- * considering TempRegs (pre-reg-alloc) or RealRegs (post-reg-alloc).
- * Useful for analysis/optimisation passes. */
-extern Int  VG_(get_reg_usage) ( UInstr* u, Tag tag, RegUse* arr );
+   Useful for analysis/optimisation passes. */
+extern Int VG_(get_reg_usage) ( UInstr* u, Tag tag, Int* regs, Bool* isWrites );
 
 
-/* ------------------------------------------------------------------ */
 /* Used to register helper functions to be called from generated code.  A
    limited number of compact helpers can be registered;  the code generated
    to call them is slightly shorter -- so register the mostly frequently
@@ -767,10 +762,14 @@ extern void VG_(new_UInstr3) ( UCodeBlock* cb, Opcode opcode, Int sz,
                               Tag tag2, UInt val2,
                               Tag tag3, UInt val3 );
 
-extern void VG_(set_flag_RW)      ( UInstr* u, FlagSet fr, FlagSet fw );
+/* Set read/write/undefined flags.  Undefined flags are treaten as written, 
+   but it's worth keeping them logically distinct. */
+extern void VG_(set_flag_fields)  ( UCodeBlock* cb, FlagSet fr, FlagSet fw,
+                                    FlagSet fu);
 extern void VG_(set_lit_field)    ( UCodeBlock* cb, UInt lit32 );
 extern void VG_(set_ccall_fields) ( UCodeBlock* cb, Addr fn, UChar argc,
                                     UChar regparms_n, Bool has_ret_val );
+extern void VG_(set_cond_field)   ( UCodeBlock* cb, Condcode code );
 
 extern void VG_(copy_UInstr) ( UCodeBlock* cb, UInstr* instr );
 
@@ -783,6 +782,8 @@ extern Bool VG_(any_flag_use)( UInstr* u );
 #define uInstr3   VG_(new_UInstr3)
 #define uLiteral  VG_(set_lit_field)
 #define uCCall    VG_(set_ccall_fields)
+#define uCond     VG_(set_cond_field)
+#define uFlagsRWU VG_(set_flag_fields)
 #define newTemp   VG_(get_new_temp)
 #define newShadow VG_(get_new_shadow)
 
@@ -804,7 +805,7 @@ extern void VG_(set_global_var) ( UCodeBlock* cb, Addr globvar_ptr, UInt val);
 
 /* ------------------------------------------------------------------ */
 /* Allocating/freeing basic blocks of UCode */
-extern UCodeBlock* VG_(alloc_UCodeBlock) ( void );
+extern UCodeBlock* VG_(setup_UCodeBlock) ( UCodeBlock* cb );
 extern void        VG_(free_UCodeBlock)  ( UCodeBlock* cb );
 
 /* ------------------------------------------------------------------ */
@@ -996,26 +997,25 @@ typedef
    Int         /* Do not make this unsigned! */
    SuppKind;
 
-/* An extensible (via the 'extra' field) suppression record.  This holds
-   the suppression details of interest to a skin.  Skins can use a normal
-   enum (with element values in the normal range (0..)) for `skind'. 
-
-   If VG_(needs).report_errors==True, for each suppression read in by core
-   SKN_(recognised_suppression)() and SKN_(read_extra_suppression_info) will
-   be called.  The `skind' field is filled in by the value returned in the
-   argument of the first function;  the second function can fill in the
-   `string' and `extra' fields if it wants. 
+/* The skin-relevant parts of a suppression are:
+     kind:   what kind of suppression; must be in the range (0..)
+     string: use is optional.  NULL by default.
+     extra:  use is optional.  NULL by default.  void* so it's extensible.
 */
 typedef
-   struct {
-      /* What kind of suppression.  Must use the range (0..) */
-      SuppKind skind;
-      /* String -- use is optional.  NULL by default. */
-      Char* string;
-      /* Anything else -- use is optional.  NULL by default. */
-      void* extra;
-   }
-   SkinSupp;
+   struct _Supp
+   Supp;
+
+/* Useful in SK_(error_matches_suppression)() */
+SuppKind VG_(get_supp_kind)   ( Supp* su );
+Char*    VG_(get_supp_string) ( Supp* su );
+void*    VG_(get_supp_extra)  ( Supp* su );
+
+/* Must be used in VG_(recognised_suppression)() */
+void VG_(set_supp_kind)   ( Supp* su, SuppKind suppkind );
+/* May be used in VG_(read_extra_suppression_info)() */
+void VG_(set_supp_string) ( Supp* su, Char* string );
+void VG_(set_supp_extra)  ( Supp* su, void* extra );
 
 
 /* ------------------------------------------------------------------ */
@@ -1029,29 +1029,22 @@ typedef
    Int         /* Do not make this unsigned! */
    ErrorKind;
 
-/* An extensible (via the 'extra' field) error record.  This holds
-   the error details of interest to a skin.  Skins can use a normal
-   enum (with element values in the normal range (0..)) for `ekind'. 
-
-   When errors are found and recorded with VG_(maybe_record_error)(), all
-   the skin must do is pass in the four parameters;  core will
-   allocate/initialise the error record.
+/* The skin-relevant parts of an Error are:
+     kind:   what kind of error; must be in the range (0..)
+     addr:   use is optional.  0 by default.
+     string: use is optional.  NULL by default.
+     extra:  use is optional.  NULL by default.  void* so it's extensible.
 */
 typedef
-   struct {
-      /* Used by ALL.  Must be in the range (0..) */
-      Int ekind;
-      /* Used frequently */
-      Addr addr;
-      /* Used frequently */
-      Char* string;
-      /* For any skin-specific extras */
-      void* extra;
-   }
-   SkinError;
+   struct _Error
+   Error;
 
+/* Useful in SK_(error_matches_suppression)(), SK_(pp_SkinError)(), etc */
+SuppKind VG_(get_error_kind)    ( Error* err );
+Addr     VG_(get_error_address) ( Error* err );
+Char*    VG_(get_error_string)  ( Error* err );
+void*    VG_(get_error_extra)   ( Error* err );
 
-/* ------------------------------------------------------------------ */
 /* Call this when an error occurs.  It will be recorded if it hasn't been
    seen before.  If it has, the existing error record will have its count
    incremented.  
@@ -1134,26 +1127,29 @@ extern VgSectKind VG_(seg_sect_kind)(Addr);
 /*=== Shadow chunks and block-finding                              ===*/
 /*====================================================================*/
 
+/* The skin-relevant parts of a ShadowChunk are:
+     size:   size of the block in bytes
+     addr:   addr of the block
+     extra:  anything extra kept by the skin;  size is determined by
+             VG_(needs).sizeof_shadow_chunk
+*/
 typedef
-   enum { 
-      Vg_AllocMalloc = 0,
-      Vg_AllocNew    = 1,
-      Vg_AllocNewVec = 2 
-   }
-   VgAllocKind;
-
-/* Description of a malloc'd chunk.  skin_extra[] part can be used by
-   the skin;  size of array is given by VG_(needs).sizeof_shadow_chunk. */
-typedef 
-   struct _ShadowChunk {
-      struct _ShadowChunk* next;
-      UInt          size : 30;      /* size requested                   */
-      VgAllocKind   allockind : 2;  /* which wrapper did the allocation */
-      Addr          data;           /* ptr to actual block              */
-      UInt          skin_extra[0];  /* extra skin-specific info         */
-   } 
+   struct _ShadowChunk
    ShadowChunk;
 
+extern UInt         VG_(get_sc_size)  ( ShadowChunk* sc );
+extern Addr         VG_(get_sc_data)  ( ShadowChunk* sc );
+/* Gets the ith word of the `extra' field. */
+extern UInt         VG_(get_sc_extra) ( ShadowChunk* sc, UInt i );
+/* Sets the ith word of the `extra' field to `word'. */
+extern void         VG_(set_sc_extra) ( ShadowChunk* sc, UInt i, UInt word );
+
+/* These two should only be used if the `alternative_free' need is set, once
+   we reach the point where the block would have been free'd. */
+extern ShadowChunk* VG_(get_sc_next)  ( ShadowChunk* sc );
+extern void         VG_(set_sc_next)  ( ShadowChunk* sc, ShadowChunk* next );
+
+
 /* Use this to free blocks if VG_(needs).alternative_free == True. 
    It frees the ShadowChunk and the malloc'd block it points to. */
 extern void VG_(free_ShadowChunk) ( ShadowChunk* sc );
@@ -1192,101 +1188,85 @@ extern void VG_(generic_detect_memory_leaks) (
 
 /* ------------------------------------------------------------------ */
 /* Details */
-typedef
-   struct {
-      /* Information used in the startup message. `name' also determines the
-         string used for identifying suppressions in a suppression file as
-         belonging to this skin.  `version' can be NULL, in which case (not
-         surprisingly) no version info is printed; this mechanism is
-         designed for skins distributed with Valgrind that share a version
-         number with Valgrind.  Other skins not distributed as part of
-         Valgrind should probably have their own version number. */
-      Char* name;
-      Char* version;
-      Char* description;
-      Char* copyright_author;
-
-      /* String printed if an `sk_assert' assertion fails or VG_(skin_panic)
-         is called.  Should probably be an email address. */
-      Char* bug_reports_to;
-   }
-   VgDetails;
 
-extern VgDetails VG_(details);
+/* Information used in the startup message.  `name' also determines the
+   string used for identifying suppressions in a suppression file as
+   belonging to this skin.  `version' can be NULL, in which case (not
+   surprisingly) no version info is printed; this mechanism is designed for
+   skins distributed with Valgrind that share a version number with
+   Valgrind.  Other skins not distributed as part of Valgrind should
+   probably have their own version number. */
+extern void VG_(details_name)             ( Char* name );
+extern void VG_(details_version)          ( Char* version );
+extern void VG_(details_description)      ( Char* description );
+extern void VG_(details_copyright_author) ( Char* copyright_author );
+
+/* String printed if an `sk_assert' assertion fails or VG_(skin_panic)
+   is called.  Should probably be an email address. */
+extern void VG_(details_bug_reports_to)   ( Char* bug_reports_to );
 
 /* ------------------------------------------------------------------ */
 /* Needs */
 
-/* If new fields are added to this type, update:
- *  - vg_main.c:initialisation of VG_(needs)
- *  - vg_main.c:sanity_check_needs()
- *
- * If the name of this type or any of its fields change, update:
- *  - dependent comments (just search for "VG_(needs)"). 
- */
-typedef
-   struct {
-      /* Booleans that decide core behaviour, but don't require extra
-         operations to be defined if `True' */
-
-      /* Should __libc_freeres() be run?  Bugs in it can crash the skin. */
-      Bool libc_freeres;
-
-      /* Want to have errors detected by Valgrind's core reported?  Includes:
-         - pthread API errors (many;  eg. unlocking a non-locked mutex)
-         - silly arguments to malloc() et al (eg. negative size)
-         - invalid file descriptors to blocking syscalls read() and write()
-         - bad signal numbers passed to sigaction()
-         - attempt to install signal handler for SIGKILL or SIGSTOP */  
-      Bool core_errors;
-
-      /* Booleans that indicate extra operations are defined;  if these are
-         True, the corresponding template functions (given below) must be
-         defined.  A lot like being a member of a type class. */
-
-      /* Want to report errors from the skin?  This implies use of
-         suppressions, too. */
-      Bool skin_errors;
-
-      /* Is information kept about specific individual basic blocks?  (Eg. for
-         cachegrind there are cost-centres for every instruction, stored at a
-         basic block level.)  If so, it sometimes has to be discarded, because
-         .so mmap/munmap-ping or self-modifying code (informed by the
-         DISCARD_TRANSLATIONS user request) can cause one instruction address
-         to be used for more than one instruction in one program run...  */
-      Bool basic_block_discards;
-
-      /* Skin maintains information about each register? */
-      Bool shadow_regs;
-
-      /* Skin defines its own command line options? */
-      Bool command_line_options;
-      /* Skin defines its own client requests? */
-      Bool client_requests;
-
-      /* Skin defines its own UInstrs? */
-      Bool extended_UCode;
-
-      /* Skin does stuff before and/or after system calls? */
-      Bool syscall_wrapper;
-
-      /* Size, in words, of extra info about malloc'd blocks recorded by
-         skin.  Be careful to get this right or you'll get seg faults! */
-      UInt sizeof_shadow_block;
-
-      /* Skin does free()s itself? */
-      Bool alternative_free;
-
-      /* Are skin-state sanity checks performed? */
-      Bool sanity_checks;
-
-      /* Do we need to see data symbols? */
-      Bool data_syms;
-   } 
-   VgNeeds;
+/* Booleans that decide core behaviour, but don't require extra
+   operations to be defined if `True' */
+
+/* Should __libc_freeres() be run?  Bugs in it can crash the skin. */
+extern void VG_(needs_libc_freeres) ( void );
+
+/* Want to have errors detected by Valgrind's core reported?  Includes:
+   - pthread API errors (many;  eg. unlocking a non-locked mutex)
+   - silly arguments to malloc() et al (eg. negative size)
+   - invalid file descriptors to blocking syscalls read() and write()
+   - bad signal numbers passed to sigaction()
+   - attempt to install signal handler for SIGKILL or SIGSTOP */  
+extern void VG_(needs_core_errors) ( void );
+
+/* Booleans that indicate extra operations are defined;  if these are True,
+   the corresponding template functions (given below) must be defined.  A
+   lot like being a member of a type class. */
+
+/* Want to report errors from skin?  This implies use of suppressions, too. */
+extern void VG_(needs_skin_errors) ( void );
+
+/* Is information kept about specific individual basic blocks?  (Eg. for
+   cachegrind there are cost-centres for every instruction, stored at a
+   basic block level.)  If so, it sometimes has to be discarded, because
+   .so mmap/munmap-ping or self-modifying code (informed by the
+   DISCARD_TRANSLATIONS user request) can cause one instruction address
+   to be used for more than one instruction in one program run...  */
+extern void VG_(needs_basic_block_discards) ( void );
+
+/* Skin maintains information about each register? */
+extern void VG_(needs_shadow_regs) ( void );
+
+/* Skin defines its own command line options? */
+extern void VG_(needs_command_line_options) ( void );
+
+/* Skin defines its own client requests? */
+extern void VG_(needs_client_requests) ( void );
+
+/* Skin defines its own UInstrs? */
+extern void VG_(needs_extended_UCode) ( void );
 
-extern VgNeeds VG_(needs);
+/* Skin does stuff before and/or after system calls? */
+extern void VG_(needs_syscall_wrapper) ( void );
 
+/* Size, in words, of extra info about malloc'd blocks recorded by
+   skin.  Be careful to get this right or you'll get seg faults! */
+extern void VG_(needs_sizeof_shadow_block) ( Int size );
+
+/* Skin does free()s itself?  Useful if a skin needs to keep track of
+   blocks in some way after they're free'd.  
+   WARNING: don't forget to call VG_(free_ShadowChunk)() for each block 
+   eventually! */
+extern void VG_(needs_alternative_free) ( void );
+
+/* Are skin-state sanity checks performed? */
+extern void VG_(needs_sanity_checks) ( void );
+
+/* Do we need to see data symbols? */
+extern void VG_(needs_data_syms) ( void );
 
 /* ------------------------------------------------------------------ */
 /* Core events to track */
@@ -1297,87 +1277,89 @@ typedef
    enum { Vg_CorePThread, Vg_CoreSignal, Vg_CoreSysCall, Vg_CoreTranslate }
    CorePart;
 
-/* Events happening in core to track.  To be notified, assign a function
-   to the function pointer.  To ignore an event, don't do anything
-   (default assignment is to NULL in which case the call is skipped). */
-typedef
-   struct {
-      /* Memory events */
-      void (*new_mem_startup)( Addr a, UInt len, Bool rr, Bool ww, Bool xx );
-      void (*new_mem_heap)   ( Addr a, UInt len, Bool is_inited );
-      void (*new_mem_stack)  ( Addr a, UInt len );
-      void (*new_mem_stack_aligned) ( Addr a, UInt len );
-      void (*new_mem_stack_signal)  ( Addr a, UInt len );
-      void (*new_mem_brk)    ( Addr a, UInt len );
-      void (*new_mem_mmap)   ( Addr a, UInt len, Bool rr, Bool ww, Bool xx );
-
-      void (*copy_mem_heap)  ( Addr from, Addr to, UInt len );
-      void (*copy_mem_remap) ( Addr from, Addr to, UInt len );
-      void (*change_mem_mprotect) ( Addr a, UInt len, Bool rr, Bool ww, Bool xx );
-      
-      /* Used on redzones around malloc'd blocks and at end of stack */
-      void (*ban_mem_heap)   ( Addr a, UInt len );
-      void (*ban_mem_stack)  ( Addr a, UInt len );
-
-      void (*die_mem_heap)   ( Addr a, UInt len );
-      void (*die_mem_stack)  ( Addr a, UInt len );
-      void (*die_mem_stack_aligned) ( Addr a, UInt len );
-      void (*die_mem_stack_signal)  ( Addr a, UInt len );
-      void (*die_mem_brk)    ( Addr a, UInt len );
-      void (*die_mem_munmap) ( Addr a, UInt len );
-
-      void (*bad_free)        ( ThreadState* tst, Addr a );
-      void (*mismatched_free) ( ThreadState* tst, Addr a );
-
-      void (*pre_mem_read)   ( CorePart part, ThreadState* tst,
-                               Char* s, Addr a, UInt size );
-      void (*pre_mem_read_asciiz) ( CorePart part, ThreadState* tst,
-                                    Char* s, Addr a );
-      void (*pre_mem_write)  ( CorePart part, ThreadState* tst,
-                               Char* s, Addr a, UInt size );
-      /* Not implemented yet -- have to add in lots of places, which is a
-         pain.  Won't bother unless/until there's a need. */
-      /* void (*post_mem_read)  ( ThreadState* tst, Char* s, 
-                                  Addr a, UInt size ); */
-      void (*post_mem_write) ( Addr a, UInt size );
-
-
-      /* Scheduler events (not exhaustive) */
-      void (*thread_run) ( ThreadId tid );
-
-
-      /* Mutex events (not exhaustive) */
-
-      /* Called before a thread can block while waiting for a mutex
-        (called regardless of whether the thread will block or
-        not) */
-      void (*pre_mutex_lock)    ( ThreadId tid, 
-                                  void* /*pthread_mutex_t* */ mutex );
-      /* Called once the thread actually holds the mutex (always
-        paired with pre_mutex_lock) */
-      void (*post_mutex_lock)   ( ThreadId tid, 
-                                  void* /*pthread_mutex_t* */ mutex );
-      /* Called after a thread has released a mutex (no need for a
-        corresponding pre_mutex_unlock, because unlocking can't
-        block) */
-      void (*post_mutex_unlock) ( ThreadId tid, 
-                                  void* /*pthread_mutex_t* */ mutex );
-
-      /* Called during thread create, before the new thread has run
-        any instructions (or touched any memory). */
-      void (*post_thread_create)( ThreadId tid, ThreadId child );
-      /* Called once the joinee thread is terminated and the joining
-        thread is about to resume. */
-      void (*post_thread_join)  ( ThreadId joiner, ThreadId joinee );
-      
-      /* Others... thread, condition variable, signal events... */
-      /* ... */
-   }
-   VgTrackEvents;
+#define EV  extern void
+
+/* Events happening in core to track.  To be notified, pass a callback
+   function to the appropriate function.  To ignore an event, don't do
+   anything (default is for events to be ignored). */
+
+/* Memory events */
 
-/* Declare the struct instance */
-extern VgTrackEvents VG_(track_events);
+EV VG_(track_new_mem_startup) ( void (*f)(Addr a, UInt len, 
+                                          Bool rr, Bool ww, Bool xx) );
+EV VG_(track_new_mem_heap)    ( void (*f)(Addr a, UInt len, Bool is_inited) );
+EV VG_(track_new_mem_stack)   ( void (*f)(Addr a, UInt len) );
+EV VG_(track_new_mem_stack_aligned) ( void (*f)(Addr a, UInt len) );
+EV VG_(track_new_mem_stack_signal)  ( void (*f)(Addr a, UInt len) );
+EV VG_(track_new_mem_brk)     ( void (*f)(Addr a, UInt len) );
+EV VG_(track_new_mem_mmap)    ( void (*f)(Addr a, UInt len,
+                                          Bool rr, Bool ww, Bool xx) );
 
+EV VG_(track_copy_mem_heap)   ( void (*f)(Addr from, Addr to, UInt len) );
+EV VG_(track_copy_mem_remap)  ( void (*f)(Addr from, Addr to, UInt len) );
+EV VG_(track_change_mem_mprotect) ( void (*f)(Addr a, UInt len,
+                                              Bool rr, Bool ww, Bool xx) );
+      
+/* Used on redzones around malloc'd blocks and at end of stack */
+EV VG_(track_ban_mem_heap)    ( void (*f)(Addr a, UInt len) );
+EV VG_(track_ban_mem_stack)   ( void (*f)(Addr a, UInt len) );
+
+EV VG_(track_die_mem_heap)    ( void (*f)(Addr a, UInt len) );
+EV VG_(track_die_mem_stack)   ( void (*f)(Addr a, UInt len) );
+EV VG_(track_die_mem_stack_aligned) ( void (*f)(Addr a, UInt len) );
+EV VG_(track_die_mem_stack_signal)  ( void (*f)(Addr a, UInt len) );
+EV VG_(track_die_mem_brk)     ( void (*f)(Addr a, UInt len) );
+EV VG_(track_die_mem_munmap)  ( void (*f)(Addr a, UInt len) );
+
+EV VG_(track_bad_free)        ( void (*f)(ThreadState* tst, Addr a) );
+EV VG_(track_mismatched_free) ( void (*f)(ThreadState* tst, Addr a) );
+
+EV VG_(track_pre_mem_read)    ( void (*f)(CorePart part, ThreadState* tst,
+                                          Char* s, Addr a, UInt size) );
+EV VG_(track_pre_mem_read_asciiz) ( void (*f)(CorePart part, ThreadState* tst,
+                                              Char* s, Addr a) );
+EV VG_(track_pre_mem_write)   ( void (*f)(CorePart part, ThreadState* tst,
+                                          Char* s, Addr a, UInt size) );
+/* Not implemented yet -- have to add in lots of places, which is a
+   pain.  Won't bother unless/until there's a need. */
+/* EV VG_(track_post_mem_read)  ( void (*f)(ThreadState* tst, Char* s, 
+                                            Addr a, UInt size) ); */
+EV VG_(track_post_mem_write) ( void (*f)(Addr a, UInt size) );
+
+
+/* Scheduler events (not exhaustive) */
+
+EV VG_(track_thread_run) ( void (*f)(ThreadId tid) );
+
+/* Thread events (not exhaustive) */
+
+/* Called during thread create, before the new thread has run any
+   instructions (or touched any memory). */
+EV VG_(track_post_thread_create)( void (*f)(ThreadId tid, ThreadId child) );
+/* Called once the joinee thread is terminated and the joining thread is
+   about to resume. */
+EV VG_(track_post_thread_join)  ( void (*f)(ThreadId joiner, ThreadId joinee) );
+
+      
+/* Mutex events (not exhaustive) */
+
+/* Called before a thread can block while waiting for a mutex (called
+   regardless of whether the thread will block or not). */
+EV VG_(track_pre_mutex_lock)    ( void (*f)(ThreadId tid, 
+                                          void* /*pthread_mutex_t* */ mutex) );
+/* Called once the thread actually holds the mutex (always paired with
+   pre_mutex_lock). */
+EV VG_(track_post_mutex_lock)   ( void (*f)(ThreadId tid, 
+                                          void* /*pthread_mutex_t* */ mutex) );
+/* Called after a thread has released a mutex (no need for a corresponding
+   pre_mutex_unlock, because unlocking can't block). */
+EV VG_(track_post_mutex_unlock) ( void (*f)(ThreadId tid, 
+                                          void* /*pthread_mutex_t* */ mutex) );
+
+/* Others... condition variable, signal events... */
+/* ... */
+
+#undef EV
 
 /* ------------------------------------------------------------------ */
 /* Template functions */
@@ -1393,17 +1375,18 @@ extern VgTrackEvents VG_(track_events);
 /* Fundamental template functions */
 
 /* Initialise skin.   Must do the following:
-     - initialise the `details' struct
+     - initialise the `details' struct, via the VG_(details_*)() functions
      - register any helpers called by generated code
   
    May do the following:
-     - initialise the `needs' struct to indicate certain requirements
-     - initialise the `track' struct to indicate core events of interest
+     - initialise the `needs' struct to indicate certain requirements, via
+       the VG_(needs_*)() functions
+     - initialise the `track' struct to indicate core events of interest, via
+       the VG_(track_*)() functions
      - register any skin-specific profiling events
      - any other skin-specific initialisation
 */
-extern void        SK_(pre_clo_init) ( VgDetails* details, VgNeeds* needs,
-                                       VgTrackEvents* track );
+extern void        SK_(pre_clo_init) ( void );
 
 /* Do initialisation that can only be done after command line processing. */
 extern void        SK_(post_clo_init)( void );
@@ -1423,40 +1406,44 @@ extern void        SK_(fini)         ( void );
 
 /* Identify if two errors are equal, or equal enough.  `res' indicates how
    close is "close enough".  `res' should be passed on as necessary, eg. if
-   the SkinError's extra field contains an ExeContext, `res' should be
+   the Error's `extra' part contains an ExeContext, `res' should be
    passed to VG_(eq_ExeContext)() if the ExeContexts are considered.  Other
    than that, probably don't worry about it unless you have lots of very
    similar errors occurring.
  */
-extern Bool SK_(eq_SkinError) ( VgRes res,
-                                SkinError* e1, SkinError* e2 );
+extern Bool SK_(eq_SkinError) ( VgRes res, Error* e1, Error* e2 );
 
 /* Print error context.  The passed function pp_ExeContext() can be (and
    probably should be) used to print the location of the error. */
-extern void SK_(pp_SkinError) ( SkinError* ec, void (*pp_ExeContext)(void) );
+extern void SK_(pp_SkinError) ( Error* err, void (*pp_ExeContext)(void) );
 
-/* Copy the ec->extra part and replace ec->extra with the new copy.  This is
-   necessary to move from a temporary stack copy to a permanent heap one.
+/* Should copy the `extra' part which the core uses to override the old
+   version.  This is necessary to move from a temporary stack copy to a
+   permanent heap one.
   
-   Then fill in any details that could be postponed until after the decision
-   whether to ignore the error (ie. details not affecting the result of
-   SK_(eq_SkinError)()).  This saves time when errors are ignored.
+   Then should fill in any details that could be postponed until after the
+   decision whether to ignore the error (ie. details not affecting the
+   result of SK_(eq_SkinError)()).  This saves time when errors are ignored.
   
    Yuk.
 */
-extern void SK_(dup_extra_and_update)(SkinError* ec);
+extern void* SK_(dup_extra_and_update) ( Error* err );
 
-/* Return value indicates recognition.  If recognised, type goes in `skind'. */
-extern Bool SK_(recognised_suppression) ( Char* name, SuppKind *skind );
+/* Return value indicates recognition.  If recognised, must set skind using
+   VG_(set_supp_kind)(). */
+extern Bool SK_(recognised_suppression) ( Char* name, Supp* su );
 
-/* Read any extra info for this suppression kind.  For filling up the
-   `string' and `extra' fields in a `SkinSupp' struct if necessary. */
-extern Bool SK_(read_extra_suppression_info) ( Int fd, Char* buf, 
-                                               Int nBuf, SkinSupp *s );
+/* Read any extra info for this suppression kind.  Most likely for filling
+   in the `extra' and `string' parts (with VG_(set_supp_{extra,string})())
+   of a suppression if necessary.  Should return False if a syntax error 
+   occurred, True otherwise. */
+extern Bool SK_(read_extra_suppression_info) ( Int fd, Char* buf, Int nBuf,
+                                               Supp* su );
 
 /* This should just check the kinds match and maybe some stuff in the
-   'extra' field if appropriate */
-extern Bool SK_(error_matches_suppression)(SkinError* ec, SkinSupp* su);
+   `string' and `extra' field if appropriate (using VG_(get_supp_*)() to
+   get the relevant suppression parts). */
+extern Bool SK_(error_matches_suppression)(Error* err, Supp* su);
 
 
 /* ------------------------------------------------------------------ */
@@ -1496,23 +1483,24 @@ extern Bool SK_(handle_client_request) ( ThreadState* tst, UInt* arg_block, UInt
 /* VG_(needs).extends_UCode */
 
 /* Useful to use in VG_(get_Xreg_usage)() */
-#define VG_UINSTR_READS_REG(ono)                \
+#define VG_UINSTR_READS_REG(ono,regs,isWrites)  \
    { if (mycat(u->tag,ono) == tag)              \
-        { arr[n].num     = mycat(u->val,ono);   \
-          arr[n].isWrite = False;               \
+        { regs[n]     = mycat(u->val,ono);      \
+          isWrites[n] = False;                  \
           n++;                                  \
         }                                       \
    }
-#define VG_UINSTR_WRITES_REG(ono)               \
+#define VG_UINSTR_WRITES_REG(ono,regs,isWrites) \
    { if (mycat(u->tag,ono) == tag)              \
-        { arr[n].num     = mycat(u->val,ono);   \
-          arr[n].isWrite = True;                \
+        { regs[n]     = mycat(u->val,ono);      \
+          isWrites[n] = True;                   \
           n++;                                  \
         }                                       \
    }
 
 /* 'X' prefix indicates eXtended UCode. */
-extern Int   SK_(get_Xreg_usage) ( UInstr* u, Tag tag, RegUse* arr );
+extern Int   SK_(get_Xreg_usage) ( UInstr* u, Tag tag, Int* regs,
+                                   Bool* isWrites );
 extern void  SK_(emit_XUInstr)   ( UInstr* u, RRegSet regs_live_before );
 extern Bool  SK_(sane_XUInstr)   ( Bool beforeRA, Bool beforeLiveness,
                                    UInstr* u );
@@ -1536,12 +1524,16 @@ extern void  SK_(post_syscall) ( ThreadId tid, UInt syscallno,
 /* ------------------------------------------------------------------ */
 /* VG_(needs).sizeof_shadow_chunk (if > 0) */
 
+/* Must fill in the `extra' part, using VG_(set_sc_extra)(). */
 extern void SK_(complete_shadow_chunk) ( ShadowChunk* sc, ThreadState* tst );
 
 
 /* ------------------------------------------------------------------ */
 /* VG_(needs).alternative_free */
 
+/* If this need is set, when a dynamic block would normally be free'd, this
+   is called instead.  The block is contained inside the ShadowChunk;  use
+   the VG_(get_sc_*)() functions to access it. */
 extern void SK_(alt_free) ( ShadowChunk* sc, ThreadState* tst );
 
 
index 4b79d9a1e6d992b9055ae43182788cc9c74a42cf..117cb49ad01c86883dc73417db72727a9e9f3ea8 100644 (file)
@@ -74,15 +74,14 @@ static void add_one_Jcc_untaken(void)
    n_Jccs_untaken++;
 }
 
-void SK_(pre_clo_init)(VgDetails* details, VgNeeds* not_used1,
-                       VgTrackEvents* not_used2)
+void SK_(pre_clo_init)(void)
 {
-   details->name             = "Lackey";
-   details->version          = NULL;
-   details->description      = "an example Valgrind skin";
-   details->copyright_author =
-      "Copyright (C) 2002, and GNU GPL'd, by Nicholas Nethercote.";
-   details->bug_reports_to   = "njn25@cam.ac.uk";
+   VG_(details_name)            ("Lackey");
+   VG_(details_version)         (NULL);
+   VG_(details_description)     ("an example Valgrind skin");
+   VG_(details_copyright_author)(
+      "Copyright (C) 2002, and GNU GPL'd, by Nicholas Nethercote.");
+   VG_(details_bug_reports_to)  ("njn25@cam.ac.uk");
 
    VG_(register_compact_helper)((Addr) & add_one_dlrr_call);
    VG_(register_compact_helper)((Addr) & add_one_BB);
@@ -145,8 +144,7 @@ UCodeBlock* SK_(instrument)(UCodeBlock* cb_in, Addr orig_addr)
    UInstr*     u;
    Char        fnname[100];
 
-   cb = VG_(alloc_UCodeBlock)();
-   cb->nextTemp = cb_in->nextTemp;
+   cb = VG_(setup_UCodeBlock)(cb_in);
 
    /* Count call to dlrr(), if this BB is dlrr()'s entry point */
    if (VG_(get_fnname_if_entry)(orig_addr, fnname, 100) &&
@@ -158,8 +156,8 @@ UCodeBlock* SK_(instrument)(UCodeBlock* cb_in, Addr orig_addr)
    /* Count basic block */
    VG_(call_helper_0_0)(cb, (Addr) & add_one_BB);
 
-   for (i = 0; i < cb_in->used; i++) {
-      u = &cb_in->instrs[i];
+   for (i = 0; i < VG_(get_num_instrs)(cb_in); i++) {
+      u = VG_(get_instr)(cb_in, i);
 
       switch (u->opcode) {
          case NOP: case LOCK: case CALLM_S: case CALLM_E:
index 9a4bde2b8fd29abc1df3122b60b10711453e349d..d770deeeae622824d0d86bb686d695c2f346f4e5 100644 (file)
@@ -128,27 +128,29 @@ static Bool eq_AddrInfo ( VgRes res, AddrInfo* ai1, AddrInfo* ai2 )
    are otherwise the same, the faulting addrs and associated rwoffsets
    are allowed to be different.  */
 
-Bool SK_(eq_SkinError) ( VgRes res,
-                          SkinError* e1, SkinError* e2 )
+Bool SK_(eq_SkinError) ( VgRes res, Error* e1, Error* e2 )
 {
-   MemCheckError* e1_extra = e1->extra;
-   MemCheckError* e2_extra = e2->extra;
+   MemCheckError* e1_extra = VG_(get_error_extra)(e1);
+   MemCheckError* e2_extra = VG_(get_error_extra)(e2);
    
-   switch (e1->ekind) {
-      case CoreMemErr:
+   switch (VG_(get_error_kind)(e1)) {
+      case CoreMemErr: {
+         Char *e1s, *e2s;
          if (e1_extra->isWrite != e2_extra->isWrite)   return False;
-         if (e2->ekind != CoreMemErr)                  return False; 
-         if (e1->string == e2->string)                 return True;
-         if (0 == VG_(strcmp)(e1->string, e2->string)) return True;
+         if (VG_(get_error_kind)(e2) != CoreMemErr)    return False; 
+         e1s = VG_(get_error_string)(e1);
+         e2s = VG_(get_error_string)(e2);
+         if (e1s == e2s)                               return True;
+         if (0 == VG_(strcmp)(e1s, e2s))               return True;
          return False;
+      }
 
       case UserErr:
       case ParamErr:
-         if (e1_extra->isWrite != e2_extra->isWrite)
-            return False;
-         if (e1->ekind == ParamErr 
-             && 0 != VG_(strcmp)(e1->string, e2->string))
-            return False;
+         if (e1_extra->isWrite != e2_extra->isWrite)           return False;
+         if (VG_(get_error_kind)(e1) == ParamErr 
+             && 0 != VG_(strcmp)(VG_(get_error_string)(e1),
+                                 VG_(get_error_string)(e2)))   return False;
          return True;
 
       case FreeErr:
@@ -177,7 +179,8 @@ Bool SK_(eq_SkinError) ( VgRes res,
          return True;
 
       default: 
-         VG_(printf)("Error:\n  unknown MemCheck error code %d\n", e1->ekind);
+         VG_(printf)("Error:\n  unknown MemCheck error code %d\n",
+                     VG_(get_error_kind)(e1));
          VG_(skin_panic)("unknown error code in SK_(eq_SkinError)");
    }
 }
@@ -237,19 +240,19 @@ static void pp_AddrInfo ( Addr a, AddrInfo* ai )
    }
 }
 
-void SK_(pp_SkinError) ( SkinError* err, void (*pp_ExeContext)(void) )
+void SK_(pp_SkinError) ( Error* err, void (*pp_ExeContext)(void) )
 {
-   MemCheckError* err_extra = err->extra;
+   MemCheckError* err_extra = VG_(get_error_extra)(err);
 
-   switch (err->ekind) {
+   switch (VG_(get_error_kind)(err)) {
       case CoreMemErr:
          if (err_extra->isWrite) {
             VG_(message)(Vg_UserMsg, 
-               "%s contains unaddressable byte(s)", err->string );
+               "%s contains unaddressable byte(s)", VG_(get_error_string)(err));
          } else {
             VG_(message)(Vg_UserMsg, 
                 "%s contains uninitialised or unaddressable byte(s)",
-                err->string);
+                VG_(get_error_string)(err));
          }
          pp_ExeContext();
          break;
@@ -285,33 +288,33 @@ void SK_(pp_SkinError) ( SkinError* err, void (*pp_ExeContext)(void) )
                VG_(skin_panic)("pp_SkinError(axskind)");
          }
          pp_ExeContext();
-         pp_AddrInfo(err->addr, &err_extra->addrinfo);
+         pp_AddrInfo(VG_(get_error_address)(err), &err_extra->addrinfo);
          break;
 
       case FreeErr:
          VG_(message)(Vg_UserMsg,"Invalid free() / delete / delete[]");
          /* fall through */
       case FreeMismatchErr:
-         if (err->ekind == FreeMismatchErr)
+         if (VG_(get_error_kind)(err) == FreeMismatchErr)
             VG_(message)(Vg_UserMsg, 
                          "Mismatched free() / delete / delete []");
          pp_ExeContext();
-         pp_AddrInfo(err->addr, &err_extra->addrinfo);
+         pp_AddrInfo(VG_(get_error_address)(err), &err_extra->addrinfo);
          break;
 
       case ParamErr:
          if (err_extra->isWrite) {
             VG_(message)(Vg_UserMsg, 
                "Syscall param %s contains unaddressable byte(s)",
-                err->string );
+                VG_(get_error_string)(err));
          } else {
             VG_(message)(Vg_UserMsg, 
                 "Syscall param %s contains uninitialised or "
                 "unaddressable byte(s)",
-            err->string);
+                VG_(get_error_string)(err));
          }
          pp_ExeContext();
-         pp_AddrInfo(err->addr, &err_extra->addrinfo);
+         pp_AddrInfo(VG_(get_error_address)(err), &err_extra->addrinfo);
          break;
 
       case UserErr:
@@ -324,11 +327,12 @@ void SK_(pp_SkinError) ( SkinError* err, void (*pp_ExeContext)(void) )
                "unaddressable byte(s) found during client check request");
          }
          pp_ExeContext();
-         pp_AddrInfo(err->addr, &err_extra->addrinfo);
+         pp_AddrInfo(VG_(get_error_address)(err), &err_extra->addrinfo);
          break;
 
       default: 
-         VG_(printf)("Error:\n  unknown MemCheck error code %d\n", err->ekind);
+         VG_(printf)("Error:\n  unknown MemCheck error code %d\n",
+                     VG_(get_error_kind)(err));
          VG_(skin_panic)("unknown error code in SK_(pp_SkinError)");
    }
 }
@@ -356,7 +360,8 @@ static void describe_addr ( Addr a, AddrInfo* ai )
    /* Closure for searching malloc'd and free'd lists */
    Bool addr_is_in_block(ShadowChunk *sh_ch)
    {
-      return VG_(addr_is_in_block) ( a, sh_ch->data, sh_ch->size );
+      return VG_(addr_is_in_block) ( a, VG_(get_sc_data)(sh_ch),
+                                        VG_(get_sc_size)(sh_ch) );
    }
 
    /* Perhaps it's a user-def'd block ? */
@@ -374,18 +379,18 @@ static void describe_addr ( Addr a, AddrInfo* ai )
    sc = SK_(any_matching_freed_ShadowChunks)(addr_is_in_block);
    if (NULL != sc) {
       ai->akind      = Freed;
-      ai->blksize    = sc->size;
-      ai->rwoffset   = (Int)(a) - (Int)(sc->data);
-      ai->lastchange = (ExeContext*)sc->skin_extra[0];
+      ai->blksize    = VG_(get_sc_size)(sc);
+      ai->rwoffset   = (Int)(a) - (Int)(VG_(get_sc_data)(sc));
+      ai->lastchange = (ExeContext*)( VG_(get_sc_extra)(sc, 0) );
       return;
    }
    /* Search for a currently malloc'd block which might bracket it. */
    sc = VG_(any_matching_mallocd_ShadowChunks)(addr_is_in_block);
    if (NULL != sc) {
       ai->akind      = Mallocd;
-      ai->blksize    = sc->size;
-      ai->rwoffset   = (Int)(a) - (Int)(sc->data);
-      ai->lastchange = (ExeContext*)sc->skin_extra[0];
+      ai->blksize    = VG_(get_sc_size)(sc);
+      ai->rwoffset   = (Int)(a) - (Int)(VG_(get_sc_data)(sc));
+      ai->lastchange = (ExeContext*)( VG_(get_sc_extra)(sc, 0) );
       return;
    } 
    /* Clueless ... */
@@ -394,19 +399,19 @@ static void describe_addr ( Addr a, AddrInfo* ai )
 }
 
 
-/* Creates a copy of the err_extra, updates the copy with address info if
-   necessary, sticks the copy into the SkinError. */
-void SK_(dup_extra_and_update)(SkinError* err)
+/* Creates a copy of the `extra' part, updates the copy with address info if
+   necessary, and returns the copy. */
+void* SK_(dup_extra_and_update)( Error* err )
 {
-   MemCheckError* err_extra;
+   MemCheckError* new_extra;
 
-   err_extra  = VG_(malloc)(sizeof(MemCheckError));
-   *err_extra = *((MemCheckError*)err->extra);
+   new_extra  = VG_(malloc)(sizeof(MemCheckError));
+   *new_extra = *((MemCheckError*)VG_(get_error_extra)(err));
 
-   if (err_extra->addrinfo.akind == Undescribed)
-      describe_addr ( err->addr, &(err_extra->addrinfo) );
+   if (new_extra->addrinfo.akind == Undescribed)
+      describe_addr ( VG_(get_error_address)(err), &(new_extra->addrinfo) );
 
-   err->extra = err_extra;
+   return new_extra;
 }
 
 /* These two are called from generated code. */
@@ -530,51 +535,56 @@ void SK_(record_user_error) ( ThreadState* tst, Addr a, Bool isWrite )
 #define STREQ(s1,s2) (s1 != NULL && s2 != NULL \
                       && VG_(strcmp)((s1),(s2))==0)
 
-Bool SK_(recognised_suppression) ( Char* name, SuppKind *skind )
+Bool SK_(recognised_suppression) ( Char* name, Supp* su )
 {
-   if      (STREQ(name, "Param"))   *skind = ParamSupp;
-   else if (STREQ(name, "CoreMem")) *skind = CoreMemSupp;
-   else if (STREQ(name, "Value0"))  *skind = Value0Supp; /* backwards compat */ 
-   else if (STREQ(name, "Cond"))    *skind = Value0Supp;
-   else if (STREQ(name, "Value1"))  *skind = Value1Supp;
-   else if (STREQ(name, "Value2"))  *skind = Value2Supp;
-   else if (STREQ(name, "Value4"))  *skind = Value4Supp;
-   else if (STREQ(name, "Value8"))  *skind = Value8Supp;
-   else if (STREQ(name, "Addr1"))   *skind = Addr1Supp;
-   else if (STREQ(name, "Addr2"))   *skind = Addr2Supp;
-   else if (STREQ(name, "Addr4"))   *skind = Addr4Supp;
-   else if (STREQ(name, "Addr8"))   *skind = Addr8Supp;
-   else if (STREQ(name, "Free"))    *skind = FreeSupp;
+   SuppKind skind;
+   
+   if      (STREQ(name, "Param"))   skind = ParamSupp;
+   else if (STREQ(name, "CoreMem")) skind = CoreMemSupp;
+   else if (STREQ(name, "Value0"))  skind = Value0Supp; /* backwards compat */ 
+   else if (STREQ(name, "Cond"))    skind = Value0Supp;
+   else if (STREQ(name, "Value1"))  skind = Value1Supp;
+   else if (STREQ(name, "Value2"))  skind = Value2Supp;
+   else if (STREQ(name, "Value4"))  skind = Value4Supp;
+   else if (STREQ(name, "Value8"))  skind = Value8Supp;
+   else if (STREQ(name, "Addr1"))   skind = Addr1Supp;
+   else if (STREQ(name, "Addr2"))   skind = Addr2Supp;
+   else if (STREQ(name, "Addr4"))   skind = Addr4Supp;
+   else if (STREQ(name, "Addr8"))   skind = Addr8Supp;
+   else if (STREQ(name, "Free"))    skind = FreeSupp;
    else 
       return False;
 
+   VG_(set_supp_kind)(su, skind);
    return True;
 }
 
-Bool SK_(read_extra_suppression_info) ( Int fd, Char* buf, Int nBuf, 
-                                         SkinSupp *s )
+Bool SK_(read_extra_suppression_info) ( Int fd, Char* buf, Int nBuf, Supp *su )
 {
    Bool eof;
 
-   if (s->skind == ParamSupp) {
+   if (VG_(get_supp_kind)(su) == ParamSupp) {
       eof = VG_(get_line) ( fd, buf, nBuf );
       if (eof) return False;
-      s->string = VG_(strdup)(buf);
+      VG_(set_supp_string)(su, VG_(strdup)(buf));
    }
    return True;
 }
 
-extern Bool SK_(error_matches_suppression)(SkinError* err, SkinSupp* su)
+extern Bool SK_(error_matches_suppression)(Error* err, Supp* su)
 {
    UInt su_size;
-   MemCheckError* err_extra = err->extra;
+   MemCheckError* err_extra = VG_(get_error_extra)(err);
+   ErrorKind      ekind     = VG_(get_error_kind )(err);
 
-   switch (su->skind) {
+   switch (VG_(get_supp_kind)(su)) {
       case ParamSupp:
-         return (err->ekind == ParamErr && STREQ(su->string, err->string));
+         return (ekind == ParamErr 
+              && STREQ(VG_(get_error_string)(err), VG_(get_supp_string)(su)));
 
       case CoreMemSupp:
-         return (err->ekind == CoreMemErr && STREQ(su->string, err->string));
+         return (ekind == CoreMemErr
+              && STREQ(VG_(get_error_string)(err), VG_(get_supp_string)(su)));
 
       case Value0Supp: su_size = 0; goto value_case;
       case Value1Supp: su_size = 1; goto value_case;
@@ -582,21 +592,22 @@ extern Bool SK_(error_matches_suppression)(SkinError* err, SkinSupp* su)
       case Value4Supp: su_size = 4; goto value_case;
       case Value8Supp: su_size = 8; goto value_case;
       value_case:
-         return (err->ekind == ValueErr && err_extra->size == su_size);
+         return (ekind == ValueErr && err_extra->size == su_size);
 
       case Addr1Supp: su_size = 1; goto addr_case;
       case Addr2Supp: su_size = 2; goto addr_case;
       case Addr4Supp: su_size = 4; goto addr_case;
       case Addr8Supp: su_size = 8; goto addr_case;
       addr_case:
-         return (err->ekind == AddrErr && err_extra->size == su_size);
+         return (ekind == AddrErr && err_extra->size == su_size);
 
       case FreeSupp:
-         return (err->ekind == FreeErr || err->ekind == FreeMismatchErr);
+         return (ekind == FreeErr || ekind == FreeMismatchErr);
 
       default:
          VG_(printf)("Error:\n"
-                     "  unknown MemCheck suppression type %d\n", su->skind);
+                     "  unknown MemCheck suppression type %d\n",
+                     VG_(get_supp_kind)(su));
          VG_(skin_panic)("unknown suppression type in "
                          "SK_(error_matches_suppression)");
    }
index 288359a166f766a862db424cb845c173ac540ead..0d6e0f7fdc9c42869d65f059039476d37dcd699f 100644 (file)
@@ -1519,18 +1519,18 @@ void fpu_write_check_SLOWLY ( Addr addr, Int size )
 static __inline__
 void set_where( ShadowChunk* sc, ExeContext* ec )
 {
-   sc->skin_extra[0] = (UInt)ec;
+   VG_(set_sc_extra)( sc, 0, (UInt)ec );
 }
 
 static __inline__
 ExeContext *get_where( ShadowChunk* sc )
 {
-   return (ExeContext*)sc->skin_extra[0];
+   return (ExeContext*)VG_(get_sc_extra)(sc, 0);
 }
 
 void SK_(complete_shadow_chunk) ( ShadowChunk* sc, ThreadState* tst )
 {
-   set_where( sc, VG_(get_ExeContext) ( tst ) );
+   VG_(set_sc_extra) ( sc, 0, (UInt)VG_(get_ExeContext)(tst) );
 }
 
 /*------------------------------------------------------------*/
@@ -1547,7 +1547,7 @@ static __attribute__ ((unused))
 {
    ShadowChunk* sc;
    Int n = 0;
-   for (sc = vg_freed_list_start; sc != NULL; sc = sc->next)
+   for (sc = vg_freed_list_start; sc != NULL; sc = VG_(get_sc_next)(sc))
       n++;
    return n;
 }
@@ -1558,8 +1558,8 @@ static __attribute__ ((unused))
    ShadowChunk* sc;
    Int n = 0;
    /* VG_(printf)("freelist sanity\n"); */
-   for (sc = vg_freed_list_start; sc != NULL; sc = sc->next)
-      n += sc->size;
+   for (sc = vg_freed_list_start; sc != NULL; sc = VG_(get_sc_next)(sc))
+      n += VG_(get_sc_size)(sc);
    sk_assert(n == vg_freed_list_volume);
 }
 
@@ -1573,14 +1573,14 @@ static void add_to_freed_queue ( ShadowChunk* sc )
    if (vg_freed_list_end == NULL) {
       sk_assert(vg_freed_list_start == NULL);
       vg_freed_list_end = vg_freed_list_start = sc;
-      vg_freed_list_volume = sc->size;
+      vg_freed_list_volume = VG_(get_sc_size)(sc);
    } else {    
-      sk_assert(vg_freed_list_end->next == NULL);
-      vg_freed_list_end->next = sc;
+      sk_assert(VG_(get_sc_next)(vg_freed_list_end) == NULL);
+      VG_(set_sc_next)(vg_freed_list_end, sc);
       vg_freed_list_end = sc;
-      vg_freed_list_volume += sc->size;
+      vg_freed_list_volume += VG_(get_sc_size)(sc);
    }
-   sc->next = NULL;
+   VG_(set_sc_next)(sc, NULL);
 
    /* Release enough of the oldest blocks to bring the free queue
       volume below vg_clo_freelist_vol. */
@@ -1591,16 +1591,16 @@ static void add_to_freed_queue ( ShadowChunk* sc )
       sk_assert(vg_freed_list_end != NULL);
 
       sc1 = vg_freed_list_start;
-      vg_freed_list_volume -= sc1->size;
+      vg_freed_list_volume -= VG_(get_sc_size)(sc1);
       /* VG_(printf)("volume now %d\n", vg_freed_list_volume); */
       sk_assert(vg_freed_list_volume >= 0);
 
       if (vg_freed_list_start == vg_freed_list_end) {
          vg_freed_list_start = vg_freed_list_end = NULL;
       } else {
-         vg_freed_list_start = sc1->next;
+         vg_freed_list_start = VG_(get_sc_next)(sc1);
       }
-      sc1->next = NULL; /* just paranoia */
+      VG_(set_sc_next)(sc1, NULL); /* just paranoia */
       VG_(free_ShadowChunk) ( sc1 );
    }
 }
@@ -1613,7 +1613,7 @@ ShadowChunk* SK_(any_matching_freed_ShadowChunks)
 
    /* No point looking through freed blocks if we're not keeping
       them around for a while... */
-   for (sc = vg_freed_list_start; sc != NULL; sc = sc->next)
+   for (sc = vg_freed_list_start; sc != NULL; sc = VG_(get_sc_next)(sc))
       if (p(sc))
          return sc;
 
@@ -1937,57 +1937,56 @@ Char* SK_(usage)(void)
 /*--- Setup                                                ---*/
 /*------------------------------------------------------------*/
 
-void SK_(pre_clo_init)(VgDetails* details, VgNeeds* needs, VgTrackEvents* track)
-{
-   details->name             = "Memcheck";
-   details->version          = NULL;
-   details->description      = "a.k.a. Valgrind, a memory error detector";
-   details->copyright_author =
-      "Copyright (C) 2000-2002, and GNU GPL'd, by Julian Seward.";
-   details->bug_reports_to   = "jseward@acm.org";
-
-   needs->core_errors          = True;
-   needs->skin_errors          = True;
-   needs->libc_freeres         = True;
-   needs->sizeof_shadow_block  = 1;
-   needs->basic_block_discards = False;
-   needs->shadow_regs          = True;
-   needs->command_line_options = True;
-   needs->client_requests      = True;
-   needs->extended_UCode       = True;
-   needs->syscall_wrapper      = True;
-   needs->alternative_free     = True;
-   needs->sanity_checks        = True;
-
-   track->new_mem_startup       = & memcheck_new_mem_startup;
-   track->new_mem_heap          = & memcheck_new_mem_heap;
-   track->new_mem_stack         = & SK_(make_writable);
-   track->new_mem_stack_aligned = & make_writable_aligned;
-   track->new_mem_stack_signal  = & SK_(make_writable);
-   track->new_mem_brk           = & SK_(make_writable);
-   track->new_mem_mmap          = & memcheck_set_perms;
+void SK_(pre_clo_init)(void)
+{
+   VG_(details_name)            ("Memcheck");
+   VG_(details_version)         (NULL);
+   VG_(details_description)     ("a.k.a. Valgrind, a memory error detector");
+   VG_(details_copyright_author)(
+      "Copyright (C) 2002, and GNU GPL'd, by Julian Seward.");
+   VG_(details_bug_reports_to)  ("jseward@acm.org");
+
+   VG_(needs_core_errors)         ();
+   VG_(needs_skin_errors)         ();
+   VG_(needs_libc_freeres)        ();
+   VG_(needs_sizeof_shadow_block) ( 1 );
+   VG_(needs_shadow_regs)         ();
+   VG_(needs_command_line_options)();
+   VG_(needs_client_requests)     ();
+   VG_(needs_extended_UCode)      ();
+   VG_(needs_syscall_wrapper)     ();
+   VG_(needs_alternative_free)    ();
+   VG_(needs_sanity_checks)       ();
+
+   VG_(track_new_mem_startup)      ( & memcheck_new_mem_startup );
+   VG_(track_new_mem_heap)         ( & memcheck_new_mem_heap );
+   VG_(track_new_mem_stack)        ( & SK_(make_writable) );
+   VG_(track_new_mem_stack_aligned)( & make_writable_aligned );
+   VG_(track_new_mem_stack_signal) ( & SK_(make_writable) );
+   VG_(track_new_mem_brk)          ( & SK_(make_writable) );
+   VG_(track_new_mem_mmap)         ( & memcheck_set_perms );
    
-   track->copy_mem_heap         = & copy_address_range_state;
-   track->copy_mem_remap        = & copy_address_range_state;
-   track->change_mem_mprotect   = & memcheck_set_perms;
+   VG_(track_copy_mem_heap)        ( & copy_address_range_state );
+   VG_(track_copy_mem_remap)       ( & copy_address_range_state );
+   VG_(track_change_mem_mprotect)  ( & memcheck_set_perms );
       
-   track->ban_mem_heap          = & SK_(make_noaccess);
-   track->ban_mem_stack         = & SK_(make_noaccess);
-
-   track->die_mem_heap          = & SK_(make_noaccess);
-   track->die_mem_stack         = & SK_(make_noaccess);
-   track->die_mem_stack_aligned = & make_noaccess_aligned
-   track->die_mem_stack_signal  = & SK_(make_noaccess); 
-   track->die_mem_brk           = & SK_(make_noaccess);
-   track->die_mem_munmap        = & SK_(make_noaccess); 
-
-   track->bad_free              = & SK_(record_free_error);
-   track->mismatched_free       = & SK_(record_freemismatch_error);
-
-   track->pre_mem_read          = & check_is_readable;
-   track->pre_mem_read_asciiz   = & check_is_readable_asciiz;
-   track->pre_mem_write         = & check_is_writable;
-   track->post_mem_write        = & SK_(make_readable);
+   VG_(track_ban_mem_heap)         ( & SK_(make_noaccess) );
+   VG_(track_ban_mem_stack)        ( & SK_(make_noaccess) );
+
+   VG_(track_die_mem_heap)         ( & SK_(make_noaccess) );
+   VG_(track_die_mem_stack)        ( & SK_(make_noaccess) );
+   VG_(track_die_mem_stack_aligned)( & make_noaccess_aligned )
+   VG_(track_die_mem_stack_signal) ( & SK_(make_noaccess) ); 
+   VG_(track_die_mem_brk)          ( & SK_(make_noaccess) );
+   VG_(track_die_mem_munmap)       ( & SK_(make_noaccess) ); 
+
+   VG_(track_bad_free)             ( & SK_(record_free_error) );
+   VG_(track_mismatched_free)      ( & SK_(record_freemismatch_error) );
+
+   VG_(track_pre_mem_read)         ( & check_is_readable );
+   VG_(track_pre_mem_read_asciiz)  ( & check_is_readable_asciiz );
+   VG_(track_pre_mem_write)        ( & check_is_writable );
+   VG_(track_post_mem_write)       ( & SK_(make_readable) );
 
    VG_(register_compact_helper)((Addr) & SK_(helper_value_check4_fail));
    VG_(register_compact_helper)((Addr) & SK_(helper_value_check0_fail));
index 657b99801cfd072466cd651ebc8af1696a6a6e10..faa270e07c1a9f5449ebf9fb00744497e609f57c 100644 (file)
@@ -237,14 +237,13 @@ void SK_(pp_XUInstr)(UInstr* u)
 
 }
 
-Int SK_(get_Xreg_usage)(UInstr* u, Tag tag, RegUse* arr)
+Int SK_(get_Xreg_usage)(UInstr* u, Tag tag, Int* regs, Bool* isWrites)
 {
-#  define RD(ono)    VG_UINSTR_READS_REG(ono)
-#  define WR(ono)    VG_UINSTR_WRITES_REG(ono)
+#  define RD(ono)    VG_UINSTR_READS_REG(ono, regs, isWrites)
+#  define WR(ono)    VG_UINSTR_WRITES_REG(ono, regs, isWrites)
 
    Int n = 0;
    switch (u->opcode) {        
-
       case TAG1:    RD(1); WR(1);        break;
       case TAG2:    RD(1); RD(2); WR(2); break;
       case LOADV:   RD(1); WR(2);        break;
@@ -499,8 +498,8 @@ static UCodeBlock* memcheck_instrument ( UCodeBlock* cb_in )
    UInstr*     u_in;
    Int         qs, qd, qt, qtt;
    Bool        bogusLiterals;
-   cb = VG_(alloc_UCodeBlock)();
-   cb->nextTemp = cb_in->nextTemp;
+
+   cb = VG_(setup_UCodeBlock)(cb_in);
 
    /* Scan the block to look for bogus literals.  These are magic
       numbers which particularly appear in hand-optimised / inlined
@@ -511,8 +510,8 @@ static UCodeBlock* memcheck_instrument ( UCodeBlock* cb_in )
    bogusLiterals = False;
 
    if (SK_(clo_avoid_strlen_errors)) {
-      for (i = 0; i < cb_in->used; i++) {
-         u_in = &cb_in->instrs[i];
+      for (i = 0; i < VG_(get_num_instrs)(cb_in); i++) {
+         u_in = VG_(get_instr)(cb_in, i);
          switch (u_in->opcode) {
             case ADD: case SUB: case MOV: 
                if (u_in->size == 4 && u_in->tag1 == Literal)
@@ -535,9 +534,9 @@ static UCodeBlock* memcheck_instrument ( UCodeBlock* cb_in )
       }
    }
 
-   for (i = 0; i < cb_in->used; i++) {
+   for (i = 0; i < VG_(get_num_instrs)(cb_in); i++) {
+      u_in = VG_(get_instr)(cb_in, i);
       qs = qd = qt = qtt = INVALID_TEMPREG;
-      u_in = &cb_in->instrs[i];
 
       switch (u_in->opcode) {
 
@@ -853,8 +852,8 @@ static UCodeBlock* memcheck_instrument ( UCodeBlock* cb_in )
             uInstr1(cb, SETV, 0, TempReg, qt);
 
             uInstr2(cb, CMOV, 4, TempReg, qs, TempReg, qd);
-            LAST_UINSTR(cb).cond    = u_in->cond;
-            LAST_UINSTR(cb).flags_r = u_in->flags_r;
+            uCond(cb, u_in->cond);         
+            uFlagsRWU(cb, u_in->flags_r, u_in->flags_w, FlagsEmpty);
 
             VG_(copy_UInstr)(cb, u_in);
             break;
@@ -977,8 +976,8 @@ static UCodeBlock* memcheck_instrument ( UCodeBlock* cb_in )
             qt  = newShadow(cb);
             qtt = newShadow(cb);
             uInstr1(cb, SETV, 0, TempReg, qt);
-            for (j = i-1; cb_in->instrs[j].opcode != CALLM_S; j--) {
-               uu = & cb_in->instrs[j];
+            for (j = i-1; VG_(get_instr)(cb_in, j)->opcode != CALLM_S; j--) {
+               uu = VG_(get_instr)(cb_in, j);
                if (uu->opcode != PUSH) continue;
                /* cast via a temporary */
                uInstr2(cb, MOV, 4, TempReg, SHADOW(uu->val1),
@@ -1003,8 +1002,8 @@ static UCodeBlock* memcheck_instrument ( UCodeBlock* cb_in )
                a dummy tempreg. 
             */
             res_used = False;
-            for (j = i+1; cb_in->instrs[j].opcode != CALLM_E; j++) {
-               uu = & cb_in->instrs[j];
+            for (j = i+1; VG_(get_instr)(cb_in, j)->opcode != CALLM_E; j++) {
+               uu = VG_(get_instr)(cb_in, j);
                if (uu->opcode != POP) continue;
                /* Cast via a temp. */
                uInstr2(cb, MOV, 4, TempReg, qt, TempReg, qtt);
@@ -1139,10 +1138,11 @@ Bool VG_(clo_memcheck_codegen) = False;
 static void vg_delete_redundant_SETVs ( UCodeBlock* cb )
 {
    Int     i, j, k;
-   Int     n_temps = cb->nextTemp;
+   Int     n_temps = VG_(get_num_temps)(cb);
    Bool*   next_is_write;
    UInstr* u;
-   RegUse  tempUse[3];
+   Int     tempUse[3];
+   Bool    isWrites[3];
 
    if (n_temps == 0) return;
 
@@ -1150,8 +1150,8 @@ static void vg_delete_redundant_SETVs ( UCodeBlock* cb )
 
    for (i = 0; i < n_temps; i++) next_is_write[i] = True;
 
-   for (i = cb->used-1; i >= 0; i--) {
-      u = &cb->instrs[i];
+   for (i = VG_(get_num_instrs)(cb) - 1; i >= 0; i--) {
+      u = VG_(get_instr)(cb, i);
 
       /* If we're not checking address V bits, there will be a lot of
          GETVs, TAG1s and TAG2s calculating values which are never
@@ -1211,11 +1211,10 @@ static void vg_delete_redundant_SETVs ( UCodeBlock* cb )
 
       } else {
          /* Find out what this insn does to the temps. */
-         k = VG_(get_reg_usage)(u, TempReg, &tempUse[0]);
+         k = VG_(get_reg_usage)(u, TempReg, &tempUse[0], &isWrites[0]);
          sk_assert(k <= 3);
          for (j = k-1; j >= 0; j--) {
-            next_is_write[ tempUse[j].num ]
-                         = tempUse[j].isWrite;
+            next_is_write[ tempUse[j] ] = isWrites[j];
          }
       }
    }
@@ -1239,10 +1238,11 @@ static void vg_delete_redundant_SETVs ( UCodeBlock* cb )
 static void vg_propagate_definedness ( UCodeBlock* cb )
 {
    Int     i, j, k, t;
-   Int     n_temps = cb->nextTemp;
+   Int     n_temps = VG_(get_num_temps)(cb);
    UChar*  def;
    UInstr* u;
-   RegUse  tempUse[3];
+   Int     tempUse[3];
+   Bool    isWrites[3];
 
    if (n_temps == 0) return;
 
@@ -1253,8 +1253,8 @@ static void vg_propagate_definedness ( UCodeBlock* cb )
 
    /* Run forwards, detecting and using the all-defined property. */
 
-   for (i = 0; i < cb->used; i++) {
-      u = &cb->instrs[i];
+   for (i = 0; i < VG_(get_num_instrs)(cb); i++) {
+      u = VG_(get_instr)(cb, i);
       switch (u->opcode) {
 
       /* Tag-handling uinstrs. */
@@ -1470,12 +1470,12 @@ static void vg_propagate_definedness ( UCodeBlock* cb )
          unhandled:
             /* We don't know how to handle this uinstr.  Be safe, and 
                set to VGC_VALUE or VGC_UNDEF all temps written by it. */
-            k = VG_(get_reg_usage)(u, TempReg, &tempUse[0]);
+            k = VG_(get_reg_usage)(u, TempReg, &tempUse[0], &isWrites[0]);
             sk_assert(k <= 3);
             for (j = 0; j < k; j++) {
-               t = tempUse[j].num;
+               t = tempUse[j];
                sk_assert(t >= 0 && t < n_temps);
-               if (!tempUse[j].isWrite) {
+               if (!isWrites[j]) {
                   /* t is read; ignore it. */
                   if (0&& VGC_IS_SHADOW(t) && def[t] <= 4)
                      VG_(printf)("ignoring def %d at %s %s\n", 
index 609e6e3fc209bb0f8914af1cb4ad2c0a74398c3d..dc31c817079de57d6cdf7ae0fb6ecd68b5db6350 100644 (file)
 
 VG_DETERMINE_INTERFACE_VERSION
 
-void SK_(pre_clo_init)(VgDetails* details, VgNeeds* not_used1,
-                       VgTrackEvents* not_used2) 
+void SK_(pre_clo_init)(void)
 {
-   details->name             = "Nulgrind";
-   details->version          = NULL;
-   details->description      = "a binary JIT-compiler";
-   details->copyright_author =
-      "Copyright (C) 2002, and GNU GPL'd, by Nicholas Nethercote.";
-   details->bug_reports_to   = "njn25@cam.ac.uk";
+   VG_(details_name)            ("Nulgrind");
+   VG_(details_version)         (NULL);
+   VG_(details_description)     ("a binary JIT-compiler");
+   VG_(details_copyright_author)(
+      "Copyright (C) 2002, and GNU GPL'd, by Nicholas Nethercote.");
+   VG_(details_bug_reports_to)  ("njn25@cam.ac.uk");
 
    /* No needs, no core events to track */
 }