Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * Ptrace test for GPR/FPR registers
0004  *
0005  * Copyright (C) 2015 Anshuman Khandual, IBM Corporation.
0006  */
0007 #include "ptrace.h"
0008 #include "ptrace-gpr.h"
0009 #include "reg.h"
0010 #include <time.h>
0011 
0012 /* Tracer and Tracee Shared Data */
0013 int shm_id;
0014 int *cptr, *pptr;
0015 
0016 extern void gpr_child_loop(int *read_flag, int *write_flag,
0017                unsigned long *gpr_buf, double *fpr_buf);
0018 
0019 unsigned long child_gpr_val, parent_gpr_val;
0020 double child_fpr_val, parent_fpr_val;
0021 
0022 static int child(void)
0023 {
0024     unsigned long gpr_buf[32];
0025     double fpr_buf[32];
0026     int i;
0027 
0028     cptr = (int *)shmat(shm_id, NULL, 0);
0029     memset(gpr_buf, 0, sizeof(gpr_buf));
0030     memset(fpr_buf, 0, sizeof(fpr_buf));
0031 
0032     for (i = 0; i < 32; i++) {
0033         gpr_buf[i] = child_gpr_val;
0034         fpr_buf[i] = child_fpr_val;
0035     }
0036 
0037     gpr_child_loop(&cptr[0], &cptr[1], gpr_buf, fpr_buf);
0038 
0039     shmdt((void *)cptr);
0040 
0041     FAIL_IF(validate_gpr(gpr_buf, parent_gpr_val));
0042     FAIL_IF(validate_fpr_double(fpr_buf, parent_fpr_val));
0043 
0044     return 0;
0045 }
0046 
0047 int trace_gpr(pid_t child)
0048 {
0049     __u64 tmp, fpr[32], *peeked_fprs;
0050     unsigned long gpr[18];
0051 
0052     FAIL_IF(start_trace(child));
0053 
0054     // Check child GPRs match what we expect using GETREGS
0055     FAIL_IF(show_gpr(child, gpr));
0056     FAIL_IF(validate_gpr(gpr, child_gpr_val));
0057 
0058     // Check child FPRs match what we expect using GETFPREGS
0059     FAIL_IF(show_fpr(child, fpr));
0060     memcpy(&tmp, &child_fpr_val, sizeof(tmp));
0061     FAIL_IF(validate_fpr(fpr, tmp));
0062 
0063     // Check child FPRs match what we expect using PEEKUSR
0064     peeked_fprs = peek_fprs(child);
0065     FAIL_IF(!peeked_fprs);
0066     FAIL_IF(validate_fpr(peeked_fprs, tmp));
0067     free(peeked_fprs);
0068 
0069     // Write child GPRs using SETREGS
0070     FAIL_IF(write_gpr(child, parent_gpr_val));
0071 
0072     // Write child FPRs using SETFPREGS
0073     memcpy(&tmp, &parent_fpr_val, sizeof(tmp));
0074     FAIL_IF(write_fpr(child, tmp));
0075 
0076     // Check child FPRs match what we just set, using PEEKUSR
0077     peeked_fprs = peek_fprs(child);
0078     FAIL_IF(!peeked_fprs);
0079     FAIL_IF(validate_fpr(peeked_fprs, tmp));
0080 
0081     // Write child FPRs using POKEUSR
0082     FAIL_IF(poke_fprs(child, (unsigned long *)peeked_fprs));
0083 
0084     // Child will check its FPRs match before exiting
0085     FAIL_IF(stop_trace(child));
0086 
0087     return TEST_PASS;
0088 }
0089 
0090 #ifndef __LONG_WIDTH__
0091 #define __LONG_WIDTH__ (sizeof(long) * 8)
0092 #endif
0093 
0094 static uint64_t rand_reg(void)
0095 {
0096     uint64_t result;
0097     long r;
0098 
0099     r = random();
0100 
0101     // Small values are typical
0102     result = r & 0xffff;
0103     if (r & 0x10000)
0104         return result;
0105 
0106     // Pointers tend to have high bits set
0107     result |= random() << (__LONG_WIDTH__ - 31);
0108     if (r & 0x100000)
0109         return result;
0110 
0111     // And sometimes we want a full 64-bit value
0112     result ^= random() << 16;
0113 
0114     return result;
0115 }
0116 
0117 int ptrace_gpr(void)
0118 {
0119     unsigned long seed;
0120     int ret, status;
0121     pid_t pid;
0122 
0123     seed = getpid() ^ time(NULL);
0124     printf("srand(%lu)\n", seed);
0125     srand(seed);
0126 
0127     child_gpr_val = rand_reg();
0128     child_fpr_val = rand_reg();
0129     parent_gpr_val = rand_reg();
0130     parent_fpr_val = rand_reg();
0131 
0132     shm_id = shmget(IPC_PRIVATE, sizeof(int) * 2, 0777|IPC_CREAT);
0133     pid = fork();
0134     if (pid < 0) {
0135         perror("fork() failed");
0136         return TEST_FAIL;
0137     }
0138     if (pid == 0)
0139         exit(child());
0140 
0141     if (pid) {
0142         pptr = (int *)shmat(shm_id, NULL, 0);
0143         while (!pptr[1])
0144             asm volatile("" : : : "memory");
0145 
0146         ret = trace_gpr(pid);
0147         if (ret) {
0148             kill(pid, SIGTERM);
0149             shmdt((void *)pptr);
0150             shmctl(shm_id, IPC_RMID, NULL);
0151             return TEST_FAIL;
0152         }
0153 
0154         pptr[0] = 1;
0155         shmdt((void *)pptr);
0156 
0157         ret = wait(&status);
0158         shmctl(shm_id, IPC_RMID, NULL);
0159         if (ret != pid) {
0160             printf("Child's exit status not captured\n");
0161             return TEST_FAIL;
0162         }
0163 
0164         return (WIFEXITED(status) && WEXITSTATUS(status)) ? TEST_FAIL :
0165             TEST_PASS;
0166     }
0167 
0168     return TEST_PASS;
0169 }
0170 
0171 int main(int argc, char *argv[])
0172 {
0173     return test_harness(ptrace_gpr, "ptrace_gpr");
0174 }