2 /*--------------------------------------------------------------------*/
3 /*--- Create/destroy signal delivery frames. ---*/
4 /*--- sigframe-s390x-linux.c ---*/
5 /*--------------------------------------------------------------------*/
8 This file is part of Valgrind, a dynamic binary instrumentation
11 Copyright IBM Corp. 2010-2013
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.
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.
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
28 The GNU General Public License is contained in the file COPYING.
31 /* Contributed by Christian Borntraeger */
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"
49 #if defined(VGA_s390x)
51 /* This module creates and removes signal frames for signal deliveries
54 Note, this file contains kernel-specific knowledge in the form of
55 'struct sigframe' and 'struct rt_sigframe'.
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
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), \
71 /*------------------------------------------------------------*/
72 /*--- Signal frame layouts ---*/
73 /*------------------------------------------------------------*/
75 // A structure in which to save the application's registers
76 // during the execution of signal handlers.
78 // Linux has 2 signal frame structures: one for normal signal
79 // deliveries, and one for SA_SIGINFO deliveries (also known as RT
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.
88 /* Valgrind-specific parts of the signal frame */
91 /* Sanity check word. */
94 UInt handlerflags
; /* flags for signal handler */
97 /* Safely-saved version of sigNo, as described above. */
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
;
106 VexGuestS390XState vex
;
109 /* saved signal mask to be restored when handler returns */
112 /* Sanity check word. Is the highest-addressed word; do not
117 #define S390_SYSCALL_SIZE 2
121 UChar callee_used_stack
[__VKI_SIGNAL_FRAMESIZE
];
122 struct vki_sigcontext sc
;
125 UChar retcode
[S390_SYSCALL_SIZE
];
127 struct vg_sigframe vg
;
132 UChar callee_used_stack
[__VKI_SIGNAL_FRAMESIZE
];
133 UChar retcode
[S390_SYSCALL_SIZE
];
134 struct vki_siginfo info
;
135 struct vki_ucontext uc
;
137 struct vg_sigframe vg
;
140 /*------------------------------------------------------------*/
141 /*--- Creating signal frames ---*/
142 /*------------------------------------------------------------*/
144 /* Saves all user-controlled register into a _vki_sigregs structure */
145 static void save_sigregs(ThreadState
*tst
, _vki_sigregs
*sigregs
)
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
;
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
;
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
;
199 sigregs
->regs
.psw
.addr
= tst
->arch
.vex
.guest_IA
;
200 /* save a sane dummy mask */
201 sigregs
->regs
.psw
.mask
= 0x0705000180000000UL
;
204 static void restore_sigregs(ThreadState
*tst
, _vki_sigregs
*sigregs
)
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];
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];
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
;
258 tst
->arch
.vex
.guest_IA
= sigregs
->regs
.psw
.addr
;
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.
265 static Bool
extend ( ThreadState
*tst
, Addr addr
, SizeT size
)
267 ThreadId tid
= tst
->tid
;
268 NSegment
const* stackseg
= NULL
;
270 if (VG_(extend_stack
)(addr
, tst
->client_stack_szB
)) {
271 stackseg
= VG_(am_find_nsegment
)(addr
);
273 VG_(printf
)("frame=%#lx seg=%#lx-%#lx\n",
274 addr
, stackseg
->start
, stackseg
->end
);
277 if (stackseg
== NULL
|| !stackseg
->hasR
|| !stackseg
->hasW
) {
280 "Can't extend stack to %#lx during signal delivery for thread %d:\n",
282 if (stackseg
== NULL
)
283 VG_(message
)(Vg_UserMsg
, " no stack segment\n");
285 VG_(message
)(Vg_UserMsg
, " too small or bad protection modes\n");
287 /* set SIGSEGV to default handler */
288 VG_(set_default_handler
)(VKI_SIGSEGV
);
289 VG_(synth_fault_mapping
)(tid
, addr
);
291 /* The whole process should be about to die, since the default
292 action of SIGSEGV to kill the whole process. */
296 /* For tracking memory events, indicate the entire frame has been
298 VG_TRACK( new_mem_stack_signal
, addr
- VG_STACK_REDZONE_SZB
,
299 size
+ VG_STACK_REDZONE_SZB
, tid
);
305 /* Build the Valgrind-specific part of a signal frame. */
307 static void build_vg_sigframe(struct vg_sigframe
*frame
,
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
;
317 frame
->vex
= tst
->arch
.vex
;
319 frame
->mask
= tst
->sig_mask
;
320 frame
->handlerflags
= flags
;
321 frame
->magicE
= 0x27182818;
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
,
330 const vki_sigset_t
*mask
,
333 struct sigframe
*frame
;
334 Addr sp
= sp_top_of_frame
;
336 vg_assert((flags
& VKI_SA_SIGINFO
) == 0);
337 vg_assert((sizeof(*frame
) & 7) == 0);
338 vg_assert((sp
& 7) == 0);
340 sp
-= sizeof(*frame
);
341 frame
= (struct sigframe
*)sp
;
343 if (!extend(tst
, sp
, sizeof(*frame
)))
344 return sp_top_of_frame
;
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
) );
350 save_sigregs(tst
, &frame
->sregs
);
352 frame
->sigNo
= siginfo
->si_signo
;
353 frame
->sc
.sregs
= &frame
->sregs
;
354 VG_(memcpy
)(frame
->sc
.oldmask
, mask
->sig
, sizeof(frame
->sc
.oldmask
));
356 if (flags
& VKI_SA_RESTORER
) {
357 SET_SIGNAL_GPR(tst
, 14, restorer
);
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
));
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*/
373 /* Set up backchain. */
374 *((Addr
*) sp
) = sp_top_of_frame
;
376 VG_TRACK( post_mem_write
, Vg_CoreSignal
, tst
->tid
,
377 sp
, offsetof(struct sigframe
, vg
) );
379 build_vg_sigframe(&frame
->vg
, tst
, flags
, siginfo
->si_signo
);
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
,
389 const vki_sigset_t
*mask
,
392 struct rt_sigframe
*frame
;
393 Addr sp
= sp_top_of_frame
;
394 Int sigNo
= siginfo
->si_signo
;
396 vg_assert((flags
& VKI_SA_SIGINFO
) != 0);
397 vg_assert((sizeof(*frame
) & 7) == 0);
398 vg_assert((sp
& 7) == 0);
400 sp
-= sizeof(*frame
);
401 frame
= (struct rt_sigframe
*)sp
;
403 if (!extend(tst
, sp
, sizeof(*frame
)))
404 return sp_top_of_frame
;
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
) );
410 save_sigregs(tst
, &frame
->uc
.uc_mcontext
);
412 if (flags
& VKI_SA_RESTORER
) {
413 frame
->retcode
[0] = 0;
414 frame
->retcode
[1] = 0;
415 SET_SIGNAL_GPR(tst
, 14, restorer
);
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
));
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
;
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
);
437 /* Set up backchain. */
438 *((Addr
*) sp
) = sp_top_of_frame
;
440 VG_TRACK( post_mem_write
, Vg_CoreSignal
, tst
->tid
,
441 sp
, offsetof(struct rt_sigframe
, vg
) );
443 build_vg_sigframe(&frame
->vg
, tst
, flags
, sigNo
);
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
,
454 const vki_sigset_t
*mask
,
458 ThreadState
* tst
= VG_(get_ThreadState
)(tid
);
460 if (flags
& VKI_SA_SIGINFO
)
461 sp
= build_rt_sigframe(tst
, sp_top_of_frame
, siginfo
, siguc
,
462 flags
, mask
, restorer
);
464 sp
= build_sigframe(tst
, sp_top_of_frame
, siginfo
, siguc
,
465 flags
, mask
, restorer
);
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
));
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
482 /*------------------------------------------------------------*/
483 /*--- Destroying signal frames ---*/
484 /*------------------------------------------------------------*/
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. */
489 Bool
restore_vg_sigframe ( ThreadState
*tst
,
490 struct vg_sigframe
*frame
, Int
*sigNo
)
492 if (frame
->magicPI
!= 0x31415927 ||
493 frame
->magicE
!= 0x27182818) {
494 VG_(message
)(Vg_UserMsg
, "Thread %d return signal frame "
495 "corrupted. Killing process.\n",
497 VG_(set_default_handler
)(VKI_SIGSEGV
);
498 VG_(synth_fault
)(tst
->tid
);
499 *sigNo
= VKI_SIGSEGV
;
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
;
507 tst
->arch
.vex
= frame
->vex
;
509 *sigNo
= frame
->sigNo_private
;
514 SizeT
restore_sigframe ( ThreadState
*tst
,
515 struct sigframe
*frame
, Int
*sigNo
)
517 if (restore_vg_sigframe(tst
, &frame
->vg
, sigNo
))
518 restore_sigregs(tst
, frame
->sc
.sregs
);
520 return sizeof(*frame
);
524 SizeT
restore_rt_sigframe ( ThreadState
*tst
,
525 struct rt_sigframe
*frame
, Int
*sigNo
)
527 if (restore_vg_sigframe(tst
, &frame
->vg
, sigNo
)) {
528 restore_sigregs(tst
, &frame
->uc
.uc_mcontext
);
530 return sizeof(*frame
);
535 void VG_(sigframe_destroy
)( ThreadId tid
, Bool isRT
)
542 tst
= VG_(get_ThreadState
)(tid
);
544 /* Correctly reestablish the frame base address. */
545 sp
= tst
->arch
.vex
.guest_SP
;
548 size
= restore_sigframe(tst
, (struct sigframe
*)sp
, &sigNo
);
550 size
= restore_rt_sigframe(tst
, (struct rt_sigframe
*)sp
, &sigNo
);
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
);
557 if (VG_(clo_trace_signals
))
560 "VG_(sigframe_destroy) (thread %d): isRT=%d valid magic; IP=%#llx\n",
561 tid
, isRT
, tst
->arch
.vex
.guest_IA
);
564 VG_TRACK( post_deliver_signal
, tid
, sigNo
);
567 #endif /* VGA_s390x */
569 /*--------------------------------------------------------------------*/
570 /*--- end sigframe-s390x-linux.c ---*/
571 /*--------------------------------------------------------------------*/