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-2013 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
49
50 /* Cheap-ass hack copied from ppc32-aix5 code, just to get started.
51 Produce a frame with layout entirely of our own choosing. */
52
53 /* This module creates and removes signal frames for signal deliveries
54 on x86-darwin. Kludgey; the machine state ought to be saved in a
55 ucontext and retrieved from it later, so the handler can modify it
56 and return. However .. for now .. just stick the vex guest state
57 in the frame and snarf it again later.
58
59 Also, don't bother with creating siginfo and ucontext in the
60 handler, although do point them somewhere non-faulting.
61
62 Frame should have a 16-aligned size, just in case that turns out to
63 be important for Darwin. (be conservative)
64 */
65 struct hacky_sigframe {
66 /* first four words look like a call to a 3-arg x86 function */
67 UInt returnAddr;
68 UInt a1_signo;
69 UInt a2_siginfo;
70 UInt a3_ucontext;
71 UChar lower_guardzone[512]; // put nothing here
72 VexGuestX86State gst;
73 VexGuestX86State gshadow1;
74 VexGuestX86State gshadow2;
75 vki_siginfo_t fake_siginfo;
76 struct vki_ucontext fake_ucontext;
77 UInt magicPI;
78 UInt sigNo_private;
79 vki_sigset_t mask; // saved sigmask; restore when hdlr returns
80 UInt __pad[1];
81 UChar upper_guardzone[512]; // put nothing here
82 // and don't zero it, since that might overwrite the client's
83 // stack redzone, at least on archs which have one
84 };
85
86
87 /* Create a signal frame for thread 'tid'. Make a 3-arg frame
88 regardless of whether the client originally requested a 1-arg
89 version (no SA_SIGINFO) or a 3-arg one (SA_SIGINFO) since in the
90 former case, the x86 calling conventions will simply cause the
91 extra 2 args to be ignored (inside the handler). */
VG_(sigframe_create)92 void VG_(sigframe_create) ( ThreadId tid,
93 Addr sp_top_of_frame,
94 const vki_siginfo_t *siginfo,
95 const struct vki_ucontext *siguc,
96 void *handler,
97 UInt flags,
98 const vki_sigset_t *mask,
99 void *restorer )
100 {
101 ThreadState* tst;
102 Addr esp;
103 struct hacky_sigframe* frame;
104 Int sigNo = siginfo->si_signo;
105
106 vg_assert(VG_IS_16_ALIGNED(sizeof(struct hacky_sigframe)));
107
108 sp_top_of_frame &= ~0xf;
109 esp = sp_top_of_frame - sizeof(struct hacky_sigframe);
110 esp -= 4; /* ELF ABI says that esp+4 must be 16 aligned on
111 entry to a function. */
112
113 tst = VG_(get_ThreadState)(tid);
114 if (! ML_(sf_maybe_extend_stack)(tst, esp, sp_top_of_frame - esp, flags))
115 return;
116
117 vg_assert(VG_IS_16_ALIGNED(esp+4));
118
119 frame = (struct hacky_sigframe *) esp;
120
121 /* clear it (very conservatively) (why so conservatively??) */
122 VG_(memset)(&frame->lower_guardzone, 0, sizeof frame->lower_guardzone);
123 VG_(memset)(&frame->gst, 0, sizeof(VexGuestX86State));
124 VG_(memset)(&frame->gshadow1, 0, sizeof(VexGuestX86State));
125 VG_(memset)(&frame->gshadow2, 0, sizeof(VexGuestX86State));
126 VG_(memset)(&frame->fake_siginfo, 0, sizeof(frame->fake_siginfo));
127 VG_(memset)(&frame->fake_ucontext, 0, sizeof(frame->fake_ucontext));
128
129 /* save stuff in frame */
130 frame->gst = tst->arch.vex;
131 frame->gshadow1 = tst->arch.vex_shadow1;
132 frame->gshadow2 = tst->arch.vex_shadow2;
133 frame->sigNo_private = sigNo;
134 frame->mask = tst->sig_mask;
135 frame->magicPI = 0x31415927;
136
137 /* Minimally fill in the siginfo and ucontext. Note, utter
138 lameness prevails. Be underwhelmed, be very underwhelmed. */
139 frame->fake_siginfo.si_signo = sigNo;
140 frame->fake_siginfo.si_code = siginfo->si_code;
141
142 /* Set up stack pointer */
143 vg_assert(esp == (Addr)&frame->returnAddr);
144 VG_(set_SP)(tid, esp);
145 VG_TRACK( post_reg_write, Vg_CoreSignal, tid, VG_O_STACK_PTR, sizeof(UInt));
146
147 /* Set up program counter */
148 VG_(set_IP)(tid, (UInt)handler);
149 VG_TRACK( post_reg_write, Vg_CoreSignal, tid, VG_O_INSTR_PTR, sizeof(UInt));
150
151 /* Set up RA and args for the frame */
152 VG_TRACK( pre_mem_write, Vg_CoreSignal, tid, "signal handler frame",
153 (Addr)frame, 4*sizeof(UInt) );
154 frame->returnAddr = (UInt)&VG_(x86_darwin_SUBST_FOR_sigreturn);
155 frame->a1_signo = sigNo;
156 frame->a2_siginfo = (UInt)&frame->fake_siginfo; /* oh well */
157 frame->a3_ucontext = (UInt)&frame->fake_ucontext; /* oh well */
158 VG_TRACK( post_mem_write, Vg_CoreSignal, tid,
159 (Addr)frame, 4*sizeof(UInt) );
160 VG_TRACK( post_mem_write, Vg_CoreSignal, tid,
161 (Addr)&frame->fake_siginfo, sizeof(frame->fake_siginfo));
162 VG_TRACK( post_mem_write, Vg_CoreSignal, tid,
163 (Addr)&frame->fake_ucontext, sizeof(frame->fake_ucontext));
164
165 if (VG_(clo_trace_signals))
166 VG_(message)(Vg_DebugMsg,
167 "sigframe_create (thread %d): "
168 "next EIP=%#lx, next ESP=%#lx\n",
169 tid, (Addr)handler, (Addr)frame );
170 }
171
172
173 /* Remove a signal frame from thread 'tid's stack, and restore the CPU
174 state from it. Note, isRT is irrelevant here. */
VG_(sigframe_destroy)175 void VG_(sigframe_destroy)( ThreadId tid, Bool isRT )
176 {
177 ThreadState *tst;
178 Addr esp;
179 Int sigNo;
180 struct hacky_sigframe* frame;
181
182 vg_assert(VG_(is_valid_tid)(tid));
183 tst = VG_(get_ThreadState)(tid);
184
185 /* Check that the stack frame looks valid */
186 esp = VG_(get_SP)(tid);
187
188 /* why -4 ? because the signal handler's return will have popped
189 the return address off the stack; and the return address is the
190 lowest-addressed element of hacky_sigframe. */
191 frame = (struct hacky_sigframe*)(esp - 4);
192 vg_assert(frame->magicPI == 0x31415927);
193
194 /* This +8 is because of the -4 referred to in the ELF ABI comment
195 in VG_(sigframe_create) just above. */
196 vg_assert(VG_IS_16_ALIGNED((Addr)frame + 4));
197
198 /* restore the entire guest state, and shadows, from the
199 frame. Note, as per comments above, this is a kludge - should
200 restore it from saved ucontext. Oh well. */
201 tst->arch.vex = frame->gst;
202 tst->arch.vex_shadow1 = frame->gshadow1;
203 tst->arch.vex_shadow2 = frame->gshadow2;
204 tst->sig_mask = frame->mask;
205 tst->tmp_sig_mask = frame->mask;
206 sigNo = frame->sigNo_private;
207
208 if (VG_(clo_trace_signals))
209 VG_(message)(Vg_DebugMsg,
210 "sigframe_destroy (thread %d): "
211 "valid magic; next EIP=%#x\n",
212 tid, tst->arch.vex.guest_EIP);
213
214 VG_TRACK( die_mem_stack_signal,
215 (Addr)frame - VG_STACK_REDZONE_SZB,
216 sizeof(struct hacky_sigframe) );
217
218 /* tell the tools */
219 VG_TRACK( post_deliver_signal, tid, sigNo );
220 }
221
222 #endif // defined(VGP_x86_darwin)
223
224 /*--------------------------------------------------------------------*/
225 /*--- end ---*/
226 /*--------------------------------------------------------------------*/
227