Make the GDB-attach stuff thread-aware, and work (at least partially)
when running multithreaded.  Can still cause crashes (assertion failures)
when GDB exits.  I think it that's due to my use of libc's system()
call; should roll my own.


git-svn-id: svn://svn.valgrind.org/valgrind/trunk@111 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/coregrind/arch/x86-linux/vg_libpthread.c b/coregrind/arch/x86-linux/vg_libpthread.c
index f5c5361..5b18a84 100644
--- a/coregrind/arch/x86-linux/vg_libpthread.c
+++ b/coregrind/arch/x86-linux/vg_libpthread.c
@@ -233,7 +233,7 @@
 int* __errno_location ( void )
 {
    int tid;
-   ensure_valgrind("__errno_location");
+   /* ensure_valgrind("__errno_location"); */
    VALGRIND_MAGIC_SEQUENCE(tid, 0 /* default */,
                            VG_USERREQ__PTHREAD_GET_THREADID,
                            0, 0, 0, 0);
diff --git a/coregrind/vg_errcontext.c b/coregrind/vg_errcontext.c
index 3f44821..1e3297f 100644
--- a/coregrind/vg_errcontext.c
+++ b/coregrind/vg_errcontext.c
@@ -144,6 +144,14 @@
       Bool isWriteableLack;
       /* ALL */
       ThreadId tid;
+      /* ALL */
+      /* 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;
    } 
    ErrContext;
 
@@ -192,6 +200,9 @@
    clear_AddrInfo ( &ec->addrinfo );
    ec->syscall_param   = NULL;
    ec->isWriteableLack = False;
+   ec->m_eip   = 0xDEADB00F;
+   ec->m_esp   = 0xDEADBE0F;
+   ec->m_ebp   = 0xDEADB0EF;
    ec->tid     = VG_INVALID_THREADID;
 }
 
@@ -531,7 +542,8 @@
       vg_n_errs_shown++;
       /* Perhaps we want a GDB attach at this point? */
       if (vg_is_GDB_attach_requested()) {
-         VG_(swizzle_esp_then_start_GDB)();
+         VG_(swizzle_esp_then_start_GDB)(
+            ec->m_eip, ec->m_esp, ec->m_ebp);
       }
    } else {
       vg_n_errs_suppressed++;
@@ -562,6 +574,9 @@
    ec.ekind = ValueErr;
    ec.size  = size;
    ec.tid   = VG_(get_current_tid)();
+   ec.m_eip = VG_(baseBlock)[VGOFF_(m_eip)];
+   ec.m_esp = VG_(baseBlock)[VGOFF_(m_esp)];
+   ec.m_ebp = VG_(baseBlock)[VGOFF_(m_ebp)];
    VG_(maybe_add_context) ( &ec );
 }
 
@@ -585,6 +600,9 @@
    ec.size    = size;
    ec.addr    = a;
    ec.tid     = VG_(get_current_tid)();
+   ec.m_eip = VG_(baseBlock)[VGOFF_(m_eip)];
+   ec.m_esp = VG_(baseBlock)[VGOFF_(m_esp)];
+   ec.m_ebp = VG_(baseBlock)[VGOFF_(m_ebp)];
    VG_(describe_addr) ( a, &ec.addrinfo );
    VG_(maybe_add_context) ( &ec );
 }
@@ -604,6 +622,9 @@
    ec.ekind   = FreeErr;
    ec.addr    = a;
    ec.tid     = tst->tid;
+   ec.m_eip   = tst->m_eip;
+   ec.m_esp   = tst->m_esp;
+   ec.m_ebp   = tst->m_ebp;
    VG_(describe_addr) ( a, &ec.addrinfo );
    VG_(maybe_add_context) ( &ec );
 }
@@ -618,6 +639,9 @@
    ec.ekind   = FreeMismatchErr;
    ec.addr    = a;
    ec.tid     = tst->tid;
+   ec.m_eip   = tst->m_eip;
+   ec.m_esp   = tst->m_esp;
+   ec.m_ebp   = tst->m_ebp;
    VG_(describe_addr) ( a, &ec.addrinfo );
    VG_(maybe_add_context) ( &ec );
 }
@@ -633,6 +657,9 @@
    ec.axskind = ExecAxs;
    ec.addr    = a;
    ec.tid     = tst->tid;
+   ec.m_eip   = tst->m_eip;
+   ec.m_esp   = tst->m_esp;
+   ec.m_ebp   = tst->m_ebp;
    VG_(describe_addr) ( a, &ec.addrinfo );
    VG_(maybe_add_context) ( &ec );
 }
@@ -648,6 +675,9 @@
    ec.ekind   = ParamErr;
    ec.addr    = a;
    ec.tid     = tst->tid;
+   ec.m_eip   = tst->m_eip;
+   ec.m_esp   = tst->m_esp;
+   ec.m_ebp   = tst->m_ebp;
    VG_(describe_addr) ( a, &ec.addrinfo );
    ec.syscall_param = msg;
    ec.isWriteableLack = isWriteLack;
@@ -664,6 +694,9 @@
    ec.ekind   = UserErr;
    ec.addr    = a;
    ec.tid     = tst->tid;
+   ec.m_eip   = tst->m_eip;
+   ec.m_esp   = tst->m_esp;
+   ec.m_ebp   = tst->m_ebp;
    VG_(describe_addr) ( a, &ec.addrinfo );
    ec.isWriteableLack = isWriteLack;
    VG_(maybe_add_context) ( &ec );
diff --git a/coregrind/vg_include.h b/coregrind/vg_include.h
index 09bafb0..ee7adfa 100644
--- a/coregrind/vg_include.h
+++ b/coregrind/vg_include.h
@@ -1490,7 +1490,9 @@
 extern void VG_(shutdown);
 extern void VG_(switch_to_real_CPU) ( void );
 
-extern void VG_(swizzle_esp_then_start_GDB) ( void );
+extern void VG_(swizzle_esp_then_start_GDB) ( Addr m_eip_at_error,
+                                              Addr m_esp_at_error,
+                                              Addr m_ebp_at_error );
 
 
 /* ---------------------------------------------------------------------
diff --git a/coregrind/vg_libpthread.c b/coregrind/vg_libpthread.c
index f5c5361..5b18a84 100644
--- a/coregrind/vg_libpthread.c
+++ b/coregrind/vg_libpthread.c
@@ -233,7 +233,7 @@
 int* __errno_location ( void )
 {
    int tid;
-   ensure_valgrind("__errno_location");
+   /* ensure_valgrind("__errno_location"); */
    VALGRIND_MAGIC_SEQUENCE(tid, 0 /* default */,
                            VG_USERREQ__PTHREAD_GET_THREADID,
                            0, 0, 0, 0);
diff --git a/coregrind/vg_startup.S b/coregrind/vg_startup.S
index 1215e68..1a3b60f 100644
--- a/coregrind/vg_startup.S
+++ b/coregrind/vg_startup.S
@@ -175,6 +175,12 @@
 /*--- %esp/%ebp and then start up GDB.                     ---*/
 /*------------------------------------------------------------*/
 
+/*
+extern void VG_(swizzle_esp_then_start_GDB) ( Addr m_eip_at_error,
+                                              Addr m_esp_at_error,
+                                              Addr m_ebp_at_error );
+*/
+
 /*--- This is clearly not re-entrant! ---*/
 .data
 vg_ebp_saved_over_GDB_start:
@@ -190,12 +196,15 @@
 	# remember the simulators current stack/frame pointers
 	movl	%ebp, vg_ebp_saved_over_GDB_start
 	movl	%esp, vg_esp_saved_over_GDB_start
-	
-	movl	$VG_(baseBlock), %ebx
 
-	# fetch %ESP into %esp
-	movl	VGOFF_(m_esp), %esi
-	movl	(%ebx, %esi, 4), %esp
+	# get args into regs
+	movl	44(%esp), %eax		# client %EBP
+	movl	40(%esp), %ebx		# client %ESP
+	movl	36(%esp), %ecx		# client %EIP
+
+	# Now thatn we don't need to refer to simulators stack any more,
+	# put %ESP into %esp
+	movl	%ebx, %esp
 
 	### %esp now refers to clients stack
 	### mess with the clients stack to make it look as if it
@@ -203,14 +212,10 @@
 	### as if the top (currently executing) stack frame of the
 	### client is missing.
 	
-	# push %EIP, via %eax.  This is a faked-up return address.
-	movl	VGOFF_(m_eip), %esi
-	movl	(%ebx, %esi, 4), %eax
-	pushl	%eax
+	# push %EIP.  This is a faked-up return address.
+	pushl	%ecx
 
-	# push %EBP, via %eax.  This is a faked %ebp-chain pointer.
-	movl	VGOFF_(m_ebp), %esi
-	movl	(%ebx, %esi, 4), %eax
+	# push %EBP.  This is a faked %ebp-chain pointer.
 	pushl	%eax
 
 	movl	%esp, %ebp
diff --git a/vg_errcontext.c b/vg_errcontext.c
index 3f44821..1e3297f 100644
--- a/vg_errcontext.c
+++ b/vg_errcontext.c
@@ -144,6 +144,14 @@
       Bool isWriteableLack;
       /* ALL */
       ThreadId tid;
+      /* ALL */
+      /* 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;
    } 
    ErrContext;
 
@@ -192,6 +200,9 @@
    clear_AddrInfo ( &ec->addrinfo );
    ec->syscall_param   = NULL;
    ec->isWriteableLack = False;
+   ec->m_eip   = 0xDEADB00F;
+   ec->m_esp   = 0xDEADBE0F;
+   ec->m_ebp   = 0xDEADB0EF;
    ec->tid     = VG_INVALID_THREADID;
 }
 
@@ -531,7 +542,8 @@
       vg_n_errs_shown++;
       /* Perhaps we want a GDB attach at this point? */
       if (vg_is_GDB_attach_requested()) {
-         VG_(swizzle_esp_then_start_GDB)();
+         VG_(swizzle_esp_then_start_GDB)(
+            ec->m_eip, ec->m_esp, ec->m_ebp);
       }
    } else {
       vg_n_errs_suppressed++;
@@ -562,6 +574,9 @@
    ec.ekind = ValueErr;
    ec.size  = size;
    ec.tid   = VG_(get_current_tid)();
+   ec.m_eip = VG_(baseBlock)[VGOFF_(m_eip)];
+   ec.m_esp = VG_(baseBlock)[VGOFF_(m_esp)];
+   ec.m_ebp = VG_(baseBlock)[VGOFF_(m_ebp)];
    VG_(maybe_add_context) ( &ec );
 }
 
@@ -585,6 +600,9 @@
    ec.size    = size;
    ec.addr    = a;
    ec.tid     = VG_(get_current_tid)();
+   ec.m_eip = VG_(baseBlock)[VGOFF_(m_eip)];
+   ec.m_esp = VG_(baseBlock)[VGOFF_(m_esp)];
+   ec.m_ebp = VG_(baseBlock)[VGOFF_(m_ebp)];
    VG_(describe_addr) ( a, &ec.addrinfo );
    VG_(maybe_add_context) ( &ec );
 }
@@ -604,6 +622,9 @@
    ec.ekind   = FreeErr;
    ec.addr    = a;
    ec.tid     = tst->tid;
+   ec.m_eip   = tst->m_eip;
+   ec.m_esp   = tst->m_esp;
+   ec.m_ebp   = tst->m_ebp;
    VG_(describe_addr) ( a, &ec.addrinfo );
    VG_(maybe_add_context) ( &ec );
 }
@@ -618,6 +639,9 @@
    ec.ekind   = FreeMismatchErr;
    ec.addr    = a;
    ec.tid     = tst->tid;
+   ec.m_eip   = tst->m_eip;
+   ec.m_esp   = tst->m_esp;
+   ec.m_ebp   = tst->m_ebp;
    VG_(describe_addr) ( a, &ec.addrinfo );
    VG_(maybe_add_context) ( &ec );
 }
@@ -633,6 +657,9 @@
    ec.axskind = ExecAxs;
    ec.addr    = a;
    ec.tid     = tst->tid;
+   ec.m_eip   = tst->m_eip;
+   ec.m_esp   = tst->m_esp;
+   ec.m_ebp   = tst->m_ebp;
    VG_(describe_addr) ( a, &ec.addrinfo );
    VG_(maybe_add_context) ( &ec );
 }
@@ -648,6 +675,9 @@
    ec.ekind   = ParamErr;
    ec.addr    = a;
    ec.tid     = tst->tid;
+   ec.m_eip   = tst->m_eip;
+   ec.m_esp   = tst->m_esp;
+   ec.m_ebp   = tst->m_ebp;
    VG_(describe_addr) ( a, &ec.addrinfo );
    ec.syscall_param = msg;
    ec.isWriteableLack = isWriteLack;
@@ -664,6 +694,9 @@
    ec.ekind   = UserErr;
    ec.addr    = a;
    ec.tid     = tst->tid;
+   ec.m_eip   = tst->m_eip;
+   ec.m_esp   = tst->m_esp;
+   ec.m_ebp   = tst->m_ebp;
    VG_(describe_addr) ( a, &ec.addrinfo );
    ec.isWriteableLack = isWriteLack;
    VG_(maybe_add_context) ( &ec );
diff --git a/vg_include.h b/vg_include.h
index 09bafb0..ee7adfa 100644
--- a/vg_include.h
+++ b/vg_include.h
@@ -1490,7 +1490,9 @@
 extern void VG_(shutdown);
 extern void VG_(switch_to_real_CPU) ( void );
 
-extern void VG_(swizzle_esp_then_start_GDB) ( void );
+extern void VG_(swizzle_esp_then_start_GDB) ( Addr m_eip_at_error,
+                                              Addr m_esp_at_error,
+                                              Addr m_ebp_at_error );
 
 
 /* ---------------------------------------------------------------------
diff --git a/vg_libpthread.c b/vg_libpthread.c
index f5c5361..5b18a84 100644
--- a/vg_libpthread.c
+++ b/vg_libpthread.c
@@ -233,7 +233,7 @@
 int* __errno_location ( void )
 {
    int tid;
-   ensure_valgrind("__errno_location");
+   /* ensure_valgrind("__errno_location"); */
    VALGRIND_MAGIC_SEQUENCE(tid, 0 /* default */,
                            VG_USERREQ__PTHREAD_GET_THREADID,
                            0, 0, 0, 0);
diff --git a/vg_startup.S b/vg_startup.S
index 1215e68..1a3b60f 100644
--- a/vg_startup.S
+++ b/vg_startup.S
@@ -175,6 +175,12 @@
 /*--- %esp/%ebp and then start up GDB.                     ---*/
 /*------------------------------------------------------------*/
 
+/*
+extern void VG_(swizzle_esp_then_start_GDB) ( Addr m_eip_at_error,
+                                              Addr m_esp_at_error,
+                                              Addr m_ebp_at_error );
+*/
+
 /*--- This is clearly not re-entrant! ---*/
 .data
 vg_ebp_saved_over_GDB_start:
@@ -190,12 +196,15 @@
 	# remember the simulators current stack/frame pointers
 	movl	%ebp, vg_ebp_saved_over_GDB_start
 	movl	%esp, vg_esp_saved_over_GDB_start
-	
-	movl	$VG_(baseBlock), %ebx
 
-	# fetch %ESP into %esp
-	movl	VGOFF_(m_esp), %esi
-	movl	(%ebx, %esi, 4), %esp
+	# get args into regs
+	movl	44(%esp), %eax		# client %EBP
+	movl	40(%esp), %ebx		# client %ESP
+	movl	36(%esp), %ecx		# client %EIP
+
+	# Now thatn we don't need to refer to simulators stack any more,
+	# put %ESP into %esp
+	movl	%ebx, %esp
 
 	### %esp now refers to clients stack
 	### mess with the clients stack to make it look as if it
@@ -203,14 +212,10 @@
 	### as if the top (currently executing) stack frame of the
 	### client is missing.
 	
-	# push %EIP, via %eax.  This is a faked-up return address.
-	movl	VGOFF_(m_eip), %esi
-	movl	(%ebx, %esi, 4), %eax
-	pushl	%eax
+	# push %EIP.  This is a faked-up return address.
+	pushl	%ecx
 
-	# push %EBP, via %eax.  This is a faked %ebp-chain pointer.
-	movl	VGOFF_(m_ebp), %esi
-	movl	(%ebx, %esi, 4), %eax
+	# push %EBP.  This is a faked %ebp-chain pointer.
 	pushl	%eax
 
 	movl	%esp, %ebp