2
0

strace.c 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. #include <stdio.h>
  2. #include <errno.h>
  3. #include <sys/select.h>
  4. #include <sys/types.h>
  5. #include <unistd.h>
  6. #include <sys/syscall.h>
  7. #include "qemu.h"
  8. int do_strace=0;
  9. struct syscallname {
  10. int nr;
  11. const char *name;
  12. const char *format;
  13. void (*call)(const struct syscallname *,
  14. abi_long, abi_long, abi_long,
  15. abi_long, abi_long, abi_long);
  16. void (*result)(const struct syscallname *, abi_long);
  17. };
  18. /*
  19. * Utility functions
  20. */
  21. static void
  22. print_execve(const struct syscallname *name,
  23. abi_long arg1, abi_long arg2, abi_long arg3,
  24. abi_long arg4, abi_long arg5, abi_long arg6)
  25. {
  26. abi_ulong arg_ptr_addr;
  27. char *s;
  28. if (!(s = lock_user_string(arg1)))
  29. return;
  30. gemu_log("%s(\"%s\",{", name->name, s);
  31. unlock_user(s, arg1, 0);
  32. for (arg_ptr_addr = arg2; ; arg_ptr_addr += sizeof(abi_ulong)) {
  33. abi_ulong *arg_ptr, arg_addr;
  34. arg_ptr = lock_user(VERIFY_READ, arg_ptr_addr, sizeof(abi_ulong), 1);
  35. if (!arg_ptr)
  36. return;
  37. arg_addr = tswapl(*arg_ptr);
  38. unlock_user(arg_ptr, arg_ptr_addr, 0);
  39. if (!arg_addr)
  40. break;
  41. if ((s = lock_user_string(arg_addr))) {
  42. gemu_log("\"%s\",", s);
  43. unlock_user(s, arg_addr, 0);
  44. }
  45. }
  46. gemu_log("NULL})");
  47. }
  48. /*
  49. * Variants for the return value output function
  50. */
  51. static void
  52. print_syscall_ret_addr(const struct syscallname *name, abi_long ret)
  53. {
  54. if( ret == -1 ) {
  55. gemu_log(" = -1 errno=%d (%s)\n", errno, strerror(errno));
  56. } else {
  57. gemu_log(" = 0x" TARGET_ABI_FMT_lx "\n", ret);
  58. }
  59. }
  60. #if 0 /* currently unused */
  61. static void
  62. print_syscall_ret_raw(struct syscallname *name, abi_long ret)
  63. {
  64. gemu_log(" = 0x" TARGET_ABI_FMT_lx "\n", ret);
  65. }
  66. #endif
  67. /*
  68. * An array of all of the syscalls we know about
  69. */
  70. static const struct syscallname freebsd_scnames[] = {
  71. #include "freebsd/strace.list"
  72. };
  73. static const struct syscallname netbsd_scnames[] = {
  74. #include "netbsd/strace.list"
  75. };
  76. static const struct syscallname openbsd_scnames[] = {
  77. #include "openbsd/strace.list"
  78. };
  79. static void
  80. print_syscall(int num, const struct syscallname *scnames, unsigned int nscnames,
  81. abi_long arg1, abi_long arg2, abi_long arg3,
  82. abi_long arg4, abi_long arg5, abi_long arg6)
  83. {
  84. unsigned int i;
  85. const char *format="%s(" TARGET_ABI_FMT_ld "," TARGET_ABI_FMT_ld ","
  86. TARGET_ABI_FMT_ld "," TARGET_ABI_FMT_ld "," TARGET_ABI_FMT_ld ","
  87. TARGET_ABI_FMT_ld ")";
  88. gemu_log("%d ", getpid() );
  89. for (i = 0; i < nscnames; i++)
  90. if (scnames[i].nr == num) {
  91. if (scnames[i].call != NULL) {
  92. scnames[i].call(&scnames[i], arg1, arg2, arg3, arg4, arg5,
  93. arg6);
  94. } else {
  95. /* XXX: this format system is broken because it uses
  96. host types and host pointers for strings */
  97. if (scnames[i].format != NULL)
  98. format = scnames[i].format;
  99. gemu_log(format, scnames[i].name, arg1, arg2, arg3, arg4,
  100. arg5, arg6);
  101. }
  102. return;
  103. }
  104. gemu_log("Unknown syscall %d\n", num);
  105. }
  106. static void
  107. print_syscall_ret(int num, abi_long ret, const struct syscallname *scnames,
  108. unsigned int nscnames)
  109. {
  110. unsigned int i;
  111. for (i = 0; i < nscnames; i++)
  112. if (scnames[i].nr == num) {
  113. if (scnames[i].result != NULL) {
  114. scnames[i].result(&scnames[i], ret);
  115. } else {
  116. if( ret < 0 ) {
  117. gemu_log(" = -1 errno=" TARGET_ABI_FMT_ld " (%s)\n", -ret,
  118. strerror(-ret));
  119. } else {
  120. gemu_log(" = " TARGET_ABI_FMT_ld "\n", ret);
  121. }
  122. }
  123. break;
  124. }
  125. }
  126. /*
  127. * The public interface to this module.
  128. */
  129. void
  130. print_freebsd_syscall(int num,
  131. abi_long arg1, abi_long arg2, abi_long arg3,
  132. abi_long arg4, abi_long arg5, abi_long arg6)
  133. {
  134. print_syscall(num, freebsd_scnames, ARRAY_SIZE(freebsd_scnames),
  135. arg1, arg2, arg3, arg4, arg5, arg6);
  136. }
  137. void
  138. print_freebsd_syscall_ret(int num, abi_long ret)
  139. {
  140. print_syscall_ret(num, ret, freebsd_scnames, ARRAY_SIZE(freebsd_scnames));
  141. }
  142. void
  143. print_netbsd_syscall(int num,
  144. abi_long arg1, abi_long arg2, abi_long arg3,
  145. abi_long arg4, abi_long arg5, abi_long arg6)
  146. {
  147. print_syscall(num, netbsd_scnames, ARRAY_SIZE(netbsd_scnames),
  148. arg1, arg2, arg3, arg4, arg5, arg6);
  149. }
  150. void
  151. print_netbsd_syscall_ret(int num, abi_long ret)
  152. {
  153. print_syscall_ret(num, ret, netbsd_scnames, ARRAY_SIZE(netbsd_scnames));
  154. }
  155. void
  156. print_openbsd_syscall(int num,
  157. abi_long arg1, abi_long arg2, abi_long arg3,
  158. abi_long arg4, abi_long arg5, abi_long arg6)
  159. {
  160. print_syscall(num, openbsd_scnames, ARRAY_SIZE(openbsd_scnames),
  161. arg1, arg2, arg3, arg4, arg5, arg6);
  162. }
  163. void
  164. print_openbsd_syscall_ret(int num, abi_long ret)
  165. {
  166. print_syscall_ret(num, ret, openbsd_scnames, ARRAY_SIZE(openbsd_scnames));
  167. }