shim_parser.c 45 KB

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