1
2 /*--------------------------------------------------------------------*/
3 /*--- Create/destroy signal delivery frames. ---*/
4 /*--- sigframe-solaris.c ---*/
5 /*--------------------------------------------------------------------*/
6
7 /*
8 This file is part of Valgrind, a dynamic binary instrumentation
9 framework.
10
11 Copyright (C) 2011-2017 Petr Pavlu
12 setup@dagobah.cz
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_solaris) || defined(VGP_amd64_solaris)
33
34 #include "pub_core_basics.h"
35 #include "pub_core_vki.h"
36 #include "pub_core_threadstate.h"
37 #include "pub_core_aspacemgr.h"
38 #include "pub_core_libcassert.h"
39 #include "pub_core_libcbase.h"
40 #include "pub_core_libcprint.h"
41 #include "pub_core_machine.h"
42 #include "pub_core_options.h"
43 #include "pub_core_signals.h"
44 #include "pub_core_tooliface.h"
45 #include "pub_core_sigframe.h" /* Self */
46 #include "pub_core_syswrap.h"
47 #include "priv_sigframe.h"
48
49 /* This module creates and removes signal frames for signal deliveries
50 on x86/amd64-solaris. */
51
52 /* Create a signal frame for thread 'tid'. Make a 3-arg frame regardless of
53 whether the client originally requested a 1-arg version (no SA_SIGINFO) or
54 a 3-arg one (SA_SIGINFO) since in the former case, the x86/amd64 calling
55 conventions will simply cause the extra 2 args to be ignored (inside the
56 handler). */
VG_(sigframe_create)57 void VG_(sigframe_create)(ThreadId tid, Bool on_altstack,
58 Addr sp_top_of_frame, const vki_siginfo_t *siginfo,
59 const struct vki_ucontext *siguc,
60 void *handler, UInt flags, const vki_sigset_t *mask,
61 void *restorer)
62 {
63 ThreadState *tst = VG_(get_ThreadState)(tid);
64 Addr esp;
65 vki_sigframe_t *frame;
66 Int signo = siginfo->si_signo;
67
68 /* Calculate new stack pointer. */
69 esp = sp_top_of_frame - sizeof(vki_sigframe_t);
70 esp = VG_ROUNDDN(esp, 16) - sizeof(UWord);
71
72 if (!ML_(sf_maybe_extend_stack)(tst, esp, sp_top_of_frame - esp, flags))
73 return;
74
75 /* Fill in the frame. */
76 frame = (vki_sigframe_t*)esp;
77
78 /* Set a bogus return address. This return address should be never used
79 because to return from a signal handler a program has to call
80 setcontext() explicitly. */
81 frame->return_addr = (void*)~0UL;
82
83 /* Save current context. (This has to be done before the thread state is
84 modified in any way.) */
85 VG_(save_context)(tid, &frame->ucontext, Vg_CoreSignal);
86
87 /* Fill in the siginfo. */
88 frame->siginfo = *siginfo;
89 /* Set expected si_addr value.
90
91 Manual page siginfo.h(3HEAD) describes that some signals define si_addr
92 to be an address of the faulting instruction (SIGILL). Then it is needed
93 to change the real CPU address to the VCPU address. Some signals define
94 si_addr to be an address of the faulting memory reference (SIGSEGV,
95 SIGBUS). Then the address should be passed unmodified.
96
97 However documentation contained in the manpage does not reflect the
98 reality found in the Solaris kernel - uts/<arch>/os/trap.c. Here one can
99 observe that in some cases si_addr is set to address provided by the
100 underlying subsystem. In some cases si_addr is set to the current
101 program counter. Other signals are missing documentation altogether.
102 It is almost impossible to determine what value is stored in si_addr
103 based on the information provided by kernel to the signal handler.
104
105 POSIX.1-2008 says about si_addr:
106 SIGILL, SIGFPE ... Address of faulting instruction.
107 SIGSEGV, SIGBUS ... Address of faulting memory reference.
108 For some implementations, the value of si_addr may be inaccurate.
109
110 See tests none/tests/faultstatus and none/tests/x86/badseg for examples.
111 The code below simply follows the POSIX standard, but propagates any
112 possibly incorrect values from the kernel to the user.
113 */
114 switch (signo) {
115 case VKI_SIGSEGV:
116 switch (siginfo->si_code) {
117 case VKI_SEGV_ACCERR:
118 case VKI_SEGV_MAPERR:
119 default:
120 break;
121 case VKI_SEGV_MADE_UP_GPF:
122 /* Translate si_code synthesized by Valgrind to SEGV_MAPPER. */
123 frame->siginfo.si_code = VKI_SEGV_MAPERR;
124 break;
125 }
126 break;
127 case VKI_SIGBUS:
128 break;
129 case VKI_SIGFPE:
130 case VKI_SIGILL:
131 case VKI_SIGTRAP:
132 frame->siginfo.si_addr = (void*)VG_(get_IP)(tid);
133 break;
134 case VKI_SIGPROF:
135 frame->siginfo.si_faddr = (void*)VG_(get_IP)(tid);
136 break;
137 default:
138 break;
139 }
140 VG_TRACK(post_mem_write, Vg_CoreSignal, tid, (Addr)&frame->siginfo,
141 sizeof(frame->siginfo));
142
143 /* Save the signal number in an unused slot. Later, when a return from the
144 signal is made, this value is used to inform the tool that the
145 processing for the given signal has ended. */
146 VKI_UC_SIGNO(&frame->ucontext) = signo | ((~(UWord)signo & 0xFFFF) << 16);
147 /* Old context has to point to the saved ucontext. */
148 tst->os_state.oldcontext = &frame->ucontext;
149 /* Save ERR and TRAPNO if siguc is present. */
150 if (siguc) {
151 frame->ucontext.uc_mcontext.gregs[VKI_REG_ERR]
152 = siguc->uc_mcontext.gregs[VKI_REG_ERR];
153 VG_TRACK(post_mem_write, Vg_CoreSignal, tid,
154 (Addr)&frame->ucontext.uc_mcontext.gregs[VKI_REG_ERR],
155 sizeof(UWord));
156 frame->ucontext.uc_mcontext.gregs[VKI_REG_TRAPNO]
157 = siguc->uc_mcontext.gregs[VKI_REG_TRAPNO];
158 VG_TRACK(post_mem_write, Vg_CoreSignal, tid,
159 (Addr)&frame->ucontext.uc_mcontext.gregs[VKI_REG_TRAPNO],
160 sizeof(UWord));
161 }
162
163 /* Prepare parameters for a signal handler. */
164 frame->a1_signo = signo;
165 /* The first parameter has to be 16-byte aligned, resembling function
166 calls. */
167 {
168 /* Using
169 vg_assert(VG_IS_16_ALIGNED(&frame->a1_signo));
170 seems to get miscompiled on amd64 with GCC 4.7.2. */
171 Addr signo_addr = (Addr)&frame->a1_signo;
172 vg_assert(VG_IS_16_ALIGNED(signo_addr));
173 }
174 frame->a2_siginfo = &frame->siginfo;
175 VG_TRACK(post_mem_write, Vg_CoreSignal, tid, (Addr)&frame->a1_signo,
176 sizeof(frame->a1_signo) + sizeof(frame->a2_siginfo));
177 #if defined(VGP_x86_solaris)
178 frame->a3_ucontext = &frame->ucontext;
179 VG_TRACK(post_mem_write, Vg_CoreSignal, tid, (Addr)&frame->a3_ucontext,
180 sizeof(frame->a3_ucontext));
181 #elif defined(VGP_amd64_solaris)
182 tst->arch.vex.guest_RDI = signo;
183 VG_TRACK(post_reg_write, Vg_CoreSignal, tid, offsetof(VexGuestAMD64State,
184 guest_RDI), sizeof(ULong));
185 tst->arch.vex.guest_RSI = (Addr)&frame->siginfo;
186 VG_TRACK(post_reg_write, Vg_CoreSignal, tid, offsetof(VexGuestAMD64State,
187 guest_RSI), sizeof(ULong));
188 tst->arch.vex.guest_RDX = (Addr)&frame->ucontext;
189 VG_TRACK(post_reg_write, Vg_CoreSignal, tid, offsetof(VexGuestAMD64State,
190 guest_RDX), sizeof(ULong));
191 #endif
192
193 /* Set up the stack pointer. */
194 vg_assert(esp == (Addr)&frame->return_addr);
195 VG_(set_SP)(tid, esp);
196 VG_TRACK(post_reg_write, Vg_CoreSignal, tid, VG_O_STACK_PTR, sizeof(Addr));
197
198 /* Set up the program counter. Note that we don't inform a tool about IP
199 write because IP is always defined. */
200 VG_(set_IP)(tid, (Addr)handler);
201
202 /* If the signal is delivered on the alternate stack, copy it out to
203 ustack. This has to be done after setting a new IP so the SS_ONSTACK
204 flag is set by VG_(do_sys_sigaltstack)(). */
205 if (on_altstack && tst->os_state.ustack
206 && VG_(am_is_valid_for_client)((Addr)tst->os_state.ustack,
207 sizeof(*tst->os_state.ustack),
208 VKI_PROT_WRITE)) {
209 SysRes res;
210 vki_stack_t altstack;
211
212 /* Get information about alternate stack. */
213 res = VG_(do_sys_sigaltstack)(tid, NULL, &altstack);
214 vg_assert(!sr_isError(res));
215
216 /* Copy it to ustack. */
217 *tst->os_state.ustack = altstack;
218 VG_TRACK(post_mem_write, Vg_CoreSignal, tid, (Addr)tst->os_state.ustack,
219 sizeof(*tst->os_state.ustack));
220 }
221
222 if (VG_(clo_trace_signals))
223 VG_(message)(Vg_DebugMsg,
224 "sigframe_create (thread %u): next IP=%#lx, "
225 "next SP=%#lx\n",
226 tid, (Addr)handler, (Addr)frame);
227 }
228
VG_(sigframe_destroy)229 void VG_(sigframe_destroy)(ThreadId tid, Bool isRT)
230 {
231 /* Not used on Solaris. */
232 vg_assert(0);
233 }
234
VG_(sigframe_return)235 void VG_(sigframe_return)(ThreadId tid, const vki_ucontext_t *uc)
236 {
237 Int signo;
238
239 /* Check if a signal number was saved in the restored context. */
240 signo = VKI_UC_SIGNO_CONST(uc) & 0xFFFF;
241 if (!signo || signo != ((~VKI_UC_SIGNO_CONST(uc) >> 16) & 0xFFFF))
242 return;
243
244 /* Note: The active tool should be informed here about the dead stack area.
245 However, this was already done when the original context was restored (in
246 VG_(restore_context)()) so it is not necessary to do it here again.
247
248 There is a small nuance though, VG_(restore_context)() triggers the
249 die_mem_stack event while in this case, it should really trigger the
250 die_mem_stack_signal event. This is not currently a problem because all
251 official tools handle these two events in the same way.
252
253 If a return from an alternate stack is made then no die_mem_stack event
254 is currently triggered. */
255
256 /* Returning from a signal handler. */
257 if (VG_(clo_trace_signals))
258 VG_(message)(Vg_DebugMsg,
259 "sigframe_return (thread %u): IP=%#lx\n",
260 tid, VG_(get_IP)(tid));
261
262 /* Tell the tool. */
263 VG_TRACK(post_deliver_signal, tid, signo);
264 }
265
266 #endif // defined(VGP_x86_solaris) || defined(VGP_amd64_solaris)
267
268 /*--------------------------------------------------------------------*/
269 /*--- end ---*/
270 /*--------------------------------------------------------------------*/
271