shim_parser.c 41 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236
  1. /* -*- mode:c; c-file-style:"k&r"; c-basic-offset: 4; tab-width:4; indent-tabs-mode:nil; mode:auto-fill; fill-column:78; -*- */
  2. /* vim: set ts=4 sw=4 et tw=78 fo=cqt wm=0: */
  3. /* Copyright (C) 2014 Stony Brook University
  4. This file is part of Graphene Library OS.
  5. Graphene Library OS is free software: you can redistribute it and/or
  6. modify it under the terms of the GNU Lesser General Public License
  7. as published by the Free Software Foundation, either version 3 of the
  8. License, or (at your option) any later version.
  9. Graphene Library OS is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU Lesser General Public License for more details.
  13. You should have received a copy of the GNU Lesser General Public License
  14. along with this program. If not, see <http://www.gnu.org/licenses/>. */
  15. /*
  16. * shim_parser.c
  17. *
  18. * This file contains codes for parsing system call arguements for debug
  19. * purpose.
  20. */
  21. #include <shim_internal.h>
  22. #include <shim_tls.h>
  23. #include <shim_table.h>
  24. #include <shim_thread.h>
  25. #include <shim_utils.h>
  26. #include <pal.h>
  27. #include <pal_error.h>
  28. #include <errno.h>
  29. #include <asm/fcntl.h>
  30. #include <asm/unistd.h>
  31. #include <asm/prctl.h>
  32. #include <asm/mman.h>
  33. #include <asm/ioctls.h>
  34. #include <linux/stat.h>
  35. #include <linux/fcntl.h>
  36. #include <linux/sched.h>
  37. #include <linux/futex.h>
  38. #include <linux/wait.h>
  39. #include <linux/in.h>
  40. #include <linux/in6.h>
  41. #include <linux/un.h>
  42. static void parse_open_flags (const char *, va_list *);
  43. static void parse_open_mode (const char *, va_list *);
  44. static void parse_access_mode (const char *, va_list *);
  45. static void parse_clone_flags (const char *, va_list *);
  46. static void parse_mmap_prot (const char *, va_list *);
  47. static void parse_mmap_flags (const char *, va_list *);
  48. static void parse_exec_args (const char *, va_list *);
  49. static void parse_exec_envp (const char *, va_list *);
  50. static void parse_pipe_fds (const char *, va_list *);
  51. static void parse_signum (const char *, va_list *);
  52. static void parse_sigmask (const char *, va_list *);
  53. static void parse_sigprocmask_how (const char *, va_list *);
  54. static void parse_timespec (const char *, va_list *);
  55. static void parse_sockaddr (const char *, va_list *);
  56. static void parse_domain (const char *, va_list *);
  57. static void parse_socktype (const char *, va_list *);
  58. static void parse_futexop (const char *, va_list *);
  59. static void parse_ioctlop (const char *, va_list *);
  60. static void parse_fcntlop (const char *, va_list *);
  61. static void parse_seek (const char *, va_list *);
  62. static void parse_at_fdcwd (const char *, va_list *);
  63. static void parse_wait_option (const char *, va_list *);
  64. struct parser_table {
  65. int slow;
  66. int stop;
  67. void (*parser[6]) (const char *, va_list *);
  68. } syscall_parser_table[LIBOS_SYSCALL_BOUND] = {
  69. { .slow = 1, .parser = { NULL } }, /* read */
  70. { .slow = 1, .parser = { NULL } }, /* write */
  71. { .slow = 1, /* open */
  72. .parser = { NULL, &parse_open_flags, &parse_open_mode, } },
  73. { .slow = 0, .parser = { NULL } }, /* close */
  74. { .slow = 0, .parser = { NULL } }, /* stat */
  75. { .slow = 0, .parser = { NULL } }, /* fstat */
  76. { .slow = 0, .parser = { NULL } }, /* lstat */
  77. { .slow = 1, .parser = { NULL } }, /* poll */
  78. { .slow = 0, .parser = { NULL, NULL, &parse_seek } }, /* lseek */
  79. { .slow = 1, /* mmap */
  80. .parser = { NULL, NULL, &parse_mmap_prot, &parse_mmap_flags } },
  81. { .slow = 1, /* mprotect */
  82. .parser = { NULL, NULL, &parse_mmap_prot } },
  83. { .slow = 1, .parser = { NULL } }, /* munmap */
  84. { .slow = 0, .parser = { NULL } }, /* brk */
  85. { .slow = 0, .parser = { &parse_signum } }, /* rt_sigaction */
  86. { .slow = 0, /* rt_sigprocmask */
  87. .parser = { &parse_sigprocmask_how, &parse_sigmask, &parse_sigmask } },
  88. { .slow = 0, .parser = { NULL } }, /* rt_sigreturn */
  89. { .slow = 1, .parser = { NULL, &parse_ioctlop } }, /* ioctl */
  90. { .slow = 1, .parser = { NULL } }, /* pread64 */
  91. { .slow = 0, .parser = { NULL } }, /* pwrite64 */
  92. { .slow = 1, .parser = { NULL } }, /* readv */
  93. { .slow = 0, .parser = { NULL } }, /* writev */
  94. { .slow = 0, /* access */
  95. .parser = { NULL, &parse_access_mode } },
  96. { .slow = 0, /* pipe */
  97. .parser = { &parse_pipe_fds } },
  98. { .slow = 0, .parser = { NULL } }, /* select */
  99. { .slow = 0, .parser = { NULL } }, /* sched_yield */
  100. { .slow = 0, .parser = { NULL } }, /* mremap */
  101. { .slow = 0, .parser = { NULL } }, /* msync */
  102. { .slow = 0, .parser = { NULL } }, /* mincore */
  103. { .slow = 0, .parser = { NULL } }, /* madvise */
  104. { .slow = 0, .parser = { NULL } }, /* shmget */
  105. { .slow = 0, .parser = { NULL } }, /* shmat */
  106. { .slow = 0, .parser = { NULL } }, /* shmctl */
  107. { .slow = 0, .parser = { NULL } }, /* dup */
  108. { .slow = 0, .parser = { NULL } }, /* dup2 */
  109. { .slow = 0, .parser = { NULL } }, /* pause */
  110. { .slow = 1,
  111. .parser = { &parse_timespec } }, /* nanosleep */
  112. { .slow = 0, .parser = { NULL } }, /* getitimer */
  113. { .slow = 0, .parser = { NULL } }, /* alarm */
  114. { .slow = 0, .parser = { NULL } }, /* setitimer */
  115. { .slow = 0, .parser = { NULL } }, /* getpid */
  116. { .slow = 0, .parser = { NULL } }, /* sendfile */
  117. { .slow = 0, .parser = { &parse_domain, &parse_socktype } }, /* socket */
  118. { .slow = 1, .parser = { NULL, &parse_sockaddr } }, /* connect */
  119. { .slow = 1, .parser = { NULL } }, /* accept */
  120. { .slow = 0, .parser = { NULL } }, /* sendto */
  121. { .slow = 0, .parser = { NULL } }, /* recvfrom */
  122. { .slow = 0, .parser = { NULL } }, /* sendmsg */
  123. { .slow = 1, .parser = { NULL } }, /* recvmsg */
  124. { .slow = 0, .parser = { NULL } }, /* shutdown */
  125. { .slow = 0, .parser = { NULL } }, /* bind */
  126. { .slow = 0, .parser = { NULL } }, /* listen */
  127. { .slow = 0, .parser = { NULL } }, /* getsockname */
  128. { .slow = 0, .parser = { NULL } }, /* getpeername */
  129. { .slow = 0, .stop = 3, /* socketpair */
  130. .parser = { &parse_domain, &parse_socktype, NULL, &parse_pipe_fds } },
  131. { .slow = 0, .parser = { NULL } }, /* setsockopt */
  132. { .slow = 0, .parser = { NULL } }, /* getsockopt */
  133. { .slow = 1, .parser = { &parse_clone_flags } }, /* clone */
  134. { .slow = 1, .parser = { NULL } }, /* fork */
  135. { .slow = 1, .parser = { NULL } }, /* vfork */
  136. { .slow = 1, /* execve */
  137. .parser = { NULL, &parse_exec_args, &parse_exec_envp, } },
  138. { .slow = 0, .parser = { NULL } }, /* exit */
  139. { .slow = 1, .parser = { NULL, NULL,
  140. &parse_wait_option,
  141. NULL } }, /* wait4 */
  142. { .slow = 0, .parser = { NULL, &parse_signum, } }, /* kill */
  143. { .slow = 0, .parser = { NULL } }, /* uname */
  144. { .slow = 0, .parser = { NULL } }, /* semget */
  145. { .slow = 1, .parser = { NULL } }, /* semop */
  146. { .slow = 0, .parser = { NULL } }, /* semctl */
  147. { .slow = 0, .parser = { NULL } }, /* shmdt */
  148. { .slow = 1, .parser = { NULL } }, /* msgget */
  149. { .slow = 1, .parser = { NULL } }, /* msgsnd */
  150. { .slow = 1, .parser = { NULL } }, /* msgrcv */
  151. { .slow = 1, .parser = { NULL } }, /* msgctl */
  152. { .slow = 0, .parser = { NULL, &parse_fcntlop } }, /* fcntl */
  153. { .slow = 0, .parser = { NULL } }, /* flock */
  154. { .slow = 0, .parser = { NULL } }, /* fsync */
  155. { .slow = 0, .parser = { NULL } }, /* fdatasync */
  156. { .slow = 0, .parser = { NULL } }, /* truncate */
  157. { .slow = 0, .parser = { NULL } }, /* ftruncate */
  158. { .slow = 0, .parser = { NULL } }, /* getdents */
  159. { .slow = 0, .parser = { NULL } }, /* getcwd */
  160. { .slow = 0, .parser = { NULL } }, /* chdir */
  161. { .slow = 0, .parser = { NULL } }, /* fchdir */
  162. { .slow = 0, .parser = { NULL } }, /* rename */
  163. { .slow = 0, .parser = { NULL } }, /* mkdir */
  164. { .slow = 0, .parser = { NULL } }, /* rmdir */
  165. { .slow = 0, .parser = { NULL, &parse_open_mode } }, /* creat */
  166. { .slow = 0, .parser = { NULL } }, /* link */
  167. { .slow = 0, .parser = { NULL } }, /* unlink */
  168. { .slow = 0, .parser = { NULL } }, /* symlink */
  169. { .slow = 0, .parser = { NULL } }, /* readlink */
  170. { .slow = 0, .parser = { NULL } }, /* chmod */
  171. { .slow = 0, .parser = { NULL } }, /* fchmod */
  172. { .slow = 0, .parser = { NULL } }, /* chown */
  173. { .slow = 0, .parser = { NULL } }, /* fchown */
  174. { .slow = 0, .parser = { NULL } }, /* lchown */
  175. { .slow = 0, .parser = { NULL } }, /* umask */
  176. { .slow = 0, .parser = { NULL } }, /* gettimeofday */
  177. { .slow = 0, .parser = { NULL } }, /* getrlimit */
  178. { .slow = 0, .parser = { NULL } }, /* getrusage */
  179. { .slow = 0, .parser = { NULL } }, /* sysinfo */
  180. { .slow = 0, .parser = { NULL } }, /* times */
  181. { .slow = 0, .parser = { NULL } }, /* ptrace */
  182. { .slow = 0, .parser = { NULL } }, /* getuid */
  183. { .slow = 0, .parser = { NULL } }, /* syslog */
  184. { .slow = 0, .parser = { NULL } }, /* getgid */
  185. { .slow = 0, .parser = { NULL } }, /* setuid */
  186. { .slow = 0, .parser = { NULL } }, /* setgid */
  187. { .slow = 0, .parser = { NULL } }, /* geteuid */
  188. { .slow = 0, .parser = { NULL } }, /* getegid */
  189. { .slow = 0, .parser = { NULL } }, /* setpgid */
  190. { .slow = 0, .parser = { NULL } }, /* getppid */
  191. { .slow = 0, .parser = { NULL } }, /* getpgrp */
  192. { .slow = 0, .parser = { NULL } }, /* setsid */
  193. { .slow = 0, .parser = { NULL } }, /* setreuid */
  194. { .slow = 0, .parser = { NULL } }, /* setregid */
  195. { .slow = 0, .parser = { NULL } }, /* getgroups */
  196. { .slow = 0, .parser = { NULL } }, /* setgroups */
  197. { .slow = 0, .parser = { NULL } }, /* setresuid */
  198. { .slow = 0, .parser = { NULL } }, /* getresuid */
  199. { .slow = 0, .parser = { NULL } }, /* setresgid */
  200. { .slow = 0, .parser = { NULL } }, /* getresgid */
  201. { .slow = 0, .parser = { NULL } }, /* getpgid */
  202. { .slow = 0, .parser = { NULL } }, /* setfsuid */
  203. { .slow = 0, .parser = { NULL } }, /* setfsgid */
  204. { .slow = 0, .parser = { NULL } }, /* getsid */
  205. { .slow = 0, .parser = { NULL } }, /* capget */
  206. { .slow = 0, .parser = { NULL } }, /* capset */
  207. { .slow = 0, .parser = { NULL } }, /* rt_sigpending */
  208. { .slow = 0, .parser = { NULL } }, /* rt_sigtimedwait */
  209. { .slow = 0, .parser = { NULL } }, /* rt_sigqueueinfo */
  210. { .slow = 1, .parser = { NULL } }, /* rt_sigsuspend */
  211. { .slow = 0, .parser = { NULL } }, /* sigaltstack */
  212. { .slow = 0, .parser = { NULL } }, /* utime */
  213. { .slow = 0, .parser = { NULL } }, /* mknod */
  214. { .slow = 0, .parser = { NULL } }, /* uselib */
  215. { .slow = 0, .parser = { NULL } }, /* personality */
  216. { .slow = 0, .parser = { NULL } }, /* ustat */
  217. { .slow = 0, .parser = { NULL } }, /* statfs */
  218. { .slow = 0, .parser = { NULL } }, /* fstatfs */
  219. { .slow = 0, .parser = { NULL } }, /* sysfs */
  220. { .slow = 0, .parser = { NULL } }, /* getpriority */
  221. { .slow = 0, .parser = { NULL } }, /* setpriority */
  222. { .slow = 0, .parser = { NULL } }, /* sched_setparam */
  223. { .slow = 0, .parser = { NULL } }, /* sched_getparam */
  224. { .slow = 0, .parser = { NULL } }, /* sched_setscheduler */
  225. { .slow = 0, .parser = { NULL } }, /* sched_getscheduler */
  226. { .slow = 0, .parser = { NULL } }, /* sched_get_priority_max */
  227. { .slow = 0, .parser = { NULL } }, /* sched_get_priority_min */
  228. { .slow = 0, .parser = { NULL } }, /* sched_rr_get_interval */
  229. { .slow = 0, .parser = { NULL } }, /* mlock */
  230. { .slow = 0, .parser = { NULL } }, /* munlock */
  231. { .slow = 0, .parser = { NULL } }, /* mlockall */
  232. { .slow = 0, .parser = { NULL } }, /* munlockall */
  233. { .slow = 0, .parser = { NULL } }, /* vhangup */
  234. { .slow = 0, .parser = { NULL } }, /* modify_ldt */
  235. { .slow = 0, .parser = { NULL } }, /* pivot_root */
  236. { .slow = 0, .parser = { NULL } }, /* _sysctl */
  237. { .slow = 0, .parser = { NULL } }, /* prctl */
  238. { .slow = 0, .parser = { NULL } }, /* arch_prctl */
  239. { .slow = 0, .parser = { NULL } }, /* adjtimex */
  240. { .slow = 0, .parser = { NULL } }, /* setrlimit */
  241. { .slow = 0, .parser = { NULL } }, /* chroot */
  242. { .slow = 0, .parser = { NULL } }, /* sync */
  243. { .slow = 0, .parser = { NULL } }, /* acct */
  244. { .slow = 0, .parser = { NULL } }, /* settimeofday */
  245. { .slow = 0, .parser = { NULL } }, /* mount */
  246. { .slow = 0, .parser = { NULL } }, /* umount2 */
  247. { .slow = 0, .parser = { NULL } }, /* swapon */
  248. { .slow = 0, .parser = { NULL } }, /* swapoff */
  249. { .slow = 0, .parser = { NULL } }, /* reboot */
  250. { .slow = 0, .parser = { NULL } }, /* sethostname */
  251. { .slow = 0, .parser = { NULL } }, /* setdomainname */
  252. { .slow = 0, .parser = { NULL } }, /* iopl */
  253. { .slow = 0, .parser = { NULL } }, /* ioperm */
  254. { .slow = 0, .parser = { NULL } }, /* create_module */
  255. { .slow = 0, .parser = { NULL } }, /* init_module */
  256. { .slow = 0, .parser = { NULL } }, /* delete_module */
  257. { .slow = 0, .parser = { NULL } }, /* get_kernel_syms */
  258. { .slow = 0, .parser = { NULL } }, /* query_module */
  259. { .slow = 0, .parser = { NULL } }, /* quotactl */
  260. { .slow = 0, .parser = { NULL } }, /* nfsservctl */
  261. { .slow = 0, .parser = { NULL } }, /* getpmsg */
  262. { .slow = 0, .parser = { NULL } }, /* putpmsg */
  263. { .slow = 0, .parser = { NULL } }, /* afs_syscall */
  264. { .slow = 0, .parser = { NULL } }, /* tuxcall */
  265. { .slow = 0, .parser = { NULL } }, /* security */
  266. { .slow = 0, .parser = { NULL } }, /* gettid */
  267. { .slow = 0, .parser = { NULL } }, /* readahead */
  268. { .slow = 0, .parser = { NULL } }, /* setxattr */
  269. { .slow = 0, .parser = { NULL } }, /* lsetxattr */
  270. { .slow = 0, .parser = { NULL } }, /* fsetxattr */
  271. { .slow = 0, .parser = { NULL } }, /* getxattr */
  272. { .slow = 0, .parser = { NULL } }, /* lgetxattr */
  273. { .slow = 0, .parser = { NULL } }, /* fgetxattr */
  274. { .slow = 0, .parser = { NULL } }, /* listxattr */
  275. { .slow = 0, .parser = { NULL } }, /* llistxattr */
  276. { .slow = 0, .parser = { NULL } }, /* flistxattr */
  277. { .slow = 0, .parser = { NULL } }, /* removexattr */
  278. { .slow = 0, .parser = { NULL } }, /* lremovexattr */
  279. { .slow = 0, .parser = { NULL } }, /* fremovexattr */
  280. { .slow = 0, .parser = { NULL, &parse_signum } }, /* tkill */
  281. { .slow = 0, .parser = { NULL } }, /* time */
  282. { .slow = 1, .parser = { NULL, &parse_futexop } }, /* futex */
  283. { .slow = 0, .parser = { NULL } }, /* sched_setaffinity */
  284. { .slow = 0, .parser = { NULL } }, /* sched_getaffinity */
  285. { .slow = 0, .parser = { NULL } }, /* set_thread_area */
  286. { .slow = 0, .parser = { NULL } }, /* io_setup */
  287. { .slow = 0, .parser = { NULL } }, /* io_destroy */
  288. { .slow = 0, .parser = { NULL } }, /* io_getevents */
  289. { .slow = 0, .parser = { NULL } }, /* io_submit */
  290. { .slow = 0, .parser = { NULL } }, /* io_cancel */
  291. { .slow = 0, .parser = { NULL } }, /* get_thread_area */
  292. { .slow = 0, .parser = { NULL } }, /* lookup_dcookie */
  293. { .slow = 0, .parser = { NULL } }, /* epoll_create */
  294. { .slow = 0, .parser = { NULL } }, /* epoll_ctl_old */
  295. { .slow = 0, .parser = { NULL } }, /* epoll_wait_old */
  296. { .slow = 0, .parser = { NULL } }, /* remap_file_pages */
  297. { .slow = 0, .parser = { NULL } }, /* getdents64 */
  298. { .slow = 0, .parser = { NULL } }, /* set_tid_address */
  299. { .slow = 0, .parser = { NULL } }, /* restart_syscall */
  300. { .slow = 0, .parser = { NULL } }, /* semtimedop */
  301. { .slow = 0, .parser = { NULL } }, /* fadvise64 */
  302. { .slow = 0, .parser = { NULL } }, /* timer_create */
  303. { .slow = 0, .parser = { NULL } }, /* timer_settime */
  304. { .slow = 0, .parser = { NULL } }, /* timer_gettime */
  305. { .slow = 0, .parser = { NULL } }, /* timer_getoverrun */
  306. { .slow = 0, .parser = { NULL } }, /* timer_delete */
  307. { .slow = 0, .parser = { NULL } }, /* clock_settime */
  308. { .slow = 0, .parser = { NULL } }, /* clock_gettime */
  309. { .slow = 0, .parser = { NULL } }, /* clock_getres */
  310. { .slow = 0, .parser = { NULL } }, /* clock_nanosleep */
  311. { .slow = 0, .parser = { NULL } }, /* exit_group */
  312. { .slow = 1, .parser = { NULL } }, /* epoll_wait */
  313. { .slow = 0, .parser = { NULL } }, /* epoll_ctl */
  314. { .slow = 0,
  315. .parser = { NULL, NULL, &parse_signum } }, /* tgkill */
  316. { .slow = 0, .parser = { NULL } }, /* utimes */
  317. { .slow = 0, .parser = { NULL } }, /* vserver */
  318. { .slow = 0, .parser = { NULL } }, /* mbind */
  319. { .slow = 0, .parser = { NULL } }, /* set_mempolicy */
  320. { .slow = 0, .parser = { NULL } }, /* get_mempolicy */
  321. { .slow = 0, .parser = { NULL } }, /* mq_open */
  322. { .slow = 0, .parser = { NULL } }, /* mq_unlink */
  323. { .slow = 0, .parser = { NULL } }, /* mq_timedsend */
  324. { .slow = 0, .parser = { NULL } }, /* mq_timedreceive */
  325. { .slow = 0, .parser = { NULL } }, /* mq_notify */
  326. { .slow = 0, .parser = { NULL } }, /* mq_getsetattr */
  327. { .slow = 0, .parser = { NULL } }, /* kexec_load */
  328. { .slow = 1, .parser = { NULL } }, /* waitid */
  329. { .slow = 0, .parser = { NULL } }, /* add_key */
  330. { .slow = 0, .parser = { NULL } }, /* request_key */
  331. { .slow = 0, .parser = { NULL } }, /* keyctl */
  332. { .slow = 0, .parser = { NULL } }, /* ioprio_set */
  333. { .slow = 0, .parser = { NULL } }, /* ioprio_get */
  334. { .slow = 0, .parser = { NULL } }, /* inotify_init */
  335. { .slow = 0, .parser = { NULL } }, /* inotify_add_watch */
  336. { .slow = 0, .parser = { NULL } }, /* inotify_rm_watch */
  337. { .slow = 0, .parser = { NULL } }, /* migrate_pages */
  338. { .slow = 0, .parser = { &parse_at_fdcwd, NULL,
  339. &parse_open_flags,
  340. &parse_open_mode } }, /* openat */
  341. { .slow = 0, .parser = { &parse_at_fdcwd, } }, /* mkdirat */
  342. { .slow = 0, .parser = { &parse_at_fdcwd, } }, /* mknodat */
  343. { .slow = 0, .parser = { &parse_at_fdcwd, } }, /* fchownat */
  344. { .slow = 0, .parser = { &parse_at_fdcwd, } }, /* futimesat */
  345. { .slow = 0, .parser = { &parse_at_fdcwd, } }, /* newfstatat */
  346. { .slow = 0, .parser = { &parse_at_fdcwd, } }, /* unlinkat */
  347. { .slow = 0, .parser = { &parse_at_fdcwd, } }, /* renameat */
  348. { .slow = 0, .parser = { &parse_at_fdcwd, } }, /* linkat */
  349. { .slow = 0, .parser = { &parse_at_fdcwd, } }, /* symlinkat */
  350. { .slow = 0, .parser = { &parse_at_fdcwd, } }, /* readlinkat */
  351. { .slow = 0, .parser = { &parse_at_fdcwd, } }, /* fchmodat */
  352. { .slow = 0, .parser = { &parse_at_fdcwd, } }, /* faccessat */
  353. { .slow = 0, .parser = { NULL } }, /* pselect6 */
  354. { .slow = 1, .parser = { NULL } }, /* ppoll */
  355. { .slow = 0, .parser = { NULL } }, /* unshare */
  356. { .slow = 0, .parser = { NULL } }, /* set_robust_list */
  357. { .slow = 0, .parser = { NULL } }, /* get_robust_list */
  358. { .slow = 0, .parser = { NULL } }, /* splice */
  359. { .slow = 0, .parser = { NULL } }, /* tee */
  360. { .slow = 0, .parser = { NULL } }, /* sync_file_range */
  361. { .slow = 0, .parser = { NULL } }, /* vmsplice */
  362. { .slow = 0, .parser = { NULL } }, /* move_pages */
  363. { .slow = 0, .parser = { NULL } }, /* utimensat */
  364. { .slow = 1, .parser = { NULL } }, /* epoll_pwait */
  365. { .slow = 0, .parser = { NULL } }, /* signalfd */
  366. { .slow = 0, .parser = { NULL } }, /* timerfd_create */
  367. { .slow = 0, .parser = { NULL } }, /* eventfd */
  368. { .slow = 0, .parser = { NULL } }, /* fallocate */
  369. { .slow = 0, .parser = { NULL } }, /* timerfd_settime */
  370. { .slow = 0, .parser = { NULL } }, /* timerfd_gettime */
  371. { .slow = 1, .parser = { NULL } }, /* accept4 */
  372. { .slow = 0, .parser = { NULL } }, /* signalfd4 */
  373. { .slow = 0, .parser = { NULL } }, /* eventfd2 */
  374. { .slow = 0, .parser = { NULL } }, /* epoll_create1 */
  375. { .slow = 0, .parser = { NULL } }, /* dup3 */
  376. { .slow = 0, .parser = { NULL } }, /* pipe2 */
  377. { .slow = 0, .parser = { NULL } }, /* inotify_init1 */
  378. { .slow = 0, .parser = { NULL } }, /* preadv */
  379. { .slow = 0, .parser = { NULL } }, /* pwritev */
  380. { .slow = 0, .parser = { NULL } }, /* rt_tgsigqueueinfo */
  381. { .slow = 0, .parser = { NULL } }, /* perf_event_open */
  382. { .slow = 0, .parser = { NULL } }, /* recvmmsg */
  383. [LIBOS_SYSCALL_BASE] = { .slow = 0, .parser = { NULL } },
  384. { .slow = 1, .parser = { NULL } }, /* checkpoint */
  385. { .slow = 1, .parser = { NULL } }, /* restore */
  386. { .slow = 1, .parser = { NULL } }, /* sandbox_create */
  387. { .slow = 0, .parser = { NULL } }, /* sandbox_attach */
  388. { .slow = 0, .parser = { NULL } }, /* sandbox_current */
  389. { .slow = 1, .parser = { NULL } }, /* msgpersist */
  390. { .slow = 1, .parser = { NULL } }, /* benchmark_ipc */
  391. { .slow = 1, .parser = { NULL } }, /* send_rpc */
  392. { .slow = 1, .parser = { NULL } }, /* recv_rpc */
  393. };
  394. static inline int is_pointer (const char * type)
  395. {
  396. return type[strlen(type) - 1] == '*'
  397. || strcmp_static(type, "long")
  398. || strcmp_static(type, "unsigned long");
  399. }
  400. #define PRINTF(fmt, ...) \
  401. do { \
  402. debug_printf((fmt), __VA_ARGS__); \
  403. } while (0)
  404. #define PUTS(str) \
  405. do { \
  406. debug_puts((str)); \
  407. } while (0)
  408. #define PUTCH(ch) \
  409. do { \
  410. debug_putch((ch)); \
  411. } while (0)
  412. #define VPRINTF(fmt, ap) \
  413. do { \
  414. debug_vprintf((fmt), (ap)); \
  415. } while (0)
  416. static inline void parse_string_arg (va_list * ap)
  417. {
  418. VPRINTF("\"%s\"", ap);
  419. }
  420. static inline void parse_pointer_arg (va_list * ap)
  421. {
  422. VPRINTF("%p", ap);
  423. }
  424. static inline void parse_integer_arg (va_list * ap)
  425. {
  426. VPRINTF("%d", ap);
  427. }
  428. static inline void parse_syscall_args (va_list * ap)
  429. {
  430. const char * arg_type = va_arg(*ap, const char *);
  431. if (strcmp_static(arg_type, "const char *"))
  432. parse_string_arg(ap);
  433. else if (is_pointer(arg_type))
  434. parse_pointer_arg(ap);
  435. else
  436. parse_integer_arg(ap);
  437. }
  438. static inline void skip_syscall_args (va_list * ap)
  439. {
  440. const char * arg_type = va_arg(*ap, const char *);
  441. if (strcmp_static(arg_type, "const char *"))
  442. va_arg(*ap, const char *);
  443. else if (is_pointer(arg_type))
  444. va_arg(*ap, void *);
  445. else
  446. va_arg(*ap, int);
  447. }
  448. void sysparser_printf (const char * fmt, ...)
  449. {
  450. va_list ap;
  451. va_start(ap, fmt);
  452. VPRINTF(fmt, &ap);
  453. va_end(ap);
  454. }
  455. void parse_syscall_before (int sysno, const char * name, int nr, ...)
  456. {
  457. if (!debug_handle)
  458. return;
  459. struct parser_table * parser = &syscall_parser_table[sysno];
  460. if (!parser->slow && !parser->stop)
  461. return;
  462. va_list ap;
  463. va_start(ap, nr);
  464. PRINTF("---- shim_%s(", name);
  465. for (int i = 0 ; i < nr ; i++) {
  466. if (parser->stop && parser->stop == i)
  467. goto dotdotdot;
  468. if (i)
  469. PUTCH(',');
  470. if (parser->parser[i]) {
  471. const char * type = va_arg(ap, const char *);
  472. (*parser->parser[i])(type, &ap);
  473. } else
  474. parse_syscall_args(&ap);
  475. }
  476. PUTCH(')');
  477. dotdotdot:
  478. PRINTF(" ...\n", name);
  479. va_end(ap);
  480. }
  481. void parse_syscall_after (int sysno, const char * name, int nr, ...)
  482. {
  483. if (!debug_handle)
  484. return;
  485. struct parser_table * parser = &syscall_parser_table[sysno];
  486. va_list ap;
  487. va_start(ap, nr);
  488. const char * ret_type = va_arg(ap, const char *);
  489. if (parser->slow || parser->stop)
  490. PRINTF("---- return from shim_%s(...", name);
  491. else
  492. PRINTF("---- shim_%s(", name);
  493. unsigned long ret_ptr;
  494. int ret_val;
  495. if (is_pointer(ret_type))
  496. ret_ptr = (unsigned long) va_arg(ap, void *);
  497. else
  498. ret_val = va_arg(ap, int);
  499. if (!parser->slow || parser->stop)
  500. for (int i = 0 ; i < nr ; i++) {
  501. if (parser->stop && i < parser->stop) {
  502. skip_syscall_args(&ap);
  503. continue;
  504. }
  505. if (i)
  506. PUTCH(',');
  507. if (parser->parser[i]) {
  508. const char * type = va_arg(ap, const char *);
  509. (*parser->parser[i])(type, &ap);
  510. } else
  511. parse_syscall_args(&ap);
  512. }
  513. if (is_pointer(ret_type)) {
  514. if (ret_ptr < -4095L)
  515. PRINTF(") = %p\n", ret_ptr);
  516. else
  517. PRINTF(") = %ld\n", (long) ret_ptr);
  518. } else {
  519. if (ret_val >= 0)
  520. PRINTF(") = %d\n", ret_val);
  521. else
  522. PRINTF(") = %d\n", ret_val);
  523. }
  524. va_end (ap);
  525. }
  526. static void parse_open_flags (const char * type, va_list * ap)
  527. {
  528. int flags = va_arg(*ap, int);
  529. if (flags & O_WRONLY) {
  530. PUTS("O_WRONLY");
  531. flags &= ~O_WRONLY;
  532. } else if (flags & O_RDWR) {
  533. PUTS("O_RDWR");
  534. flags &= ~O_RDWR;
  535. } else
  536. PUTS("O_RDONLY");
  537. if (flags & O_APPEND) {
  538. PUTS("|O_APPEND");
  539. flags &= ~O_APPEND;
  540. }
  541. if (flags & O_CREAT) {
  542. PUTS("|O_CREAT");
  543. flags &= ~O_CREAT;
  544. }
  545. if (flags & O_TRUNC) {
  546. PUTS("|O_TRUNC");
  547. flags &= ~O_TRUNC;
  548. }
  549. if (flags & O_EXCL) {
  550. PUTS("|O_EXCL");
  551. flags &= ~O_EXCL;
  552. }
  553. if (flags)
  554. PRINTF("|%o", flags);
  555. }
  556. static void parse_open_mode (const char * type, va_list * ap)
  557. {
  558. VPRINTF("%04o", ap);
  559. }
  560. static void parse_access_mode (const char * type, va_list * ap)
  561. {
  562. int mode = va_arg(*ap, int);
  563. PUTS("F_OK");
  564. if (mode) {
  565. if (mode & R_OK)
  566. PUTS("|R_OK");
  567. if (mode & W_OK)
  568. PUTS("|W_OK");
  569. if (mode & X_OK)
  570. PUTS("|X_OK");
  571. }
  572. }
  573. static void parse_clone_flags (const char * type, va_list * ap)
  574. {
  575. int flags = va_arg(*ap, int);
  576. #define FLG(n) { "CLONE_" #n, CLONE_##n, }
  577. const struct {
  578. const char * name; int flag;
  579. } all_flags[] = {
  580. FLG(VM), FLG(FS), FLG(FILES), FLG(SIGHAND), FLG(PTRACE), FLG(VFORK),
  581. FLG(PARENT), FLG(THREAD), FLG(NEWNS), FLG(SYSVSEM), FLG(SETTLS),
  582. FLG(PARENT_SETTID), FLG(CHILD_CLEARTID), FLG(DETACHED), FLG(UNTRACED),
  583. FLG(CHILD_SETTID), FLG(NEWUTS), FLG(NEWIPC), FLG(NEWUSER),
  584. FLG(NEWPID), FLG(NEWNET), FLG(IO),
  585. };
  586. #undef FLG
  587. bool printed = false;
  588. for (int i = 0 ; i < sizeof(all_flags) / sizeof(all_flags[0]) ; i++)
  589. if (flags & all_flags[i].flag) {
  590. if (printed)
  591. PUTCH('|');
  592. else
  593. printed = true;
  594. PUTS(all_flags[i].name);
  595. flags &= ~all_flags[i].flag;
  596. }
  597. if (flags)
  598. PRINTF("|0x%x", flags);
  599. }
  600. static void parse_mmap_prot (const char * type, va_list * ap)
  601. {
  602. int prot = va_arg(*ap, int);
  603. int nflags = 0;
  604. if (prot == PROT_NONE) {
  605. PUTS("PROT_NONE");
  606. return;
  607. }
  608. if (prot & PROT_READ) {
  609. if (nflags++)
  610. PUTS("|");
  611. PUTS("PROT_READ");
  612. }
  613. if (prot & PROT_WRITE) {
  614. if (nflags++)
  615. PUTS("|");
  616. PUTS("PROT_WRITE");
  617. }
  618. if (prot & PROT_EXEC) {
  619. if (nflags++)
  620. PUTS("|");
  621. PUTS("PROT_EXEC");
  622. }
  623. }
  624. static void parse_mmap_flags (const char * type, va_list * ap)
  625. {
  626. int flags = va_arg(*ap, int);
  627. if (flags & MAP_SHARED) {
  628. PUTS("MAP_SHARED");
  629. flags &= ~MAP_SHARED;
  630. }
  631. if (flags & MAP_PRIVATE) {
  632. PUTS("MAP_PRIVATE");
  633. flags &= ~MAP_PRIVATE;
  634. }
  635. if (flags & MAP_ANONYMOUS) {
  636. PUTS("|MAP_ANON");
  637. flags &= ~MAP_ANONYMOUS;
  638. }
  639. if (flags & MAP_FILE) {
  640. PUTS("|MAP_FILE");
  641. flags &= ~MAP_FILE;
  642. }
  643. if (flags & MAP_FIXED) {
  644. PUTS("|MAP_FIXED");
  645. flags &= ~MAP_FIXED;
  646. }
  647. #ifdef CONFIG_MMAP_ALLOW_UNINITIALIZED
  648. if (flags & MAP_UNINITIALIZED) {
  649. PUTS("|MAP_UNINITIALIZED");
  650. flags &= ~MAP_UNINITIALIZED;
  651. }
  652. #endif
  653. if (flags)
  654. PRINTF("|0x%x", flags);
  655. }
  656. static void parse_exec_args (const char * type, va_list * ap)
  657. {
  658. const char ** args = va_arg(*ap, const char **);
  659. PUTS("[");
  660. for (; *args ; args++) {
  661. PUTS(*args);
  662. PUTS(",");
  663. }
  664. PUTS("]");
  665. }
  666. static void parse_exec_envp (const char * type, va_list * ap)
  667. {
  668. const char ** envp = va_arg(*ap, const char **);
  669. if (!envp) {
  670. PUTS("NULL");
  671. return;
  672. }
  673. int cnt = 0;
  674. PUTS("[");
  675. for (; *envp ; envp++)
  676. if (cnt++ < 2) {
  677. PUTS(*envp);
  678. PUTS(",");
  679. }
  680. if (cnt > 2)
  681. PRINTF("(%d more)", cnt);
  682. PUTS("]");
  683. }
  684. static void parse_pipe_fds (const char * type, va_list * ap)
  685. {
  686. int * fds = va_arg(*ap, int *);
  687. PRINTF("[%d, %d]", fds[0], fds[1]);
  688. }
  689. #define S(sig) #sig
  690. const char *const siglist[NUM_KNOWN_SIGS + 1] =
  691. {
  692. S(SIGUNUSED),
  693. S(SIGHUP),
  694. S(SIGINT),
  695. S(SIGQUIT),
  696. S(SIGILL),
  697. S(SIGTRAP),
  698. S(SIGABRT),
  699. S(SIGBUS),
  700. S(SIGFPE),
  701. S(SIGKILL),
  702. S(SIGUSR1),
  703. S(SIGSEGV),
  704. S(SIGUSR2),
  705. S(SIGPIPE),
  706. S(SIGALRM),
  707. S(SIGTERM),
  708. S(SIGSTKFLT),
  709. S(SIGCHLD),
  710. S(SIGCONT),
  711. S(SIGSTOP),
  712. S(SIGTSTP),
  713. S(SIGTTIN),
  714. S(SIGTTOU),
  715. S(SIGURG),
  716. S(SIGXCPU),
  717. S(SIGXFSZ),
  718. S(SIGVTALRM),
  719. S(SIGPROF),
  720. S(SIGWINCH),
  721. S(SIGIO),
  722. S(SIGPWR),
  723. S(SIGSYS),
  724. S(SIGRTMIN),
  725. };
  726. static void parse_signum (const char * type, va_list * ap)
  727. {
  728. unsigned int signum = va_arg(*ap, unsigned int);
  729. if (signum >= 0 && signum <= NUM_KNOWN_SIGS)
  730. PUTS(signal_name(signum));
  731. else
  732. PRINTF("[SIG %d]", signum);
  733. }
  734. static void parse_sigmask (const char * type, va_list * ap)
  735. {
  736. __sigset_t * sigset = va_arg(*ap, __sigset_t *);
  737. if (!sigset) {
  738. PUTS("NULL");
  739. return;
  740. }
  741. PUTS("[");
  742. for (int signum = 1 ; signum <= sizeof(sigset) * 8 ; signum++)
  743. if (__sigismember(sigset, signum)) {
  744. PUTS(signal_name(signum));
  745. PUTS(",");
  746. }
  747. PUTS("]");
  748. }
  749. static void parse_sigprocmask_how (const char * type, va_list * ap)
  750. {
  751. int how = va_arg(*ap, int);
  752. switch (how) {
  753. case SIG_BLOCK:
  754. PUTS("BLOCK");
  755. break;
  756. case SIG_UNBLOCK:
  757. PUTS("UNBLOCK");
  758. break;
  759. case SIG_SETMASK:
  760. PUTS("SETMASK");
  761. break;
  762. default:
  763. PUTS("<unknown>");
  764. break;
  765. }
  766. }
  767. static void parse_timespec (const char * type, va_list * ap)
  768. {
  769. const struct timespec * tv = va_arg(*ap, const struct timespec *);
  770. if (!tv) {
  771. PUTS("NULL");
  772. return;
  773. }
  774. PRINTF("[%ld,%lld]", tv->tv_sec, tv->tv_nsec);
  775. }
  776. static void parse_sockaddr (const char * type, va_list *ap)
  777. {
  778. const struct sockaddr *addr = va_arg(*ap, const struct sockaddr *);
  779. if (!addr) {
  780. PUTS("NULL");
  781. return;
  782. }
  783. switch (addr->sa_family) {
  784. case AF_INET: {
  785. struct sockaddr_in * a = (void *) addr;
  786. unsigned char * ip = (void *) &a->sin_addr.s_addr;
  787. PRINTF("{family=INET,ip=%u.%u.%u.%u,port=htons(%u)}",
  788. ip[0], ip[1], ip[2], ip[3], __ntohs(a->sin_port));
  789. break;
  790. }
  791. case AF_INET6: {
  792. struct sockaddr_in6 * a = (void *) addr;
  793. unsigned short * ip = (void *) &a->sin6_addr.s6_addr;
  794. PRINTF("{family=INET,ip=[%x:%x:%x:%x:%x:%x:%x:%x],"
  795. "port=htons(%u)}",
  796. __ntohs(ip[0]), __ntohs(ip[1]),
  797. __ntohs(ip[2]), __ntohs(ip[3]),
  798. __ntohs(ip[4]), __ntohs(ip[5]),
  799. __ntohs(ip[6]), __ntohs(ip[7]),
  800. __ntohs(a->sin6_port));
  801. break;
  802. }
  803. case AF_UNIX: {
  804. struct sockaddr_un * a = (void *) addr;
  805. PRINTF("{family=UNIX,path=%s}", a->sun_path);
  806. break;
  807. }
  808. default:
  809. PUTS("UNKNOWN");
  810. break;
  811. }
  812. }
  813. static void parse_domain (const char * type, va_list * ap)
  814. {
  815. int domain = va_arg(*ap, int);
  816. #define PF_UNSPEC 0 /* Unspecified. */
  817. #define PF_INET 2 /* IP protocol family. */
  818. #define PF_AX25 3 /* Amateur Radio AX.25. */
  819. #define PF_IPX 4 /* Novell Internet Protocol. */
  820. #define PF_APPLETALK 5 /* Appletalk DDP. */
  821. #define PF_ATMPVC 8 /* ATM PVCs. */
  822. #define PF_X25 9 /* Reserved for X.25 project. */
  823. #define PF_INET6 10 /* IP version 6. */
  824. #define PF_NETLINK 16
  825. #define PF_PACKET 17 /* Packet family. */
  826. switch (domain) {
  827. case PF_UNSPEC:
  828. PUTS("UNSPEC");
  829. break;
  830. case PF_UNIX:
  831. PUTS("UNIX");
  832. break;
  833. case PF_INET:
  834. PUTS("INET");
  835. break;
  836. case PF_INET6:
  837. PUTS("INET6");
  838. break;
  839. case PF_IPX:
  840. PUTS("IPX");
  841. break;
  842. case PF_NETLINK:
  843. PUTS("NETLINK");
  844. break;
  845. case PF_X25:
  846. PUTS("X25");
  847. break;
  848. case PF_AX25:
  849. PUTS("AX25");
  850. break;
  851. case PF_ATMPVC:
  852. PUTS("ATMPVC");
  853. break;
  854. case PF_APPLETALK:
  855. PUTS("APPLETALK");
  856. break;
  857. case PF_PACKET:
  858. PUTS("PACKET");
  859. break;
  860. default:
  861. PUTS("UNKNOWN");
  862. break;
  863. }
  864. }
  865. static void parse_socktype (const char * type, va_list * ap)
  866. {
  867. int socktype = va_arg(*ap, int);
  868. if (socktype & SOCK_NONBLOCK) {
  869. socktype &= ~SOCK_NONBLOCK;
  870. PUTS("SOCK_NONBLOCK|");
  871. }
  872. if (socktype & SOCK_CLOEXEC) {
  873. socktype &= ~SOCK_CLOEXEC;
  874. PUTS("SOCK_CLOEXEC|");
  875. }
  876. #define SOCK_RAW 3 /* Raw protocol interface. */
  877. #define SOCK_RDM 4 /* Reliably-delivered messages. */
  878. #define SOCK_SEQPACKET 5 /* Sequenced, reliable, connection-based, */
  879. #define SOCK_DCCP 6 /* Datagram Congestion Control Protocol. */
  880. #define SOCK_PACKET 10 /* Linux specific way of getting packets */
  881. switch (socktype) {
  882. case SOCK_STREAM:
  883. PUTS("STREAM");
  884. break;
  885. case SOCK_DGRAM:
  886. PUTS("DGRAM");
  887. break;
  888. case SOCK_SEQPACKET:
  889. PUTS("SEQPACKET");
  890. break;
  891. case SOCK_RAW:
  892. PUTS("RAW");
  893. break;
  894. case SOCK_RDM:
  895. PUTS("RDM");
  896. break;
  897. case SOCK_PACKET:
  898. PUTS("PACKET");
  899. break;
  900. default:
  901. PUTS("UNKNOWN");
  902. break;
  903. }
  904. }
  905. static void parse_futexop (const char * type, va_list * ap)
  906. {
  907. int op = va_arg(*ap, int);
  908. #ifdef FUTEX_PRIVATE_FLAG
  909. if (op & FUTEX_PRIVATE_FLAG) {
  910. PUTS("FUTEX_PRIVATE|");
  911. op &= ~FUTEX_PRIVATE_FLAG;
  912. }
  913. #endif
  914. #ifdef FUTEX_CLOCK_REALTIME
  915. if (op & FUTEX_CLOCK_REALTIME) {
  916. PUTS("FUTEX_CLOCK_REALTIME|");
  917. op &= ~FUTEX_CLOCK_REALTIME;
  918. }
  919. #endif
  920. op &= FUTEX_CMD_MASK;
  921. switch (op) {
  922. case FUTEX_WAIT:
  923. PUTS("FUTEX_WAIT");
  924. break;
  925. case FUTEX_WAIT_BITSET:
  926. PUTS("FUTEX_WAIT_BITSET");
  927. break;
  928. case FUTEX_WAKE:
  929. PUTS("FUTEX_WAKE");
  930. break;
  931. case FUTEX_WAKE_BITSET:
  932. PUTS("FUTEX_WAKE_BITSET");
  933. break;
  934. case FUTEX_FD:
  935. PUTS("FUTEX_FD");
  936. break;
  937. case FUTEX_REQUEUE:
  938. PUTS("FUTEX_REQUEUE");
  939. break;
  940. case FUTEX_CMP_REQUEUE:
  941. PUTS("FUTEX_CMP_REQUEUE");
  942. break;
  943. case FUTEX_WAKE_OP:
  944. PUTS("FUTEX_WAKE_OP");
  945. break;
  946. default:
  947. PRINTF("OP %d", op);
  948. break;
  949. }
  950. }
  951. static void parse_fcntlop (const char * type, va_list * ap)
  952. {
  953. int op = va_arg(*ap, int);
  954. switch (op) {
  955. case F_DUPFD:
  956. PUTS("F_DUPFD");
  957. break;
  958. case F_GETFD:
  959. PUTS("F_GETFD");
  960. break;
  961. case F_SETFD:
  962. PUTS("F_SETFD");
  963. break;
  964. case F_GETFL:
  965. PUTS("F_GETFL");
  966. break;
  967. case F_SETFL:
  968. PUTS("F_SETFL");
  969. break;
  970. case F_GETLK:
  971. PUTS("F_GETLK");
  972. break;
  973. case F_SETLK:
  974. PUTS("F_SETLK");
  975. break;
  976. case F_SETLKW:
  977. PUTS("F_SETLKW");
  978. break;
  979. case F_SETOWN:
  980. PUTS("F_SETOWN");
  981. break;
  982. case F_GETOWN:
  983. PUTS("F_GETOWN");
  984. break;
  985. case F_SETSIG:
  986. PUTS("F_SETSIG");
  987. break;
  988. case F_GETSIG:
  989. PUTS("F_GETSIG");
  990. break;
  991. case F_GETLK64:
  992. PUTS("F_GETLK64");
  993. break;
  994. case F_SETLK64:
  995. PUTS("F_SETLK64");
  996. break;
  997. case F_SETLKW64:
  998. PUTS("F_SETLKW64");
  999. break;
  1000. case F_SETOWN_EX:
  1001. PUTS("F_SETOWN_EX");
  1002. break;
  1003. case F_GETOWN_EX:
  1004. PUTS("F_GETOWN_EX");
  1005. break;
  1006. case F_GETOWNER_UIDS:
  1007. PUTS("F_GETOWNER_UIDS");
  1008. break;
  1009. default:
  1010. PRINTF("OP %d", op);
  1011. break;
  1012. }
  1013. }
  1014. static void parse_ioctlop (const char * type, va_list * ap)
  1015. {
  1016. int op = va_arg(*ap, int);
  1017. if (op >= TCGETS && op <= TIOCVHANGUP) {
  1018. const char * opnames[] = {
  1019. "TCGETS", /* 0x5401 */ "TCSETS", /* 0x5402 */
  1020. "TCSETSW", /* 0x5403 */ "TCSETSF", /* 0x5404 */
  1021. "TCGETA", /* 0x5405 */ "TCSETA", /* 0x5406 */
  1022. "TCSETAW", /* 0x5407 */ "TCSETAF", /* 0x5408 */
  1023. "TCSBRK", /* 0x5409 */ "TCXONC", /* 0x540A */
  1024. "TCFLSH", /* 0x540B */ "TIOCEXCL", /* 0x540C */
  1025. "TIOCNXCL", /* 0x540D */ "TIOCSCTTY", /* 0x540E */
  1026. "TIOCGPGRP", /* 0x540F */ "TIOCSPGRP", /* 0x5410 */
  1027. "TIOCOUTQ", /* 0x5411 */ "TIOCSTI", /* 0x5412 */
  1028. "TIOCGWINSZ", /* 0x5413 */ "TIOCSWINSZ", /* 0x5414 */
  1029. "TIOCMGET", /* 0x5415 */ "TIOCMBIS", /* 0x5416 */
  1030. "TIOCMBIC", /* 0x5417 */ "TIOCMSET", /* 0x5418 */
  1031. "TIOCGSOFTCAR", /* 0x5419 */ "TIOCSSOFTCAR", /* 0x541A */
  1032. "FIONREAD", /* 0x541B */ "TIOCLINUX", /* 0x541C */
  1033. "TIOCCONS", /* 0x541D */ "TIOCGSERIAL", /* 0x541E */
  1034. "TIOCSSERIAL", /* 0x541F */ "TIOCPKT", /* 0x5420 */
  1035. "FIONBIO", /* 0x5421 */ "TIOCNOTTY", /* 0x5422 */
  1036. "TIOCSETD", /* 0x5423 */ "TIOCGETD", /* 0x5424 */
  1037. "TCSBRKP", /* 0x5425 */ "",
  1038. "TIOCSBRK", /* 0x5427 */ "TIOCCBRK", /* 0x5428 */
  1039. "TIOCGSID", /* 0x5429 */ "TCGETS2", /* 0x542A */
  1040. "TCSETS2", /* 0x542B */ "TCSETSW2", /* 0x542C */
  1041. "TCSETSF2", /* 0x542D */ "TIOCGRS485", /* 0x542E */
  1042. "TIOCSRS485", /* 0x542F */ "TIOCGPTN" /* 0x5430 */
  1043. "TIOCSPTLCK", /* 0x5431 */ "TCGETX", /* 0x5432 */
  1044. "TCSETX", /* 0x5433 */ "TCSETXF", /* 0x5434 */
  1045. "TCSETXW", /* 0x5435 */ "TIOCSIG", /* 0x5436 */
  1046. "TIOCVHANGUP", /* 0x5437 */
  1047. };
  1048. PUTS(opnames[op - TCGETS]);
  1049. return;
  1050. }
  1051. if (op >= FIONCLEX && op <= TIOCSERSETMULTI) {
  1052. const char * opnames[] = {
  1053. "FIONCLEX", /* 0x5450 */ "FIOCLEX", /* 0x5451 */
  1054. "FIOASYNC", /* 0x5452 */ "TIOCSERCONFIG", /* 0x5453 */
  1055. "TIOCSERGWILD", /* 0x5454 */ "TIOCSERSWILD", /* 0x5455 */
  1056. "TIOCGLCKTRMIOS", /* 0x5456 */ "TIOCSLCKTRMIOS", /* 0x5457 */
  1057. "TIOCSERGSTRUCT", /* 0x5458 */ "TIOCSERGETLSR", /* 0x5459 */
  1058. "TIOCSERGETMULTI", /* 0x545A */ "TIOCSERSETMULTI", /* 0x545B */
  1059. };
  1060. PUTS(opnames[op - FIONCLEX]);
  1061. return;
  1062. }
  1063. #define TIOCMIWAIT 0x545C /* wait for a change on serial input line(s) */
  1064. #define TIOCGICOUNT 0x545D /* read serial port __inline__ interrupt counts */
  1065. PRINTF("OP 0x%04x", op);
  1066. }
  1067. static void parse_seek (const char * type, va_list * ap)
  1068. {
  1069. int seek = va_arg(*ap, int);
  1070. switch(seek) {
  1071. case SEEK_CUR:
  1072. PUTS("SEEK_CUR");
  1073. break;
  1074. case SEEK_SET:
  1075. PUTS("SEEK_SET");
  1076. break;
  1077. case SEEK_END:
  1078. PUTS("SEEK_END");
  1079. break;
  1080. default:
  1081. PRINTF("%d", seek);
  1082. break;
  1083. }
  1084. }
  1085. static void parse_at_fdcwd (const char * type, va_list * ap)
  1086. {
  1087. int fd = va_arg(*ap, int);
  1088. switch(fd) {
  1089. case AT_FDCWD:
  1090. PUTS("AT_FDCWD");
  1091. break;
  1092. default:
  1093. PRINTF("%d", fd);
  1094. break;
  1095. }
  1096. }
  1097. static void parse_wait_option (const char * type, va_list * ap)
  1098. {
  1099. int option = va_arg(*ap, int);
  1100. if (option & WNOHANG)
  1101. PUTS("WNOHANG");
  1102. }