Fix const signedness issue in VG_(show_open_fds)
[valgrind.git] / coregrind / m_sigframe / sigframe-x86-linux.c
blob309bae2a780a2240e3cab301e2fb335ef3375491
2 /*--------------------------------------------------------------------*/
3 /*--- Create/destroy signal delivery frames. ---*/
4 /*--- sigframe-x86-linux.c ---*/
5 /*--------------------------------------------------------------------*/
7 /*
8 This file is part of Valgrind, a dynamic binary instrumentation
9 framework.
11 Copyright (C) 2000-2017 Nicholas Nethercote
12 njn@valgrind.org
14 This program is free software; you can redistribute it and/or
15 modify it under the terms of the GNU General Public License as
16 published by the Free Software Foundation; either version 2 of the
17 License, or (at your option) any later version.
19 This program is distributed in the hope that it will be useful, but
20 WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 General Public License for more details.
24 You should have received a copy of the GNU General Public License
25 along with this program; if not, see <http://www.gnu.org/licenses/>.
27 The GNU General Public License is contained in the file COPYING.
30 #if defined(VGP_x86_linux)
32 #include "pub_core_basics.h"
33 #include "pub_core_vki.h"
34 #include "pub_core_threadstate.h"
35 #include "pub_core_aspacemgr.h" /* find_segment */
36 #include "pub_core_libcbase.h"
37 #include "pub_core_libcassert.h"
38 #include "pub_core_libcprint.h"
39 #include "pub_core_machine.h"
40 #include "pub_core_options.h"
41 #include "pub_core_signals.h"
42 #include "pub_core_tooliface.h"
43 #include "pub_core_trampoline.h"
44 #include "pub_core_sigframe.h" /* self */
45 #include "priv_sigframe.h"
47 /* This module creates and removes signal frames for signal deliveries
48 on x86-linux.
50 Note, this file contains kernel-specific knowledge in the form of
51 'struct sigframe' and 'struct rt_sigframe'. How does that relate
52 to the vki kernel interface stuff?
54 Either a 'struct sigframe' or a 'struct rtsigframe' is pushed
55 onto the client's stack. This contains a subsidiary
56 vki_ucontext. That holds the vcpu's state across the signal,
57 so that the sighandler can mess with the vcpu state if it
58 really wants.
60 FIXME: sigcontexting is basically broken for the moment. When
61 delivering a signal, the integer registers and %eflags are
62 correctly written into the sigcontext, however the FP and SSE state
63 is not. When returning from a signal, only the integer registers
64 are restored from the sigcontext; the rest of the CPU state is
65 restored to what it was before the signal.
67 This will be fixed.
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
80 // signals).
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 */
89 struct vg_sigframe
91 /* Sanity check word. */
92 UInt magicPI;
94 UInt handlerflags; /* flags for signal handler */
97 /* Safely-saved version of sigNo, as described above. */
98 Int sigNo_private;
100 /* XXX This is wrong. Surely we should store the shadow values
101 into the shadow memory behind the actual values? */
102 VexGuestX86State vex_shadow1;
103 VexGuestX86State vex_shadow2;
105 /* HACK ALERT */
106 VexGuestX86State vex;
107 /* end HACK ALERT */
109 /* saved signal mask to be restored when handler returns */
110 vki_sigset_t mask;
112 /* Sanity check word. Is the highest-addressed word; do not
113 move!*/
114 UInt magicE;
117 struct sigframe
119 /* Sig handler's return address */
120 Addr retaddr;
121 Int sigNo;
123 struct vki_sigcontext sigContext;
124 struct _vki_fpstate fpstate;
126 struct vg_sigframe vg;
129 struct rt_sigframe
131 /* Sig handler's return address */
132 Addr retaddr;
133 Int sigNo;
135 /* ptr to siginfo_t. */
136 Addr psigInfo;
138 /* ptr to ucontext */
139 Addr puContext;
140 /* pointed to by psigInfo */
141 vki_siginfo_t sigInfo;
143 /* pointed to by puContext */
144 struct vki_ucontext uContext;
145 struct _vki_fpstate fpstate;
147 struct vg_sigframe vg;
151 //:: /*------------------------------------------------------------*/
152 //:: /*--- Signal operations ---*/
153 //:: /*------------------------------------------------------------*/
154 //::
155 //:: /*
156 //:: Great gobs of FP state conversion taken wholesale from
157 //:: linux/arch/i386/kernel/i387.c
158 //:: */
159 //::
160 //:: /*
161 //:: * FXSR floating point environment conversions.
162 //:: */
163 //:: #define X86_FXSR_MAGIC 0x0000
164 //::
165 //:: /*
166 //:: * FPU tag word conversions.
167 //:: */
168 //::
169 //:: static inline unsigned short twd_i387_to_fxsr( unsigned short twd )
170 //:: {
171 //:: unsigned int tmp; /* to avoid 16 bit prefixes in the code */
172 //::
173 //:: /* Transform each pair of bits into 01 (valid) or 00 (empty) */
174 //:: tmp = ~twd;
175 //:: tmp = (tmp | (tmp>>1)) & 0x5555; /* 0V0V0V0V0V0V0V0V */
176 //:: /* and move the valid bits to the lower byte. */
177 //:: tmp = (tmp | (tmp >> 1)) & 0x3333; /* 00VV00VV00VV00VV */
178 //:: tmp = (tmp | (tmp >> 2)) & 0x0f0f; /* 0000VVVV0000VVVV */
179 //:: tmp = (tmp | (tmp >> 4)) & 0x00ff; /* 00000000VVVVVVVV */
180 //:: return tmp;
181 //:: }
182 //::
183 //:: static unsigned long twd_fxsr_to_i387( const struct i387_fxsave_struct *fxsave )
184 //:: {
185 //:: struct _vki_fpxreg *st = NULL;
186 //:: unsigned long twd = (unsigned long) fxsave->twd;
187 //:: unsigned long tag;
188 //:: unsigned long ret = 0xffff0000u;
189 //:: int i;
190 //::
191 //:: #define FPREG_ADDR(f, n) ((char *)&(f)->st_space + (n) * 16);
192 //::
193 //:: for ( i = 0 ; i < 8 ; i++ ) {
194 //:: if ( twd & 0x1 ) {
195 //:: st = (struct _vki_fpxreg *) FPREG_ADDR( fxsave, i );
196 //::
197 //:: switch ( st->exponent & 0x7fff ) {
198 //:: case 0x7fff:
199 //:: tag = 2; /* Special */
200 //:: break;
201 //:: case 0x0000:
202 //:: if ( !st->significand[0] &&
203 //:: !st->significand[1] &&
204 //:: !st->significand[2] &&
205 //:: !st->significand[3] ) {
206 //:: tag = 1; /* Zero */
207 //:: } else {
208 //:: tag = 2; /* Special */
209 //:: }
210 //:: break;
211 //:: default:
212 //:: if ( st->significand[3] & 0x8000 ) {
213 //:: tag = 0; /* Valid */
214 //:: } else {
215 //:: tag = 2; /* Special */
216 //:: }
217 //:: break;
218 //:: }
219 //:: } else {
220 //:: tag = 3; /* Empty */
221 //:: }
222 //:: ret |= (tag << (2 * i));
223 //:: twd = twd >> 1;
224 //:: }
225 //:: return ret;
226 //:: }
227 //::
228 //:: static void convert_fxsr_to_user( struct _vki_fpstate *buf,
229 //:: const struct i387_fxsave_struct *fxsave )
230 //:: {
231 //:: unsigned long env[7];
232 //:: struct _vki_fpreg *to;
233 //:: struct _vki_fpxreg *from;
234 //:: int i;
235 //::
236 //:: env[0] = (unsigned long)fxsave->cwd | 0xffff0000ul;
237 //:: env[1] = (unsigned long)fxsave->swd | 0xffff0000ul;
238 //:: env[2] = twd_fxsr_to_i387(fxsave);
239 //:: env[3] = fxsave->fip;
240 //:: env[4] = fxsave->fcs | ((unsigned long)fxsave->fop << 16);
241 //:: env[5] = fxsave->foo;
242 //:: env[6] = fxsave->fos;
243 //::
244 //:: VG_(memcpy)(buf, env, 7 * sizeof(unsigned long));
245 //::
246 //:: to = &buf->_st[0];
247 //:: from = (struct _vki_fpxreg *) &fxsave->st_space[0];
248 //:: for ( i = 0 ; i < 8 ; i++, to++, from++ ) {
249 //:: unsigned long __user *t = (unsigned long __user *)to;
250 //:: unsigned long *f = (unsigned long *)from;
251 //::
252 //:: t[0] = f[0];
253 //:: t[1] = f[1];
254 //:: to->exponent = from->exponent;
255 //:: }
256 //:: }
257 //::
258 //:: static void convert_fxsr_from_user( struct i387_fxsave_struct *fxsave,
259 //:: const struct _vki_fpstate *buf )
260 //:: {
261 //:: unsigned long env[7];
262 //:: struct _vki_fpxreg *to;
263 //:: const struct _vki_fpreg *from;
264 //:: int i;
265 //::
266 //:: VG_(memcpy)(env, buf, 7 * sizeof(long));
267 //::
268 //:: fxsave->cwd = (unsigned short)(env[0] & 0xffff);
269 //:: fxsave->swd = (unsigned short)(env[1] & 0xffff);
270 //:: fxsave->twd = twd_i387_to_fxsr((unsigned short)(env[2] & 0xffff));
271 //:: fxsave->fip = env[3];
272 //:: fxsave->fop = (unsigned short)((env[4] & 0xffff0000ul) >> 16);
273 //:: fxsave->fcs = (env[4] & 0xffff);
274 //:: fxsave->foo = env[5];
275 //:: fxsave->fos = env[6];
276 //::
277 //:: to = (struct _vki_fpxreg *) &fxsave->st_space[0];
278 //:: from = &buf->_st[0];
279 //:: for ( i = 0 ; i < 8 ; i++, to++, from++ ) {
280 //:: unsigned long *t = (unsigned long *)to;
281 //:: unsigned long __user *f = (unsigned long __user *)from;
282 //::
283 //:: t[0] = f[0];
284 //:: t[1] = f[1];
285 //:: to->exponent = from->exponent;
286 //:: }
287 //:: }
288 //::
289 //:: static inline void save_i387_fsave( arch_thread_t *regs, struct _vki_fpstate *buf )
290 //:: {
291 //:: struct i387_fsave_struct *fs = &regs->m_sse.fsave;
292 //::
293 //:: fs->status = fs->swd;
294 //:: VG_(memcpy)(buf, fs, sizeof(*fs));
295 //:: }
296 //::
297 //:: static void save_i387_fxsave( arch_thread_t *regs, struct _vki_fpstate *buf )
298 //:: {
299 //:: const struct i387_fxsave_struct *fx = &regs->m_sse.fxsave;
300 //:: convert_fxsr_to_user( buf, fx );
301 //::
302 //:: buf->status = fx->swd;
303 //:: buf->magic = X86_FXSR_MAGIC;
304 //:: VG_(memcpy)(buf->_fxsr_env, fx, sizeof(struct i387_fxsave_struct));
305 //:: }
306 //::
307 //:: static void save_i387( arch_thread_t *regs, struct _vki_fpstate *buf )
308 //:: {
309 //:: if ( VG_(have_ssestate) )
310 //:: save_i387_fxsave( regs, buf );
311 //:: else
312 //:: save_i387_fsave( regs, buf );
313 //:: }
314 //::
315 //:: static inline void restore_i387_fsave( arch_thread_t *regs, const struct _vki_fpstate __user *buf )
316 //:: {
317 //:: VG_(memcpy)( &regs->m_sse.fsave, buf, sizeof(struct i387_fsave_struct) );
318 //:: }
319 //::
320 //:: static void restore_i387_fxsave( arch_thread_t *regs, const struct _vki_fpstate __user *buf )
321 //:: {
322 //:: VG_(memcpy)(&regs->m_sse.fxsave, &buf->_fxsr_env[0],
323 //:: sizeof(struct i387_fxsave_struct) );
324 //:: /* mxcsr reserved bits must be masked to zero for security reasons */
325 //:: regs->m_sse.fxsave.mxcsr &= 0xffbf;
326 //:: convert_fxsr_from_user( &regs->m_sse.fxsave, buf );
327 //:: }
328 //::
329 //:: static void restore_i387( arch_thread_t *regs, const struct _vki_fpstate __user *buf )
330 //:: {
331 //:: if ( VG_(have_ssestate) ) {
332 //:: restore_i387_fxsave( regs, buf );
333 //:: } else {
334 //:: restore_i387_fsave( regs, buf );
335 //:: }
336 //:: }
339 /*------------------------------------------------------------*/
340 /*--- Creating signal frames ---*/
341 /*------------------------------------------------------------*/
343 /* Create a plausible-looking sigcontext from the thread's
344 Vex guest state. NOTE: does not fill in the FP or SSE
345 bits of sigcontext at the moment.
347 static
348 void synth_ucontext(ThreadId tid, const vki_siginfo_t *si,
349 UWord trapno, UWord err, const vki_sigset_t *set,
350 struct vki_ucontext *uc, struct _vki_fpstate *fpstate)
352 ThreadState *tst = VG_(get_ThreadState)(tid);
353 struct vki_sigcontext *sc = &uc->uc_mcontext;
355 VG_(memset)(uc, 0, sizeof(*uc));
357 uc->uc_flags = 0;
358 uc->uc_link = 0;
359 uc->uc_sigmask = *set;
360 uc->uc_stack = tst->altstack;
361 sc->fpstate = fpstate;
363 // FIXME: save_i387(&tst->arch, fpstate);
365 # define SC2(reg,REG) sc->reg = tst->arch.vex.guest_##REG
366 SC2(gs,GS);
367 SC2(fs,FS);
368 SC2(es,ES);
369 SC2(ds,DS);
371 SC2(edi,EDI);
372 SC2(esi,ESI);
373 SC2(ebp,EBP);
374 SC2(esp,ESP);
375 SC2(ebx,EBX);
376 SC2(edx,EDX);
377 SC2(ecx,ECX);
378 SC2(eax,EAX);
380 SC2(eip,EIP);
381 SC2(cs,CS);
382 sc->eflags = LibVEX_GuestX86_get_eflags(&tst->arch.vex);
383 SC2(ss,SS);
384 /* XXX esp_at_signal */
385 sc->trapno = trapno;
386 sc->err = err;
387 # undef SC2
389 sc->cr2 = (UInt)si->_sifields._sigfault._addr;
393 /* Build the Valgrind-specific part of a signal frame. */
395 static void build_vg_sigframe(struct vg_sigframe *frame,
396 ThreadState *tst,
397 UInt flags,
398 Int sigNo)
400 frame->sigNo_private = sigNo;
401 frame->magicPI = 0x31415927;
402 frame->vex_shadow1 = tst->arch.vex_shadow1;
403 frame->vex_shadow2 = tst->arch.vex_shadow2;
404 /* HACK ALERT */
405 frame->vex = tst->arch.vex;
406 /* end HACK ALERT */
407 frame->mask = tst->sig_mask;
408 frame->handlerflags = flags;
409 frame->magicE = 0x27182818;
413 static Addr build_sigframe(ThreadState *tst,
414 Addr esp_top_of_frame,
415 const vki_siginfo_t *siginfo,
416 const struct vki_ucontext *siguc,
417 UInt flags,
418 const vki_sigset_t *mask,
419 void *restorer)
421 struct sigframe *frame;
422 Addr esp = esp_top_of_frame;
423 Int sigNo = siginfo->si_signo;
424 UWord trapno;
425 UWord err;
426 struct vki_ucontext uc;
428 vg_assert((flags & VKI_SA_SIGINFO) == 0);
430 esp -= sizeof(*frame);
431 esp = VG_ROUNDDN(esp, 16) - 4;
432 frame = (struct sigframe *)esp;
434 if (! ML_(sf_maybe_extend_stack)(tst, esp, sizeof(*frame), flags))
435 return esp_top_of_frame;
437 /* retaddr, sigNo, siguContext fields are to be written */
438 VG_TRACK( pre_mem_write, Vg_CoreSignal, tst->tid, "signal handler frame",
439 esp, offsetof(struct sigframe, vg) );
441 frame->sigNo = sigNo;
443 if (flags & VKI_SA_RESTORER)
444 frame->retaddr = (Addr)restorer;
445 else
446 frame->retaddr = (Addr)&VG_(x86_linux_SUBST_FOR_sigreturn);
448 if (siguc) {
449 trapno = siguc->uc_mcontext.trapno;
450 err = siguc->uc_mcontext.err;
451 } else {
452 trapno = 0;
453 err = 0;
456 synth_ucontext(tst->tid, siginfo, trapno, err, mask, &uc, &frame->fpstate);
458 VG_(memcpy)(&frame->sigContext, &uc.uc_mcontext,
459 sizeof(struct vki_sigcontext));
460 frame->sigContext.oldmask = mask->sig[0];
462 VG_TRACK( post_mem_write, Vg_CoreSignal, tst->tid,
463 esp, offsetof(struct sigframe, vg) );
465 build_vg_sigframe(&frame->vg, tst, flags, sigNo);
467 return esp;
471 static Addr build_rt_sigframe(ThreadState *tst,
472 Addr esp_top_of_frame,
473 const vki_siginfo_t *siginfo,
474 const struct vki_ucontext *siguc,
475 UInt flags,
476 const vki_sigset_t *mask,
477 void *restorer)
479 struct rt_sigframe *frame;
480 Addr esp = esp_top_of_frame;
481 Int sigNo = siginfo->si_signo;
482 UWord trapno;
483 UWord err;
485 vg_assert((flags & VKI_SA_SIGINFO) != 0);
487 esp -= sizeof(*frame);
488 esp = VG_ROUNDDN(esp, 16) - 4;
489 frame = (struct rt_sigframe *)esp;
491 if (! ML_(sf_maybe_extend_stack)(tst, esp, sizeof(*frame), flags))
492 return esp_top_of_frame;
494 /* retaddr, sigNo, pSiginfo, puContext fields are to be written */
495 VG_TRACK( pre_mem_write, Vg_CoreSignal, tst->tid, "rt signal handler frame",
496 esp, offsetof(struct rt_sigframe, vg) );
498 frame->sigNo = sigNo;
500 if (flags & VKI_SA_RESTORER)
501 frame->retaddr = (Addr)restorer;
502 else
503 frame->retaddr = (Addr)&VG_(x86_linux_SUBST_FOR_rt_sigreturn);
505 if (siguc) {
506 trapno = siguc->uc_mcontext.trapno;
507 err = siguc->uc_mcontext.err;
508 } else {
509 trapno = 0;
510 err = 0;
513 frame->psigInfo = (Addr)&frame->sigInfo;
514 frame->puContext = (Addr)&frame->uContext;
515 VG_(memcpy)(&frame->sigInfo, siginfo, sizeof(vki_siginfo_t));
517 /* SIGILL defines addr to be the faulting address */
518 if (sigNo == VKI_SIGILL && siginfo->si_code > 0)
519 frame->sigInfo._sifields._sigfault._addr
520 = (void*)tst->arch.vex.guest_EIP;
522 synth_ucontext(tst->tid, siginfo, trapno, err, mask,
523 &frame->uContext, &frame->fpstate);
525 VG_TRACK( post_mem_write, Vg_CoreSignal, tst->tid,
526 esp, offsetof(struct rt_sigframe, vg) );
528 build_vg_sigframe(&frame->vg, tst, flags, sigNo);
530 return esp;
534 /* EXPORTED */
535 void VG_(sigframe_create)( ThreadId tid,
536 Bool on_altstack,
537 Addr esp_top_of_frame,
538 const vki_siginfo_t *siginfo,
539 const struct vki_ucontext *siguc,
540 void *handler,
541 UInt flags,
542 const vki_sigset_t *mask,
543 void *restorer )
545 Addr esp;
546 ThreadState* tst = VG_(get_ThreadState)(tid);
548 if (flags & VKI_SA_SIGINFO)
549 esp = build_rt_sigframe(tst, esp_top_of_frame, siginfo, siguc,
550 flags, mask, restorer);
551 else
552 esp = build_sigframe(tst, esp_top_of_frame, siginfo, siguc,
553 flags, mask, restorer);
555 /* Set the thread so it will next run the handler. */
556 /* tst->m_esp = esp; also notify the tool we've updated ESP */
557 VG_(set_SP)(tid, esp);
558 VG_TRACK( post_reg_write, Vg_CoreSignal, tid, VG_O_STACK_PTR, sizeof(Addr));
560 //VG_(printf)("handler = %p\n", handler);
561 tst->arch.vex.guest_EIP = (Addr) handler;
562 /* This thread needs to be marked runnable, but we leave that the
563 caller to do. */
565 if (0)
566 VG_(printf)("pushed signal frame; %%ESP now = %#lx, "
567 "next %%EIP = %#x, status=%d\n",
568 esp, tst->arch.vex.guest_EIP, (Int)tst->status);
572 /*------------------------------------------------------------*/
573 /*--- Destroying signal frames ---*/
574 /*------------------------------------------------------------*/
576 /* Return False and don't do anything, just set the client to take a
577 segfault, if it looks like the frame is corrupted. */
578 static
579 Bool restore_vg_sigframe ( ThreadState *tst,
580 struct vg_sigframe *frame, Int *sigNo )
582 if (frame->magicPI != 0x31415927 ||
583 frame->magicE != 0x27182818) {
584 VG_(message)(Vg_UserMsg, "Thread %u return signal frame "
585 "corrupted. Killing process.\n",
586 tst->tid);
587 VG_(set_default_handler)(VKI_SIGSEGV);
588 VG_(synth_fault)(tst->tid);
589 *sigNo = VKI_SIGSEGV;
590 return False;
592 tst->sig_mask = frame->mask;
593 tst->tmp_sig_mask = frame->mask;
594 tst->arch.vex_shadow1 = frame->vex_shadow1;
595 tst->arch.vex_shadow2 = frame->vex_shadow2;
596 /* HACK ALERT */
597 tst->arch.vex = frame->vex;
598 /* end HACK ALERT */
599 *sigNo = frame->sigNo_private;
600 return True;
603 static
604 void restore_sigcontext( ThreadState *tst,
605 struct vki_sigcontext *sc,
606 struct _vki_fpstate *fpstate )
608 tst->arch.vex.guest_EAX = sc->eax;
609 tst->arch.vex.guest_ECX = sc->ecx;
610 tst->arch.vex.guest_EDX = sc->edx;
611 tst->arch.vex.guest_EBX = sc->ebx;
612 tst->arch.vex.guest_EBP = sc->ebp;
613 tst->arch.vex.guest_ESP = sc->esp;
614 tst->arch.vex.guest_ESI = sc->esi;
615 tst->arch.vex.guest_EDI = sc->edi;
616 //:: tst->arch.vex.guest_eflags = sc->eflags;
617 tst->arch.vex.guest_EIP = sc->eip;
618 tst->arch.vex.guest_CS = sc->cs;
619 tst->arch.vex.guest_SS = sc->ss;
620 tst->arch.vex.guest_DS = sc->ds;
621 tst->arch.vex.guest_ES = sc->es;
622 tst->arch.vex.guest_FS = sc->fs;
623 tst->arch.vex.guest_GS = sc->gs;
625 //:: restore_i387(&tst->arch, fpstate);
629 static
630 SizeT restore_sigframe ( ThreadState *tst,
631 struct sigframe *frame, Int *sigNo )
633 if (restore_vg_sigframe(tst, &frame->vg, sigNo))
634 restore_sigcontext(tst, &frame->sigContext, &frame->fpstate);
636 return sizeof(*frame);
639 static
640 SizeT restore_rt_sigframe ( ThreadState *tst,
641 struct rt_sigframe *frame, Int *sigNo )
643 if (restore_vg_sigframe(tst, &frame->vg, sigNo))
644 restore_sigcontext(tst, &frame->uContext.uc_mcontext, &frame->fpstate);
646 return sizeof(*frame);
650 /* EXPORTED */
651 void VG_(sigframe_destroy)( ThreadId tid, Bool isRT )
653 Addr esp;
654 ThreadState* tst;
655 SizeT size;
656 Int sigNo;
658 tst = VG_(get_ThreadState)(tid);
660 /* Correctly reestablish the frame base address. */
661 esp = tst->arch.vex.guest_ESP;
663 if (!isRT)
664 size = restore_sigframe(tst, (struct sigframe *)esp, &sigNo);
665 else
666 size = restore_rt_sigframe(tst, (struct rt_sigframe *)esp, &sigNo);
668 VG_TRACK( die_mem_stack_signal, esp - VG_STACK_REDZONE_SZB,
669 size + VG_STACK_REDZONE_SZB );
671 if (VG_(clo_trace_signals))
672 VG_(message)(
673 Vg_DebugMsg,
674 "VG_(sigframe_destroy) (thread %u): isRT=%d valid magic; EIP=%#x\n",
675 tid, isRT, tst->arch.vex.guest_EIP);
677 /* tell the tools */
678 VG_TRACK( post_deliver_signal, tid, sigNo );
681 #endif // defined(VGP_x86_linux)
683 /*--------------------------------------------------------------------*/
684 /*--- end ---*/
685 /*--------------------------------------------------------------------*/