tests/vg_regtest: Always evaluate prerequisite expressions with sh
[valgrind.git] / coregrind / m_sigframe / sigframe-x86-linux.c
blobce33f7356bb3dd72fe90cee2a7030adcc1cd6b76
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-2013 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, write to the Free Software
26 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
27 02111-1307, USA.
29 The GNU General Public License is contained in the file COPYING.
32 #if defined(VGP_x86_linux)
34 #include "pub_core_basics.h"
35 #include "pub_core_vki.h"
36 #include "pub_core_threadstate.h"
37 #include "pub_core_aspacemgr.h" /* find_segment */
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_signals.h"
44 #include "pub_core_tooliface.h"
45 #include "pub_core_trampoline.h"
46 #include "pub_core_sigframe.h" /* self */
47 #include "priv_sigframe.h"
49 /* This module creates and removes signal frames for signal deliveries
50 on x86-linux.
52 Note, this file contains kernel-specific knowledge in the form of
53 'struct sigframe' and 'struct rt_sigframe'. How does that relate
54 to the vki kernel interface stuff?
56 Either a 'struct sigframe' or a 'struct rtsigframe' is pushed
57 onto the client's stack. This contains a subsidiary
58 vki_ucontext. That holds the vcpu's state across the signal,
59 so that the sighandler can mess with the vcpu state if it
60 really wants.
62 FIXME: sigcontexting is basically broken for the moment. When
63 delivering a signal, the integer registers and %eflags are
64 correctly written into the sigcontext, however the FP and SSE state
65 is not. When returning from a signal, only the integer registers
66 are restored from the sigcontext; the rest of the CPU state is
67 restored to what it was before the signal.
69 This will be fixed.
73 /*------------------------------------------------------------*/
74 /*--- Signal frame layouts ---*/
75 /*------------------------------------------------------------*/
77 // A structure in which to save the application's registers
78 // during the execution of signal handlers.
80 // Linux has 2 signal frame structures: one for normal signal
81 // deliveries, and one for SA_SIGINFO deliveries (also known as RT
82 // signals).
84 // In theory, so long as we get the arguments to the handler function
85 // right, it doesn't matter what the exact layout of the rest of the
86 // frame is. Unfortunately, things like gcc's exception unwinding
87 // make assumptions about the locations of various parts of the frame,
88 // so we need to duplicate it exactly.
90 /* Valgrind-specific parts of the signal frame */
91 struct vg_sigframe
93 /* Sanity check word. */
94 UInt magicPI;
96 UInt handlerflags; /* flags for signal handler */
99 /* Safely-saved version of sigNo, as described above. */
100 Int sigNo_private;
102 /* XXX This is wrong. Surely we should store the shadow values
103 into the shadow memory behind the actual values? */
104 VexGuestX86State vex_shadow1;
105 VexGuestX86State vex_shadow2;
107 /* HACK ALERT */
108 VexGuestX86State vex;
109 /* end HACK ALERT */
111 /* saved signal mask to be restored when handler returns */
112 vki_sigset_t mask;
114 /* Sanity check word. Is the highest-addressed word; do not
115 move!*/
116 UInt magicE;
119 struct sigframe
121 /* Sig handler's return address */
122 Addr retaddr;
123 Int sigNo;
125 struct vki_sigcontext sigContext;
126 struct _vki_fpstate fpstate;
128 struct vg_sigframe vg;
131 struct rt_sigframe
133 /* Sig handler's return address */
134 Addr retaddr;
135 Int sigNo;
137 /* ptr to siginfo_t. */
138 Addr psigInfo;
140 /* ptr to ucontext */
141 Addr puContext;
142 /* pointed to by psigInfo */
143 vki_siginfo_t sigInfo;
145 /* pointed to by puContext */
146 struct vki_ucontext uContext;
147 struct _vki_fpstate fpstate;
149 struct vg_sigframe vg;
153 //:: /*------------------------------------------------------------*/
154 //:: /*--- Signal operations ---*/
155 //:: /*------------------------------------------------------------*/
156 //::
157 //:: /*
158 //:: Great gobs of FP state conversion taken wholesale from
159 //:: linux/arch/i386/kernel/i387.c
160 //:: */
161 //::
162 //:: /*
163 //:: * FXSR floating point environment conversions.
164 //:: */
165 //:: #define X86_FXSR_MAGIC 0x0000
166 //::
167 //:: /*
168 //:: * FPU tag word conversions.
169 //:: */
170 //::
171 //:: static inline unsigned short twd_i387_to_fxsr( unsigned short twd )
172 //:: {
173 //:: unsigned int tmp; /* to avoid 16 bit prefixes in the code */
174 //::
175 //:: /* Transform each pair of bits into 01 (valid) or 00 (empty) */
176 //:: tmp = ~twd;
177 //:: tmp = (tmp | (tmp>>1)) & 0x5555; /* 0V0V0V0V0V0V0V0V */
178 //:: /* and move the valid bits to the lower byte. */
179 //:: tmp = (tmp | (tmp >> 1)) & 0x3333; /* 00VV00VV00VV00VV */
180 //:: tmp = (tmp | (tmp >> 2)) & 0x0f0f; /* 0000VVVV0000VVVV */
181 //:: tmp = (tmp | (tmp >> 4)) & 0x00ff; /* 00000000VVVVVVVV */
182 //:: return tmp;
183 //:: }
184 //::
185 //:: static unsigned long twd_fxsr_to_i387( const struct i387_fxsave_struct *fxsave )
186 //:: {
187 //:: struct _vki_fpxreg *st = NULL;
188 //:: unsigned long twd = (unsigned long) fxsave->twd;
189 //:: unsigned long tag;
190 //:: unsigned long ret = 0xffff0000u;
191 //:: int i;
192 //::
193 //:: #define FPREG_ADDR(f, n) ((char *)&(f)->st_space + (n) * 16);
194 //::
195 //:: for ( i = 0 ; i < 8 ; i++ ) {
196 //:: if ( twd & 0x1 ) {
197 //:: st = (struct _vki_fpxreg *) FPREG_ADDR( fxsave, i );
198 //::
199 //:: switch ( st->exponent & 0x7fff ) {
200 //:: case 0x7fff:
201 //:: tag = 2; /* Special */
202 //:: break;
203 //:: case 0x0000:
204 //:: if ( !st->significand[0] &&
205 //:: !st->significand[1] &&
206 //:: !st->significand[2] &&
207 //:: !st->significand[3] ) {
208 //:: tag = 1; /* Zero */
209 //:: } else {
210 //:: tag = 2; /* Special */
211 //:: }
212 //:: break;
213 //:: default:
214 //:: if ( st->significand[3] & 0x8000 ) {
215 //:: tag = 0; /* Valid */
216 //:: } else {
217 //:: tag = 2; /* Special */
218 //:: }
219 //:: break;
220 //:: }
221 //:: } else {
222 //:: tag = 3; /* Empty */
223 //:: }
224 //:: ret |= (tag << (2 * i));
225 //:: twd = twd >> 1;
226 //:: }
227 //:: return ret;
228 //:: }
229 //::
230 //:: static void convert_fxsr_to_user( struct _vki_fpstate *buf,
231 //:: const struct i387_fxsave_struct *fxsave )
232 //:: {
233 //:: unsigned long env[7];
234 //:: struct _vki_fpreg *to;
235 //:: struct _vki_fpxreg *from;
236 //:: int i;
237 //::
238 //:: env[0] = (unsigned long)fxsave->cwd | 0xffff0000ul;
239 //:: env[1] = (unsigned long)fxsave->swd | 0xffff0000ul;
240 //:: env[2] = twd_fxsr_to_i387(fxsave);
241 //:: env[3] = fxsave->fip;
242 //:: env[4] = fxsave->fcs | ((unsigned long)fxsave->fop << 16);
243 //:: env[5] = fxsave->foo;
244 //:: env[6] = fxsave->fos;
245 //::
246 //:: VG_(memcpy)(buf, env, 7 * sizeof(unsigned long));
247 //::
248 //:: to = &buf->_st[0];
249 //:: from = (struct _vki_fpxreg *) &fxsave->st_space[0];
250 //:: for ( i = 0 ; i < 8 ; i++, to++, from++ ) {
251 //:: unsigned long __user *t = (unsigned long __user *)to;
252 //:: unsigned long *f = (unsigned long *)from;
253 //::
254 //:: t[0] = f[0];
255 //:: t[1] = f[1];
256 //:: to->exponent = from->exponent;
257 //:: }
258 //:: }
259 //::
260 //:: static void convert_fxsr_from_user( struct i387_fxsave_struct *fxsave,
261 //:: const struct _vki_fpstate *buf )
262 //:: {
263 //:: unsigned long env[7];
264 //:: struct _vki_fpxreg *to;
265 //:: const struct _vki_fpreg *from;
266 //:: int i;
267 //::
268 //:: VG_(memcpy)(env, buf, 7 * sizeof(long));
269 //::
270 //:: fxsave->cwd = (unsigned short)(env[0] & 0xffff);
271 //:: fxsave->swd = (unsigned short)(env[1] & 0xffff);
272 //:: fxsave->twd = twd_i387_to_fxsr((unsigned short)(env[2] & 0xffff));
273 //:: fxsave->fip = env[3];
274 //:: fxsave->fop = (unsigned short)((env[4] & 0xffff0000ul) >> 16);
275 //:: fxsave->fcs = (env[4] & 0xffff);
276 //:: fxsave->foo = env[5];
277 //:: fxsave->fos = env[6];
278 //::
279 //:: to = (struct _vki_fpxreg *) &fxsave->st_space[0];
280 //:: from = &buf->_st[0];
281 //:: for ( i = 0 ; i < 8 ; i++, to++, from++ ) {
282 //:: unsigned long *t = (unsigned long *)to;
283 //:: unsigned long __user *f = (unsigned long __user *)from;
284 //::
285 //:: t[0] = f[0];
286 //:: t[1] = f[1];
287 //:: to->exponent = from->exponent;
288 //:: }
289 //:: }
290 //::
291 //:: static inline void save_i387_fsave( arch_thread_t *regs, struct _vki_fpstate *buf )
292 //:: {
293 //:: struct i387_fsave_struct *fs = &regs->m_sse.fsave;
294 //::
295 //:: fs->status = fs->swd;
296 //:: VG_(memcpy)(buf, fs, sizeof(*fs));
297 //:: }
298 //::
299 //:: static void save_i387_fxsave( arch_thread_t *regs, struct _vki_fpstate *buf )
300 //:: {
301 //:: const struct i387_fxsave_struct *fx = &regs->m_sse.fxsave;
302 //:: convert_fxsr_to_user( buf, fx );
303 //::
304 //:: buf->status = fx->swd;
305 //:: buf->magic = X86_FXSR_MAGIC;
306 //:: VG_(memcpy)(buf->_fxsr_env, fx, sizeof(struct i387_fxsave_struct));
307 //:: }
308 //::
309 //:: static void save_i387( arch_thread_t *regs, struct _vki_fpstate *buf )
310 //:: {
311 //:: if ( VG_(have_ssestate) )
312 //:: save_i387_fxsave( regs, buf );
313 //:: else
314 //:: save_i387_fsave( regs, buf );
315 //:: }
316 //::
317 //:: static inline void restore_i387_fsave( arch_thread_t *regs, const struct _vki_fpstate __user *buf )
318 //:: {
319 //:: VG_(memcpy)( &regs->m_sse.fsave, buf, sizeof(struct i387_fsave_struct) );
320 //:: }
321 //::
322 //:: static void restore_i387_fxsave( arch_thread_t *regs, const struct _vki_fpstate __user *buf )
323 //:: {
324 //:: VG_(memcpy)(&regs->m_sse.fxsave, &buf->_fxsr_env[0],
325 //:: sizeof(struct i387_fxsave_struct) );
326 //:: /* mxcsr reserved bits must be masked to zero for security reasons */
327 //:: regs->m_sse.fxsave.mxcsr &= 0xffbf;
328 //:: convert_fxsr_from_user( &regs->m_sse.fxsave, buf );
329 //:: }
330 //::
331 //:: static void restore_i387( arch_thread_t *regs, const struct _vki_fpstate __user *buf )
332 //:: {
333 //:: if ( VG_(have_ssestate) ) {
334 //:: restore_i387_fxsave( regs, buf );
335 //:: } else {
336 //:: restore_i387_fsave( regs, buf );
337 //:: }
338 //:: }
341 /*------------------------------------------------------------*/
342 /*--- Creating signal frames ---*/
343 /*------------------------------------------------------------*/
345 /* Create a plausible-looking sigcontext from the thread's
346 Vex guest state. NOTE: does not fill in the FP or SSE
347 bits of sigcontext at the moment.
349 static
350 void synth_ucontext(ThreadId tid, const vki_siginfo_t *si,
351 UWord trapno, UWord err, const vki_sigset_t *set,
352 struct vki_ucontext *uc, struct _vki_fpstate *fpstate)
354 ThreadState *tst = VG_(get_ThreadState)(tid);
355 struct vki_sigcontext *sc = &uc->uc_mcontext;
357 VG_(memset)(uc, 0, sizeof(*uc));
359 uc->uc_flags = 0;
360 uc->uc_link = 0;
361 uc->uc_sigmask = *set;
362 uc->uc_stack = tst->altstack;
363 sc->fpstate = fpstate;
365 // FIXME: save_i387(&tst->arch, fpstate);
367 # define SC2(reg,REG) sc->reg = tst->arch.vex.guest_##REG
368 SC2(gs,GS);
369 SC2(fs,FS);
370 SC2(es,ES);
371 SC2(ds,DS);
373 SC2(edi,EDI);
374 SC2(esi,ESI);
375 SC2(ebp,EBP);
376 SC2(esp,ESP);
377 SC2(ebx,EBX);
378 SC2(edx,EDX);
379 SC2(ecx,ECX);
380 SC2(eax,EAX);
382 SC2(eip,EIP);
383 SC2(cs,CS);
384 sc->eflags = LibVEX_GuestX86_get_eflags(&tst->arch.vex);
385 SC2(ss,SS);
386 /* XXX esp_at_signal */
387 sc->trapno = trapno;
388 sc->err = err;
389 # undef SC2
391 sc->cr2 = (UInt)si->_sifields._sigfault._addr;
395 /* Build the Valgrind-specific part of a signal frame. */
397 static void build_vg_sigframe(struct vg_sigframe *frame,
398 ThreadState *tst,
399 UInt flags,
400 Int sigNo)
402 frame->sigNo_private = sigNo;
403 frame->magicPI = 0x31415927;
404 frame->vex_shadow1 = tst->arch.vex_shadow1;
405 frame->vex_shadow2 = tst->arch.vex_shadow2;
406 /* HACK ALERT */
407 frame->vex = tst->arch.vex;
408 /* end HACK ALERT */
409 frame->mask = tst->sig_mask;
410 frame->handlerflags = flags;
411 frame->magicE = 0x27182818;
415 static Addr build_sigframe(ThreadState *tst,
416 Addr esp_top_of_frame,
417 const vki_siginfo_t *siginfo,
418 const struct vki_ucontext *siguc,
419 UInt flags,
420 const vki_sigset_t *mask,
421 void *restorer)
423 struct sigframe *frame;
424 Addr esp = esp_top_of_frame;
425 Int sigNo = siginfo->si_signo;
426 UWord trapno;
427 UWord err;
428 struct vki_ucontext uc;
430 vg_assert((flags & VKI_SA_SIGINFO) == 0);
432 esp -= sizeof(*frame);
433 esp = VG_ROUNDDN(esp, 16);
434 frame = (struct sigframe *)esp;
436 if (! ML_(sf_maybe_extend_stack)(tst, esp, sizeof(*frame), flags))
437 return esp_top_of_frame;
439 /* retaddr, sigNo, siguContext fields are to be written */
440 VG_TRACK( pre_mem_write, Vg_CoreSignal, tst->tid, "signal handler frame",
441 esp, offsetof(struct sigframe, vg) );
443 frame->sigNo = sigNo;
445 if (flags & VKI_SA_RESTORER)
446 frame->retaddr = (Addr)restorer;
447 else
448 frame->retaddr = (Addr)&VG_(x86_linux_SUBST_FOR_sigreturn);
450 if (siguc) {
451 trapno = siguc->uc_mcontext.trapno;
452 err = siguc->uc_mcontext.err;
453 } else {
454 trapno = 0;
455 err = 0;
458 synth_ucontext(tst->tid, siginfo, trapno, err, mask, &uc, &frame->fpstate);
460 VG_(memcpy)(&frame->sigContext, &uc.uc_mcontext,
461 sizeof(struct vki_sigcontext));
462 frame->sigContext.oldmask = mask->sig[0];
464 VG_TRACK( post_mem_write, Vg_CoreSignal, tst->tid,
465 esp, offsetof(struct sigframe, vg) );
467 build_vg_sigframe(&frame->vg, tst, flags, sigNo);
469 return esp;
473 static Addr build_rt_sigframe(ThreadState *tst,
474 Addr esp_top_of_frame,
475 const vki_siginfo_t *siginfo,
476 const struct vki_ucontext *siguc,
477 UInt flags,
478 const vki_sigset_t *mask,
479 void *restorer)
481 struct rt_sigframe *frame;
482 Addr esp = esp_top_of_frame;
483 Int sigNo = siginfo->si_signo;
484 UWord trapno;
485 UWord err;
487 vg_assert((flags & VKI_SA_SIGINFO) != 0);
489 esp -= sizeof(*frame);
490 esp = VG_ROUNDDN(esp, 16);
491 frame = (struct rt_sigframe *)esp;
493 if (! ML_(sf_maybe_extend_stack)(tst, esp, sizeof(*frame), flags))
494 return esp_top_of_frame;
496 /* retaddr, sigNo, pSiginfo, puContext fields are to be written */
497 VG_TRACK( pre_mem_write, Vg_CoreSignal, tst->tid, "rt signal handler frame",
498 esp, offsetof(struct rt_sigframe, vg) );
500 frame->sigNo = sigNo;
502 if (flags & VKI_SA_RESTORER)
503 frame->retaddr = (Addr)restorer;
504 else
505 frame->retaddr = (Addr)&VG_(x86_linux_SUBST_FOR_rt_sigreturn);
507 if (siguc) {
508 trapno = siguc->uc_mcontext.trapno;
509 err = siguc->uc_mcontext.err;
510 } else {
511 trapno = 0;
512 err = 0;
515 frame->psigInfo = (Addr)&frame->sigInfo;
516 frame->puContext = (Addr)&frame->uContext;
517 VG_(memcpy)(&frame->sigInfo, siginfo, sizeof(vki_siginfo_t));
519 /* SIGILL defines addr to be the faulting address */
520 if (sigNo == VKI_SIGILL && siginfo->si_code > 0)
521 frame->sigInfo._sifields._sigfault._addr
522 = (void*)tst->arch.vex.guest_EIP;
524 synth_ucontext(tst->tid, siginfo, trapno, err, mask,
525 &frame->uContext, &frame->fpstate);
527 VG_TRACK( post_mem_write, Vg_CoreSignal, tst->tid,
528 esp, offsetof(struct rt_sigframe, vg) );
530 build_vg_sigframe(&frame->vg, tst, flags, sigNo);
532 return esp;
536 /* EXPORTED */
537 void VG_(sigframe_create)( ThreadId tid,
538 Bool on_altstack,
539 Addr esp_top_of_frame,
540 const vki_siginfo_t *siginfo,
541 const struct vki_ucontext *siguc,
542 void *handler,
543 UInt flags,
544 const vki_sigset_t *mask,
545 void *restorer )
547 Addr esp;
548 ThreadState* tst = VG_(get_ThreadState)(tid);
550 if (flags & VKI_SA_SIGINFO)
551 esp = build_rt_sigframe(tst, esp_top_of_frame, siginfo, siguc,
552 flags, mask, restorer);
553 else
554 esp = build_sigframe(tst, esp_top_of_frame, siginfo, siguc,
555 flags, mask, restorer);
557 /* Set the thread so it will next run the handler. */
558 /* tst->m_esp = esp; also notify the tool we've updated ESP */
559 VG_(set_SP)(tid, esp);
560 VG_TRACK( post_reg_write, Vg_CoreSignal, tid, VG_O_STACK_PTR, sizeof(Addr));
562 //VG_(printf)("handler = %p\n", handler);
563 tst->arch.vex.guest_EIP = (Addr) handler;
564 /* This thread needs to be marked runnable, but we leave that the
565 caller to do. */
567 if (0)
568 VG_(printf)("pushed signal frame; %%ESP now = %#lx, "
569 "next %%EIP = %#x, status=%d\n",
570 esp, tst->arch.vex.guest_EIP, tst->status);
574 /*------------------------------------------------------------*/
575 /*--- Destroying signal frames ---*/
576 /*------------------------------------------------------------*/
578 /* Return False and don't do anything, just set the client to take a
579 segfault, if it looks like the frame is corrupted. */
580 static
581 Bool restore_vg_sigframe ( ThreadState *tst,
582 struct vg_sigframe *frame, Int *sigNo )
584 if (frame->magicPI != 0x31415927 ||
585 frame->magicE != 0x27182818) {
586 VG_(message)(Vg_UserMsg, "Thread %d return signal frame "
587 "corrupted. Killing process.\n",
588 tst->tid);
589 VG_(set_default_handler)(VKI_SIGSEGV);
590 VG_(synth_fault)(tst->tid);
591 *sigNo = VKI_SIGSEGV;
592 return False;
594 tst->sig_mask = frame->mask;
595 tst->tmp_sig_mask = frame->mask;
596 tst->arch.vex_shadow1 = frame->vex_shadow1;
597 tst->arch.vex_shadow2 = frame->vex_shadow2;
598 /* HACK ALERT */
599 tst->arch.vex = frame->vex;
600 /* end HACK ALERT */
601 *sigNo = frame->sigNo_private;
602 return True;
605 static
606 void restore_sigcontext( ThreadState *tst,
607 struct vki_sigcontext *sc,
608 struct _vki_fpstate *fpstate )
610 tst->arch.vex.guest_EAX = sc->eax;
611 tst->arch.vex.guest_ECX = sc->ecx;
612 tst->arch.vex.guest_EDX = sc->edx;
613 tst->arch.vex.guest_EBX = sc->ebx;
614 tst->arch.vex.guest_EBP = sc->ebp;
615 tst->arch.vex.guest_ESP = sc->esp;
616 tst->arch.vex.guest_ESI = sc->esi;
617 tst->arch.vex.guest_EDI = sc->edi;
618 //:: tst->arch.vex.guest_eflags = sc->eflags;
619 tst->arch.vex.guest_EIP = sc->eip;
620 tst->arch.vex.guest_CS = sc->cs;
621 tst->arch.vex.guest_SS = sc->ss;
622 tst->arch.vex.guest_DS = sc->ds;
623 tst->arch.vex.guest_ES = sc->es;
624 tst->arch.vex.guest_FS = sc->fs;
625 tst->arch.vex.guest_GS = sc->gs;
627 //:: restore_i387(&tst->arch, fpstate);
631 static
632 SizeT restore_sigframe ( ThreadState *tst,
633 struct sigframe *frame, Int *sigNo )
635 if (restore_vg_sigframe(tst, &frame->vg, sigNo))
636 restore_sigcontext(tst, &frame->sigContext, &frame->fpstate);
638 return sizeof(*frame);
641 static
642 SizeT restore_rt_sigframe ( ThreadState *tst,
643 struct rt_sigframe *frame, Int *sigNo )
645 if (restore_vg_sigframe(tst, &frame->vg, sigNo))
646 restore_sigcontext(tst, &frame->uContext.uc_mcontext, &frame->fpstate);
648 return sizeof(*frame);
652 /* EXPORTED */
653 void VG_(sigframe_destroy)( ThreadId tid, Bool isRT )
655 Addr esp;
656 ThreadState* tst;
657 SizeT size;
658 Int sigNo;
660 tst = VG_(get_ThreadState)(tid);
662 /* Correctly reestablish the frame base address. */
663 esp = tst->arch.vex.guest_ESP;
665 if (!isRT)
666 size = restore_sigframe(tst, (struct sigframe *)esp, &sigNo);
667 else
668 size = restore_rt_sigframe(tst, (struct rt_sigframe *)esp, &sigNo);
670 VG_TRACK( die_mem_stack_signal, esp - VG_STACK_REDZONE_SZB,
671 size + VG_STACK_REDZONE_SZB );
673 if (VG_(clo_trace_signals))
674 VG_(message)(
675 Vg_DebugMsg,
676 "VG_(signal_return) (thread %d): isRT=%d valid magic; EIP=%#x\n",
677 tid, isRT, tst->arch.vex.guest_EIP);
679 /* tell the tools */
680 VG_TRACK( post_deliver_signal, tid, sigNo );
683 #endif // defined(VGP_x86_linux)
685 /*--------------------------------------------------------------------*/
686 /*--- end ---*/
687 /*--------------------------------------------------------------------*/