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