shim_parser.c 41 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277
  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 <shim_internal.h>
  20. #include <shim_tls.h>
  21. #include <shim_table.h>
  22. #include <shim_thread.h>
  23. #include <shim_utils.h>
  24. #include <pal.h>
  25. #include <pal_error.h>
  26. #include <errno.h>
  27. #include <asm/fcntl.h>
  28. #include <asm/unistd.h>
  29. #include <asm/prctl.h>
  30. #include <asm/mman.h>
  31. #include <asm/ioctls.h>
  32. #include <linux/stat.h>
  33. #include <linux/fcntl.h>
  34. #include <linux/sched.h>
  35. #include <linux/futex.h>
  36. #include <linux/wait.h>
  37. #include <linux/in.h>
  38. #include <linux/in6.h>
  39. #include <linux/un.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. { .slow = 1, .parser = { NULL } }, /* read */
  68. { .slow = 1, .parser = { NULL } }, /* write */
  69. { .slow = 1, /* open */
  70. .parser = { NULL, &parse_open_flags, &parse_open_mode, } },
  71. { .slow = 0, .parser = { NULL } }, /* close */
  72. { .slow = 0, .parser = { NULL } }, /* stat */
  73. { .slow = 0, .parser = { NULL } }, /* fstat */
  74. { .slow = 0, .parser = { NULL } }, /* lstat */
  75. { .slow = 1, .parser = { NULL } }, /* poll */
  76. { .slow = 0, .parser = { NULL, NULL, &parse_seek } }, /* lseek */
  77. { .slow = 1, /* mmap */
  78. .parser = { NULL, NULL, &parse_mmap_prot, &parse_mmap_flags } },
  79. { .slow = 1, /* mprotect */
  80. .parser = { NULL, NULL, &parse_mmap_prot } },
  81. { .slow = 1, .parser = { NULL } }, /* munmap */
  82. { .slow = 0, .parser = { NULL } }, /* brk */
  83. { .slow = 0, .parser = { &parse_signum } }, /* rt_sigaction */
  84. { .slow = 0, /* rt_sigprocmask */
  85. .parser = { &parse_sigprocmask_how, &parse_sigmask, &parse_sigmask } },
  86. { .slow = 0, .parser = { NULL } }, /* rt_sigreturn */
  87. { .slow = 1, .parser = { NULL, &parse_ioctlop } }, /* ioctl */
  88. { .slow = 1, .parser = { NULL } }, /* pread64 */
  89. { .slow = 0, .parser = { NULL } }, /* pwrite64 */
  90. { .slow = 1, .parser = { NULL } }, /* readv */
  91. { .slow = 0, .parser = { NULL } }, /* writev */
  92. { .slow = 0, /* access */
  93. .parser = { NULL, &parse_access_mode } },
  94. { .slow = 0, /* pipe */
  95. .parser = { &parse_pipe_fds } },
  96. { .slow = 0, .parser = { NULL } }, /* select */
  97. { .slow = 0, .parser = { NULL } }, /* sched_yield */
  98. { .slow = 0, .parser = { NULL } }, /* mremap */
  99. { .slow = 0, .parser = { NULL } }, /* msync */
  100. { .slow = 0, .parser = { NULL } }, /* mincore */
  101. { .slow = 0, .parser = { NULL } }, /* madvise */
  102. { .slow = 0, .parser = { NULL } }, /* shmget */
  103. { .slow = 0, .parser = { NULL } }, /* shmat */
  104. { .slow = 0, .parser = { NULL } }, /* shmctl */
  105. { .slow = 0, .parser = { NULL } }, /* dup */
  106. { .slow = 0, .parser = { NULL } }, /* dup2 */
  107. { .slow = 1, .parser = { NULL } }, /* pause */
  108. { .slow = 1,
  109. .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, .stop = 3, /* socketpair */
  128. .parser = { &parse_domain, &parse_socktype, NULL, &parse_pipe_fds } },
  129. { .slow = 0, .parser = { NULL } }, /* setsockopt */
  130. { .slow = 0, .parser = { NULL } }, /* getsockopt */
  131. { .slow = 1, .parser = { &parse_clone_flags } }, /* clone */
  132. { .slow = 1, .parser = { NULL } }, /* fork */
  133. { .slow = 1, .parser = { NULL } }, /* vfork */
  134. { .slow = 1, /* execve */
  135. .parser = { NULL, &parse_exec_args, &parse_exec_envp, } },
  136. { .slow = 0, .parser = { NULL } }, /* exit */
  137. { .slow = 1, .parser = { NULL, NULL,
  138. &parse_wait_option,
  139. NULL } }, /* wait4 */
  140. { .slow = 0, .parser = { NULL, &parse_signum, } }, /* kill */
  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,
  313. .parser = { NULL, NULL, &parse_signum } }, /* tgkill */
  314. { .slow = 0, .parser = { NULL } }, /* utimes */
  315. { .slow = 0, .parser = { NULL } }, /* vserver */
  316. { .slow = 0, .parser = { NULL } }, /* mbind */
  317. { .slow = 0, .parser = { NULL } }, /* set_mempolicy */
  318. { .slow = 0, .parser = { NULL } }, /* get_mempolicy */
  319. { .slow = 0, .parser = { NULL } }, /* mq_open */
  320. { .slow = 0, .parser = { NULL } }, /* mq_unlink */
  321. { .slow = 0, .parser = { NULL } }, /* mq_timedsend */
  322. { .slow = 0, .parser = { NULL } }, /* mq_timedreceive */
  323. { .slow = 0, .parser = { NULL } }, /* mq_notify */
  324. { .slow = 0, .parser = { NULL } }, /* mq_getsetattr */
  325. { .slow = 0, .parser = { NULL } }, /* kexec_load */
  326. { .slow = 1, .parser = { NULL } }, /* waitid */
  327. { .slow = 0, .parser = { NULL } }, /* add_key */
  328. { .slow = 0, .parser = { NULL } }, /* request_key */
  329. { .slow = 0, .parser = { NULL } }, /* keyctl */
  330. { .slow = 0, .parser = { NULL } }, /* ioprio_set */
  331. { .slow = 0, .parser = { NULL } }, /* ioprio_get */
  332. { .slow = 0, .parser = { NULL } }, /* inotify_init */
  333. { .slow = 0, .parser = { NULL } }, /* inotify_add_watch */
  334. { .slow = 0, .parser = { NULL } }, /* inotify_rm_watch */
  335. { .slow = 0, .parser = { NULL } }, /* migrate_pages */
  336. { .slow = 0, .parser = { &parse_at_fdcwd, NULL,
  337. &parse_open_flags,
  338. &parse_open_mode } }, /* openat */
  339. { .slow = 0, .parser = { &parse_at_fdcwd, } }, /* mkdirat */
  340. { .slow = 0, .parser = { &parse_at_fdcwd, } }, /* mknodat */
  341. { .slow = 0, .parser = { &parse_at_fdcwd, } }, /* fchownat */
  342. { .slow = 0, .parser = { &parse_at_fdcwd, } }, /* futimesat */
  343. { .slow = 0, .parser = { &parse_at_fdcwd, } }, /* newfstatat */
  344. { .slow = 0, .parser = { &parse_at_fdcwd, } }, /* unlinkat */
  345. { .slow = 0, .parser = { &parse_at_fdcwd, } }, /* renameat */
  346. { .slow = 0, .parser = { &parse_at_fdcwd, } }, /* linkat */
  347. { .slow = 0, .parser = { &parse_at_fdcwd, } }, /* symlinkat */
  348. { .slow = 0, .parser = { &parse_at_fdcwd, } }, /* readlinkat */
  349. { .slow = 0, .parser = { &parse_at_fdcwd, } }, /* fchmodat */
  350. { .slow = 0, .parser = { &parse_at_fdcwd, } }, /* faccessat */
  351. { .slow = 0, .parser = { NULL } }, /* pselect6 */
  352. { .slow = 1, .parser = { NULL } }, /* ppoll */
  353. { .slow = 0, .parser = { NULL } }, /* unshare */
  354. { .slow = 0, .parser = { NULL } }, /* set_robust_list */
  355. { .slow = 0, .parser = { NULL } }, /* get_robust_list */
  356. { .slow = 0, .parser = { NULL } }, /* splice */
  357. { .slow = 0, .parser = { NULL } }, /* tee */
  358. { .slow = 0, .parser = { NULL } }, /* sync_file_range */
  359. { .slow = 0, .parser = { NULL } }, /* vmsplice */
  360. { .slow = 0, .parser = { NULL } }, /* move_pages */
  361. { .slow = 0, .parser = { NULL } }, /* utimensat */
  362. { .slow = 1, .parser = { NULL } }, /* epoll_pwait */
  363. { .slow = 0, .parser = { NULL } }, /* signalfd */
  364. { .slow = 0, .parser = { NULL } }, /* timerfd_create */
  365. { .slow = 0, .parser = { NULL } }, /* eventfd */
  366. { .slow = 0, .parser = { NULL } }, /* fallocate */
  367. { .slow = 0, .parser = { NULL } }, /* timerfd_settime */
  368. { .slow = 0, .parser = { NULL } }, /* timerfd_gettime */
  369. { .slow = 1, .parser = { NULL } }, /* accept4 */
  370. { .slow = 0, .parser = { NULL } }, /* signalfd4 */
  371. { .slow = 0, .parser = { NULL } }, /* eventfd2 */
  372. { .slow = 0, .parser = { NULL } }, /* epoll_create1 */
  373. { .slow = 0, .parser = { NULL } }, /* dup3 */
  374. { .slow = 0, .parser = { NULL } }, /* pipe2 */
  375. { .slow = 0, .parser = { NULL } }, /* inotify_init1 */
  376. { .slow = 0, .parser = { NULL } }, /* preadv */
  377. { .slow = 0, .parser = { NULL } }, /* pwritev */
  378. { .slow = 0, .parser = { NULL } }, /* rt_tgsigqueueinfo */
  379. { .slow = 0, .parser = { NULL } }, /* perf_event_open */
  380. { .slow = 0, .parser = { NULL } }, /* recvmmsg */
  381. [LIBOS_SYSCALL_BASE] = { .slow = 0, .parser = { NULL } },
  382. { .slow = 1, .parser = { NULL } }, /* checkpoint */
  383. { .slow = 1, .parser = { NULL } }, /* restore */
  384. { .slow = 1, .parser = { NULL } }, /* sandbox_create */
  385. { .slow = 0, .parser = { NULL } }, /* sandbox_attach */
  386. { .slow = 0, .parser = { NULL } }, /* sandbox_current */
  387. { .slow = 1, .parser = { NULL } }, /* msgpersist */
  388. { .slow = 1, .parser = { NULL } }, /* benchmark_ipc */
  389. { .slow = 1, .parser = { NULL } }, /* send_rpc */
  390. { .slow = 1, .parser = { NULL } }, /* recv_rpc */
  391. };
  392. static inline int is_pointer (const char * type)
  393. {
  394. return type[strlen(type) - 1] == '*'
  395. || strcmp_static(type, "long")
  396. || strcmp_static(type, "unsigned long");
  397. }
  398. #define PRINTF(fmt, ...) \
  399. do { \
  400. debug_printf(fmt, __VA_ARGS__); \
  401. } while (0)
  402. #define PUTS(str) \
  403. do { \
  404. debug_puts(str); \
  405. } while (0)
  406. #define PUTCH(ch) \
  407. do { \
  408. debug_putch(ch); \
  409. } while (0)
  410. #define VPRINTF(fmt, ap) \
  411. do { \
  412. debug_vprintf(fmt, ap); \
  413. } while (0)
  414. static inline void parse_string_arg (va_list * ap)
  415. {
  416. va_list ap_test_arg;
  417. va_copy(ap_test_arg, *ap);
  418. const char* test_arg = va_arg(ap_test_arg, const char*);
  419. if (!test_user_string(test_arg)) {
  420. VPRINTF("\"%s\"", ap);
  421. } else {
  422. /* invalid memory region, print arg as ptr not string */
  423. VPRINTF("\"(invalid-addr %p)\"", ap);
  424. }
  425. va_end(ap_test_arg);
  426. }
  427. static inline void parse_pointer_arg (va_list * ap)
  428. {
  429. VPRINTF("%p", ap);
  430. }
  431. static inline void parse_integer_arg (va_list * ap)
  432. {
  433. VPRINTF("%d", ap);
  434. }
  435. static inline void parse_syscall_args (va_list * ap)
  436. {
  437. const char * arg_type = va_arg(*ap, const char *);
  438. if (strcmp_static(arg_type, "const char *"))
  439. parse_string_arg(ap);
  440. else if (is_pointer(arg_type))
  441. parse_pointer_arg(ap);
  442. else
  443. parse_integer_arg(ap);
  444. }
  445. static inline void skip_syscall_args (va_list * ap)
  446. {
  447. const char * arg_type = va_arg(*ap, const char *);
  448. if (strcmp_static(arg_type, "const char *"))
  449. va_arg(*ap, const char *);
  450. else if (is_pointer(arg_type))
  451. va_arg(*ap, void *);
  452. else
  453. va_arg(*ap, int);
  454. }
  455. void sysparser_printf (const char * fmt, ...)
  456. {
  457. va_list ap;
  458. va_start(ap, fmt);
  459. VPRINTF(fmt, &ap);
  460. va_end(ap);
  461. }
  462. void parse_syscall_before (int sysno, const char * name, int nr, ...)
  463. {
  464. if (!debug_handle)
  465. return;
  466. struct parser_table * parser = &syscall_parser_table[sysno];
  467. if (!parser->slow && !parser->stop)
  468. return;
  469. va_list ap;
  470. va_start(ap, nr);
  471. PRINTF("---- shim_%s(", name);
  472. for (int i = 0 ; i < nr ; i++) {
  473. if (parser->stop && parser->stop == i)
  474. goto dotdotdot;
  475. if (i)
  476. PUTCH(',');
  477. if (parser->parser[i]) {
  478. const char * type = va_arg(ap, const char *);
  479. __UNUSED(type); // type not needed on this path
  480. (*parser->parser[i])(&ap);
  481. } else
  482. parse_syscall_args(&ap);
  483. }
  484. PUTCH(')');
  485. dotdotdot:
  486. PRINTF(" ... %s\n", name);
  487. va_end(ap);
  488. }
  489. void parse_syscall_after (int sysno, const char * name, int nr, ...)
  490. {
  491. if (!debug_handle)
  492. return;
  493. struct parser_table * parser = &syscall_parser_table[sysno];
  494. va_list ap;
  495. va_start(ap, nr);
  496. const char * ret_type = va_arg(ap, const char *);
  497. if (parser->slow || parser->stop)
  498. PRINTF("---- return from shim_%s(...", name);
  499. else
  500. PRINTF("---- shim_%s(", name);
  501. unsigned long ret_ptr;
  502. int ret_val;
  503. if (is_pointer(ret_type))
  504. ret_ptr = (unsigned long) va_arg(ap, void *);
  505. else
  506. ret_val = va_arg(ap, int);
  507. if (!parser->slow || parser->stop)
  508. for (int i = 0 ; i < nr ; i++) {
  509. if (parser->stop && i < parser->stop) {
  510. skip_syscall_args(&ap);
  511. continue;
  512. }
  513. if (i)
  514. PUTCH(',');
  515. if (parser->parser[i]) {
  516. const char * type = va_arg(ap, const char *);
  517. __UNUSED(type); // type not needed on this path
  518. (*parser->parser[i])(&ap);
  519. } else
  520. parse_syscall_args(&ap);
  521. }
  522. if (is_pointer(ret_type)) {
  523. if ((uint64_t) ret_ptr < (uint64_t) -4095L)
  524. PRINTF(") = 0x%08lx\n", ret_ptr);
  525. else
  526. PRINTF(") = %ld\n", (long) ret_ptr);
  527. } else {
  528. if (ret_val >= 0)
  529. PRINTF(") = %d\n", ret_val);
  530. else
  531. PRINTF(") = %d\n", ret_val);
  532. }
  533. va_end (ap);
  534. }
  535. static void parse_open_flags (va_list * ap)
  536. {
  537. int flags = va_arg(*ap, int);
  538. if (flags & O_WRONLY) {
  539. PUTS("O_WRONLY");
  540. flags &= ~O_WRONLY;
  541. } else if (flags & O_RDWR) {
  542. PUTS("O_RDWR");
  543. flags &= ~O_RDWR;
  544. } else
  545. PUTS("O_RDONLY");
  546. if (flags & O_APPEND) {
  547. PUTS("|O_APPEND");
  548. flags &= ~O_APPEND;
  549. }
  550. if (flags & O_CREAT) {
  551. PUTS("|O_CREAT");
  552. flags &= ~O_CREAT;
  553. }
  554. if (flags & O_TRUNC) {
  555. PUTS("|O_TRUNC");
  556. flags &= ~O_TRUNC;
  557. }
  558. if (flags & O_EXCL) {
  559. PUTS("|O_EXCL");
  560. flags &= ~O_EXCL;
  561. }
  562. if (flags)
  563. PRINTF("|%o", flags);
  564. }
  565. static void parse_open_mode (va_list * ap)
  566. {
  567. VPRINTF("%04o", ap);
  568. }
  569. static void parse_access_mode (va_list * ap)
  570. {
  571. int mode = va_arg(*ap, int);
  572. PUTS("F_OK");
  573. if (mode) {
  574. if (mode & R_OK)
  575. PUTS("|R_OK");
  576. if (mode & W_OK)
  577. PUTS("|W_OK");
  578. if (mode & X_OK)
  579. PUTS("|X_OK");
  580. }
  581. }
  582. static void parse_clone_flags (va_list * ap)
  583. {
  584. int flags = va_arg(*ap, int);
  585. #define FLG(n) { "CLONE_" #n, CLONE_##n, }
  586. const struct {
  587. const char * name; int flag;
  588. } all_flags[] = {
  589. FLG(VM), FLG(FS), FLG(FILES), FLG(SIGHAND), FLG(PTRACE), FLG(VFORK),
  590. FLG(PARENT), FLG(THREAD), FLG(NEWNS), FLG(SYSVSEM), FLG(SETTLS),
  591. FLG(PARENT_SETTID), FLG(CHILD_CLEARTID), FLG(DETACHED), FLG(UNTRACED),
  592. FLG(CHILD_SETTID), FLG(NEWUTS), FLG(NEWIPC), FLG(NEWUSER),
  593. FLG(NEWPID), FLG(NEWNET), FLG(IO),
  594. };
  595. #undef FLG
  596. bool printed = false;
  597. for (size_t i = 0 ; i < sizeof(all_flags) / sizeof(all_flags[0]) ; 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. if (flags)
  607. PRINTF("|0x%x", flags);
  608. }
  609. static void parse_mmap_prot (va_list * ap)
  610. {
  611. int prot = va_arg(*ap, int);
  612. int nflags = 0;
  613. if (prot == PROT_NONE) {
  614. PUTS("PROT_NONE");
  615. return;
  616. }
  617. if (prot & PROT_READ) {
  618. if (nflags++)
  619. PUTS("|");
  620. PUTS("PROT_READ");
  621. }
  622. if (prot & PROT_WRITE) {
  623. if (nflags++)
  624. PUTS("|");
  625. PUTS("PROT_WRITE");
  626. }
  627. if (prot & PROT_EXEC) {
  628. if (nflags++)
  629. PUTS("|");
  630. PUTS("PROT_EXEC");
  631. }
  632. }
  633. static void parse_mmap_flags (va_list * ap)
  634. {
  635. int flags = va_arg(*ap, int);
  636. if (flags & MAP_SHARED) {
  637. PUTS("MAP_SHARED");
  638. flags &= ~MAP_SHARED;
  639. }
  640. if (flags & MAP_PRIVATE) {
  641. PUTS("MAP_PRIVATE");
  642. flags &= ~MAP_PRIVATE;
  643. }
  644. if (flags & MAP_ANONYMOUS) {
  645. PUTS("|MAP_ANON");
  646. flags &= ~MAP_ANONYMOUS;
  647. }
  648. if (flags & MAP_FILE) {
  649. PUTS("|MAP_FILE");
  650. flags &= ~MAP_FILE;
  651. }
  652. if (flags & MAP_FIXED) {
  653. PUTS("|MAP_FIXED");
  654. flags &= ~MAP_FIXED;
  655. }
  656. #ifdef CONFIG_MMAP_ALLOW_UNINITIALIZED
  657. if (flags & MAP_UNINITIALIZED) {
  658. PUTS("|MAP_UNINITIALIZED");
  659. flags &= ~MAP_UNINITIALIZED;
  660. }
  661. #endif
  662. if (flags)
  663. PRINTF("|0x%x", flags);
  664. }
  665. static void parse_exec_args (va_list * ap)
  666. {
  667. const char ** args = va_arg(*ap, const char **);
  668. PUTS("[");
  669. for (; ; args++) {
  670. if (test_user_memory(args, sizeof(*args), false)) {
  671. PRINTF("(invalid-argv %p)", args);
  672. break;
  673. }
  674. if (*args == NULL)
  675. break;
  676. if (test_user_string(*args)) {
  677. PRINTF("(invalid-addr %p),", *args);
  678. continue;
  679. }
  680. PUTS(*args);
  681. PUTS(",");
  682. }
  683. PUTS("]");
  684. }
  685. static void parse_exec_envp (va_list * ap)
  686. {
  687. const char ** envp = va_arg(*ap, const char **);
  688. if (!envp) {
  689. PUTS("NULL");
  690. return;
  691. }
  692. PUTS("[");
  693. int cnt = 0;
  694. for (; cnt < 2; cnt++, envp++) {
  695. if (test_user_memory(envp, sizeof(*envp), false)) {
  696. PRINTF("(invalid-envp %p)", envp);
  697. break;
  698. }
  699. if (*envp == NULL)
  700. break;
  701. if (test_user_string(*envp)) {
  702. PRINTF("(invalid-addr %p),", *envp);
  703. continue;
  704. }
  705. PUTS(*envp);
  706. PUTS(",");
  707. }
  708. if (cnt > 2)
  709. PRINTF("(%d more)", cnt);
  710. PUTS("]");
  711. }
  712. static void parse_pipe_fds (va_list * ap)
  713. {
  714. int * fds = va_arg(*ap, int *);
  715. PRINTF("[%d, %d]", fds[0], fds[1]);
  716. }
  717. #define S(sig) #sig
  718. const char *const siglist[NUM_KNOWN_SIGS + 1] =
  719. {
  720. S(SIGUNUSED),
  721. S(SIGHUP),
  722. S(SIGINT),
  723. S(SIGQUIT),
  724. S(SIGILL),
  725. S(SIGTRAP),
  726. S(SIGABRT),
  727. S(SIGBUS),
  728. S(SIGFPE),
  729. S(SIGKILL),
  730. S(SIGUSR1),
  731. S(SIGSEGV),
  732. S(SIGUSR2),
  733. S(SIGPIPE),
  734. S(SIGALRM),
  735. S(SIGTERM),
  736. S(SIGSTKFLT),
  737. S(SIGCHLD),
  738. S(SIGCONT),
  739. S(SIGSTOP),
  740. S(SIGTSTP),
  741. S(SIGTTIN),
  742. S(SIGTTOU),
  743. S(SIGURG),
  744. S(SIGXCPU),
  745. S(SIGXFSZ),
  746. S(SIGVTALRM),
  747. S(SIGPROF),
  748. S(SIGWINCH),
  749. S(SIGIO),
  750. S(SIGPWR),
  751. S(SIGSYS),
  752. S(SIGRTMIN),
  753. };
  754. static void parse_signum (va_list * ap)
  755. {
  756. int signum = va_arg(*ap, int);
  757. if (signum >= 0 && signum <= NUM_KNOWN_SIGS)
  758. PUTS(signal_name(signum));
  759. else
  760. PRINTF("[SIG %d]", signum);
  761. }
  762. static void parse_sigmask (va_list * ap)
  763. {
  764. __sigset_t * sigset = va_arg(*ap, __sigset_t *);
  765. if (!sigset) {
  766. PUTS("NULL");
  767. return;
  768. }
  769. if (test_user_memory(sigset, sizeof(*sigset), false)) {
  770. PRINTF("(invalid-addr %p)", sigset);
  771. return;
  772. }
  773. PUTS("[");
  774. for (size_t signum = 1 ; signum <= sizeof(sigset) * 8 ; signum++)
  775. if (__sigismember(sigset, signum)) {
  776. PUTS(signal_name(signum));
  777. PUTS(",");
  778. }
  779. PUTS("]");
  780. }
  781. static void parse_sigprocmask_how (va_list * ap)
  782. {
  783. int how = va_arg(*ap, int);
  784. switch (how) {
  785. case SIG_BLOCK:
  786. PUTS("BLOCK");
  787. break;
  788. case SIG_UNBLOCK:
  789. PUTS("UNBLOCK");
  790. break;
  791. case SIG_SETMASK:
  792. PUTS("SETMASK");
  793. break;
  794. default:
  795. PUTS("<unknown>");
  796. break;
  797. }
  798. }
  799. static void parse_timespec (va_list * ap)
  800. {
  801. const struct timespec * tv = va_arg(*ap, const struct timespec *);
  802. if (!tv) {
  803. PUTS("NULL");
  804. return;
  805. }
  806. if (test_user_memory((void*)tv, sizeof(*tv), false)) {
  807. PRINTF("(invalid-addr %p)", tv);
  808. return;
  809. }
  810. PRINTF("[%ld,%ld]", tv->tv_sec, tv->tv_nsec);
  811. }
  812. static void parse_sockaddr (va_list *ap)
  813. {
  814. const struct sockaddr *addr = va_arg(*ap, const struct sockaddr *);
  815. if (!addr) {
  816. PUTS("NULL");
  817. return;
  818. }
  819. if (test_user_memory((void*)addr, sizeof(*addr), false)) {
  820. PRINTF("(invalid-addr %p)", addr);
  821. return;
  822. }
  823. switch (addr->sa_family) {
  824. case AF_INET: {
  825. struct sockaddr_in * a = (void *) addr;
  826. unsigned char * ip = (void *) &a->sin_addr.s_addr;
  827. PRINTF("{family=INET,ip=%u.%u.%u.%u,port=htons(%u)}",
  828. ip[0], ip[1], ip[2], ip[3], __ntohs(a->sin_port));
  829. break;
  830. }
  831. case AF_INET6: {
  832. struct sockaddr_in6 * a = (void *) addr;
  833. unsigned short * ip = (void *) &a->sin6_addr.s6_addr;
  834. PRINTF("{family=INET,ip=[%x:%x:%x:%x:%x:%x:%x:%x],"
  835. "port=htons(%u)}",
  836. __ntohs(ip[0]), __ntohs(ip[1]),
  837. __ntohs(ip[2]), __ntohs(ip[3]),
  838. __ntohs(ip[4]), __ntohs(ip[5]),
  839. __ntohs(ip[6]), __ntohs(ip[7]),
  840. __ntohs(a->sin6_port));
  841. break;
  842. }
  843. case AF_UNIX: {
  844. struct sockaddr_un * a = (void *) addr;
  845. PRINTF("{family=UNIX,path=%s}", a->sun_path);
  846. break;
  847. }
  848. default:
  849. PUTS("UNKNOWN");
  850. break;
  851. }
  852. }
  853. static void parse_domain (va_list * ap)
  854. {
  855. int domain = va_arg(*ap, int);
  856. #define PF_UNSPEC 0 /* Unspecified. */
  857. #define PF_INET 2 /* IP protocol family. */
  858. #define PF_AX25 3 /* Amateur Radio AX.25. */
  859. #define PF_IPX 4 /* Novell Internet Protocol. */
  860. #define PF_APPLETALK 5 /* Appletalk DDP. */
  861. #define PF_ATMPVC 8 /* ATM PVCs. */
  862. #define PF_X25 9 /* Reserved for X.25 project. */
  863. #define PF_INET6 10 /* IP version 6. */
  864. #define PF_NETLINK 16
  865. #define PF_PACKET 17 /* Packet family. */
  866. switch (domain) {
  867. case PF_UNSPEC:
  868. PUTS("UNSPEC");
  869. break;
  870. case PF_UNIX:
  871. PUTS("UNIX");
  872. break;
  873. case PF_INET:
  874. PUTS("INET");
  875. break;
  876. case PF_INET6:
  877. PUTS("INET6");
  878. break;
  879. case PF_IPX:
  880. PUTS("IPX");
  881. break;
  882. case PF_NETLINK:
  883. PUTS("NETLINK");
  884. break;
  885. case PF_X25:
  886. PUTS("X25");
  887. break;
  888. case PF_AX25:
  889. PUTS("AX25");
  890. break;
  891. case PF_ATMPVC:
  892. PUTS("ATMPVC");
  893. break;
  894. case PF_APPLETALK:
  895. PUTS("APPLETALK");
  896. break;
  897. case PF_PACKET:
  898. PUTS("PACKET");
  899. break;
  900. default:
  901. PUTS("UNKNOWN");
  902. break;
  903. }
  904. }
  905. static void parse_socktype (va_list * ap)
  906. {
  907. int socktype = va_arg(*ap, int);
  908. if (socktype & SOCK_NONBLOCK) {
  909. socktype &= ~SOCK_NONBLOCK;
  910. PUTS("SOCK_NONBLOCK|");
  911. }
  912. if (socktype & SOCK_CLOEXEC) {
  913. socktype &= ~SOCK_CLOEXEC;
  914. PUTS("SOCK_CLOEXEC|");
  915. }
  916. #define SOCK_RAW 3 /* Raw protocol interface. */
  917. #define SOCK_RDM 4 /* Reliably-delivered messages. */
  918. #define SOCK_SEQPACKET 5 /* Sequenced, reliable, connection-based, */
  919. #define SOCK_DCCP 6 /* Datagram Congestion Control Protocol. */
  920. #define SOCK_PACKET 10 /* Linux specific way of getting packets */
  921. switch (socktype) {
  922. case SOCK_STREAM:
  923. PUTS("STREAM");
  924. break;
  925. case SOCK_DGRAM:
  926. PUTS("DGRAM");
  927. break;
  928. case SOCK_SEQPACKET:
  929. PUTS("SEQPACKET");
  930. break;
  931. case SOCK_RAW:
  932. PUTS("RAW");
  933. break;
  934. case SOCK_RDM:
  935. PUTS("RDM");
  936. break;
  937. case SOCK_PACKET:
  938. PUTS("PACKET");
  939. break;
  940. default:
  941. PUTS("UNKNOWN");
  942. break;
  943. }
  944. }
  945. static void parse_futexop (va_list * ap)
  946. {
  947. int op = va_arg(*ap, int);
  948. #ifdef FUTEX_PRIVATE_FLAG
  949. if (op & FUTEX_PRIVATE_FLAG) {
  950. PUTS("FUTEX_PRIVATE|");
  951. op &= ~FUTEX_PRIVATE_FLAG;
  952. }
  953. #endif
  954. #ifdef FUTEX_CLOCK_REALTIME
  955. if (op & FUTEX_CLOCK_REALTIME) {
  956. PUTS("FUTEX_CLOCK_REALTIME|");
  957. op &= ~FUTEX_CLOCK_REALTIME;
  958. }
  959. #endif
  960. op &= FUTEX_CMD_MASK;
  961. switch (op) {
  962. case FUTEX_WAIT:
  963. PUTS("FUTEX_WAIT");
  964. break;
  965. case FUTEX_WAIT_BITSET:
  966. PUTS("FUTEX_WAIT_BITSET");
  967. break;
  968. case FUTEX_WAKE:
  969. PUTS("FUTEX_WAKE");
  970. break;
  971. case FUTEX_WAKE_BITSET:
  972. PUTS("FUTEX_WAKE_BITSET");
  973. break;
  974. case FUTEX_FD:
  975. PUTS("FUTEX_FD");
  976. break;
  977. case FUTEX_REQUEUE:
  978. PUTS("FUTEX_REQUEUE");
  979. break;
  980. case FUTEX_CMP_REQUEUE:
  981. PUTS("FUTEX_CMP_REQUEUE");
  982. break;
  983. case FUTEX_WAKE_OP:
  984. PUTS("FUTEX_WAKE_OP");
  985. break;
  986. default:
  987. PRINTF("OP %d", op);
  988. break;
  989. }
  990. }
  991. static void parse_fcntlop (va_list * ap)
  992. {
  993. int op = va_arg(*ap, int);
  994. switch (op) {
  995. case F_DUPFD:
  996. PUTS("F_DUPFD");
  997. break;
  998. case F_GETFD:
  999. PUTS("F_GETFD");
  1000. break;
  1001. case F_SETFD:
  1002. PUTS("F_SETFD");
  1003. break;
  1004. case F_GETFL:
  1005. PUTS("F_GETFL");
  1006. break;
  1007. case F_SETFL:
  1008. PUTS("F_SETFL");
  1009. break;
  1010. case F_GETLK:
  1011. PUTS("F_GETLK");
  1012. break;
  1013. case F_SETLK:
  1014. PUTS("F_SETLK");
  1015. break;
  1016. case F_SETLKW:
  1017. PUTS("F_SETLKW");
  1018. break;
  1019. case F_SETOWN:
  1020. PUTS("F_SETOWN");
  1021. break;
  1022. case F_GETOWN:
  1023. PUTS("F_GETOWN");
  1024. break;
  1025. case F_SETSIG:
  1026. PUTS("F_SETSIG");
  1027. break;
  1028. case F_GETSIG:
  1029. PUTS("F_GETSIG");
  1030. break;
  1031. case F_GETLK64:
  1032. PUTS("F_GETLK64");
  1033. break;
  1034. case F_SETLK64:
  1035. PUTS("F_SETLK64");
  1036. break;
  1037. case F_SETLKW64:
  1038. PUTS("F_SETLKW64");
  1039. break;
  1040. case F_SETOWN_EX:
  1041. PUTS("F_SETOWN_EX");
  1042. break;
  1043. case F_GETOWN_EX:
  1044. PUTS("F_GETOWN_EX");
  1045. break;
  1046. case F_GETOWNER_UIDS:
  1047. PUTS("F_GETOWNER_UIDS");
  1048. break;
  1049. default:
  1050. PRINTF("OP %d", op);
  1051. break;
  1052. }
  1053. }
  1054. static void parse_ioctlop (va_list * ap)
  1055. {
  1056. int op = va_arg(*ap, int);
  1057. if (op >= TCGETS && op <= TIOCVHANGUP) {
  1058. const char * opnames[] = {
  1059. "TCGETS", /* 0x5401 */ "TCSETS", /* 0x5402 */
  1060. "TCSETSW", /* 0x5403 */ "TCSETSF", /* 0x5404 */
  1061. "TCGETA", /* 0x5405 */ "TCSETA", /* 0x5406 */
  1062. "TCSETAW", /* 0x5407 */ "TCSETAF", /* 0x5408 */
  1063. "TCSBRK", /* 0x5409 */ "TCXONC", /* 0x540A */
  1064. "TCFLSH", /* 0x540B */ "TIOCEXCL", /* 0x540C */
  1065. "TIOCNXCL", /* 0x540D */ "TIOCSCTTY", /* 0x540E */
  1066. "TIOCGPGRP", /* 0x540F */ "TIOCSPGRP", /* 0x5410 */
  1067. "TIOCOUTQ", /* 0x5411 */ "TIOCSTI", /* 0x5412 */
  1068. "TIOCGWINSZ", /* 0x5413 */ "TIOCSWINSZ", /* 0x5414 */
  1069. "TIOCMGET", /* 0x5415 */ "TIOCMBIS", /* 0x5416 */
  1070. "TIOCMBIC", /* 0x5417 */ "TIOCMSET", /* 0x5418 */
  1071. "TIOCGSOFTCAR", /* 0x5419 */ "TIOCSSOFTCAR", /* 0x541A */
  1072. "FIONREAD", /* 0x541B */ "TIOCLINUX", /* 0x541C */
  1073. "TIOCCONS", /* 0x541D */ "TIOCGSERIAL", /* 0x541E */
  1074. "TIOCSSERIAL", /* 0x541F */ "TIOCPKT", /* 0x5420 */
  1075. "FIONBIO", /* 0x5421 */ "TIOCNOTTY", /* 0x5422 */
  1076. "TIOCSETD", /* 0x5423 */ "TIOCGETD", /* 0x5424 */
  1077. "TCSBRKP", /* 0x5425 */ "",
  1078. "TIOCSBRK", /* 0x5427 */ "TIOCCBRK", /* 0x5428 */
  1079. "TIOCGSID", /* 0x5429 */ "TCGETS2", /* 0x542A */
  1080. "TCSETS2", /* 0x542B */ "TCSETSW2", /* 0x542C */
  1081. "TCSETSF2", /* 0x542D */ "TIOCGRS485", /* 0x542E */
  1082. "TIOCSRS485", /* 0x542F */ "TIOCGPTN", /* 0x5430 */
  1083. "TIOCSPTLCK", /* 0x5431 */ "TCGETX", /* 0x5432 */
  1084. "TCSETX", /* 0x5433 */ "TCSETXF", /* 0x5434 */
  1085. "TCSETXW", /* 0x5435 */ "TIOCSIG", /* 0x5436 */
  1086. "TIOCVHANGUP", /* 0x5437 */
  1087. };
  1088. PUTS(opnames[op - TCGETS]);
  1089. return;
  1090. }
  1091. if (op >= FIONCLEX && op <= TIOCSERSETMULTI) {
  1092. const char * opnames[] = {
  1093. "FIONCLEX", /* 0x5450 */ "FIOCLEX", /* 0x5451 */
  1094. "FIOASYNC", /* 0x5452 */ "TIOCSERCONFIG", /* 0x5453 */
  1095. "TIOCSERGWILD", /* 0x5454 */ "TIOCSERSWILD", /* 0x5455 */
  1096. "TIOCGLCKTRMIOS", /* 0x5456 */ "TIOCSLCKTRMIOS", /* 0x5457 */
  1097. "TIOCSERGSTRUCT", /* 0x5458 */ "TIOCSERGETLSR", /* 0x5459 */
  1098. "TIOCSERGETMULTI", /* 0x545A */ "TIOCSERSETMULTI", /* 0x545B */
  1099. };
  1100. PUTS(opnames[op - FIONCLEX]);
  1101. return;
  1102. }
  1103. #define TIOCMIWAIT 0x545C /* wait for a change on serial input line(s) */
  1104. #define TIOCGICOUNT 0x545D /* read serial port __inline__ interrupt counts */
  1105. PRINTF("OP 0x%04x", op);
  1106. }
  1107. static void parse_seek (va_list * ap)
  1108. {
  1109. int seek = va_arg(*ap, int);
  1110. switch(seek) {
  1111. case SEEK_CUR:
  1112. PUTS("SEEK_CUR");
  1113. break;
  1114. case SEEK_SET:
  1115. PUTS("SEEK_SET");
  1116. break;
  1117. case SEEK_END:
  1118. PUTS("SEEK_END");
  1119. break;
  1120. default:
  1121. PRINTF("%d", seek);
  1122. break;
  1123. }
  1124. }
  1125. static void parse_at_fdcwd (va_list * ap)
  1126. {
  1127. int fd = va_arg(*ap, int);
  1128. switch(fd) {
  1129. case AT_FDCWD:
  1130. PUTS("AT_FDCWD");
  1131. break;
  1132. default:
  1133. PRINTF("%d", fd);
  1134. break;
  1135. }
  1136. }
  1137. static void parse_wait_option (va_list * ap)
  1138. {
  1139. int option = va_arg(*ap, int);
  1140. if (option & WNOHANG)
  1141. PUTS("WNOHANG");
  1142. }