Esempio n. 1
0
static 
void stack_mcontext ( struct vki_mcontext *mc, 
                      ThreadState* tst, 
                      Bool use_rt_sigreturn,
                      UInt fault_addr )
{
   VG_TRACK( pre_mem_write, Vg_CoreSignal, tst->tid, "signal frame mcontext",
             (Addr)mc, sizeof(struct vki_pt_regs) );

#  define DO(gpr)  mc->mc_gregs[VKI_PT_R0+gpr] = tst->arch.vex.guest_GPR##gpr
   DO(0);  DO(1);  DO(2);  DO(3);  DO(4);  DO(5);  DO(6);  DO(7);
   DO(8);  DO(9);  DO(10); DO(11); DO(12); DO(13); DO(14); DO(15);
   DO(16); DO(17); DO(18); DO(19); DO(20); DO(21); DO(22); DO(23);
   DO(24); DO(25); DO(26); DO(27); DO(28); DO(29); DO(30); DO(31);
#  undef DO

   mc->mc_gregs[VKI_PT_NIP]     = tst->arch.vex.guest_CIA;
   mc->mc_gregs[VKI_PT_MSR]     = 0xf032;   /* pretty arbitrary */
   mc->mc_gregs[VKI_PT_ORIG_R3] = tst->arch.vex.guest_GPR3;
   mc->mc_gregs[VKI_PT_CTR]     = tst->arch.vex.guest_CTR;
   mc->mc_gregs[VKI_PT_LNK]     = tst->arch.vex.guest_LR;
   mc->mc_gregs[VKI_PT_XER]     = LibVEX_GuestPPC32_get_XER(&tst->arch.vex);
   mc->mc_gregs[VKI_PT_CCR]     = LibVEX_GuestPPC32_get_CR(&tst->arch.vex);
   mc->mc_gregs[VKI_PT_MQ]      = 0;
   mc->mc_gregs[VKI_PT_TRAP]    = 0;
   mc->mc_gregs[VKI_PT_DAR]     = fault_addr;
   mc->mc_gregs[VKI_PT_DSISR]   = 0;
   mc->mc_gregs[VKI_PT_RESULT]  = 0;
   VG_TRACK( post_mem_write, Vg_CoreSignal, tst->tid, 
             (Addr)mc, sizeof(struct vki_pt_regs) );

   /* XXX should do FP and vector regs */

   /* set up signal return trampoline */
   /* NB.  5 Sept 07.  mc->mc_pad[0..1] used to contain a the code to
      which the signal handler returns, and it just did sys_sigreturn
      or sys_rt_sigreturn.  But this doesn't work if the stack is
      non-executable, and it isn't consistent with the x86-linux and
      amd64-linux scheme for removing the stack frame.  So instead be
      consistent and use a stub in m_trampoline.  Then it doesn't
      matter whether or not the (guest) stack is executable.  This
      fixes #149519 and #145837. */
   VG_TRACK(pre_mem_write, Vg_CoreSignal, tst->tid, "signal frame mcontext",
            (Addr)&mc->mc_pad, sizeof(mc->mc_pad));
   mc->mc_pad[0] = 0; /* invalid */
   mc->mc_pad[1] = 0; /* invalid */
   VG_TRACK( post_mem_write,  Vg_CoreSignal, tst->tid, 
             (Addr)&mc->mc_pad, sizeof(mc->mc_pad) );
   /* invalidate any translation of this area */
   VG_(discard_translations)( (Addr)&mc->mc_pad, 
                              sizeof(mc->mc_pad), "stack_mcontext" );   

   /* set the signal handler to return to the trampoline */
   SET_SIGNAL_LR(tst, (Addr)(use_rt_sigreturn 
                               ? (Addr)&VG_(ppc32_linux_SUBST_FOR_rt_sigreturn)
                               : (Addr)&VG_(ppc32_linux_SUBST_FOR_sigreturn)
                      ));
}
Esempio n. 2
0
static 
void stack_mcontext ( struct vki_mcontext *mc, 
                      ThreadState* tst, 
                      Int ret,
                      UInt fault_addr )
{
   VG_TRACK( pre_mem_write, Vg_CoreSignal, tst->tid, "signal frame mcontext",
             (Addr)mc, sizeof(struct vki_pt_regs) );

#  define DO(gpr)  mc->mc_gregs[VKI_PT_R0+gpr] = tst->arch.vex.guest_GPR##gpr
   DO(0);  DO(1);  DO(2);  DO(3);  DO(4);  DO(5);  DO(6);  DO(7);
   DO(8);  DO(9);  DO(10); DO(11); DO(12); DO(13); DO(14); DO(15);
   DO(16); DO(17); DO(18); DO(19); DO(20); DO(21); DO(22); DO(23);
   DO(24); DO(25); DO(26); DO(27); DO(28); DO(29); DO(30); DO(31);
#  undef DO

   mc->mc_gregs[VKI_PT_NIP]     = tst->arch.vex.guest_CIA;
   mc->mc_gregs[VKI_PT_MSR]     = 0xf032;   /* pretty arbitrary */
   mc->mc_gregs[VKI_PT_ORIG_R3] = tst->arch.vex.guest_GPR3;
   mc->mc_gregs[VKI_PT_CTR]     = tst->arch.vex.guest_CTR;
   mc->mc_gregs[VKI_PT_LNK]     = tst->arch.vex.guest_LR;
   mc->mc_gregs[VKI_PT_XER]     = LibVEX_GuestPPC32_get_XER(&tst->arch.vex);
   mc->mc_gregs[VKI_PT_CCR]     = LibVEX_GuestPPC32_get_CR(&tst->arch.vex);
   mc->mc_gregs[VKI_PT_MQ]      = 0;
   mc->mc_gregs[VKI_PT_TRAP]    = 0;
   mc->mc_gregs[VKI_PT_DAR]     = fault_addr;
   mc->mc_gregs[VKI_PT_DSISR]   = 0;
   mc->mc_gregs[VKI_PT_RESULT]  = 0;
   VG_TRACK( post_mem_write, Vg_CoreSignal, tst->tid, 
             (Addr)mc, sizeof(struct vki_pt_regs) );

   /* XXX should do FP and vector regs */

   /* set up signal return trampoline */
   VG_TRACK(pre_mem_write, Vg_CoreSignal, tst->tid, "signal frame mcontext",
            (Addr)&mc->mc_pad, sizeof(mc->mc_pad));
   mc->mc_pad[0] = 0x38000000U + ret;   /* li 0,ret */
   mc->mc_pad[1] = 0x44000002U;         /* sc */
   VG_TRACK( post_mem_write,  Vg_CoreSignal, tst->tid, 
             (Addr)&mc->mc_pad, sizeof(mc->mc_pad) );
   /* invalidate any translation of this area */
   VG_(discard_translations)( (Addr64)(Addr)&mc->mc_pad, 
                              sizeof(mc->mc_pad), "stack_mcontext" );   

   /* set the signal handler to return to the trampoline */
   SET_SIGNAL_LR(tst, (Addr) &mc->mc_pad[0]);
}
/* Create a signal frame for thread 'tid'. */
void VG_(sigframe_create) ( ThreadId tid,
                            Addr sp_top_of_frame,
                            const vki_siginfo_t *siginfo,
                            void *handler,
                            UInt flags,
                            const vki_sigset_t *mask,
                            void *restorer )
{
   ThreadState* tst;
   Addr sp;
   struct hacky_sigframe* frame;
   Int sigNo = siginfo->si_signo;
   Int __NR_FAKE_SIGRETURN = __NR_AIX5_FAKE_SIGRETURN;

   vg_assert(VG_IS_16_ALIGNED(sizeof(struct hacky_sigframe)));

   sp_top_of_frame &= ~0xf;
   sp = sp_top_of_frame - sizeof(struct hacky_sigframe);

   tst = VG_(get_ThreadState)(tid);
   if (!extend(tst, sp, sp_top_of_frame - sp))
     return;

   vg_assert(VG_IS_16_ALIGNED(sp));

   frame = (struct hacky_sigframe *) sp;

   /* clear it (very conservatively) */
   VG_(memset)(&frame->lower_guardzone, 0, 512);
   VG_(memset)(&frame->gst,     0, sizeof(VexGuestPPC32State));
   VG_(memset)(&frame->gshadow, 0, sizeof(VexGuestPPC32State));

   /* save stuff in frame */
   frame->gst           = tst->arch.vex;
   frame->gshadow       = tst->arch.vex_shadow;
   frame->sigNo_private = sigNo;
   frame->magicPI       = 0x31415927;

   /* Set up stack frame pointer */
   sp += 256;
   vg_assert(sp == (Addr)&frame->lower_guardzone[256]);
   VG_TRACK( pre_mem_write, Vg_CoreSignal, tid, "signal handler frame",
             sp, sizeof(UWord) );
   *(Addr*)sp = tst->arch.vex.guest_GPR1;
   VG_TRACK( post_mem_write, Vg_CoreSignal, tid,
             sp, sizeof(UWord) );

   /* Set regs for the handler */
   SET_SIGNAL_GPR(tid, 1, sp);
   SET_SIGNAL_GPR(tid, 2, ((UWord*)handler)[1]);
   SET_SIGNAL_GPR(tid, 3, sigNo);
   SET_SIGNAL_GPR(tid, 4, 0); /* XXX: the siginfo* */
   SET_SIGNAL_GPR(tid, 5, 0); /* XXX: the ucontext* */
   tst->arch.vex.guest_CIA = ((UWord*)handler)[0];

   /* set up return trampoline */
   vg_assert(__NR_FAKE_SIGRETURN >= 10000);
   vg_assert(__NR_FAKE_SIGRETURN <= 32767);
   frame->tramp[0] = 0x38400000U 
                     + __NR_FAKE_SIGRETURN; /* li 2,__NR_FAKE_SIGRETURN */
   frame->tramp[1] = 0x44000002U;           /* sc */

   /* invalidate any translation of this area */
   VG_(discard_translations)( (Addr64)(Addr)&frame->tramp[0], 
                              sizeof(frame->tramp), "sigframe tramp" );   
   /* set the signal handler to return to the trampoline */
   SET_SIGNAL_LR(tst, (Addr) &frame->tramp[0]);

   VG_TRACK(post_mem_write, Vg_CoreSignal, tst->tid,
            (Addr)&frame->tramp, sizeof(frame->tramp));

   if (0) {
      VG_(printf)("pushed signal frame for sig %d; R1 now = %p, "
                  "next %%CIA = %p, status=%d\n", 
                  sigNo,
	          sp, tst->arch.vex.guest_CIA, tst->status);
      VG_(printf)("trampoline is at %p\n",  &frame->tramp[0]);
   }
}
Esempio n. 4
0
/* EXPORTED */
void VG_(sigframe_create)( ThreadId tid, 
                           Addr sp_top_of_frame,
                           const vki_siginfo_t *siginfo,
                           const struct vki_ucontext *siguc,
                           void *handler, 
                           UInt flags,
                           const vki_sigset_t *mask,
		           void *restorer )
{
   struct vg_sig_private* priv;
   Addr sp;
   ThreadState* tst;
   Int sigNo = siginfo->si_signo;
   Addr faultaddr;
   struct rt_sigframe* frame;

   /* Stack must be 16-byte aligned */
   vg_assert(VG_IS_16_ALIGNED(sizeof(struct vg_sig_private)));
   vg_assert(VG_IS_16_ALIGNED(sizeof(struct rt_sigframe)));

   sp_top_of_frame &= ~0xf;
   sp = sp_top_of_frame - sizeof(struct rt_sigframe);

   tst = VG_(get_ThreadState)(tid);
   if (!extend(tst, sp, sp_top_of_frame - sp))
      return;

   vg_assert(VG_IS_16_ALIGNED(sp));

   frame = (struct rt_sigframe *) sp;

   /* clear it (conservatively) */
   VG_(memset)(frame, 0, sizeof(*frame));

   /////////
   frame->pinfo = &frame->info;
   frame->puc = &frame->uc;

   frame->uc.uc_flags = 0;
   frame->uc.uc_link = 0;
   /////////

   /* Set up the stack chain pointer */
   VG_TRACK( pre_mem_write, Vg_CoreSignal, tid, "signal handler frame",
             sp, sizeof(UWord) );
   *(Addr *)sp = tst->arch.vex.guest_GPR1;
   VG_TRACK( post_mem_write, Vg_CoreSignal, tid, 
             sp, sizeof(UWord) );

   faultaddr = (Addr)siginfo->_sifields._sigfault._addr;
   if (sigNo == VKI_SIGILL && siginfo->si_code > 0)
      faultaddr = tst->arch.vex.guest_CIA;

   VG_(memcpy)(&frame->info, siginfo, sizeof(*siginfo));
   VG_TRACK( post_mem_write, Vg_CoreSignal, tid,
             (Addr)&frame->info, sizeof(frame->info) );

   frame->uc.uc_flags = 0;
   frame->uc.uc_link  = 0;
   frame->uc.uc_stack = tst->altstack;
   frame->uc.uc_sigmask = tst->sig_mask;
   VG_TRACK( post_mem_write, Vg_CoreSignal, tid,
             (Addr)(&frame->uc), sizeof(frame->uc) );

#  define DO(gpr)  frame->uc.uc_mcontext.gp_regs[VKI_PT_R0+gpr] \
                      = tst->arch.vex.guest_GPR##gpr 
   DO(0);  DO(1);  DO(2);  DO(3);  DO(4);  DO(5);  DO(6);  DO(7);
   DO(8);  DO(9);  DO(10); DO(11); DO(12); DO(13); DO(14); DO(15);
   DO(16); DO(17); DO(18); DO(19); DO(20); DO(21); DO(22); DO(23);
   DO(24); DO(25); DO(26); DO(27); DO(28); DO(29); DO(30); DO(31);
#  undef DO

   frame->uc.uc_mcontext.gp_regs[VKI_PT_NIP]     = tst->arch.vex.guest_CIA;
   frame->uc.uc_mcontext.gp_regs[VKI_PT_MSR]     = 0xf032;   /* pretty arbitrary */
   frame->uc.uc_mcontext.gp_regs[VKI_PT_ORIG_R3] = tst->arch.vex.guest_GPR3;
   frame->uc.uc_mcontext.gp_regs[VKI_PT_CTR]     = tst->arch.vex.guest_CTR;
   frame->uc.uc_mcontext.gp_regs[VKI_PT_LNK]     = tst->arch.vex.guest_LR;
   frame->uc.uc_mcontext.gp_regs[VKI_PT_XER]     = LibVEX_GuestPPC64_get_XER(
                                                      &tst->arch.vex);
   frame->uc.uc_mcontext.gp_regs[VKI_PT_CCR]     = LibVEX_GuestPPC64_get_CR(
                                                      &tst->arch.vex);
   //mc->mc_gregs[VKI_PT_MQ]      = 0;
   //mc->mc_gregs[VKI_PT_TRAP]    = 0;
   //mc->mc_gregs[VKI_PT_DAR]     = fault_addr;
   //mc->mc_gregs[VKI_PT_DSISR]   = 0;
   //mc->mc_gregs[VKI_PT_RESULT]  = 0;

   /* XXX should do FP and vector regs */

   /* set up signal return trampoline */
   /* NB.  5 Sept 07.  mc->mc_pad[0..1] used to contain a the code to
      which the signal handler returns, and it just did sys_sigreturn
      or sys_rt_sigreturn.  But this doesn't work if the stack is
      non-executable, and it isn't consistent with the x86-linux and
      amd64-linux scheme for removing the stack frame.  So instead be
      consistent and use a stub in m_trampoline.  Then it doesn't
      matter whether or not the (guest) stack is executable.  This
      fixes #149519 and #145837. */
   frame->tramp[0] = 0; /* invalid */
   frame->tramp[1] = 0; /* invalid */
   VG_TRACK(post_mem_write, Vg_CoreSignal, tst->tid,
            (Addr)&frame->tramp, sizeof(frame->tramp));

   /* invalidate any translation of this area */
   VG_(discard_translations)( (Addr64)&frame->tramp[0], 
                              sizeof(frame->tramp), "stack_mcontext" );   

   /* set the signal handler to return to the trampoline */
   SET_SIGNAL_LR(tst, (Addr)&VG_(ppc64_linux_SUBST_FOR_rt_sigreturn));

   /* Stack pointer for the handler .. (note, back chain set
      earlier) */
   SET_SIGNAL_GPR(tid, 1, sp);

   /* Args for the handler .. */
   SET_SIGNAL_GPR(tid, 3, sigNo);
   SET_SIGNAL_GPR(tid, 4, (Addr) &frame->info);
   SET_SIGNAL_GPR(tid, 5, (Addr) &frame->uc);
   /* the kernel sets this, though it doesn't seem to be in the ABI */
   SET_SIGNAL_GPR(tid, 6, (Addr) &frame->info);

   /* Handler is in fact a standard ppc64-linux function descriptor, 
      so extract the function entry point and also the toc ptr to use. */
   SET_SIGNAL_GPR(tid, 2, (Addr) ((ULong*)handler)[1]);
   tst->arch.vex.guest_CIA = (Addr) ((ULong*)handler)[0];

   priv = &frame->priv;
   priv->magicPI       = 0x31415927;
   priv->sigNo_private = sigNo;
   priv->vex_shadow1   = tst->arch.vex_shadow1;
   priv->vex_shadow2   = tst->arch.vex_shadow2;

   if (0)
      VG_(printf)("pushed signal frame; %%R1 now = %#lx, "
                  "next %%CIA = %#llx, status=%d\n",
		  sp, tst->arch.vex.guest_CIA, tst->status);
}