• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 
2 /*--------------------------------------------------------------------*/
3 /*--- Create/destroy signal delivery frames.                       ---*/
4 /*---                                       sigframe-s390x-linux.c ---*/
5 /*--------------------------------------------------------------------*/
6 
7 /*
8    This file is part of Valgrind, a dynamic binary instrumentation
9    framework.
10 
11    Copyright IBM Corp. 2010-2013
12 
13    This program is free software; you can redistribute it and/or
14    modify it under the terms of the GNU General Public License as
15    published by the Free Software Foundation; either version 2 of the
16    License, or (at your option) any later version.
17 
18    This program is distributed in the hope that it will be useful, but
19    WITHOUT ANY WARRANTY; without even the implied warranty of
20    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
21    General Public License for more details.
22 
23    You should have received a copy of the GNU General Public License
24    along with this program; if not, write to the Free Software
25    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
26    02111-1307, USA.
27 
28    The GNU General Public License is contained in the file COPYING.
29 */
30 
31 /* Contributed by Christian Borntraeger */
32 
33 #include "pub_core_basics.h"
34 #include "pub_core_vki.h"
35 #include "pub_core_vkiscnums.h"
36 #include "pub_core_libcsetjmp.h"    // to keep _threadstate.h happy
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_sigframe.h"
45 #include "pub_core_signals.h"
46 #include "pub_core_tooliface.h"
47 #include "pub_core_trampoline.h"
48 
49 #if defined(VGA_s390x)
50 
51 /* This module creates and removes signal frames for signal deliveries
52    on s390x-linux.
53 
54    Note, this file contains kernel-specific knowledge in the form of
55    'struct sigframe' and 'struct rt_sigframe'.
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 
64 #define SET_SIGNAL_GPR(zztst, zzn, zzval)                    \
65    do { zztst->arch.vex.guest_r##zzn = (unsigned long)(zzval);              \
66       VG_TRACK( post_reg_write, Vg_CoreSignal, zztst->tid,     \
67                 offsetof(VexGuestS390XState,guest_r##zzn), \
68                 sizeof(UWord) );                             \
69    } while (0)
70 
71 /*------------------------------------------------------------*/
72 /*--- Signal frame layouts                                 ---*/
73 /*------------------------------------------------------------*/
74 
75 // A structure in which to save the application's registers
76 // during the execution of signal handlers.
77 
78 // Linux has 2 signal frame structures: one for normal signal
79 // deliveries, and one for SA_SIGINFO deliveries (also known as RT
80 // signals).
81 //
82 // In theory, so long as we get the arguments to the handler function
83 // right, it doesn't matter what the exact layout of the rest of the
84 // frame is.  Unfortunately, things like gcc's exception unwinding
85 // make assumptions about the locations of various parts of the frame,
86 // so we need to duplicate it exactly.
87 
88 /* Valgrind-specific parts of the signal frame */
89 struct vg_sigframe
90 {
91    /* Sanity check word. */
92    UInt magicPI;
93 
94    UInt handlerflags;	/* flags for signal handler */
95 
96 
97    /* Safely-saved version of sigNo, as described above. */
98    Int  sigNo_private;
99 
100    /* XXX This is wrong.  Surely we should store the shadow values
101       into the shadow memory behind the actual values? */
102    VexGuestS390XState vex_shadow1;
103    VexGuestS390XState vex_shadow2;
104 
105    /* HACK ALERT */
106    VexGuestS390XState vex;
107    /* end HACK ALERT */
108 
109    /* saved signal mask to be restored when handler returns */
110    vki_sigset_t	mask;
111 
112    /* Sanity check word.  Is the highest-addressed word; do not
113       move!*/
114    UInt magicE;
115 };
116 
117 #define S390_SYSCALL_SIZE 2
118 
119 struct sigframe
120 {
121    UChar callee_used_stack[__VKI_SIGNAL_FRAMESIZE];
122    struct vki_sigcontext sc;
123    _vki_sigregs sregs;
124    Int sigNo;
125    UChar retcode[S390_SYSCALL_SIZE];
126 
127    struct vg_sigframe vg;
128 };
129 
130 struct rt_sigframe
131 {
132    UChar callee_used_stack[__VKI_SIGNAL_FRAMESIZE];
133    UChar retcode[S390_SYSCALL_SIZE];
134    struct vki_siginfo info;
135    struct vki_ucontext uc;
136 
137    struct vg_sigframe vg;
138 };
139 
140 /*------------------------------------------------------------*/
141 /*--- Creating signal frames                               ---*/
142 /*------------------------------------------------------------*/
143 
144 /* Saves all user-controlled register into a _vki_sigregs structure */
save_sigregs(ThreadState * tst,_vki_sigregs * sigregs)145 static void save_sigregs(ThreadState *tst, _vki_sigregs *sigregs)
146 {
147    sigregs->regs.gprs[0]  = tst->arch.vex.guest_r0;
148    sigregs->regs.gprs[1]  = tst->arch.vex.guest_r1;
149    sigregs->regs.gprs[2]  = tst->arch.vex.guest_r2;
150    sigregs->regs.gprs[3]  = tst->arch.vex.guest_r3;
151    sigregs->regs.gprs[4]  = tst->arch.vex.guest_r4;
152    sigregs->regs.gprs[5]  = tst->arch.vex.guest_r5;
153    sigregs->regs.gprs[6]  = tst->arch.vex.guest_r6;
154    sigregs->regs.gprs[7]  = tst->arch.vex.guest_r7;
155    sigregs->regs.gprs[8]  = tst->arch.vex.guest_r8;
156    sigregs->regs.gprs[9]  = tst->arch.vex.guest_r9;
157    sigregs->regs.gprs[10] = tst->arch.vex.guest_r10;
158    sigregs->regs.gprs[11] = tst->arch.vex.guest_r11;
159    sigregs->regs.gprs[12] = tst->arch.vex.guest_r12;
160    sigregs->regs.gprs[13] = tst->arch.vex.guest_r13;
161    sigregs->regs.gprs[14] = tst->arch.vex.guest_r14;
162    sigregs->regs.gprs[15] = tst->arch.vex.guest_r15;
163 
164    sigregs->regs.acrs[0]  = tst->arch.vex.guest_a0;
165    sigregs->regs.acrs[1]  = tst->arch.vex.guest_a1;
166    sigregs->regs.acrs[2]  = tst->arch.vex.guest_a2;
167    sigregs->regs.acrs[3]  = tst->arch.vex.guest_a3;
168    sigregs->regs.acrs[4]  = tst->arch.vex.guest_a4;
169    sigregs->regs.acrs[5]  = tst->arch.vex.guest_a5;
170    sigregs->regs.acrs[6]  = tst->arch.vex.guest_a6;
171    sigregs->regs.acrs[7]  = tst->arch.vex.guest_a7;
172    sigregs->regs.acrs[8]  = tst->arch.vex.guest_a8;
173    sigregs->regs.acrs[9]  = tst->arch.vex.guest_a9;
174    sigregs->regs.acrs[10] = tst->arch.vex.guest_a10;
175    sigregs->regs.acrs[11] = tst->arch.vex.guest_a11;
176    sigregs->regs.acrs[12] = tst->arch.vex.guest_a12;
177    sigregs->regs.acrs[13] = tst->arch.vex.guest_a13;
178    sigregs->regs.acrs[14] = tst->arch.vex.guest_a14;
179    sigregs->regs.acrs[15] = tst->arch.vex.guest_a15;
180 
181    sigregs->fpregs.fprs[0] = tst->arch.vex.guest_f0;
182    sigregs->fpregs.fprs[1] = tst->arch.vex.guest_f1;
183    sigregs->fpregs.fprs[2] = tst->arch.vex.guest_f2;
184    sigregs->fpregs.fprs[3] = tst->arch.vex.guest_f3;
185    sigregs->fpregs.fprs[4] = tst->arch.vex.guest_f4;
186    sigregs->fpregs.fprs[5] = tst->arch.vex.guest_f5;
187    sigregs->fpregs.fprs[6] = tst->arch.vex.guest_f6;
188    sigregs->fpregs.fprs[7] = tst->arch.vex.guest_f7;
189    sigregs->fpregs.fprs[8] = tst->arch.vex.guest_f8;
190    sigregs->fpregs.fprs[9] = tst->arch.vex.guest_f9;
191    sigregs->fpregs.fprs[10] = tst->arch.vex.guest_f10;
192    sigregs->fpregs.fprs[11] = tst->arch.vex.guest_f11;
193    sigregs->fpregs.fprs[12] = tst->arch.vex.guest_f12;
194    sigregs->fpregs.fprs[13] = tst->arch.vex.guest_f13;
195    sigregs->fpregs.fprs[14] = tst->arch.vex.guest_f14;
196    sigregs->fpregs.fprs[15] = tst->arch.vex.guest_f15;
197    sigregs->fpregs.fpc      = tst->arch.vex.guest_fpc;
198 
199    sigregs->regs.psw.addr = tst->arch.vex.guest_IA;
200    /* save a sane dummy mask */
201    sigregs->regs.psw.mask = 0x0705000180000000UL;
202 }
203 
restore_sigregs(ThreadState * tst,_vki_sigregs * sigregs)204 static void restore_sigregs(ThreadState *tst, _vki_sigregs *sigregs)
205 {
206    tst->arch.vex.guest_r0  = sigregs->regs.gprs[0];
207    tst->arch.vex.guest_r1  = sigregs->regs.gprs[1];
208    tst->arch.vex.guest_r2  = sigregs->regs.gprs[2];
209    tst->arch.vex.guest_r3  = sigregs->regs.gprs[3];
210    tst->arch.vex.guest_r4  = sigregs->regs.gprs[4];
211    tst->arch.vex.guest_r5  = sigregs->regs.gprs[5];
212    tst->arch.vex.guest_r6  = sigregs->regs.gprs[6];
213    tst->arch.vex.guest_r7  = sigregs->regs.gprs[7];
214    tst->arch.vex.guest_r8  = sigregs->regs.gprs[8];
215    tst->arch.vex.guest_r9  = sigregs->regs.gprs[9];
216    tst->arch.vex.guest_r10 = sigregs->regs.gprs[10];
217    tst->arch.vex.guest_r11 = sigregs->regs.gprs[11];
218    tst->arch.vex.guest_r12 = sigregs->regs.gprs[12];
219    tst->arch.vex.guest_r13 = sigregs->regs.gprs[13];
220    tst->arch.vex.guest_r14 = sigregs->regs.gprs[14];
221    tst->arch.vex.guest_r15 = sigregs->regs.gprs[15];
222 
223    tst->arch.vex.guest_a0  = sigregs->regs.acrs[0];
224    tst->arch.vex.guest_a1  = sigregs->regs.acrs[1];
225    tst->arch.vex.guest_a2  = sigregs->regs.acrs[2];
226    tst->arch.vex.guest_a3  = sigregs->regs.acrs[3];
227    tst->arch.vex.guest_a4  = sigregs->regs.acrs[4];
228    tst->arch.vex.guest_a5  = sigregs->regs.acrs[5];
229    tst->arch.vex.guest_a6  = sigregs->regs.acrs[6];
230    tst->arch.vex.guest_a7  = sigregs->regs.acrs[7];
231    tst->arch.vex.guest_a8  = sigregs->regs.acrs[8];
232    tst->arch.vex.guest_a9  = sigregs->regs.acrs[9];
233    tst->arch.vex.guest_a10 = sigregs->regs.acrs[10];
234    tst->arch.vex.guest_a11 = sigregs->regs.acrs[11];
235    tst->arch.vex.guest_a12 = sigregs->regs.acrs[12];
236    tst->arch.vex.guest_a13 = sigregs->regs.acrs[13];
237    tst->arch.vex.guest_a14 = sigregs->regs.acrs[14];
238    tst->arch.vex.guest_a15 = sigregs->regs.acrs[15];
239 
240    tst->arch.vex.guest_f0  = sigregs->fpregs.fprs[0];
241    tst->arch.vex.guest_f1  = sigregs->fpregs.fprs[1];
242    tst->arch.vex.guest_f2  = sigregs->fpregs.fprs[2];
243    tst->arch.vex.guest_f3  = sigregs->fpregs.fprs[3];
244    tst->arch.vex.guest_f4  = sigregs->fpregs.fprs[4];
245    tst->arch.vex.guest_f5  = sigregs->fpregs.fprs[5];
246    tst->arch.vex.guest_f6  = sigregs->fpregs.fprs[6];
247    tst->arch.vex.guest_f7  = sigregs->fpregs.fprs[7];
248    tst->arch.vex.guest_f8  = sigregs->fpregs.fprs[8];
249    tst->arch.vex.guest_f9  = sigregs->fpregs.fprs[9];
250    tst->arch.vex.guest_f10 = sigregs->fpregs.fprs[10];
251    tst->arch.vex.guest_f11 = sigregs->fpregs.fprs[11];
252    tst->arch.vex.guest_f12 = sigregs->fpregs.fprs[12];
253    tst->arch.vex.guest_f13 = sigregs->fpregs.fprs[13];
254    tst->arch.vex.guest_f14 = sigregs->fpregs.fprs[14];
255    tst->arch.vex.guest_f15 = sigregs->fpregs.fprs[15];
256    tst->arch.vex.guest_fpc = sigregs->fpregs.fpc;
257 
258    tst->arch.vex.guest_IA = sigregs->regs.psw.addr;
259 }
260 
261 /* Extend the stack segment downwards if needed so as to ensure the
262    new signal frames are mapped to something.  Return a Bool
263    indicating whether or not the operation was successful.
264 */
extend(ThreadState * tst,Addr addr,SizeT size)265 static Bool extend ( ThreadState *tst, Addr addr, SizeT size )
266 {
267    ThreadId        tid = tst->tid;
268    NSegment const* stackseg = NULL;
269 
270    if (VG_(extend_stack)(addr, tst->client_stack_szB)) {
271       stackseg = VG_(am_find_nsegment)(addr);
272       if (0 && stackseg)
273 	 VG_(printf)("frame=%#lx seg=%#lx-%#lx\n",
274 		     addr, stackseg->start, stackseg->end);
275    }
276 
277    if (stackseg == NULL || !stackseg->hasR || !stackseg->hasW) {
278       VG_(message)(
279          Vg_UserMsg,
280          "Can't extend stack to %#lx during signal delivery for thread %d:\n",
281          addr, tid);
282       if (stackseg == NULL)
283          VG_(message)(Vg_UserMsg, "  no stack segment\n");
284       else
285          VG_(message)(Vg_UserMsg, "  too small or bad protection modes\n");
286 
287       /* set SIGSEGV to default handler */
288       VG_(set_default_handler)(VKI_SIGSEGV);
289       VG_(synth_fault_mapping)(tid, addr);
290 
291       /* The whole process should be about to die, since the default
292 	 action of SIGSEGV to kill the whole process. */
293       return False;
294    }
295 
296    /* For tracking memory events, indicate the entire frame has been
297       allocated. */
298    VG_TRACK( new_mem_stack_signal, addr - VG_STACK_REDZONE_SZB,
299              size + VG_STACK_REDZONE_SZB, tid );
300 
301    return True;
302 }
303 
304 
305 /* Build the Valgrind-specific part of a signal frame. */
306 
build_vg_sigframe(struct vg_sigframe * frame,ThreadState * tst,UInt flags,Int sigNo)307 static void build_vg_sigframe(struct vg_sigframe *frame,
308 			      ThreadState *tst,
309 			      UInt flags,
310 			      Int sigNo)
311 {
312    frame->sigNo_private = sigNo;
313    frame->magicPI       = 0x31415927;
314    frame->vex_shadow1   = tst->arch.vex_shadow1;
315    frame->vex_shadow2   = tst->arch.vex_shadow2;
316    /* HACK ALERT */
317    frame->vex           = tst->arch.vex;
318    /* end HACK ALERT */
319    frame->mask          = tst->sig_mask;
320    frame->handlerflags  = flags;
321    frame->magicE        = 0x27182818;
322 }
323 
324 
build_sigframe(ThreadState * tst,Addr sp_top_of_frame,const vki_siginfo_t * siginfo,const struct vki_ucontext * siguc,UInt flags,const vki_sigset_t * mask,void * restorer)325 static Addr build_sigframe(ThreadState *tst,
326 			   Addr sp_top_of_frame,
327 			   const vki_siginfo_t *siginfo,
328 			   const struct vki_ucontext *siguc,
329 			   UInt flags,
330 			   const vki_sigset_t *mask,
331 			   void *restorer)
332 {
333    struct sigframe *frame;
334    Addr sp = sp_top_of_frame;
335 
336    vg_assert((flags & VKI_SA_SIGINFO) == 0);
337    vg_assert((sizeof(*frame) & 7) == 0);
338    vg_assert((sp & 7) == 0);
339 
340    sp -= sizeof(*frame);
341    frame = (struct sigframe *)sp;
342 
343    if (!extend(tst, sp, sizeof(*frame)))
344       return sp_top_of_frame;
345 
346    /* retcode, sigNo, sc, sregs fields are to be written */
347    VG_TRACK( pre_mem_write, Vg_CoreSignal, tst->tid, "signal handler frame",
348 	     sp, offsetof(struct sigframe, vg) );
349 
350    save_sigregs(tst, &frame->sregs);
351 
352    frame->sigNo = siginfo->si_signo;
353    frame->sc.sregs = &frame->sregs;
354    VG_(memcpy)(frame->sc.oldmask, mask->sig, sizeof(frame->sc.oldmask));
355 
356    if (flags & VKI_SA_RESTORER) {
357       SET_SIGNAL_GPR(tst, 14, restorer);
358    } else {
359       frame->retcode[0] = 0x0a;
360       frame->retcode[1] = __NR_sigreturn;
361       /* This normally should be &frame->recode. but since there
362          might be problems with non-exec stack and we must discard
363          the translation for the on-stack sigreturn we just use the
364          trampoline like x86,ppc. We still fill in the retcode, lets
365          just hope that nobody actually jumps here */
366       SET_SIGNAL_GPR(tst, 14, (Addr)&VG_(s390x_linux_SUBST_FOR_sigreturn));
367    }
368 
369    SET_SIGNAL_GPR(tst, 2, siginfo->si_signo);
370    SET_SIGNAL_GPR(tst, 3, &frame->sc);
371    /* fixs390: we dont fill in trapno and prot_addr in r4 and r5*/
372 
373    /* Set up backchain. */
374    *((Addr *) sp) = sp_top_of_frame;
375 
376    VG_TRACK( post_mem_write, Vg_CoreSignal, tst->tid,
377              sp, offsetof(struct sigframe, vg) );
378 
379    build_vg_sigframe(&frame->vg, tst, flags, siginfo->si_signo);
380 
381    return sp;
382 }
383 
build_rt_sigframe(ThreadState * tst,Addr sp_top_of_frame,const vki_siginfo_t * siginfo,const struct vki_ucontext * siguc,UInt flags,const vki_sigset_t * mask,void * restorer)384 static Addr build_rt_sigframe(ThreadState *tst,
385 			      Addr sp_top_of_frame,
386 			      const vki_siginfo_t *siginfo,
387 			      const struct vki_ucontext *siguc,
388 			      UInt flags,
389 			      const vki_sigset_t *mask,
390 			      void *restorer)
391 {
392    struct rt_sigframe *frame;
393    Addr sp = sp_top_of_frame;
394    Int sigNo = siginfo->si_signo;
395 
396    vg_assert((flags & VKI_SA_SIGINFO) != 0);
397    vg_assert((sizeof(*frame) & 7) == 0);
398    vg_assert((sp & 7) == 0);
399 
400    sp -= sizeof(*frame);
401    frame = (struct rt_sigframe *)sp;
402 
403    if (!extend(tst, sp, sizeof(*frame)))
404       return sp_top_of_frame;
405 
406    /* retcode, sigNo, sc, sregs fields are to be written */
407    VG_TRACK( pre_mem_write, Vg_CoreSignal, tst->tid, "signal handler frame",
408 	     sp, offsetof(struct rt_sigframe, vg) );
409 
410    save_sigregs(tst, &frame->uc.uc_mcontext);
411 
412    if (flags & VKI_SA_RESTORER) {
413       frame->retcode[0] = 0;
414       frame->retcode[1] = 0;
415       SET_SIGNAL_GPR(tst, 14, restorer);
416    } else {
417       frame->retcode[0] = 0x0a;
418       frame->retcode[1] = __NR_rt_sigreturn;
419       /* This normally should be &frame->recode. but since there
420          might be problems with non-exec stack and we must discard
421          the translation for the on-stack sigreturn we just use the
422          trampoline like x86,ppc. We still fill in the retcode, lets
423          just hope that nobody actually jumps here */
424       SET_SIGNAL_GPR(tst, 14, (Addr)&VG_(s390x_linux_SUBST_FOR_rt_sigreturn));
425    }
426 
427    VG_(memcpy)(&frame->info, siginfo, sizeof(vki_siginfo_t));
428    frame->uc.uc_flags = 0;
429    frame->uc.uc_link = 0;
430    frame->uc.uc_sigmask = *mask;
431    frame->uc.uc_stack = tst->altstack;
432 
433    SET_SIGNAL_GPR(tst, 2, siginfo->si_signo);
434    SET_SIGNAL_GPR(tst, 3, &frame->info);
435    SET_SIGNAL_GPR(tst, 4, &frame->uc);
436 
437    /* Set up backchain. */
438    *((Addr *) sp) = sp_top_of_frame;
439 
440    VG_TRACK( post_mem_write, Vg_CoreSignal, tst->tid,
441              sp, offsetof(struct rt_sigframe, vg) );
442 
443    build_vg_sigframe(&frame->vg, tst, flags, sigNo);
444    return sp;
445 }
446 
447 /* EXPORTED */
VG_(sigframe_create)448 void VG_(sigframe_create)( ThreadId tid,
449 			   Addr sp_top_of_frame,
450 			   const vki_siginfo_t *siginfo,
451 			   const struct vki_ucontext *siguc,
452 			   void *handler,
453 			   UInt flags,
454 			   const vki_sigset_t *mask,
455 			   void *restorer )
456 {
457    Addr sp;
458    ThreadState* tst = VG_(get_ThreadState)(tid);
459 
460    if (flags & VKI_SA_SIGINFO)
461       sp = build_rt_sigframe(tst, sp_top_of_frame, siginfo, siguc,
462 			     flags, mask, restorer);
463    else
464       sp = build_sigframe(tst, sp_top_of_frame, siginfo, siguc,
465 			  flags, mask, restorer);
466 
467    /* Set the thread so it will next run the handler. */
468    VG_(set_SP)(tid, sp);
469    VG_TRACK( post_reg_write, Vg_CoreSignal, tid, VG_O_STACK_PTR, sizeof(Addr));
470 
471    tst->arch.vex.guest_IA = (Addr) handler;
472    /* We might have interrupted a repeating instruction that uses the guest
473       counter. Since our VEX requires that a new instruction will see a
474       guest counter == 0, we have to set it here. The old value will be
475       restored by restore_vg_sigframe. */
476    tst->arch.vex.guest_counter = 0;
477    /* This thread needs to be marked runnable, but we leave that the
478       caller to do. */
479 }
480 
481 
482 /*------------------------------------------------------------*/
483 /*--- Destroying signal frames                             ---*/
484 /*------------------------------------------------------------*/
485 
486 /* Return False and don't do anything, just set the client to take a
487    segfault, if it looks like the frame is corrupted. */
488 static
restore_vg_sigframe(ThreadState * tst,struct vg_sigframe * frame,Int * sigNo)489 Bool restore_vg_sigframe ( ThreadState *tst,
490                            struct vg_sigframe *frame, Int *sigNo )
491 {
492    if (frame->magicPI != 0x31415927 ||
493        frame->magicE  != 0x27182818) {
494       VG_(message)(Vg_UserMsg, "Thread %d return signal frame "
495 			       "corrupted.  Killing process.\n",
496 		   tst->tid);
497       VG_(set_default_handler)(VKI_SIGSEGV);
498       VG_(synth_fault)(tst->tid);
499       *sigNo = VKI_SIGSEGV;
500       return False;
501    }
502    tst->sig_mask         = frame->mask;
503    tst->tmp_sig_mask     = frame->mask;
504    tst->arch.vex_shadow1 = frame->vex_shadow1;
505    tst->arch.vex_shadow2 = frame->vex_shadow2;
506    /* HACK ALERT */
507    tst->arch.vex         = frame->vex;
508    /* end HACK ALERT */
509    *sigNo                = frame->sigNo_private;
510    return True;
511 }
512 
513 static
restore_sigframe(ThreadState * tst,struct sigframe * frame,Int * sigNo)514 SizeT restore_sigframe ( ThreadState *tst,
515                          struct sigframe *frame, Int *sigNo )
516 {
517    if (restore_vg_sigframe(tst, &frame->vg, sigNo))
518       restore_sigregs(tst, frame->sc.sregs);
519 
520    return sizeof(*frame);
521 }
522 
523 static
restore_rt_sigframe(ThreadState * tst,struct rt_sigframe * frame,Int * sigNo)524 SizeT restore_rt_sigframe ( ThreadState *tst,
525                             struct rt_sigframe *frame, Int *sigNo )
526 {
527    if (restore_vg_sigframe(tst, &frame->vg, sigNo)) {
528       restore_sigregs(tst, &frame->uc.uc_mcontext);
529    }
530    return sizeof(*frame);
531 }
532 
533 
534 /* EXPORTED */
VG_(sigframe_destroy)535 void VG_(sigframe_destroy)( ThreadId tid, Bool isRT )
536 {
537    Addr          sp;
538    ThreadState*  tst;
539    SizeT         size;
540    Int            sigNo;
541 
542    tst = VG_(get_ThreadState)(tid);
543 
544    /* Correctly reestablish the frame base address. */
545    sp   = tst->arch.vex.guest_SP;
546 
547    if (!isRT)
548       size = restore_sigframe(tst, (struct sigframe *)sp, &sigNo);
549    else
550       size = restore_rt_sigframe(tst, (struct rt_sigframe *)sp, &sigNo);
551 
552    /* same as for creation: we must announce the full memory (including
553       alignment), otherwise massif might fail on longjmp */
554    VG_TRACK( die_mem_stack_signal, sp - VG_STACK_REDZONE_SZB,
555              size + VG_STACK_REDZONE_SZB );
556 
557    if (VG_(clo_trace_signals))
558       VG_(message)(
559          Vg_DebugMsg,
560          "VG_(sigframe_destroy) (thread %d): isRT=%d valid magic; IP=%#llx\n",
561          tid, isRT, tst->arch.vex.guest_IA);
562 
563    /* tell the tools */
564    VG_TRACK( post_deliver_signal, tid, sigNo );
565 }
566 
567 #endif /* VGA_s390x */
568 
569 /*--------------------------------------------------------------------*/
570 /*--- end                                   sigframe-s390x-linux.c ---*/
571 /*--------------------------------------------------------------------*/
572