static void vg_async_signalhandler ( Int sigNo, vki_ksiginfo_t *info, struct vki_ucontext * );
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);
static const Char *signame(Int sigNo);
vg_assert(!terminate);
}
+/* 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 )
{
VG_(proxy_handlesig)(info, &uc->uc_mcontext);
}
+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.
}
}
- 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);
- }
+ /* Can't continue; must longjmp back to the scheduler and thus
+ enter the sighandler immediately. */
+ resume_scheduler(sigNo, info);
if (info->si_code <= VKI_SI_USER) {
/*
if (seg == NULL ||
!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
seg->flags |= SF_CODE; /* contains cached code */
--- /dev/null
+#include <stdio.h>
+#include <signal.h>
+
+static void handler(int sig, siginfo_t *info, void *v)
+{
+ printf("info: sig=%d code=%d addr=%p\n",
+ info->si_signo, info->si_code, info->si_addr);
+ exit(0);
+}
+
+int main()
+{
+ struct sigaction sa;
+ int val;
+
+ sa.sa_sigaction = handler;
+ sigemptyset(&sa.sa_mask);
+ sa.sa_flags = SA_SIGINFO;
+
+ sigaction(SIGSEGV, &sa, NULL);
+
+ asm volatile("mov %1, %%fs; mov %%fs:0, %0" : "=r" (val) : "r"(4));
+
+ printf("val=%d\n", val);
+
+ return 0;
+}