1 2/*--------------------------------------------------------------------*/ 3/*--- Create/destroy signal delivery frames. ---*/ 4/*--- sigframe-arm64-linux.c ---*/ 5/*--------------------------------------------------------------------*/ 6 7/* 8 This file is part of Valgrind, a dynamic binary instrumentation 9 framework. 10 11 Copyright (C) 2013-2015 OpenWorks 12 info@open-works.net 13 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. 18 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. 23 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. 28 29 The GNU General Public License is contained in the file COPYING. 30*/ 31 32#if defined(VGP_arm64_linux) 33 34#include "pub_core_basics.h" 35#include "pub_core_vki.h" 36#include "pub_core_threadstate.h" 37#include "pub_core_aspacemgr.h" 38#include "pub_core_libcbase.h" 39#include "pub_core_libcassert.h" 40#include "pub_core_libcprint.h" 41#include "pub_core_machine.h" 42#include "pub_core_options.h" 43#include "pub_core_sigframe.h" 44#include "pub_core_signals.h" 45#include "pub_core_tooliface.h" 46#include "pub_core_trampoline.h" 47#include "priv_sigframe.h" 48 49 50/* This uses the hack of dumping the vex guest state along with both 51 shadows in the frame, and restoring it afterwards from there, 52 rather than pulling it out of the ucontext. That means that signal 53 handlers which modify the ucontext and then return, expecting their 54 modifications to take effect, will have those modifications 55 ignored. This could be fixed properly with an hour or so more 56 effort. */ 57 58/* This also always does the 'has siginfo' behaviour whether or 59 not it is requested. */ 60 61struct vg_sig_private { 62 UInt magicPI; 63 UInt sigNo_private; 64 VexGuestARM64State vex; 65 VexGuestARM64State vex_shadow1; 66 VexGuestARM64State vex_shadow2; 67}; 68 69struct sigframe { 70 struct vki_ucontext uc; 71 unsigned long retcode[2]; 72 struct vg_sig_private vp; 73}; 74 75struct rt_sigframe { 76 vki_siginfo_t info; 77 struct sigframe sig; 78}; 79 80 81static void synth_ucontext( ThreadId tid, const vki_siginfo_t *si, 82 UWord trapno, UWord err, const vki_sigset_t *set, 83 struct vki_ucontext *uc) 84{ 85 86 ThreadState *tst = VG_(get_ThreadState)(tid); 87 struct vki_sigcontext *sc = &uc->uc_mcontext; 88 89 VG_(memset)(uc, 0, sizeof(*uc)); 90 91 uc->uc_flags = 0; 92 uc->uc_link = 0; 93 uc->uc_sigmask = *set; 94 uc->uc_stack = tst->altstack; 95 96# define SC2(reg) sc->regs[reg] = tst->arch.vex.guest_X##reg 97 SC2(0); SC2(1); SC2(2); SC2(3); 98 SC2(4); SC2(5); SC2(6); SC2(7); 99 SC2(8); SC2(9); SC2(10); SC2(11); 100 SC2(12); SC2(13); SC2(14); SC2(15); 101 SC2(16); SC2(17); SC2(18); SC2(19); 102 SC2(20); SC2(21); SC2(22); SC2(23); 103 SC2(24); SC2(25); SC2(26); SC2(27); 104 SC2(28); SC2(29); SC2(30); 105# undef SC2 106 sc->sp = tst->arch.vex.guest_XSP; 107 sc->pc = tst->arch.vex.guest_PC; 108 sc->pstate = 0; /* slack .. could do better */ 109 110 //sc->trap_no = trapno; 111 //sc->error_code = err; 112 sc->fault_address = (ULong)si->_sifields._sigfault._addr; 113} 114 115 116static void build_sigframe(ThreadState *tst, 117 struct sigframe *frame, 118 const vki_siginfo_t *siginfo, 119 const struct vki_ucontext *siguc, 120 void *handler, UInt flags, 121 const vki_sigset_t *mask, 122 void *restorer) 123{ 124 UWord trapno; 125 UWord err; 126 Int sigNo = siginfo->si_signo; 127 struct vg_sig_private *priv = &frame->vp; 128 129 VG_TRACK( pre_mem_write, Vg_CoreSignal, tst->tid, "signal handler frame", 130 (Addr)frame, offsetof(struct sigframe, vp)); 131 132 if (siguc) { 133 trapno = 0; //siguc->uc_mcontext.trap_no; 134 err = 0; //siguc->uc_mcontext.error_code; 135 } else { 136 trapno = 0; 137 err = 0; 138 } 139 140 synth_ucontext(tst->tid, siginfo, trapno, err, mask, &frame->uc); 141 142 VG_TRACK( post_mem_write, Vg_CoreSignal, tst->tid, 143 (Addr)frame, offsetof(struct sigframe, vp)); 144 145 priv->magicPI = 0x31415927; 146 priv->sigNo_private = sigNo; 147 priv->vex = tst->arch.vex; 148 priv->vex_shadow1 = tst->arch.vex_shadow1; 149 priv->vex_shadow2 = tst->arch.vex_shadow2; 150} 151 152 153/* EXPORTED */ 154void VG_(sigframe_create)( ThreadId tid, 155 Bool on_altstack, 156 Addr sp_top_of_frame, 157 const vki_siginfo_t *siginfo, 158 const struct vki_ucontext *siguc, 159 void *handler, 160 UInt flags, 161 const vki_sigset_t *mask, 162 void *restorer ) 163{ 164 ThreadState *tst; 165 Addr sp = sp_top_of_frame; 166 Int sigNo = siginfo->si_signo; 167 UInt size; 168 169 tst = VG_(get_ThreadState)(tid); 170 171 size = sizeof(struct rt_sigframe); 172 173 sp -= size; 174 sp = VG_ROUNDDN(sp, 16); 175 176 if (! ML_(sf_maybe_extend_stack)(tst, sp, size, flags)) 177 return; // Give up. No idea if this is correct 178 179 struct rt_sigframe *rsf = (struct rt_sigframe *)sp; 180 181 /* Track our writes to siginfo */ 182 VG_TRACK( pre_mem_write, Vg_CoreSignal, tst->tid, /* VVVVV */ 183 "signal handler siginfo", (Addr)rsf, 184 offsetof(struct rt_sigframe, sig)); 185 186 VG_(memcpy)(&rsf->info, siginfo, sizeof(vki_siginfo_t)); 187 188 if (sigNo == VKI_SIGILL && siginfo->si_code > 0) { 189 rsf->info._sifields._sigfault._addr 190 = (Addr*)(tst)->arch.vex.guest_PC; 191 } 192 VG_TRACK( post_mem_write, Vg_CoreSignal, tst->tid, /* ^^^^^ */ 193 (Addr)rsf, offsetof(struct rt_sigframe, sig)); 194 195 build_sigframe(tst, &rsf->sig, siginfo, siguc, 196 handler, flags, mask, restorer); 197 tst->arch.vex.guest_X1 = (Addr)&rsf->info; 198 tst->arch.vex.guest_X2 = (Addr)&rsf->sig.uc; 199 200 VG_(set_SP)(tid, sp); 201 VG_TRACK( post_reg_write, Vg_CoreSignal, tid, VG_O_STACK_PTR, 202 sizeof(Addr)); 203 tst->arch.vex.guest_X0 = sigNo; 204 205 if (flags & VKI_SA_RESTORER) 206 tst->arch.vex.guest_X30 = (Addr)restorer; 207 else 208 tst->arch.vex.guest_X30 209 = (Addr)&VG_(arm64_linux_SUBST_FOR_rt_sigreturn); 210 211 tst->arch.vex.guest_PC = (Addr)handler; 212} 213 214 215/*------------------------------------------------------------*/ 216/*--- Destroying signal frames ---*/ 217/*------------------------------------------------------------*/ 218 219/* EXPORTED */ 220void VG_(sigframe_destroy)( ThreadId tid, Bool isRT ) 221{ 222 ThreadState *tst; 223 struct vg_sig_private *priv; 224 Addr sp; 225 UInt frame_size; 226//ZZ struct vki_sigcontext *mc; 227 Int sigNo; 228 Bool has_siginfo = isRT; 229 230 vg_assert(VG_(is_valid_tid)(tid)); 231 tst = VG_(get_ThreadState)(tid); 232 sp = tst->arch.vex.guest_XSP; 233 234//ZZ if (has_siginfo) { 235 struct rt_sigframe *frame = (struct rt_sigframe *)sp; 236 frame_size = sizeof(*frame); 237 //mc = &frame->sig.uc.uc_mcontext; 238 priv = &frame->sig.vp; 239 vg_assert(priv->magicPI == 0x31415927); 240 tst->sig_mask = frame->sig.uc.uc_sigmask; 241//ZZ } else { 242//ZZ struct sigframe *frame = (struct sigframe *)sp; 243//ZZ frame_size = sizeof(*frame); 244//ZZ mc = &frame->uc.uc_mcontext; 245//ZZ priv = &frame->vp; 246//ZZ vg_assert(priv->magicPI == 0x31415927); 247//ZZ tst->sig_mask = frame->uc.uc_sigmask; 248//ZZ //VG_(printf)("Setting signmask to %08x%08x\n", 249//ZZ // tst->sig_mask[0],tst->sig_mask[1]); 250//ZZ } 251 tst->tmp_sig_mask = tst->sig_mask; 252 253 sigNo = priv->sigNo_private; 254 255//ZZ //XXX: restore regs 256//ZZ # define REST(reg,REG) tst->arch.vex.guest_##REG = mc->arm_##reg; 257//ZZ REST(r0,R0); 258//ZZ REST(r1,R1); 259//ZZ REST(r2,R2); 260//ZZ REST(r3,R3); 261//ZZ REST(r4,R4); 262//ZZ REST(r5,R5); 263//ZZ REST(r6,R6); 264//ZZ REST(r7,R7); 265//ZZ REST(r8,R8); 266//ZZ REST(r9,R9); 267//ZZ REST(r10,R10); 268//ZZ REST(fp,R11); 269//ZZ REST(ip,R12); 270//ZZ REST(sp,R13); 271//ZZ REST(lr,R14); 272//ZZ REST(pc,R15T); 273//ZZ # undef REST 274 275 /* Uh, the next line makes all the REST() above pointless. */ 276 tst->arch.vex = priv->vex; 277 278 tst->arch.vex_shadow1 = priv->vex_shadow1; 279 tst->arch.vex_shadow2 = priv->vex_shadow2; 280 281 VG_TRACK( die_mem_stack_signal, sp - VG_STACK_REDZONE_SZB, 282 frame_size + VG_STACK_REDZONE_SZB ); 283 284 if (VG_(clo_trace_signals)) 285 VG_(message)(Vg_DebugMsg, 286 "vg_pop_signal_frame (thread %u): " 287 "isRT=%d valid magic; PC=%#llx\n", 288 tid, has_siginfo, tst->arch.vex.guest_PC); 289 290 /* tell the tools */ 291 VG_TRACK( post_deliver_signal, tid, sigNo ); 292} 293 294#endif // defined(VGP_arm_linux) 295 296/*--------------------------------------------------------------------*/ 297/*--- end sigframe-arm64-linux.c ---*/ 298/*--------------------------------------------------------------------*/ 299