2
0

strace.c 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316
  1. #include <stdio.h>
  2. #include <errno.h>
  3. #include <sys/ipc.h>
  4. #include <sys/msg.h>
  5. #include <sys/sem.h>
  6. #include <sys/shm.h>
  7. #include <sys/select.h>
  8. #include <sys/types.h>
  9. #include <unistd.h>
  10. #include "qemu.h"
  11. int do_strace=0;
  12. struct syscallname {
  13. int nr;
  14. const char *name;
  15. const char *format;
  16. void (*call)(const struct syscallname *,
  17. abi_long, abi_long, abi_long,
  18. abi_long, abi_long, abi_long);
  19. void (*result)(const struct syscallname *, abi_long);
  20. };
  21. /*
  22. * Utility functions
  23. */
  24. static void
  25. print_ipc_cmd(int cmd)
  26. {
  27. #define output_cmd(val) \
  28. if( cmd == val ) { \
  29. gemu_log(#val); \
  30. return; \
  31. }
  32. cmd &= 0xff;
  33. /* General IPC commands */
  34. output_cmd( IPC_RMID );
  35. output_cmd( IPC_SET );
  36. output_cmd( IPC_STAT );
  37. output_cmd( IPC_INFO );
  38. /* msgctl() commands */
  39. #ifdef __USER_MISC
  40. output_cmd( MSG_STAT );
  41. output_cmd( MSG_INFO );
  42. #endif
  43. /* shmctl() commands */
  44. output_cmd( SHM_LOCK );
  45. output_cmd( SHM_UNLOCK );
  46. output_cmd( SHM_STAT );
  47. output_cmd( SHM_INFO );
  48. /* semctl() commands */
  49. output_cmd( GETPID );
  50. output_cmd( GETVAL );
  51. output_cmd( GETALL );
  52. output_cmd( GETNCNT );
  53. output_cmd( GETZCNT );
  54. output_cmd( SETVAL );
  55. output_cmd( SETALL );
  56. output_cmd( SEM_STAT );
  57. output_cmd( SEM_INFO );
  58. output_cmd( IPC_RMID );
  59. output_cmd( IPC_RMID );
  60. output_cmd( IPC_RMID );
  61. output_cmd( IPC_RMID );
  62. output_cmd( IPC_RMID );
  63. output_cmd( IPC_RMID );
  64. output_cmd( IPC_RMID );
  65. output_cmd( IPC_RMID );
  66. output_cmd( IPC_RMID );
  67. /* Some value we don't recognize */
  68. gemu_log("%d",cmd);
  69. }
  70. #ifdef TARGET_NR__newselect
  71. static void
  72. print_fdset(int n, abi_ulong target_fds_addr)
  73. {
  74. int i;
  75. gemu_log("[");
  76. if( target_fds_addr ) {
  77. abi_long *target_fds;
  78. target_fds = lock_user(VERIFY_READ,
  79. target_fds_addr,
  80. sizeof(*target_fds)*(n / TARGET_ABI_BITS + 1),
  81. 1);
  82. if (!target_fds)
  83. return;
  84. for (i=n; i>=0; i--) {
  85. if ((tswapl(target_fds[i / TARGET_ABI_BITS]) >> (i & (TARGET_ABI_BITS - 1))) & 1)
  86. gemu_log("%d,", i );
  87. }
  88. unlock_user(target_fds, target_fds_addr, 0);
  89. }
  90. gemu_log("]");
  91. }
  92. static void
  93. print_timeval(abi_ulong tv_addr)
  94. {
  95. if( tv_addr ) {
  96. struct target_timeval *tv;
  97. tv = lock_user(VERIFY_READ, tv_addr, sizeof(*tv), 1);
  98. if (!tv)
  99. return;
  100. gemu_log("{" TARGET_ABI_FMT_ld "," TARGET_ABI_FMT_ld "}",
  101. tv->tv_sec, tv->tv_usec);
  102. unlock_user(tv, tv_addr, 0);
  103. } else
  104. gemu_log("NULL");
  105. }
  106. #endif
  107. /*
  108. * Sysycall specific output functions
  109. */
  110. /* select */
  111. #ifdef TARGET_NR__newselect
  112. static long newselect_arg1 = 0;
  113. static long newselect_arg2 = 0;
  114. static long newselect_arg3 = 0;
  115. static long newselect_arg4 = 0;
  116. static long newselect_arg5 = 0;
  117. static void
  118. print_newselect(const struct syscallname *name,
  119. abi_long arg1, abi_long arg2, abi_long arg3,
  120. abi_long arg4, abi_long arg5, abi_long arg6)
  121. {
  122. gemu_log("%s(" TARGET_ABI_FMT_ld ",", name->name, arg1);
  123. print_fdset(arg1, arg2);
  124. gemu_log(",");
  125. print_fdset(arg1, arg3);
  126. gemu_log(",");
  127. print_fdset(arg1, arg4);
  128. gemu_log(",");
  129. print_timeval(arg5);
  130. gemu_log(")");
  131. /* save for use in the return output function below */
  132. newselect_arg1=arg1;
  133. newselect_arg2=arg2;
  134. newselect_arg3=arg3;
  135. newselect_arg4=arg4;
  136. newselect_arg5=arg5;
  137. }
  138. #endif
  139. #ifdef TARGET_NR_semctl
  140. static void
  141. print_semctl(const struct syscallname *name,
  142. abi_long arg1, abi_long arg2, abi_long arg3,
  143. abi_long arg4, abi_long arg5, abi_long arg6)
  144. {
  145. gemu_log("%s(" TARGET_ABI_FMT_ld "," TARGET_ABI_FMT_ld ",", name->name, arg1, arg2);
  146. print_ipc_cmd(arg3);
  147. gemu_log(",0x" TARGET_ABI_FMT_lx ")", arg4);
  148. }
  149. #endif
  150. static void
  151. print_execve(const struct syscallname *name,
  152. abi_long arg1, abi_long arg2, abi_long arg3,
  153. abi_long arg4, abi_long arg5, abi_long arg6)
  154. {
  155. abi_ulong arg_ptr_addr;
  156. char *s;
  157. if (!(s = lock_user_string(arg1)))
  158. return;
  159. gemu_log("%s(\"%s\",{", name->name, s);
  160. unlock_user(s, arg1, 0);
  161. for (arg_ptr_addr = arg2; ; arg_ptr_addr += sizeof(abi_ulong)) {
  162. abi_ulong *arg_ptr, arg_addr;
  163. arg_ptr = lock_user(VERIFY_READ, arg_ptr_addr, sizeof(abi_ulong), 1);
  164. if (!arg_ptr)
  165. return;
  166. arg_addr = tswapl(*arg_ptr);
  167. unlock_user(arg_ptr, arg_ptr_addr, 0);
  168. if (!arg_addr)
  169. break;
  170. if ((s = lock_user_string(arg_addr))) {
  171. gemu_log("\"%s\",", s);
  172. unlock_user(s, arg_addr, 0);
  173. }
  174. }
  175. gemu_log("NULL})");
  176. }
  177. #ifdef TARGET_NR_ipc
  178. static void
  179. print_ipc(const struct syscallname *name,
  180. abi_long arg1, abi_long arg2, abi_long arg3,
  181. abi_long arg4, abi_long arg5, abi_long arg6)
  182. {
  183. switch(arg1) {
  184. case IPCOP_semctl:
  185. gemu_log("semctl(" TARGET_ABI_FMT_ld "," TARGET_ABI_FMT_ld ",", arg1, arg2);
  186. print_ipc_cmd(arg3);
  187. gemu_log(",0x" TARGET_ABI_FMT_lx ")", arg4);
  188. break;
  189. default:
  190. gemu_log("%s(" TARGET_ABI_FMT_ld "," TARGET_ABI_FMT_ld "," TARGET_ABI_FMT_ld "," TARGET_ABI_FMT_ld ")",
  191. name->name, arg1, arg2, arg3, arg4);
  192. }
  193. }
  194. #endif
  195. /*
  196. * Variants for the return value output function
  197. */
  198. static void
  199. print_syscall_ret_addr(const struct syscallname *name, abi_long ret)
  200. {
  201. if( ret == -1 ) {
  202. gemu_log(" = -1 errno=%d (%s)\n", errno, target_strerror(errno));
  203. } else {
  204. gemu_log(" = 0x" TARGET_ABI_FMT_lx "\n", ret);
  205. }
  206. }
  207. #if 0 /* currently unused */
  208. static void
  209. print_syscall_ret_raw(struct syscallname *name, abi_long ret)
  210. {
  211. gemu_log(" = 0x" TARGET_ABI_FMT_lx "\n", ret);
  212. }
  213. #endif
  214. #ifdef TARGET_NR__newselect
  215. static void
  216. print_syscall_ret_newselect(const struct syscallname *name, abi_long ret)
  217. {
  218. gemu_log(" = 0x" TARGET_ABI_FMT_lx " (", ret);
  219. print_fdset(newselect_arg1,newselect_arg2);
  220. gemu_log(",");
  221. print_fdset(newselect_arg1,newselect_arg3);
  222. gemu_log(",");
  223. print_fdset(newselect_arg1,newselect_arg4);
  224. gemu_log(",");
  225. print_timeval(newselect_arg5);
  226. gemu_log(")\n");
  227. }
  228. #endif
  229. /*
  230. * An array of all of the syscalls we know about
  231. */
  232. static const struct syscallname scnames[] = {
  233. #include "strace.list"
  234. };
  235. static int nsyscalls = ARRAY_SIZE(scnames);
  236. /*
  237. * The public interface to this module.
  238. */
  239. void
  240. print_syscall(int num,
  241. abi_long arg1, abi_long arg2, abi_long arg3,
  242. abi_long arg4, abi_long arg5, abi_long arg6)
  243. {
  244. int i;
  245. const char *format="%s(" TARGET_ABI_FMT_ld "," TARGET_ABI_FMT_ld "," TARGET_ABI_FMT_ld "," TARGET_ABI_FMT_ld "," TARGET_ABI_FMT_ld "," TARGET_ABI_FMT_ld ")";
  246. gemu_log("%d ", getpid() );
  247. for(i=0;i<nsyscalls;i++)
  248. if( scnames[i].nr == num ) {
  249. if( scnames[i].call != NULL ) {
  250. scnames[i].call(&scnames[i],arg1,arg2,arg3,arg4,arg5,arg6);
  251. } else {
  252. /* XXX: this format system is broken because it uses
  253. host types and host pointers for strings */
  254. if( scnames[i].format != NULL )
  255. format = scnames[i].format;
  256. gemu_log(format,scnames[i].name, arg1,arg2,arg3,arg4,arg5,arg6);
  257. }
  258. return;
  259. }
  260. gemu_log("Unknown syscall %d\n", num);
  261. }
  262. void
  263. print_syscall_ret(int num, abi_long ret)
  264. {
  265. int i;
  266. for(i=0;i<nsyscalls;i++)
  267. if( scnames[i].nr == num ) {
  268. if( scnames[i].result != NULL ) {
  269. scnames[i].result(&scnames[i],ret);
  270. } else {
  271. if( ret < 0 ) {
  272. gemu_log(" = -1 errno=" TARGET_ABI_FMT_ld " (%s)\n", -ret, target_strerror(-ret));
  273. } else {
  274. gemu_log(" = " TARGET_ABI_FMT_ld "\n", ret);
  275. }
  276. }
  277. break;
  278. }
  279. }