shim_parser.c 45 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235
  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_tcb.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. }
  471. PUTCH(')');
  472. dotdotdot:
  473. PRINTF(" ... %s\n", name);
  474. va_end(ap);
  475. }
  476. void parse_syscall_after(int sysno, const char* name, int nr, ...) {
  477. if (!debug_handle)
  478. return;
  479. struct parser_table* parser = &syscall_parser_table[sysno];
  480. va_list ap;
  481. va_start(ap, nr);
  482. const char* ret_type = va_arg(ap, const char*);
  483. if (parser->slow || parser->stop)
  484. PRINTF("---- return from shim_%s(...", name);
  485. else
  486. PRINTF("---- shim_%s(", name);
  487. unsigned long ret_ptr = 0;
  488. int ret_val = 0;
  489. if (is_pointer(ret_type))
  490. ret_ptr = (unsigned long)va_arg(ap, void*);
  491. else
  492. ret_val = va_arg(ap, int);
  493. if (!parser->slow || parser->stop)
  494. for (int i = 0; i < nr; i++) {
  495. if (parser->stop && i < parser->stop) {
  496. skip_syscall_args(ap);
  497. continue;
  498. }
  499. if (i)
  500. PUTCH(',');
  501. if (parser->parser[i]) {
  502. const char* type = va_arg(ap, const char*);
  503. __UNUSED(type); // type not needed on this path
  504. (*parser->parser[i])(ap);
  505. } else {
  506. parse_syscall_args(ap);
  507. }
  508. }
  509. if (is_pointer(ret_type)) {
  510. if ((uint64_t)ret_ptr < (uint64_t)-4095L)
  511. PRINTF(") = 0x%08lx\n", ret_ptr);
  512. else
  513. PRINTF(") = %ld\n", (long)ret_ptr);
  514. } else {
  515. PRINTF(") = %d\n", ret_val);
  516. }
  517. va_end(ap);
  518. }
  519. static void parse_open_flags(va_list ap) {
  520. int flags = va_arg(ap, int);
  521. if (flags & O_WRONLY) {
  522. PUTS("O_WRONLY");
  523. flags &= ~O_WRONLY;
  524. } else if (flags & O_RDWR) {
  525. PUTS("O_RDWR");
  526. flags &= ~O_RDWR;
  527. } else {
  528. PUTS("O_RDONLY");
  529. }
  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. if (test_user_memory(fds, 2 * sizeof(*fds), false)) {
  720. PRINTF("[invalid-addr %p]", fds);
  721. return;
  722. }
  723. PRINTF("[%d, %d]", fds[0], fds[1]);
  724. }
  725. #define S(sig) #sig
  726. const char* const siglist[NUM_KNOWN_SIGS + 1] = {
  727. S(SIGUNUSED), S(SIGHUP), S(SIGINT), S(SIGQUIT), S(SIGILL), S(SIGTRAP), S(SIGABRT),
  728. S(SIGBUS), S(SIGFPE), S(SIGKILL), S(SIGUSR1), S(SIGSEGV), S(SIGUSR2), S(SIGPIPE),
  729. S(SIGALRM), S(SIGTERM), S(SIGSTKFLT), S(SIGCHLD), S(SIGCONT), S(SIGSTOP), S(SIGTSTP),
  730. S(SIGTTIN), S(SIGTTOU), S(SIGURG), S(SIGXCPU), S(SIGXFSZ), S(SIGVTALRM), S(SIGPROF),
  731. S(SIGWINCH), S(SIGIO), S(SIGPWR), S(SIGSYS), S(SIGRTMIN),
  732. };
  733. static void parse_signum(va_list ap) {
  734. int signum = va_arg(ap, int);
  735. if (signum >= 0 && signum <= NUM_KNOWN_SIGS)
  736. PUTS(signal_name(signum));
  737. else
  738. PRINTF("[SIG %d]", signum);
  739. }
  740. static void parse_sigmask(va_list ap) {
  741. __sigset_t* sigset = va_arg(ap, __sigset_t*);
  742. if (!sigset) {
  743. PUTS("NULL");
  744. return;
  745. }
  746. if (test_user_memory(sigset, sizeof(*sigset), false)) {
  747. PRINTF("(invalid-addr %p)", sigset);
  748. return;
  749. }
  750. PUTS("[");
  751. for (size_t signum = 1; signum <= sizeof(sigset) * 8; signum++)
  752. if (__sigismember(sigset, signum)) {
  753. PUTS(signal_name(signum));
  754. PUTS(",");
  755. }
  756. PUTS("]");
  757. }
  758. static void parse_sigprocmask_how(va_list ap) {
  759. int how = va_arg(ap, int);
  760. switch (how) {
  761. case SIG_BLOCK:
  762. PUTS("BLOCK");
  763. break;
  764. case SIG_UNBLOCK:
  765. PUTS("UNBLOCK");
  766. break;
  767. case SIG_SETMASK:
  768. PUTS("SETMASK");
  769. break;
  770. default:
  771. PUTS("<unknown>");
  772. break;
  773. }
  774. }
  775. static void parse_timespec(va_list ap) {
  776. const struct timespec* tv = va_arg(ap, const struct timespec*);
  777. if (!tv) {
  778. PUTS("NULL");
  779. return;
  780. }
  781. if (test_user_memory((void*)tv, sizeof(*tv), false)) {
  782. PRINTF("(invalid-addr %p)", tv);
  783. return;
  784. }
  785. PRINTF("[%ld,%ld]", tv->tv_sec, tv->tv_nsec);
  786. }
  787. static void parse_sockaddr(va_list ap) {
  788. const struct sockaddr* addr = va_arg(ap, const struct sockaddr*);
  789. if (!addr) {
  790. PUTS("NULL");
  791. return;
  792. }
  793. if (test_user_memory((void*)addr, sizeof(*addr), false)) {
  794. PRINTF("(invalid-addr %p)", addr);
  795. return;
  796. }
  797. switch (addr->sa_family) {
  798. case AF_INET: {
  799. struct sockaddr_in* a = (void*)addr;
  800. unsigned char* ip = (void*)&a->sin_addr.s_addr;
  801. PRINTF("{family=INET,ip=%u.%u.%u.%u,port=htons(%u)}", ip[0], ip[1], ip[2], ip[3],
  802. __ntohs(a->sin_port));
  803. break;
  804. }
  805. case AF_INET6: {
  806. struct sockaddr_in6* a = (void*)addr;
  807. unsigned short* ip = (void*)&a->sin6_addr.s6_addr;
  808. PRINTF(
  809. "{family=INET,ip=[%x:%x:%x:%x:%x:%x:%x:%x],"
  810. "port=htons(%u)}",
  811. __ntohs(ip[0]), __ntohs(ip[1]), __ntohs(ip[2]), __ntohs(ip[3]), __ntohs(ip[4]),
  812. __ntohs(ip[5]), __ntohs(ip[6]), __ntohs(ip[7]), __ntohs(a->sin6_port));
  813. break;
  814. }
  815. case AF_UNIX: {
  816. struct sockaddr_un* a = (void*)addr;
  817. PRINTF("{family=UNIX,path=%s}", a->sun_path);
  818. break;
  819. }
  820. default:
  821. PUTS("UNKNOWN");
  822. break;
  823. }
  824. }
  825. static void parse_domain(va_list ap) {
  826. int domain = va_arg(ap, int);
  827. #define PF_UNSPEC 0 /* Unspecified. */
  828. #define PF_INET 2 /* IP protocol family. */
  829. #define PF_AX25 3 /* Amateur Radio AX.25. */
  830. #define PF_IPX 4 /* Novell Internet Protocol. */
  831. #define PF_APPLETALK 5 /* Appletalk DDP. */
  832. #define PF_ATMPVC 8 /* ATM PVCs. */
  833. #define PF_X25 9 /* Reserved for X.25 project. */
  834. #define PF_INET6 10 /* IP version 6. */
  835. #define PF_NETLINK 16
  836. #define PF_PACKET 17 /* Packet family. */
  837. switch (domain) {
  838. case PF_UNSPEC:
  839. PUTS("UNSPEC");
  840. break;
  841. case PF_UNIX:
  842. PUTS("UNIX");
  843. break;
  844. case PF_INET:
  845. PUTS("INET");
  846. break;
  847. case PF_INET6:
  848. PUTS("INET6");
  849. break;
  850. case PF_IPX:
  851. PUTS("IPX");
  852. break;
  853. case PF_NETLINK:
  854. PUTS("NETLINK");
  855. break;
  856. case PF_X25:
  857. PUTS("X25");
  858. break;
  859. case PF_AX25:
  860. PUTS("AX25");
  861. break;
  862. case PF_ATMPVC:
  863. PUTS("ATMPVC");
  864. break;
  865. case PF_APPLETALK:
  866. PUTS("APPLETALK");
  867. break;
  868. case PF_PACKET:
  869. PUTS("PACKET");
  870. break;
  871. default:
  872. PUTS("UNKNOWN");
  873. break;
  874. }
  875. }
  876. static void parse_socktype(va_list ap) {
  877. int socktype = va_arg(ap, int);
  878. if (socktype & SOCK_NONBLOCK) {
  879. socktype &= ~SOCK_NONBLOCK;
  880. PUTS("SOCK_NONBLOCK|");
  881. }
  882. if (socktype & SOCK_CLOEXEC) {
  883. socktype &= ~SOCK_CLOEXEC;
  884. PUTS("SOCK_CLOEXEC|");
  885. }
  886. #define SOCK_RAW 3 /* Raw protocol interface. */
  887. #define SOCK_RDM 4 /* Reliably-delivered messages. */
  888. #define SOCK_SEQPACKET 5 /* Sequenced, reliable, connection-based, */
  889. #define SOCK_DCCP 6 /* Datagram Congestion Control Protocol. */
  890. #define SOCK_PACKET 10 /* Linux specific way of getting packets */
  891. switch (socktype) {
  892. case SOCK_STREAM:
  893. PUTS("STREAM");
  894. break;
  895. case SOCK_DGRAM:
  896. PUTS("DGRAM");
  897. break;
  898. case SOCK_SEQPACKET:
  899. PUTS("SEQPACKET");
  900. break;
  901. case SOCK_RAW:
  902. PUTS("RAW");
  903. break;
  904. case SOCK_RDM:
  905. PUTS("RDM");
  906. break;
  907. case SOCK_PACKET:
  908. PUTS("PACKET");
  909. break;
  910. default:
  911. PUTS("UNKNOWN");
  912. break;
  913. }
  914. }
  915. static void parse_futexop(va_list ap) {
  916. int op = va_arg(ap, int);
  917. #ifdef FUTEX_PRIVATE_FLAG
  918. if (op & FUTEX_PRIVATE_FLAG) {
  919. PUTS("FUTEX_PRIVATE|");
  920. op &= ~FUTEX_PRIVATE_FLAG;
  921. }
  922. #endif
  923. #ifdef FUTEX_CLOCK_REALTIME
  924. if (op & FUTEX_CLOCK_REALTIME) {
  925. PUTS("FUTEX_CLOCK_REALTIME|");
  926. op &= ~FUTEX_CLOCK_REALTIME;
  927. }
  928. #endif
  929. op &= FUTEX_CMD_MASK;
  930. switch (op) {
  931. case FUTEX_WAIT:
  932. PUTS("FUTEX_WAIT");
  933. break;
  934. case FUTEX_WAIT_BITSET:
  935. PUTS("FUTEX_WAIT_BITSET");
  936. break;
  937. case FUTEX_WAKE:
  938. PUTS("FUTEX_WAKE");
  939. break;
  940. case FUTEX_WAKE_BITSET:
  941. PUTS("FUTEX_WAKE_BITSET");
  942. break;
  943. case FUTEX_FD:
  944. PUTS("FUTEX_FD");
  945. break;
  946. case FUTEX_REQUEUE:
  947. PUTS("FUTEX_REQUEUE");
  948. break;
  949. case FUTEX_CMP_REQUEUE:
  950. PUTS("FUTEX_CMP_REQUEUE");
  951. break;
  952. case FUTEX_WAKE_OP:
  953. PUTS("FUTEX_WAKE_OP");
  954. break;
  955. default:
  956. PRINTF("OP %d", op);
  957. break;
  958. }
  959. }
  960. static void parse_fcntlop(va_list ap) {
  961. int op = va_arg(ap, int);
  962. switch (op) {
  963. case F_DUPFD:
  964. PUTS("F_DUPFD");
  965. break;
  966. case F_GETFD:
  967. PUTS("F_GETFD");
  968. break;
  969. case F_SETFD:
  970. PUTS("F_SETFD");
  971. break;
  972. case F_GETFL:
  973. PUTS("F_GETFL");
  974. break;
  975. case F_SETFL:
  976. PUTS("F_SETFL");
  977. break;
  978. case F_GETLK:
  979. PUTS("F_GETLK");
  980. break;
  981. case F_SETLK:
  982. PUTS("F_SETLK");
  983. break;
  984. case F_SETLKW:
  985. PUTS("F_SETLKW");
  986. break;
  987. case F_SETOWN:
  988. PUTS("F_SETOWN");
  989. break;
  990. case F_GETOWN:
  991. PUTS("F_GETOWN");
  992. break;
  993. case F_SETSIG:
  994. PUTS("F_SETSIG");
  995. break;
  996. case F_GETSIG:
  997. PUTS("F_GETSIG");
  998. break;
  999. case F_GETLK64:
  1000. PUTS("F_GETLK64");
  1001. break;
  1002. case F_SETLK64:
  1003. PUTS("F_SETLK64");
  1004. break;
  1005. case F_SETLKW64:
  1006. PUTS("F_SETLKW64");
  1007. break;
  1008. case F_SETOWN_EX:
  1009. PUTS("F_SETOWN_EX");
  1010. break;
  1011. case F_GETOWN_EX:
  1012. PUTS("F_GETOWN_EX");
  1013. break;
  1014. case F_GETOWNER_UIDS:
  1015. PUTS("F_GETOWNER_UIDS");
  1016. break;
  1017. default:
  1018. PRINTF("OP %d", op);
  1019. break;
  1020. }
  1021. }
  1022. static void parse_ioctlop(va_list ap) {
  1023. int op = va_arg(ap, int);
  1024. if (op >= TCGETS && op <= TIOCVHANGUP) {
  1025. const char* opnames[] = {
  1026. "TCGETS", /* 0x5401 */ "TCSETS", /* 0x5402 */
  1027. "TCSETSW", /* 0x5403 */ "TCSETSF", /* 0x5404 */
  1028. "TCGETA", /* 0x5405 */ "TCSETA", /* 0x5406 */
  1029. "TCSETAW", /* 0x5407 */ "TCSETAF", /* 0x5408 */
  1030. "TCSBRK", /* 0x5409 */ "TCXONC", /* 0x540A */
  1031. "TCFLSH", /* 0x540B */ "TIOCEXCL", /* 0x540C */
  1032. "TIOCNXCL", /* 0x540D */ "TIOCSCTTY", /* 0x540E */
  1033. "TIOCGPGRP", /* 0x540F */ "TIOCSPGRP", /* 0x5410 */
  1034. "TIOCOUTQ", /* 0x5411 */ "TIOCSTI", /* 0x5412 */
  1035. "TIOCGWINSZ", /* 0x5413 */ "TIOCSWINSZ", /* 0x5414 */
  1036. "TIOCMGET", /* 0x5415 */ "TIOCMBIS", /* 0x5416 */
  1037. "TIOCMBIC", /* 0x5417 */ "TIOCMSET", /* 0x5418 */
  1038. "TIOCGSOFTCAR", /* 0x5419 */ "TIOCSSOFTCAR", /* 0x541A */
  1039. "FIONREAD", /* 0x541B */ "TIOCLINUX", /* 0x541C */
  1040. "TIOCCONS", /* 0x541D */ "TIOCGSERIAL", /* 0x541E */
  1041. "TIOCSSERIAL", /* 0x541F */ "TIOCPKT", /* 0x5420 */
  1042. "FIONBIO", /* 0x5421 */ "TIOCNOTTY", /* 0x5422 */
  1043. "TIOCSETD", /* 0x5423 */ "TIOCGETD", /* 0x5424 */
  1044. "TCSBRKP", /* 0x5425 */ "",
  1045. "TIOCSBRK", /* 0x5427 */ "TIOCCBRK", /* 0x5428 */
  1046. "TIOCGSID", /* 0x5429 */ "TCGETS2", /* 0x542A */
  1047. "TCSETS2", /* 0x542B */ "TCSETSW2", /* 0x542C */
  1048. "TCSETSF2", /* 0x542D */ "TIOCGRS485", /* 0x542E */
  1049. "TIOCSRS485", /* 0x542F */ "TIOCGPTN", /* 0x5430 */
  1050. "TIOCSPTLCK", /* 0x5431 */ "TCGETX", /* 0x5432 */
  1051. "TCSETX", /* 0x5433 */ "TCSETXF", /* 0x5434 */
  1052. "TCSETXW", /* 0x5435 */ "TIOCSIG", /* 0x5436 */
  1053. "TIOCVHANGUP", /* 0x5437 */
  1054. };
  1055. PUTS(opnames[op - TCGETS]);
  1056. return;
  1057. }
  1058. if (op >= FIONCLEX && op <= TIOCSERSETMULTI) {
  1059. const char* opnames[] = {
  1060. "FIONCLEX", /* 0x5450 */ "FIOCLEX", /* 0x5451 */
  1061. "FIOASYNC", /* 0x5452 */ "TIOCSERCONFIG", /* 0x5453 */
  1062. "TIOCSERGWILD", /* 0x5454 */ "TIOCSERSWILD", /* 0x5455 */
  1063. "TIOCGLCKTRMIOS", /* 0x5456 */ "TIOCSLCKTRMIOS", /* 0x5457 */
  1064. "TIOCSERGSTRUCT", /* 0x5458 */ "TIOCSERGETLSR", /* 0x5459 */
  1065. "TIOCSERGETMULTI", /* 0x545A */ "TIOCSERSETMULTI", /* 0x545B */
  1066. };
  1067. PUTS(opnames[op - FIONCLEX]);
  1068. return;
  1069. }
  1070. #define TIOCMIWAIT 0x545C /* wait for a change on serial input line(s) */
  1071. #define TIOCGICOUNT 0x545D /* read serial port __inline__ interrupt counts */
  1072. PRINTF("OP 0x%04x", op);
  1073. }
  1074. static void parse_seek(va_list ap) {
  1075. int seek = va_arg(ap, int);
  1076. switch (seek) {
  1077. case SEEK_CUR:
  1078. PUTS("SEEK_CUR");
  1079. break;
  1080. case SEEK_SET:
  1081. PUTS("SEEK_SET");
  1082. break;
  1083. case SEEK_END:
  1084. PUTS("SEEK_END");
  1085. break;
  1086. default:
  1087. PRINTF("%d", seek);
  1088. break;
  1089. }
  1090. }
  1091. static void parse_at_fdcwd(va_list ap) {
  1092. int fd = va_arg(ap, int);
  1093. switch (fd) {
  1094. case AT_FDCWD:
  1095. PUTS("AT_FDCWD");
  1096. break;
  1097. default:
  1098. PRINTF("%d", fd);
  1099. break;
  1100. }
  1101. }
  1102. static void parse_wait_option(va_list ap) {
  1103. int option = va_arg(ap, int);
  1104. if (option & WNOHANG)
  1105. PUTS("WNOHANG");
  1106. }