blob: 723bf030e23e7b5105621c1a2796559f05a6b0ce [file] [log] [blame]
sewardj2c48c7b2005-11-29 13:05:56 +00001
2/*--------------------------------------------------------------------*/
3/*--- Create/destroy signal delivery frames. ---*/
4/*--- sigframe-ppc64-linux.c ---*/
5/*--------------------------------------------------------------------*/
6
7/*
8 This file is part of Valgrind, a dynamic binary instrumentation
9 framework.
10
11 Copyright (C) 2000-2005 Nicholas Nethercote
12 njn@valgrind.org
13 Copyright (C) 2004-2005 Paul Mackerras
14 paulus@samba.org
15
16 This program is free software; you can redistribute it and/or
17 modify it under the terms of the GNU General Public License as
18 published by the Free Software Foundation; either version 2 of the
19 License, or (at your option) any later version.
20
21 This program is distributed in the hope that it will be useful, but
22 WITHOUT ANY WARRANTY; without even the implied warranty of
23 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
24 General Public License for more details.
25
26 You should have received a copy of the GNU General Public License
27 along with this program; if not, write to the Free Software
28 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
29 02111-1307, USA.
30
31 The GNU General Public License is contained in the file COPYING.
32*/
33
34#include "pub_core_basics.h"
35#include "pub_core_threadstate.h"
36#include "pub_core_aspacemgr.h"
37#include "pub_core_libcbase.h"
38#include "pub_core_libcassert.h"
39#include "pub_core_libcprint.h"
40#include "pub_core_machine.h"
41#include "pub_core_options.h"
42#include "pub_core_sigframe.h"
43#include "pub_core_signals.h"
44#include "pub_core_tooliface.h"
45#include "pub_core_trampoline.h"
46#include "pub_core_transtab.h" // VG_(discard_translations)
47#include "vki_unistd-ppc64-linux.h" // __NR_rt_sigreturn
48
49
50/* This module creates and removes signal frames for signal deliveries
51 on ppc64-linux.
52
53 Note, this file contains kernel-specific knowledge in the form of
54 'struct sigframe' and 'struct rt_sigframe'. How does that relate
55 to the vki kernel interface stuff?
56
57 Either a 'struct sigframe' or a 'struct rtsigframe' is pushed
58 onto the client's stack. This contains a subsidiary
59 vki_ucontext. That holds the vcpu's state across the signal,
60 so that the sighandler can mess with the vcpu state if it
61 really wants.
62
63 FIXME: sigcontexting is basically broken for the moment. When
64 delivering a signal, the integer registers and %eflags are
65 correctly written into the sigcontext, however the FP and SSE state
66 is not. When returning from a signal, only the integer registers
67 are restored from the sigcontext; the rest of the CPU state is
68 restored to what it was before the signal.
69
70 This will be fixed.
71*/
72
73
74/*------------------------------------------------------------*/
75/*--- Signal frame layouts ---*/
76/*------------------------------------------------------------*/
77
78// A structure in which to save the application's registers
79// during the execution of signal handlers.
80
81// Linux has 2 signal frame structures: one for normal signal
82// deliveries, and one for SA_SIGINFO deliveries (also known as RT
83// signals).
84//
85// In theory, so long as we get the arguments to the handler function
86// right, it doesn't matter what the exact layout of the rest of the
87// frame is. Unfortunately, things like gcc's exception unwinding
88// make assumptions about the locations of various parts of the frame,
89// so we need to duplicate it exactly.
90
91/* Structure containing bits of information that we want to save
92 on signal delivery. */
93//zz struct vg_sig_private {
94//zz UInt magicPI;
95//zz UInt sigNo_private;
96//zz VexGuestPPC32State shadow;
97//zz };
98//zz
99//zz /* Structure put on stack for signal handlers with SA_SIGINFO clear. */
100//zz struct nonrt_sigframe {
101//zz UInt gap1[16];
102//zz struct vki_sigcontext sigcontext;
103//zz struct vki_mcontext mcontext;
104//zz struct vg_sig_private priv;
105//zz unsigned char abigap[224];
106//zz };
107//zz
108//zz /* Structure put on stack for signal handlers with SA_SIGINFO set. */
109//zz struct rt_sigframe {
110//zz UInt gap1[20];
111//zz vki_siginfo_t siginfo;
112//zz struct vki_ucontext ucontext;
113//zz struct vg_sig_private priv;
114//zz unsigned char abigap[224];
115//zz };
116
117#define SET_SIGNAL_LR(zztst, zzval) \
118 do { tst->arch.vex.guest_LR = (zzval); \
119 VG_TRACK( post_reg_write, Vg_CoreSignal, tst->tid, \
120 offsetof(VexGuestPPC32State,guest_LR), \
121 sizeof(UWord) ); \
122 } while (0)
123
124#define SET_SIGNAL_GPR(zztst, zzn, zzval) \
125 do { tst->arch.vex.guest_GPR##zzn = (zzval); \
126 VG_TRACK( post_reg_write, Vg_CoreSignal, tst->tid, \
127 offsetof(VexGuestPPC32State,guest_GPR##zzn), \
128 sizeof(UWord) ); \
129 } while (0)
130
131
132static
133void stack_mcontext ( struct vki_mcontext *mc,
134 ThreadState* tst,
135 Int ret,
136 UInt fault_addr )
137{
138// VG_TRACK( pre_mem_write, Vg_CoreSignal, tst->tid, "signal frame mcontext",
139// (Addr)mc, sizeof(struct vki_pt_regs) );
140//
141//# define DO(gpr) mc->mc_gregs[VKI_PT_R0+gpr] = tst->arch.vex.guest_GPR##gpr
142// DO(0); DO(1); DO(2); DO(3); DO(4); DO(5); DO(6); DO(7);
143// DO(8); DO(9); DO(10); DO(11); DO(12); DO(13); DO(14); DO(15);
144// DO(16); DO(17); DO(18); DO(19); DO(20); DO(21); DO(22); DO(23);
145// DO(24); DO(25); DO(26); DO(27); DO(28); DO(29); DO(30); DO(31);
146//# undef DO
147//
148// mc->mc_gregs[VKI_PT_NIP] = tst->arch.vex.guest_CIA;
149// mc->mc_gregs[VKI_PT_MSR] = 0xf032; /* pretty arbitrary */
150// mc->mc_gregs[VKI_PT_ORIG_R3] = tst->arch.vex.guest_GPR3;
151// mc->mc_gregs[VKI_PT_CTR] = tst->arch.vex.guest_CTR;
152// mc->mc_gregs[VKI_PT_LNK] = tst->arch.vex.guest_LR;
153// mc->mc_gregs[VKI_PT_XER] = LibVEX_GuestPPC32_get_XER(&tst->arch.vex);
154// mc->mc_gregs[VKI_PT_CCR] = LibVEX_GuestPPC32_get_CR(&tst->arch.vex);
155// mc->mc_gregs[VKI_PT_MQ] = 0;
156// mc->mc_gregs[VKI_PT_TRAP] = 0;
157// mc->mc_gregs[VKI_PT_DAR] = fault_addr;
158// mc->mc_gregs[VKI_PT_DSISR] = 0;
159// mc->mc_gregs[VKI_PT_RESULT] = 0;
160// VG_TRACK( post_mem_write, Vg_CoreSignal, tst->tid,
161// (Addr)mc, sizeof(struct vki_pt_regs) );
162//
163// /* XXX should do FP and vector regs */
164//
165// /* set up signal return trampoline */
166// VG_TRACK(pre_mem_write, Vg_CoreSignal, tst->tid, "signal frame mcontext",
167// (Addr)&mc->mc_pad, sizeof(mc->mc_pad));
168// mc->mc_pad[0] = 0x38000000U + ret; /* li 0,ret */
169// mc->mc_pad[1] = 0x44000002U; /* sc */
170// VG_TRACK( post_mem_write, Vg_CoreSignal, tst->tid,
171// (Addr)&mc->mc_pad, sizeof(mc->mc_pad) );
172// /* invalidate any translation of this area */
173// VG_(discard_translations)( (Addr64)(Addr)&mc->mc_pad,
174// sizeof(mc->mc_pad), "stack_mcontext" );
175//
176// /* set the signal handler to return to the trampoline */
177// SET_SIGNAL_LR(tst, (Addr) &mc->mc_pad[0]);
178}
179
180
181/* Extend the stack segment downwards if needed so as to ensure the
182 new signal frames are mapped to something. Return a Bool
183 indicating whether or not the operation was successful.
184*/
185static Bool extend ( ThreadState *tst, Addr addr, SizeT size )
186{
187 I_die_here;
188// ThreadId tid = tst->tid;
189// NSegment *stackseg = NULL;
190//
191// if (VG_(extend_stack)(addr, tst->client_stack_szB)) {
192// stackseg = VG_(am_find_nsegment)(addr);
193// if (0 && stackseg)
194// VG_(printf)("frame=%p seg=%p-%p\n",
195// addr, stackseg->start, stackseg->end);
196// }
197//
198// if (stackseg == NULL || !stackseg->hasR || !stackseg->hasW) {
199// VG_(message)(
200// Vg_UserMsg,
201// "Can't extend stack to %p during signal delivery for thread %d:",
202// addr, tid);
203// if (stackseg == NULL)
204// VG_(message)(Vg_UserMsg, " no stack segment");
205// else
206// VG_(message)(Vg_UserMsg, " too small or bad protection modes");
207//
208// /* set SIGSEGV to default handler */
209// VG_(set_default_handler)(VKI_SIGSEGV);
210// VG_(synth_fault_mapping)(tid, addr);
211//
212// /* The whole process should be about to die, since the default
213// action of SIGSEGV to kill the whole process. */
214// return False;
215// }
216//
217// /* For tracking memory events, indicate the entire frame has been
218// allocated. */
219// VG_TRACK( new_mem_stack_signal, addr - VG_STACK_REDZONE_SZB,
220// size + VG_STACK_REDZONE_SZB );
221//
222// return True;
223}
224
225
226/* EXPORTED */
227void VG_(sigframe_create)( ThreadId tid,
228 Addr sp_top_of_frame,
229 const vki_siginfo_t *siginfo,
230 void *handler,
231 UInt flags,
232 const vki_sigset_t *mask,
233 void *restorer )
234{
235 I_die_here;
236// struct vg_sig_private *priv;
237// Addr sp;
238// ThreadState *tst;
239// Int sigNo = siginfo->si_signo;
240// Addr faultaddr;
241//
242// /* Stack must be 16-byte aligned */
243// sp_top_of_frame &= ~0xf;
244//
245// if (flags & VKI_SA_SIGINFO) {
246// sp = sp_top_of_frame - sizeof(struct rt_sigframe);
247// } else {
248// sp = sp_top_of_frame - sizeof(struct nonrt_sigframe);
249// }
250//
251// tst = VG_(get_ThreadState)(tid);
252//
253// if (!extend(tst, sp, sp_top_of_frame - sp))
254// return;
255//
256// vg_assert(VG_IS_16_ALIGNED(sp));
257//
258// /* Set up the stack chain pointer */
259// VG_TRACK( pre_mem_write, Vg_CoreSignal, tid, "signal handler frame",
260// sp, sizeof(UWord) );
261// *(Addr *)sp = tst->arch.vex.guest_GPR1;
262// VG_TRACK( post_mem_write, Vg_CoreSignal, tid,
263// sp, sizeof(UWord) );
264//
265// faultaddr = (Addr)siginfo->_sifields._sigfault._addr;
266// if (sigNo == VKI_SIGILL && siginfo->si_code > 0)
267// faultaddr = tst->arch.vex.guest_CIA;
268//
269// if (flags & VKI_SA_SIGINFO) {
270// struct rt_sigframe *frame = (struct rt_sigframe *) sp;
271// struct vki_ucontext *ucp = &frame->ucontext;
272//
273// VG_TRACK( pre_mem_write, Vg_CoreSignal, tid, "signal frame siginfo",
274// (Addr)&frame->siginfo, sizeof(frame->siginfo) );
275// VG_(memcpy)(&frame->siginfo, siginfo, sizeof(*siginfo));
276// VG_TRACK( post_mem_write, Vg_CoreSignal, tid,
277// (Addr)&frame->siginfo, sizeof(frame->siginfo) );
278//
279// VG_TRACK( pre_mem_write, Vg_CoreSignal, tid, "signal frame ucontext",
280// (Addr)ucp, offsetof(struct vki_ucontext, uc_pad) );
281// ucp->uc_flags = 0;
282// ucp->uc_link = 0;
283// ucp->uc_stack = tst->altstack;
284// VG_TRACK( post_mem_write, Vg_CoreSignal, tid, (Addr)ucp,
285// offsetof(struct vki_ucontext, uc_pad) );
286//
287// VG_TRACK( pre_mem_write, Vg_CoreSignal, tid, "signal frame ucontext",
288// (Addr)&ucp->uc_regs,
289// sizeof(ucp->uc_regs) + sizeof(ucp->uc_sigmask) );
290// ucp->uc_regs = &ucp->uc_mcontext;
291// ucp->uc_sigmask = tst->sig_mask;
292// VG_TRACK( post_mem_write, Vg_CoreSignal, tid,
293// (Addr)&ucp->uc_regs,
294// sizeof(ucp->uc_regs) + sizeof(ucp->uc_sigmask) );
295//
296// stack_mcontext(&ucp->uc_mcontext, tst, __NR_rt_sigreturn, faultaddr);
297// priv = &frame->priv;
298//
299// SET_SIGNAL_GPR(tid, 4, (Addr) &frame->siginfo);
300// SET_SIGNAL_GPR(tid, 5, (Addr) ucp);
301// /* the kernel sets this, though it doesn't seem to be in the ABI */
302// SET_SIGNAL_GPR(tid, 6, (Addr) &frame->siginfo);
303//
304// } else {
305// /* non-RT signal delivery */
306// struct nonrt_sigframe *frame = (struct nonrt_sigframe *) sp;
307// struct vki_sigcontext *scp = &frame->sigcontext;
308//
309// VG_TRACK( pre_mem_write, Vg_CoreSignal, tid, "signal frame sigcontext",
310// (Addr)&scp->_unused[3], sizeof(*scp) - 3 * sizeof(UInt) );
311// scp->signal = sigNo;
312// scp->handler = (Addr) handler;
313// scp->oldmask = tst->sig_mask.sig[0];
314// scp->_unused[3] = tst->sig_mask.sig[1];
315// VG_TRACK( post_mem_write, Vg_CoreSignal, tid,
316// (Addr)&scp->_unused[3], sizeof(*scp) - 3 * sizeof(UInt) );
317//
318// stack_mcontext(&frame->mcontext, tst, __NR_sigreturn, faultaddr);
319// priv = &frame->priv;
320//
321// SET_SIGNAL_GPR(tid, 4, (Addr) scp);
322// }
323//
324// priv->magicPI = 0x31415927;
325// priv->sigNo_private = sigNo;
326// priv->shadow = tst->arch.vex_shadow;
327//
328// SET_SIGNAL_GPR(tid, 1, sp);
329// SET_SIGNAL_GPR(tid, 3, sigNo);
330// tst->arch.vex.guest_CIA = (Addr) handler;
331//
332// if (0)
333// VG_(printf)("pushed signal frame; %R1 now = %p, "
334// "next %%CIA = %p, status=%d\n",
335// sp, tst->arch.vex.guest_CIA, tst->status);
336}
337
338
339/*------------------------------------------------------------*/
340/*--- Destroying signal frames ---*/
341/*------------------------------------------------------------*/
342
343/* EXPORTED */
344void VG_(sigframe_destroy)( ThreadId tid, Bool isRT )
345{
346 I_die_here;
347// ThreadState *tst;
348// struct vg_sig_private *priv;
349// Addr sp;
350// UInt frame_size;
351// struct vki_mcontext *mc;
352// Int sigNo;
353// Bool has_siginfo = isRT;
354//
355// vg_assert(VG_(is_valid_tid)(tid));
356// tst = VG_(get_ThreadState)(tid);
357//
358// /* Check that the stack frame looks valid */
359// sp = tst->arch.vex.guest_GPR1;
360// vg_assert(VG_IS_16_ALIGNED(sp));
361// /* JRS 17 Nov 05: This code used to check that *sp -- which should
362// have been set by the stwu at the start of the handler -- points
363// to just above the frame (ie, the previous frame). However, that
364// isn't valid when delivering signals on alt stacks. So I removed
365// it. The frame is still sanity-checked using the priv->magicPI
366// field. */
367//
368// if (has_siginfo) {
369// struct rt_sigframe *frame = (struct rt_sigframe *)sp;
370// frame_size = sizeof(*frame);
371// mc = &frame->ucontext.uc_mcontext;
372// priv = &frame->priv;
373// vg_assert(priv->magicPI == 0x31415927);
374// tst->sig_mask = frame->ucontext.uc_sigmask;
375// } else {
376// struct nonrt_sigframe *frame = (struct nonrt_sigframe *)sp;
377// frame_size = sizeof(*frame);
378// mc = &frame->mcontext;
379// priv = &frame->priv;
380// vg_assert(priv->magicPI == 0x31415927);
381// tst->sig_mask.sig[0] = frame->sigcontext.oldmask;
382// tst->sig_mask.sig[1] = frame->sigcontext._unused[3];
383// }
384// tst->tmp_sig_mask = tst->sig_mask;
385//
386// sigNo = priv->sigNo_private;
387//
388//# define DO(gpr) tst->arch.vex.guest_GPR##gpr = mc->mc_gregs[VKI_PT_R0+gpr]
389// DO(0); DO(1); DO(2); DO(3); DO(4); DO(5); DO(6); DO(7);
390// DO(8); DO(9); DO(10); DO(11); DO(12); DO(13); DO(14); DO(15);
391// DO(16); DO(17); DO(18); DO(19); DO(20); DO(21); DO(22); DO(23);
392// DO(24); DO(25); DO(26); DO(27); DO(28); DO(29); DO(30); DO(31);
393//# undef DO
394//
395// tst->arch.vex.guest_CIA = mc->mc_gregs[VKI_PT_NIP];
396//
397// // Umm ... ? (jrs 2005 July 8)
398// // tst->arch.m_orig_gpr3 = mc->mc_gregs[VKI_PT_ORIG_R3];
399//
400// LibVEX_GuestPPC32_put_CR( mc->mc_gregs[VKI_PT_CCR], &tst->arch.vex );
401//
402// tst->arch.vex.guest_LR = mc->mc_gregs[VKI_PT_LNK];
403// tst->arch.vex.guest_CTR = mc->mc_gregs[VKI_PT_CTR];
404// LibVEX_GuestPPC32_put_XER( mc->mc_gregs[VKI_PT_XER], &tst->arch.vex );
405//
406// tst->arch.vex_shadow = priv->shadow;
407//
408// VG_TRACK(die_mem_stack_signal, sp, frame_size);
409//
410// if (VG_(clo_trace_signals))
411// VG_(message)(Vg_DebugMsg,
412// "vg_pop_signal_frame (thread %d): isRT=%d valid magic; EIP=%p",
413// tid, has_siginfo, tst->arch.vex.guest_CIA);
414//
415// /* tell the tools */
416// VG_TRACK( post_deliver_signal, tid, sigNo );
417}
418
419/*--------------------------------------------------------------------*/
420/*--- end sigframe-ppc64-linux.c ---*/
421/*--------------------------------------------------------------------*/