tests/vg_regtest: Always evaluate prerequisite expressions with sh
[valgrind.git] / coregrind / m_sigframe / sigframe-x86-darwin.c
blob8e77f6006df5d8874d4822464c5ad19d0f71b93f
2 /*--------------------------------------------------------------------*/
3 /*--- Create/destroy signal delivery frames. ---*/
4 /*--- sigframe-x86-darwin.c ---*/
5 /*--------------------------------------------------------------------*/
7 /*
8 This file is part of Valgrind, a dynamic binary instrumentation
9 framework.
11 Copyright (C) 2006-2013 OpenWorks Ltd
12 info@open-works.co.uk
14 This program is free software; you can redistribute it and/or
15 modify it under the terms of the GNU General Public License as
16 published by the Free Software Foundation; either version 2 of the
17 License, or (at your option) any later version.
19 This program is distributed in the hope that it will be useful, but
20 WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 General Public License for more details.
24 You should have received a copy of the GNU General Public License
25 along with this program; if not, write to the Free Software
26 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
27 02111-1307, USA.
29 The GNU General Public License is contained in the file COPYING.
32 #if defined(VGP_x86_darwin)
34 #include "pub_core_basics.h"
35 #include "pub_core_vki.h"
36 #include "pub_core_vkiscnums.h"
37 #include "pub_core_threadstate.h"
38 #include "pub_core_aspacemgr.h"
39 #include "pub_core_libcbase.h"
40 #include "pub_core_libcassert.h"
41 #include "pub_core_libcprint.h"
42 #include "pub_core_machine.h"
43 #include "pub_core_options.h"
44 #include "pub_core_signals.h"
45 #include "pub_core_tooliface.h"
46 #include "pub_core_trampoline.h"
47 #include "pub_core_sigframe.h" /* self */
48 #include "priv_sigframe.h"
51 /* Originally copied from ppc32-aix5 code.
52 Produce a frame with layout entirely of our own choosing.
54 This module creates and removes signal frames for signal deliveries
55 on x86-darwin. The machine state is saved in a ucontext and retrieved
56 from it later, so the handler can modify it and return.
58 Frame should have a 16-aligned size, just in case that turns out to
59 be important for Darwin. (be conservative)
61 struct hacky_sigframe {
62 /* first four words look like a call to a 3-arg x86 function */
63 UInt returnAddr;
64 UInt a1_signo;
65 UInt a2_siginfo;
66 UInt a3_ucontext;
67 UChar lower_guardzone[512]; // put nothing here
68 VexGuestX86State vex;
69 VexGuestX86State vex_shadow1;
70 VexGuestX86State vex_shadow2;
71 vki_siginfo_t fake_siginfo;
72 struct vki_ucontext fake_ucontext;
73 UInt magicPI;
74 UInt sigNo_private;
75 vki_sigset_t mask; // saved sigmask; restore when hdlr returns
76 UInt __pad[3];
77 UChar upper_guardzone[512]; // put nothing here
78 // and don't zero it, since that might overwrite the client's
79 // stack redzone, at least on archs which have one
82 /* Create a plausible-looking sigcontext from the thread's
83 Vex guest state. NOTE: does not fill in the FP or SSE
84 bits of sigcontext at the moment.
86 static void synthesize_ucontext(ThreadState *tst,
87 struct vki_ucontext *uc,
88 const struct vki_ucontext *siguc)
90 VG_(memset)(uc, 0, sizeof(*uc));
92 if (siguc) uc->uc_sigmask = siguc->uc_sigmask;
93 uc->uc_stack = tst->altstack;
94 uc->uc_mcontext = &uc->__mcontext_data;
96 # define SC2(reg,REG) uc->__mcontext_data.__ss.reg = tst->arch.vex.guest_##REG
97 SC2(__edi,EDI);
98 SC2(__esi,ESI);
99 SC2(__ebp,EBP);
100 SC2(__ebx,EBX);
101 SC2(__edx,EDX);
102 SC2(__eax,EAX);
103 SC2(__ecx,ECX);
104 SC2(__esp,ESP);
105 SC2(__eip,EIP);
106 uc->__mcontext_data.__ss.__eflags = LibVEX_GuestX86_get_eflags(&tst->arch.vex);
108 if (siguc)
109 uc->__mcontext_data.__es = siguc->__mcontext_data.__es;
110 # undef SC2
113 static void restore_from_ucontext(ThreadState *tst,
114 const struct vki_ucontext *uc)
116 # define SC2(REG,reg) tst->arch.vex.guest_##REG = uc->__mcontext_data.__ss.reg
117 SC2(EDI,__edi);
118 SC2(ESI,__esi);
119 SC2(EBP,__ebp);
120 SC2(EBX,__ebx);
121 SC2(EDX,__edx);
122 SC2(EAX,__eax);
123 SC2(ECX,__ecx);
124 SC2(ESP,__esp);
125 SC2(EIP,__eip);
126 /* There doesn't seem to be an easy way to restore eflags */
127 # undef SC2
130 /* Create a signal frame for thread 'tid'. Make a 3-arg frame
131 regardless of whether the client originally requested a 1-arg
132 version (no SA_SIGINFO) or a 3-arg one (SA_SIGINFO) since in the
133 former case, the x86 calling conventions will simply cause the
134 extra 2 args to be ignored (inside the handler). */
135 void VG_(sigframe_create) ( ThreadId tid,
136 Bool on_altstack,
137 Addr sp_top_of_frame,
138 const vki_siginfo_t *siginfo,
139 const struct vki_ucontext *siguc,
140 void *handler,
141 UInt flags,
142 const vki_sigset_t *mask,
143 void *restorer )
145 ThreadState* tst;
146 Addr esp;
147 struct hacky_sigframe* frame;
148 Int sigNo = siginfo->si_signo;
150 vg_assert(VG_IS_16_ALIGNED(sizeof(struct hacky_sigframe)));
152 sp_top_of_frame &= ~0xf;
153 esp = sp_top_of_frame - sizeof(struct hacky_sigframe);
154 esp -= 4; /* ELF ABI says that esp+4 must be 16 aligned on
155 entry to a function. */
157 tst = VG_(get_ThreadState)(tid);
158 if (! ML_(sf_maybe_extend_stack)(tst, esp, sp_top_of_frame - esp, flags))
159 return;
161 vg_assert(VG_IS_16_ALIGNED(esp+4));
163 frame = (struct hacky_sigframe *) esp;
165 /* clear it (very conservatively) */
166 VG_(memset)(&frame->lower_guardzone, 0, sizeof frame->lower_guardzone);
167 VG_(memset)(&frame->vex, 0, sizeof(VexGuestX86State));
168 VG_(memset)(&frame->vex_shadow1, 0, sizeof(VexGuestX86State));
169 VG_(memset)(&frame->vex_shadow2, 0, sizeof(VexGuestX86State));
170 VG_(memset)(&frame->fake_siginfo, 0, sizeof(frame->fake_siginfo));
171 VG_(memset)(&frame->fake_ucontext, 0, sizeof(frame->fake_ucontext));
173 /* save stuff in frame */
174 frame->vex = tst->arch.vex;
175 frame->vex_shadow1 = tst->arch.vex_shadow1;
176 frame->vex_shadow2 = tst->arch.vex_shadow2;
177 frame->sigNo_private = sigNo;
178 frame->mask = tst->sig_mask;
179 frame->magicPI = 0x31415927;
181 /* Fill in the siginfo and ucontext. */
182 synthesize_ucontext(tst, &frame->fake_ucontext, siguc);
183 frame->fake_siginfo = *siginfo;
185 /* Set up stack pointer */
186 vg_assert(esp == (Addr)&frame->returnAddr);
187 VG_(set_SP)(tid, esp);
188 VG_TRACK( post_reg_write, Vg_CoreSignal, tid, VG_O_STACK_PTR, sizeof(UInt));
190 /* Set up program counter */
191 VG_(set_IP)(tid, (UInt)handler);
192 VG_TRACK( post_reg_write, Vg_CoreSignal, tid, VG_O_INSTR_PTR, sizeof(UInt));
194 /* Set up RA and args for the frame */
195 VG_TRACK( pre_mem_write, Vg_CoreSignal, tid, "signal handler frame",
196 (Addr)frame, 4*sizeof(UInt) );
197 frame->returnAddr = (UInt)&VG_(x86_darwin_SUBST_FOR_sigreturn);
199 frame->a1_signo = sigNo;
200 frame->a2_siginfo = (UInt) &frame->fake_siginfo;
201 frame->a3_ucontext = (UInt) &frame->fake_ucontext;
203 VG_TRACK( post_mem_write, Vg_CoreSignal, tid,
204 (Addr)frame, 4*sizeof(UInt) );
205 VG_TRACK( post_mem_write, Vg_CoreSignal, tid,
206 (Addr)&frame->fake_siginfo, sizeof(frame->fake_siginfo));
207 VG_TRACK( post_mem_write, Vg_CoreSignal, tid,
208 (Addr)&frame->fake_ucontext, sizeof(frame->fake_ucontext));
210 if (VG_(clo_trace_signals))
211 VG_(message)(Vg_DebugMsg,
212 "sigframe_create (thread %d): "
213 "next EIP=%#lx, next ESP=%#lx\n",
214 tid, (Addr)handler, (Addr)frame );
218 /* Remove a signal frame from thread 'tid's stack, and restore the CPU
219 state from it. Note, isRT is irrelevant here. */
220 void VG_(sigframe_destroy)( ThreadId tid, Bool isRT )
222 ThreadState *tst;
223 Addr esp;
224 Int sigNo;
225 struct hacky_sigframe* frame;
227 vg_assert(VG_(is_valid_tid)(tid));
228 tst = VG_(get_ThreadState)(tid);
230 /* Check that the stack frame looks valid */
231 esp = VG_(get_SP)(tid);
233 /* why -4 ? because the signal handler's return will have popped
234 the return address off the stack; and the return address is the
235 lowest-addressed element of hacky_sigframe. */
236 frame = (struct hacky_sigframe*)(esp - 4);
237 vg_assert(frame->magicPI == 0x31415927);
239 /* This +4 is because of the -4 referred to in the ELF ABI comment
240 in VG_(sigframe_create) just above. */
241 vg_assert(VG_IS_16_ALIGNED((Addr)frame + 4));
243 /* restore the entire guest state, and shadows, from the frame. */
244 tst->arch.vex = frame->vex;
245 tst->arch.vex_shadow1 = frame->vex_shadow1;
246 tst->arch.vex_shadow2 = frame->vex_shadow2;
247 restore_from_ucontext(tst, &frame->fake_ucontext);
249 tst->sig_mask = frame->mask;
250 tst->tmp_sig_mask = frame->mask;
251 sigNo = frame->sigNo_private;
253 if (VG_(clo_trace_signals))
254 VG_(message)(Vg_DebugMsg,
255 "sigframe_destroy (thread %d): "
256 "valid magic; next EIP=%#x\n",
257 tid, tst->arch.vex.guest_EIP);
259 VG_TRACK( die_mem_stack_signal,
260 (Addr)frame - VG_STACK_REDZONE_SZB,
261 sizeof(struct hacky_sigframe) );
263 /* tell the tools */
264 VG_TRACK( post_deliver_signal, tid, sigNo );
267 #endif // defined(VGP_x86_darwin)
269 /*--------------------------------------------------------------------*/
270 /*--- end ---*/
271 /*--------------------------------------------------------------------*/