
Implement int3 (breakpoint) instruction.


 coregrind/core.h                  |    7 ++++---
 coregrind/vg_main.c               |    4 ++++
 coregrind/vg_signals.c            |   15 +++++++++------
 coregrind/vg_to_ucode.c           |    7 +++++++
 coregrind/x86/core_arch.h         |    1 +
 coregrind/x86/helpers.S           |    9 ++++++++-
 none/tests/faultstatus.c          |   25 +++++++++++++++++++++++--
 none/tests/faultstatus.stderr.exp |   11 ++++++-----
 8 files changed, 62 insertions(+), 17 deletions(-)

diff -puN coregrind/core.h~int3-emu coregrind/core.h
--- valgrind-fresh/coregrind/core.h~int3-emu	2005-01-19 19:56:10.000000000 -0800
+++ valgrind-fresh-jeremy/coregrind/core.h	2005-01-19 19:56:10.000000000 -0800
@@ -840,9 +840,9 @@ extern Bool VG_(my_fault);
 
 /* This is a signal mask with almost everything blocked.  The
    exceptions are signals which could be synchronous (SIGILL, SIGBUS,
-   SIGSEGV - if we get one of those when they're blocked, then the
-   whole process could just die without warning), and the unblockable
-   ones (SIGKILL and SIGSTOP). */
+   SIGSEGV, SIGFPE, SIGTRAP - if we get one of those when they're
+   blocked, then the whole process could just die without warning),
+   and the unblockable ones (SIGKILL and SIGSTOP). */
 extern vki_sigset_t	VG_(blocked_mask);
 
 /* Highest signal the kernel will let us use */
@@ -1682,6 +1682,7 @@ extern UInt VG_(patch_me);
    ------------------------------------------------------------------ */
 
 extern void VG_(helper_undefined_instruction);
+extern void VG_(helper_breakpoint);
 
 /* Information about trampoline code (for signal return and syscalls) */
 extern const Char VG_(trampoline_code_start);
diff -puN coregrind/vg_signals.c~int3-emu coregrind/vg_signals.c
--- valgrind-fresh/coregrind/vg_signals.c~int3-emu	2005-01-19 19:56:10.000000000 -0800
+++ valgrind-fresh-jeremy/coregrind/vg_signals.c	2005-01-19 19:56:10.000000000 -0800
@@ -33,11 +33,11 @@
 
    There are 4 distinct classes of signal:
 
-   1. Synchronous, instruction-generated (SIGILL, FPE, BUS and SEGV):
-   these are signals as a result of an instruction fault.  If we get
-   one while running client code, then we just do the appropriate
-   thing.  If it happens while running Valgrind code, then it
-   indicates a Valgrind bug.  Note that we "manually" implement
+   1. Synchronous, instruction-generated (SIGILL, FPE, BUS, SIGTRAP
+   and SEGV): these are signals as a result of an instruction fault.
+   If we get one while running client code, then we just do the
+   appropriate thing.  If it happens while running Valgrind code, then
+   it indicates a Valgrind bug.  Note that we "manually" implement
    automatic stack growth, such that if a fault happens near the
    client process stack, it is extended in the same way the kernel
    would, and the fault is never reported to the client program.
@@ -247,6 +247,7 @@ void calculate_SKSS_from_SCSS ( SKSS* ds
       case VKI_SIGBUS:
       case VKI_SIGFPE:
       case VKI_SIGILL:
+      case VKI_SIGTRAP:
 	 /* For these, we always want to catch them and report, even
 	    if the client code doesn't. */
 	 skss_handler = vg_sync_signalhandler;
@@ -1639,7 +1640,8 @@ void vg_sync_signalhandler ( Int sigNo, 
    vg_assert(sigNo == VKI_SIGSEGV ||
 	     sigNo == VKI_SIGBUS  ||
 	     sigNo == VKI_SIGFPE  ||
-	     sigNo == VKI_SIGILL);
+	     sigNo == VKI_SIGILL  ||
+	     sigNo == VKI_SIGTRAP);
 
    if (!VG_(is_running_thread)(tid)) {
       /* This may possibly happen if someone sent us one of the sync
@@ -1916,6 +1918,7 @@ void VG_(sigstartup_actions) ( void )
    VG_(sigdelset)(&VG_(blocked_mask), VKI_SIGBUS);
    VG_(sigdelset)(&VG_(blocked_mask), VKI_SIGFPE);
    VG_(sigdelset)(&VG_(blocked_mask), VKI_SIGILL);
+   VG_(sigdelset)(&VG_(blocked_mask), VKI_SIGTRAP);
    VG_(sigdelset)(&VG_(blocked_mask), VKI_SIGSTOP);
    VG_(sigdelset)(&VG_(blocked_mask), VKI_SIGKILL);
 
diff -puN coregrind/vg_to_ucode.c~int3-emu coregrind/vg_to_ucode.c
--- valgrind-fresh/coregrind/vg_to_ucode.c~int3-emu	2005-01-19 19:56:10.000000000 -0800
+++ valgrind-fresh-jeremy/coregrind/vg_to_ucode.c	2005-01-19 19:56:10.000000000 -0800
@@ -7322,6 +7322,13 @@ static Addr disInstr ( UCodeBlock* cb, A
    goto decode_success;
    } /* case 0x0F: of primary opcode */
 
+   case 0xcc:			/* int3 */
+   uInstr0(cb, CALLM_S, 0);
+   uInstr1(cb, CALLM,   0, Lit16, 
+               VGOFF_(helper_breakpoint));
+   uInstr0(cb, CALLM_E, 0);
+   break;
+
    /* ------------------------ ??? ------------------------ */
   
   default:
diff -puN coregrind/x86/helpers.S~int3-emu coregrind/x86/helpers.S
--- valgrind-fresh/coregrind/x86/helpers.S~int3-emu	2005-01-19 19:56:10.000000000 -0800
+++ valgrind-fresh-jeremy/coregrind/x86/helpers.S	2005-01-19 19:56:10.000000000 -0800
@@ -721,7 +721,14 @@ VG_(helper_cmpxchg8b):
 VG_(helper_undefined_instruction):
 1:	ud2
 	jmp	1b
-	        
+
+/* Breakpoint instruction (generates SIGTRAP) */
+.globl VG_(helper_breakpoint)
+VG_(helper_breakpoint):
+	int3	/* should never finish */
+1:	ud2
+	jmp	1b	
+
 /* Let the linker know we don't need an executable stack */
 .section .note.GNU-stack,"",@progbits
 		
diff -puN coregrind/vg_main.c~int3-emu coregrind/vg_main.c
--- valgrind-fresh/coregrind/vg_main.c~int3-emu	2005-01-19 19:56:10.000000000 -0800
+++ valgrind-fresh-jeremy/coregrind/vg_main.c	2005-01-19 19:56:10.000000000 -0800
@@ -2123,6 +2123,7 @@ static void setup_file_descriptors(void)
 /*====================================================================*/
 
 Int VGOFF_(helper_undefined_instruction) = INVALID_OFFSET;
+Int VGOFF_(helper_breakpoint)            = INVALID_OFFSET;
 
 /* MAX_NONCOMPACT_HELPERS can be increased easily.  If MAX_COMPACT_HELPERS is
  * increased too much, they won't really be compact any more... */
@@ -2265,6 +2266,9 @@ static void init_baseBlock ( Addr client
    VGOFF_(helper_undefined_instruction)
       = VG_(alloc_BaB_1_set)( (Addr) & VG_(helper_undefined_instruction));
 
+   VGOFF_(helper_breakpoint)
+      = VG_(alloc_BaB_1_set)( (Addr) & VG_(helper_breakpoint));
+
    /* Allocate slots for noncompact helpers */
    assign_helpers_in_baseBlock(VG_(n_noncompact_helpers), 
                                VG_(noncompact_helper_offsets), 
diff -puN coregrind/x86/core_arch.h~int3-emu coregrind/x86/core_arch.h
--- valgrind-fresh/coregrind/x86/core_arch.h~int3-emu	2005-01-19 19:56:10.000000000 -0800
+++ valgrind-fresh-jeremy/coregrind/x86/core_arch.h	2005-01-19 19:56:10.000000000 -0800
@@ -123,6 +123,7 @@ extern Int VGOFF_(tls_ptr);
 
 /* Nb: Most helper offsets are in include/tool.h, for use by tools */
 extern Int VGOFF_(helper_undefined_instruction);
+extern Int VGOFF_(helper_breakpoint);
 
 
 /* ---------------------------------------------------------------------
diff -puN none/tests/faultstatus.c~int3-emu none/tests/faultstatus.c
--- valgrind-fresh/none/tests/faultstatus.c~int3-emu	2005-01-19 19:56:10.000000000 -0800
+++ valgrind-fresh-jeremy/none/tests/faultstatus.c	2005-01-19 19:56:10.000000000 -0800
@@ -137,6 +137,26 @@ static void handler5(int sig, siginfo_t 
 	siglongjmp(escape, 1);
 }
 
+static void test6()
+{
+	asm volatile ("int3");
+}
+
+static void handler6(int sig, siginfo_t *si, void *uc)
+{
+	int ok = 1;
+	
+	ok = ok && testsig(sig, SIGTRAP);
+	
+	/* This is expected to fail, since the kernel seems to give us
+	   an si_code of 128 rather than TRAP_BRKPT */
+	ok = ok && testcode(si->si_code, TRAP_BRKPT);
+	if (ok)
+		fprintf(stderr, "  PASS 6\n");
+
+	siglongjmp(escape, 1);
+}
+
 
 int main()
 {
@@ -151,9 +171,10 @@ int main()
 		T(3),
 		T(4),
 		T(5),
+		T(6),
 #undef T
 	};
-	static const int sigs[] = { SIGSEGV, SIGILL, SIGBUS, SIGFPE };
+	static const int sigs[] = { SIGSEGV, SIGILL, SIGBUS, SIGFPE, SIGTRAP };
 	int i;
 
 	fd = open("faultstatus.tmp", O_CREAT|O_TRUNC|O_EXCL, 0600);
@@ -178,7 +199,7 @@ int main()
 			sigaction(sigs[j], &sa, NULL);
 		
 		if (sigsetjmp(escape, 1) == 0) {
-			fprintf(stderr, "Test %d: ", i);
+			fprintf(stderr, "Test %d: ", i+1);
 			tests[i].test();
 			fprintf(stderr, "  FAIL: no fault, or handler returned\n");
 		}
diff -puN none/tests/faultstatus.stderr.exp~int3-emu none/tests/faultstatus.stderr.exp
--- valgrind-fresh/none/tests/faultstatus.stderr.exp~int3-emu	2005-01-19 19:56:10.000000000 -0800
+++ valgrind-fresh-jeremy/none/tests/faultstatus.stderr.exp	2005-01-19 19:56:10.000000000 -0800
@@ -1,9 +1,10 @@
 
-Test 0:   PASS 1
-Test 1:   PASS 2
-Test 2:   PASS 3
-Test 3: disInstr: unhandled instruction bytes: 0x........ 0x........ 0x........ 0x........
+Test 1:   PASS 1
+Test 2:   PASS 2
+Test 3:   PASS 3
+Test 4: disInstr: unhandled instruction bytes: 0x........ 0x........ 0x........ 0x........
           at 0x........: test4 (faultstatus.c:108)
   PASS 4
-Test 4:   PASS 5
+Test 5:   PASS 5
+Test 6:   FAIL: expected si_code==1, not 128
 

_
