1
2/*--------------------------------------------------------------------*/
3/*--- Create/destroy signal delivery frames.                       ---*/
4/*---                                        sigframe-x86-darwin.c ---*/
5/*--------------------------------------------------------------------*/
6
7/*
8   This file is part of Valgrind, a dynamic binary instrumentation
9   framework.
10
11   Copyright (C) 2006-2017 OpenWorks Ltd
12      info@open-works.co.uk
13
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.
18
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.
23
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.
28
29   The GNU General Public License is contained in the file COPYING.
30*/
31
32#if defined(VGP_x86_darwin)
33
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"
49
50
51/* Originally copied from ppc32-aix5 code.
52   Produce a frame with layout entirely of our own choosing.
53
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.
57
58   Frame should have a 16-aligned size, just in case that turns out to
59   be important for Darwin.  (be conservative)
60*/
61struct 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
80};
81
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.
85 */
86static void synthesize_ucontext(ThreadState *tst,
87				struct vki_ucontext *uc,
88				const struct vki_ucontext *siguc)
89{
90   VG_(memset)(uc, 0, sizeof(*uc));
91
92   if (siguc) uc->uc_sigmask = siguc->uc_sigmask;
93   uc->uc_stack = tst->altstack;
94   uc->uc_mcontext = &uc->__mcontext_data;
95
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);
107
108   if (siguc)
109      uc->__mcontext_data.__es = siguc->__mcontext_data.__es;
110#  undef SC2
111}
112
113static void restore_from_ucontext(ThreadState *tst,
114				  const struct vki_ucontext *uc)
115{
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
128}
129
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). */
135void 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 )
144{
145   ThreadState* tst;
146   Addr esp;
147   struct hacky_sigframe* frame;
148   Int sigNo = siginfo->si_signo;
149
150   vg_assert(VG_IS_16_ALIGNED(sizeof(struct hacky_sigframe)));
151
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. */
156
157   tst = VG_(get_ThreadState)(tid);
158   if (! ML_(sf_maybe_extend_stack)(tst, esp, sp_top_of_frame - esp, flags))
159      return;
160
161   vg_assert(VG_IS_16_ALIGNED(esp+4));
162
163   frame = (struct hacky_sigframe *) esp;
164
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));
172
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;
180
181   /* Fill in the siginfo and ucontext.  */
182   synthesize_ucontext(tst, &frame->fake_ucontext, siguc);
183   frame->fake_siginfo = *siginfo;
184
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));
189
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));
193
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);
198
199   frame->a1_signo    =         sigNo;
200   frame->a2_siginfo  = (UInt)  &frame->fake_siginfo;
201   frame->a3_ucontext = (UInt)  &frame->fake_ucontext;
202
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));
209
210   if (VG_(clo_trace_signals))
211      VG_(message)(Vg_DebugMsg,
212                   "sigframe_create (thread %u): "
213                   "next EIP=%#lx, next ESP=%#lx\n",
214                   tid, (Addr)handler, (Addr)frame );
215}
216
217
218/* Remove a signal frame from thread 'tid's stack, and restore the CPU
219   state from it.  Note, isRT is irrelevant here. */
220void VG_(sigframe_destroy)( ThreadId tid, Bool isRT )
221{
222   ThreadState *tst;
223   Addr esp;
224   Int sigNo;
225   struct hacky_sigframe* frame;
226
227   vg_assert(VG_(is_valid_tid)(tid));
228   tst = VG_(get_ThreadState)(tid);
229
230   /* Check that the stack frame looks valid */
231   esp = VG_(get_SP)(tid);
232
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);
238
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));
242
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);
248
249   tst->sig_mask            = frame->mask;
250   tst->tmp_sig_mask        = frame->mask;
251   sigNo                    = frame->sigNo_private;
252
253   if (VG_(clo_trace_signals))
254      VG_(message)(Vg_DebugMsg,
255                   "sigframe_destroy (thread %u): "
256                   "valid magic; next EIP=%#x\n",
257                   tid, tst->arch.vex.guest_EIP);
258
259   VG_TRACK( die_mem_stack_signal,
260             (Addr)frame - VG_STACK_REDZONE_SZB,
261             sizeof(struct hacky_sigframe) );
262
263   /* tell the tools */
264   VG_TRACK( post_deliver_signal, tid, sigNo );
265}
266
267#endif // defined(VGP_x86_darwin)
268
269/*--------------------------------------------------------------------*/
270/*--- end                                                          ---*/
271/*--------------------------------------------------------------------*/
272