|
From: Jeremy F. <je...@go...> - 2004-03-16 09:49:14
|
CVS commit by fitzhardinge:
This change does two things: one is the implementation of
VG_(synth_fault_*), which synthesize faults as if an instruction had
caused a CPU fault. This is used in two places: one in vg_translate.c,
when trying to fetch instructions from bad memory, and the other in
vg_ldt.c, when using a bad segment register. This fixes a bug where an
assertion would fail rather than getting a useful message.
A none/tests/badseg.c 1.1 [POSSIBLY UNSAFE: printf] [no copyright]
A none/tests/badseg.stderr.exp 1.1
A none/tests/badseg.stdout.exp 1.1
A none/tests/badseg.vgtest 1.1
M +8 -0 coregrind/vg_include.h 1.187
M +4 -1 coregrind/vg_ldt.c 1.14
M +62 -8 coregrind/vg_signals.c 1.66
M +2 -8 coregrind/vg_translate.c 1.72
--- valgrind/coregrind/vg_signals.c #1.65:1.66
@@ -101,4 +101,5 @@ static void vg_async_signalhandler ( Int
static void vg_babyeater ( Int sigNo, vki_ksiginfo_t *info, struct vki_ucontext * );
static void proxy_sigvg_handler ( Int sigNo, vki_ksiginfo_t *info, struct vki_ucontext * );
+static void resume_scheduler(Int signo, vki_ksiginfo_t *info);
static Bool is_correct_sigmask(void);
@@ -1818,4 +1819,50 @@ static void vg_default_action(const vki_
}
+/* Synthesize a fault where the address is OK, but the page
+ permissions are bad */
+void VG_(synth_fault_perms)(ThreadId tid, Addr addr)
+{
+ vki_ksiginfo_t info;
+
+ vg_assert(VG_(threads)[tid].status == VgTs_Runnable);
+
+ info.si_signo = VKI_SIGSEGV;
+ info.si_code = 2;
+ info._sifields._sigfault._addr = (void*)addr;
+
+ resume_scheduler(VKI_SIGSEGV, &info);
+ VG_(deliver_signal)(tid, &info, False);
+}
+
+/* Synthesize a fault where the address there's nothing mapped at the
+ address */
+void VG_(synth_fault_mapping)(ThreadId tid, Addr addr)
+{
+ vki_ksiginfo_t info;
+
+ vg_assert(VG_(threads)[tid].status == VgTs_Runnable);
+
+ info.si_signo = VKI_SIGSEGV;
+ info.si_code = 1;
+ info._sifields._sigfault._addr = (void*)addr;
+
+ resume_scheduler(VKI_SIGSEGV, &info);
+ VG_(deliver_signal)(tid, &info, False);
+}
+
+/* Synthesize a misc memory fault */
+void VG_(synth_fault)(ThreadId tid)
+{
+ vki_ksiginfo_t info;
+
+ vg_assert(VG_(threads)[tid].status == VgTs_Runnable);
+
+ info.si_signo = VKI_SIGSEGV;
+ info.si_code = 0x80;
+ info._sifields._sigfault._addr = (void*)0;
+
+ resume_scheduler(VKI_SIGSEGV, &info);
+ VG_(deliver_signal)(tid, &info, False);
+}
void VG_(deliver_signal) ( ThreadId tid, const vki_ksiginfo_t *info, Bool async )
@@ -1974,4 +2021,16 @@ void vg_async_signalhandler ( Int sigNo,
}
+static void resume_scheduler(Int sigNo, vki_ksiginfo_t *info)
+{
+ if (VG_(scheduler_jmpbuf_valid)) {
+ /* Can't continue; must longjmp back to the scheduler and thus
+ enter the sighandler immediately. */
+ VG_(memcpy)(&VG_(unresumable_siginfo), info, sizeof(vki_ksiginfo_t));
+
+ VG_(longjmpd_on_signal) = sigNo;
+ __builtin_longjmp(VG_(scheduler_jmpbuf),1);
+ }
+}
+
/*
Recieve a sync signal from the host.
@@ -2112,12 +2171,7 @@ void vg_sync_signalhandler ( Int sigNo,
}
- if (VG_(scheduler_jmpbuf_valid)) {
/* Can't continue; must longjmp back to the scheduler and thus
enter the sighandler immediately. */
- VG_(memcpy)(&VG_(unresumable_siginfo), info, sizeof(vki_ksiginfo_t));
-
- VG_(longjmpd_on_signal) = sigNo;
- __builtin_longjmp(VG_(scheduler_jmpbuf),1);
- }
+ resume_scheduler(sigNo, info);
if (info->si_code <= VKI_SI_USER) {
--- valgrind/coregrind/vg_include.h #1.186:1.187
@@ -1081,4 +1081,12 @@ extern vki_ksiginfo_t VG_(unresumable_si
extern void VG_(kill_self)(Int sigNo);
+/* These function synthesize a fault, as if the running instruction
+ had had a fault. These functions do not return - they longjmp back
+ into the scheduler so the signal can be delivered. */
+extern void VG_(synth_fault) (ThreadId tid);
+extern void VG_(synth_fault_mapping)(ThreadId tid, Addr addr);
+extern void VG_(synth_fault_perms) (ThreadId tid, Addr addr);
+
+
/* ---------------------------------------------------------------------
Exports of vg_mylibc.c
--- valgrind/coregrind/vg_translate.c #1.71:1.72
@@ -2400,19 +2400,13 @@ void VG_(translate) ( /*IN*/ ThreadId t
!VG_(seg_contains)(seg, orig_addr, 1) ||
(seg->prot & (VKI_PROT_READ|VKI_PROT_EXEC)) == 0) {
- vki_ksiginfo_t info;
-
/* Code address is bad - deliver a signal instead */
vg_assert(!VG_(is_addressable)(orig_addr, 1));
- info.si_signo = VKI_SIGSEGV;
-
if (seg != NULL && VG_(seg_contains)(seg, orig_addr, 1)) {
vg_assert((seg->prot & VKI_PROT_EXEC) == 0);
- info.si_code = 2; /* invalid permissions for mapped object */
+ VG_(synth_fault_perms)(tid, orig_addr);
} else
- info.si_code = 1; /* address not mapped to object */
- info._sifields._sigfault._addr = (void*)orig_addr;
+ VG_(synth_fault_mapping)(tid, orig_addr);
- VG_(deliver_signal)(tid, &info, False);
return;
} else
--- valgrind/coregrind/vg_ldt.c #1.13:1.14
@@ -182,5 +182,8 @@ Addr VG_(do_useseg) ( UInt seg_selector,
/* Sanity check the segment selector. Ensure that RPL=11b (least
privilege). This forms the bottom 2 bits of the selector. */
- vg_assert((seg_selector & 3) == 3);
+ if ((seg_selector & 3) != 3) {
+ VG_(synth_fault)(VG_(get_current_tid)());
+ return 0;
+ }
/* Extract the table number */
|