Arch-abstraction:
- abstract out signal frame pushing/popping
git-svn-id: svn://svn.valgrind.org/valgrind/trunk@2713 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/coregrind/core.h b/coregrind/core.h
index ac9b0ad..8265303 100644
--- a/coregrind/core.h
+++ b/coregrind/core.h
@@ -1509,6 +1509,13 @@
extern UInt* VGA_(reg_addr_from_BB) ( Int reg );
extern UInt* VGA_(reg_addr_from_tst) ( Int reg, arch_thread_t* );
+// Signal stuff
+extern void VGA_(push_signal_frame) ( ThreadId tid, Addr esp_top_of_frame,
+ const vki_ksiginfo_t *siginfo,
+ void *handler, UInt flags,
+ const vki_ksigset_t *mask);
+extern Int VGA_(pop_signal_frame) ( ThreadId tid );
+
// Pointercheck
extern Bool VGA_(setup_pointercheck) ( void );
diff --git a/coregrind/vg_signals.c b/coregrind/vg_signals.c
index 9a8ace7..b83928e 100644
--- a/coregrind/vg_signals.c
+++ b/coregrind/vg_signals.c
@@ -824,128 +824,7 @@
Linux kernel does.
------------------------------------------------------------------ */
-/* A structure in which to save the application's registers
- during the execution of signal handlers. */
-typedef
- struct {
- /* There are two different stack frame formats, depending on
- whether the client set the SA_SIGINFO flag for the handler.
- This structure is put onto the client's stack as part of
- signal delivery, and therefore appears as the signal
- handler's arguments.
-
- The first two words are common for both frame formats -
- they're the return address and the signal number. */
-
- /* Sig handler's (bogus) return address */
- Addr retaddr;
- /* The arg to the sig handler. We need to inspect this after
- the handler returns, but it's unreasonable to assume that the
- handler won't change it. So we keep a second copy of it in
- sigNo_private. */
- Int sigNo;
-
- /* This is where the two frames start differing. */
- union {
- struct { /* set SA_SIGINFO */
- /* ptr to siginfo_t. */
- Addr psigInfo;
-
- /* ptr to ucontext */
- Addr puContext;
- } sigInfo;
- struct vki_sigcontext sigContext; /* did not set SA_SIGINFO */
- } handlerArgs;
-
- /* The rest are private fields which the handler is unaware of. */
-
- /* Sanity check word. */
- UInt magicPI;
- /* pointed to by psigInfo */
- vki_ksiginfo_t sigInfo;
- /* pointed to by puContext */
- struct vki_ucontext uContext;
-
- /* Safely-saved version of sigNo, as described above. */
- Int sigNo_private;
- /* Saved processor state. */
- UInt m_sse[VG_SIZE_OF_SSESTATE_W];
-
- UInt m_eax;
- UInt m_ecx;
- UInt m_edx;
- UInt m_ebx;
- UInt m_ebp;
- UInt m_esp;
- UInt m_esi;
- UInt m_edi;
- UInt m_eflags;
- Addr m_eip;
-
- UInt sh_eax;
- UInt sh_ebx;
- UInt sh_ecx;
- UInt sh_edx;
- UInt sh_esi;
- UInt sh_edi;
- UInt sh_ebp;
- UInt sh_esp;
- UInt sh_eflags;
-
- /* saved signal mask to be restored when handler returns */
- vki_ksigset_t mask;
-
- /* Scheduler-private stuff: what was the thread's status prior to
- delivering this signal? */
- ThreadStatus status;
- /* Sanity check word. Is the highest-addressed word; do not
- move!*/
- UInt magicE;
- }
- VgSigFrame;
-
-
-/* Make up a plausible-looking thread state from the thread's current state */
-static void synth_ucontext(ThreadId tid, const vki_ksiginfo_t *si,
- const vki_ksigset_t *set, struct vki_ucontext *uc)
-{
- ThreadState *tst = VG_(get_ThreadState)(tid);
- struct vki_sigcontext *sc = &uc->uc_mcontext;
-
- VG_(memset)(uc, 0, sizeof(*uc));
-
- uc->uc_flags = 0;
- uc->uc_link = 0;
- uc->uc_sigmask = *set;
- uc->uc_stack = tst->altstack;
-
-#define SC(reg) sc->reg = tst->arch.m_##reg
- SC(gs);
- SC(fs);
- SC(es);
- SC(ds);
-
- SC(edi);
- SC(esi);
- SC(ebp);
- SC(esp);
- SC(ebx);
- SC(edx);
- SC(ecx);
- SC(eax);
-
- SC(eip);
- SC(cs);
- SC(eflags);
- SC(ss);
- /* XXX esp_at_signal */
- /* XXX trapno */
- /* XXX err */
-#undef SC
-
- sc->cr2 = (UInt)si->_sifields._sigfault._addr;
-}
/* Set up a stack frame (VgSigContext) for the client's signal
handler. This includes the signal number and a bogus return
@@ -953,9 +832,7 @@
static
void vg_push_signal_frame ( ThreadId tid, const vki_ksiginfo_t *siginfo )
{
- Int i;
- Addr esp, esp_top_of_frame;
- VgSigFrame* frame;
+ Addr esp_top_of_frame;
ThreadState* tst;
Int sigNo = siginfo->si_signo;
@@ -990,117 +867,10 @@
/* Signal delivery to tools */
VG_TRACK( pre_deliver_signal, tid, sigNo, /*alt_stack*/False );
}
-
- esp = esp_top_of_frame;
- esp -= sizeof(VgSigFrame);
- frame = (VgSigFrame*)esp;
-
- /* For tracking memory events, indicate the entire frame has been
- * allocated, but pretend that only the first four words are written */
- VG_TRACK( new_mem_stack_signal, (Addr)frame, sizeof(VgSigFrame) );
-
- /* Assert that the frame is placed correctly. */
- vg_assert( (sizeof(VgSigFrame) & 0x3) == 0 );
- vg_assert( ((Char*)(&frame->magicE)) + sizeof(UInt)
- == ((Char*)(esp_top_of_frame)) );
-
- /* retaddr, sigNo, psigInfo, puContext fields are to be written */
- VG_TRACK( pre_mem_write, Vg_CoreSignal, tid, "signal handler frame",
- (Addr)frame, offsetof(VgSigFrame, handlerArgs) );
- frame->retaddr = (UInt)VG_(client_trampoline_code)+VG_(tramp_sigreturn_offset);
- frame->sigNo = sigNo;
- frame->sigNo_private = sigNo;
- VG_TRACK( post_mem_write, (Addr)frame, offsetof(VgSigFrame, handlerArgs) );
-
- if (vg_scss.scss_per_sig[sigNo].scss_flags & VKI_SA_SIGINFO) {
- /* if the client asked for a siginfo delivery, then build the stack that way */
- VG_TRACK( pre_mem_write, Vg_CoreSignal, tid, "signal handler frame (siginfo)",
- (Addr)&frame->handlerArgs, sizeof(frame->handlerArgs.sigInfo) );
- frame->handlerArgs.sigInfo.psigInfo = (Addr)&frame->sigInfo;
- frame->handlerArgs.sigInfo.puContext = (Addr)&frame->uContext;
- VG_TRACK( post_mem_write, (Addr)&frame->handlerArgs, sizeof(frame->handlerArgs.sigInfo) );
-
- VG_TRACK( pre_mem_write, Vg_CoreSignal, tid, "signal handler frame (siginfo)",
- (Addr)&frame->sigInfo, sizeof(frame->sigInfo) );
- VG_(memcpy)(&frame->sigInfo, siginfo, sizeof(vki_ksiginfo_t));
- if (sigNo == VKI_SIGFPE) {
- frame->sigInfo._sifields._sigfault._addr = (void *)tst->arch.m_eip;
- }
- VG_TRACK( post_mem_write, (Addr)&frame->sigInfo, sizeof(frame->sigInfo) );
-
- VG_TRACK( pre_mem_write, Vg_CoreSignal, tid, "signal handler frame (siginfo)",
- (Addr)&frame->uContext, sizeof(frame->uContext) );
- synth_ucontext(tid, siginfo, &vg_scss.scss_per_sig[sigNo].scss_mask, &frame->uContext);
- VG_TRACK( post_mem_write, (Addr)&frame->uContext, sizeof(frame->uContext) );
- } else {
- struct vki_ucontext uc;
-
- /* otherwise just put the sigcontext there */
-
- synth_ucontext(tid, siginfo, &vg_scss.scss_per_sig[sigNo].scss_mask, &uc);
-
- VG_TRACK( pre_mem_write, Vg_CoreSignal, tid, "signal handler frame (sigcontext)",
- (Addr)&frame->handlerArgs, sizeof(frame->handlerArgs.sigContext) );
- VG_(memcpy)(&frame->handlerArgs.sigContext, &uc.uc_mcontext,
- sizeof(struct vki_sigcontext));
- VG_TRACK( post_mem_write, (Addr)&frame->handlerArgs,
- sizeof(frame->handlerArgs.sigContext) );
-
- frame->handlerArgs.sigContext.oldmask = tst->sig_mask.ws[0];
- }
-
- frame->magicPI = 0x31415927;
-
- for (i = 0; i < VG_SIZE_OF_SSESTATE_W; i++)
- frame->m_sse[i] = tst->arch.m_sse[i];
-
- frame->m_eax = tst->arch.m_eax;
- frame->m_ecx = tst->arch.m_ecx;
- frame->m_edx = tst->arch.m_edx;
- frame->m_ebx = tst->arch.m_ebx;
- frame->m_ebp = tst->arch.m_ebp;
- frame->m_esp = tst->arch.m_esp;
- frame->m_esi = tst->arch.m_esi;
- frame->m_edi = tst->arch.m_edi;
- frame->m_eflags = tst->arch.m_eflags;
- frame->m_eip = tst->arch.m_eip;
-
- if (VG_(needs).shadow_regs) {
- frame->sh_eax = tst->arch.sh_eax;
- frame->sh_ecx = tst->arch.sh_ecx;
- frame->sh_edx = tst->arch.sh_edx;
- frame->sh_ebx = tst->arch.sh_ebx;
- frame->sh_ebp = tst->arch.sh_ebp;
- frame->sh_esp = tst->arch.sh_esp;
- frame->sh_esi = tst->arch.sh_esi;
- frame->sh_edi = tst->arch.sh_edi;
- frame->sh_eflags = tst->arch.sh_eflags;
- }
-
- frame->mask = tst->sig_mask;
-
- /* If the thread is currently blocked in a syscall, we want it to
- resume as runnable. */
- if (tst->status == VgTs_WaitSys)
- frame->status = VgTs_Runnable;
- else
- frame->status = tst->status;
-
- frame->magicE = 0x27182818;
-
- /* Ensure 'tid' and 'tst' correspond */
- vg_assert(& VG_(threads)[tid] == tst);
- /* Set the thread so it will next run the handler. */
- /* tst->arch.m_esp = esp; */
- SET_SIGNAL_ESP(tid, esp);
-
- tst->arch.m_eip = (Addr)vg_scss.scss_per_sig[sigNo].scss_handler;
- /* This thread needs to be marked runnable, but we leave that the
- caller to do. */
-
- if (0)
- VG_(printf)("pushed signal frame; %%ESP now = %p, next %%EBP = %p, status=%d\n",
- esp, tst->arch.m_eip, tst->status);
+ VGA_(push_signal_frame)(tid, esp_top_of_frame, siginfo,
+ vg_scss.scss_per_sig[sigNo].scss_handler,
+ vg_scss.scss_per_sig[sigNo].scss_flags,
+ &vg_scss.scss_per_sig[sigNo].scss_mask);
}
/* Clear the signal frame created by vg_push_signal_frame, restore the
@@ -1109,65 +879,8 @@
static
Int vg_pop_signal_frame ( ThreadId tid )
{
- Addr esp;
- Int sigNo, i;
- VgSigFrame* frame;
- ThreadState* tst;
+ Int sigNo = VGA_(pop_signal_frame)(tid);
- vg_assert(VG_(is_valid_tid)(tid));
- tst = & VG_(threads)[tid];
-
- /* Correctly reestablish the frame base address. */
- esp = tst->arch.m_esp;
- frame = (VgSigFrame*)
- (esp -4 /* because the handler's RET pops the RA */
- +20 /* because signalreturn_bogusRA pushes 5 words */);
-
- vg_assert(frame->magicPI == 0x31415927);
- vg_assert(frame->magicE == 0x27182818);
- if (VG_(clo_trace_signals))
- VG_(message)(Vg_DebugMsg,
- "vg_pop_signal_frame (thread %d): valid magic; EIP=%p", tid, frame->m_eip);
-
- /* Mark the frame structure as nonaccessible. */
- VG_TRACK( die_mem_stack_signal, (Addr)frame, sizeof(VgSigFrame) );
-
- /* restore machine state */
- for (i = 0; i < VG_SIZE_OF_SSESTATE_W; i++)
- tst->arch.m_sse[i] = frame->m_sse[i];
-
- tst->arch.m_eax = frame->m_eax;
- tst->arch.m_ecx = frame->m_ecx;
- tst->arch.m_edx = frame->m_edx;
- tst->arch.m_ebx = frame->m_ebx;
- tst->arch.m_ebp = frame->m_ebp;
- tst->arch.m_esp = frame->m_esp;
- tst->arch.m_esi = frame->m_esi;
- tst->arch.m_edi = frame->m_edi;
- tst->arch.m_eflags = frame->m_eflags;
- tst->arch.m_eip = frame->m_eip;
-
- if (VG_(needs).shadow_regs) {
- tst->arch.sh_eax = frame->sh_eax;
- tst->arch.sh_ecx = frame->sh_ecx;
- tst->arch.sh_edx = frame->sh_edx;
- tst->arch.sh_ebx = frame->sh_ebx;
- tst->arch.sh_ebp = frame->sh_ebp;
- tst->arch.sh_esp = frame->sh_esp;
- tst->arch.sh_esi = frame->sh_esi;
- tst->arch.sh_edi = frame->sh_edi;
- tst->arch.sh_eflags = frame->sh_eflags;
- }
-
- /* don't use the copy exposed to the handler; it might have changed
- it. */
- sigNo = frame->sigNo_private;
-
- /* And restore the thread's status to what it was before the signal
- was delivered. */
- tst->status = frame->status;
-
- tst->sig_mask = frame->mask;
VG_(proxy_setsigmask)(tid);
/* Notify tools */
diff --git a/coregrind/x86/Makefile.am b/coregrind/x86/Makefile.am
index 8552427..af552ac 100644
--- a/coregrind/x86/Makefile.am
+++ b/coregrind/x86/Makefile.am
@@ -18,6 +18,7 @@
CLEANFILES = stage2.lds
libarch_a_SOURCES = \
+ signal.c \
state.c
# Extract ld's default linker script and hack it to our needs