]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Yay! Opera (6.0TP2) now works.
authorJulian Seward <jseward@acm.org>
Thu, 18 Apr 2002 11:37:52 +0000 (11:37 +0000)
committerJulian Seward <jseward@acm.org>
Thu, 18 Apr 2002 11:37:52 +0000 (11:37 +0000)
Various enhancements:

* Make the error message system more thread-aware.

* Fix stupid bug in do_pthread_create causing incorrect initial
  %ESP values sometimes.

* Fix various other minor things needed to make opera work.

Performance of threaded apps is pretty terrible.  This needs
looking into.

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

15 files changed:
coregrind/arch/x86-linux/vg_libpthread.c
coregrind/vg_clientmalloc.c
coregrind/vg_errcontext.c
coregrind/vg_include.h
coregrind/vg_libpthread.c
coregrind/vg_memory.c
coregrind/vg_scheduler.c
coregrind/vg_translate.c
vg_clientmalloc.c
vg_errcontext.c
vg_include.h
vg_libpthread.c
vg_memory.c
vg_scheduler.c
vg_translate.c

index f32c5533eaa60d03c6d61654fa2fe50052d26cd5..8ee3ccb10e657143c265ce38133365fe726a5b72 100644 (file)
@@ -499,6 +499,13 @@ int send(int s, const void *msg, size_t len, int flags)
    return __libc_send(s, msg, len, flags);
 }
 
+extern
+int __libc_recv(int s, void *buf, size_t len, int flags);
+int recv(int s, void *buf, size_t len, int flags)
+{
+   return __libc_recv(s, buf, len, flags);
+}
+
 
 /*--------------------------------------------------*/
 
index dca0e3e5cbe74526901c42ee53479dd844a15fad..b1848405aa0f3c0c10728c1c8f7f88f148a4ad03 100644 (file)
@@ -529,15 +529,17 @@ void VG_(describe_addr) ( Addr a, AddrInfo* ai )
    ShadowChunk* sc;
    UInt         ml_no;
    Bool         ok;
+   ThreadId     tid;
 
    /* Perhaps it's a user-def'd block ? */
    ok = VG_(client_perm_maybe_describe)( a, ai );
    if (ok)
       return;
-   /* Perhaps it's on the stack? */
-   if (VG_(is_plausible_stack_addr)(a)
-       && a >= (Addr)VG_(baseBlock)[VGOFF_(m_esp)]) {
-      ai->akind = Stack;
+   /* Perhaps it's on a thread's stack? */
+   tid = VG_(identify_stack_addr)(a);
+   if (tid != VG_INVALID_THREADID) {
+      ai->akind     = Stack;
+      ai->stack_tid = tid;
       return;
    }
    /* Search for a freed block which might bracket it. */
index c632124eaa026e74e2b673b62e5681e7cfae934b..0ac2cb36b4855d1d5fc5325bba41f0fe4b053ad8 100644 (file)
@@ -142,6 +142,8 @@ typedef
       Char* syscall_param;
       /* Param, User */
       Bool isWriteableLack;
+      /* ALL */
+      ThreadId tid;
    } 
    ErrContext;
 
@@ -174,6 +176,7 @@ static void clear_AddrInfo ( AddrInfo* ai )
    ai->blksize    = 0;
    ai->rwoffset   = 0;
    ai->lastchange = NULL;
+   ai->stack_tid  = VG_INVALID_THREADID;
 }
 
 static void clear_ErrContext ( ErrContext* ec )
@@ -189,6 +192,7 @@ static void clear_ErrContext ( ErrContext* ec )
    clear_AddrInfo ( &ec->addrinfo );
    ec->syscall_param   = NULL;
    ec->isWriteableLack = False;
+   ec->tid     = VG_INVALID_THREADID;
 }
 
 
@@ -264,7 +268,9 @@ static void pp_AddrInfo ( Addr a, AddrInfo* ai )
 {
    switch (ai->akind) {
       case Stack: 
-         VG_(message)(Vg_UserMsg, "   Address 0x%x is on the stack", a);
+         VG_(message)(Vg_UserMsg, 
+                      "   Address 0x%x is on thread %d's stack", 
+                      ai->stack_tid, a);
          break;
       case Unknown:
          VG_(message)(Vg_UserMsg, 
@@ -309,6 +315,8 @@ static void pp_ErrContext ( ErrContext* ec, Bool printCount )
 {
    if (printCount)
       VG_(message)(Vg_UserMsg, "Observed %d times:", ec->count );
+   if (ec->tid > 0)
+      VG_(message)(Vg_UserMsg, "Thread %d:", ec->tid );
    switch (ec->ekind) {
       case ValueErr:
          if (ec->size == 0) {
@@ -441,6 +449,8 @@ static void VG_(maybe_add_context) ( ErrContext* ec )
    static Bool slowdown_message       = False;
    static Int  vg_n_errs_shown        = 0;
 
+   vg_assert(ec->tid >= 0 && ec->tid < VG_N_THREADS);
+
    /* After M_VG_COLLECT_NO_ERRORS_AFTER different errors have been
       found, just refuse to collect any more. */
    if (vg_n_errs_shown >= M_VG_COLLECT_NO_ERRORS_AFTER) {
@@ -551,6 +561,7 @@ void VG_(record_value_error) ( Int size )
                                           VG_(baseBlock)[VGOFF_(m_ebp)] );
    ec.ekind = ValueErr;
    ec.size  = size;
+   ec.tid   = VG_(get_current_tid)();
    VG_(maybe_add_context) ( &ec );
 }
 
@@ -573,26 +584,27 @@ void VG_(record_address_error) ( Addr a, Int size, Bool isWrite )
    ec.axskind = isWrite ? WriteAxs : ReadAxs;
    ec.size    = size;
    ec.addr    = a;
+   ec.tid     = VG_(get_current_tid)();
    VG_(describe_addr) ( a, &ec.addrinfo );
    VG_(maybe_add_context) ( &ec );
 }
 
-void VG_(record_jump_error) ( Addr a )
+void VG_(record_free_error) ( Addr a )
 {
    ErrContext ec;
    clear_ErrContext( &ec );
    ec.count   = 1;
    ec.next    = NULL;
-   ec.where   = VG_(get_ExeContext)( False, VG_(baseBlock)[VGOFF_(m_eip)], 
-                                            VG_(baseBlock)[VGOFF_(m_ebp)] );
-   ec.ekind   = AddrErr;
-   ec.axskind = ExecAxs;
+   ec.where   = VG_(get_ExeContext)( True, VG_(baseBlock)[VGOFF_(m_eip)], 
+                                           VG_(baseBlock)[VGOFF_(m_ebp)] );
+   ec.ekind   = FreeErr;
    ec.addr    = a;
+   ec.tid     = VG_(get_current_tid)();
    VG_(describe_addr) ( a, &ec.addrinfo );
    VG_(maybe_add_context) ( &ec );
 }
 
-void VG_(record_free_error) ( Addr a )
+void VG_(record_freemismatch_error) ( Addr a )
 {
    ErrContext ec;
    clear_ErrContext( &ec );
@@ -600,30 +612,33 @@ void VG_(record_free_error) ( Addr a )
    ec.next    = NULL;
    ec.where   = VG_(get_ExeContext)( True, VG_(baseBlock)[VGOFF_(m_eip)], 
                                            VG_(baseBlock)[VGOFF_(m_ebp)] );
-   ec.ekind   = FreeErr;
+   ec.ekind   = FreeMismatchErr;
    ec.addr    = a;
+   ec.tid     = VG_(get_current_tid)();
    VG_(describe_addr) ( a, &ec.addrinfo );
    VG_(maybe_add_context) ( &ec );
 }
 
-void VG_(record_freemismatch_error) ( Addr a )
+
+/* These three are called not from generated code but in response to
+   requests passed back to the scheduler.  So we pick up %EIP/%EBP
+   values from the stored thread state, not from VG_(baseBlock).  */
+
+void VG_(record_jump_error) ( ThreadState* tst, Addr a )
 {
    ErrContext ec;
    clear_ErrContext( &ec );
    ec.count   = 1;
    ec.next    = NULL;
-   ec.where   = VG_(get_ExeContext)( True, VG_(baseBlock)[VGOFF_(m_eip)], 
-                                           VG_(baseBlock)[VGOFF_(m_ebp)] );
-   ec.ekind   = FreeMismatchErr;
+   ec.where   = VG_(get_ExeContext)( False, tst->m_eip, tst->m_ebp );
+   ec.ekind   = AddrErr;
+   ec.axskind = ExecAxs;
    ec.addr    = a;
+   ec.tid     = tst->tid;
    VG_(describe_addr) ( a, &ec.addrinfo );
    VG_(maybe_add_context) ( &ec );
 }
 
-/* These two are called not from generated code but in response to
-   requests passed back to the scheduler.  So we pick up %EIP/%EBP
-   values from the stored thread state, not from VG_(baseBlock).  */
-
 void VG_(record_param_err) ( ThreadState* tst, Addr a, Bool isWriteLack, 
                              Char* msg )
 {
@@ -634,13 +649,13 @@ void VG_(record_param_err) ( ThreadState* tst, Addr a, Bool isWriteLack,
    ec.where   = VG_(get_ExeContext)( False, tst->m_eip, tst->m_ebp );
    ec.ekind   = ParamErr;
    ec.addr    = a;
+   ec.tid     = tst->tid;
    VG_(describe_addr) ( a, &ec.addrinfo );
    ec.syscall_param = msg;
    ec.isWriteableLack = isWriteLack;
    VG_(maybe_add_context) ( &ec );
 }
 
-
 void VG_(record_user_err) ( ThreadState* tst, Addr a, Bool isWriteLack )
 {
    ErrContext ec;
@@ -650,6 +665,7 @@ void VG_(record_user_err) ( ThreadState* tst, Addr a, Bool isWriteLack )
    ec.where   = VG_(get_ExeContext)( False, tst->m_eip, tst->m_ebp );
    ec.ekind   = UserErr;
    ec.addr    = a;
+   ec.tid     = tst->tid;
    VG_(describe_addr) ( a, &ec.addrinfo );
    ec.isWriteableLack = isWriteLack;
    VG_(maybe_add_context) ( &ec );
@@ -710,7 +726,8 @@ void VG_(show_all_errors) ( void )
       pp_ErrContext( p_min, False );
 
       if ((i+1 == VG_(clo_dump_error))) {
-         VG_(translate) ( p_min->where->eips[0], NULL, NULL, NULL );
+       VG_(translate) ( 0 /* dummy ThreadId; irrelevant due to below NULLs */,
+                         p_min->where->eips[0], NULL, NULL, NULL );
       }
 
       p_min->count = 1 << 30;
index c4ba60310b51b005bae6ee0140900629b800d930..c9be8842718427042b5de5af5c33f2fe6717851e 100644 (file)
 #define VG_N_WAITING_FDS 10
 
 /* Maximum number of mutexes allowed. */
-#define VG_N_MUTEXES 10
+#define VG_N_MUTEXES 30
 
 
 /* ---------------------------------------------------------------------
@@ -461,7 +461,11 @@ typedef
    struct {
       /* The thread identity is simply the index in vg_threads[].
          ThreadId == 0 is the root thread and has the special property
-         that we don't try and allocate or deallocate its stack.  */
+         that we don't try and allocate or deallocate its stack.  For
+         convenience of generating error message, we also put the
+         ThreadId in this tid field, but be aware that it should
+         ALWAYS just == the index in vg_threads[]. */
+      ThreadId tid;
 
       /* Current scheduling status. */
       ThreadStatus status;
@@ -498,6 +502,12 @@ typedef
       */
       Addr stack_base;
 
+     /* Address of the highest legitimate word in this stack.  This is
+        used for error messages only -- not critical for execution
+        correctness.  Is is set for all stacks, specifically including
+        ThreadId == 0 (the main thread). */
+      Addr stack_highest_word;
+
       /* Saved machine context. */
       UInt m_eax;
       UInt m_ebx;
@@ -535,10 +545,16 @@ extern void VG_(save_thread_state)( ThreadId );
 /* Get the thread state block for the specified thread. */
 extern ThreadState* VG_(get_thread_state)( ThreadId );
 
+/* And for the currently running one, if valid. */
+extern ThreadState* VG_(get_current_thread_state) ( void );
+
+/* Similarly ... */
+extern ThreadId VG_(get_current_tid) ( void );
+
+/* Which thread is this address in the stack of, if any?  Used for
+   error message generation. */
+extern ThreadId VG_(identify_stack_addr)( Addr a );
 
-/* Create, and add to TT/TC, the translation of a client basic
-   block. */
-extern void VG_(create_translation_for) ( Addr orig_addr );
 
 /* Return codes from the scheduler. */
 typedef
@@ -959,7 +975,8 @@ extern Int   VG_(getNewShadow)   ( UCodeBlock* cb );
    Exports of vg_translate.c
    ------------------------------------------------------------------ */
 
-extern void  VG_(translate)  ( Addr  orig_addr,
+extern void  VG_(translate)  ( ThreadState* tst,
+                               Addr  orig_addr,
                                UInt* orig_size,
                                Addr* trans_addr,
                                UInt* trans_size );
@@ -1054,7 +1071,8 @@ extern void VG_(record_free_error)    ( Addr a );
 extern void VG_(record_freemismatch_error)    ( Addr a );
 extern void VG_(record_address_error) ( Addr a, Int size, 
                                         Bool isWrite );
-extern void VG_(record_jump_error) ( Addr a );
+
+extern void VG_(record_jump_error) ( ThreadState* tst, Addr a );
 
 extern void VG_(record_param_err) ( ThreadState* tst,
                                     Addr a, 
@@ -1080,6 +1098,8 @@ typedef
       Int rwoffset;
       /* Freed, Mallocd */
       ExeContext* lastchange;
+      /* Stack */
+      ThreadId stack_tid;
    }
    AddrInfo;
 
@@ -1357,11 +1377,8 @@ extern Bool VG_(is_just_below_ESP)( Addr esp, Addr aa );
 
 /* Nasty kludgery to deal with applications which switch stacks,
    like netscape. */
-#define VG_STACK_STARTS_AT      0xC0000000
 #define VG_PLAUSIBLE_STACK_SIZE 8000000
 
-extern Bool VG_(is_plausible_stack_addr) ( Addr );
-
 
 /* ---------------------------------------------------------------------
    Exports of vg_syscall_mem.c
index f32c5533eaa60d03c6d61654fa2fe50052d26cd5..8ee3ccb10e657143c265ce38133365fe726a5b72 100644 (file)
@@ -499,6 +499,13 @@ int send(int s, const void *msg, size_t len, int flags)
    return __libc_send(s, msg, len, flags);
 }
 
+extern
+int __libc_recv(int s, void *buf, size_t len, int flags);
+int recv(int s, void *buf, size_t len, int flags)
+{
+   return __libc_recv(s, buf, len, flags);
+}
+
 
 /*--------------------------------------------------*/
 
index 48c11f3e235857f351dae96772eb5a1b6884bda2..9d3cf86e7c02a180b6759bf77ae52ea501aaab0e 100644 (file)
@@ -1314,14 +1314,15 @@ void fpu_write_check_SLOWLY ( Addr addr, Int size )
    addresses below %esp are not live; those at and above it are.  
 */
 
-/* Does this address look like something in the program's main 
-   stack ? */
-Bool VG_(is_plausible_stack_addr) ( Addr aa )
+/* Does this address look like something in or vaguely near the
+   current thread's stack? */
+static
+Bool is_plausible_stack_addr ( ThreadState* tst, Addr aa )
 {
    UInt a = (UInt)aa;
    PROF_EVENT(100);
-   if (a < VG_STACK_STARTS_AT && 
-       a > VG_STACK_STARTS_AT - VG_PLAUSIBLE_STACK_SIZE)
+   if (a <= tst->stack_highest_word && 
+       a > tst->stack_highest_word - VG_PLAUSIBLE_STACK_SIZE)
       return True;
    else
       return False;
@@ -1466,6 +1467,7 @@ static void vg_handle_esp_assignment_SLOWLY ( Addr new_espA )
                             - 0 * VKI_BYTES_PER_PAGE;
      Addr valid_up_to     = get_page_base(new_esp) + VKI_BYTES_PER_PAGE
                             + 0 * VKI_BYTES_PER_PAGE;
+     ThreadState* tst     = VG_(get_current_thread_state)();
      PROF_EVENT(114);
      if (VG_(clo_verbosity) > 1)
         VG_(message)(Vg_UserMsg, "Warning: client switching stacks?  "
@@ -1474,7 +1476,7 @@ static void vg_handle_esp_assignment_SLOWLY ( Addr new_espA )
      /* VG_(printf)("na %p,   %%esp %p,   wr %p\n",
                     invalid_down_to, new_esp, valid_up_to ); */
      VGM_(make_noaccess) ( invalid_down_to, new_esp - invalid_down_to );
-     if (!VG_(is_plausible_stack_addr)(new_esp)) {
+     if (!is_plausible_stack_addr(tst, new_esp)) {
         VGM_(make_readable) ( new_esp, valid_up_to - new_esp );
      }
    }
index fadde58fc4834a081468995a68e7bd561e1d1d53..fb0852e82fb71eb44a29893bbdc1cd0f67e1bbe4 100644 (file)
@@ -73,6 +73,9 @@ suitable for use by anyone at all!
 /* Private globals.  A statically allocated array of threads. */
 static ThreadState vg_threads[VG_N_THREADS];
 
+/* The tid of the thread currently in VG_(baseBlock). */
+static Int vg_tid_currently_in_baseBlock = VG_INVALID_THREADID;
+
 
 /* vg_oursignalhandler() might longjmp().  Here's the jmp_buf. */
 jmp_buf VG_(scheduler_jmpbuf);
@@ -131,6 +134,39 @@ static void do_nontrivial_clientreq ( ThreadId tid );
    Helper functions for the scheduler.
    ------------------------------------------------------------------ */
 
+/* For constructing error messages only: try and identify a thread
+   whose stack this address currently falls within, or return
+   VG_INVALID_THREADID if it doesn't.  A small complication is dealing
+   with any currently VG_(baseBlock)-resident thread. 
+*/
+ThreadId VG_(identify_stack_addr)( Addr a )
+{
+   ThreadId tid, tid_to_skip;
+
+   tid_to_skip = VG_INVALID_THREADID;
+
+   /* First check to see if there's a currently-loaded thread in
+      VG_(baseBlock). */
+   if (vg_tid_currently_in_baseBlock != VG_INVALID_THREADID) {
+      tid = vg_tid_currently_in_baseBlock;
+      if (VG_(baseBlock)[VGOFF_(m_esp)] <= a
+          && a <= vg_threads[tid].stack_highest_word) 
+         return tid;
+      else
+         tid_to_skip = tid;
+   }
+
+   for (tid = 0; tid < VG_N_THREADS; tid++) {
+      if (vg_threads[tid].status == VgTs_Empty) continue;
+      if (tid == tid_to_skip) continue;
+      if (vg_threads[tid].m_esp <= a 
+          && a <= vg_threads[tid].stack_highest_word)
+         return tid;
+   }
+   return VG_INVALID_THREADID;
+}
+
 /* Print the scheduler status. */
 void VG_(pp_sched_status) ( void )
 {
@@ -212,14 +248,16 @@ Char* name_of_sched_event ( UInt event )
    orig_addr, and add it to the translation cache & translation table.
    This probably doesn't really belong here, but, hey ... 
 */
-void VG_(create_translation_for) ( Addr orig_addr )
+static
+void create_translation_for ( ThreadId tid, Addr orig_addr )
 {
    Addr    trans_addr;
    TTEntry tte;
    Int orig_size, trans_size;
    /* Ensure there is space to hold a translation. */
    VG_(maybe_do_lru_pass)();
-   VG_(translate)( orig_addr, &orig_size, &trans_addr, &trans_size );
+   VG_(translate)( &vg_threads[tid],
+                   orig_addr, &orig_size, &trans_addr, &trans_size );
    /* Copy data at trans_addr into the translation cache.
       Returned pointer is to the code, not to the 4-byte
       header. */
@@ -273,6 +311,20 @@ ThreadState* VG_(get_thread_state) ( ThreadId tid )
 }
 
 
+ThreadState* VG_(get_current_thread_state) ( void )
+{
+   vg_assert(vg_tid_currently_in_baseBlock != VG_INVALID_THREADID);
+   return VG_(get_thread_state) ( VG_INVALID_THREADID );
+}
+
+
+ThreadId VG_(get_current_tid) ( void )
+{
+   vg_assert(vg_tid_currently_in_baseBlock != VG_INVALID_THREADID);
+   return vg_tid_currently_in_baseBlock;
+}
+
+
 /* Find an unused VgMutex record. */
 static
 MutexId vg_alloc_VgMutex ( void )
@@ -295,6 +347,8 @@ __inline__
 void VG_(load_thread_state) ( ThreadId tid )
 {
    Int i;
+   vg_assert(vg_tid_currently_in_baseBlock == VG_INVALID_THREADID);
+
    VG_(baseBlock)[VGOFF_(m_eax)] = vg_threads[tid].m_eax;
    VG_(baseBlock)[VGOFF_(m_ebx)] = vg_threads[tid].m_ebx;
    VG_(baseBlock)[VGOFF_(m_ecx)] = vg_threads[tid].m_ecx;
@@ -318,6 +372,8 @@ void VG_(load_thread_state) ( ThreadId tid )
    VG_(baseBlock)[VGOFF_(sh_ebp)] = vg_threads[tid].sh_ebp;
    VG_(baseBlock)[VGOFF_(sh_esp)] = vg_threads[tid].sh_esp;
    VG_(baseBlock)[VGOFF_(sh_eflags)] = vg_threads[tid].sh_eflags;
+
+   vg_tid_currently_in_baseBlock = tid;
 }
 
 
@@ -333,6 +389,8 @@ void VG_(save_thread_state) ( ThreadId tid )
    Int i;
    const UInt junk = 0xDEADBEEF;
 
+   vg_assert(vg_tid_currently_in_baseBlock != VG_INVALID_THREADID);
+
    vg_threads[tid].m_eax = VG_(baseBlock)[VGOFF_(m_eax)];
    vg_threads[tid].m_ebx = VG_(baseBlock)[VGOFF_(m_ebx)];
    vg_threads[tid].m_ecx = VG_(baseBlock)[VGOFF_(m_ecx)];
@@ -371,6 +429,8 @@ void VG_(save_thread_state) ( ThreadId tid )
 
    for (i = 0; i < VG_SIZE_OF_FPUSTATE_W; i++)
       VG_(baseBlock)[VGOFF_(m_fpustate) + i] = junk;
+
+   vg_tid_currently_in_baseBlock = VG_INVALID_THREADID;
 }
 
 
@@ -450,6 +510,7 @@ void VG_(scheduler_init) ( void )
    for (i = 0; i < VG_N_THREADS; i++) {
       vg_threads[i].stack_size = 0;
       vg_threads[i].stack_base = (Addr)NULL;
+      vg_threads[i].tid        = i;
    }
 
    for (i = 0; i < VG_N_WAITING_FDS; i++)
@@ -466,9 +527,15 @@ void VG_(scheduler_init) ( void )
    vg_threads[tid_main].status      = VgTs_Runnable;
    vg_threads[tid_main].joiner      = VG_INVALID_THREADID;
    vg_threads[tid_main].retval      = NULL; /* not important */
+   vg_threads[tid_main].stack_highest_word 
+      = vg_threads[tid_main].m_esp /* -4  ??? */;
 
    /* Copy VG_(baseBlock) state to tid_main's slot. */
+   vg_tid_currently_in_baseBlock = tid_main;
    VG_(save_thread_state) ( tid_main );
+
+   /* So now ... */
+   vg_assert(vg_tid_currently_in_baseBlock == VG_INVALID_THREADID);
 }
 
 
@@ -1037,6 +1104,9 @@ VgSchedReturnCode VG_(scheduler) ( void )
       /* ... and remember what we asked for. */
       dispatch_ctr_SAVED = VG_(dispatch_ctr);
 
+      /* paranoia ... */
+      vg_assert(vg_threads[tid].tid == tid);
+
       /* Actually run thread tid. */
       while (True) {
 
@@ -1061,7 +1131,7 @@ VgSchedReturnCode VG_(scheduler) ( void )
                = VG_(search_transtab) ( vg_threads[tid].m_eip );
             if (trans_addr == (Addr)0) {
                /* Not found; we need to request a translation. */
-               VG_(create_translation_for)( vg_threads[tid].m_eip ); 
+               create_translation_for( tid, vg_threads[tid].m_eip ); 
                trans_addr = VG_(search_transtab) ( vg_threads[tid].m_eip ); 
                if (trans_addr == (Addr)0)
                   VG_(panic)("VG_TRC_INNER_FASTMISS: missing tt_fast entry");
@@ -1191,7 +1261,7 @@ VgSchedReturnCode VG_(scheduler) ( void )
       throwing away the result. */
    VG_(printf)(
       "======vvvvvvvv====== LAST TRANSLATION ======vvvvvvvv======\n");
-   VG_(translate)( vg_threads[tid].m_eip, NULL, NULL, NULL );
+   VG_(translate)( &vg_threads[tid], vg_threads[tid].m_eip, NULL, NULL, NULL );
    VG_(printf)("\n");
    VG_(printf)(
       "======^^^^^^^^====== LAST TRANSLATION ======^^^^^^^^======\n");
@@ -1388,7 +1458,7 @@ void do_pthread_create ( ThreadId parent_tid,
 
    vg_assert(vg_threads[parent_tid].status != VgTs_Empty);
 
-   tid         = vg_alloc_ThreadState();
+   tid = vg_alloc_ThreadState();
 
    /* If we've created the main thread's tid, we're in deep trouble :) */
    vg_assert(tid != 0);
@@ -1413,10 +1483,16 @@ void do_pthread_create ( ThreadId parent_tid,
       new_stack = (Addr)VG_(get_memory_from_mmap)( new_stk_szb );
       vg_threads[tid].stack_base = new_stack;
       vg_threads[tid].stack_size = new_stk_szb;
-      vg_threads[tid].m_esp 
+      vg_threads[tid].stack_highest_word
          = new_stack + new_stk_szb 
-                     - VG_AR_CLIENT_STACKBASE_REDZONE_SZB;
+                     - VG_AR_CLIENT_STACKBASE_REDZONE_SZB; /* -4  ??? */;
    }
+
+   vg_threads[tid].m_esp 
+      = vg_threads[tid].stack_base 
+        + vg_threads[tid].stack_size
+        - VG_AR_CLIENT_STACKBASE_REDZONE_SZB;
+
    if (VG_(clo_instrument))
       VGM_(make_noaccess)( vg_threads[tid].m_esp, 
                            VG_AR_CLIENT_STACKBASE_REDZONE_SZB );
index 19bdfb5d8a0b68a6a21aa3fe9720db62e72032ae..73cad5e9bcd6a8414f3eab590c76b1cca196954d 100644 (file)
@@ -3039,7 +3039,9 @@ static void vg_cleanup ( UCodeBlock* cb )
    throw away the translation once it is made, and (b) produce a load
    of debugging output. 
 */
-void VG_(translate) ( Addr  orig_addr,
+void VG_(translate) ( ThreadState* tst, 
+                         /* Identity of thread needing this block */
+                      Addr  orig_addr,
                       UInt* orig_size,
                       Addr* trans_addr,
                       UInt* trans_size )
@@ -3063,7 +3065,7 @@ void VG_(translate) ( Addr  orig_addr,
       Addr bad_addr;
       Bool ok = VGM_(check_readable) ( orig_addr, 1, &bad_addr );
       if (!ok) {
-         VG_(record_jump_error)(bad_addr);
+         VG_(record_jump_error)(tst, bad_addr);
       }
    }
 
index dca0e3e5cbe74526901c42ee53479dd844a15fad..b1848405aa0f3c0c10728c1c8f7f88f148a4ad03 100644 (file)
@@ -529,15 +529,17 @@ void VG_(describe_addr) ( Addr a, AddrInfo* ai )
    ShadowChunk* sc;
    UInt         ml_no;
    Bool         ok;
+   ThreadId     tid;
 
    /* Perhaps it's a user-def'd block ? */
    ok = VG_(client_perm_maybe_describe)( a, ai );
    if (ok)
       return;
-   /* Perhaps it's on the stack? */
-   if (VG_(is_plausible_stack_addr)(a)
-       && a >= (Addr)VG_(baseBlock)[VGOFF_(m_esp)]) {
-      ai->akind = Stack;
+   /* Perhaps it's on a thread's stack? */
+   tid = VG_(identify_stack_addr)(a);
+   if (tid != VG_INVALID_THREADID) {
+      ai->akind     = Stack;
+      ai->stack_tid = tid;
       return;
    }
    /* Search for a freed block which might bracket it. */
index c632124eaa026e74e2b673b62e5681e7cfae934b..0ac2cb36b4855d1d5fc5325bba41f0fe4b053ad8 100644 (file)
@@ -142,6 +142,8 @@ typedef
       Char* syscall_param;
       /* Param, User */
       Bool isWriteableLack;
+      /* ALL */
+      ThreadId tid;
    } 
    ErrContext;
 
@@ -174,6 +176,7 @@ static void clear_AddrInfo ( AddrInfo* ai )
    ai->blksize    = 0;
    ai->rwoffset   = 0;
    ai->lastchange = NULL;
+   ai->stack_tid  = VG_INVALID_THREADID;
 }
 
 static void clear_ErrContext ( ErrContext* ec )
@@ -189,6 +192,7 @@ static void clear_ErrContext ( ErrContext* ec )
    clear_AddrInfo ( &ec->addrinfo );
    ec->syscall_param   = NULL;
    ec->isWriteableLack = False;
+   ec->tid     = VG_INVALID_THREADID;
 }
 
 
@@ -264,7 +268,9 @@ static void pp_AddrInfo ( Addr a, AddrInfo* ai )
 {
    switch (ai->akind) {
       case Stack: 
-         VG_(message)(Vg_UserMsg, "   Address 0x%x is on the stack", a);
+         VG_(message)(Vg_UserMsg, 
+                      "   Address 0x%x is on thread %d's stack", 
+                      ai->stack_tid, a);
          break;
       case Unknown:
          VG_(message)(Vg_UserMsg, 
@@ -309,6 +315,8 @@ static void pp_ErrContext ( ErrContext* ec, Bool printCount )
 {
    if (printCount)
       VG_(message)(Vg_UserMsg, "Observed %d times:", ec->count );
+   if (ec->tid > 0)
+      VG_(message)(Vg_UserMsg, "Thread %d:", ec->tid );
    switch (ec->ekind) {
       case ValueErr:
          if (ec->size == 0) {
@@ -441,6 +449,8 @@ static void VG_(maybe_add_context) ( ErrContext* ec )
    static Bool slowdown_message       = False;
    static Int  vg_n_errs_shown        = 0;
 
+   vg_assert(ec->tid >= 0 && ec->tid < VG_N_THREADS);
+
    /* After M_VG_COLLECT_NO_ERRORS_AFTER different errors have been
       found, just refuse to collect any more. */
    if (vg_n_errs_shown >= M_VG_COLLECT_NO_ERRORS_AFTER) {
@@ -551,6 +561,7 @@ void VG_(record_value_error) ( Int size )
                                           VG_(baseBlock)[VGOFF_(m_ebp)] );
    ec.ekind = ValueErr;
    ec.size  = size;
+   ec.tid   = VG_(get_current_tid)();
    VG_(maybe_add_context) ( &ec );
 }
 
@@ -573,26 +584,27 @@ void VG_(record_address_error) ( Addr a, Int size, Bool isWrite )
    ec.axskind = isWrite ? WriteAxs : ReadAxs;
    ec.size    = size;
    ec.addr    = a;
+   ec.tid     = VG_(get_current_tid)();
    VG_(describe_addr) ( a, &ec.addrinfo );
    VG_(maybe_add_context) ( &ec );
 }
 
-void VG_(record_jump_error) ( Addr a )
+void VG_(record_free_error) ( Addr a )
 {
    ErrContext ec;
    clear_ErrContext( &ec );
    ec.count   = 1;
    ec.next    = NULL;
-   ec.where   = VG_(get_ExeContext)( False, VG_(baseBlock)[VGOFF_(m_eip)], 
-                                            VG_(baseBlock)[VGOFF_(m_ebp)] );
-   ec.ekind   = AddrErr;
-   ec.axskind = ExecAxs;
+   ec.where   = VG_(get_ExeContext)( True, VG_(baseBlock)[VGOFF_(m_eip)], 
+                                           VG_(baseBlock)[VGOFF_(m_ebp)] );
+   ec.ekind   = FreeErr;
    ec.addr    = a;
+   ec.tid     = VG_(get_current_tid)();
    VG_(describe_addr) ( a, &ec.addrinfo );
    VG_(maybe_add_context) ( &ec );
 }
 
-void VG_(record_free_error) ( Addr a )
+void VG_(record_freemismatch_error) ( Addr a )
 {
    ErrContext ec;
    clear_ErrContext( &ec );
@@ -600,30 +612,33 @@ void VG_(record_free_error) ( Addr a )
    ec.next    = NULL;
    ec.where   = VG_(get_ExeContext)( True, VG_(baseBlock)[VGOFF_(m_eip)], 
                                            VG_(baseBlock)[VGOFF_(m_ebp)] );
-   ec.ekind   = FreeErr;
+   ec.ekind   = FreeMismatchErr;
    ec.addr    = a;
+   ec.tid     = VG_(get_current_tid)();
    VG_(describe_addr) ( a, &ec.addrinfo );
    VG_(maybe_add_context) ( &ec );
 }
 
-void VG_(record_freemismatch_error) ( Addr a )
+
+/* These three are called not from generated code but in response to
+   requests passed back to the scheduler.  So we pick up %EIP/%EBP
+   values from the stored thread state, not from VG_(baseBlock).  */
+
+void VG_(record_jump_error) ( ThreadState* tst, Addr a )
 {
    ErrContext ec;
    clear_ErrContext( &ec );
    ec.count   = 1;
    ec.next    = NULL;
-   ec.where   = VG_(get_ExeContext)( True, VG_(baseBlock)[VGOFF_(m_eip)], 
-                                           VG_(baseBlock)[VGOFF_(m_ebp)] );
-   ec.ekind   = FreeMismatchErr;
+   ec.where   = VG_(get_ExeContext)( False, tst->m_eip, tst->m_ebp );
+   ec.ekind   = AddrErr;
+   ec.axskind = ExecAxs;
    ec.addr    = a;
+   ec.tid     = tst->tid;
    VG_(describe_addr) ( a, &ec.addrinfo );
    VG_(maybe_add_context) ( &ec );
 }
 
-/* These two are called not from generated code but in response to
-   requests passed back to the scheduler.  So we pick up %EIP/%EBP
-   values from the stored thread state, not from VG_(baseBlock).  */
-
 void VG_(record_param_err) ( ThreadState* tst, Addr a, Bool isWriteLack, 
                              Char* msg )
 {
@@ -634,13 +649,13 @@ void VG_(record_param_err) ( ThreadState* tst, Addr a, Bool isWriteLack,
    ec.where   = VG_(get_ExeContext)( False, tst->m_eip, tst->m_ebp );
    ec.ekind   = ParamErr;
    ec.addr    = a;
+   ec.tid     = tst->tid;
    VG_(describe_addr) ( a, &ec.addrinfo );
    ec.syscall_param = msg;
    ec.isWriteableLack = isWriteLack;
    VG_(maybe_add_context) ( &ec );
 }
 
-
 void VG_(record_user_err) ( ThreadState* tst, Addr a, Bool isWriteLack )
 {
    ErrContext ec;
@@ -650,6 +665,7 @@ void VG_(record_user_err) ( ThreadState* tst, Addr a, Bool isWriteLack )
    ec.where   = VG_(get_ExeContext)( False, tst->m_eip, tst->m_ebp );
    ec.ekind   = UserErr;
    ec.addr    = a;
+   ec.tid     = tst->tid;
    VG_(describe_addr) ( a, &ec.addrinfo );
    ec.isWriteableLack = isWriteLack;
    VG_(maybe_add_context) ( &ec );
@@ -710,7 +726,8 @@ void VG_(show_all_errors) ( void )
       pp_ErrContext( p_min, False );
 
       if ((i+1 == VG_(clo_dump_error))) {
-         VG_(translate) ( p_min->where->eips[0], NULL, NULL, NULL );
+       VG_(translate) ( 0 /* dummy ThreadId; irrelevant due to below NULLs */,
+                         p_min->where->eips[0], NULL, NULL, NULL );
       }
 
       p_min->count = 1 << 30;
index c4ba60310b51b005bae6ee0140900629b800d930..c9be8842718427042b5de5af5c33f2fe6717851e 100644 (file)
 #define VG_N_WAITING_FDS 10
 
 /* Maximum number of mutexes allowed. */
-#define VG_N_MUTEXES 10
+#define VG_N_MUTEXES 30
 
 
 /* ---------------------------------------------------------------------
@@ -461,7 +461,11 @@ typedef
    struct {
       /* The thread identity is simply the index in vg_threads[].
          ThreadId == 0 is the root thread and has the special property
-         that we don't try and allocate or deallocate its stack.  */
+         that we don't try and allocate or deallocate its stack.  For
+         convenience of generating error message, we also put the
+         ThreadId in this tid field, but be aware that it should
+         ALWAYS just == the index in vg_threads[]. */
+      ThreadId tid;
 
       /* Current scheduling status. */
       ThreadStatus status;
@@ -498,6 +502,12 @@ typedef
       */
       Addr stack_base;
 
+     /* Address of the highest legitimate word in this stack.  This is
+        used for error messages only -- not critical for execution
+        correctness.  Is is set for all stacks, specifically including
+        ThreadId == 0 (the main thread). */
+      Addr stack_highest_word;
+
       /* Saved machine context. */
       UInt m_eax;
       UInt m_ebx;
@@ -535,10 +545,16 @@ extern void VG_(save_thread_state)( ThreadId );
 /* Get the thread state block for the specified thread. */
 extern ThreadState* VG_(get_thread_state)( ThreadId );
 
+/* And for the currently running one, if valid. */
+extern ThreadState* VG_(get_current_thread_state) ( void );
+
+/* Similarly ... */
+extern ThreadId VG_(get_current_tid) ( void );
+
+/* Which thread is this address in the stack of, if any?  Used for
+   error message generation. */
+extern ThreadId VG_(identify_stack_addr)( Addr a );
 
-/* Create, and add to TT/TC, the translation of a client basic
-   block. */
-extern void VG_(create_translation_for) ( Addr orig_addr );
 
 /* Return codes from the scheduler. */
 typedef
@@ -959,7 +975,8 @@ extern Int   VG_(getNewShadow)   ( UCodeBlock* cb );
    Exports of vg_translate.c
    ------------------------------------------------------------------ */
 
-extern void  VG_(translate)  ( Addr  orig_addr,
+extern void  VG_(translate)  ( ThreadState* tst,
+                               Addr  orig_addr,
                                UInt* orig_size,
                                Addr* trans_addr,
                                UInt* trans_size );
@@ -1054,7 +1071,8 @@ extern void VG_(record_free_error)    ( Addr a );
 extern void VG_(record_freemismatch_error)    ( Addr a );
 extern void VG_(record_address_error) ( Addr a, Int size, 
                                         Bool isWrite );
-extern void VG_(record_jump_error) ( Addr a );
+
+extern void VG_(record_jump_error) ( ThreadState* tst, Addr a );
 
 extern void VG_(record_param_err) ( ThreadState* tst,
                                     Addr a, 
@@ -1080,6 +1098,8 @@ typedef
       Int rwoffset;
       /* Freed, Mallocd */
       ExeContext* lastchange;
+      /* Stack */
+      ThreadId stack_tid;
    }
    AddrInfo;
 
@@ -1357,11 +1377,8 @@ extern Bool VG_(is_just_below_ESP)( Addr esp, Addr aa );
 
 /* Nasty kludgery to deal with applications which switch stacks,
    like netscape. */
-#define VG_STACK_STARTS_AT      0xC0000000
 #define VG_PLAUSIBLE_STACK_SIZE 8000000
 
-extern Bool VG_(is_plausible_stack_addr) ( Addr );
-
 
 /* ---------------------------------------------------------------------
    Exports of vg_syscall_mem.c
index f32c5533eaa60d03c6d61654fa2fe50052d26cd5..8ee3ccb10e657143c265ce38133365fe726a5b72 100644 (file)
@@ -499,6 +499,13 @@ int send(int s, const void *msg, size_t len, int flags)
    return __libc_send(s, msg, len, flags);
 }
 
+extern
+int __libc_recv(int s, void *buf, size_t len, int flags);
+int recv(int s, void *buf, size_t len, int flags)
+{
+   return __libc_recv(s, buf, len, flags);
+}
+
 
 /*--------------------------------------------------*/
 
index 48c11f3e235857f351dae96772eb5a1b6884bda2..9d3cf86e7c02a180b6759bf77ae52ea501aaab0e 100644 (file)
@@ -1314,14 +1314,15 @@ void fpu_write_check_SLOWLY ( Addr addr, Int size )
    addresses below %esp are not live; those at and above it are.  
 */
 
-/* Does this address look like something in the program's main 
-   stack ? */
-Bool VG_(is_plausible_stack_addr) ( Addr aa )
+/* Does this address look like something in or vaguely near the
+   current thread's stack? */
+static
+Bool is_plausible_stack_addr ( ThreadState* tst, Addr aa )
 {
    UInt a = (UInt)aa;
    PROF_EVENT(100);
-   if (a < VG_STACK_STARTS_AT && 
-       a > VG_STACK_STARTS_AT - VG_PLAUSIBLE_STACK_SIZE)
+   if (a <= tst->stack_highest_word && 
+       a > tst->stack_highest_word - VG_PLAUSIBLE_STACK_SIZE)
       return True;
    else
       return False;
@@ -1466,6 +1467,7 @@ static void vg_handle_esp_assignment_SLOWLY ( Addr new_espA )
                             - 0 * VKI_BYTES_PER_PAGE;
      Addr valid_up_to     = get_page_base(new_esp) + VKI_BYTES_PER_PAGE
                             + 0 * VKI_BYTES_PER_PAGE;
+     ThreadState* tst     = VG_(get_current_thread_state)();
      PROF_EVENT(114);
      if (VG_(clo_verbosity) > 1)
         VG_(message)(Vg_UserMsg, "Warning: client switching stacks?  "
@@ -1474,7 +1476,7 @@ static void vg_handle_esp_assignment_SLOWLY ( Addr new_espA )
      /* VG_(printf)("na %p,   %%esp %p,   wr %p\n",
                     invalid_down_to, new_esp, valid_up_to ); */
      VGM_(make_noaccess) ( invalid_down_to, new_esp - invalid_down_to );
-     if (!VG_(is_plausible_stack_addr)(new_esp)) {
+     if (!is_plausible_stack_addr(tst, new_esp)) {
         VGM_(make_readable) ( new_esp, valid_up_to - new_esp );
      }
    }
index fadde58fc4834a081468995a68e7bd561e1d1d53..fb0852e82fb71eb44a29893bbdc1cd0f67e1bbe4 100644 (file)
@@ -73,6 +73,9 @@ suitable for use by anyone at all!
 /* Private globals.  A statically allocated array of threads. */
 static ThreadState vg_threads[VG_N_THREADS];
 
+/* The tid of the thread currently in VG_(baseBlock). */
+static Int vg_tid_currently_in_baseBlock = VG_INVALID_THREADID;
+
 
 /* vg_oursignalhandler() might longjmp().  Here's the jmp_buf. */
 jmp_buf VG_(scheduler_jmpbuf);
@@ -131,6 +134,39 @@ static void do_nontrivial_clientreq ( ThreadId tid );
    Helper functions for the scheduler.
    ------------------------------------------------------------------ */
 
+/* For constructing error messages only: try and identify a thread
+   whose stack this address currently falls within, or return
+   VG_INVALID_THREADID if it doesn't.  A small complication is dealing
+   with any currently VG_(baseBlock)-resident thread. 
+*/
+ThreadId VG_(identify_stack_addr)( Addr a )
+{
+   ThreadId tid, tid_to_skip;
+
+   tid_to_skip = VG_INVALID_THREADID;
+
+   /* First check to see if there's a currently-loaded thread in
+      VG_(baseBlock). */
+   if (vg_tid_currently_in_baseBlock != VG_INVALID_THREADID) {
+      tid = vg_tid_currently_in_baseBlock;
+      if (VG_(baseBlock)[VGOFF_(m_esp)] <= a
+          && a <= vg_threads[tid].stack_highest_word) 
+         return tid;
+      else
+         tid_to_skip = tid;
+   }
+
+   for (tid = 0; tid < VG_N_THREADS; tid++) {
+      if (vg_threads[tid].status == VgTs_Empty) continue;
+      if (tid == tid_to_skip) continue;
+      if (vg_threads[tid].m_esp <= a 
+          && a <= vg_threads[tid].stack_highest_word)
+         return tid;
+   }
+   return VG_INVALID_THREADID;
+}
+
 /* Print the scheduler status. */
 void VG_(pp_sched_status) ( void )
 {
@@ -212,14 +248,16 @@ Char* name_of_sched_event ( UInt event )
    orig_addr, and add it to the translation cache & translation table.
    This probably doesn't really belong here, but, hey ... 
 */
-void VG_(create_translation_for) ( Addr orig_addr )
+static
+void create_translation_for ( ThreadId tid, Addr orig_addr )
 {
    Addr    trans_addr;
    TTEntry tte;
    Int orig_size, trans_size;
    /* Ensure there is space to hold a translation. */
    VG_(maybe_do_lru_pass)();
-   VG_(translate)( orig_addr, &orig_size, &trans_addr, &trans_size );
+   VG_(translate)( &vg_threads[tid],
+                   orig_addr, &orig_size, &trans_addr, &trans_size );
    /* Copy data at trans_addr into the translation cache.
       Returned pointer is to the code, not to the 4-byte
       header. */
@@ -273,6 +311,20 @@ ThreadState* VG_(get_thread_state) ( ThreadId tid )
 }
 
 
+ThreadState* VG_(get_current_thread_state) ( void )
+{
+   vg_assert(vg_tid_currently_in_baseBlock != VG_INVALID_THREADID);
+   return VG_(get_thread_state) ( VG_INVALID_THREADID );
+}
+
+
+ThreadId VG_(get_current_tid) ( void )
+{
+   vg_assert(vg_tid_currently_in_baseBlock != VG_INVALID_THREADID);
+   return vg_tid_currently_in_baseBlock;
+}
+
+
 /* Find an unused VgMutex record. */
 static
 MutexId vg_alloc_VgMutex ( void )
@@ -295,6 +347,8 @@ __inline__
 void VG_(load_thread_state) ( ThreadId tid )
 {
    Int i;
+   vg_assert(vg_tid_currently_in_baseBlock == VG_INVALID_THREADID);
+
    VG_(baseBlock)[VGOFF_(m_eax)] = vg_threads[tid].m_eax;
    VG_(baseBlock)[VGOFF_(m_ebx)] = vg_threads[tid].m_ebx;
    VG_(baseBlock)[VGOFF_(m_ecx)] = vg_threads[tid].m_ecx;
@@ -318,6 +372,8 @@ void VG_(load_thread_state) ( ThreadId tid )
    VG_(baseBlock)[VGOFF_(sh_ebp)] = vg_threads[tid].sh_ebp;
    VG_(baseBlock)[VGOFF_(sh_esp)] = vg_threads[tid].sh_esp;
    VG_(baseBlock)[VGOFF_(sh_eflags)] = vg_threads[tid].sh_eflags;
+
+   vg_tid_currently_in_baseBlock = tid;
 }
 
 
@@ -333,6 +389,8 @@ void VG_(save_thread_state) ( ThreadId tid )
    Int i;
    const UInt junk = 0xDEADBEEF;
 
+   vg_assert(vg_tid_currently_in_baseBlock != VG_INVALID_THREADID);
+
    vg_threads[tid].m_eax = VG_(baseBlock)[VGOFF_(m_eax)];
    vg_threads[tid].m_ebx = VG_(baseBlock)[VGOFF_(m_ebx)];
    vg_threads[tid].m_ecx = VG_(baseBlock)[VGOFF_(m_ecx)];
@@ -371,6 +429,8 @@ void VG_(save_thread_state) ( ThreadId tid )
 
    for (i = 0; i < VG_SIZE_OF_FPUSTATE_W; i++)
       VG_(baseBlock)[VGOFF_(m_fpustate) + i] = junk;
+
+   vg_tid_currently_in_baseBlock = VG_INVALID_THREADID;
 }
 
 
@@ -450,6 +510,7 @@ void VG_(scheduler_init) ( void )
    for (i = 0; i < VG_N_THREADS; i++) {
       vg_threads[i].stack_size = 0;
       vg_threads[i].stack_base = (Addr)NULL;
+      vg_threads[i].tid        = i;
    }
 
    for (i = 0; i < VG_N_WAITING_FDS; i++)
@@ -466,9 +527,15 @@ void VG_(scheduler_init) ( void )
    vg_threads[tid_main].status      = VgTs_Runnable;
    vg_threads[tid_main].joiner      = VG_INVALID_THREADID;
    vg_threads[tid_main].retval      = NULL; /* not important */
+   vg_threads[tid_main].stack_highest_word 
+      = vg_threads[tid_main].m_esp /* -4  ??? */;
 
    /* Copy VG_(baseBlock) state to tid_main's slot. */
+   vg_tid_currently_in_baseBlock = tid_main;
    VG_(save_thread_state) ( tid_main );
+
+   /* So now ... */
+   vg_assert(vg_tid_currently_in_baseBlock == VG_INVALID_THREADID);
 }
 
 
@@ -1037,6 +1104,9 @@ VgSchedReturnCode VG_(scheduler) ( void )
       /* ... and remember what we asked for. */
       dispatch_ctr_SAVED = VG_(dispatch_ctr);
 
+      /* paranoia ... */
+      vg_assert(vg_threads[tid].tid == tid);
+
       /* Actually run thread tid. */
       while (True) {
 
@@ -1061,7 +1131,7 @@ VgSchedReturnCode VG_(scheduler) ( void )
                = VG_(search_transtab) ( vg_threads[tid].m_eip );
             if (trans_addr == (Addr)0) {
                /* Not found; we need to request a translation. */
-               VG_(create_translation_for)( vg_threads[tid].m_eip ); 
+               create_translation_for( tid, vg_threads[tid].m_eip ); 
                trans_addr = VG_(search_transtab) ( vg_threads[tid].m_eip ); 
                if (trans_addr == (Addr)0)
                   VG_(panic)("VG_TRC_INNER_FASTMISS: missing tt_fast entry");
@@ -1191,7 +1261,7 @@ VgSchedReturnCode VG_(scheduler) ( void )
       throwing away the result. */
    VG_(printf)(
       "======vvvvvvvv====== LAST TRANSLATION ======vvvvvvvv======\n");
-   VG_(translate)( vg_threads[tid].m_eip, NULL, NULL, NULL );
+   VG_(translate)( &vg_threads[tid], vg_threads[tid].m_eip, NULL, NULL, NULL );
    VG_(printf)("\n");
    VG_(printf)(
       "======^^^^^^^^====== LAST TRANSLATION ======^^^^^^^^======\n");
@@ -1388,7 +1458,7 @@ void do_pthread_create ( ThreadId parent_tid,
 
    vg_assert(vg_threads[parent_tid].status != VgTs_Empty);
 
-   tid         = vg_alloc_ThreadState();
+   tid = vg_alloc_ThreadState();
 
    /* If we've created the main thread's tid, we're in deep trouble :) */
    vg_assert(tid != 0);
@@ -1413,10 +1483,16 @@ void do_pthread_create ( ThreadId parent_tid,
       new_stack = (Addr)VG_(get_memory_from_mmap)( new_stk_szb );
       vg_threads[tid].stack_base = new_stack;
       vg_threads[tid].stack_size = new_stk_szb;
-      vg_threads[tid].m_esp 
+      vg_threads[tid].stack_highest_word
          = new_stack + new_stk_szb 
-                     - VG_AR_CLIENT_STACKBASE_REDZONE_SZB;
+                     - VG_AR_CLIENT_STACKBASE_REDZONE_SZB; /* -4  ??? */;
    }
+
+   vg_threads[tid].m_esp 
+      = vg_threads[tid].stack_base 
+        + vg_threads[tid].stack_size
+        - VG_AR_CLIENT_STACKBASE_REDZONE_SZB;
+
    if (VG_(clo_instrument))
       VGM_(make_noaccess)( vg_threads[tid].m_esp, 
                            VG_AR_CLIENT_STACKBASE_REDZONE_SZB );
index 19bdfb5d8a0b68a6a21aa3fe9720db62e72032ae..73cad5e9bcd6a8414f3eab590c76b1cca196954d 100644 (file)
@@ -3039,7 +3039,9 @@ static void vg_cleanup ( UCodeBlock* cb )
    throw away the translation once it is made, and (b) produce a load
    of debugging output. 
 */
-void VG_(translate) ( Addr  orig_addr,
+void VG_(translate) ( ThreadState* tst, 
+                         /* Identity of thread needing this block */
+                      Addr  orig_addr,
                       UInt* orig_size,
                       Addr* trans_addr,
                       UInt* trans_size )
@@ -3063,7 +3065,7 @@ void VG_(translate) ( Addr  orig_addr,
       Addr bad_addr;
       Bool ok = VGM_(check_readable) ( orig_addr, 1, &bad_addr );
       if (!ok) {
-         VG_(record_jump_error)(bad_addr);
+         VG_(record_jump_error)(tst, bad_addr);
       }
    }