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_threadstate.h"
37 #include "pub_core_aspacemgr.h"
38 #include "pub_core_libcbase.h"
39 #include "pub_core_libcassert.h"
40 #include "pub_core_libcprint.h"
41 #include "pub_core_machine.h"
42 #include "pub_core_options.h"
43 #include "pub_core_sigframe.h"
44 #include "pub_core_signals.h"
45 #include "pub_core_tooliface.h"
46 #include "pub_core_trampoline.h"
47 #include "priv_sigframe.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
262 /* Build the Valgrind-specific part of a signal frame. */
263
build_vg_sigframe(struct vg_sigframe * frame,ThreadState * tst,UInt flags,Int sigNo)264 static void build_vg_sigframe(struct vg_sigframe *frame,
265 ThreadState *tst,
266 UInt flags,
267 Int sigNo)
268 {
269 frame->sigNo_private = sigNo;
270 frame->magicPI = 0x31415927;
271 frame->vex_shadow1 = tst->arch.vex_shadow1;
272 frame->vex_shadow2 = tst->arch.vex_shadow2;
273 /* HACK ALERT */
274 frame->vex = tst->arch.vex;
275 /* end HACK ALERT */
276 frame->mask = tst->sig_mask;
277 frame->handlerflags = flags;
278 frame->magicE = 0x27182818;
279 }
280
281
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)282 static Addr build_sigframe(ThreadState *tst,
283 Addr sp_top_of_frame,
284 const vki_siginfo_t *siginfo,
285 const struct vki_ucontext *siguc,
286 UInt flags,
287 const vki_sigset_t *mask,
288 void *restorer)
289 {
290 struct sigframe *frame;
291 Addr sp = sp_top_of_frame;
292
293 vg_assert((flags & VKI_SA_SIGINFO) == 0);
294 vg_assert((sizeof(*frame) & 7) == 0);
295 vg_assert((sp & 7) == 0);
296
297 sp -= sizeof(*frame);
298 frame = (struct sigframe *)sp;
299
300 if (! ML_(sf_maybe_extend_stack)(tst, sp, sizeof(*frame), flags))
301 return sp_top_of_frame;
302
303 /* retcode, sigNo, sc, sregs fields are to be written */
304 VG_TRACK( pre_mem_write, Vg_CoreSignal, tst->tid, "signal handler frame",
305 sp, offsetof(struct sigframe, vg) );
306
307 save_sigregs(tst, &frame->sregs);
308
309 frame->sigNo = siginfo->si_signo;
310 frame->sc.sregs = &frame->sregs;
311 VG_(memcpy)(frame->sc.oldmask, mask->sig, sizeof(frame->sc.oldmask));
312
313 if (flags & VKI_SA_RESTORER) {
314 SET_SIGNAL_GPR(tst, 14, restorer);
315 } else {
316 frame->retcode[0] = 0x0a;
317 frame->retcode[1] = __NR_sigreturn;
318 /* This normally should be &frame->recode. but since there
319 might be problems with non-exec stack and we must discard
320 the translation for the on-stack sigreturn we just use the
321 trampoline like x86,ppc. We still fill in the retcode, lets
322 just hope that nobody actually jumps here */
323 SET_SIGNAL_GPR(tst, 14, (Addr)&VG_(s390x_linux_SUBST_FOR_sigreturn));
324 }
325
326 SET_SIGNAL_GPR(tst, 2, siginfo->si_signo);
327 SET_SIGNAL_GPR(tst, 3, &frame->sc);
328 /* fixs390: we dont fill in trapno and prot_addr in r4 and r5*/
329
330 /* Set up backchain. */
331 *((Addr *) sp) = sp_top_of_frame;
332
333 VG_TRACK( post_mem_write, Vg_CoreSignal, tst->tid,
334 sp, offsetof(struct sigframe, vg) );
335
336 build_vg_sigframe(&frame->vg, tst, flags, siginfo->si_signo);
337
338 return sp;
339 }
340
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)341 static Addr build_rt_sigframe(ThreadState *tst,
342 Addr sp_top_of_frame,
343 const vki_siginfo_t *siginfo,
344 const struct vki_ucontext *siguc,
345 UInt flags,
346 const vki_sigset_t *mask,
347 void *restorer)
348 {
349 struct rt_sigframe *frame;
350 Addr sp = sp_top_of_frame;
351 Int sigNo = siginfo->si_signo;
352
353 vg_assert((flags & VKI_SA_SIGINFO) != 0);
354 vg_assert((sizeof(*frame) & 7) == 0);
355 vg_assert((sp & 7) == 0);
356
357 sp -= sizeof(*frame);
358 frame = (struct rt_sigframe *)sp;
359
360 if (! ML_(sf_maybe_extend_stack)(tst, sp, sizeof(*frame), flags))
361 return sp_top_of_frame;
362
363 /* retcode, sigNo, sc, sregs fields are to be written */
364 VG_TRACK( pre_mem_write, Vg_CoreSignal, tst->tid, "signal handler frame",
365 sp, offsetof(struct rt_sigframe, vg) );
366
367 save_sigregs(tst, &frame->uc.uc_mcontext);
368
369 if (flags & VKI_SA_RESTORER) {
370 frame->retcode[0] = 0;
371 frame->retcode[1] = 0;
372 SET_SIGNAL_GPR(tst, 14, restorer);
373 } else {
374 frame->retcode[0] = 0x0a;
375 frame->retcode[1] = __NR_rt_sigreturn;
376 /* This normally should be &frame->recode. but since there
377 might be problems with non-exec stack and we must discard
378 the translation for the on-stack sigreturn we just use the
379 trampoline like x86,ppc. We still fill in the retcode, lets
380 just hope that nobody actually jumps here */
381 SET_SIGNAL_GPR(tst, 14, (Addr)&VG_(s390x_linux_SUBST_FOR_rt_sigreturn));
382 }
383
384 VG_(memcpy)(&frame->info, siginfo, sizeof(vki_siginfo_t));
385 frame->uc.uc_flags = 0;
386 frame->uc.uc_link = 0;
387 frame->uc.uc_sigmask = *mask;
388 frame->uc.uc_stack = tst->altstack;
389
390 SET_SIGNAL_GPR(tst, 2, siginfo->si_signo);
391 SET_SIGNAL_GPR(tst, 3, &frame->info);
392 SET_SIGNAL_GPR(tst, 4, &frame->uc);
393
394 /* Set up backchain. */
395 *((Addr *) sp) = sp_top_of_frame;
396
397 VG_TRACK( post_mem_write, Vg_CoreSignal, tst->tid,
398 sp, offsetof(struct rt_sigframe, vg) );
399
400 build_vg_sigframe(&frame->vg, tst, flags, sigNo);
401 return sp;
402 }
403
404 /* EXPORTED */
VG_(sigframe_create)405 void VG_(sigframe_create)( ThreadId tid,
406 Addr sp_top_of_frame,
407 const vki_siginfo_t *siginfo,
408 const struct vki_ucontext *siguc,
409 void *handler,
410 UInt flags,
411 const vki_sigset_t *mask,
412 void *restorer )
413 {
414 Addr sp;
415 ThreadState* tst = VG_(get_ThreadState)(tid);
416
417 if (flags & VKI_SA_SIGINFO)
418 sp = build_rt_sigframe(tst, sp_top_of_frame, siginfo, siguc,
419 flags, mask, restorer);
420 else
421 sp = build_sigframe(tst, sp_top_of_frame, siginfo, siguc,
422 flags, mask, restorer);
423
424 /* Set the thread so it will next run the handler. */
425 VG_(set_SP)(tid, sp);
426 VG_TRACK( post_reg_write, Vg_CoreSignal, tid, VG_O_STACK_PTR, sizeof(Addr));
427
428 tst->arch.vex.guest_IA = (Addr) handler;
429 /* We might have interrupted a repeating instruction that uses the guest
430 counter. Since our VEX requires that a new instruction will see a
431 guest counter == 0, we have to set it here. The old value will be
432 restored by restore_vg_sigframe. */
433 tst->arch.vex.guest_counter = 0;
434 /* This thread needs to be marked runnable, but we leave that the
435 caller to do. */
436 }
437
438
439 /*------------------------------------------------------------*/
440 /*--- Destroying signal frames ---*/
441 /*------------------------------------------------------------*/
442
443 /* Return False and don't do anything, just set the client to take a
444 segfault, if it looks like the frame is corrupted. */
445 static
restore_vg_sigframe(ThreadState * tst,struct vg_sigframe * frame,Int * sigNo)446 Bool restore_vg_sigframe ( ThreadState *tst,
447 struct vg_sigframe *frame, Int *sigNo )
448 {
449 if (frame->magicPI != 0x31415927 ||
450 frame->magicE != 0x27182818) {
451 VG_(message)(Vg_UserMsg, "Thread %d return signal frame "
452 "corrupted. Killing process.\n",
453 tst->tid);
454 VG_(set_default_handler)(VKI_SIGSEGV);
455 VG_(synth_fault)(tst->tid);
456 *sigNo = VKI_SIGSEGV;
457 return False;
458 }
459 tst->sig_mask = frame->mask;
460 tst->tmp_sig_mask = frame->mask;
461 tst->arch.vex_shadow1 = frame->vex_shadow1;
462 tst->arch.vex_shadow2 = frame->vex_shadow2;
463 /* HACK ALERT */
464 tst->arch.vex = frame->vex;
465 /* end HACK ALERT */
466 *sigNo = frame->sigNo_private;
467 return True;
468 }
469
470 static
restore_sigframe(ThreadState * tst,struct sigframe * frame,Int * sigNo)471 SizeT restore_sigframe ( ThreadState *tst,
472 struct sigframe *frame, Int *sigNo )
473 {
474 if (restore_vg_sigframe(tst, &frame->vg, sigNo))
475 restore_sigregs(tst, frame->sc.sregs);
476
477 return sizeof(*frame);
478 }
479
480 static
restore_rt_sigframe(ThreadState * tst,struct rt_sigframe * frame,Int * sigNo)481 SizeT restore_rt_sigframe ( ThreadState *tst,
482 struct rt_sigframe *frame, Int *sigNo )
483 {
484 if (restore_vg_sigframe(tst, &frame->vg, sigNo)) {
485 restore_sigregs(tst, &frame->uc.uc_mcontext);
486 }
487 return sizeof(*frame);
488 }
489
490
491 /* EXPORTED */
VG_(sigframe_destroy)492 void VG_(sigframe_destroy)( ThreadId tid, Bool isRT )
493 {
494 Addr sp;
495 ThreadState* tst;
496 SizeT size;
497 Int sigNo;
498
499 tst = VG_(get_ThreadState)(tid);
500
501 /* Correctly reestablish the frame base address. */
502 sp = tst->arch.vex.guest_SP;
503
504 if (!isRT)
505 size = restore_sigframe(tst, (struct sigframe *)sp, &sigNo);
506 else
507 size = restore_rt_sigframe(tst, (struct rt_sigframe *)sp, &sigNo);
508
509 /* same as for creation: we must announce the full memory (including
510 alignment), otherwise massif might fail on longjmp */
511 VG_TRACK( die_mem_stack_signal, sp - VG_STACK_REDZONE_SZB,
512 size + VG_STACK_REDZONE_SZB );
513
514 if (VG_(clo_trace_signals))
515 VG_(message)(
516 Vg_DebugMsg,
517 "VG_(sigframe_destroy) (thread %d): isRT=%d valid magic; IP=%#llx\n",
518 tid, isRT, tst->arch.vex.guest_IA);
519
520 /* tell the tools */
521 VG_TRACK( post_deliver_signal, tid, sigNo );
522 }
523
524 #endif /* VGA_s390x */
525
526 /*--------------------------------------------------------------------*/
527 /*--- end sigframe-s390x-linux.c ---*/
528 /*--------------------------------------------------------------------*/
529