ptrace-gpr.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * Ptrace test for GPR/FPR registers
  4. *
  5. * Copyright (C) 2015 Anshuman Khandual, IBM Corporation.
  6. */
  7. #include "ptrace.h"
  8. #include "ptrace-gpr.h"
  9. #include "reg.h"
  10. #include <time.h>
  11. /* Tracer and Tracee Shared Data */
  12. int shm_id;
  13. int *cptr, *pptr;
  14. extern void gpr_child_loop(int *read_flag, int *write_flag,
  15. unsigned long *gpr_buf, double *fpr_buf);
  16. unsigned long child_gpr_val, parent_gpr_val;
  17. double child_fpr_val, parent_fpr_val;
  18. static int child(void)
  19. {
  20. unsigned long gpr_buf[32];
  21. double fpr_buf[32];
  22. int i;
  23. cptr = (int *)shmat(shm_id, NULL, 0);
  24. memset(gpr_buf, 0, sizeof(gpr_buf));
  25. memset(fpr_buf, 0, sizeof(fpr_buf));
  26. for (i = 0; i < 32; i++) {
  27. gpr_buf[i] = child_gpr_val;
  28. fpr_buf[i] = child_fpr_val;
  29. }
  30. gpr_child_loop(&cptr[0], &cptr[1], gpr_buf, fpr_buf);
  31. shmdt((void *)cptr);
  32. FAIL_IF(validate_gpr(gpr_buf, parent_gpr_val));
  33. FAIL_IF(validate_fpr_double(fpr_buf, parent_fpr_val));
  34. return 0;
  35. }
  36. int trace_gpr(pid_t child)
  37. {
  38. __u64 tmp, fpr[32], *peeked_fprs;
  39. unsigned long gpr[18];
  40. FAIL_IF(start_trace(child));
  41. // Check child GPRs match what we expect using GETREGS
  42. FAIL_IF(show_gpr(child, gpr));
  43. FAIL_IF(validate_gpr(gpr, child_gpr_val));
  44. // Check child FPRs match what we expect using GETFPREGS
  45. FAIL_IF(show_fpr(child, fpr));
  46. memcpy(&tmp, &child_fpr_val, sizeof(tmp));
  47. FAIL_IF(validate_fpr(fpr, tmp));
  48. // Check child FPRs match what we expect using PEEKUSR
  49. peeked_fprs = peek_fprs(child);
  50. FAIL_IF(!peeked_fprs);
  51. FAIL_IF(validate_fpr(peeked_fprs, tmp));
  52. free(peeked_fprs);
  53. // Write child GPRs using SETREGS
  54. FAIL_IF(write_gpr(child, parent_gpr_val));
  55. // Write child FPRs using SETFPREGS
  56. memcpy(&tmp, &parent_fpr_val, sizeof(tmp));
  57. FAIL_IF(write_fpr(child, tmp));
  58. // Check child FPRs match what we just set, using PEEKUSR
  59. peeked_fprs = peek_fprs(child);
  60. FAIL_IF(!peeked_fprs);
  61. FAIL_IF(validate_fpr(peeked_fprs, tmp));
  62. // Write child FPRs using POKEUSR
  63. FAIL_IF(poke_fprs(child, (unsigned long *)peeked_fprs));
  64. // Child will check its FPRs match before exiting
  65. FAIL_IF(stop_trace(child));
  66. return TEST_PASS;
  67. }
  68. #ifndef __LONG_WIDTH__
  69. #define __LONG_WIDTH__ (sizeof(long) * 8)
  70. #endif
  71. static uint64_t rand_reg(void)
  72. {
  73. uint64_t result;
  74. long r;
  75. r = random();
  76. // Small values are typical
  77. result = r & 0xffff;
  78. if (r & 0x10000)
  79. return result;
  80. // Pointers tend to have high bits set
  81. result |= random() << (__LONG_WIDTH__ - 31);
  82. if (r & 0x100000)
  83. return result;
  84. // And sometimes we want a full 64-bit value
  85. result ^= random() << 16;
  86. return result;
  87. }
  88. int ptrace_gpr(void)
  89. {
  90. unsigned long seed;
  91. int ret, status;
  92. pid_t pid;
  93. seed = getpid() ^ time(NULL);
  94. printf("srand(%lu)\n", seed);
  95. srand(seed);
  96. child_gpr_val = rand_reg();
  97. child_fpr_val = rand_reg();
  98. parent_gpr_val = rand_reg();
  99. parent_fpr_val = rand_reg();
  100. shm_id = shmget(IPC_PRIVATE, sizeof(int) * 2, 0777|IPC_CREAT);
  101. pid = fork();
  102. if (pid < 0) {
  103. perror("fork() failed");
  104. return TEST_FAIL;
  105. }
  106. if (pid == 0)
  107. exit(child());
  108. if (pid) {
  109. pptr = (int *)shmat(shm_id, NULL, 0);
  110. while (!pptr[1])
  111. asm volatile("" : : : "memory");
  112. ret = trace_gpr(pid);
  113. if (ret) {
  114. kill(pid, SIGTERM);
  115. shmdt((void *)pptr);
  116. shmctl(shm_id, IPC_RMID, NULL);
  117. return TEST_FAIL;
  118. }
  119. pptr[0] = 1;
  120. shmdt((void *)pptr);
  121. ret = wait(&status);
  122. shmctl(shm_id, IPC_RMID, NULL);
  123. if (ret != pid) {
  124. printf("Child's exit status not captured\n");
  125. return TEST_FAIL;
  126. }
  127. return (WIFEXITED(status) && WEXITSTATUS(status)) ? TEST_FAIL :
  128. TEST_PASS;
  129. }
  130. return TEST_PASS;
  131. }
  132. int main(int argc, char *argv[])
  133. {
  134. return test_harness(ptrace_gpr, "ptrace_gpr");
  135. }