cerion | 85665ca | 2005-06-20 15:51:07 +0000 | [diff] [blame] | 1 | |
| 2 | /*--------------------------------------------------------------------*/ |
| 3 | /*--- Create/destroy signal delivery frames. ---*/ |
| 4 | /*--- sigframe-ppc32-linux.c ---*/ |
| 5 | /*--------------------------------------------------------------------*/ |
| 6 | |
| 7 | /* |
| 8 | This file is part of Valgrind, a dynamic binary instrumentation |
| 9 | framework. |
| 10 | |
sewardj | 0f157dd | 2013-10-18 14:27:36 +0000 | [diff] [blame] | 11 | Copyright (C) 2000-2013 Nicholas Nethercote |
sewardj | e1c444e | 2005-07-08 18:28:40 +0000 | [diff] [blame] | 12 | njn@valgrind.org |
sewardj | 0f157dd | 2013-10-18 14:27:36 +0000 | [diff] [blame] | 13 | Copyright (C) 2004-2013 Paul Mackerras |
sewardj | e1c444e | 2005-07-08 18:28:40 +0000 | [diff] [blame] | 14 | paulus@samba.org |
cerion | 85665ca | 2005-06-20 15:51:07 +0000 | [diff] [blame] | 15 | |
| 16 | This program is free software; you can redistribute it and/or |
| 17 | modify it under the terms of the GNU General Public License as |
| 18 | published by the Free Software Foundation; either version 2 of the |
| 19 | License, or (at your option) any later version. |
| 20 | |
| 21 | This program is distributed in the hope that it will be useful, but |
| 22 | WITHOUT ANY WARRANTY; without even the implied warranty of |
| 23 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| 24 | General Public License for more details. |
| 25 | |
| 26 | You should have received a copy of the GNU General Public License |
| 27 | along with this program; if not, write to the Free Software |
| 28 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA |
| 29 | 02111-1307, USA. |
| 30 | |
| 31 | The GNU General Public License is contained in the file COPYING. |
| 32 | */ |
| 33 | |
njn | 8b68b64 | 2009-06-24 00:37:09 +0000 | [diff] [blame] | 34 | #if defined(VGP_ppc32_linux) |
| 35 | |
cerion | 85665ca | 2005-06-20 15:51:07 +0000 | [diff] [blame] | 36 | #include "pub_core_basics.h" |
sewardj | c95257a | 2006-10-14 19:51:19 +0000 | [diff] [blame] | 37 | #include "pub_core_vki.h" |
| 38 | #include "pub_core_vkiscnums.h" |
sewardj | 6c591e1 | 2011-04-11 16:17:51 +0000 | [diff] [blame] | 39 | #include "pub_core_libcsetjmp.h" // to keep _threadstate.h happy |
cerion | 85665ca | 2005-06-20 15:51:07 +0000 | [diff] [blame] | 40 | #include "pub_core_threadstate.h" |
cerion | 85665ca | 2005-06-20 15:51:07 +0000 | [diff] [blame] | 41 | #include "pub_core_aspacemgr.h" |
| 42 | #include "pub_core_libcbase.h" |
| 43 | #include "pub_core_libcassert.h" |
| 44 | #include "pub_core_libcprint.h" |
| 45 | #include "pub_core_machine.h" |
| 46 | #include "pub_core_options.h" |
| 47 | #include "pub_core_sigframe.h" |
| 48 | #include "pub_core_signals.h" |
| 49 | #include "pub_core_tooliface.h" |
| 50 | #include "pub_core_trampoline.h" |
sewardj | e1c444e | 2005-07-08 18:28:40 +0000 | [diff] [blame] | 51 | #include "pub_core_transtab.h" // VG_(discard_translations) |
florian | 01fcf6a | 2015-04-18 10:33:54 +0000 | [diff] [blame] | 52 | #include "priv_sigframe.h" |
cerion | 85665ca | 2005-06-20 15:51:07 +0000 | [diff] [blame] | 53 | |
| 54 | /* This module creates and removes signal frames for signal deliveries |
| 55 | on ppc32-linux. |
| 56 | |
| 57 | Note, this file contains kernel-specific knowledge in the form of |
| 58 | 'struct sigframe' and 'struct rt_sigframe'. How does that relate |
| 59 | to the vki kernel interface stuff? |
| 60 | |
| 61 | Either a 'struct sigframe' or a 'struct rtsigframe' is pushed |
| 62 | onto the client's stack. This contains a subsidiary |
| 63 | vki_ucontext. That holds the vcpu's state across the signal, |
| 64 | so that the sighandler can mess with the vcpu state if it |
| 65 | really wants. |
| 66 | |
| 67 | FIXME: sigcontexting is basically broken for the moment. When |
| 68 | delivering a signal, the integer registers and %eflags are |
| 69 | correctly written into the sigcontext, however the FP and SSE state |
| 70 | is not. When returning from a signal, only the integer registers |
| 71 | are restored from the sigcontext; the rest of the CPU state is |
| 72 | restored to what it was before the signal. |
| 73 | |
| 74 | This will be fixed. |
| 75 | */ |
| 76 | |
| 77 | |
| 78 | /*------------------------------------------------------------*/ |
| 79 | /*--- Signal frame layouts ---*/ |
| 80 | /*------------------------------------------------------------*/ |
| 81 | |
| 82 | // A structure in which to save the application's registers |
| 83 | // during the execution of signal handlers. |
| 84 | |
| 85 | // Linux has 2 signal frame structures: one for normal signal |
| 86 | // deliveries, and one for SA_SIGINFO deliveries (also known as RT |
| 87 | // signals). |
| 88 | // |
| 89 | // In theory, so long as we get the arguments to the handler function |
| 90 | // right, it doesn't matter what the exact layout of the rest of the |
| 91 | // frame is. Unfortunately, things like gcc's exception unwinding |
| 92 | // make assumptions about the locations of various parts of the frame, |
| 93 | // so we need to duplicate it exactly. |
| 94 | |
sewardj | e1c444e | 2005-07-08 18:28:40 +0000 | [diff] [blame] | 95 | /* Structure containing bits of information that we want to save |
| 96 | on signal delivery. */ |
| 97 | struct vg_sig_private { |
cerion | 85665ca | 2005-06-20 15:51:07 +0000 | [diff] [blame] | 98 | UInt magicPI; |
sewardj | e1c444e | 2005-07-08 18:28:40 +0000 | [diff] [blame] | 99 | UInt sigNo_private; |
sewardj | 7cf4e6b | 2008-05-01 20:24:26 +0000 | [diff] [blame] | 100 | VexGuestPPC32State vex_shadow1; |
| 101 | VexGuestPPC32State vex_shadow2; |
cerion | 85665ca | 2005-06-20 15:51:07 +0000 | [diff] [blame] | 102 | }; |
| 103 | |
sewardj | e1c444e | 2005-07-08 18:28:40 +0000 | [diff] [blame] | 104 | /* Structure put on stack for signal handlers with SA_SIGINFO clear. */ |
| 105 | struct nonrt_sigframe { |
| 106 | UInt gap1[16]; |
| 107 | struct vki_sigcontext sigcontext; |
| 108 | struct vki_mcontext mcontext; |
| 109 | struct vg_sig_private priv; |
florian | 7b7d594 | 2014-12-19 20:29:22 +0000 | [diff] [blame] | 110 | unsigned char abigap[224]; // unused |
sewardj | e1c444e | 2005-07-08 18:28:40 +0000 | [diff] [blame] | 111 | }; |
| 112 | |
| 113 | /* Structure put on stack for signal handlers with SA_SIGINFO set. */ |
| 114 | struct rt_sigframe { |
| 115 | UInt gap1[20]; |
| 116 | vki_siginfo_t siginfo; |
| 117 | struct vki_ucontext ucontext; |
| 118 | struct vg_sig_private priv; |
florian | 7b7d594 | 2014-12-19 20:29:22 +0000 | [diff] [blame] | 119 | unsigned char abigap[224]; // unused |
sewardj | e1c444e | 2005-07-08 18:28:40 +0000 | [diff] [blame] | 120 | }; |
| 121 | |
| 122 | #define SET_SIGNAL_LR(zztst, zzval) \ |
| 123 | do { tst->arch.vex.guest_LR = (zzval); \ |
| 124 | VG_TRACK( post_reg_write, Vg_CoreSignal, tst->tid, \ |
| 125 | offsetof(VexGuestPPC32State,guest_LR), \ |
| 126 | sizeof(UWord) ); \ |
| 127 | } while (0) |
| 128 | |
| 129 | #define SET_SIGNAL_GPR(zztst, zzn, zzval) \ |
| 130 | do { tst->arch.vex.guest_GPR##zzn = (zzval); \ |
| 131 | VG_TRACK( post_reg_write, Vg_CoreSignal, tst->tid, \ |
| 132 | offsetof(VexGuestPPC32State,guest_GPR##zzn), \ |
| 133 | sizeof(UWord) ); \ |
| 134 | } while (0) |
| 135 | |
| 136 | |
| 137 | static |
| 138 | void stack_mcontext ( struct vki_mcontext *mc, |
| 139 | ThreadState* tst, |
sewardj | a594026 | 2007-09-10 16:28:38 +0000 | [diff] [blame] | 140 | Bool use_rt_sigreturn, |
sewardj | e1c444e | 2005-07-08 18:28:40 +0000 | [diff] [blame] | 141 | UInt fault_addr ) |
cerion | 85665ca | 2005-06-20 15:51:07 +0000 | [diff] [blame] | 142 | { |
sewardj | e1c444e | 2005-07-08 18:28:40 +0000 | [diff] [blame] | 143 | VG_TRACK( pre_mem_write, Vg_CoreSignal, tst->tid, "signal frame mcontext", |
| 144 | (Addr)mc, sizeof(struct vki_pt_regs) ); |
cerion | 85665ca | 2005-06-20 15:51:07 +0000 | [diff] [blame] | 145 | |
sewardj | e1c444e | 2005-07-08 18:28:40 +0000 | [diff] [blame] | 146 | # define DO(gpr) mc->mc_gregs[VKI_PT_R0+gpr] = tst->arch.vex.guest_GPR##gpr |
| 147 | DO(0); DO(1); DO(2); DO(3); DO(4); DO(5); DO(6); DO(7); |
| 148 | DO(8); DO(9); DO(10); DO(11); DO(12); DO(13); DO(14); DO(15); |
| 149 | DO(16); DO(17); DO(18); DO(19); DO(20); DO(21); DO(22); DO(23); |
| 150 | DO(24); DO(25); DO(26); DO(27); DO(28); DO(29); DO(30); DO(31); |
| 151 | # undef DO |
cerion | 85665ca | 2005-06-20 15:51:07 +0000 | [diff] [blame] | 152 | |
sewardj | e1c444e | 2005-07-08 18:28:40 +0000 | [diff] [blame] | 153 | mc->mc_gregs[VKI_PT_NIP] = tst->arch.vex.guest_CIA; |
| 154 | mc->mc_gregs[VKI_PT_MSR] = 0xf032; /* pretty arbitrary */ |
| 155 | mc->mc_gregs[VKI_PT_ORIG_R3] = tst->arch.vex.guest_GPR3; |
| 156 | mc->mc_gregs[VKI_PT_CTR] = tst->arch.vex.guest_CTR; |
| 157 | mc->mc_gregs[VKI_PT_LNK] = tst->arch.vex.guest_LR; |
sewardj | 463b3d9 | 2005-07-18 11:41:15 +0000 | [diff] [blame] | 158 | mc->mc_gregs[VKI_PT_XER] = LibVEX_GuestPPC32_get_XER(&tst->arch.vex); |
| 159 | mc->mc_gregs[VKI_PT_CCR] = LibVEX_GuestPPC32_get_CR(&tst->arch.vex); |
sewardj | e1c444e | 2005-07-08 18:28:40 +0000 | [diff] [blame] | 160 | mc->mc_gregs[VKI_PT_MQ] = 0; |
| 161 | mc->mc_gregs[VKI_PT_TRAP] = 0; |
| 162 | mc->mc_gregs[VKI_PT_DAR] = fault_addr; |
| 163 | mc->mc_gregs[VKI_PT_DSISR] = 0; |
| 164 | mc->mc_gregs[VKI_PT_RESULT] = 0; |
| 165 | VG_TRACK( post_mem_write, Vg_CoreSignal, tst->tid, |
| 166 | (Addr)mc, sizeof(struct vki_pt_regs) ); |
cerion | 85665ca | 2005-06-20 15:51:07 +0000 | [diff] [blame] | 167 | |
sewardj | e1c444e | 2005-07-08 18:28:40 +0000 | [diff] [blame] | 168 | /* XXX should do FP and vector regs */ |
cerion | 85665ca | 2005-06-20 15:51:07 +0000 | [diff] [blame] | 169 | |
sewardj | e1c444e | 2005-07-08 18:28:40 +0000 | [diff] [blame] | 170 | /* set up signal return trampoline */ |
sewardj | a594026 | 2007-09-10 16:28:38 +0000 | [diff] [blame] | 171 | /* NB. 5 Sept 07. mc->mc_pad[0..1] used to contain a the code to |
| 172 | which the signal handler returns, and it just did sys_sigreturn |
| 173 | or sys_rt_sigreturn. But this doesn't work if the stack is |
| 174 | non-executable, and it isn't consistent with the x86-linux and |
| 175 | amd64-linux scheme for removing the stack frame. So instead be |
| 176 | consistent and use a stub in m_trampoline. Then it doesn't |
| 177 | matter whether or not the (guest) stack is executable. This |
| 178 | fixes #149519 and #145837. */ |
sewardj | e1c444e | 2005-07-08 18:28:40 +0000 | [diff] [blame] | 179 | VG_TRACK(pre_mem_write, Vg_CoreSignal, tst->tid, "signal frame mcontext", |
| 180 | (Addr)&mc->mc_pad, sizeof(mc->mc_pad)); |
sewardj | a594026 | 2007-09-10 16:28:38 +0000 | [diff] [blame] | 181 | mc->mc_pad[0] = 0; /* invalid */ |
| 182 | mc->mc_pad[1] = 0; /* invalid */ |
sewardj | e1c444e | 2005-07-08 18:28:40 +0000 | [diff] [blame] | 183 | VG_TRACK( post_mem_write, Vg_CoreSignal, tst->tid, |
| 184 | (Addr)&mc->mc_pad, sizeof(mc->mc_pad) ); |
| 185 | /* invalidate any translation of this area */ |
florian | ddd61ff | 2015-01-04 17:20:45 +0000 | [diff] [blame] | 186 | VG_(discard_translations)( (Addr)&mc->mc_pad, |
sewardj | a48a493 | 2005-09-29 11:09:56 +0000 | [diff] [blame] | 187 | sizeof(mc->mc_pad), "stack_mcontext" ); |
cerion | 85665ca | 2005-06-20 15:51:07 +0000 | [diff] [blame] | 188 | |
sewardj | e1c444e | 2005-07-08 18:28:40 +0000 | [diff] [blame] | 189 | /* set the signal handler to return to the trampoline */ |
sewardj | a594026 | 2007-09-10 16:28:38 +0000 | [diff] [blame] | 190 | SET_SIGNAL_LR(tst, (Addr)(use_rt_sigreturn |
| 191 | ? (Addr)&VG_(ppc32_linux_SUBST_FOR_rt_sigreturn) |
| 192 | : (Addr)&VG_(ppc32_linux_SUBST_FOR_sigreturn) |
| 193 | )); |
sewardj | e1c444e | 2005-07-08 18:28:40 +0000 | [diff] [blame] | 194 | } |
cerion | 85665ca | 2005-06-20 15:51:07 +0000 | [diff] [blame] | 195 | |
sewardj | e1c444e | 2005-07-08 18:28:40 +0000 | [diff] [blame] | 196 | //:: /* Valgrind-specific parts of the signal frame */ |
| 197 | //:: struct vg_sigframe |
| 198 | //:: { |
| 199 | //:: /* Sanity check word. */ |
| 200 | //:: UInt magicPI; |
| 201 | //:: |
| 202 | //:: UInt handlerflags; /* flags for signal handler */ |
| 203 | //:: |
| 204 | //:: |
| 205 | //:: /* Safely-saved version of sigNo, as described above. */ |
| 206 | //:: Int sigNo_private; |
| 207 | //:: |
| 208 | //:: /* XXX This is wrong. Surely we should store the shadow values |
| 209 | //:: into the shadow memory behind the actual values? */ |
| 210 | //:: VexGuestPPC32State vex_shadow; |
| 211 | //:: |
| 212 | //:: /* HACK ALERT */ |
| 213 | //:: VexGuestPPC32State vex; |
| 214 | //:: /* end HACK ALERT */ |
| 215 | //:: |
| 216 | //:: /* saved signal mask to be restored when handler returns */ |
| 217 | //:: vki_sigset_t mask; |
| 218 | //:: |
| 219 | //:: /* Sanity check word. Is the highest-addressed word; do not |
| 220 | //:: move!*/ |
| 221 | //:: UInt magicE; |
| 222 | //:: }; |
| 223 | //:: |
| 224 | //:: struct sigframe |
| 225 | //:: { |
| 226 | //:: /* Sig handler's return address */ |
| 227 | //:: Addr retaddr; |
| 228 | //:: Int sigNo; |
| 229 | //:: |
| 230 | //:: struct vki_sigcontext sigContext; |
| 231 | //:: //.. struct _vki_fpstate fpstate; |
| 232 | //:: |
| 233 | //:: struct vg_sigframe vg; |
| 234 | //:: }; |
| 235 | //:: |
| 236 | //:: struct rt_sigframe |
| 237 | //:: { |
| 238 | //:: /* Sig handler's return address */ |
| 239 | //:: Addr retaddr; |
| 240 | //:: Int sigNo; |
| 241 | //:: |
| 242 | //:: /* ptr to siginfo_t. */ |
| 243 | //:: Addr psigInfo; |
| 244 | //:: |
| 245 | //:: /* ptr to ucontext */ |
| 246 | //:: Addr puContext; |
| 247 | //:: /* pointed to by psigInfo */ |
| 248 | //:: vki_siginfo_t sigInfo; |
| 249 | //:: |
| 250 | //:: /* pointed to by puContext */ |
| 251 | //:: struct vki_ucontext uContext; |
| 252 | //:: //.. struct _vki_fpstate fpstate; |
| 253 | //:: |
| 254 | //:: struct vg_sigframe vg; |
| 255 | //:: }; |
cerion | 85665ca | 2005-06-20 15:51:07 +0000 | [diff] [blame] | 256 | |
| 257 | |
| 258 | //:: /*------------------------------------------------------------*/ |
| 259 | //:: /*--- Signal operations ---*/ |
| 260 | //:: /*------------------------------------------------------------*/ |
| 261 | //:: |
| 262 | //:: /* |
| 263 | //:: Great gobs of FP state conversion taken wholesale from |
| 264 | //:: linux/arch/i386/kernel/i387.c |
| 265 | //:: */ |
| 266 | //:: |
| 267 | //:: /* |
| 268 | //:: * FXSR floating point environment conversions. |
| 269 | //:: */ |
| 270 | //:: #define X86_FXSR_MAGIC 0x0000 |
| 271 | //:: |
| 272 | //:: /* |
| 273 | //:: * FPU tag word conversions. |
| 274 | //:: */ |
| 275 | //:: |
| 276 | //:: static inline unsigned short twd_i387_to_fxsr( unsigned short twd ) |
| 277 | //:: { |
| 278 | //:: unsigned int tmp; /* to avoid 16 bit prefixes in the code */ |
| 279 | //:: |
| 280 | //:: /* Transform each pair of bits into 01 (valid) or 00 (empty) */ |
| 281 | //:: tmp = ~twd; |
| 282 | //:: tmp = (tmp | (tmp>>1)) & 0x5555; /* 0V0V0V0V0V0V0V0V */ |
| 283 | //:: /* and move the valid bits to the lower byte. */ |
| 284 | //:: tmp = (tmp | (tmp >> 1)) & 0x3333; /* 00VV00VV00VV00VV */ |
| 285 | //:: tmp = (tmp | (tmp >> 2)) & 0x0f0f; /* 0000VVVV0000VVVV */ |
| 286 | //:: tmp = (tmp | (tmp >> 4)) & 0x00ff; /* 00000000VVVVVVVV */ |
| 287 | //:: return tmp; |
| 288 | //:: } |
| 289 | //:: |
| 290 | //:: static unsigned long twd_fxsr_to_i387( const struct i387_fxsave_struct *fxsave ) |
| 291 | //:: { |
| 292 | //:: struct _vki_fpxreg *st = NULL; |
| 293 | //:: unsigned long twd = (unsigned long) fxsave->twd; |
| 294 | //:: unsigned long tag; |
| 295 | //:: unsigned long ret = 0xffff0000u; |
| 296 | //:: int i; |
| 297 | //:: |
| 298 | //:: #define FPREG_ADDR(f, n) ((char *)&(f)->st_space + (n) * 16); |
| 299 | //:: |
| 300 | //:: for ( i = 0 ; i < 8 ; i++ ) { |
| 301 | //:: if ( twd & 0x1 ) { |
| 302 | //:: st = (struct _vki_fpxreg *) FPREG_ADDR( fxsave, i ); |
| 303 | //:: |
| 304 | //:: switch ( st->exponent & 0x7fff ) { |
| 305 | //:: case 0x7fff: |
| 306 | //:: tag = 2; /* Special */ |
| 307 | //:: break; |
| 308 | //:: case 0x0000: |
| 309 | //:: if ( !st->significand[0] && |
| 310 | //:: !st->significand[1] && |
| 311 | //:: !st->significand[2] && |
| 312 | //:: !st->significand[3] ) { |
| 313 | //:: tag = 1; /* Zero */ |
| 314 | //:: } else { |
| 315 | //:: tag = 2; /* Special */ |
| 316 | //:: } |
| 317 | //:: break; |
| 318 | //:: default: |
| 319 | //:: if ( st->significand[3] & 0x8000 ) { |
| 320 | //:: tag = 0; /* Valid */ |
| 321 | //:: } else { |
| 322 | //:: tag = 2; /* Special */ |
| 323 | //:: } |
| 324 | //:: break; |
| 325 | //:: } |
| 326 | //:: } else { |
| 327 | //:: tag = 3; /* Empty */ |
| 328 | //:: } |
| 329 | //:: ret |= (tag << (2 * i)); |
| 330 | //:: twd = twd >> 1; |
| 331 | //:: } |
| 332 | //:: return ret; |
| 333 | //:: } |
| 334 | //:: |
| 335 | //:: static void convert_fxsr_to_user( struct _vki_fpstate *buf, |
| 336 | //:: const struct i387_fxsave_struct *fxsave ) |
| 337 | //:: { |
| 338 | //:: unsigned long env[7]; |
| 339 | //:: struct _vki_fpreg *to; |
| 340 | //:: struct _vki_fpxreg *from; |
| 341 | //:: int i; |
| 342 | //:: |
| 343 | //:: env[0] = (unsigned long)fxsave->cwd | 0xffff0000ul; |
| 344 | //:: env[1] = (unsigned long)fxsave->swd | 0xffff0000ul; |
| 345 | //:: env[2] = twd_fxsr_to_i387(fxsave); |
| 346 | //:: env[3] = fxsave->fip; |
| 347 | //:: env[4] = fxsave->fcs | ((unsigned long)fxsave->fop << 16); |
| 348 | //:: env[5] = fxsave->foo; |
| 349 | //:: env[6] = fxsave->fos; |
| 350 | //:: |
| 351 | //:: VG_(memcpy)(buf, env, 7 * sizeof(unsigned long)); |
| 352 | //:: |
| 353 | //:: to = &buf->_st[0]; |
| 354 | //:: from = (struct _vki_fpxreg *) &fxsave->st_space[0]; |
| 355 | //:: for ( i = 0 ; i < 8 ; i++, to++, from++ ) { |
| 356 | //:: unsigned long __user *t = (unsigned long __user *)to; |
| 357 | //:: unsigned long *f = (unsigned long *)from; |
| 358 | //:: |
| 359 | //:: t[0] = f[0]; |
| 360 | //:: t[1] = f[1]; |
| 361 | //:: to->exponent = from->exponent; |
| 362 | //:: } |
| 363 | //:: } |
| 364 | //:: |
| 365 | //:: static void convert_fxsr_from_user( struct i387_fxsave_struct *fxsave, |
| 366 | //:: const struct _vki_fpstate *buf ) |
| 367 | //:: { |
| 368 | //:: unsigned long env[7]; |
| 369 | //:: struct _vki_fpxreg *to; |
| 370 | //:: const struct _vki_fpreg *from; |
| 371 | //:: int i; |
| 372 | //:: |
| 373 | //:: VG_(memcpy)(env, buf, 7 * sizeof(long)); |
| 374 | //:: |
| 375 | //:: fxsave->cwd = (unsigned short)(env[0] & 0xffff); |
| 376 | //:: fxsave->swd = (unsigned short)(env[1] & 0xffff); |
| 377 | //:: fxsave->twd = twd_i387_to_fxsr((unsigned short)(env[2] & 0xffff)); |
| 378 | //:: fxsave->fip = env[3]; |
| 379 | //:: fxsave->fop = (unsigned short)((env[4] & 0xffff0000ul) >> 16); |
| 380 | //:: fxsave->fcs = (env[4] & 0xffff); |
| 381 | //:: fxsave->foo = env[5]; |
| 382 | //:: fxsave->fos = env[6]; |
| 383 | //:: |
| 384 | //:: to = (struct _vki_fpxreg *) &fxsave->st_space[0]; |
| 385 | //:: from = &buf->_st[0]; |
| 386 | //:: for ( i = 0 ; i < 8 ; i++, to++, from++ ) { |
| 387 | //:: unsigned long *t = (unsigned long *)to; |
| 388 | //:: unsigned long __user *f = (unsigned long __user *)from; |
| 389 | //:: |
| 390 | //:: t[0] = f[0]; |
| 391 | //:: t[1] = f[1]; |
| 392 | //:: to->exponent = from->exponent; |
| 393 | //:: } |
| 394 | //:: } |
| 395 | //:: |
| 396 | //:: static inline void save_i387_fsave( arch_thread_t *regs, struct _vki_fpstate *buf ) |
| 397 | //:: { |
| 398 | //:: struct i387_fsave_struct *fs = ®s->m_sse.fsave; |
| 399 | //:: |
| 400 | //:: fs->status = fs->swd; |
| 401 | //:: VG_(memcpy)(buf, fs, sizeof(*fs)); |
| 402 | //:: } |
| 403 | //:: |
| 404 | //:: static void save_i387_fxsave( arch_thread_t *regs, struct _vki_fpstate *buf ) |
| 405 | //:: { |
| 406 | //:: const struct i387_fxsave_struct *fx = ®s->m_sse.fxsave; |
| 407 | //:: convert_fxsr_to_user( buf, fx ); |
| 408 | //:: |
| 409 | //:: buf->status = fx->swd; |
| 410 | //:: buf->magic = X86_FXSR_MAGIC; |
| 411 | //:: VG_(memcpy)(buf->_fxsr_env, fx, sizeof(struct i387_fxsave_struct)); |
| 412 | //:: } |
| 413 | //:: |
| 414 | //:: static void save_i387( arch_thread_t *regs, struct _vki_fpstate *buf ) |
| 415 | //:: { |
| 416 | //:: if ( VG_(have_ssestate) ) |
| 417 | //:: save_i387_fxsave( regs, buf ); |
| 418 | //:: else |
| 419 | //:: save_i387_fsave( regs, buf ); |
| 420 | //:: } |
| 421 | //:: |
| 422 | //:: static inline void restore_i387_fsave( arch_thread_t *regs, const struct _vki_fpstate __user *buf ) |
| 423 | //:: { |
| 424 | //:: VG_(memcpy)( ®s->m_sse.fsave, buf, sizeof(struct i387_fsave_struct) ); |
| 425 | //:: } |
| 426 | //:: |
| 427 | //:: static void restore_i387_fxsave( arch_thread_t *regs, const struct _vki_fpstate __user *buf ) |
| 428 | //:: { |
| 429 | //:: VG_(memcpy)(®s->m_sse.fxsave, &buf->_fxsr_env[0], |
| 430 | //:: sizeof(struct i387_fxsave_struct) ); |
| 431 | //:: /* mxcsr reserved bits must be masked to zero for security reasons */ |
| 432 | //:: regs->m_sse.fxsave.mxcsr &= 0xffbf; |
| 433 | //:: convert_fxsr_from_user( ®s->m_sse.fxsave, buf ); |
| 434 | //:: } |
| 435 | //:: |
| 436 | //:: static void restore_i387( arch_thread_t *regs, const struct _vki_fpstate __user *buf ) |
| 437 | //:: { |
| 438 | //:: if ( VG_(have_ssestate) ) { |
| 439 | //:: restore_i387_fxsave( regs, buf ); |
| 440 | //:: } else { |
| 441 | //:: restore_i387_fsave( regs, buf ); |
| 442 | //:: } |
| 443 | //:: } |
| 444 | |
| 445 | |
| 446 | |
| 447 | |
| 448 | /*------------------------------------------------------------*/ |
| 449 | /*--- Creating signal frames ---*/ |
| 450 | /*------------------------------------------------------------*/ |
| 451 | |
| 452 | //.. /* Create a plausible-looking sigcontext from the thread's |
| 453 | //.. Vex guest state. NOTE: does not fill in the FP or SSE |
| 454 | //.. bits of sigcontext at the moment. |
| 455 | //.. */ |
| 456 | //.. static |
| 457 | //.. void synth_ucontext(ThreadId tid, const vki_siginfo_t *si, |
| 458 | //.. const vki_sigset_t *set, struct vki_ucontext *uc) |
| 459 | //.. { |
| 460 | //.. ThreadState *tst = VG_(get_ThreadState)(tid); |
| 461 | //.. struct vki_sigcontext *sc = &uc->uc_mcontext; |
| 462 | //.. |
| 463 | //.. VG_(memset)(uc, 0, sizeof(*uc)); |
| 464 | //.. |
| 465 | //.. uc->uc_flags = 0; |
| 466 | //.. uc->uc_link = 0; |
| 467 | //.. uc->uc_sigmask = *set; |
| 468 | //.. uc->uc_stack = tst->altstack; |
| 469 | //.. sc->fpstate = fpstate; |
| 470 | //.. |
| 471 | //.. // FIXME: save_i387(&tst->arch, fpstate); |
| 472 | //.. |
| 473 | //.. # define SC2(reg,REG) sc->reg = tst->arch.vex.guest_##REG |
| 474 | //.. SC2(gs,GS); |
| 475 | //.. SC2(fs,FS); |
| 476 | //.. SC2(es,ES); |
| 477 | //.. SC2(ds,DS); |
| 478 | //.. |
| 479 | //.. SC2(edi,EDI); |
| 480 | //.. SC2(esi,ESI); |
| 481 | //.. SC2(ebp,EBP); |
| 482 | //.. SC2(esp,ESP); |
| 483 | //.. SC2(ebx,EBX); |
| 484 | //.. SC2(edx,EDX); |
| 485 | //.. SC2(ecx,ECX); |
| 486 | //.. SC2(eax,EAX); |
| 487 | //.. |
| 488 | //.. SC2(eip,EIP); |
| 489 | //.. SC2(cs,CS); |
| 490 | //.. sc->eflags = LibVEX_GuestX86_get_eflags(&tst->arch.vex); |
| 491 | //.. SC2(ss,SS); |
| 492 | //.. /* XXX esp_at_signal */ |
| 493 | //.. /* XXX trapno */ |
| 494 | //.. /* XXX err */ |
| 495 | //.. # undef SC2 |
| 496 | //.. |
| 497 | //.. sc->cr2 = (UInt)si->_sifields._sigfault._addr; |
| 498 | //.. } |
| 499 | /* |
| 500 | //.. #define SET_SIGNAL_ESP(zztid, zzval) \ |
| 501 | //.. SET_THREAD_REG(zztid, zzval, STACK_PTR, post_reg_write, \ |
njn | af839f5 | 2005-06-23 03:27:57 +0000 | [diff] [blame] | 502 | //.. Vg_CoreSignal, zztid, VG_O_STACK_PTR, sizeof(Addr)) |
cerion | 85665ca | 2005-06-20 15:51:07 +0000 | [diff] [blame] | 503 | */ |
cerion | 85665ca | 2005-06-20 15:51:07 +0000 | [diff] [blame] | 504 | |
| 505 | |
| 506 | //.. /* Build the Valgrind-specific part of a signal frame. */ |
| 507 | //.. |
| 508 | //.. static void build_vg_sigframe(struct vg_sigframe *frame, |
| 509 | //.. ThreadState *tst, |
| 510 | //.. const vki_sigset_t *mask, |
| 511 | //.. UInt flags, |
| 512 | //.. Int sigNo) |
| 513 | //.. { |
| 514 | //.. frame->sigNo_private = sigNo; |
| 515 | //.. frame->magicPI = 0x31415927; |
| 516 | //.. frame->vex_shadow = tst->arch.vex_shadow; |
| 517 | //.. /* HACK ALERT */ |
| 518 | //.. frame->vex = tst->arch.vex; |
| 519 | //.. /* end HACK ALERT */ |
| 520 | //.. frame->mask = tst->sig_mask; |
| 521 | //.. frame->handlerflags = flags; |
| 522 | //.. frame->magicE = 0x27182818; |
| 523 | //.. } |
| 524 | |
| 525 | |
| 526 | //.. static Addr build_sigframe(ThreadState *tst, |
| 527 | //.. Addr esp_top_of_frame, |
| 528 | //.. const vki_siginfo_t *siginfo, |
| 529 | //.. void *handler, UInt flags, |
| 530 | //.. const vki_sigset_t *mask, |
| 531 | //.. void *restorer) |
| 532 | //.. { |
| 533 | //.. struct sigframe *frame; |
| 534 | //.. Addr esp = esp_top_of_frame; |
| 535 | //.. Int sigNo = siginfo->si_signo; |
| 536 | //.. struct vki_ucontext uc; |
| 537 | //.. |
| 538 | //.. vg_assert((flags & VKI_SA_SIGINFO) == 0); |
| 539 | //.. |
| 540 | //.. esp -= sizeof(*frame); |
| 541 | //.. esp = ROUNDDN(esp, 16); |
| 542 | //.. frame = (struct sigframe *)esp; |
| 543 | //.. |
| 544 | //.. if (!extend(tst, esp, sizeof(*frame))) |
| 545 | //.. return esp_top_of_frame; |
| 546 | //.. |
| 547 | //.. /* retaddr, sigNo, siguContext fields are to be written */ |
| 548 | //.. VG_TRACK( pre_mem_write, Vg_CoreSignal, tst->tid, "signal handler frame", |
| 549 | //.. esp, offsetof(struct sigframe, vg) ); |
| 550 | //.. |
| 551 | //.. frame->sigNo = sigNo; |
| 552 | //.. |
| 553 | //.. if (flags & VKI_SA_RESTORER) |
| 554 | //.. frame->retaddr = (Addr)restorer; |
| 555 | //.. else |
| 556 | //.. frame->retaddr |
| 557 | //.. = VG_(client_trampoline_code)+VG_(tramp_sigreturn_offset); |
| 558 | //.. |
| 559 | //.. synth_ucontext(tst->tid, siginfo, mask, &uc, &frame->fpstate); |
| 560 | //.. |
| 561 | //.. VG_(memcpy)(&frame->sigContext, &uc.uc_mcontext, |
| 562 | //.. sizeof(struct vki_sigcontext)); |
| 563 | //.. frame->sigContext.oldmask = mask->sig[0]; |
| 564 | //.. |
| 565 | //.. VG_TRACK( post_mem_write, Vg_CoreSignal, tst->tid, |
| 566 | //.. esp, offsetof(struct sigframe, vg) ); |
| 567 | //.. |
| 568 | //.. build_vg_sigframe(&frame->vg, tst, mask, flags, sigNo); |
| 569 | //.. |
| 570 | //.. return esp; |
| 571 | //.. } |
| 572 | |
| 573 | |
| 574 | //.. static Addr build_rt_sigframe(ThreadState *tst, |
| 575 | //.. Addr esp_top_of_frame, |
| 576 | //.. const vki_siginfo_t *siginfo, |
| 577 | //.. void *handler, UInt flags, |
| 578 | //.. const vki_sigset_t *mask, |
| 579 | //.. void *restorer) |
| 580 | //.. { |
| 581 | //.. struct rt_sigframe *frame; |
| 582 | //.. Addr esp = esp_top_of_frame; |
| 583 | //.. Int sigNo = siginfo->si_signo; |
| 584 | //.. |
| 585 | //.. vg_assert((flags & VKI_SA_SIGINFO) != 0); |
| 586 | //.. |
| 587 | //.. esp -= sizeof(*frame); |
| 588 | //.. esp = ROUNDDN(esp, 16); |
| 589 | //.. frame = (struct rt_sigframe *)esp; |
| 590 | //.. |
| 591 | //.. if (!extend(tst, esp, sizeof(*frame))) |
| 592 | //.. return esp_top_of_frame; |
| 593 | //.. |
| 594 | //.. /* retaddr, sigNo, pSiginfo, puContext fields are to be written */ |
| 595 | //.. VG_TRACK( pre_mem_write, Vg_CoreSignal, tst->tid, "rt signal handler frame", |
| 596 | //.. esp, offsetof(struct rt_sigframe, vg) ); |
| 597 | //.. |
| 598 | //.. frame->sigNo = sigNo; |
| 599 | //.. |
| 600 | //.. if (flags & VKI_SA_RESTORER) |
| 601 | //.. frame->retaddr = (Addr)restorer; |
| 602 | //.. else |
| 603 | //.. frame->retaddr |
| 604 | //.. = VG_(client_trampoline_code)+VG_(tramp_rt_sigreturn_offset); |
| 605 | //.. |
| 606 | //.. frame->psigInfo = (Addr)&frame->sigInfo; |
| 607 | //.. frame->puContext = (Addr)&frame->uContext; |
| 608 | //.. VG_(memcpy)(&frame->sigInfo, siginfo, sizeof(vki_siginfo_t)); |
| 609 | //.. |
| 610 | //.. /* SIGILL defines addr to be the faulting address */ |
| 611 | //.. if (sigNo == VKI_SIGILL && siginfo->si_code > 0) |
| 612 | //.. frame->sigInfo._sifields._sigfault._addr |
| 613 | //.. = (void*)tst->arch.vex.guest_CIA; |
| 614 | //.. |
| 615 | //.. synth_ucontext(tst->tid, siginfo, mask, &frame->uContext, &frame->fpstate); |
| 616 | //.. |
| 617 | //.. VG_TRACK( post_mem_write, Vg_CoreSignal, tst->tid, |
| 618 | //.. esp, offsetof(struct rt_sigframe, vg) ); |
| 619 | //.. |
| 620 | //.. build_vg_sigframe(&frame->vg, tst, mask, flags, sigNo); |
| 621 | //.. |
| 622 | //.. return esp; |
| 623 | //.. } |
| 624 | |
| 625 | |
| 626 | /* EXPORTED */ |
| 627 | void VG_(sigframe_create)( ThreadId tid, |
| 628 | Addr sp_top_of_frame, |
| 629 | const vki_siginfo_t *siginfo, |
tom | adacaf9 | 2007-12-21 10:24:24 +0000 | [diff] [blame] | 630 | const struct vki_ucontext *siguc, |
cerion | 85665ca | 2005-06-20 15:51:07 +0000 | [diff] [blame] | 631 | void *handler, |
| 632 | UInt flags, |
| 633 | const vki_sigset_t *mask, |
| 634 | void *restorer ) |
| 635 | { |
sewardj | e1c444e | 2005-07-08 18:28:40 +0000 | [diff] [blame] | 636 | struct vg_sig_private *priv; |
| 637 | Addr sp; |
| 638 | ThreadState *tst; |
| 639 | Int sigNo = siginfo->si_signo; |
| 640 | Addr faultaddr; |
| 641 | |
| 642 | /* Stack must be 16-byte aligned */ |
| 643 | sp_top_of_frame &= ~0xf; |
| 644 | |
| 645 | if (flags & VKI_SA_SIGINFO) { |
| 646 | sp = sp_top_of_frame - sizeof(struct rt_sigframe); |
| 647 | } else { |
| 648 | sp = sp_top_of_frame - sizeof(struct nonrt_sigframe); |
| 649 | } |
| 650 | |
| 651 | tst = VG_(get_ThreadState)(tid); |
| 652 | |
florian | 7d4a28b | 2015-04-23 15:20:00 +0000 | [diff] [blame^] | 653 | if (! ML_(sf_maybe_extend_stack)(tst, sp, sp_top_of_frame - sp, flags)) |
sewardj | e1c444e | 2005-07-08 18:28:40 +0000 | [diff] [blame] | 654 | return; |
| 655 | |
| 656 | vg_assert(VG_IS_16_ALIGNED(sp)); |
| 657 | |
| 658 | /* Set up the stack chain pointer */ |
| 659 | VG_TRACK( pre_mem_write, Vg_CoreSignal, tid, "signal handler frame", |
| 660 | sp, sizeof(UWord) ); |
| 661 | *(Addr *)sp = tst->arch.vex.guest_GPR1; |
| 662 | VG_TRACK( post_mem_write, Vg_CoreSignal, tid, |
| 663 | sp, sizeof(UWord) ); |
| 664 | |
| 665 | faultaddr = (Addr)siginfo->_sifields._sigfault._addr; |
| 666 | if (sigNo == VKI_SIGILL && siginfo->si_code > 0) |
| 667 | faultaddr = tst->arch.vex.guest_CIA; |
| 668 | |
| 669 | if (flags & VKI_SA_SIGINFO) { |
| 670 | struct rt_sigframe *frame = (struct rt_sigframe *) sp; |
| 671 | struct vki_ucontext *ucp = &frame->ucontext; |
| 672 | |
| 673 | VG_TRACK( pre_mem_write, Vg_CoreSignal, tid, "signal frame siginfo", |
| 674 | (Addr)&frame->siginfo, sizeof(frame->siginfo) ); |
| 675 | VG_(memcpy)(&frame->siginfo, siginfo, sizeof(*siginfo)); |
| 676 | VG_TRACK( post_mem_write, Vg_CoreSignal, tid, |
| 677 | (Addr)&frame->siginfo, sizeof(frame->siginfo) ); |
| 678 | |
| 679 | VG_TRACK( pre_mem_write, Vg_CoreSignal, tid, "signal frame ucontext", |
| 680 | (Addr)ucp, offsetof(struct vki_ucontext, uc_pad) ); |
| 681 | ucp->uc_flags = 0; |
| 682 | ucp->uc_link = 0; |
| 683 | ucp->uc_stack = tst->altstack; |
| 684 | VG_TRACK( post_mem_write, Vg_CoreSignal, tid, (Addr)ucp, |
| 685 | offsetof(struct vki_ucontext, uc_pad) ); |
| 686 | |
| 687 | VG_TRACK( pre_mem_write, Vg_CoreSignal, tid, "signal frame ucontext", |
| 688 | (Addr)&ucp->uc_regs, |
| 689 | sizeof(ucp->uc_regs) + sizeof(ucp->uc_sigmask) ); |
| 690 | ucp->uc_regs = &ucp->uc_mcontext; |
| 691 | ucp->uc_sigmask = tst->sig_mask; |
| 692 | VG_TRACK( post_mem_write, Vg_CoreSignal, tid, |
| 693 | (Addr)&ucp->uc_regs, |
| 694 | sizeof(ucp->uc_regs) + sizeof(ucp->uc_sigmask) ); |
| 695 | |
sewardj | a594026 | 2007-09-10 16:28:38 +0000 | [diff] [blame] | 696 | stack_mcontext(&ucp->uc_mcontext, tst, True/*use_rt_sigreturn*/, faultaddr); |
sewardj | e1c444e | 2005-07-08 18:28:40 +0000 | [diff] [blame] | 697 | priv = &frame->priv; |
| 698 | |
| 699 | SET_SIGNAL_GPR(tid, 4, (Addr) &frame->siginfo); |
| 700 | SET_SIGNAL_GPR(tid, 5, (Addr) ucp); |
| 701 | /* the kernel sets this, though it doesn't seem to be in the ABI */ |
| 702 | SET_SIGNAL_GPR(tid, 6, (Addr) &frame->siginfo); |
| 703 | |
| 704 | } else { |
| 705 | /* non-RT signal delivery */ |
| 706 | struct nonrt_sigframe *frame = (struct nonrt_sigframe *) sp; |
| 707 | struct vki_sigcontext *scp = &frame->sigcontext; |
| 708 | |
| 709 | VG_TRACK( pre_mem_write, Vg_CoreSignal, tid, "signal frame sigcontext", |
| 710 | (Addr)&scp->_unused[3], sizeof(*scp) - 3 * sizeof(UInt) ); |
| 711 | scp->signal = sigNo; |
| 712 | scp->handler = (Addr) handler; |
| 713 | scp->oldmask = tst->sig_mask.sig[0]; |
| 714 | scp->_unused[3] = tst->sig_mask.sig[1]; |
| 715 | VG_TRACK( post_mem_write, Vg_CoreSignal, tid, |
| 716 | (Addr)&scp->_unused[3], sizeof(*scp) - 3 * sizeof(UInt) ); |
| 717 | |
sewardj | a594026 | 2007-09-10 16:28:38 +0000 | [diff] [blame] | 718 | stack_mcontext(&frame->mcontext, tst, False/*!use_rt_sigreturn*/, faultaddr); |
sewardj | e1c444e | 2005-07-08 18:28:40 +0000 | [diff] [blame] | 719 | priv = &frame->priv; |
| 720 | |
| 721 | SET_SIGNAL_GPR(tid, 4, (Addr) scp); |
| 722 | } |
| 723 | |
| 724 | priv->magicPI = 0x31415927; |
| 725 | priv->sigNo_private = sigNo; |
sewardj | 7cf4e6b | 2008-05-01 20:24:26 +0000 | [diff] [blame] | 726 | priv->vex_shadow1 = tst->arch.vex_shadow1; |
| 727 | priv->vex_shadow2 = tst->arch.vex_shadow2; |
sewardj | e1c444e | 2005-07-08 18:28:40 +0000 | [diff] [blame] | 728 | |
| 729 | SET_SIGNAL_GPR(tid, 1, sp); |
| 730 | SET_SIGNAL_GPR(tid, 3, sigNo); |
| 731 | tst->arch.vex.guest_CIA = (Addr) handler; |
cerion | 85665ca | 2005-06-20 15:51:07 +0000 | [diff] [blame] | 732 | |
| 733 | //.. Addr esp; |
| 734 | //.. ThreadState* tst = VG_(get_ThreadState)(tid); |
| 735 | //.. |
| 736 | //.. if (flags & VKI_SA_SIGINFO) |
| 737 | //.. esp = build_rt_sigframe(tst, esp_top_of_frame, siginfo, |
| 738 | //.. handler, flags, mask, restorer); |
| 739 | //.. else |
| 740 | //.. esp = build_sigframe(tst, esp_top_of_frame, |
| 741 | //.. siginfo, handler, flags, mask, restorer); |
| 742 | //.. |
| 743 | //.. /* Set the thread so it will next run the handler. */ |
| 744 | //.. /* tst->m_esp = esp; */ |
| 745 | //.. SET_SIGNAL_ESP(tid, esp); |
| 746 | //.. |
| 747 | //.. //VG_(printf)("handler = %p\n", handler); |
| 748 | //.. tst->arch.vex.guest_CIA = (Addr) handler; |
| 749 | //.. /* This thread needs to be marked runnable, but we leave that the |
| 750 | //.. caller to do. */ |
sewardj | e1c444e | 2005-07-08 18:28:40 +0000 | [diff] [blame] | 751 | |
| 752 | if (0) |
bart | a0b6b2c | 2008-07-07 06:49:24 +0000 | [diff] [blame] | 753 | VG_(printf)("pushed signal frame; %%R1 now = %#lx, " |
| 754 | "next %%CIA = %#x, status=%d\n", |
sewardj | e1c444e | 2005-07-08 18:28:40 +0000 | [diff] [blame] | 755 | sp, tst->arch.vex.guest_CIA, tst->status); |
cerion | 85665ca | 2005-06-20 15:51:07 +0000 | [diff] [blame] | 756 | } |
| 757 | |
sewardj | e1c444e | 2005-07-08 18:28:40 +0000 | [diff] [blame] | 758 | |
cerion | 85665ca | 2005-06-20 15:51:07 +0000 | [diff] [blame] | 759 | /*------------------------------------------------------------*/ |
| 760 | /*--- Destroying signal frames ---*/ |
| 761 | /*------------------------------------------------------------*/ |
| 762 | |
| 763 | //.. /* Return False and don't do anything, just set the client to take a |
| 764 | //.. segfault, if it looks like the frame is corrupted. */ |
| 765 | //.. static |
| 766 | //.. Bool restore_vg_sigframe ( ThreadState *tst, |
| 767 | //.. struct vg_sigframe *frame, Int *sigNo ) |
| 768 | //.. { |
| 769 | //.. if (frame->magicPI != 0x31415927 || |
| 770 | //.. frame->magicE != 0x27182818) { |
| 771 | //.. VG_(message)(Vg_UserMsg, "Thread %d return signal frame " |
| 772 | //.. "corrupted. Killing process.", |
| 773 | //.. tst->tid); |
| 774 | //.. VG_(set_default_handler)(VKI_SIGSEGV); |
| 775 | //.. VG_(synth_fault)(tst->tid); |
| 776 | //.. *sigNo = VKI_SIGSEGV; |
| 777 | //.. return False; |
| 778 | //.. } |
| 779 | //.. tst->sig_mask = frame->mask; |
| 780 | //.. tst->tmp_sig_mask = frame->mask; |
| 781 | //.. tst->arch.vex_shadow = frame->vex_shadow; |
| 782 | //.. /* HACK ALERT */ |
| 783 | //.. tst->arch.vex = frame->vex; |
| 784 | //.. /* end HACK ALERT */ |
| 785 | //.. *sigNo = frame->sigNo_private; |
| 786 | //.. return True; |
| 787 | //.. } |
| 788 | |
| 789 | //.. static |
| 790 | //.. void restore_sigcontext( ThreadState *tst, |
| 791 | //.. struct vki_sigcontext *sc ) |
| 792 | //.. //.. struct vki_sigcontext *sc, struct _vki_fpstate *fpstate ) |
| 793 | //.. { |
| 794 | //.. tst->arch.vex.guest_EAX = sc->eax; |
| 795 | //.. tst->arch.vex.guest_ECX = sc->ecx; |
| 796 | //.. tst->arch.vex.guest_EDX = sc->edx; |
| 797 | //.. tst->arch.vex.guest_EBX = sc->ebx; |
| 798 | //.. tst->arch.vex.guest_EBP = sc->ebp; |
| 799 | //.. tst->arch.vex.guest_ESP = sc->esp; |
| 800 | //.. tst->arch.vex.guest_ESI = sc->esi; |
| 801 | //.. tst->arch.vex.guest_EDI = sc->edi; |
| 802 | //.. //:: tst->arch.vex.guest_eflags = sc->eflags; |
| 803 | //.. //:: tst->arch.vex.guest_EIP = sc->eip; |
| 804 | //.. |
| 805 | //.. tst->arch.vex.guest_CS = sc->cs; |
| 806 | //.. tst->arch.vex.guest_SS = sc->ss; |
| 807 | //.. tst->arch.vex.guest_DS = sc->ds; |
| 808 | //.. tst->arch.vex.guest_ES = sc->es; |
| 809 | //.. tst->arch.vex.guest_FS = sc->fs; |
| 810 | //.. tst->arch.vex.guest_GS = sc->gs; |
| 811 | //.. |
| 812 | //.. //:: restore_i387(&tst->arch, fpstate); |
| 813 | //.. } |
| 814 | |
| 815 | |
| 816 | //.. static |
| 817 | //.. SizeT restore_sigframe ( ThreadState *tst, |
| 818 | //.. struct sigframe *frame, Int *sigNo ) |
| 819 | //.. { |
| 820 | //.. if (restore_vg_sigframe(tst, &frame->vg, sigNo)) |
| 821 | //.. restore_sigcontext(tst, &frame->sigContext, &frame->fpstate); |
| 822 | //.. return sizeof(*frame); |
| 823 | //.. } |
| 824 | |
| 825 | //.. static |
| 826 | //.. SizeT restore_rt_sigframe ( ThreadState *tst, |
| 827 | //.. struct rt_sigframe *frame, Int *sigNo ) |
| 828 | //.. { |
| 829 | //.. if (restore_vg_sigframe(tst, &frame->vg, sigNo)) |
| 830 | //.. restore_sigcontext(tst, &frame->uContext.uc_mcontext, &frame->fpstate); |
| 831 | //.. return sizeof(*frame); |
| 832 | //.. } |
| 833 | |
| 834 | |
sewardj | e1c444e | 2005-07-08 18:28:40 +0000 | [diff] [blame] | 835 | /* EXPORTED */ |
| 836 | void VG_(sigframe_destroy)( ThreadId tid, Bool isRT ) |
| 837 | { |
| 838 | ThreadState *tst; |
| 839 | struct vg_sig_private *priv; |
| 840 | Addr sp; |
| 841 | UInt frame_size; |
| 842 | struct vki_mcontext *mc; |
| 843 | Int sigNo; |
| 844 | Bool has_siginfo = isRT; |
| 845 | |
| 846 | vg_assert(VG_(is_valid_tid)(tid)); |
| 847 | tst = VG_(get_ThreadState)(tid); |
| 848 | |
| 849 | /* Check that the stack frame looks valid */ |
| 850 | sp = tst->arch.vex.guest_GPR1; |
| 851 | vg_assert(VG_IS_16_ALIGNED(sp)); |
sewardj | 8e73238 | 2005-11-17 13:03:42 +0000 | [diff] [blame] | 852 | /* JRS 17 Nov 05: This code used to check that *sp -- which should |
| 853 | have been set by the stwu at the start of the handler -- points |
| 854 | to just above the frame (ie, the previous frame). However, that |
| 855 | isn't valid when delivering signals on alt stacks. So I removed |
| 856 | it. The frame is still sanity-checked using the priv->magicPI |
| 857 | field. */ |
sewardj | e1c444e | 2005-07-08 18:28:40 +0000 | [diff] [blame] | 858 | |
| 859 | if (has_siginfo) { |
| 860 | struct rt_sigframe *frame = (struct rt_sigframe *)sp; |
sewardj | 8e73238 | 2005-11-17 13:03:42 +0000 | [diff] [blame] | 861 | frame_size = sizeof(*frame); |
sewardj | e1c444e | 2005-07-08 18:28:40 +0000 | [diff] [blame] | 862 | mc = &frame->ucontext.uc_mcontext; |
| 863 | priv = &frame->priv; |
sewardj | 8e73238 | 2005-11-17 13:03:42 +0000 | [diff] [blame] | 864 | vg_assert(priv->magicPI == 0x31415927); |
sewardj | e1c444e | 2005-07-08 18:28:40 +0000 | [diff] [blame] | 865 | tst->sig_mask = frame->ucontext.uc_sigmask; |
| 866 | } else { |
| 867 | struct nonrt_sigframe *frame = (struct nonrt_sigframe *)sp; |
sewardj | 8e73238 | 2005-11-17 13:03:42 +0000 | [diff] [blame] | 868 | frame_size = sizeof(*frame); |
sewardj | e1c444e | 2005-07-08 18:28:40 +0000 | [diff] [blame] | 869 | mc = &frame->mcontext; |
| 870 | priv = &frame->priv; |
sewardj | 8e73238 | 2005-11-17 13:03:42 +0000 | [diff] [blame] | 871 | vg_assert(priv->magicPI == 0x31415927); |
sewardj | e1c444e | 2005-07-08 18:28:40 +0000 | [diff] [blame] | 872 | tst->sig_mask.sig[0] = frame->sigcontext.oldmask; |
| 873 | tst->sig_mask.sig[1] = frame->sigcontext._unused[3]; |
| 874 | } |
| 875 | tst->tmp_sig_mask = tst->sig_mask; |
| 876 | |
sewardj | e1c444e | 2005-07-08 18:28:40 +0000 | [diff] [blame] | 877 | sigNo = priv->sigNo_private; |
| 878 | |
| 879 | # define DO(gpr) tst->arch.vex.guest_GPR##gpr = mc->mc_gregs[VKI_PT_R0+gpr] |
| 880 | DO(0); DO(1); DO(2); DO(3); DO(4); DO(5); DO(6); DO(7); |
| 881 | DO(8); DO(9); DO(10); DO(11); DO(12); DO(13); DO(14); DO(15); |
| 882 | DO(16); DO(17); DO(18); DO(19); DO(20); DO(21); DO(22); DO(23); |
| 883 | DO(24); DO(25); DO(26); DO(27); DO(28); DO(29); DO(30); DO(31); |
| 884 | # undef DO |
| 885 | |
| 886 | tst->arch.vex.guest_CIA = mc->mc_gregs[VKI_PT_NIP]; |
| 887 | |
| 888 | // Umm ... ? (jrs 2005 July 8) |
| 889 | // tst->arch.m_orig_gpr3 = mc->mc_gregs[VKI_PT_ORIG_R3]; |
| 890 | |
sewardj | 463b3d9 | 2005-07-18 11:41:15 +0000 | [diff] [blame] | 891 | LibVEX_GuestPPC32_put_CR( mc->mc_gregs[VKI_PT_CCR], &tst->arch.vex ); |
sewardj | e1c444e | 2005-07-08 18:28:40 +0000 | [diff] [blame] | 892 | |
| 893 | tst->arch.vex.guest_LR = mc->mc_gregs[VKI_PT_LNK]; |
| 894 | tst->arch.vex.guest_CTR = mc->mc_gregs[VKI_PT_CTR]; |
sewardj | 463b3d9 | 2005-07-18 11:41:15 +0000 | [diff] [blame] | 895 | LibVEX_GuestPPC32_put_XER( mc->mc_gregs[VKI_PT_XER], &tst->arch.vex ); |
sewardj | e1c444e | 2005-07-08 18:28:40 +0000 | [diff] [blame] | 896 | |
sewardj | 7cf4e6b | 2008-05-01 20:24:26 +0000 | [diff] [blame] | 897 | tst->arch.vex_shadow1 = priv->vex_shadow1; |
| 898 | tst->arch.vex_shadow2 = priv->vex_shadow2; |
sewardj | e1c444e | 2005-07-08 18:28:40 +0000 | [diff] [blame] | 899 | |
| 900 | VG_TRACK(die_mem_stack_signal, sp, frame_size); |
| 901 | |
| 902 | if (VG_(clo_trace_signals)) |
| 903 | VG_(message)(Vg_DebugMsg, |
sewardj | 738856f | 2009-07-15 14:48:32 +0000 | [diff] [blame] | 904 | "vg_pop_signal_frame (thread %d): " |
| 905 | "isRT=%d valid magic; EIP=%#x\n", |
sewardj | e1c444e | 2005-07-08 18:28:40 +0000 | [diff] [blame] | 906 | tid, has_siginfo, tst->arch.vex.guest_CIA); |
| 907 | |
| 908 | /* tell the tools */ |
| 909 | VG_TRACK( post_deliver_signal, tid, sigNo ); |
| 910 | |
cerion | 85665ca | 2005-06-20 15:51:07 +0000 | [diff] [blame] | 911 | //.. Addr esp; |
| 912 | //.. ThreadState* tst; |
| 913 | //.. SizeT size; |
| 914 | //.. Int sigNo; |
| 915 | //.. |
| 916 | //.. tst = VG_(get_ThreadState)(tid); |
| 917 | //.. |
| 918 | //.. /* Correctly reestablish the frame base address. */ |
| 919 | //.. esp = tst->arch.vex.guest_ESP; |
| 920 | //.. |
| 921 | //.. if (!isRT) |
| 922 | //.. size = restore_sigframe(tst, (struct sigframe *)esp, &sigNo); |
| 923 | //.. else |
| 924 | //.. size = restore_rt_sigframe(tst, (struct rt_sigframe *)esp, &sigNo); |
| 925 | //.. |
| 926 | //.. VG_TRACK( die_mem_stack_signal, esp, size ); |
| 927 | //.. |
| 928 | //.. if (VG_(clo_trace_signals)) |
| 929 | //.. VG_(message)( |
| 930 | //.. Vg_DebugMsg, |
njn | af839f5 | 2005-06-23 03:27:57 +0000 | [diff] [blame] | 931 | //.. "VG_(signal_return) (thread %d): isRT=%d valid magic; EIP=%p", |
cerion | 85665ca | 2005-06-20 15:51:07 +0000 | [diff] [blame] | 932 | //.. tid, isRT, tst->arch.vex.guest_EIP); |
| 933 | //.. |
| 934 | //.. /* tell the tools */ |
| 935 | //.. VG_TRACK( post_deliver_signal, tid, sigNo ); |
sewardj | e1c444e | 2005-07-08 18:28:40 +0000 | [diff] [blame] | 936 | } |
cerion | 85665ca | 2005-06-20 15:51:07 +0000 | [diff] [blame] | 937 | |
njn | 8b68b64 | 2009-06-24 00:37:09 +0000 | [diff] [blame] | 938 | #endif // defined(VGP_ppc32_linux) |
| 939 | |
cerion | 85665ca | 2005-06-20 15:51:07 +0000 | [diff] [blame] | 940 | /*--------------------------------------------------------------------*/ |
njn | 8b68b64 | 2009-06-24 00:37:09 +0000 | [diff] [blame] | 941 | /*--- end ---*/ |
cerion | 85665ca | 2005-06-20 15:51:07 +0000 | [diff] [blame] | 942 | /*--------------------------------------------------------------------*/ |