int main() { assign_global(); assign_struct(); assign_array(); if (num_hook_calls == 3) return 0; /* Success */ else if (num_hook_calls == 0) FAIL("No hook functions executed.\n"); else FAIL("Number of hook executions did not match expected.\n"); }
int restore_fpu(struct rt_sigframe *sigframe, CoreEntry *core) { fpu_state_t *fpu_state = &sigframe->fpu_state; struct xsave_struct *x = &fpu_state->xsave; /* * If no FPU information provided -- we're restoring * old image which has no FPU support, or the dump simply * has no FPU support at all. */ if (!core->thread_info->fpregs) { fpu_state->has_fpu = false; return 0; } if (!valid_xsave_frame(core)) return -1; fpu_state->has_fpu = true; #define assign_reg(dst, src, e) do { dst.e = (__typeof__(dst.e))src->e; } while (0) #define assign_array(dst, src, e) memcpy(dst.e, (src)->e, sizeof(dst.e)) assign_reg(x->i387, core->thread_info->fpregs, cwd); assign_reg(x->i387, core->thread_info->fpregs, swd); assign_reg(x->i387, core->thread_info->fpregs, twd); assign_reg(x->i387, core->thread_info->fpregs, fop); assign_reg(x->i387, core->thread_info->fpregs, rip); assign_reg(x->i387, core->thread_info->fpregs, rdp); assign_reg(x->i387, core->thread_info->fpregs, mxcsr); assign_reg(x->i387, core->thread_info->fpregs, mxcsr_mask); assign_array(x->i387, core->thread_info->fpregs, st_space); assign_array(x->i387, core->thread_info->fpregs, xmm_space); if (cpu_has_feature(X86_FEATURE_XSAVE)) { struct fpx_sw_bytes *fpx_sw = (void *)&x->i387.sw_reserved; void *magic2; x->xsave_hdr.xstate_bv = XSTATE_FP | XSTATE_SSE | XSTATE_YMM; /* * fpregs->xsave pointer might not present on image so we * simply clear out all ymm registers. */ if (core->thread_info->fpregs->xsave) assign_array(x->ymmh, core->thread_info->fpregs->xsave, ymmh_space); fpx_sw->magic1 = FP_XSTATE_MAGIC1; fpx_sw->xstate_bv = XSTATE_FP | XSTATE_SSE | XSTATE_YMM; fpx_sw->xstate_size = sizeof(struct xsave_struct); fpx_sw->extended_size = sizeof(struct xsave_struct) + FP_XSTATE_MAGIC2_SIZE; /* * This should be at the end of xsave frame. */ magic2 = fpu_state->__pad + sizeof(struct xsave_struct); *(u32 *)magic2 = FP_XSTATE_MAGIC2; } show_rt_xsave_frame(x); #undef assign_reg #undef assign_array return 0; }
int get_task_regs(pid_t pid, user_regs_struct_t regs, CoreEntry *core) { struct xsave_struct xsave = { }; struct iovec iov; int ret = -1; pr_info("Dumping GP/FPU registers for %d\n", pid); /* Did we come from a system call? */ if ((int)regs.orig_ax >= 0) { /* Restart the system call */ switch ((long)(int)regs.ax) { case -ERESTARTNOHAND: case -ERESTARTSYS: case -ERESTARTNOINTR: regs.ax = regs.orig_ax; regs.ip -= 2; break; case -ERESTART_RESTARTBLOCK: pr_warn("Will restore %d with interrupted system call\n", pid); regs.ax = -EINTR; break; } } #define assign_reg(dst, src, e) do { dst->e = (__typeof__(dst->e))src.e; } while (0) #define assign_array(dst, src, e) memcpy(dst->e, &src.e, sizeof(src.e)) assign_reg(core->thread_info->gpregs, regs, r15); assign_reg(core->thread_info->gpregs, regs, r14); assign_reg(core->thread_info->gpregs, regs, r13); assign_reg(core->thread_info->gpregs, regs, r12); assign_reg(core->thread_info->gpregs, regs, bp); assign_reg(core->thread_info->gpregs, regs, bx); assign_reg(core->thread_info->gpregs, regs, r11); assign_reg(core->thread_info->gpregs, regs, r10); assign_reg(core->thread_info->gpregs, regs, r9); assign_reg(core->thread_info->gpregs, regs, r8); assign_reg(core->thread_info->gpregs, regs, ax); assign_reg(core->thread_info->gpregs, regs, cx); assign_reg(core->thread_info->gpregs, regs, dx); assign_reg(core->thread_info->gpregs, regs, si); assign_reg(core->thread_info->gpregs, regs, di); assign_reg(core->thread_info->gpregs, regs, orig_ax); assign_reg(core->thread_info->gpregs, regs, ip); assign_reg(core->thread_info->gpregs, regs, cs); assign_reg(core->thread_info->gpregs, regs, flags); assign_reg(core->thread_info->gpregs, regs, sp); assign_reg(core->thread_info->gpregs, regs, ss); assign_reg(core->thread_info->gpregs, regs, fs_base); assign_reg(core->thread_info->gpregs, regs, gs_base); assign_reg(core->thread_info->gpregs, regs, ds); assign_reg(core->thread_info->gpregs, regs, es); assign_reg(core->thread_info->gpregs, regs, fs); assign_reg(core->thread_info->gpregs, regs, gs); #ifndef PTRACE_GETREGSET # define PTRACE_GETREGSET 0x4204 #endif if (!cpu_has_feature(X86_FEATURE_FPU)) goto out; /* * FPU fetched either via fxsave or via xsave, * thus decode it accrodingly. */ if (cpu_has_feature(X86_FEATURE_XSAVE)) { iov.iov_base = &xsave; iov.iov_len = sizeof(xsave); if (ptrace(PTRACE_GETREGSET, pid, (unsigned int)NT_X86_XSTATE, &iov) < 0) { pr_perror("Can't obtain FPU registers for %d", pid); goto err; } } else { if (ptrace(PTRACE_GETFPREGS, pid, NULL, &xsave)) { pr_perror("Can't obtain FPU registers for %d", pid); goto err; } } assign_reg(core->thread_info->fpregs, xsave.i387, cwd); assign_reg(core->thread_info->fpregs, xsave.i387, swd); assign_reg(core->thread_info->fpregs, xsave.i387, twd); assign_reg(core->thread_info->fpregs, xsave.i387, fop); assign_reg(core->thread_info->fpregs, xsave.i387, rip); assign_reg(core->thread_info->fpregs, xsave.i387, rdp); assign_reg(core->thread_info->fpregs, xsave.i387, mxcsr); assign_reg(core->thread_info->fpregs, xsave.i387, mxcsr_mask); /* Make sure we have enough space */ BUG_ON(core->thread_info->fpregs->n_st_space != ARRAY_SIZE(xsave.i387.st_space)); BUG_ON(core->thread_info->fpregs->n_xmm_space != ARRAY_SIZE(xsave.i387.xmm_space)); assign_array(core->thread_info->fpregs, xsave.i387, st_space); assign_array(core->thread_info->fpregs, xsave.i387, xmm_space); if (cpu_has_feature(X86_FEATURE_XSAVE)) { BUG_ON(core->thread_info->fpregs->xsave->n_ymmh_space != ARRAY_SIZE(xsave.ymmh.ymmh_space)); assign_reg(core->thread_info->fpregs->xsave, xsave.xsave_hdr, xstate_bv); assign_array(core->thread_info->fpregs->xsave, xsave.ymmh, ymmh_space); } #undef assign_reg #undef assign_array out: ret = 0; err: return ret; }