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-2011 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 */ 89struct 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 119struct 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 130struct 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 */ 145static 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 204static 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*/ 265static 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 307static 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 325static 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 384static 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 */ 448void 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. */ 488static 489Bool 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 513static 514SizeT 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 523static 524SizeT 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 */ 535void 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