1 /* 2 * make sure PEEKUSER matches GETREGS 3 * 4 * Copyright (c) 2008 Analog Devices Inc. 5 * 6 * Licensed under the GPL-2 or later 7 */ 8 9 #define _GNU_SOURCE 10 11 #include <errno.h> 12 #include <stdbool.h> 13 #include <stdio.h> 14 #include <stdlib.h> 15 #include <unistd.h> 16 17 #include <config.h> 18 #include "ptrace.h" 19 20 #include "test.h" 21 #include "spawn_ptrace_child.h" 22 23 char *TCID = "ptrace04"; 24 25 static void cleanup(); 26 27 #define R(r) { .name = "PT_" #r, .off = PT_##r }, 28 static struct { 29 const char *name; 30 long off; 31 } regs[] = { 32 #ifdef __bfin__ 33 R(ORIG_R0) R(ORIG_P0) 34 R(R0) R(R1) R(R2) R(R3) R(R4) R(R5) R(R6) R(R7) 35 R(P0) R(P1) R(P2) R(P3) R(P4) R(P5) R(FP) R(USP) 36 R(I0) R(I1) R(I2) R(I3) 37 R(M0) R(M1) R(M2) R(M3) 38 R(L0) R(L1) R(L2) R(L3) 39 R(B0) R(B1) R(B2) R(B3) 40 R(A0X) R(A0W) R(A1X) R(A1W) 41 R(LC0) R(LC1) R(LT0) R(LT1) R(LB0) R(LB1) 42 R(ASTAT) 43 R(RETS) R(PC) R(RETX) R(RETN) R(RETE) 44 R(SEQSTAT) R(IPEND) R(SYSCFG) 45 #endif 46 }; 47 48 int TST_TOTAL = 2; 49 50 void compare_registers(unsigned char poison) 51 { 52 #ifdef HAVE_STRUCT_PTRACE_REGS 53 ptrace_regs _pt_regs; 54 size_t i; 55 long ret; 56 bool failed = false; 57 58 memset(&_pt_regs, poison, sizeof(_pt_regs)); 59 errno = 0; 60 ret = ptrace(PTRACE_GETREGS, pid, NULL, &_pt_regs); 61 if (ret && errno) { 62 tst_resm(TFAIL | TERRNO, "PTRACE_GETREGS failed"); 63 } else { 64 65 for (i = 0; i < ARRAY_SIZE(regs); ++i) { 66 errno = 0; 67 ret = ptrace(PTRACE_PEEKUSER, pid, 68 (void *)regs[i].off, NULL); 69 if (ret && errno) { 70 tst_resm(TFAIL | TERRNO, 71 "PTRACE_PEEKUSER: register %s " 72 "(offset %li) failed", 73 regs[i].name, regs[i].off); 74 failed = true; 75 continue; 76 } 77 78 long *pt_val = (void *)&_pt_regs + regs[i].off; 79 if (*pt_val != ret) { 80 tst_resm(TFAIL, 81 "register %s (offset %li) did not " 82 "match\n\tGETREGS: 0x%08lx " 83 "PEEKUSER: 0x%08lx", 84 regs[i].name, regs[i].off, *pt_val, 85 ret); 86 failed = true; 87 } 88 89 } 90 91 } 92 93 tst_resm((failed ? TFAIL : TPASS), 94 "PTRACE PEEKUSER/GETREGS (poison 0x%02x)", poison); 95 #else 96 tst_brkm(TCONF, cleanup, "System doesn't have ptrace_regs structure"); 97 #endif 98 } 99 100 int main(int argc, char *argv[]) 101 { 102 tst_parse_opts(argc, argv, NULL, NULL); 103 104 if (ARRAY_SIZE(regs) == 0) 105 tst_brkm(TCONF, NULL, "test not supported for your arch (yet)"); 106 107 make_a_baby(argc, argv); 108 109 /* first compare register states when execl() syscall starts */ 110 tst_resm(TINFO, "Before exec() in child"); 111 compare_registers(0x00); 112 compare_registers(0xff); 113 114 /* then compare register states after execl() syscall finishes */ 115 tst_resm(TINFO, "After exec() in child"); 116 errno = 0; 117 if (ptrace(PTRACE_SYSCALL, pid, NULL, NULL) && errno) { 118 tst_brkm(TFAIL, NULL, "PTRACE_SYSCALL failed: %s", 119 strerror(errno)); 120 } 121 compare_registers(0x00); 122 compare_registers(0xff); 123 124 /* hopefully this worked */ 125 ptrace(PTRACE_KILL, pid, NULL, NULL); 126 127 tst_exit(); 128 } 129 130 static void cleanup(void) 131 { 132 } 133