1
2/*--------------------------------------------------------------------*/
3/*--- Create/destroy signal delivery frames.                       ---*/
4/*---                                  sigframe-mips64-linux.c     ---*/
5/*--------------------------------------------------------------------*/
6
7/*
8   This file is part of Valgrind, a dynamic binary instrumentation
9   framework.
10
11   Copyright (C) 2010-2013 RT-RK
12      mips-valgrind@rt-rk.com
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_mips64_linux)
33
34#include "pub_core_basics.h"
35#include "pub_core_vki.h"
36#include "pub_core_vkiscnums.h"
37#include "pub_core_threadstate.h"
38#include "pub_core_aspacemgr.h"
39#include "pub_core_libcbase.h"
40#include "pub_core_libcassert.h"
41#include "pub_core_libcprint.h"
42#include "pub_core_machine.h"
43#include "pub_core_options.h"
44#include "pub_core_sigframe.h"
45#include "pub_core_signals.h"
46#include "pub_core_tooliface.h"
47#include "pub_core_trampoline.h"
48#include "priv_sigframe.h"
49
50struct vg_sig_private {
51   UInt magicPI;
52   UInt sigNo_private;
53   VexGuestMIPS64State vex_shadow1;
54   VexGuestMIPS64State vex_shadow2;
55};
56
57struct sigframe {
58   UInt sf_ass[4];  /* argument save space for o32 */
59   UInt sf_pad[2];  /* Was: signal trampoline */
60   struct vki_sigcontext sf_sc;
61   vki_sigset_t sf_mask;
62   struct vg_sig_private priv;
63};
64
65struct rt_sigframe {
66   UInt rs_ass[4];  /* argument save space for o32 */
67   UInt rs_pad[2];  /* Was: signal trampoline */
68   vki_siginfo_t rs_info;
69   struct vki_ucontext rs_uc;
70   struct vg_sig_private priv;
71};
72
73
74static void setup_sigcontext ( ThreadState* tst, struct vki_sigcontext **sc1,
75                               const vki_siginfo_t *si)
76{
77   struct vki_sigcontext *sc = *sc1;
78
79   VG_TRACK(pre_mem_write, Vg_CoreSignal, tst->tid, "signal frame mcontext",
80            (Addr)sc, sizeof(unsigned long long)*34);
81   sc->sc_regs[1] = tst->arch.vex.guest_r1;
82   sc->sc_regs[2] = tst->arch.vex.guest_r2;
83   sc->sc_regs[3] = tst->arch.vex.guest_r3;
84   sc->sc_regs[4] = tst->arch.vex.guest_r4;
85   sc->sc_regs[5] = tst->arch.vex.guest_r5;
86   sc->sc_regs[6] = tst->arch.vex.guest_r6;
87   sc->sc_regs[7] = tst->arch.vex.guest_r7;
88   sc->sc_regs[8] = tst->arch.vex.guest_r8;
89   sc->sc_regs[9] = tst->arch.vex.guest_r9;
90   sc->sc_regs[10] = tst->arch.vex.guest_r10;
91   sc->sc_regs[11] = tst->arch.vex.guest_r11;
92   sc->sc_regs[12] = tst->arch.vex.guest_r12;
93   sc->sc_regs[13] = tst->arch.vex.guest_r13;
94   sc->sc_regs[14] = tst->arch.vex.guest_r14;
95   sc->sc_regs[15] = tst->arch.vex.guest_r15;
96   sc->sc_regs[16] = tst->arch.vex.guest_r16;
97   sc->sc_regs[17] = tst->arch.vex.guest_r17;
98   sc->sc_regs[18] = tst->arch.vex.guest_r18;
99   sc->sc_regs[19] = tst->arch.vex.guest_r19;
100   sc->sc_regs[20] = tst->arch.vex.guest_r20;
101   sc->sc_regs[21] = tst->arch.vex.guest_r21;
102   sc->sc_regs[22] = tst->arch.vex.guest_r22;
103   sc->sc_regs[23] = tst->arch.vex.guest_r23;
104   sc->sc_regs[24] = tst->arch.vex.guest_r24;
105   sc->sc_regs[25] = tst->arch.vex.guest_r25;
106   sc->sc_regs[26] = tst->arch.vex.guest_r26;
107   sc->sc_regs[27] = tst->arch.vex.guest_r27;
108   sc->sc_regs[28] = tst->arch.vex.guest_r28;
109   sc->sc_regs[29] = tst->arch.vex.guest_r29;
110   sc->sc_regs[30] = tst->arch.vex.guest_r30;
111   sc->sc_regs[31] = tst->arch.vex.guest_r31;
112   sc->sc_pc = tst->arch.vex.guest_PC;
113   sc->sc_mdhi = tst->arch.vex.guest_HI;
114   sc->sc_mdlo = tst->arch.vex.guest_LO;
115}
116
117/* EXPORTED */
118void VG_(sigframe_create) ( ThreadId tid,
119                            Addr sp_top_of_frame,
120                            const vki_siginfo_t *siginfo,
121                            const struct vki_ucontext *siguc,
122                            void *handler,
123                            UInt flags,
124                            const vki_sigset_t *mask,
125                            void *restorer )
126{
127   Addr sp;
128   ThreadState* tst = VG_(get_ThreadState)(tid);
129   Int sigNo = siginfo->si_signo;
130   struct vg_sig_private *priv;
131   /* Stack must be 16-byte aligned */
132   sp_top_of_frame &= ~0xf;
133
134   sp = sp_top_of_frame - sizeof(struct rt_sigframe);
135
136   tst = VG_(get_ThreadState)(tid);
137   if (! ML_(sf_maybe_extend_stack)(tst, sp, sp_top_of_frame - sp, flags))
138      return;
139
140   sp = VG_ROUNDDN(sp, 16);
141
142   struct rt_sigframe *frame = (struct rt_sigframe *)sp;
143   struct vki_ucontext *ucp = &frame->rs_uc;
144   if (VG_(clo_trace_signals))
145      VG_(printf)("rt_sigframe\n");
146   /* Create siginfo. */
147   VG_TRACK(pre_mem_write, Vg_CoreSignal, tid, "signal frame siginfo",
148            (Addr)&frame->rs_info, sizeof(frame->rs_info));
149
150   VG_(memcpy)(&frame->rs_info, siginfo, sizeof(*siginfo));
151
152   VG_TRACK(post_mem_write, Vg_CoreSignal, tid,
153            (Addr)&frame->rs_info, sizeof(frame->rs_info));
154
155   /* Create the ucontext. */
156   VG_TRACK(pre_mem_write, Vg_CoreSignal, tid, "signal frame ucontext",
157            (Addr)ucp, offsetof(struct vki_ucontext, uc_mcontext));
158
159   ucp->uc_flags = 0;
160   ucp->uc_link = 0;
161   ucp->uc_stack = tst->altstack;
162
163   VG_TRACK(post_mem_write, Vg_CoreSignal, tid, (Addr)ucp,
164            offsetof(struct vki_ucontext, uc_mcontext));
165
166   struct vki_sigcontext *scp = &(frame->rs_uc.uc_mcontext);
167   setup_sigcontext(tst, &(scp), siginfo);
168   ucp->uc_sigmask = tst->sig_mask;
169   priv = &frame->priv;
170
171   /* Arguments to signal handler:
172
173      a0 = signal number
174      a1 = 0 (should be cause)
175      a2 = pointer to ucontext
176
177      $25 and c0_epc point to the signal handler, $29 points to
178      the struct rt_sigframe. */
179
180   tst->arch.vex.guest_r4 = siginfo->si_signo;
181   tst->arch.vex.guest_r5 = (Addr) &frame->rs_info;
182   tst->arch.vex.guest_r6 = (Addr) &frame->rs_uc;
183   tst->arch.vex.guest_r29 = (Addr) frame;
184   tst->arch.vex.guest_r25 = (Addr) handler;
185
186   if (flags & VKI_SA_RESTORER)
187      tst->arch.vex.guest_r31 = (Addr) restorer;
188   else
189      tst->arch.vex.guest_r31 = (Addr)&VG_(mips64_linux_SUBST_FOR_rt_sigreturn);
190
191   priv->magicPI       = 0x31415927;
192   priv->sigNo_private = sigNo;
193   priv->vex_shadow1   = tst->arch.vex_shadow1;
194   priv->vex_shadow2   = tst->arch.vex_shadow2;
195   /* Set the thread so it will next run the handler. */
196   VG_TRACK( post_reg_write, Vg_CoreSignal, tid, VG_O_STACK_PTR, sizeof(Addr));
197   if (VG_(clo_trace_signals))
198      VG_(printf)("handler = %p\n", handler);
199   tst->arch.vex.guest_PC = (Addr) handler;
200   /* This thread needs to be marked runnable, but we leave that
201      the caller to do. */
202}
203
204/* EXPORTED */
205void VG_(sigframe_destroy) ( ThreadId tid, Bool isRT )
206{
207   ThreadState *tst;
208   struct vg_sig_private *priv1;
209   Addr sp;
210   UInt frame_size;
211   struct vki_sigcontext *mc;
212   Int sigNo;
213
214   vg_assert(VG_(is_valid_tid)(tid));
215   tst = VG_(get_ThreadState)(tid);
216   sp   = tst->arch.vex.guest_r29;
217   struct rt_sigframe *frame = (struct rt_sigframe *)sp;
218   struct vki_ucontext *ucp = &frame->rs_uc;
219   frame_size = sizeof(*frame);
220   mc = &ucp->uc_mcontext;
221   tst->sig_mask = ucp->uc_sigmask;
222   tst->tmp_sig_mask = ucp->uc_sigmask;
223   priv1 = &frame->priv;
224   sigNo = priv1->sigNo_private;
225   vg_assert(priv1->magicPI == 0x31415927);
226   /* restore regs */
227   tst->arch.vex.guest_r1 = mc->sc_regs[1];
228   tst->arch.vex.guest_r2 = mc->sc_regs[2];
229   tst->arch.vex.guest_r3 = mc->sc_regs[3];
230   tst->arch.vex.guest_r4 = mc->sc_regs[4];
231   tst->arch.vex.guest_r5 = mc->sc_regs[5];
232   tst->arch.vex.guest_r6 = mc->sc_regs[6];
233   tst->arch.vex.guest_r7 = mc->sc_regs[7];
234   tst->arch.vex.guest_r8 = mc->sc_regs[8];
235   tst->arch.vex.guest_r9 = mc->sc_regs[9];
236   tst->arch.vex.guest_r10 = mc->sc_regs[10];
237   tst->arch.vex.guest_r11 = mc->sc_regs[11];
238   tst->arch.vex.guest_r12 = mc->sc_regs[12];
239   tst->arch.vex.guest_r13= mc->sc_regs[13];
240   tst->arch.vex.guest_r14 = mc->sc_regs[14];
241   tst->arch.vex.guest_r15 = mc->sc_regs[15];
242   tst->arch.vex.guest_r16 = mc->sc_regs[16];
243   tst->arch.vex.guest_r17 = mc->sc_regs[17];
244   tst->arch.vex.guest_r18 = mc->sc_regs[18];
245   tst->arch.vex.guest_r19 = mc->sc_regs[19];
246   tst->arch.vex.guest_r20 = mc->sc_regs[20];
247   tst->arch.vex.guest_r21 = mc->sc_regs[21];
248   tst->arch.vex.guest_r22 = mc->sc_regs[22];
249   tst->arch.vex.guest_r23 = mc->sc_regs[23];
250   tst->arch.vex.guest_r24 = mc->sc_regs[24];
251   tst->arch.vex.guest_r25 = mc->sc_regs[25];
252   tst->arch.vex.guest_r26 = mc->sc_regs[26];
253   tst->arch.vex.guest_r27 = mc->sc_regs[27];
254   tst->arch.vex.guest_r28 = mc->sc_regs[28];
255   tst->arch.vex.guest_r30 = mc->sc_regs[30];
256   tst->arch.vex.guest_PC = mc->sc_pc;
257   tst->arch.vex.guest_r31 = mc->sc_regs[31];
258   tst->arch.vex.guest_r29 = mc->sc_regs[29];
259
260   tst->arch.vex.guest_HI = mc->sc_mdhi;
261   tst->arch.vex.guest_LO = mc->sc_mdlo;
262   tst->arch.vex_shadow1 = priv1->vex_shadow1;
263   tst->arch.vex_shadow2 = priv1->vex_shadow2;
264
265   VG_TRACK(die_mem_stack_signal, sp, frame_size);
266   if (VG_(clo_trace_signals))
267      VG_(message)(Vg_DebugMsg,
268         "VG_(signal_return) (thread %d): isRT=%d valid magic; EIP=%#llx\n",
269         tid, isRT, tst->arch.vex.guest_PC);
270   /* tell the tools */
271   VG_TRACK( post_deliver_signal, tid, sigNo );
272}
273
274#endif /* defined(VGP_mips64_linux) */
275
276/*--------------------------------------------------------------------*/
277/*--- end                                  sigframe-mips64-linux.c ---*/
278/*--------------------------------------------------------------------*/
279