t_ptrace_amd64_wait.h revision 1.7
1/* $NetBSD: t_ptrace_amd64_wait.h,v 1.7 2019/05/05 10:04:11 mgorny Exp $ */ 2 3/*- 4 * Copyright (c) 2016, 2017, 2018, 2019 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29#if defined(__x86_64__) 30 31/// ---------------------------------------------------------------------------- 32 33ATF_TC(x86_64_regs1); 34ATF_TC_HEAD(x86_64_regs1, tc) 35{ 36 atf_tc_set_md_var(tc, "descr", 37 "Call PT_GETREGS and iterate over General Purpose registers"); 38} 39 40ATF_TC_BODY(x86_64_regs1, tc) 41{ 42 const int exitval = 5; 43 const int sigval = SIGSTOP; 44 pid_t child, wpid; 45#if defined(TWAIT_HAVE_STATUS) 46 int status; 47#endif 48 struct reg r; 49 50 DPRINTF("Before forking process PID=%d\n", getpid()); 51 SYSCALL_REQUIRE((child = fork()) != -1); 52 if (child == 0) { 53 DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 54 FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 55 56 DPRINTF("Before raising %s from child\n", strsignal(sigval)); 57 FORKEE_ASSERT(raise(sigval) == 0); 58 59 DPRINTF("Before exiting of the child process\n"); 60 _exit(exitval); 61 } 62 DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 63 64 DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 65 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 66 67 validate_status_stopped(status, sigval); 68 69 DPRINTF("Call GETREGS for the child process\n"); 70 SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &r, 0) != -1); 71 72 DPRINTF("RAX=%#" PRIxREGISTER "\n", r.regs[_REG_RAX]); 73 DPRINTF("RBX=%#" PRIxREGISTER "\n", r.regs[_REG_RBX]); 74 DPRINTF("RCX=%#" PRIxREGISTER "\n", r.regs[_REG_RCX]); 75 DPRINTF("RDX=%#" PRIxREGISTER "\n", r.regs[_REG_RDX]); 76 77 DPRINTF("RDI=%#" PRIxREGISTER "\n", r.regs[_REG_RDI]); 78 DPRINTF("RSI=%#" PRIxREGISTER "\n", r.regs[_REG_RSI]); 79 80 DPRINTF("GS=%#" PRIxREGISTER "\n", r.regs[_REG_GS]); 81 DPRINTF("FS=%#" PRIxREGISTER "\n", r.regs[_REG_FS]); 82 DPRINTF("ES=%#" PRIxREGISTER "\n", r.regs[_REG_ES]); 83 DPRINTF("DS=%#" PRIxREGISTER "\n", r.regs[_REG_DS]); 84 DPRINTF("CS=%#" PRIxREGISTER "\n", r.regs[_REG_CS]); 85 DPRINTF("SS=%#" PRIxREGISTER "\n", r.regs[_REG_SS]); 86 87 DPRINTF("RSP=%#" PRIxREGISTER "\n", r.regs[_REG_RSP]); 88 DPRINTF("RIP=%#" PRIxREGISTER "\n", r.regs[_REG_RIP]); 89 90 DPRINTF("RFLAGS=%#" PRIxREGISTER "\n", r.regs[_REG_RFLAGS]); 91 92 DPRINTF("R8=%#" PRIxREGISTER "\n", r.regs[_REG_R8]); 93 DPRINTF("R9=%#" PRIxREGISTER "\n", r.regs[_REG_R9]); 94 DPRINTF("R10=%#" PRIxREGISTER "\n", r.regs[_REG_R10]); 95 DPRINTF("R11=%#" PRIxREGISTER "\n", r.regs[_REG_R11]); 96 DPRINTF("R12=%#" PRIxREGISTER "\n", r.regs[_REG_R12]); 97 DPRINTF("R13=%#" PRIxREGISTER "\n", r.regs[_REG_R13]); 98 DPRINTF("R14=%#" PRIxREGISTER "\n", r.regs[_REG_R14]); 99 DPRINTF("R15=%#" PRIxREGISTER "\n", r.regs[_REG_R15]); 100 101 DPRINTF("Before resuming the child process where it left off and " 102 "without signal to be sent\n"); 103 SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 104 105 DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 106 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 107 108 validate_status_exited(status, exitval); 109 110 DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 111 TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 112} 113 114ATF_TC(x86_64_regs_gp_read); 115ATF_TC_HEAD(x86_64_regs_gp_read, tc) 116{ 117 atf_tc_set_md_var(tc, "descr", 118 "Set general-purpose reg values from debugged program and read " 119 "them via PT_GETREGS, comparing values against expected."); 120} 121 122ATF_TC_BODY(x86_64_regs_gp_read, tc) 123{ 124 const int exitval = 5; 125 const int sigval = SIGTRAP; 126 pid_t child, wpid; 127#if defined(TWAIT_HAVE_STATUS) 128 int status; 129#endif 130 struct reg gpr; 131 132 const uint64_t rax = 0x0001020304050607; 133 const uint64_t rbx = 0x1011121314151617; 134 const uint64_t rcx = 0x2021222324252627; 135 const uint64_t rdx = 0x3031323334353637; 136 const uint64_t rsi = 0x4041424344454647; 137 const uint64_t rdi = 0x5051525354555657; 138 const uint64_t rsp = 0x6061626364656667; 139 const uint64_t rbp = 0x7071727374757677; 140 141 DPRINTF("Before forking process PID=%d\n", getpid()); 142 SYSCALL_REQUIRE((child = fork()) != -1); 143 if (child == 0) { 144 DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 145 FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 146 147 DPRINTF("Before running assembly from child\n"); 148 149 __asm__ __volatile__( 150 /* rbp & rbp are a bit tricky, we must not clobber them */ 151 "movq %%rsp, %%r8\n\t" 152 "movq %%rbp, %%r9\n\t" 153 "movq %6, %%rsp\n\t" 154 "movq %7, %%rbp\n\t" 155 "\n\t" 156 "int3\n\t" 157 "\n\t" 158 "movq %%r8, %%rsp\n\t" 159 "movq %%r9, %%rbp\n\t" 160 : 161 : "a"(rax), "b"(rbx), "c"(rcx), "d"(rdx), "S"(rsi), "D"(rdi), 162 "i"(rsp), "i"(rbp) 163 : "%r8", "%r9" 164 ); 165 166 DPRINTF("Before exiting of the child process\n"); 167 _exit(exitval); 168 } 169 DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 170 171 DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 172 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 173 174 validate_status_stopped(status, sigval); 175 176 DPRINTF("Call GETREGS for the child process\n"); 177 SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &gpr, 0) != -1); 178 179 ATF_CHECK_EQ((uint64_t)gpr.regs[_REG_RAX], rax); 180 ATF_CHECK_EQ((uint64_t)gpr.regs[_REG_RBX], rbx); 181 ATF_CHECK_EQ((uint64_t)gpr.regs[_REG_RCX], rcx); 182 ATF_CHECK_EQ((uint64_t)gpr.regs[_REG_RDX], rdx); 183 ATF_CHECK_EQ((uint64_t)gpr.regs[_REG_RSI], rsi); 184 ATF_CHECK_EQ((uint64_t)gpr.regs[_REG_RDI], rdi); 185 ATF_CHECK_EQ((uint64_t)gpr.regs[_REG_RSP], rsp); 186 ATF_CHECK_EQ((uint64_t)gpr.regs[_REG_RBP], rbp); 187 188 DPRINTF("Before resuming the child process where it left off and " 189 "without signal to be sent\n"); 190 SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 191 192 DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 193 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 194 195 validate_status_exited(status, exitval); 196 197 DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 198 TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 199} 200 201/// ---------------------------------------------------------------------------- 202 203 204#define ATF_TP_ADD_TCS_PTRACE_WAIT_AMD64() \ 205 ATF_TP_ADD_TC_HAVE_GPREGS(tp, x86_64_regs1); \ 206 ATF_TP_ADD_TC_HAVE_GPREGS(tp, x86_64_regs_gp_read); 207#else 208#define ATF_TP_ADD_TCS_PTRACE_WAIT_AMD64() 209#endif 210