diff --git a/docs/logging/liblog.md b/docs/logging/liblog.md index 87bb9d3ef..6c2c1d4a4 100644 --- a/docs/logging/liblog.md +++ b/docs/logging/liblog.md @@ -28,7 +28,7 @@ The `debugger` option displays all logs related to the debugging operations perf ### :material-pipe: Pipe Logging The `pipe` option, on the other hand, displays all logs related to interactions with the process pipe: bytes received and bytes sent. -pipe argv option +pipe argv option ### :material-vector-union: The best of both worlds The `dbg` option is the combination of the `pipe` and `debugger` options. It displays all logs related to the debugging operations performed on the process by libdebug, as well as interactions with the process pipe: bytes received and bytes sent. diff --git a/docs/multithreading/multithreading.md b/docs/multithreading/multithreading.md index 770acad0b..5c33568fd 100644 --- a/docs/multithreading/multithreading.md +++ b/docs/multithreading/multithreading.md @@ -59,7 +59,7 @@ stateDiagram-v2
All live threads are synchronized in their execution state.
-## **libdebug** API for Multithreading +## :octicons-code-24: API for Multithreading To access the threads of a process, you can use the `threads` attribute of the [Debugger](../../from_pydoc/generated/debugger/debugger/) object. This attribute will return a list of [ThreadContext](../../from_pydoc/generated/state/thread_context/) objects, each representing a thread of the process. If you're already familiar with the [Debugger](../../from_pydoc/generated/debugger/debugger/) object, you'll find the [ThreadContext](../../from_pydoc/generated/state/thread_context/) straightforward to use. The [Debugger](../../from_pydoc/generated/debugger/debugger/) has always acted as a facade for the main thread, enabling you to access registers, memory, and other thread state fields exactly as you would for the main thread. The difference you will notice is that the [ThreadContext](../../from_pydoc/generated/state/thread_context/) object is missing a couple of fields that just don't make sense in the context of a single thread (e.g. symbols, which belong to the binary, and memory maps, since they are shared for the whole process). diff --git a/docs/stopping_events/breakpoints.md b/docs/stopping_events/breakpoints.md index 4d684f791..f5ca0f39b 100644 --- a/docs/stopping_events/breakpoints.md +++ b/docs/stopping_events/breakpoints.md @@ -31,7 +31,11 @@ Hardware breakpoints are a more reliable way to set breakpoints. They are made p !!! TIP "Pros and Cons of Hardware Breakpoints" Hardware breakpoints are not affected by self-modifying code. They are also usually faster and more flexible. However, hardware breakpoints are limited in number and are hardware-dependent, so their support may vary across different systems. -## **libdebug** API for Breakpoints +!!! INFO "Hardware Breakpoint Alignment in AArch64" + Hardware breakpoints have to be aligned to 4 bytes (which is the size of an ARM instruction). + + +## :octicons-code-24: API for Breakpoints The `breakpoint()` function in the [Debugger](../../from_pydoc/generated/debugger/debugger/) object sets a breakpoint at a specific address. diff --git a/docs/stopping_events/debugging_flow.md b/docs/stopping_events/debugging_flow.md index 332414f38..ec6bc33f3 100644 --- a/docs/stopping_events/debugging_flow.md +++ b/docs/stopping_events/debugging_flow.md @@ -39,7 +39,7 @@ When a **synchronous** event is hit, the process will stop, awaiting further com Internally, hijacks are considered callbacks, so you cannot have a callback and hijack registered for the same event. -## Common APIs of Stopping Events +## :octicons-code-24: Common APIs of Stopping Events All **libdebug** stopping events share some common attributes that can be employed in debugging scripts. ### :material-power: Enable/Disable diff --git a/docs/stopping_events/signals.md b/docs/stopping_events/signals.md index d7622000c..aca834c20 100644 --- a/docs/stopping_events/signals.md +++ b/docs/stopping_events/signals.md @@ -19,7 +19,7 @@ Signal catchers can be created to register [stopping events](../stopping_events/ !!! INFO "Multiple catchers for the same signal" Please note that there can be at most **one** user-defined catcher or hijack for each signal. If a new catcher is defined for a signal that is already caught or hijacked, the new catcher will replace the old one, and a warning will be printed. -## **libdebug** API for Signal Catching +## :octicons-code-24: API for Signal Catching The `catch_signal()` function in the [Debugger](../../from_pydoc/generated/debugger/debugger/) object registers a catcher for the specified signal. !!! ABSTRACT "Function Signature" diff --git a/docs/stopping_events/syscalls.md b/docs/stopping_events/syscalls.md index 53d9c3bbe..2ffb4f520 100644 --- a/docs/stopping_events/syscalls.md +++ b/docs/stopping_events/syscalls.md @@ -42,7 +42,7 @@ Syscall handlers can be created to register [stopping events](../stopping_events !!! QUESTION "Do I have to handle both on enter and on exit?" When using [asynchronous](../debugging_flow) syscall handlers, you can choose to handle both or only one of the two events. However, when using synchronous handlers, both events will stop the process. -## **libdebug** API for Syscall Handlers +## :octicons-code-24: API for Syscall Handlers The `handle_syscall()` function in the [Debugger](../../from_pydoc/generated/debugger/debugger/) object registers a handler for the specified syscall. !!! ABSTRACT "Function Signature" @@ -230,3 +230,5 @@ For your convenience, you can also easily provide the syscall parameters to be u Again, the secret will be leaked to the standard output. +## :fontawesome-solid-wand-magic-sparkles: Arbitrary Syscall Invocation +Did you know? Since **libdebug** 0.9.0 NAME_TO_BE_DETERMINED you can also invoke an arbitrary syscall on a thread of your choice. Read more on this feature in the page dedicated to [Arbitrary Code Execution](../../quality_of_life/arbitrary_code_execution#arbitrary-syscall-invocation). \ No newline at end of file diff --git a/docs/stopping_events/watchpoints.md b/docs/stopping_events/watchpoints.md index 90509c387..c4a74526b 100644 --- a/docs/stopping_events/watchpoints.md +++ b/docs/stopping_events/watchpoints.md @@ -8,7 +8,7 @@ Watchpoints are a special type of [hardware breakpoint](../breakpoints#hardware- Features of watchpoints are shared with breakpoints, so you can set [asynchronous](../debugging_flow) watchpoints and use properties in the same way. -## **libdebug** API for Watchpoints +## :octicons-code-24: API for Watchpoints The `watchpoint()` function in the [Debugger](../../from_pydoc/generated/debugger/debugger/) object sets a watchpoint at a specific address. While you can also use the [breakpoint API](../breakpoints/#libdebug-api-for-breakpoints) to set up a watchpoint, a specific API is provided for your convenience: !!! ABSTRACT "Function Signature" diff --git a/libdebug/architectures/aarch64/aarch64_syscall_arg_parser.py b/libdebug/architectures/aarch64/aarch64_syscall_arg_parser.py new file mode 100644 index 000000000..063632acd --- /dev/null +++ b/libdebug/architectures/aarch64/aarch64_syscall_arg_parser.py @@ -0,0 +1,1099 @@ +# +# This file is part of libdebug Python library (https://github.com/libdebug/libdebug). +# Copyright (c) 2025 Francesco Panebianco. All rights reserved. +# Licensed under the MIT license. See LICENSE file in the project root for details. +# + +from libdebug.utils.gnu_constants import GnuConstants + +# !!! Parsing Values are up to date with Linux Kernel 6.15 !!! + +#TODO: Check if we can use the same parser for x86_64 +def parse_ptrace_data(*args) -> str: + """ + Parse the ptrace data value into a dictionary. + + Args: + *args: The arguments passed to the ptrace syscall. + """ + request, pid, addr, data = args + + # Skip any other parsing it's just 0 + if data == 0: + return "0x0" + + PTRACE_SETOPTIONS = 0x4200 + PTRACE_SEIZE = 0x4206 + + if request in (PTRACE_SETOPTIONS, PTRACE_SEIZE): + options = { + 0x1: "PTRACE_O_TRACESYSGOOD", + 0x2: "PTRACE_O_TRACEFORK", + 0x4: "PTRACE_O_TRACEVFORK", + 0x8: "PTRACE_O_TRACECLONE", + 0x10: "PTRACE_O_TRACEEXEC", + 0x20: "PTRACE_O_TRACEVFORKDONE", + 0x40: "PTRACE_O_TRACEEXIT", + 0x80: "PTRACE_O_TRACESECCOMP", + 0x100000: "PTRACE_O_EXITKILL", + 0x200000: "PTRACE_O_SUSPEND_SECCOMP", + } + + masked_bits = 0x0 + out = "" + + for bit, name in options.items(): + if data & bit: + masked_bits |= bit + out = out + " | " + name if out else name + data &= ~bit + + # Early exit if all bits are masked + if not data: + break + + # Unmasked values + if data: + return out + f" | {data:#x}" if out else f"{data:#x}" + + return out + else: + return f"{data:#x}" + +AARCH64_SYSCALL_PARSER_MAP = \ +{ + #setxattr + 5:{ + #int flags + 4: GnuConstants.XATTR_FLAGS, + }, + #lsetxattr + 6:{ + #int flags + 4: GnuConstants.XATTR_FLAGS, + }, + #fsetxattr + 7:{ + #int flags + 4: GnuConstants.XATTR_FLAGS, + }, + #eventfd2 + 19:{ + #int flags + 1: GnuConstants.EVENTFD_FLAGS, + }, + #epoll_create1 + 20:{ + #int flags + 0: GnuConstants.EPOLL_CREATE_FLAGS, + }, + #epoll_ctl + 21:{ + #int op + 1: GnuConstants.EPOLL_CTL_OPS, + }, + #dup3 + 24:{ + #int flags + 2: GnuConstants.DUP3_FLAGS, + }, + #fcntl + 25:{ + #unsigned int cmd + 1: GnuConstants.FCNTL_CMDS, + #unsigned long arg + 2: { + "parsing_mode": "custom", + "parser": GnuConstants.parse_fcntl_arg, + }, + }, + #inotify_init1 + 26:{ + #int flags + 0: GnuConstants.INOTIFY_INIT_FLAGS, + }, + #ioprio_set + 30:{ + #int which + 0: GnuConstants.IOPRIO_WHICH, + }, + #ioprio_get + 31:{ + #int which + 0: GnuConstants.IOPRIO_WHICH, + }, + #flock + 32:{ + #unsigned int cmd + 1: GnuConstants.FLOCK_CMDS, + }, + #mknodat + 33:{ + #int dfd + 0: GnuConstants.OPENAT_DFD, + #umode_t mode + 2: GnuConstants.MKNOD_MODES, + }, + #mkdirat + 34:{ + #int dfd + 0: GnuConstants.OPENAT_DFD, + #umode_t mode + 2: GnuConstants.OPEN_MODES, + }, + #unlinkat + 35:{ + #int dfd + 0: GnuConstants.OPENAT_DFD, + #int flag + 2: GnuConstants.UNLINKAT_FLAGS, + }, + #symlinkat + 36:{ + #int newdfd + 1: GnuConstants.OPENAT_DFD, + }, + #linkat + 37:{ + #int olddfd + 0: GnuConstants.OPENAT_DFD, + #int newdfd + 2: GnuConstants.OPENAT_DFD, + #int flags + 4: GnuConstants.LINKAT_FLAGS, + }, + #renameat + 38:{ + #int olddfd + 0: GnuConstants.OPENAT_DFD, + }, + #umount + 39:{ + #int flags + 1: GnuConstants.UMOUNT_FLAGS, + }, + #mount + 40:{ + #unsigned long flags + 3: GnuConstants.MOUNT_FLAGS, + }, + #fallocate + 47:{ + #int mode + 1: GnuConstants.FALLOCATE_MODES, + }, + #faccessat + 48:{ + #int dfd + 0: GnuConstants.OPENAT_DFD, + #int mode + 2: GnuConstants.OPEN_MODES, + }, + #fchmod + 52:{ + #umode_t mode + 1: GnuConstants.OPEN_MODES, + }, + #fchmodat + 53:{ + #int dfd + 0: GnuConstants.OPENAT_DFD, + #umode_t mode + 2: GnuConstants.OPEN_MODES, + }, + #fchownat + 54:{ + #int dfd + 0: GnuConstants.OPENAT_DFD, + #int flag + 4: GnuConstants.FCHOWNAT_FLAGS, + }, + #openat + 56:{ + #int dfd + 0: GnuConstants.OPENAT_DFD, + #int flags + 2: GnuConstants.OPEN_FLAGS, + #umode_t mode + 3: GnuConstants.OPEN_MODES, + }, + #pipe2 + 59:{ + #int flags + 1: GnuConstants.PIPE2_FLAGS, + }, + #quotactl + 60:{ + #unsigned int cmd + 0: GnuConstants.QUOTACTL_CMDS, + # Technically if cmd is Q_QUOTAON, + # we could parse the ID with QFMT defines but + # it's likely not worth it + }, + #lseek + 62:{ + #unsigned int whence + 2: GnuConstants.LSEEK_WHENCE, + }, + #signalfd4 + 74:{ + #int flags + 3: GnuConstants.SIGNALFD_FLAGS, + }, + #vmsplice + 75:{ + #unsigned int flags + 3: GnuConstants.VMSPLICE_FLAGS, + }, + #splice + 76:{ + #unsigned int flags + 5: GnuConstants.SPLICE_FLAGS, + }, + #tee + 77:{ + #unsigned int flags + 3: GnuConstants.SPLICE_FLAGS, + }, + #readlinkat + 78:{ + #int dfd + 0: GnuConstants.OPENAT_DFD, + }, + #newfstatat + 79:{ + #int dfd + 0: GnuConstants.OPENAT_DFD, + #int flag + 3: GnuConstants.NEWSTATFS_FLAGS, + }, + #sync_file_range + 84:{ + #unsigned int flags + 3: GnuConstants.SYNC_FILE_RANGE_FLAGS, + }, + #timerfd_create + 85:{ + #int clockid + 0: GnuConstants.TIMERFD_CREATE_CLOCKS, + #int flags + 1: GnuConstants.TIMERFD_CREATE_FLAGS, + }, + #timerfd_settime + 86:{ + #int flags + 1: GnuConstants.TIMERFD_SETTIME_FLAGS, + }, + #utimensat + 88:{ + #int flags + 3: GnuConstants.UTIMENSAT_FLAGS, + }, + #personality + 92:{ + #unsigned int personality + 0: GnuConstants.PROCESS_PERSONALITIES | { + 0x0080000: "PER_LINUX_FDPIC | FDPIC_FUNCPTRS", # Applies only to ARM and SuperH + }, + }, + #waitid + 95:{ + #int which + 0: GnuConstants.WAITID_WHICH, + #int options + 3: GnuConstants.WAITID_OPTIONS, + }, + #unshare + 97:{ + #unsigned long unshare_flags + 0: GnuConstants.UNSHARE_FLAGS, + }, + #futex + 98:{ + #int op + 1: GnuConstants.FUTEX_OPS, + }, + #getitimer + 102:{ + #int which + 0: GnuConstants.ITIMER_WHICH, + }, + #setitimer + 103:{ + #int which + 0: GnuConstants.ITIMER_WHICH, + }, + #kexec_load + 104:{ + #unsigned long flags + 3: GnuConstants.KEXEC_LOAD_FLAGS, + }, + #delete_module + 106:{ + #unsigned int flags + 1: GnuConstants.DELETE_MODULE_FLAGS, + }, + #timer_create + 107:{ + #const clockid_t which_clock + 0: GnuConstants.TIMER_CREATE_WHICH_CLOCK, + }, + #timer_settime + 110:{ + #int flags + 1: GnuConstants.TIMER_SETTIME_FLAGS, + }, + #clock_settime + 112:{ + #const clockid_t which_clock + 0: GnuConstants.WHICH_CLOCK, + }, + #clock_gettime + 113:{ + #const clockid_t which_clock + 0: GnuConstants.WHICH_CLOCK, + }, + #clock_getres + 114:{ + #const clockid_t which_clock + 0: GnuConstants.WHICH_CLOCK, + }, + #clock_nanosleep + 115:{ + #const clockid_t which_clock + 0: GnuConstants.WHICH_CLOCK, + #int flags + 1: GnuConstants.CLOCK_NANOSLEEP_FLAGS, + }, + #syslog + 116:{ + #int type + 0: GnuConstants.SYSLOG_TYPES, + }, + #ptrace + 117:{ + #long request + 0: GnuConstants.PTRACE_COMMON_REQUESTS | { + 0: "PTRACE_TRACEME", + 1: "PTRACE_PEEKTEXT", + 2: "PTRACE_PEEKDATA", + 3: "PTRACE_PEEKUSER", + 4: "PTRACE_POKETEXT", + 5: "PTRACE_POKEDATA", + 6: "PTRACE_POKEUSER", + 7: "PTRACE_CONT", + 8: "PTRACE_KILL", + 9: "PTRACE_SINGLESTEP", + 12: "PTRACE_GETREGS", + 13: "PTRACE_SETREGS", + 14: "PTRACE_GETFPREGS", + 15: "PTRACE_SETFPREGS", + 16: "PTRACE_ATTACH", + 17: "PTRACE_DETACH", + 18: "PTRACE_GETWMMXREGS", + 19: "PTRACE_SETWMMXREGS", + 21: "PTRACE_OLDSETOPTIONS", + 22: "PTRACE_GET_THREAD_AREA", + 23: "PTRACE_SET_SYSCALL", + 24: "PTRACE_SYSCALL", + 25: "PTRACE_GETCRUNCHREGS", # Should be obsolete + 26: "PTRACE_SETCRUNCHREGS", # Should be obsolete + 27: "PTRACE_GETVFPREGS", + 28: "PTRACE_SETVFPREGS", + 29: "PTRACE_GETHBPREGS", + 30: "PTRACE_SETHBPREGS", + 31: "PTRACE_GETFDPIC", + "PTRACE_GETFDPIC_EXEC": 0, + "PTRACE_GETFDPIC_INTERP": 1, + }, + #unsigned long data + 3: { + "parsing_mode": "custom", + "parser": parse_ptrace_data, + }, + }, + #sched_setscheduler + 119:{ + #int policy + 1: GnuConstants.SCHEDULER_POLICIES, + }, + #sched_get_priority_max + 125:{ + #int policy + 0: GnuConstants.SCHEDULER_POLICIES, + }, + #sched_get_priority_min + 126:{ + #int policy + 0: GnuConstants.SCHEDULER_POLICIES, + }, + #kill + 129:{ + #int sig + 1: GnuConstants.SIGNALS, + }, + #tkill + 130:{ + #int sig + 1: GnuConstants.SIGNALS, + }, + #tgkill + 131:{ + #int sig + 2: GnuConstants.SIGNALS, + }, + #rt_sigaction + 134:{ + #int sig + 0: GnuConstants.SIGNALS, + }, + #rt_sigprocmask + 135:{ + #int how + 0: GnuConstants.RT_SIGPROCMASK_HOW, + }, + #rt_sigqueueinfo + 138:{ + #int sig + 1: GnuConstants.SIGNALS, + }, + #setpriority + 140:{ + #int which + 0: GnuConstants.PRIORITY_WHICH, + }, + #getpriority + 141:{ + #int which + 0: GnuConstants.PRIORITY_WHICH, + }, + #reboot + 142:{ + #int magic1 + 0: GnuConstants.REBOOT_MAGIC1, + #int magic2 + 1: GnuConstants.REBOOT_MAGIC2, + #unsigned int cmd + 2: GnuConstants.REBOOT_CMDS, + }, + #getrlimit + 163:{ + #unsigned int resource + 0: GnuConstants.RLIMIT_RESOURCES, + }, + #setrlimit + 164:{ + #unsigned int resource + 0: GnuConstants.RLIMIT_RESOURCES, + #struct rlimit *rlim + 1: {}, + }, + #getrusage + 165:{ + #int who + 0: GnuConstants.RUSAGE_WHO, + }, + #umask + 166:{ + #int mask + 0: GnuConstants.OPEN_MODES, + }, + #prctl + 167:{ + #int option + 0: GnuConstants.PRCTL_OPTIONS, + }, + #mq_open + 180:{ + #int oflag + 1: GnuConstants.MQ_OPEN_FLAGS, + #umode_t mode + 2: GnuConstants.OPEN_MODES, + }, + #msgget + 186:{ + #key_t key + 0: GnuConstants.MSGGET_KEYS, + #int msgflg + 1: GnuConstants.MSGGET_FLAGS, + }, + #msgctl + 187:{ + #int cmd + 1: GnuConstants.MSGCTL_CMDS, + }, + #msgrcv + 188:{ + #int msgflg + 4: GnuConstants.MSGRCV_FLAGS, + }, + #msgsnd + 189:{ + #int msgflg + 3: GnuConstants.MSGSND_FLAGS, + }, + #semget + 190:{ + #key_t key + 0: GnuConstants.SEMGET_KEYS, + #int semflg + 2: GnuConstants.SEMGET_FLAGS, + }, + #semctl + 191:{ + #int cmd + 2: GnuConstants.SEMCTL_CMDS, + }, + #shmget + 194:{ + #int shmflg + 2: GnuConstants.SHMGET_FLAGS, + }, + #shmctl + 195:{ + #int cmd + 1: GnuConstants.SHMCTL_CMDS, + }, + #shmat + 196:{ + #int shmflg + 2: GnuConstants.SHMAT_FLAGS, + }, + #socket + 198:{ + # int family + 0: GnuConstants.SOCKET_FAMILIES, + # int type + 1: GnuConstants.SOCKET_TYPES, + # int protocol + # Note: Protocol is not parsed here, as it is often 0 + }, + #socketpair + 199:{ + # int family + 0: GnuConstants.SOCKET_FAMILIES, + # int type + 1: GnuConstants.SOCKET_TYPES, + # int protocol + # Note: Protocol is not parsed here, as it is often 0 + }, + #sendto + 206:{ + #unsigned int flags + 3: GnuConstants.SENDTO_FLAGS, + }, + #recvfrom + 207:{ + #unsigned int flags + 3: GnuConstants.RECV_FLAGS, + }, + #setsockopt + # TODO: Complex parsing, future work + # 208:{ + # #int fd + # 0: {}, + # #int level + # 1: {}, + # #int optname + # 2: {}, + # #char *optval + # 3: {}, + # #int optlen + # 4: {}, + # }, + #getsockopt + # TODO: Complex parsing, future work + # 209:{ + # #int fd + # 0: {}, + # #int level + # 1: {}, + # #int optname + # 2: {}, + # #char *optval + # 3: {}, + # #int *optlen + # 4: {}, + # }, + #shutdown + 210:{ + #int how + 1: GnuConstants.SHUTDOWN_HOW, + }, + #sendmsg + 211:{ + #unsigned int flags + 2: GnuConstants.SENDMSG_FLAGS, + }, + #recvmsg + 212:{ + #unsigned int flags + 2: GnuConstants.RECVMMSG_FLAGS, + }, + #mremap + 216:{ + #unsigned long flags + 3: GnuConstants.MREMAP_FLAGS, + }, + #add_key + 217:{ + #key_serial_t ringid + 4: { + 0xFFFFFFFFFFFFFFFF: "KEY_SPEC_THREAD_KEYRING", + 0xFFFFFFFFFFFFFFFE: "KEY_SPEC_PROCESS_KEYRING", + 0xFFFFFFFFFFFFFFFD: "KEY_SPEC_SESSION_KEYRING", + 0xFFFFFFFFFFFFFFFC: "KEY_SPEC_USER_KEYRING", + 0xFFFFFFFFFFFFFFFB: "KEY_SPEC_USER_SESSION_KEYRING", + 0xFFFFFFFFFFFFFFFA: "KEY_SPEC_GROUP_KEYRING", + 0xFFFFFFFFFFFFFF9F: "KEY_SPEC_REQKEY_AUTH_KEY", + 0xFFFFFFFFFFFFFF9E: "KEY_SPEC_REQUESTOR_KEYRING", + "parsing_mode": "sequential", + }, + }, + #request_key + 218:{ + #key_serial_t destringid + 3: { + 0xFFFFFFFFFFFFFFFF: "KEY_SPEC_THREAD_KEYRING", + 0xFFFFFFFFFFFFFFFE: "KEY_SPEC_PROCESS_KEYRING", + 0xFFFFFFFFFFFFFFFD: "KEY_SPEC_SESSION_KEYRING", + 0xFFFFFFFFFFFFFFFC: "KEY_SPEC_USER_KEYRING", + 0xFFFFFFFFFFFFFFFB: "KEY_SPEC_USER_SESSION_KEYRING", + 0xFFFFFFFFFFFFFFFA: "KEY_SPEC_GROUP_KEYRING", + 0xFFFFFFFFFFFFFF9F: "KEY_SPEC_REQKEY_AUTH_KEY", + 0xFFFFFFFFFFFFFF9E: "KEY_SPEC_REQUESTOR_KEYRING", + "parsing_mode": "sequential", + }, + }, + #keyctl + 219:{ + #int option + 0: GnuConstants.KEYCTL_OPTIONS, + }, + #clone + 220:{ + #unsigned long clone_flags + 0: GnuConstants.CLONE_FLAGS_COMMON, + }, + #mmap + 222:{ + #unsigned long prot + 2: GnuConstants.MMAP_PROT, + #unsigned long flags + 3: GnuConstants.MMAP_FLAGS_COMMON, + }, + #fadvise64_64 + 223:{ + #int advice + 3: GnuConstants.FADVISE_ADVICE, + }, + #swapon + 224:{ + #int swap_flags + 1: GnuConstants.SWAPON_FLAGS, + }, + #mprotect + 226:{ + #unsigned long prot + 2: GnuConstants.MPROTECT_PROT, + }, + #msync + 227:{ + #int flags + 2: GnuConstants.MSYNC_FLAGS, + }, + #mlockall + 230:{ + #int flags + 0: GnuConstants.MLOCKALL_FLAGS, + }, + #madvise + 233:{ + #int behavior + 2: GnuConstants.ADVISE_BEHAVIORS, + }, + #remap_file_pages + 234:{ + #unsigned long flags + 4: GnuConstants.REMAP_FILE_PAGES_FLAGS, + }, + #mbind + 235:{ + #unsigned long mode + 2: GnuConstants.MBIND_MODES, + #unsigned int flags + 5: GnuConstants.MBIND_FLAGS, + }, + #get_mempolicy + 236:{ + #unsigned long flags + 4: GnuConstants.GETMEMPOLICY_FLAGS, + }, + #set_mempolicy + 237:{ + #int mode + 0: GnuConstants.SETMEMPOLICY_MODES, + }, + #move_pages + 239:{ + #int flags + 5: GnuConstants.MOVEPAGES_FLAGS, + }, + #rt_tgsigqueueinfo + 240:{ + #int sig + 2: GnuConstants.SIGNALS, + }, + #perf_event_open + 241:{ + #unsigned long flags + 4: GnuConstants.PERF_EVENT_OPEN_FLAGS, + }, + #accept4 + 242:{ + #int flags + 3: GnuConstants.ACCEPT_FLAGS, + }, + #recvmmsg + 243:{ + #unsigned int flags + 3: GnuConstants.RECVMMSG_FLAGS, + }, + #wait4 + 260:{ + #int options + 2: GnuConstants.WAIT4_OPTIONS, + }, + #prlimit64 + 261:{ + #unsigned int resource + 1: GnuConstants.PRLIMIT_RESOURCES, + }, + #fanotify_init + 262:{ + #unsigned int flags + 0: GnuConstants.FANOTIFY_INIT_FLAGS, + #unsigned int event_f_flags + 1: GnuConstants.FANOTIFY_EVENT_F_FLAGS, + }, + #fanotify_mark + 263:{ + #unsigned int flags + 1: GnuConstants.FANOTIFY_MARK_FLAGS, + #__u64 mask + 2: GnuConstants.FANOTIFY_MARK_MASK, + #int dfd + 3: GnuConstants.OPENAT_DFD, + }, + #name_to_handle_at + 264:{ + #int dfd + 0: GnuConstants.OPENAT_DFD, + #int flag + 4: GnuConstants.NAME_TO_HANDLE_FLAGS, + }, + #open_by_handle_at + 265:{ + #int mountdirfd + 0: GnuConstants.OPENAT_DFD, + #int flags + 2: GnuConstants.OPEN_FLAGS, + }, + #clock_adjtime + 266:{ + #const clockid_t which_clock + 0: GnuConstants.WHICH_CLOCK, + }, + #setns + 268:{ + #int flags + 1: GnuConstants.SETNS_FLAGS, + }, + #sendmmsg + 269:{ + #unsigned int flags + 3: GnuConstants.SENDTO_FLAGS, + }, + #kcmp + 272:{ + #int type + 2: GnuConstants.KCMP_TYPES, + }, + #finit_module + 273:{ + #int flags + 2: GnuConstants.FINIT_MODULE_FLAGS, + }, + #renameat2 + 276:{ + #int olddfd + 0: GnuConstants.OPENAT_DFD, + #unsigned int flags + 4: GnuConstants.RENAMEAT_FLAGS, + }, + #seccomp + 277:{ + #unsigned int op + 0: GnuConstants.SECCOMP_OPS, + #unsigned int flags + 1: GnuConstants.SECCOMP_FLAGS, + }, + #getrandom + 278:{ + #unsigned int flags + 2: GnuConstants.GETRANDOM_FLAGS, + }, + #memfd_create + 279:{ + #unsigned int flags + 1: GnuConstants.MEMFD_CREATE_FLAGS, + }, + #bpf + 280:{ + #int cmd + 0: GnuConstants.BPF_CMDS, + }, + #execveat + 281:{ + #int fd + 0: GnuConstants.OPENAT_DFD, + #int flags + 4: GnuConstants.EXECVEAT_FLAGS, + }, + #userfaultfd + 282:{ + #int flags + 0: GnuConstants.USERFAULTFD_FLAGS, + }, + #membarrier + 283:{ + #int cmd + 0: GnuConstants.MEMBARRIER_CMDS, + #unsigned int flags + 1: GnuConstants.MEMBARRIER_FLAGS, + }, + #mlock2 + 284:{ + #int flags + 2: GnuConstants.MLOCK_FLAGS, + }, + #preadv2 + 286:{ + #rwf_t flags + 5: GnuConstants.PREADV_FLAGS, + }, + #pwritev2 + 287:{ + #rwf_t flags + 5: GnuConstants.PREADV_FLAGS, + }, + #pkey_mprotect + 288:{ + #unsigned long prot + 2: GnuConstants.PKEY_MPROTECT_PROTS, + }, + #pkey_alloc + 289:{ + #unsigned long init_val + 1: GnuConstants.PKEY_ALLOC_INIT_VALS, + }, + #statx + 291:{ + #int dfd + 0: GnuConstants.OPENAT_DFD, + #unsigned flags + 2: GnuConstants.STATX_FLAGS, + #unsigned int mask + 3: GnuConstants.STATX_MASKS, + }, + #rseq + 293:{ + #int flags + 2: GnuConstants.RSEQ_FLAGS, + }, + #kexec_file_load + 294:{ + #unsigned long flags + 4: GnuConstants.KEXEC_FILE_LOAD_FLAGS, + }, + #pidfd_send_signal + 424:{ + #int sig + 1: GnuConstants.SIGNALS, + #unsigned int flags + 3: GnuConstants.PIDFD_SEND_SIGNAL_FLAGS, + }, + #io_uring_enter + 426:{ + #u32 flags + 3: GnuConstants.IO_URING_ENTER_FLAGS, + }, + #io_uring_register + 427:{ + #unsigned int opcode + 1: GnuConstants.IO_URING_REGISTER_OPCODES, + }, + #open_tree + 428:{ + #int dfd + 0: GnuConstants.OPENAT_DFD, + #unsigned flags + 2: GnuConstants.OPENTREE_FLAGS, + }, + #move_mount + 429:{ + #int from_dfd + 0: GnuConstants.OPENAT_DFD, + #int to_dfd + 2: GnuConstants.OPENAT_DFD, + #unsigned int flags + 4: GnuConstants.MOVE_MOUNT_FLAGS, + }, + #fsopen + 430:{ + #unsigned int flags + 1: GnuConstants.FSOPEN_FLAGS, + }, + #fsconfig + 431:{ + #unsigned int cmd + 1: GnuConstants.FSCONFIG_CMDS, + }, + #fsmount + 432:{ + #unsigned int flags + 1: GnuConstants.FSMOUNT_FLAGS, + #unsigned int attr_flags + 2: GnuConstants.FSMOUNT_ATTR_FLAGS, + }, + #fspick + 433:{ + #int dfd + 0: GnuConstants.OPENAT_DFD, + #unsigned int flags + 2: GnuConstants.FSPICK_FLAGS, + }, + #pidfd_open + 434:{ + #unsigned int flags + 1: GnuConstants.PIDFD_OPEN_FLAGS, + }, + #close_range + 436:{ + #unsigned int flags + 2: GnuConstants.CLOSE_RANGE_FLAGS, + }, + #openat2 + 437:{ + #int dfd + 0: GnuConstants.OPENAT_DFD, + }, + #faccessat2 + 439:{ + #int dfd + 0: GnuConstants.OPENAT_DFD, + #int mode + 2: GnuConstants.OPEN_MODES, + #int flags + 3: GnuConstants.FACCESSAT_FLAGS, + }, + #process_madvise + 440:{ + #int behavior + 3: GnuConstants.ADVISE_BEHAVIORS, + }, + #mount_setattr + 442:{ + #int dfd + 0: GnuConstants.OPENAT_DFD, + #unsigned int flags + 2: GnuConstants.MOUNT_SETATTR_FLAGS, + }, + #quotactl_fd + 443:{ + #unsigned int cmd + 1: GnuConstants.QUOTACTL_CMDS, + }, + #landlock_create_ruleset + 444:{ + #const __u32 flags + 2: GnuConstants.LANDLOCK_CREATE_RULESET_FLAGS, + }, + #landlock_add_rule + 445:{ + #const enum landlock_rule_type rule_type + 1: GnuConstants.LANDLOCK_ADD_RULE_TYPES, + }, + #memfd_secret + 447:{ + #unsigned int flags + 0: GnuConstants.MEMFD_SECRET_FLAGS, + }, + #futex_waitv + 449:{ + #clockid_t clockid + 4: GnuConstants.WHICH_CLOCK, + }, + #fchmodat2 + 452:{ + #int dfd + 0: GnuConstants.OPENAT_DFD, + #umode_t mode + 2: GnuConstants.OPEN_MODES, + #unsigned int flags + 3: GnuConstants.FCHMODAT_FLAGS, + }, + #map_shadow_stack + 453:{ + #unsigned int flags + 2: GnuConstants.MAP_SHADOW_STACK_FLAGS, + }, + #futex_wake + 454:{ + #unsigned int flags + 3: GnuConstants.FUTEX2_FLAGS, + }, + #futex_wait + 455:{ + #clockid_t clockid + 5: GnuConstants.WHICH_CLOCK, + }, + #listmount + 458:{ + #unsigned int flags + 3: GnuConstants.LISTMOUNT_FLAGS, + }, + #lsm_get_self_attr + 459:{ + #u32 flags + 3: GnuConstants.LSM_GET_SELF_ATTR_FLAGS, + }, + #setxattrat + 463:{ + #int dfd + 0: GnuConstants.OPENAT_DFD, + #unsigned int at_flags + 2: GnuConstants.XATTRAT_FLAGS, + }, + #getxattrat + 464:{ + #int dfd + 0: GnuConstants.OPENAT_DFD, + #unsigned int at_flags + 2: GnuConstants.XATTRAT_FLAGS, + }, + #listxattrat + 465:{ + # int dfd + 0: GnuConstants.OPENAT_DFD, + # unsigned int at_flags + 2: GnuConstants.XATTRAT_FLAGS, + }, + #removexattrat + 466:{ + # int dfd + 0: GnuConstants.OPENAT_DFD, + # unsigned int at_flags + 2: GnuConstants.XATTRAT_FLAGS, + }, +} diff --git a/libdebug/architectures/amd64/amd64_syscall_arg_parser.py b/libdebug/architectures/amd64/amd64_syscall_arg_parser.py new file mode 100644 index 000000000..43831e241 --- /dev/null +++ b/libdebug/architectures/amd64/amd64_syscall_arg_parser.py @@ -0,0 +1,1149 @@ +# +# This file is part of libdebug Python library (https://github.com/libdebug/libdebug). +# Copyright (c) 2025 Francesco Panebianco. All rights reserved. +# Licensed under the MIT license. See LICENSE file in the project root for details. +# +from libdebug.utils.gnu_constants import GnuConstants +from libdebug.utils.parsing_utils import or_parse, sequential_parse + +# !!! Parsing Values are up to date with Linux Kernel 6.15 !!! + + +def parse_ptrace_data(*args) -> str: + """ + Parse the ptrace data value into a dictionary. + + Args: + *args: The arguments passed to the ptrace syscall. + """ + request, pid, addr, data = args + + # Skip any other parsing it's just 0 + if data == 0: + return "0x0" + + PTRACE_SETOPTIONS = 0x4200 + PTRACE_SEIZE = 0x4206 + + if request in (PTRACE_SETOPTIONS, PTRACE_SEIZE): + options = { + 0x1: "PTRACE_O_TRACESYSGOOD", + 0x2: "PTRACE_O_TRACEFORK", + 0x4: "PTRACE_O_TRACEVFORK", + 0x8: "PTRACE_O_TRACECLONE", + 0x10: "PTRACE_O_TRACEEXEC", + 0x20: "PTRACE_O_TRACEVFORKDONE", + 0x40: "PTRACE_O_TRACEEXIT", + 0x80: "PTRACE_O_TRACESECCOMP", + 0x100000: "PTRACE_O_EXITKILL", + 0x200000: "PTRACE_O_SUSPEND_SECCOMP", + } + + masked_bits = 0x0 + out = "" + + for bit, name in options.items(): + if data & bit: + masked_bits |= bit + out = out + " | " + name if out else name + data &= ~bit + + # Early exit if all bits are masked + if not data: + break + + # Unmasked values + if data: + return out + f" | {data:#x}" if out else f"{data:#x}" + + return out + else: + return f"{data:#x}" + + +AMD64_SYSCALL_PARSER_MAP = { + # open + 2: { + # int flags + 1: GnuConstants.OPEN_FLAGS, + # umode_t mode + 2: GnuConstants.OPEN_MODES, + }, + # lseek + 8: { + # unsigned int whence + 2: GnuConstants.LSEEK_WHENCE, + }, + # mmap + 9: { + # unsigned long prot + 2: GnuConstants.MMAP_PROT, + # unsigned long flags + 3: GnuConstants.MMAP_FLAGS_COMMON | {0x00000040: "MAP_32BIT"}, + }, + # mprotect + 10: { + # unsigned long prot + 2: GnuConstants.MPROTECT_PROT, + }, + # rt_sigaction + 13: { + # int sig + 0: GnuConstants.SIGNALS, + }, + # rt_sigprocmask + 14: { + # int how + 0: GnuConstants.RT_SIGPROCMASK_HOW, + }, + # access + 21: { + # int mode + 1: GnuConstants.ACCESS_MODES, + }, + # mremap + 25: { + # unsigned long flags + 3: GnuConstants.MREMAP_FLAGS, + }, + # msync + 26: { + # int flags + 2: GnuConstants.MSYNC_FLAGS, + }, + # madvise + 28: { + # int behavior + 2: GnuConstants.ADVISE_BEHAVIORS, + }, + # shmget + 29: { + # int shmflg + 2: GnuConstants.SHMGET_FLAGS, + }, + # shmat + 30: { + # int shmflg + 2: GnuConstants.SHMAT_FLAGS, + }, + # shmctl + 31: { + # int cmd + 1: GnuConstants.SHMCTL_CMDS, + }, + # getitimer + 36: { + # int which + 0: GnuConstants.ITIMER_WHICH, + }, + # setitimer + 38: { + # int which + 0: GnuConstants.ITIMER_WHICH, + }, + # socket + 41: { + # int family + 0: GnuConstants.SOCKET_FAMILIES, + # int type + 1: GnuConstants.SOCKET_TYPES, + # int protocol + # Note: Protocol is not parsed here, as it is often 0 + }, + # sendto + 44: { + # unsigned int flags + 3: GnuConstants.SENDTO_FLAGS, + }, + # recvfrom + 45: { + # unsigned int flags + 3: GnuConstants.RECV_FLAGS, + }, + # sendmsg + 46: { + # unsigned int flags + 2: GnuConstants.SENDMSG_FLAGS, + }, + # recvmsg + 47: { + # unsigned int flags + 2: GnuConstants.RECVMMSG_FLAGS, + }, + # shutdown + 48: { + # int how + 1: GnuConstants.SHUTDOWN_HOW, + }, + # socketpair + 53: { + # int family + 0: GnuConstants.SOCKET_FAMILIES, + # int type + 1: GnuConstants.SOCKET_TYPES, + # int protocol + # Note: Protocol is not parsed here, as it is often 0 + }, + # setsockopt + 54: { + # TODO: Complex parsing, future work + # int level + 1: {}, + # SO_ACCEPTCONN, SO_ATTACH_FILTER, SO_ATTACH_BPF, SO_ATTACH_REUSEPORT_CBPF, SO_ATTACH_REUSEPORT_EBPF, SO_BINDTODEVICE, SO_BROADCAST, SO_BSDCOMPAT, SO_DEBUG, SO_DETACH_FILTER, SO_DETACH_BPF, SO_DOMAIN, SO_ERROR, SO_DONTROUTE, + # SO_INCOMING_CPU, SO_INCOMING_NAPI_ID, SO_KEEPALIVE, SO_LINGER, SO_LOCK_FILTER, SO_MARK, SO_OOBINLINE, SO_PASSCRED, SO_PASSSEC, SO_PEEK_OFF, SO_PEERCRED, SO_PEERSEC, SO_PRIORITY, SO_RCVBUF, SO_RCVBUFFORCE, SO_RCVLOWAT, + # SO_SNDLOWAT, SO_RCVTIMEO, SO_SNDTIMEO, SO_REUSEADDR, SO_REUSEPORT, SO_RXQ_OVFL, SO_SELECT_ERR_QUEUE, SO_SNDBUF, SO_SNDBUFFORCE, SO_TIMESTAMP, SO_TIMESTAMPNS, SO_TYPE, SO_BUSY_POLL + # int optname + 2: {}, + }, + # getsockopt + 55: { + # TODO: Complex parsing, future work + # int level + 1: {}, + # int optname + 2: {}, + }, + # clone + 56: { + # unsigned long clone_flags + 0: GnuConstants.CLONE_FLAGS_COMMON, + }, + # wait4 + 61: { + # int options + 2: GnuConstants.WAIT4_OPTIONS, + }, + # kill + 62: { + # int sig + 1: GnuConstants.SIGNALS, + }, + # semget + 64: { + # key_t key + 0: GnuConstants.SEMGET_KEYS, + # int semflg + 2: GnuConstants.SEMGET_FLAGS, + }, + # semctl + 66: { + # int cmd + 2: GnuConstants.SEMCTL_CMDS, + }, + # msgget + 68: { + # key_t key + 0: GnuConstants.MSGGET_KEYS, + # int msgflg + 2: GnuConstants.MSGGET_FLAGS, + }, + # msgsnd + 69: { + # int msgflg + 3: GnuConstants.MSGSND_FLAGS, + }, + # msgrcv + 70: { + # int msgflg + 4: GnuConstants.MSGRCV_FLAGS, + }, + # msgctl + 71: { + # int cmd + 1: GnuConstants.MSGCTL_CMDS, + }, + # fcntl + 72: { + # unsigned int cmd + 1: GnuConstants.FCNTL_CMDS, + # unsigned long arg + 2: { + "parsing_mode": "custom", + "parser": GnuConstants.parse_fcntl_arg, + }, + }, + # flock + 73: { + # unsigned int cmd + 1: GnuConstants.FLOCK_CMDS, + }, + # mkdir + 83: { + # umode_t mode + 1: GnuConstants.OPEN_MODES, + }, + # creat + 85: { + # umode_t mode + 1: GnuConstants.OPEN_MODES, + }, + # chmod + 90: { + # umode_t mode + 1: GnuConstants.OPEN_MODES, + }, + # fchmod + 91: { + # umode_t mode + 1: GnuConstants.OPEN_MODES, + }, + # umask + 95: { + # int mask + 0: GnuConstants.OPEN_MODES, + }, + # getrlimit + 97: { + # unsigned int resource + 0: GnuConstants.RLIMIT_RESOURCES, + }, + # getrusage + 98: { + # int who + 0: GnuConstants.RUSAGE_WHO, + }, + # ptrace + 101: { + # long request + 0: GnuConstants.PTRACE_COMMON_REQUESTS + | { + # Arch-specific + 0: "PTRACE_TRACEME", + 1: "PTRACE_PEEKTEXT", + 2: "PTRACE_PEEKDATA", + 3: "PTRACE_PEEKUSER", + 4: "PTRACE_POKETEXT", + 5: "PTRACE_POKEDATA", + 6: "PTRACE_POKEUSER", + 7: "PTRACE_CONT", + 8: "PTRACE_KILL", + 9: "PTRACE_SINGLESTEP", + 16: "PTRACE_ATTACH", + 17: "PTRACE_DETACH", + 24: "PTRACE_SYSCALL", + 12: "PTRACE_GETREGS", + 13: "PTRACE_SETREGS", + 14: "PTRACE_GETFPREGS", + 15: "PTRACE_SETFPREGS", + 18: "PTRACE_GETFPXREGS", + 19: "PTRACE_SETFPXREGS", + 21: "PTRACE_OLDSETOPTIONS", + 25: "PTRACE_GET_THREAD_AREA", + 26: "PTRACE_SET_THREAD_AREA", + 30: "PTRACE_ARCH_PRCTL", + 31: "PTRACE_SYSEMU", + 32: "PTRACE_SYSEMU_SINGLESTEP", + 33: "PTRACE_SINGLEBLOCK", + }, + # unsigned long data + 3: { + "parsing_mode": "custom", + "parser": parse_ptrace_data, + }, + }, + # syslog + 103: { + # int type + 0: GnuConstants.SYSLOG_TYPES, + }, + # rt_sigqueueinfo + 129: { + # int sig + 1: GnuConstants.SIGNALS, + }, + # mknod + 133: { + # umode_t mode + 1: GnuConstants.MKNOD_MODES, + }, + # personality + 135: { + # unsigned int personality + 0: GnuConstants.PROCESS_PERSONALITIES, + }, + # getpriority + 140: { + # int which + 0: GnuConstants.PRIORITY_WHICH, + }, + # setpriority + 141: { + # int which + 0: GnuConstants.PRIORITY_WHICH, + }, + # sched_setscheduler + 144: { + # int policy + 1: GnuConstants.SCHEDULER_POLICIES, + }, + # sched_get_priority_max + 146: { + # int policy + 0: GnuConstants.SCHEDULER_POLICIES, + }, + # sched_get_priority_min + 147: { + # int policy + 0: GnuConstants.SCHEDULER_POLICIES, + }, + # mlockall + 151: { + # int flags + 0: GnuConstants.MLOCKALL_FLAGS, + }, + # prctl + 157: { + # int option + 0: GnuConstants.PRCTL_OPTIONS, + }, + # arch_prctl + 158: { + # int option + 0: { + 0x1001: "ARCH_SET_GS", + 0x1002: "ARCH_SET_FS", + 0x1003: "ARCH_GET_FS", + 0x1004: "ARCH_GET_GS", + 0x1011: "ARCH_GET_CPUID", + 0x1012: "ARCH_SET_CPUID", + # From linux / arch / x86 / include / uapi / asm / prctl.h + # Undocumented, unsure if they should be included + # define ARCH_GET_XCOMP_SUPP 0x1021 + # define ARCH_GET_XCOMP_PERM 0x1022 + # define ARCH_REQ_XCOMP_PERM 0x1023 + # define ARCH_GET_XCOMP_GUEST_PERM 0x1024 + # define ARCH_REQ_XCOMP_GUEST_PERM 0x1025 + # define ARCH_XCOMP_TILECFG 17 + # define ARCH_XCOMP_TILEDATA 18 + # define ARCH_MAP_VDSO_X32 0x2001 + # define ARCH_MAP_VDSO_32 0x2002 + # define ARCH_MAP_VDSO_64 0x2003 + # /* Don't use 0x3001-0x3004 because of old glibcs */ + # define ARCH_GET_UNTAG_MASK 0x4001 + # define ARCH_ENABLE_TAGGED_ADDR 0x4002 + # define ARCH_GET_MAX_TAG_BITS 0x4003 + # define ARCH_FORCE_TAGGED_SVA 0x4004 + # define ARCH_SHSTK_ENABLE 0x5001 + # define ARCH_SHSTK_DISABLE 0x5002 + # define ARCH_SHSTK_LOCK 0x5003 + # define ARCH_SHSTK_UNLOCK 0x5004 + # define ARCH_SHSTK_STATUS 0x5005 + }, + }, + # setrlimit + 160: { + # unsigned int resource + 0: GnuConstants.RLIMIT_RESOURCES, + }, + # mount + 165: { + # unsigned long flags + 3: GnuConstants.MOUNT_FLAGS, + }, + # umount + 166: { + # int flags + 1: GnuConstants.UMOUNT_FLAGS, + }, + # swapon + 167: { + # int swap_flags + 1: GnuConstants.SWAPON_FLAGS, + }, + # reboot + 169: { + # int magic1 + 0: GnuConstants.REBOOT_MAGIC1, + # int magic2 + 1: GnuConstants.REBOOT_MAGIC2, + # unsigned int cmd + 2: GnuConstants.REBOOT_CMDS, + }, + # delete_module + 176: { + # unsigned int flags + 1: GnuConstants.DELETE_MODULE_FLAGS, + }, + # quotactl + 179: { + # unsigned int cmd + 0: GnuConstants.QUOTACTL_CMDS, + # Technically if cmd is Q_QUOTAON, + # we could parse the ID with QFMT defines but + # it's likely not worth it + }, + # setxattr + 188: { + # int flags + 4: GnuConstants.XATTR_FLAGS, + }, + # lsetxattr + 189: { + # int flags + 4: GnuConstants.XATTR_FLAGS, + }, + # fsetxattr + 190: { + # int flags + 4: GnuConstants.XATTR_FLAGS, + }, + # tkill + 200: { + # int sig + 1: GnuConstants.SIGNALS, + }, + # futex + 202: { + # int op + 1: GnuConstants.FUTEX_OPS, + }, + # remap_file_pages + 216: { + # unsigned long flags + 4: GnuConstants.REMAP_FILE_PAGES_FLAGS, + }, + # fadvise64 + 221: { + # int advice + 3: GnuConstants.FADVISE_ADVICE, + }, + # timer_create + 222: { + # const clockid_t which_clock + 0: GnuConstants.TIMER_CREATE_WHICH_CLOCK, + }, + # timer_settime + 223: { + # int flags + 1: GnuConstants.TIMER_SETTIME_FLAGS, + }, + # clock_settime + 227: { + # const clockid_t which_clock + 0: GnuConstants.WHICH_CLOCK, + }, + # clock_gettime + 228: { + # const clockid_t which_clock + 0: GnuConstants.WHICH_CLOCK, + }, + # clock_getres + 229: { + # const clockid_t which_clock + 0: GnuConstants.WHICH_CLOCK, + }, + # clock_nanosleep + 230: { + # const clockid_t which_clock + 0: GnuConstants.WHICH_CLOCK, + # int flags + 1: GnuConstants.CLOCK_NANOSLEEP_FLAGS, + }, + # epoll_ctl + 233: { + # int op + 1: GnuConstants.EPOLL_CTL_OPS, + }, + # tgkill + 234: { + # int sig + 2: GnuConstants.SIGNALS, + }, + # mbind + 237: { + # unsigned long mode + 2: GnuConstants.MBIND_MODES, + # unsigned int flags + 5: GnuConstants.MBIND_FLAGS, + }, + # set_mempolicy + 238: { + # int mode + 0: GnuConstants.SETMEMPOLICY_MODES, + }, + # get_mempolicy + 239: { + # unsigned long flags + 4: GnuConstants.GETMEMPOLICY_FLAGS, + }, + # mq_open + 240: { + # int oflag + 1: GnuConstants.MQ_OPEN_FLAGS, + # umode_t mode + 2: GnuConstants.OPEN_MODES, + }, + # kexec_load + 246: { + # unsigned long flags + 3: GnuConstants.KEXEC_LOAD_FLAGS, + }, + # waitid + 247: { + # int which + 0: GnuConstants.WAITID_WHICH, + # int options + 3: GnuConstants.WAITID_OPTIONS, + }, + # add_key + 248: { + # key_serial_t ringid + 4: { + 0xFFFFFFFFFFFFFFFF: "KEY_SPEC_THREAD_KEYRING", + 0xFFFFFFFFFFFFFFFE: "KEY_SPEC_PROCESS_KEYRING", + 0xFFFFFFFFFFFFFFFD: "KEY_SPEC_SESSION_KEYRING", + 0xFFFFFFFFFFFFFFFC: "KEY_SPEC_USER_KEYRING", + 0xFFFFFFFFFFFFFFFB: "KEY_SPEC_USER_SESSION_KEYRING", + 0xFFFFFFFFFFFFFFFA: "KEY_SPEC_GROUP_KEYRING", + 0xFFFFFFFFFFFFFF9F: "KEY_SPEC_REQKEY_AUTH_KEY", + 0xFFFFFFFFFFFFFF9E: "KEY_SPEC_REQUESTOR_KEYRING", + "parsing_mode": "sequential", + }, + }, + # request_key + 249: { + # key_serial_t destringid + 3: { + 0xFFFFFFFFFFFFFFFF: "KEY_SPEC_THREAD_KEYRING", + 0xFFFFFFFFFFFFFFFE: "KEY_SPEC_PROCESS_KEYRING", + 0xFFFFFFFFFFFFFFFD: "KEY_SPEC_SESSION_KEYRING", + 0xFFFFFFFFFFFFFFFC: "KEY_SPEC_USER_KEYRING", + 0xFFFFFFFFFFFFFFFB: "KEY_SPEC_USER_SESSION_KEYRING", + 0xFFFFFFFFFFFFFFFA: "KEY_SPEC_GROUP_KEYRING", + 0xFFFFFFFFFFFFFF9F: "KEY_SPEC_REQKEY_AUTH_KEY", + 0xFFFFFFFFFFFFFF9E: "KEY_SPEC_REQUESTOR_KEYRING", + "parsing_mode": "sequential", + }, + }, + # keyctl + 250: { + # int option + 0: GnuConstants.KEYCTL_OPTIONS, + }, + # ioprio_set + 251: { + # int which + 0: GnuConstants.IOPRIO_WHICH, + }, + # ioprio_get + 252: { + # int which + 0: GnuConstants.IOPRIO_WHICH, + }, + # openat + 257: { + # int dfd + 0: GnuConstants.OPENAT_DFD, + # int flags + 2: GnuConstants.OPEN_FLAGS, + # umode_t mode + 3: GnuConstants.OPEN_MODES, + }, + # mkdirat + 258: { + # int dfd + 0: GnuConstants.OPENAT_DFD, + # umode_t mode + 2: GnuConstants.OPEN_MODES, + }, + # mknodat + 259: { + # int dfd + 0: GnuConstants.OPENAT_DFD, + # umode_t mode + 2: GnuConstants.MKNOD_MODES, + }, + # fchownat + 260: { + # int dfd + 0: GnuConstants.OPENAT_DFD, + # int flag + 4: GnuConstants.FCHOWNAT_FLAGS, + }, + # newfstatat + 262: { + # int dfd + 0: GnuConstants.OPENAT_DFD, + # int flag + 3: GnuConstants.NEWSTATFS_FLAGS, + }, + # unlinkat + 263: { + # int dfd + 0: GnuConstants.OPENAT_DFD, + # int flag + 2: GnuConstants.UNLINKAT_FLAGS, + }, + # renameat + 264: { + # int olddfd + 0: GnuConstants.OPENAT_DFD, + }, + # linkat + 265: { + # int olddfd + 0: GnuConstants.OPENAT_DFD, + # int newdfd + 2: GnuConstants.OPENAT_DFD, + # int flags + 4: GnuConstants.LINKAT_FLAGS, + }, + # symlinkat + 266: { + # int newdfd + 1: GnuConstants.OPENAT_DFD, + }, + # readlinkat + 267: { + # int dfd + 0: GnuConstants.OPENAT_DFD, + }, + # fchmodat + 268: { + # int dfd + 0: GnuConstants.OPENAT_DFD, + # umode_t mode + 2: GnuConstants.OPEN_MODES, + }, + # faccessat + 269: { + # int dfd + 0: GnuConstants.OPENAT_DFD, + # int mode + 2: GnuConstants.OPEN_MODES, + }, + # unshare + 272: { + # unsigned long unshare_flags + 0: GnuConstants.UNSHARE_FLAGS, + }, + # splice + 275: { + # unsigned int flags + 5: GnuConstants.SPLICE_FLAGS, + }, + # tee + 276: { + # unsigned int flags + 3: GnuConstants.SPLICE_FLAGS, + }, + # sync_file_range + 277: { + # unsigned int flags + 3: GnuConstants.SYNC_FILE_RANGE_FLAGS, + }, + # vmsplice + 278: { + # unsigned int flags + 3: GnuConstants.VMSPLICE_FLAGS, + }, + # move_pages + 279: { + # int flags + 5: GnuConstants.MOVEPAGES_FLAGS, + }, + # utimensat + 280: { + # int flags + 3: GnuConstants.UTIMENSAT_FLAGS, + }, + # timerfd_create + 283: { + # int clockid + 0: GnuConstants.TIMERFD_CREATE_CLOCKS, + # int flags + 1: GnuConstants.TIMERFD_CREATE_FLAGS, + }, + # fallocate + 285: { + # int mode + 1: GnuConstants.FALLOCATE_MODES, + }, + # timerfd_settime + 286: { + # int flags + 1: GnuConstants.TIMERFD_SETTIME_FLAGS, + }, + # accept4 + 288: { + # int flags + 3: GnuConstants.ACCEPT_FLAGS, + }, + # signalfd4 + 289: { + # int flags + 3: GnuConstants.SIGNALFD_FLAGS, + }, + # eventfd2 + 290: { + # int flags + 1: GnuConstants.EVENTFD_FLAGS, + }, + # epoll_create1 + 291: { + # int flags + 0: GnuConstants.EPOLL_CREATE_FLAGS, + }, + # dup3 + 292: { + # int flags + 2: GnuConstants.DUP3_FLAGS, + }, + # pipe2 + 293: { + # int flags + 1: GnuConstants.PIPE2_FLAGS, + }, + # inotify_init1 + 294: { + # int flags + 0: GnuConstants.INOTIFY_INIT_FLAGS, + }, + # rt_tgsigqueueinfo + 297: { + # int sig + 2: GnuConstants.SIGNALS, + }, + # perf_event_open + 298: { + # unsigned long flags + 4: GnuConstants.PERF_EVENT_OPEN_FLAGS, + }, + # recvmmsg + 299: { + # unsigned int flags + 3: GnuConstants.RECVMMSG_FLAGS, + }, + # fanotify_init + 300: { + # unsigned int flags + 0: GnuConstants.FANOTIFY_INIT_FLAGS, + # unsigned int event_f_flags + 1: GnuConstants.FANOTIFY_EVENT_F_FLAGS, + }, + # fanotify_mark + 301: { + # unsigned int flags + 1: GnuConstants.FANOTIFY_MARK_FLAGS, + # __u64 mask + 2: GnuConstants.FANOTIFY_MARK_MASK, + # int dfd + 3: GnuConstants.OPENAT_DFD, + }, + # prlimit64 + 302: { + # unsigned int resource + 1: GnuConstants.PRLIMIT_RESOURCES, + }, + # name_to_handle_at + 303: { + # int dfd + 0: GnuConstants.OPENAT_DFD, + # int flag + 4: GnuConstants.NAME_TO_HANDLE_FLAGS, + }, + # open_by_handle_at + 304: { + # int mountdirfd + 0: GnuConstants.OPENAT_DFD, + # int flags + 2: GnuConstants.OPEN_FLAGS, + }, + # clock_adjtime + 305: { + # const clockid_t which_clock + 0: GnuConstants.WHICH_CLOCK, + }, + # sendmmsg + 307: { + # unsigned int flags + 3: GnuConstants.SENDTO_FLAGS, + }, + # setns + 308: { + # int flags + 1: GnuConstants.SETNS_FLAGS, + }, + # kcmp + 312: { + # int type + 2: GnuConstants.KCMP_TYPES, + }, + # finit_module + 313: { + # int flags + 2: GnuConstants.FINIT_MODULE_FLAGS, + }, + # renameat2 + 316: { + # int olddfd + 0: GnuConstants.OPENAT_DFD, + # unsigned int flags + 4: GnuConstants.RENAMEAT_FLAGS, + }, + # seccomp + 317: { + # unsigned int op + 0: GnuConstants.SECCOMP_OPS, + # unsigned int flags + 1: GnuConstants.SECCOMP_FLAGS, + }, + # getrandom + 318: { + # unsigned int flags + 2: GnuConstants.GETRANDOM_FLAGS, + }, + # memfd_create + 319: { + # unsigned int flags + 1: GnuConstants.MEMFD_CREATE_FLAGS, + }, + # kexec_file_load + 320: { + # unsigned long flags + 4: GnuConstants.KEXEC_FILE_LOAD_FLAGS, + }, + # bpf + 321: { + # int cmd + 0: GnuConstants.BPF_CMDS, + }, + # execveat + 322: { + # int fd + 0: GnuConstants.OPENAT_DFD, + # int flags + 4: GnuConstants.EXECVEAT_FLAGS, + }, + # userfaultfd + 323: { + # int flags + 0: GnuConstants.USERFAULTFD_FLAGS, + }, + # membarrier + 324: { + # int cmd + 0: GnuConstants.MEMBARRIER_CMDS, + # unsigned int flags + 1: GnuConstants.MEMBARRIER_FLAGS, + }, + # mlock2 + 325: { + # int flags + 2: GnuConstants.MLOCK_FLAGS, + }, + # preadv2 + 327: { + # rwf_t flags + 5: GnuConstants.PREADV_FLAGS, + }, + # pwritev2 + 328: { + # rwf_t flags + 5: GnuConstants.PREADV_FLAGS, + }, + # pkey_mprotect + 329: { + # unsigned long prot + 2: GnuConstants.PKEY_MPROTECT_PROTS, + }, + # pkey_alloc + 330: { + # unsigned long init_val + 1: GnuConstants.PKEY_ALLOC_INIT_VALS, + }, + # statx + 332: { + # int dfd + 0: GnuConstants.OPENAT_DFD, + # unsigned flags + 2: GnuConstants.STATX_FLAGS, + # unsigned int mask + 3: GnuConstants.STATX_MASKS, + }, + # rseq + 334: { + # int flags + 2: GnuConstants.RSEQ_FLAGS, + }, + # pidfd_send_signal + 424: { + # int sig + 1: GnuConstants.SIGNALS, + # unsigned int flags + 3: GnuConstants.PIDFD_SEND_SIGNAL_FLAGS, + }, + # io_uring_enter + 426: { + # u32 flags + 2: GnuConstants.IO_URING_ENTER_FLAGS, + }, + # io_uring_register + 427: { + # unsigned int opcode + 1: GnuConstants.IO_URING_REGISTER_OPCODES, + }, + # open_tree + 428: { + # int dfd + 0: GnuConstants.OPENAT_DFD, + # unsigned flags + 2: GnuConstants.OPENTREE_FLAGS, + }, + # move_mount + 429: { + # int from_dfd + 0: GnuConstants.OPENAT_DFD, + # int to_dfd + 2: GnuConstants.OPENAT_DFD, + # unsigned int flags + 4: GnuConstants.MOVE_MOUNT_FLAGS, + }, + # fsopen + 430: { + # unsigned int flags + 1: GnuConstants.FSOPEN_FLAGS, + }, + # fsconfig + 431: { + # unsigned int cmd + 1: GnuConstants.FSCONFIG_CMDS, + }, + # fsmount + 432: { + # unsigned int flags + 1: GnuConstants.FSMOUNT_FLAGS, + # unsigned int attr_flags + 2: GnuConstants.FSMOUNT_ATTR_FLAGS, + }, + # fspick + 433: { + # int dfd + 0: GnuConstants.OPENAT_DFD, + # unsigned int flags + 2: GnuConstants.FSPICK_FLAGS, + }, + # pidfd_open + 434: { + # unsigned int flags + 1: GnuConstants.PIDFD_OPEN_FLAGS, + }, + # close_range + 436: { + # unsigned int flags + 2: GnuConstants.CLOSE_RANGE_FLAGS, + }, + # openat2 + 437: { + # int dfd + 0: GnuConstants.OPENAT_DFD, + }, + # faccessat2 + 439: { + # int dfd + 0: GnuConstants.OPENAT_DFD, + # int mode + 2: GnuConstants.OPEN_MODES, + # int flags + 3: GnuConstants.FACCESSAT_FLAGS, + }, + # process_madvise + 440: { + # int behavior + 3: GnuConstants.ADVISE_BEHAVIORS, + }, + # mount_setattr + 442: { + # int dfd + 0: GnuConstants.OPENAT_DFD, + # unsigned int flags + 2: GnuConstants.MOUNT_SETATTR_FLAGS, + }, + # landlock_create_ruleset + 444: { + # const __u32 flags + 2: GnuConstants.LANDLOCK_CREATE_RULESET_FLAGS, + }, + # landlock_add_rule + 445: { + # const enum landlock_rule_type rule_type + 1: GnuConstants.LANDLOCK_ADD_RULE_TYPES, + }, + # memfd_secret + 447: { + # unsigned int flags + 0: GnuConstants.MEMFD_SECRET_FLAGS, + }, + # futex_waitv + 449: { + # clockid_t clockid + 4: GnuConstants.WHICH_CLOCK, + }, + # cachestat + 451: { + # unsigned int fd + 0: GnuConstants.OPENAT_DFD, + }, + # fchmodat2 + 452: { + # int dfd + 0: GnuConstants.OPENAT_DFD, + # umode_t mode + 2: GnuConstants.OPEN_MODES, + # unsigned int flags + 3: GnuConstants.FCHMODAT_FLAGS, + }, + # map_shadow_stack + 453: { + # unsigned int flags + 2: GnuConstants.MAP_SHADOW_STACK_FLAGS, + }, + # futex_wake + 454: { + # unsigned int flags + 3: GnuConstants.FUTEX2_FLAGS, + }, + # futex_wait + 455: { + # clockid_t clockid + 5: GnuConstants.WHICH_CLOCK, + }, + # listmount + 458: { + # unsigned int flags + 3: GnuConstants.LISTMOUNT_FLAGS, + }, + # lsm_get_self_attr + 459: { + # u32 flags + 3: GnuConstants.LSM_GET_SELF_ATTR_FLAGS, + }, + # setxattrat + 463: { + # int dfd + 0: GnuConstants.OPENAT_DFD, + # unsigned int at_flags + 2: GnuConstants.XATTRAT_FLAGS, + }, + # getxattrat + 464: { + # int dfd + 0: GnuConstants.OPENAT_DFD, + # unsigned int at_flags + 2: GnuConstants.XATTRAT_FLAGS, + }, + # listxattrat + 465: { + # int dfd + 0: GnuConstants.OPENAT_DFD, + # unsigned int at_flags + 2: GnuConstants.XATTRAT_FLAGS, + }, + # removexattrat + 466: { + # int dfd + 0: GnuConstants.OPENAT_DFD, + # unsigned int at_flags + 2: GnuConstants.XATTRAT_FLAGS, + }, +} diff --git a/libdebug/architectures/call_utilities_manager.py b/libdebug/architectures/call_utilities_manager.py index b9a2040cd..56b55fca2 100644 --- a/libdebug/architectures/call_utilities_manager.py +++ b/libdebug/architectures/call_utilities_manager.py @@ -21,5 +21,5 @@ def compute_call_skip(self: CallUtilitiesManager, opcode_window: bytes) -> int: """Compute the address where to skip after the current call instruction.""" @abstractmethod - def get_call_and_skip_amount(self, opcode_window: bytes) -> tuple[bool, int]: + def get_call_and_skip_amount(self: CallUtilitiesManager, opcode_window: bytes) -> tuple[bool, int]: """Check if the current instruction is a call instruction and compute the instruction size.""" diff --git a/libdebug/architectures/i386/i386_syscall_arg_parser.py b/libdebug/architectures/i386/i386_syscall_arg_parser.py new file mode 100644 index 000000000..672fd73aa --- /dev/null +++ b/libdebug/architectures/i386/i386_syscall_arg_parser.py @@ -0,0 +1,1352 @@ +# +# This file is part of libdebug Python library (https://github.com/libdebug/libdebug). +# Copyright (c) 2025 Francesco Panebianco. All rights reserved. +# Licensed under the MIT license. See LICENSE file in the project root for details. +# + +from libdebug.utils.gnu_constants import GnuConstants +from libdebug.utils.parsing_utils import or_parse, sequential_parse + +# !!! Parsing Values are up to date with Linux Kernel 6.15 !!! + + +def parse_ptrace_data(*args) -> str: + """ + Parse the ptrace data value into a dictionary. + + Args: + *args: The arguments passed to the ptrace syscall. + """ + request, pid, addr, data = args + + # Skip any other parsing it's just 0 + if data == 0: + return "0x0" + + PTRACE_SETOPTIONS = 0x4200 + PTRACE_SEIZE = 0x4206 + + if request in (PTRACE_SETOPTIONS, PTRACE_SEIZE): + options = { + 0x1: "PTRACE_O_TRACESYSGOOD", + 0x2: "PTRACE_O_TRACEFORK", + 0x4: "PTRACE_O_TRACEVFORK", + 0x8: "PTRACE_O_TRACECLONE", + 0x10: "PTRACE_O_TRACEEXEC", + 0x20: "PTRACE_O_TRACEVFORKDONE", + 0x40: "PTRACE_O_TRACEEXIT", + 0x80: "PTRACE_O_TRACESECCOMP", + 0x100000: "PTRACE_O_EXITKILL", + 0x200000: "PTRACE_O_SUSPEND_SECCOMP", + } + + masked_bits = 0x0 + out = "" + + for bit, name in options.items(): + if data & bit: + masked_bits |= bit + out = out + " | " + name if out else name + data &= ~bit + + # Early exit if all bits are masked + if not data: + break + + # Unmasked values + if data: + return out + f" | {data:#x}" if out else f"{data:#x}" + + return out + else: + return f"{data:#x}" + + +I386_SYSCALL_PARSER_MAP = { + # open + 5: { + # int flags + 1: GnuConstants.OPEN_FLAGS, + # umode_t mode + 2: GnuConstants.OPEN_MODES, + }, + # waitpid + 7: { + # int options + 2: GnuConstants.WAITID_OPTIONS, + }, + # creat + 8: { + # umode_t mode + 1: GnuConstants.OPEN_MODES, + }, + # mknod + 14: { + # umode_t mode + 1: GnuConstants.MKNOD_MODES, + }, + # chmod + 15: { + # umode_t mode + 1: GnuConstants.OPEN_MODES, + }, + # lseek + 19: { + # unsigned int whence + 2: GnuConstants.LSEEK_WHENCE, + }, + # mount + 21: { + # unsigned long flags + 3: GnuConstants.MOUNT_FLAGS, + }, + # ptrace + 26: { + # long request + 0: GnuConstants.PTRACE_COMMON_REQUESTS + | { + 0: "PTRACE_TRACEME", + 1: "PTRACE_PEEKTEXT", + 2: "PTRACE_PEEKDATA", + 3: "PTRACE_PEEKUSER", + 4: "PTRACE_POKETEXT", + 5: "PTRACE_POKEDATA", + 6: "PTRACE_POKEUSER", + 7: "PTRACE_CONT", + 8: "PTRACE_KILL", + 9: "PTRACE_SINGLESTEP", + 16: "PTRACE_ATTACH", + 17: "PTRACE_DETACH", + 24: "PTRACE_SYSCALL", + 12: "PTRACE_GETREGS", + 13: "PTRACE_SETREGS", + 14: "PTRACE_GETFPREGS", + 15: "PTRACE_SETFPREGS", + 18: "PTRACE_GETFPXREGS", + 19: "PTRACE_SETFPXREGS", + 21: "PTRACE_OLDSETOPTIONS", + 25: "PTRACE_GET_THREAD_AREA", + 26: "PTRACE_SET_THREAD_AREA", + 31: "PTRACE_SYSEMU", + 32: "PTRACE_SYSEMU_SINGLESTEP", + }, + # unsigned long data + 3: { + "parsing_mode": "custom", + "parser": parse_ptrace_data, + }, + }, + # access + 33: { + # int mode + 1: GnuConstants.ACCESS_MODES, + }, + # kill + 37: { + # int sig + 1: GnuConstants.SIGNALS, + }, + # mkdir + 39: { + # umode_t mode + 1: GnuConstants.OPEN_MODES, + }, + # signal + 48: { + # int sig + 0: GnuConstants.SIGNALS, + }, + # umount + 52: { + # int flags + 1: GnuConstants.UMOUNT_FLAGS, + }, + # fcntl + 55: { + # unsigned int cmd + 1: GnuConstants.FCNTL_CMDS, + # unsigned long arg + 2: { + "parsing_mode": "custom", + "parser": GnuConstants.parse_fcntl_arg, + }, + }, + # umask + 60: { + # int mask + 0: GnuConstants.OPEN_MODES, + }, + # sigaction + 67: { + # int sig + 0: GnuConstants.SIGNALS, + }, + # setrlimit + 75: { + # unsigned int resource + 0: { + 0: "RLIMIT_CPU", + 1: "RLIMIT_FSIZE", + 2: "RLIMIT_DATA", + 3: "RLIMIT_STACK", + 4: "RLIMIT_CORE", + 5: "RLIMIT_RSS", + 6: "RLIMIT_NPROC", + 7: "RLIMIT_NOFILE", + 8: "RLIMIT_MEMLOCK", + 9: "RLIMIT_AS", + 10: "RLIMIT_LOCKS", + 11: "RLIMIT_SIGPENDING", + 12: "RLIMIT_MSGQUEUE", + 13: "RLIMIT_NICE", + 14: "RLIMIT_RTPRIO", + 15: "RLIMIT_RTTIME", + }, + }, + # getrlimit + 76: { + # unsigned int resource + 0: GnuConstants.RLIMIT_RESOURCES + }, + # getrusage + 77: { + # int who + 0: GnuConstants.RUSAGE_WHO, + }, + # swapon + 87: { + # int swap_flags + 1: GnuConstants.SWAPON_FLAGS, + }, + # reboot + 88: { + # int magic1 + 0: GnuConstants.REBOOT_MAGIC1, + # int magic2 + 1: GnuConstants.REBOOT_MAGIC2, + # unsigned int cmd + 2: GnuConstants.REBOOT_CMDS, + }, + # TODO: Implement struct parsing just for this + # #mmap + # 90:{ + # #struct mmap_arg_struct *arg + # 0: {}, + # }, + # fchmod + 94: { + # umode_t mode + 1: GnuConstants.OPEN_MODES, + }, + # getpriority + 96: { + # int which + 0: GnuConstants.PRIORITY_WHICH, + }, + # setpriority + 97: { + # int which + 0: GnuConstants.PRIORITY_WHICH, + }, + # socketcall + 102: { + # int call + 0: { + 1: "SYS_SOCKET", + 2: "SYS_BIND", + 3: "SYS_CONNECT", + 4: "SYS_LISTEN", + 5: "SYS_ACCEPT", + 6: "SYS_GETSOCKNAME", + 7: "SYS_GETPEERNAME", + 8: "SYS_SOCKETPAIR", + 9: "SYS_SEND", + 10: "SYS_RECV", + 11: "SYS_SENDTO", + 12: "SYS_RECVFROM", + 13: "SYS_SHUTDOWN", + 14: "SYS_SETSOCKOPT", + 15: "SYS_GETSOCKOPT", + 16: "SYS_SENDMSG", + 17: "SYS_RECVMSG", + 18: "SYS_ACCEPT4", + 19: "SYS_RECVMMSG", + 20: "SYS_SENDMMSG", + "parsing_mode": "sequential", + }, + }, + # syslog + 103: { + # int type + 0: GnuConstants.SYSLOG_TYPES, + }, + # setitimer + 104: { + # int which + 0: GnuConstants.ITIMER_WHICH, + }, + # getitimer + 105: { + # int which + 0: GnuConstants.ITIMER_WHICH, + }, + # wait4 + 114: { + # int options + 2: GnuConstants.WAIT4_OPTIONS, + }, + # ipc + 117: { + # unsigned int call + 0: { + 1: "SEMOP", + 2: "SEMGET", + 3: "SEMCTL", + 4: "SEMTIMEDOP", + 11: "MSGSND", + 12: "MSGRCV", + 13: "MSGGET", + 14: "MSGCTL", + 21: "SHMAT", + 22: "SHMDT", + 23: "SHMGET", + 24: "SHMCTL", + "parsing_mode": "sequential", + }, + }, + # clone + 120: { + # unsigned long clone_flags + 0: GnuConstants.CLONE_FLAGS_COMMON, + }, + # mprotect + 125: { + # unsigned long prot + 2: GnuConstants.MPROTECT_PROT, + }, + # sigprocmask + 126: { + # int how + 0: GnuConstants.RT_SIGPROCMASK_HOW, + }, + # delete_module + 129: { + # unsigned int flags + 1: GnuConstants.DELETE_MODULE_FLAGS, + }, + # quotactl + 131: { + # unsigned int cmd + 0: GnuConstants.QUOTACTL_CMDS, + }, + # fchdir + 133: { + # unsigned int fd + 0: GnuConstants.OPENAT_DFD, + }, + # personality + 136: { + # unsigned int personality + 0: GnuConstants.PROCESS_PERSONALITIES, + }, + # llseek + 140: { + # unsigned int whence + 4: GnuConstants.LSEEK_WHENCE, + }, + # flock + 143: { + # unsigned int cmd + 1: GnuConstants.FLOCK_CMDS, + }, + # msync + 144: { + # int flags + 2: GnuConstants.MSYNC_FLAGS, + }, + # mlockall + 152: { + # int flags + 0: GnuConstants.MLOCKALL_FLAGS, + }, + # sched_setscheduler + 156: { + # int policy + 1: GnuConstants.SCHEDULER_POLICIES, + }, + # sched_get_priority_max + 159: { + # int policy + 0: GnuConstants.SCHEDULER_POLICIES, + }, + # sched_get_priority_min + 160: { + # int policy + 0: GnuConstants.SCHEDULER_POLICIES, + }, + # mremap + 163: { + # unsigned long flags + 3: GnuConstants.MREMAP_FLAGS, + }, + # vm86 + 166: { + # unsigned long cmd + 0: { + 0: "VM86_PLUS_INSTALL_CHECK", + 1: "VM86_ENTER", + 2: "VM86_ENTER_NO_BYPASS", + 3: "VM86_REQUEST_IRQ", + 4: "VM86_FREE_IRQ", + 5: "VM86_GET_IRQ_BITS", + 6: "VM86_GET_AND_RESET_IRQ", + "parsing_mode": "sequential", + }, + }, + # prctl + 172: { + # int option + 0: { + 0x0000002F: "PR_CAP_AMBIENT", + 0x00000017: "PR_CAPBSET_READ", + 0x00000018: "PR_CAPBSET_DROP", + 0x00000024: "PR_SET_CHILD_SUBREAPER", + 0x00000025: "PR_GET_CHILD_SUBREAPER", + 0x00000004: "PR_SET_DUMPABLE", + 0x00000003: "PR_GET_DUMPABLE", + 0x00000014: "PR_SET_ENDIAN", + 0x00000013: "PR_GET_ENDIAN", + 0x0000002D: "PR_SET_FP_MODE", + 0x0000002E: "PR_GET_FP_MODE", + 0x0000000A: "PR_SET_FPEMU", + 0x00000009: "PR_GET_FPEMU", + 0x0000000C: "PR_SET_FPEXC", + 0x0000000B: "PR_GET_FPEXC", + 0x00000039: "PR_SET_IO_FLUSHER", + 0x0000003A: "PR_GET_IO_FLUSHER", + 0x00000008: "PR_SET_KEEPCAPS", + 0x00000007: "PR_GET_KEEPCAPS", + 0x00000021: "PR_MCE_KILL", + 0x00000022: "PR_MCE_KILL_GET", + 0x00000023: "PR_SET_MM", + 0x53564D41: "PR_SET_VMA", + 0x0000002B: "PR_MPX_ENABLE_MANAGEMENT", + 0x0000002C: "PR_MPX_DISABLE_MANAGEMENT", + 0x0000000F: "PR_SET_NAME", + 0x00000010: "PR_GET_NAME", + 0x00000026: "PR_SET_NO_NEW_PRIVS", + 0x00000027: "PR_GET_NO_NEW_PRIVS", + 0x00000036: "PR_PAC_RESET_KEYS", + 0x00000001: "PR_SET_PDEATHSIG", + 0x00000002: "PR_GET_PDEATHSIG", + 0x59616D61: "PR_SET_PTRACER", + 0x00000016: "PR_SET_SECCOMP", + 0x00000015: "PR_GET_SECCOMP", + 0x0000001C: "PR_SET_SECUREBITS", + 0x0000001B: "PR_GET_SECUREBITS", + 0x00000034: "PR_GET_SPECULATION_CTRL", + 0x00000035: "PR_SET_SPECULATION_CTRL", + 0x00000032: "PR_SVE_SET_VL", + 0x00000033: "PR_SVE_GET_VL", + 0x0000003B: "PR_SET_SYSCALL_USER_DISPATCH", + 0x00000037: "PR_SET_TAGGED_ADDR_CTRL", + 0x00000038: "PR_GET_TAGGED_ADDR_CTRL", + 0x0000001F: "PR_TASK_PERF_EVENTS_DISABLE", + 0x00000020: "PR_TASK_PERF_EVENTS_ENABLE", + 0x00000029: "PR_SET_THP_DISABLE", + 0x0000002A: "PR_GET_THP_DISABLE", + 0x00000028: "PR_GET_TID_ADDRESS", + 0x0000001D: "PR_SET_TIMERSLACK", + 0x0000001E: "PR_GET_TIMERSLACK", + 0x0000000E: "PR_SET_TIMING", + 0x0000000D: "PR_GET_TIMING", + 0x0000001A: "PR_SET_TSC", + 0x00000019: "PR_GET_TSC", + 0x00000006: "PR_SET_UNALIGN", + 0x00000005: "PR_GET_UNALIGN", + 0x41555856: "PR_GET_AUXV", + 0x00000041: "PR_SET_MDWE", + 0x00000042: "PR_GET_MDWE", + 0x00000047: "PR_RISCV_SET_ICACHE_FLUSH_CTX", + "parsing_mode": "sequential", + }, + }, + # rt_sigaction + 174: { + # int sig + 0: GnuConstants.SIGNALS, + }, + # rt_sigprocmask + 175: { + # int how + 0: GnuConstants.RT_SIGPROCMASK_HOW, + }, + # getrlimit + 191: { + # unsigned int resource + 0: GnuConstants.RLIMIT_RESOURCES, + }, + # mmap_pgoff + 192: { + # unsigned long prot + 2: GnuConstants.MMAP_PROT, + # unsigned long flags + 3: GnuConstants.MMAP_FLAGS_COMMON, + }, + # madvise + 219: { + # int behavior + 2: GnuConstants.ADVISE_BEHAVIORS, + }, + # fcntl64 + 221: { + # unsigned int cmd + 1: GnuConstants.FCNTL64_CMDS, + # unsigned long arg + 2: { + "parsing_mode": "custom", + "parser": GnuConstants.parse_fcntl_arg, + }, + }, + # setxattr + 226: { + # int flags + 4: GnuConstants.XATTR_FLAGS, + }, + # lsetxattr + 227: { + # int flags + 4: GnuConstants.XATTR_FLAGS, + }, + # fsetxattr + 228: { + # int flags + 4: GnuConstants.XATTR_FLAGS, + }, + # tkill + 238: { + # int sig + 1: GnuConstants.SIGNALS, + }, + # futex + 240: { + # int op + 1: GnuConstants.FUTEX_OPS, + }, + # fadvise64 + 250: { + # int advice + 4: GnuConstants.FADVISE_ADVICE, + }, + # epoll_ctl + 255: { + # int op + 1: GnuConstants.EPOLL_CTL_OPS, + }, + # remap_file_pages + 257: { + # unsigned long flags + 4: GnuConstants.REMAP_FILE_PAGES_FLAGS, + }, + # timer_create + 259: { + # const clockid_t which_clock + 0: GnuConstants.TIMER_CREATE_WHICH_CLOCK, + }, + # timer_settime + 260: { + # int flags + 1: { + 1: "TIMER_ABSTIME", + }, + }, + # clock_settime + 264: { + # clockid_t which_clock + 0: GnuConstants.WHICH_CLOCK, + }, + # clock_gettime + 265: { + # clockid_t which_clock + 0: GnuConstants.WHICH_CLOCK, + }, + # clock_getres + 266: { + # clockid_t which_clock + 0: GnuConstants.WHICH_CLOCK, + }, + # clock_nanosleep + 267: { + # clockid_t which_clock + 0: GnuConstants.WHICH_CLOCK, + # int flags + 1: GnuConstants.CLOCK_NANOSLEEP_FLAGS, + }, + # tgkill + 270: { + # int sig + 2: GnuConstants.SIGNALS, + }, + # fadvise64_64 + 272: { + # int advice + 5: GnuConstants.FADVISE_ADVICE, + }, + # mbind + 274: { + # unsigned long mode + 2: GnuConstants.MBIND_MODES, + # unsigned int flags + 5: GnuConstants.MBIND_FLAGS, + }, + # get_mempolicy + 275: { + # unsigned long flags + 4: GnuConstants.GETMEMPOLICY_FLAGS, + }, + # set_mempolicy + 276: { + # int mode + 0: GnuConstants.SETMEMPOLICY_MODES, + }, + # mq_open + 277: { + # int oflag + 1: GnuConstants.MQ_OPEN_FLAGS, + # umode_t mode + 2: GnuConstants.OPEN_MODES, + }, + # kexec_load + 283: { + # unsigned long flags + 3: GnuConstants.KEXEC_LOAD_FLAGS, + }, + # waitid + 284: { + # int which + 0: GnuConstants.WAITID_WHICH, + # int options + 3: GnuConstants.WAITID_OPTIONS, + }, + # add_key + 286: { + # key_serial_t ringid + 4: { + 0xFFFFFFFF: "KEY_SPEC_THREAD_KEYRING", + 0xFFFFFFFD: "KEY_SPEC_SESSION_KEYRING", + 0xFFFFFFFE: "KEY_SPEC_PROCESS_KEYRING", + 0xFFFFFFFC: "KEY_SPEC_USER_KEYRING", + 0xFFFFFFFB: "KEY_SPEC_USER_SESSION_KEYRING", + 0xFFFFFFFA: "KEY_SPEC_GROUP_KEYRING", + 0xFFFFFF9F: "KEY_SPEC_REQKEY_AUTH_KEY", + 0xFFFFFF9E: "KEY_SPEC_REQUESTOR_KEYRING", + "parsing_mode": "sequential", + }, + }, + # request_key + 287: { + # key_serial_t destringid + 3: { + 0xFFFFFFFF: "KEY_SPEC_THREAD_KEYRING", + 0xFFFFFFFE: "KEY_SPEC_PROCESS_KEYRING", + 0xFFFFFFFD: "KEY_SPEC_SESSION_KEYRING", + 0xFFFFFFFC: "KEY_SPEC_USER_KEYRING", + 0xFFFFFFFB: "KEY_SPEC_USER_SESSION_KEYRING", + 0xFFFFFFFA: "KEY_SPEC_GROUP_KEYRING", + 0xFFFFFF9F: "KEY_SPEC_REQKEY_AUTH_KEY", + 0xFFFFFF9E: "KEY_SPEC_REQUESTOR_KEYRING", + "parsing_mode": "sequential", + }, + }, + # keyctl + 288: { + # int option + 0: GnuConstants.KEYCTL_OPTIONS, + }, + # ioprio_set + 289: { + # int which + 0: GnuConstants.IOPRIO_WHICH, + }, + # ioprio_get + 290: { + # int which + 0: GnuConstants.IOPRIO_WHICH, + }, + # openat + 295: { + # int dfd + 0: GnuConstants.OPENAT_DFD, + # int flags + 2: GnuConstants.OPEN_FLAGS, + # umode_t mode + 3: GnuConstants.OPEN_MODES, + }, + # mkdirat + 296: { + # int dfd + 0: GnuConstants.OPENAT_DFD, + # umode_t mode + 2: GnuConstants.OPEN_MODES, + }, + # mknodat + 297: { + # int dfd + 0: GnuConstants.OPENAT_DFD, + # umode_t mode + 2: GnuConstants.MKNOD_MODES, + }, + # fchownat + 298: { + # int dfd + 0: GnuConstants.OPENAT_DFD, + # int flag + 4: GnuConstants.FCHOWNAT_FLAGS, + }, + # futimesat + 299: { + # unsigned int dfd + 0: GnuConstants.OPENAT_DFD, + }, + # fstatat64 + 300: { + # int dfd + 0: GnuConstants.OPENAT_DFD, + # int flag + 3: GnuConstants.NEWSTATFS_FLAGS, + }, + # unlinkat + 301: { + # int dfd + 0: GnuConstants.OPENAT_DFD, + # int flag + 2: GnuConstants.UNLINKAT_FLAGS, + }, + # renameat + 302: { + # int olddfd + 0: GnuConstants.OPENAT_DFD, + }, + # linkat + 303: { + # int olddfd + 0: GnuConstants.OPENAT_DFD, + # int newdfd + 2: GnuConstants.OPENAT_DFD, + # int flags + 4: GnuConstants.LINKAT_FLAGS, + }, + # symlinkat + 304: { + # int newdfd + 1: GnuConstants.OPENAT_DFD, + }, + # readlinkat + 305: { + # int dfd + 0: GnuConstants.OPENAT_DFD, + }, + # fchmodat + 306: { + # int dfd + 0: GnuConstants.OPENAT_DFD, + # umode_t mode + 2: GnuConstants.OPEN_MODES, + }, + # faccessat + 307: { + # int dfd + 0: GnuConstants.OPENAT_DFD, + # int mode + 2: GnuConstants.OPEN_MODES, + }, + # unshare + 310: { + # unsigned long unshare_flags + 0: GnuConstants.UNSHARE_FLAGS, + }, + # splice + 313: { + # unsigned int flags + 5: GnuConstants.SPLICE_FLAGS, + }, + # sync_file_range + 314: { + # int flags + 5: GnuConstants.SYNC_FILE_RANGE_FLAGS, + }, + # tee + 315: { + # unsigned int flags + 3: GnuConstants.SPLICE_FLAGS, + }, + # vmsplice + 316: { + # unsigned int flags + 3: GnuConstants.VMSPLICE_FLAGS, + }, + # move_pages + 317: { + # int flags + 5: GnuConstants.MOVEPAGES_FLAGS, + }, + # utimensat + 320: { + # int flags + 3: GnuConstants.UTIMENSAT_FLAGS, + }, + # timerfd_create + 322: { + # int clockid + 0: GnuConstants.TIMERFD_CREATE_CLOCKS, + # int flags + 1: GnuConstants.TIMERFD_CREATE_FLAGS, + }, + # fallocate + 324: { + # int mode + 1: GnuConstants.FALLOCATE_MODES, + }, + # timerfd_settime + 325: { + # int flags + 1: GnuConstants.TIMERFD_SETTIME_FLAGS, + }, + # signalfd4 + 327: { + # int flags + 3: GnuConstants.SIGNALFD_FLAGS, + }, + # eventfd2 + 328: { + # int flags + 1: GnuConstants.EVENTFD_FLAGS, + }, + # epoll_create1 + 329: { + # int flags + 0: GnuConstants.EPOLL_CREATE_FLAGS, + }, + # dup3 + 330: { + # int flags + 2: GnuConstants.DUP3_FLAGS, + }, + # pipe2 + 331: { + # int flags + 1: GnuConstants.PIPE2_FLAGS, + }, + # inotify_init1 + 332: { + # int flags + 0: GnuConstants.INOTIFY_INIT_FLAGS, + }, + # rt_tgsigqueueinfo + 335: { + # int sig + 2: GnuConstants.SIGNALS, + }, + # perf_event_open + 336: { + # unsigned long flags + 4: GnuConstants.PERF_EVENT_OPEN_FLAGS, + }, + # recvmmsg + 337: { + # unsigned int flags + 3: GnuConstants.RECVMMSG_FLAGS, + }, + # fanotify_init + 338: { + # unsigned int flags + 0: GnuConstants.FANOTIFY_INIT_FLAGS, + # unsigned int event_f_flags + 1: GnuConstants.FANOTIFY_EVENT_F_FLAGS, + }, + # fanotify_mark + 339: { + # unsigned int flags + 1: GnuConstants.FANOTIFY_MARK_FLAGS, + # u32 mask_lo + 2: GnuConstants.FANOTIFY_MARK_MASK, + # int dfd + 4: GnuConstants.OPENAT_DFD, + }, + # prlimit64 + 340: { + # unsigned int resource + 1: GnuConstants.PRLIMIT_RESOURCES, + }, + # name_to_handle_at + 341: { + # int dfd + 0: GnuConstants.OPENAT_DFD, + # int flag + 4: GnuConstants.NAME_TO_HANDLE_FLAGS, + }, + # open_by_handle_at + 342: { + # int mountdirfd + 0: GnuConstants.OPENAT_DFD, + # int flags + 2: GnuConstants.OPEN_FLAGS, + }, + # clock_adjtime + 343: { + # clockid_t which_clock + 0: GnuConstants.WHICH_CLOCK, + }, + # sendmmsg + 345: { + # unsigned int flags + 3: GnuConstants.SENDTO_FLAGS, + }, + # setns + 346: { + # int flags + 1: GnuConstants.SETNS_FLAGS, + }, + # kcmp + 349: { + # int type + 2: GnuConstants.KCMP_TYPES, + }, + # finit_module + 350: { + # int flags + 2: GnuConstants.FINIT_MODULE_FLAGS, + }, + # renameat2 + 353: { + # int olddfd + 0: GnuConstants.OPENAT_DFD, + # unsigned int flags + 4: GnuConstants.RENAMEAT_FLAGS, + }, + # seccomp + 354: { + # unsigned int op + 0: GnuConstants.SECCOMP_OPS, + # unsigned int flags + 1: GnuConstants.SECCOMP_FLAGS, + }, + # getrandom + 355: { + # unsigned int flags + 2: GnuConstants.GETRANDOM_FLAGS, + }, + # memfd_create + 356: { + # unsigned int flags + 1: GnuConstants.MEMFD_CREATE_FLAGS, + }, + # bpf + 357: { + # int cmd + 0: GnuConstants.BPF_CMDS, + }, + # execveat + 358: { + # int fd + 0: GnuConstants.OPENAT_DFD, + # int flags + 4: GnuConstants.EXECVEAT_FLAGS, + }, + # socket + 359: { + # int family + 0: GnuConstants.SOCKET_FAMILIES, + # int type + 1: GnuConstants.SOCKET_TYPES, + # int protocol + # Note: Socket protocol is not parsed here as it is often 0 + }, + # socketpair + 360: { + # int family + 0: GnuConstants.SOCKET_FAMILIES, + # int type + 1: GnuConstants.SOCKET_TYPES, + # int protocol + # Note: Socket protocol is not parsed here as it is often 0 + }, + # accept4 + 364: { + # int flags + 3: GnuConstants.ACCEPT_FLAGS, + }, + # TODO: Complex parsing, future work + # #getsockopt + # 365:{ + # #int level + # 1: {}, + # #int optname + # 2: {}, + # }, + # setsockopt + # 366:{ + # #int level + # 1: {}, + # #int optname + # 2: {}, + # }, + # sendto + 369: { + # unsigned int flags + 3: GnuConstants.SENDTO_FLAGS, + }, + # sendmsg + 370: { + # unsigned int flags + 2: GnuConstants.SENDMSG_FLAGS, + }, + # recvfrom + 371: { + # unsigned int flags + 3: GnuConstants.RECV_FLAGS, + }, + # recvmsg + 372: { + # unsigned int flags + 2: GnuConstants.RECVMMSG_FLAGS, + }, + # shutdown + 373: { + # int how + 1: GnuConstants.SHUTDOWN_HOW, + }, + # userfaultfd + 374: { + # int flags + 0: GnuConstants.USERFAULTFD_FLAGS, + }, + # membarrier + 375: { + # int cmd + 0: GnuConstants.MEMBARRIER_CMDS, + # unsigned int flags + 1: GnuConstants.MEMBARRIER_FLAGS, + }, + # mlock2 + 376: { + # int flags + 2: GnuConstants.MLOCK_FLAGS, + }, + # preadv2 + 378: { + # rwf_t flags + 5: GnuConstants.PREADV_FLAGS, + }, + # pwritev2 + 379: { + # rwf_t flags + 5: GnuConstants.PREADV_FLAGS, + }, + # statx + 383: { + # int dfd + 0: GnuConstants.OPENAT_DFD, + # unsigned flags + 2: GnuConstants.STATX_FLAGS, + # unsigned int mask + 3: GnuConstants.STATX_MASKS, + }, + # arch_prctl + 384: { + # int option + 0: { + 0x1011: "ARCH_GET_CPUID", + 0x1012: "ARCH_SET_CPUID", + "parsing_mode": "sequential", + }, + }, + # rseq + 386: { + # int flags + 2: GnuConstants.RSEQ_FLAGS, + }, + # semget + 393: { + # key_t key + 0: GnuConstants.SEMGET_KEYS, + # int semflg + 2: GnuConstants.SEMGET_FLAGS, + }, + # semctl + 394: { + # int cmd + 2: GnuConstants.SEMCTL_CMDS, + }, + # shmget + 395: { + # int shmflg + 2: GnuConstants.SHMGET_FLAGS, + }, + # shmctl + 396: { + # int cmd + 1: GnuConstants.SHMCTL_CMDS, + }, + # shmat + 397: { + # int shmflg + 2: GnuConstants.SHMAT_FLAGS, + }, + # msgget + 399: { + # key_t key + 0: GnuConstants.MSGGET_KEYS, + # int msgflg + 1: GnuConstants.MSGGET_FLAGS, + }, + # msgsnd + 400: { + # int msgflg + 3: GnuConstants.MSGSND_FLAGS, + }, + # msgrcv + 401: { + # int msgflg + 4: GnuConstants.MSGRCV_FLAGS, + }, + # msgctl + 402: { + # int cmd + 1: GnuConstants.MSGCTL_CMDS, + }, + # clock_gettime + 403: { + # const clockid_t which_clock + 0: GnuConstants.WHICH_CLOCK, + }, + # clock_settime + 404: { + # const clockid_t which_clock + 0: GnuConstants.WHICH_CLOCK, + }, + # clock_adjtime + 405: { + # const clockid_t which_clock + 0: GnuConstants.WHICH_CLOCK, + }, + # clock_getres + 406: { + # const clockid_t which_clock + 0: GnuConstants.WHICH_CLOCK, + }, + # clock_nanosleep + 407: { + # const clockid_t which_clock + 0: GnuConstants.WHICH_CLOCK, + # int flags + 1: GnuConstants.CLOCK_NANOSLEEP_FLAGS, + }, + # timer_settime + 409: { + # int flags + 1: GnuConstants.TIMER_SETTIME_FLAGS, + }, + # timerfd_settime + 411: { + # int flags + 1: GnuConstants.TIMERFD_SETTIME_FLAGS, + }, + # utimensat + 412: { + # int dfd + 0: GnuConstants.OPENAT_DFD, + # int flags + 3: GnuConstants.UTIMENSAT_FLAGS, + }, + # recvmmsg + 417: { + # unsigned int flags + 3: GnuConstants.RECVMMSG_FLAGS, + }, + # futex + 422: { + # int op + 1: GnuConstants.FUTEX_OPS, + }, + # pidfd_send_signal + 424: { + # int sig + 1: GnuConstants.SIGNALS, + # unsigned int flags + 3: GnuConstants.PIDFD_SEND_SIGNAL_FLAGS, + }, + # io_uring_enter + 426: { + # u32 flags + 3: GnuConstants.IO_URING_ENTER_FLAGS, + }, + # io_uring_register + 427: { + # unsigned int opcode + 1: GnuConstants.IO_URING_REGISTER_OPCODES, + }, + # open_tree + 428: { + # int dfd + 0: GnuConstants.OPENAT_DFD, + # unsigned flags + 2: GnuConstants.OPENTREE_FLAGS, + }, + # move_mount + 429: { + # int from_dfd + 0: GnuConstants.OPENAT_DFD, + # int to_dfd + 2: GnuConstants.OPENAT_DFD, + # unsigned int flags + 4: GnuConstants.MOVE_MOUNT_FLAGS, + }, + # fsopen + 430: { + # unsigned int flags + 1: GnuConstants.FSOPEN_FLAGS, + }, + # fsconfig + 431: { + # unsigned int cmd + 1: GnuConstants.FSCONFIG_CMDS, + }, + # fsmount + 432: { + # unsigned int flags + 1: GnuConstants.FSMOUNT_FLAGS, + # unsigned int attr_flags + 2: GnuConstants.FSMOUNT_ATTR_FLAGS, + }, + # fspick + 433: { + # int dfd + 0: GnuConstants.OPENAT_DFD, + # unsigned int flags + 2: GnuConstants.FSPICK_FLAGS, + }, + # pidfd_open + 434: { + # unsigned int flags + 1: GnuConstants.PIDFD_OPEN_FLAGS, + }, + # close_range + 436: { + # unsigned int flags + 2: GnuConstants.CLOSE_RANGE_FLAGS, + }, + # openat2 + 437: { + # int dfd + 0: GnuConstants.OPENAT_DFD, + }, + # faccessat2 + 439: { + # int dfd + 0: GnuConstants.OPENAT_DFD, + # int mode + 2: GnuConstants.OPEN_MODES, + # int flags + 3: GnuConstants.FACCESSAT_FLAGS, + }, + # process_madvise + 440: { + # int behavior + 3: GnuConstants.ADVISE_BEHAVIORS, + }, + # mount_setattr + 442: { + # int dfd + 0: GnuConstants.OPENAT_DFD, + # unsigned int flags + 2: GnuConstants.MOUNT_SETATTR_FLAGS, + }, + # quotactl_fd + 443: { + # unsigned int cmd + 1: GnuConstants.QUOTACTL_CMDS, + }, + # landlock_create_ruleset + 444: { + # const __u32 flags + 2: GnuConstants.LANDLOCK_CREATE_RULESET_FLAGS, + }, + # landlock_add_rule + 445: { + # const enum landlock_rule_type rule_type + 1: GnuConstants.LANDLOCK_ADD_RULE_TYPES, + }, + # memfd_secret + 447: { + # unsigned int flags + 0: GnuConstants.MEMFD_SECRET_FLAGS, + }, + # futex_waitv + 449: { + # clockid_t clockid + 4: GnuConstants.WHICH_CLOCK, + }, + # cachestat + 451: { + # unsigned int fd + 0: GnuConstants.OPENAT_DFD, + }, + # fchmodat2 + 452: { + # int dfd + 0: GnuConstants.OPENAT_DFD, + # umode_t mode + 2: GnuConstants.OPEN_MODES, + # unsigned int flags + 3: GnuConstants.FCHMODAT_FLAGS, + }, + # futex_wake + 454: { + # unsigned int flags + 3: GnuConstants.FUTEX2_FLAGS, + }, + # futex_wait + 455: { + # clockid_t clockid + 5: GnuConstants.WHICH_CLOCK, + }, + # listmount + 458: { + # unsigned int flags + 3: GnuConstants.LISTMOUNT_FLAGS, + }, + # lsm_get_self_attr + 459: { + # u32 flags + 3: GnuConstants.LSM_GET_SELF_ATTR_FLAGS, + }, + # setxattrat + 463: { + # int dfd + 0: GnuConstants.OPENAT_DFD, + # unsigned int at_flags + 2: GnuConstants.XATTRAT_FLAGS, + }, + # getxattrat + 464: { + # int dfd + 0: GnuConstants.OPENAT_DFD, + # unsigned int at_flags + 2: GnuConstants.XATTRAT_FLAGS, + }, + # listxattrat + 465: { + # int dfd + 0: GnuConstants.OPENAT_DFD, + # unsigned int at_flags + 2: GnuConstants.XATTRAT_FLAGS, + }, + # removexattrat + 466: { + # int dfd + 0: GnuConstants.OPENAT_DFD, + # unsigned int at_flags + 2: GnuConstants.XATTRAT_FLAGS, + }, +} diff --git a/libdebug/architectures/syscall_arg_parser.py b/libdebug/architectures/syscall_arg_parser.py new file mode 100644 index 000000000..e18e2f4d6 --- /dev/null +++ b/libdebug/architectures/syscall_arg_parser.py @@ -0,0 +1,138 @@ +# +# This file is part of libdebug Python library (https://github.com/libdebug/libdebug). +# Copyright (c) 2025 Francesco Panebianco. All rights reserved. +# Licensed under the MIT license. See LICENSE file in the project root for details. +# + +from libdebug.architectures.aarch64.aarch64_syscall_arg_parser import ( + AARCH64_SYSCALL_PARSER_MAP, +) +from libdebug.architectures.amd64.amd64_syscall_arg_parser import ( + AMD64_SYSCALL_PARSER_MAP, +) +from libdebug.architectures.i386.i386_syscall_arg_parser import ( + I386_SYSCALL_PARSER_MAP, +) +from libdebug.utils.parsing_utils import or_parse, sequential_parse + + +def syscall_arg_parser( + architecture: str, + syscall_number: int, + syscall_arg_index: int, + syscall_arg_value: int, +) -> str: + """Parse the syscall arguments based on the syscall number and argument name. + + Args: + architecture (str): The architecture of the binary (e.g., "amd64", "i386", "aarch64"). + syscall_number (int): The syscall number. + syscall_arg_index (int): The syscall argument index." + syscall_arg_value (int): The syscall argument value." + + Returns: + str: The parsed syscall argument value. + """ + if architecture == "amd64": + syscall_parser_map = AMD64_SYSCALL_PARSER_MAP + elif architecture == "i386": + syscall_parser_map = I386_SYSCALL_PARSER_MAP + elif architecture == "aarch64": + syscall_parser_map = AARCH64_SYSCALL_PARSER_MAP + else: + raise ValueError(f"Unsupported architecture: {architecture}") + + default_val = f"{syscall_arg_value:#x}" + + # Get the syscall parser map for the given syscall number + specific_syscall_map = syscall_parser_map.get(syscall_number) + + # If the syscall has not defined constants, return the default value + if specific_syscall_map is None: + return default_val + + specific_arg_map = specific_syscall_map.get(syscall_arg_index) + + # If the syscall argument has not defined constants, return the default value + if specific_arg_map is None: + return default_val + + # Retrieve the parsing mode (default is OR) + parsing_mode = specific_arg_map.get("parsing_mode", "or") + + if parsing_mode == "or": + out_mnemonic = or_parse(specific_arg_map, syscall_arg_value) + elif parsing_mode == "sequential": + out_mnemonic = sequential_parse(specific_arg_map, syscall_arg_value) + elif parsing_mode == "mixed": + out_mnemonic = "" + + # Handle "or_flags" if present + or_flags = specific_arg_map.get("or_flags", {}) + if or_flags: + masked_bits = 0x000000000000000000 + or_mnemonic = "" + + for mnemonic_mask, mnemonic in or_flags.items(): + if mnemonic_mask == 0 and syscall_arg_value != 0: + # If the mask is 0 and the syscall argument value is not 0, skip it + continue + + if mnemonic_mask & syscall_arg_value == mnemonic_mask: + if len(or_mnemonic) == 0: + or_mnemonic = mnemonic + else: + or_mnemonic += f" | {mnemonic}" + + masked_bits |= mnemonic_mask + + # If not all bits are masked, add the remaining bits to the mnemonic in OR + if ~masked_bits & syscall_arg_value != 0: + or_mnemonic += f" | {syscall_arg_value & ~masked_bits:#08x}" + + # Combine sequential and OR mnemonics if both exist + if len(out_mnemonic) > 0 and len(or_mnemonic) > 0: + out_mnemonic += f" | {or_mnemonic}" + elif len(or_mnemonic) > 0: + out_mnemonic = or_mnemonic + + # Handle "sequential_flags" if present + sequential_flags = specific_arg_map.get("sequential_flags", {}) + + masked_seq_value = syscall_arg_value & ~(masked_bits) + + candidate = sequential_flags.get(masked_seq_value) + if candidate is None: + # If we don't find a base sequential let's not bother parsing ORed flags + return default_val + + if out_mnemonic == "": + out_mnemonic = candidate + f" ({syscall_arg_value:#x})" + else: + out_mnemonic += f" | {candidate} ({syscall_arg_value:#x})" + elif parsing_mode == "custom": + parser_func = specific_arg_map.get("parser") + + if parser_func is None: + raise ValueError( + f"Custom parser function not defined for syscall number {syscall_number}", + ) + + # Call the custom parser function + out_mnemonic = parser_func(syscall_arg_value) + + if out_mnemonic is None or len(out_mnemonic) == 0: + # If the custom parser returns None, use the default value + out_mnemonic = default_val + else: + out_mnemonic += f" ({syscall_arg_value:#x})" + else: + raise ValueError( + f"Unsupported parsing mode '{parsing_mode}' for syscall number {syscall_number}", + ) + + if len(out_mnemonic) == 0: + return default_val + + # Before returning, escape the special characters + return out_mnemonic diff --git a/libdebug/builtin/pretty_print_syscall_handler.py b/libdebug/builtin/pretty_print_syscall_handler.py index dfd23d22f..706d5c040 100644 --- a/libdebug/builtin/pretty_print_syscall_handler.py +++ b/libdebug/builtin/pretty_print_syscall_handler.py @@ -1,6 +1,6 @@ # # This file is part of libdebug Python library (https://github.com/libdebug/libdebug). -# Copyright (c) 2024 Roberto Alessandro Bertolini, Gabriele Digregorio. All rights reserved. +# Copyright (c) 2024-2025 Roberto Alessandro Bertolini, Gabriele Digregorio, Francesco Panebianco. All rights reserved. # Licensed under the MIT license. See LICENSE file in the project root for details. # @@ -8,7 +8,11 @@ from typing import TYPE_CHECKING +from libdebug.architectures.syscall_arg_parser import syscall_arg_parser from libdebug.utils.ansi_escape_codes import ANSIColors +from libdebug.utils.gnu_constants import GnuConstants +from libdebug.utils.libcontext import libcontext +from libdebug.utils.platform_utils import get_platform_gp_register_size from libdebug.utils.syscall_utils import ( resolve_syscall_arguments, resolve_syscall_name, @@ -17,6 +21,124 @@ if TYPE_CHECKING: from libdebug.state.thread_context import ThreadContext +MAX_STR_SHOW_LEN = 32 + +def negate_value(value: int, word_size: int) -> int: + """Negate a value. + + Args: + value (int): the value. + word_size (int): the word size. + + Returns: + int: the negated value. + """ + return (1 << word_size * 8) - value + + +def numeric_or_mnemonic( + value: int, + mnemonic_dict: dict, + equality: bool, + negate_search: bool, + word_size: int | None = None, +) -> str: + """Return the mnemonic of a value if it is present in the mnemonic dictionary. + + Args: + value (int): the value. + mnemonic_dict (dict): the mnemonic dictionary. + equality (bool): if True, check for equality of the value, otherwise mask values in OR. + negate_search (bool): if True, negate the value to query the mnemonic. Valid if equality is True. + word_size (int | None): the word size. Defaults to None. + + Returns: + str: the mnemonic. + """ + numeric_str = f"{value:#x}" + + if not libcontext.parse_pprint_constants: + return numeric_str + + # Parse exact match + if equality: + mnemonic_val = negate_value(value, word_size) if negate_search else value + mnemonic = mnemonic_dict.get(mnemonic_val) + mnemonic = mnemonic["short_name"] if mnemonic is not None else numeric_str + # Parse bitwise OR + else: + mnemonics_list = [] + for key, mnemonic in mnemonic_dict.items(): + if key & value: + mnemonics_list.append(mnemonic["short_name"]) + mnemonic = " | ".join(mnemonics_list) if mnemonics_list else numeric_str + + return mnemonic + + +def parse_syscall_arg(t: ThreadContext, sycall_num: int, arg_num: int, arg_val: int, is_string: bool = False) -> str: + """Parse a syscall argument. + + Args: + t (ThreadContext): the thread context. + sycall_num (int): the syscall number. + arg_num (int): the argument number. + arg_val (int): the argument value. + is_string (bool): if True, the argument is a string. Defaults to False. + """ + if not libcontext.parse_pprint_constants: + return f"{arg_val:#x}" + elif is_string: + string_content = "" + + curr_char = "" + cursor = arg_val + + BASE_ESCAPES = { + 0x00: "\0", + 0x07: r"\a", + 0x08: r"\b", + 0x09: r"\t", + 0x0A: r"\n", + 0x0B: r"\v", + 0x0C: r"\f", + 0x0D: r"\r", + } + + while curr_char != "\0": + string_content += curr_char + curr_char_ord = int.from_bytes(t.memory[cursor, 1, "absolute"]) + + def escape_char(ch_ord: int) -> str: + # Fast lookup for the common control chars + if ch_ord in BASE_ESCAPES: + return BASE_ESCAPES[ch_ord] + + # Other non-printables should be \x escaped + if ch_ord < 0x20 or ch_ord > 0x7E: + return fr"\x{ch_ord:02x}" + + # Printable ASCII: keep as-is + return chr(ch_ord) + + curr_char = escape_char(curr_char_ord) + cursor += 1 + + if cursor - arg_val > MAX_STR_SHOW_LEN: + string_content += f"...[truncated] ({MAX_STR_SHOW_LEN} bytes)" + break + + return ( + f'"{string_content}" ({arg_val:#x})' + ) + else: + return syscall_arg_parser( + t._internal_debugger.arch, + sycall_num, + arg_num, + arg_val, + ) + def pprint_on_enter(t: ThreadContext, syscall_number: int, **kwargs: int) -> None: """Function that will be called when a syscall is entered in pretty print mode. @@ -38,22 +160,38 @@ def pprint_on_enter(t: ThreadContext, syscall_number: int, **kwargs: int) -> Non t.syscall_arg5, ] + values_str = [] + + # Parse the arguments + for arg_index, value, name in zip(range(len(values)), values, syscall_args, strict=False): + is_string = "char" in name + + values_str.append(parse_syscall_arg(t, syscall_number, arg_index, value, is_string)) + # Print the thread id header = f"{ANSIColors.BOLD}{t.tid}{ANSIColors.RESET} " if "old_args" in kwargs: old_args = kwargs["old_args"] + old_args_str = [] + + # Parse the old arguments + for arg_index, value, name in zip(range(len(old_args)), old_args, syscall_args, strict=False): + is_string = "char" in name + + old_args_str[arg_index] = parse_syscall_arg(t, syscall_number, arg_index, value, is_string) + entries = [ - f"{arg} = {ANSIColors.BRIGHT_YELLOW}0x{value:x}{ANSIColors.DEFAULT_COLOR}" + f"{arg} = {ANSIColors.BRIGHT_YELLOW}{value}{ANSIColors.DEFAULT_COLOR}" if old_value == value - else f"{arg} = {ANSIColors.STRIKE}{ANSIColors.BRIGHT_YELLOW}0x{old_value:x}{ANSIColors.RESET} {ANSIColors.BRIGHT_YELLOW}0x{value:x}{ANSIColors.DEFAULT_COLOR}" - for arg, value, old_value in zip(syscall_args, values, old_args, strict=False) + else f"{arg} = {ANSIColors.STRIKE}{ANSIColors.BRIGHT_YELLOW}{old_value}{ANSIColors.RESET} {ANSIColors.BRIGHT_YELLOW}0x{value:x}{ANSIColors.DEFAULT_COLOR}" + for arg, value, old_value in zip(syscall_args, values_str, old_args_str, strict=False) if arg is not None ] else: entries = [ - f"{arg} = {ANSIColors.BRIGHT_YELLOW}0x{value:x}{ANSIColors.DEFAULT_COLOR}" - for arg, value in zip(syscall_args, values, strict=False) + f"{arg} = {ANSIColors.BRIGHT_YELLOW}{value}{ANSIColors.DEFAULT_COLOR}" + for arg, value in zip(syscall_args, values_str, strict=False) if arg is not None ] @@ -81,15 +219,34 @@ def pprint_on_enter(t: ThreadContext, syscall_number: int, **kwargs: int) -> Non ) -def pprint_on_exit(syscall_return: int | tuple[int, int]) -> None: +def pprint_on_exit(t: ThreadContext, syscall_return: int | tuple[int, int]) -> None: """Function that will be called when a syscall is exited in pretty print mode. Args: + t (ThreadContext): the thread context. syscall_return (int | list[int]): the syscall return value. """ + word_size = get_platform_gp_register_size(t.debugger.arch) + if isinstance(syscall_return, tuple): + real_retval = numeric_or_mnemonic( + syscall_return[0], + GnuConstants.ERRNOS, + equality=True, + negate_search=True, + word_size=word_size, + ) + changed_retval = numeric_or_mnemonic( + syscall_return[1], + GnuConstants.ERRNOS, + equality=True, + negate_search=True, + word_size=word_size, + ) + print( - f"{ANSIColors.YELLOW}{ANSIColors.STRIKE}0x{syscall_return[0]:x}{ANSIColors.RESET} {ANSIColors.YELLOW}0x{syscall_return[1]:x}{ANSIColors.RESET}", + f"{ANSIColors.YELLOW}{ANSIColors.STRIKE}{real_retval}{ANSIColors.RESET} {ANSIColors.YELLOW}{changed_retval}{ANSIColors.RESET}", ) else: - print(f"{ANSIColors.YELLOW}0x{syscall_return:x}{ANSIColors.RESET}") + retval = numeric_or_mnemonic(syscall_return, GnuConstants.ERRNOS, equality=True, negate_search=True, word_size=word_size) + print(f"{ANSIColors.YELLOW}{retval}{ANSIColors.RESET}") diff --git a/libdebug/data/syscall_handler.py b/libdebug/data/syscall_handler.py index 01c07b941..eb786f360 100644 --- a/libdebug/data/syscall_handler.py +++ b/libdebug/data/syscall_handler.py @@ -35,7 +35,7 @@ class SyscallHandler: on_enter_user: Callable[[ThreadContext, SyscallHandler], None] on_exit_user: Callable[[ThreadContext, SyscallHandler], None] on_enter_pprint: Callable[[ThreadContext, int, Any], None] = field(repr=False) - on_exit_pprint: Callable[[int | tuple[int, int]], None] = field(repr=False) + on_exit_pprint: Callable[[ThreadContext, int | tuple[int, int]], None] = field(repr=False) recursive: bool = False hit_count: int = 0 diff --git a/libdebug/ptrace/ptrace_status_handler.py b/libdebug/ptrace/ptrace_status_handler.py index a7c239fdf..20c7edb02 100644 --- a/libdebug/ptrace/ptrace_status_handler.py +++ b/libdebug/ptrace/ptrace_status_handler.py @@ -227,7 +227,7 @@ def _manage_syscall_on_enter( handler._has_entered = True self.internal_debugger.resume_context.resume = False - def _handle_syscall(self: PtraceStatusHandler, thread_id: int) -> bool: + def handle_syscall(self: PtraceStatusHandler, thread_id: int) -> bool: """Handle a syscall trap.""" thread = self.internal_debugger.get_thread_by_id(thread_id) if not hasattr(thread, "syscall_number"): @@ -289,17 +289,18 @@ def _handle_syscall(self: PtraceStatusHandler, thread_id: int) -> bool: return_value_after_callback = thread.syscall_return if return_value_after_callback != return_value_before_callback: handler.on_exit_pprint( + thread, (return_value_before_callback, return_value_after_callback), ) else: - handler.on_exit_pprint(return_value_after_callback) + handler.on_exit_pprint(thread, return_value_after_callback) elif handler.on_exit_pprint: # Pretty print the return value - handler.on_exit_pprint(thread.syscall_return) + handler.on_exit_pprint(thread, thread.syscall_return) handler._has_entered = False handler._skip_exit = False - if not handler.on_enter_user and not handler.on_exit_user and handler._enabled: + if not handler.on_enter_user and not handler.on_exit_user and handler.enabled: # If the syscall has no callback, we need to stop the process despite the other signals self.internal_debugger.resume_context.event_type[thread_id] = EventType.SYSCALL self.internal_debugger.resume_context.resume = False @@ -397,7 +398,7 @@ def _internal_signal_handler( if signum == SYSCALL_SIGTRAP: # We hit a syscall liblog.debugger("Child thread %d stopped on syscall", pid) - self._handle_syscall(pid) + self.handle_syscall(pid) self.forward_signal = False elif signum == signal.SIGSTOP and self.internal_debugger.resume_context.force_interrupt: # The user has requested an interrupt, we need to stop the process despite the ohter signals diff --git a/libdebug/state/thread_context.py b/libdebug/state/thread_context.py index f865fb3c4..464b2d61d 100644 --- a/libdebug/state/thread_context.py +++ b/libdebug/state/thread_context.py @@ -1,11 +1,11 @@ # # This file is part of libdebug Python library (https://github.com/libdebug/libdebug). -# Copyright (c) 2024 Roberto Alessandro Bertolini, Gabriele Digregorio, Francesco Panebianco. All rights reserved. +# Copyright (c) 2024-2025 Roberto Alessandro Bertolini, Gabriele Digregorio, Francesco Panebianco. All rights reserved. # Licensed under the MIT license. See LICENSE file in the project root for details. # from __future__ import annotations -from abc import ABC +from abc import ABC, abstractmethod from typing import TYPE_CHECKING from libdebug.architectures.stack_unwinding_provider import stack_unwinding_provider @@ -49,7 +49,7 @@ class ThreadContext(ABC): """The thread's syscall argument 5.""" syscall_number: int - """The thread's syscall number.""" + """The thread's syscall number when the kernel has entered a syscall.""" syscall_return: int """The thread's syscall return value.""" @@ -398,3 +398,8 @@ def create_snapshot(self: ThreadContext, level: str = "base", name: str | None = def notify_snapshot_taken(self: ThreadContext) -> None: """Notify the thread that a snapshot has been taken.""" self._snapshot_count += 1 + + @property + def num_syscall_args(self: ThreadContext) -> int: + """The number of syscall arguments.""" + return 6 diff --git a/libdebug/utils/gnu_constants.py b/libdebug/utils/gnu_constants.py new file mode 100644 index 000000000..9162387e9 --- /dev/null +++ b/libdebug/utils/gnu_constants.py @@ -0,0 +1,1862 @@ +# +# This file is part of libdebug Python library (https://github.com/libdebug/libdebug). +# Copyright (c) 2025 Francesco Panebianco. All rights reserved. +# Licensed under the MIT license. See LICENSE file in the project root for details. +# + +# ruff: noqa: RUF012 + +# !!! Parsing Values are up to date with Linux Kernel 6.15 !!! + +from __future__ import annotations + +from dataclasses import dataclass + +from libdebug.utils.parsing_utils import or_parse, sequential_parse + + +@dataclass(frozen=True) +class GnuConstants: + """ + A class that provides constants used in GNU/Linux syscall parsing. + + This class contains mappings of numeric values to human-readable names + for various Linux kernel constants, including error codes, syscall flags, + file modes, socket options, and other system-specific values. + """ + + # Mapping of error codes to their short names and descriptions + # From /usr/include/asm-generic/errno-base.h + ERRNOS = { + 1: {"short_name": "EPERM", "description": "Operation not permitted"}, + 2: {"short_name": "ENOENT", "description": "No such file or directory"}, + 3: {"short_name": "ESRCH", "description": "No such process"}, + 4: {"short_name": "EINTR", "description": "Interrupted system call"}, + 5: {"short_name": "EIO", "description": "I/O error"}, + 6: {"short_name": "ENXIO", "description": "No such device or address"}, + 7: {"short_name": "E2BIG", "description": "Argument list too long"}, + 8: {"short_name": "ENOEXEC", "description": "Exec format error"}, + 9: {"short_name": "EBADF", "description": "Bad file number"}, + 10: {"short_name": "ECHILD", "description": "No child processes"}, + 11: {"short_name": "EAGAIN", "description": "Try again"}, + 12: {"short_name": "ENOMEM", "description": "Out of memory"}, + 13: {"short_name": "EACCES", "description": "Permission denied"}, + 14: {"short_name": "EFAULT", "description": "Bad address"}, + 15: {"short_name": "ENOTBLK", "description": "Block device required"}, + 16: {"short_name": "EBUSY", "description": "Device or resource busy"}, + 17: {"short_name": "EEXIST", "description": "File exists"}, + 18: {"short_name": "EXDEV", "description": "Cross-device link"}, + 19: {"short_name": "ENODEV", "description": "No such device"}, + 20: {"short_name": "ENOTDIR", "description": "Not a directory"}, + 21: {"short_name": "EISDIR", "description": "Is a directory"}, + 22: {"short_name": "EINVAL", "description": "Invalid argument"}, + 23: {"short_name": "ENFILE", "description": "File table overflow"}, + 24: {"short_name": "EMFILE", "description": "Too many open files"}, + 25: {"short_name": "ENOTTY", "description": "Not a typewriter"}, + 26: {"short_name": "ETXTBSY", "description": "Text file busy"}, + 27: {"short_name": "EFBIG", "description": "File too large"}, + 28: {"short_name": "ENOSPC", "description": "No space left on device"}, + 29: {"short_name": "ESPIPE", "description": "Illegal seek"}, + 30: {"short_name": "EROFS", "description": "Read-only file system"}, + 31: {"short_name": "EMLINK", "description": "Too many links"}, + 32: {"short_name": "EPIPE", "description": "Broken pipe"}, + 33: {"short_name": "EDOM", "description": "Math argument out of domain of func"}, + 34: {"short_name": "ERANGE", "description": "Math result not representable"}, + 35: {"short_name": "EDEADLK", "description": "Resource deadlock would occur"}, + 36: {"short_name": "ENAMETOOLONG", "description": "File name too long"}, + 37: {"short_name": "ENOLCK", "description": "No record locks available"}, + 38: {"short_name": "ENOSYS", "description": "Invalid system call number"}, + 39: {"short_name": "ENOTEMPTY", "description": "Directory not empty"}, + 40: {"short_name": "ELOOP", "description": "Too many symbolic links encountered"}, + 42: {"short_name": "ENOMSG", "description": "No message of desired type"}, + 43: {"short_name": "EIDRM", "description": "Identifier removed"}, + 44: {"short_name": "ECHRNG", "description": "Channel number out of range"}, + 45: {"short_name": "EL2NSYNC", "description": "Level 2 not synchronized"}, + 46: {"short_name": "EL3HLT", "description": "Level 3 halted"}, + 47: {"short_name": "EL3RST", "description": "Level 3 reset"}, + 48: {"short_name": "ELNRNG", "description": "Link number out of range"}, + 49: {"short_name": "EUNATCH", "description": "Protocol driver not attached"}, + 50: {"short_name": "ENOCSI", "description": "No CSI structure available"}, + 51: {"short_name": "EL2HLT", "description": "Level 2 halted"}, + 52: {"short_name": "EBADE", "description": "Invalid exchange"}, + 53: {"short_name": "EBADR", "description": "Invalid request descriptor"}, + 54: {"short_name": "EXFULL", "description": "Exchange full"}, + 55: {"short_name": "ENOANO", "description": "No anode"}, + 56: {"short_name": "EBADRQC", "description": "Invalid request code"}, + 57: {"short_name": "EBADSLT", "description": "Invalid slot"}, + 59: {"short_name": "EBFONT", "description": "Bad font file format"}, + 60: {"short_name": "ENOSTR", "description": "Device not a stream"}, + 61: {"short_name": "ENODATA", "description": "No data available"}, + 62: {"short_name": "ETIME", "description": "Timer expired"}, + 63: {"short_name": "ENOSR", "description": "Out of streams resources"}, + 64: {"short_name": "ENONET", "description": "Machine is not on the network"}, + 65: {"short_name": "ENOPKG", "description": "Package not installed"}, + 66: {"short_name": "EREMOTE", "description": "Object is remote"}, + 67: {"short_name": "ENOLINK", "description": "Link has been severed"}, + 68: {"short_name": "EADV", "description": "Advertise error"}, + 69: {"short_name": "ESRMNT", "description": "Srmount error"}, + 70: {"short_name": "ECOMM", "description": "Communication error on send"}, + 71: {"short_name": "EPROTO", "description": "Protocol error"}, + 72: {"short_name": "EMULTIHOP", "description": "Multihop attempted"}, + 73: {"short_name": "EDOTDOT", "description": "RFS specific error"}, + 74: {"short_name": "EBADMSG", "description": "Not a data message"}, + 75: {"short_name": "EOVERFLOW", "description": "Value too large for defined data type"}, + } + + # Common flags flags across syscalls + OPEN_FLAGS = { + "or_flags": { + 0o00002000: "O_APPEND", + 0o00020000: "O_ASYNC", + 0o02000000: "O_CLOEXEC", + 0o00000100: "O_CREAT", + 0o00040000: "O_DIRECT", + 0o00200000: "O_DIRECTORY", + 0o00010000: "O_DSYNC", + 0o00000200: "O_EXCL", + 0o00100000: "O_LARGEFILE", + 0o00000400: "O_NOCTTY", + 0o00004000: "O_NOFOLLOW / O_NONBLOCK", + 0o10000000: "O_PATH", + 0o04000000: "O_SYNC", + 0o01000000: "O_TMPFILE / O_NOATIME", + 0o00001000: "O_TRUNC", + }, + "sequential_flags": { + 0o00000000: "O_RDONLY", + 0o00000001: "O_WRONLY", + 0o00000002: "O_RDWR", + }, + "parsing_mode": "mixed", + } + + OPEN_MODES = { + 0o00700: "S_IRWXU", + 0o00400: "S_IRUSR", + 0o00200: "S_IWUSR", + 0o00100: "S_IXUSR", + 0o00070: "S_IRWXG", + 0o00040: "S_IRGRP", + 0o00020: "S_IWGRP", + 0o00010: "S_IXGRP", + 0o00007: "S_IRWXO", + 0o00004: "S_IROTH", + 0o00002: "S_IWOTH", + 0o00001: "S_IXOTH", + 0o0004000: "S_ISUID", + 0o0002000: "S_ISGID", + 0o0001000: "S_ISVTX", + } + + SIGNALS = { + 1: "SIGHUP", + 2: "SIGINT", + 3: "SIGQUIT", + 4: "SIGILL", + 5: "SIGTRAP", + 6: "SIGABRT / SIGIOT", + 7: "SIGBUS", + 8: "SIGFPE", + 9: "SIGKILL", + 10: "SIGUSR1", + 11: "SIGSEGV", + 12: "SIGUSR2", + 13: "SIGPIPE", + 14: "SIGALRM", + 15: "SIGTERM", + 16: "SIGSTKFLT", + 17: "SIGCHLD", + 18: "SIGCONT", + 19: "SIGSTOP", + 20: "SIGTSTP", + 21: "SIGTTIN", + 22: "SIGTTOU", + 23: "SIGURG", + 24: "SIGXCPU", + 25: "SIGXFSZ", + 26: "SIGVTALRM", + 27: "SIGPROF", + 28: "SIGWINCH", + 29: "SIGIO / SIGPOLL", + 30: "SIGPWR", + 31: "SIGSYS", + "parsing_mode": "sequential", + } + + WHICH_CLOCK = { + 0: "CLOCK_REALTIME", + 1: "CLOCK_MONOTONIC", + 2: "CLOCK_PROCESS_CPUTIME_ID", + 3: "CLOCK_THREAD_CPUTIME_ID", + 4: "CLOCK_MONOTONIC_RAW", + 5: "CLOCK_REALTIME_COARSE", + 6: "CLOCK_MONOTONIC_COARSE", + 7: "CLOCK_BOOTTIME", + 8: "CLOCK_REALTIME_ALARM", + 9: "CLOCK_BOOTTIME_ALARM", + 10: "CLOCK_SGI_CYCLE", + 11: "CLOCK_TAI", + "parsing_mode": "sequential", + } + + OPENAT_DFD = { + 0xFFFFFF9C: "AT_FDCWD", + } + + SPLICE_FLAGS = { + 0x01: "SPLICE_F_MOVE", + 0x02: "SPLICE_F_NONBLOCK", + 0x04: "SPLICE_F_MORE", + } + + VMSPLICE_FLAGS = { + 0x02: "SPLICE_F_NONBLOCK", + 0x04: "SPLICE_F_MORE", + 0x08: "SPLICE_F_GIFT", + } + + ADVISE_BEHAVIORS = { + 0: "MADV_NORMAL", + 1: "MADV_RANDOM", + 2: "MADV_SEQUENTIAL", + 3: "MADV_WILLNEED", + 4: "MADV_DONTNEED", + 8: "MADV_FREE", + 9: "MADV_REMOVE", + 10: "MADV_DONTFORK", + 11: "MADV_DOFORK", + 12: "MADV_MERGEABLE", + 13: "MADV_UNMERGEABLE", + 14: "MADV_HUGEPAGE", + 15: "MADV_NOHUGEPAGE", + 16: "MADV_DONTDUMP", + 17: "MADV_DODUMP", + 18: "MADV_WIPEONFORK", + 19: "MADV_KEEPONFORK", + 20: "MADV_COLD", + 21: "MADV_PAGEOUT", + 22: "MADV_POPULATE_READ", + 23: "MADV_POPULATE_WRITE", + 24: "MADV_DONTNEED_LOCKED", + 25: "MADV_COLLAPSE", + 100: "MADV_HWPOISON", + 101: "MADV_SOFT_OFFLINE", + 102: "MADV_GUARD_INSTALL", + 103: "MADV_GUARD_REMOVE", + "parsing_mode": "sequential", + } + + FCNTL_CMDS = { + 0: "F_DUPFD", + 1: "F_GETFD", + 2: "F_SETFD", + 3: "F_GETFL", + 4: "F_SETFL", + 5: "F_GETLK", + 6: "F_SETLK", + 7: "F_SETLKW", + 8: "F_SETOWN", + 9: "F_GETOWN", + 10: "F_SETSIG", + 11: "F_GETSIG", + 15: "F_SETOWN_EX", + 16: "F_GETOWN_EX", + 17: "F_GETOWNER_UIDS", + 36: "F_OFD_GETLK", + 37: "F_OFD_SETLK", + 38: "F_OFD_SETLKW", + 1024: "F_SETLEASE", + 1025: "F_GETLEASE", + 1026: "F_NOTIFY", + 1027: "F_DUPFD_QUERY", + 1028: "F_CREATED_QUERY", + 1029: "F_CANCELLK", + 1030: "F_DUPFD_CLOEXEC", + 1031: "F_SETPIPE_SZ", + 1032: "F_GETPIPE_SZ", + 1033: "F_ADD_SEALS", + 1034: "F_GET_SEALS", + 1035: "F_GET_RW_HINT", + 1036: "F_SET_RW_HINT", + 1037: "F_GET_FILE_RW_HINT", + 1038: "F_SET_FILE_RW_HINT", + "parsing_mode": "sequential", + } + + FCNTL64_CMDS = FCNTL_CMDS | { + 12: "F_GETLK64", + 13: "F_SETLK64", + 14: "F_SETLKW64", + } + + LSEEK_WHENCE = { + 0: "SEEK_SET", + 1: "SEEK_CUR", + 2: "SEEK_END", + 3: "SEEK_DATA", + 4: "SEEK_HOLE", + } + + MMAP_PROT = { + 0x0: "PROT_NONE", + 0x1: "PROT_READ", + 0x2: "PROT_WRITE", + 0x4: "PROT_EXEC", + } + + MMAP_FLAGS_COMMON = { + 0x00000000: "MAP_FILE", + 0x00000001: "MAP_SHARED", + 0x00000003: "MAP_SHARED_VALIDATE", + 0x00000002: "MAP_PRIVATE", + # 0x00000040: "MAP_32BIT" 32-bit only + 0x00000020: "MAP_ANONYMOUS", + 0x00000800: "MAP_DENYWRITE", + 0x00001000: "MAP_EXECUTABLE", + 0x00000010: "MAP_FIXED", + 0x00100000: "MAP_FIXED_NOREPLACE", + 0x00000100: "MAP_GROWSDOWN", + 0x00040000: "MAP_HUGETLB", + 0x54000000: "MAP_HUGE_2MB", + 0x78000000: "MAP_HUGE_1GB", + 0x00002000: "MAP_LOCKED", + 0x00010000: "MAP_NONBLOCK", + 0x00004000: "MAP_NORESERVE", + 0x00008000: "MAP_POPULATE", + 0x00020000: "MAP_STACK", + 0x00080000: "MAP_SYNC", + 0x04000000: "MAP_UNINITIALIZED", + } + + MPROTECT_PROT = { + 0x0: "PROT_NONE", + 0x1: "PROT_READ", + 0x2: "PROT_WRITE", + 0x4: "PROT_EXEC", + 0x8: "PROT_SEM", + 0x01000000: "PROT_GROWSDOWN", + 0x02000000: "PROT_GROWSUP", + } + + RT_SIGPROCMASK_HOW = { + 0: "SIG_BLOCK", + 1: "SIG_UNBLOCK", + 2: "SIG_SETMASK", + "parsing_mode": "sequential", + } + + ACCESS_MODES = { + 0: "F_OK", + 1: "X_OK", + 2: "W_OK", + 4: "R_OK", + } + + MREMAP_FLAGS = { + 1: "MREMAP_MAYMOVE", + 2: "MREMAP_FIXED", + 4: "MREMAP_DONTUNMAP", + } + + MSYNC_FLAGS = { + 1: "MS_ASYNC", + 2: "MS_INVALIDATE", + 4: "MS_SYNC", + } + + SHMGET_FLAGS = { + 0o00001000: "IPC_CREAT", + 0o00002000: "IPC_EXCL", + 0o00010000: "SHM_NORESERVE", + 0x54000000: "SHM_HUGE_2MB", + 0x78000000: "SHM_HUGE_1GB", + 0o0004000: "SHM_HUGETLB", + 0o0000032: "SHM_HUGE_SHIFT", + } + + SHMAT_FLAGS = { + 0o00001000: "IPC_CREAT", + 0o00002000: "IPC_EXCL", + 0o00010000: "SHM_NORESERVE", + 0x54000000: "SHM_HUGE_2MB", + 0x78000000: "SHM_HUGE_1GB", + 0o0004000: "SHM_HUGETLB", + 0o0000032: "SHM_HUGE_SHIFT", + } + + SHMCTL_CMDS = { + 0: "IPC_RMID", + 1: "IPC_SET", + 2: "IPC_STAT", + 3: "IPC_INFO", + 11: "SHM_LOCK", + 12: "SHM_UNLOCK", + 13: "SHM_STAT", + 14: "SHM_INFO", + 15: "SHM_STAT_ANY", + "parsing_mode": "sequential", + } + + ITIMER_WHICH = { + 0: "ITIMER_REAL", + 1: "ITIMER_VIRTUAL", + 2: "ITIMER_PROF", + "parsing_mode": "sequential", + } + + SOCKET_FAMILIES = { + 0: "AF_UNSPEC", + 1: "AF_UNIX / AF_LOCAL", + 2: "AF_INET", + 3: "AF_AX25", + 4: "AF_IPX", + 5: "AF_APPLETALK", + 6: "AF_NETROM", + 7: "AF_BRIDGE", + 8: "AF_ATMPVC", + 9: "AF_X25", + 10: "AF_INET6", + 11: "AF_ROSE", + 12: "AF_DECnet", + 13: "AF_NETBEUI", + 14: "AF_SECURITY", + 15: "AF_KEY", + 16: "AF_NETLINK / AF_ROUTE", + 17: "AF_PACKET", + 18: "AF_ASH", + 19: "AF_ECONET", + 20: "AF_ATMSVC", + 21: "AF_RDS", + 22: "AF_SNA", + 23: "AF_IRDA", + 24: "AF_PPPOX", + 25: "AF_WANPIPE", + 26: "AF_LLC", + 27: "AF_IB", + 28: "AF_MPLS", + 29: "AF_CAN", + 30: "AF_TIPC", + 31: "AF_BLUETOOTH", + 32: "AF_IUCV", + 33: "AF_RXRPC", + 34: "AF_ISDN", + 35: "AF_PHONET", + 36: "AF_IEEE802154", + 37: "AF_CAIF", + 38: "AF_ALG", + 39: "AF_NFC", + 40: "AF_VSOCK", + 41: "AF_KCM", + 42: "AF_QIPCRTR", + 43: "AF_SMC", + 44: "AF_XDP", + 45: "AF_MCTP", + "parsing_mode": "sequential", + } + + SOCKET_TYPES = { + "sequential_flags": { + 0x000001: "SOCK_STREAM", + 0x000002: "SOCK_DGRAM", + 0x000003: "SOCK_RAW", + 0x000004: "SOCK_RDM", + 0x000005: "SOCK_SEQPACKET", + 0x00000A: "SOCK_PACKET", + }, + "or_flags": { + 0x000800: "SOCK_NONBLOCK", + 0x080000: "SOCK_CLOEXEC", + }, + "parsing_mode": "mixed", + } + + SENDTO_FLAGS = { + 0x00000800: "MSG_CONFIRM", + 0x00000004: "MSG_DONTROUTE", + 0x00000040: "MSG_DONTWAIT", + 0x00000080: "MSG_EOR", + 0x00008000: "MSG_MORE", + 0x00004000: "MSG_NOSIGNAL", + 0x00000001: "MSG_OOB", + 0x20000000: "MSG_FASTOPEN", + } + + RECV_FLAGS = { + 0x40000000: "MSG_CMSG_CLOEXEC", + 0x00000040: "MSG_DONTWAIT", + 0x00002000: "MSG_ERRQUEUE", + 0x00000001: "MSG_OOB", + 0x00000002: "MSG_PEEK", + 0x00000020: "MSG_TRUNC", + 0x00000100: "MSG_WAITALL", + } + + SENDMSG_FLAGS = { + 0x00000800: "MSG_CONFIRM", + 0x00000004: "MSG_DONTROUTE", + 0x00000040: "MSG_DONTWAIT", + 0x00000080: "MSG_EOR", + 0x00008000: "MSG_MORE", + 0x00004000: "MSG_NOSIGNAL", + 0x00000001: "MSG_OOB", + 0x20000000: "MSG_FASTOPEN", + } + + SHUTDOWN_HOW = { + 0: "SHUT_RD", + 1: "SHUT_WR", + 2: "SHUT_RDWR", + "parsing_mode": "sequential", + } + + CLONE_FLAGS_COMMON = { + 0x00000100: "CLONE_VM", + 0x00000200: "CLONE_FS", + 0x00000400: "CLONE_FILES", + 0x00000800: "CLONE_SIGHAND", + 0x00001000: "CLONE_PIDFD", + 0x00002000: "CLONE_PTRACE", + 0x00004000: "CLONE_VFORK", + 0x00008000: "CLONE_PARENT", + 0x00010000: "CLONE_THREAD", + 0x00020000: "CLONE_NEWNS", + 0x00040000: "CLONE_SYSVSEM", + 0x00080000: "CLONE_SETTLS", + 0x00100000: "CLONE_PARENT_SETTID", + 0x00200000: "CLONE_CHILD_CLEARTID", + 0x00400000: "CLONE_DETACHED", + 0x00800000: "CLONE_UNTRACED", + 0x01000000: "CLONE_CHILD_SETTID", + 0x02000000: "CLONE_NEWCGROUP", + 0x04000000: "CLONE_NEWUTS", + 0x08000000: "CLONE_NEWIPC", + 0x10000000: "CLONE_NEWUSER", + 0x20000000: "CLONE_NEWPID", + 0x40000000: "CLONE_NEWNET", + 0x80000000: "CLONE_IO", + } + + WAIT4_OPTIONS = { + 0x00000001: "WNOHANG", + 0x00000002: "WUNTRACED / WSTOPPED", + 0x00000004: "WEXITED", + 0x00000008: "WCONTINUED", + 0x01000000: "WNOWAIT", + 0x20000000: "__WNOTHREAD", + 0x40000000: "__WALL", + 0x80000000: "__WCLONE", + } + + SEMGET_KEYS = { + 0: "IPC_PRIVATE", + } + + SEMGET_FLAGS = { + 0o0001000: "IPC_CREAT", + 0o0002000: "IPC_EXCL", + 0o0004000: "IPC_NOWAIT", + } + + SEMCTL_CMDS = { + 0: "IPC_RMID", + 1: "IPC_SET", + 2: "IPC_STAT", + 3: "IPC_INFO", + 18: "SEM_STAT", + 19: "SEM_INFO", + 20: "SEM_STAT_ANY", + 11: "GETPID", + 12: "GETVAL", + 13: "GETALL", + 14: "GETNCNT", + 15: "GETZCNT", + 16: "SETVAL", + 17: "SETALL", + "parsing_mode": "sequential", + } + + FLOCK_CMDS = { + 1: "LOCK_SH", + 2: "LOCK_EX", + 4: "LOCK_NB", + 8: "LOCK_UN", + } + + RLIMIT_RESOURCES = { + 0: "RLIMIT_CPU", + 1: "RLIMIT_FSIZE", + 2: "RLIMIT_DATA", + 3: "RLIMIT_STACK", + 4: "RLIMIT_CORE", + 5: "RLIMIT_RSS", + 6: "RLIMIT_NPROC", + 7: "RLIMIT_NOFILE", + 8: "RLIMIT_MEMLOCK", + 9: "RLIMIT_AS", + 10: "RLIMIT_LOCKS", + 11: "RLIMIT_SIGPENDING", + 12: "RLIMIT_MSGQUEUE", + 13: "RLIMIT_NICE", + 14: "RLIMIT_RTPRIO", + 15: "RLIMIT_RTTIME", + "parsing_mode": "sequential", + } + + RUSAGE_WHO = { + 0: "RUSAGE_SELF", + 0xFFFFFFFF: "RUSAGE_CHILDREN", + 0xFFFFFFFE: "RUSAGE_BOTH", + 1: "RUSAGE_THREAD", + "parsing_mode": "sequential", + } + + PTRACE_COMMON_REQUESTS = { + # Arch-independent + 0x4200: "PTRACE_SETOPTIONS", + 0x4201: "PTRACE_GETEVENTMSG", + 0x4202: "PTRACE_GETSIGINFO", + 0x4203: "PTRACE_SETSIGINFO", + 0x4204: "PTRACE_GETREGSET", + 0x4205: "PTRACE_SETREGSET", + 0x4206: "PTRACE_SEIZE", + 0x4207: "PTRACE_INTERRUPT", + 0x4208: "PTRACE_LISTEN", + 0x4209: "PTRACE_PEEKSIGINFO", + 0x420A: "PTRACE_GETSIGMASK", + 0x420B: "PTRACE_SETSIGMASK", + 0x420C: "PTRACE_SECCOMP_GET_FILTER", + 0x420D: "PTRACE_SECCOMP_GET_METADATA", + 0x420E: "PTRACE_GET_SYSCALL_INFO", + 0x420F: "PTRACE_GET_RSEQ_CONFIGURATION", + 0x4210: "PTRACE_SET_SYSCALL_USER_DISPATCH_CONFIG", + 0x4211: "PTRACE_GET_SYSCALL_USER_DISPATCH_CONFIG", + "parsing_mode": "sequential", + } + + SYSLOG_TYPES = { + 0: "SYSLOG_ACTION_CLOSE", + 1: "SYSLOG_ACTION_OPEN", + 2: "SYSLOG_ACTION_READ", + 3: "SYSLOG_ACTION_READ_ALL", + 4: "SYSLOG_ACTION_READ_CLEAR", + 5: "SYSLOG_ACTION_CLEAR", + 6: "SYSLOG_ACTION_CONSOLE_OFF", + 7: "SYSLOG_ACTION_CONSOLE_ON", + 8: "SYSLOG_ACTION_CONSOLE_LEVEL", + 9: "SYSLOG_ACTION_SIZE_UNREAD", + 10: "SYSLOG_ACTION_SIZE_BUFFER", + "parsing_mode": "sequential", + } + + MKNOD_MODES = { + # Permissions + 0o00700: "S_IRWXU", + 0o00400: "S_IRUSR", + 0o00200: "S_IWUSR", + 0o00100: "S_IXUSR", + 0o00070: "S_IRWXG", + 0o00040: "S_IRGRP", + 0o00020: "S_IWGRP", + 0o00010: "S_IXGRP", + 0o00007: "S_IRWXO", + 0o00004: "S_IROTH", + 0o00002: "S_IWOTH", + 0o00001: "S_IXOTH", + 0o0004000: "S_ISUID", + 0o0002000: "S_ISGID", + 0o0001000: "S_ISVTX", + # File type + 0o100000: "S_IFREG", + 0o020000: "S_IFCHR", + 0o060000: "S_IFBLK", + 0o010000: "S_IFIFO", + 0o140000: "S_IFSOCK", + } + + PROCESS_PERSONALITIES = { + 0x0200000: "ADDR_COMPAT_LAYOUT", + 0x0040000: "ADDR_NO_RANDOMIZE", + 0x0800000: "PER_LINUX_32BIT | ADDR_LIMIT_32BIT", + 0x8000000: "ADDR_LIMIT_3GB", + 0x0100000: "MMAP_PAGE_ZERO", + 0x0400000: "READ_IMPLIES_EXEC", + 0x1000000: "SHORT_INODE", + 0x4000000: "STICKY_TIMEOUTS", + 0x0020000: "UNAME26", + 0x2000000: "WHOLE_SECONDS", + 0x0006: "PER_BSD", + 0x0010: "PER_HPUX", + 0x4000009: "PER_IRIX32", + 0x400000B: "PER_IRIX64", + 0x400000A: "PER_IRIXN32", + 0x4000005: "PER_ISCR4", + 0x0000000: "PER_LINUX", + 0x0000008: "PER_LINUX32", + 0x8000008: "PER_LINUX32_3GB", + 0x000F: "PER_OSF4", + 0x0000000C: "PER_RISCOS", + 0x07000003: "PER_SCOSVR3", + 0x0400000D: "PER_SOLARIS", + 0x04000006: "PER_SUNOS", + 0x05000002: "PER_SVR3", + 0x04100001: "PER_SVR4", + 0x0410000E: "PER_UW7", + 0x05000004: "PER_WYSEV386", + 0x05000007: "PER_XENIX", + } + + PRIORITY_WHICH = { + 0: "PRIO_PROCESS", + 1: "PRIO_PGRP", + 2: "PRIO_USER", + "parsing_mode": "sequential", + } + + SCHEDULER_POLICIES = { + 0: "SCHED_NORMAL", + 1: "SCHED_FIFO", + 2: "SCHED_RR", + 3: "SCHED_BATCH", + 5: "SCHED_IDLE", + 6: "SCHED_DEADLINE", + 7: "SCHED_EXT", + "parsing_mode": "sequential", + } + + MLOCKALL_FLAGS = { + 0x00000001: "MCL_CURRENT", + 0x00000002: "MCL_FUTURE", + 0x00000004: "MCL_ONFAULT", + } + + PRCTL_OPTIONS = { + 0x0000002F: "PR_CAP_AMBIENT", + 0x00000017: "PR_CAPBSET_READ", + 0x00000018: "PR_CAPBSET_DROP", + 0x00000024: "PR_SET_CHILD_SUBREAPER", + 0x00000025: "PR_GET_CHILD_SUBREAPER", + 0x00000004: "PR_SET_DUMPABLE", + 0x00000003: "PR_GET_DUMPABLE", + 0x00000014: "PR_SET_ENDIAN", + 0x00000013: "PR_GET_ENDIAN", + 0x0000002D: "PR_SET_FP_MODE", + 0x0000002E: "PR_GET_FP_MODE", + 0x0000000A: "PR_SET_FPEMU", + 0x00000009: "PR_GET_FPEMU", + 0x0000000C: "PR_SET_FPEXC", + 0x0000000B: "PR_GET_FPEXC", + 0x00000039: "PR_SET_IO_FLUSHER", + 0x0000003A: "PR_GET_IO_FLUSHER", + 0x00000008: "PR_SET_KEEPCAPS", + 0x00000007: "PR_GET_KEEPCAPS", + 0x00000021: "PR_MCE_KILL", + 0x00000022: "PR_MCE_KILL_GET", + 0x00000023: "PR_SET_MM", + 0x53564D41: "PR_SET_VMA", + 0x0000002B: "PR_MPX_ENABLE_MANAGEMENT", + 0x0000002C: "PR_MPX_DISABLE_MANAGEMENT", + 0x0000000F: "PR_SET_NAME", + 0x00000010: "PR_GET_NAME", + 0x00000026: "PR_SET_NO_NEW_PRIVS", + 0x00000027: "PR_GET_NO_NEW_PRIVS", + 0x00000036: "PR_PAC_RESET_KEYS", + 0x00000001: "PR_SET_PDEATHSIG", + 0x00000002: "PR_GET_PDEATHSIG", + 0x59616D61: "PR_SET_PTRACER", + 0x00000016: "PR_SET_SECCOMP", + 0x00000015: "PR_GET_SECCOMP", + 0x0000001C: "PR_SET_SECUREBITS", + 0x0000001B: "PR_GET_SECUREBITS", + 0x00000034: "PR_GET_SPECULATION_CTRL", + 0x00000035: "PR_SET_SPECULATION_CTRL", + 0x00000032: "PR_SVE_SET_VL", + 0x00000033: "PR_SVE_GET_VL", + 0x0000003B: "PR_SET_SYSCALL_USER_DISPATCH", + 0x00000037: "PR_SET_TAGGED_ADDR_CTRL", + 0x00000038: "PR_GET_TAGGED_ADDR_CTRL", + 0x0000001F: "PR_TASK_PERF_EVENTS_DISABLE", + 0x00000020: "PR_TASK_PERF_EVENTS_ENABLE", + 0x00000029: "PR_SET_THP_DISABLE", + 0x0000002A: "PR_GET_THP_DISABLE", + 0x00000028: "PR_GET_TID_ADDRESS", + 0x0000001D: "PR_SET_TIMERSLACK", + 0x0000001E: "PR_GET_TIMERSLACK", + 0x0000000E: "PR_SET_TIMING", + 0x0000000D: "PR_GET_TIMING", + 0x0000001A: "PR_SET_TSC", + 0x00000019: "PR_GET_TSC", + 0x00000006: "PR_SET_UNALIGN", + 0x00000005: "PR_GET_UNALIGN", + 0x41555856: "PR_GET_AUXV", + 0x00000041: "PR_SET_MDWE", + 0x00000042: "PR_GET_MDWE", + 0x00000047: "PR_RISCV_SET_ICACHE_FLUSH_CTX", + "parsing_mode": "sequential", + } + + MOUNT_FLAGS = { + 0x00000001: "MS_RDONLY", + 0x00000002: "MS_NOSUID", + 0x00000004: "MS_NODEV", + 0x00000008: "MS_NOEXEC", + 0x00000010: "MS_SYNCHRONOUS", + 0x00000020: "MS_REMOUNT", + 0x00000040: "MS_MANDLOCK", + 0x00000080: "MS_DIRSYNC", + 0x00000100: "MS_NOSYMFOLLOW", + 0x00000400: "MS_NOATIME", + 0x00000800: "MS_NODIRATIME", + 0x00001000: "MS_BIND", + 0x00002000: "MS_MOVE", + 0x00004000: "MS_REC", + # 0x00008000: "MS_VERBOSE", /* War is peace. Verbosity is silence. MS_VERBOSE is deprecated. */ + 0x00008000: "MS_SILENT", + 0x00010000: "MS_POSIXACL", + 0x00020000: "MS_UNBINDABLE", + 0x00040000: "MS_PRIVATE", + 0x00080000: "MS_SLAVE", + 0x00100000: "MS_SHARED", + 0x00200000: "MS_RELATIME", + 0x00400000: "MS_KERNMOUNT", + 0x00800000: "MS_I_VERSION", + 0x01000000: "MS_STRICTATIME", + 0x02000000: "MS_LAZYTIME", + } + + UMOUNT_FLAGS = { + 0x00000001: "MNT_FORCE", + 0x00000002: "MNT_DETACH", + 0x00000004: "MNT_EXPIRE", + 0x00000008: "UMOUNT_NOFOLLOW", + 0x80000000: "UMOUNT_UNUSED", + } + + SWAPON_FLAGS = { + 0x8000: "SWAP_FLAG_PREFER", + 0x10000: "SWAP_FLAG_DISCARD", + } + + REBOOT_MAGIC1 = { + 0xFEE1DEAD: "LINUX_REBOOT_MAGIC1", + "parsing_mode": "sequential", + } + + REBOOT_MAGIC2 = { + 672274793: "LINUX_REBOOT_MAGIC2", + 85072278: "LINUX_REBOOT_MAGIC2A", + 369367448: "LINUX_REBOOT_MAGIC2B", + 537993216: "LINUX_REBOOT_MAGIC2C", + "parsing_mode": "sequential", + } + + REBOOT_CMDS = { + 0x01234567: "LINUX_REBOOT_CMD_RESTART", + 0xCDEF0123: "LINUX_REBOOT_CMD_HALT", + 0x89ABCDEF: "LINUX_REBOOT_CMD_CAD_ON", + 0x00000000: "LINUX_REBOOT_CMD_CAD_OFF", + 0x4321FEDC: "LINUX_REBOOT_CMD_POWER_OFF", + 0xA1B2C3D4: "LINUX_REBOOT_CMD_RESTART2", + 0xD000FCE2: "LINUX_REBOOT_CMD_SW_SUSPEND", + 0x45584543: "LINUX_REBOOT_CMD_KEXEC", + "parsing_mode": "sequential", + } + + DELETE_MODULE_FLAGS = { + 0o0004000: "O_NONBLOCK", + 0o0001000: "O_TRUNC", + } + + QUOTACTL_CMDS = { + 0: "USRQUOTA", + 1: "GRPQUOTA", + 2: "PRJQUOTA", + 0x80000100: "Q_SYNC", + 0x80000200: "Q_QUOTAON", + 0x80000300: "Q_QUOTAOFF", + 0x80000400: "Q_GETFMT", + 0x80000500: "Q_GETINFO", + 0x80000600: "Q_SETINFO", + 0x80000700: "Q_GETQUOTA", + 0x80000800: "Q_SETQUOTA", + 0x80000900: "Q_GETNEXTQUOTA", + } + + XATTR_FLAGS = { + 0x00000001: "XATTR_CREATE", + 0x00000002: "XATTR_REPLACE", + "parsing_mode": "sequential", + } + + FUTEX_OPS = { + "sequential_flags": { + 0: "FUTEX_WAIT", + 1: "FUTEX_WAKE", + 2: "FUTEX_FD", + 3: "FUTEX_REQUEUE", + 4: "FUTEX_CMP_REQUEUE", + 5: "FUTEX_WAKE_OP", + 6: "FUTEX_LOCK_PI", + 7: "FUTEX_UNLOCK_PI", + 8: "FUTEX_TRYLOCK_PI", + 9: "FUTEX_WAIT_BITSET", + 10: "FUTEX_WAKE_BITSET", + 11: "FUTEX_WAIT_REQUEUE_PI", + 12: "FUTEX_CMP_REQUEUE_PI", + 13: "FUTEX_LOCK_PI2", + }, + "or_flags": { + 128: "FUTEX_PRIVATE_FLAG", + 256: "FUTEX_CLOCK_REALTIME", + }, + "parsing_mode": "mixed", + } + + REMAP_FILE_PAGES_FLAGS = { + # All flags other that MAP_NONBLOCK are ignored + 0x00010000: "MAP_NONBLOCK", + } + + FADVISE_ADVICE = { + 0: "POSIX_FADV_NORMAL", + 1: "POSIX_FADV_RANDOM", + 2: "POSIX_FADV_SEQUENTIAL", + 3: "POSIX_FADV_WILLNEED", + 4: "POSIX_FADV_DONTNEED", + 5: "POSIX_FADV_NOREUSE", + "parsing_mode": "sequential", + } + + TIMER_SETTIME_FLAGS = { + 1: "TIMER_ABSTIME", + } + + CLOCK_NANOSLEEP_FLAGS = { + 1: "TIMER_ABSTIME", + } + + EPOLL_CTL_OPS = { + 1: "EPOLL_CTL_ADD", + 2: "EPOLL_CTL_DEL", + 3: "EPOLL_CTL_MOD", + "parsing_mode": "sequential", + } + + MBIND_MODES = { + "sequential_flags": { + 0: "MPOL_DEFAULT", + 1: "MPOL_PREFERRED", + 2: "MPOL_BIND", + 3: "MPOL_INTERLEAVE", + 4: "MPOL_LOCAL", + 5: "MPOL_PREFERRED_MANY", + 6: "MPOL_WEIGHTED_INTERLEAVE", + 7: "MPOL_MAX", + }, + "or_flags": { + 0b1000000000000000: "MPOL_F_STATIC_NODES", + 0b0100000000000000: "MPOL_F_RELATIVE_NODES", + 0b0010000000000000: "MPOL_F_NUMA_BALANCING", + }, + "parsing_mode": "mixed", + } + + MBIND_FLAGS = { + 0b00000001: "MPOL_MF_STRICT", + 0b00000010: "MPOL_MF_MOVE", + 0b00000100: "MPOL_MF_MOVE_ALL", + 0b00001000: "MPOL_MF_LAZY", + 0b00010000: "MPOL_MF_INTERNAL", + } + + SETMEMPOLICY_MODES = { + "sequential_flags": { + 0: "MPOL_DEFAULT", + 1: "MPOL_PREFERRED", + 2: "MPOL_BIND", + 3: "MPOL_INTERLEAVE", + 4: "MPOL_LOCAL", + 5: "MPOL_PREFERRED_MANY", + 6: "MPOL_WEIGHTED_INTERLEAVE", + 7: "MPOL_MAX", + }, + "or_flags": { + 0b1000000000000000: "MPOL_F_STATIC_NODES", + 0b0100000000000000: "MPOL_F_RELATIVE_NODES", + 0b0010000000000000: "MPOL_F_NUMA_BALANCING", + }, + "parsing_mode": "mixed", + } + + GETMEMPOLICY_FLAGS = { + 0b0001: "MPOL_F_NODE", + 0b0010: "MPOL_F_ADDR", + 0b0100: "MPOL_F_MEMS_ALLOWED", + } + + MQ_OPEN_FLAGS = { + "or_flags": { + 0o02000000: "O_CLOEXEC", + 0o00000100: "O_CREAT", + 0o00000200: "O_EXCL", + 0o00004000: "O_NOFOLLOW / O_NONBLOCK", + }, + "sequential_flags": { + 0o00000000: "O_RDONLY", + 0o00000001: "O_WRONLY", + 0o00000002: "O_RDWR", + }, + "parsing_mode": "mixed", + } + + KEXEC_LOAD_FLAGS = { + "or_flags": { + 0x00000001: "KEXEC_ON_CRASH", + 0x00000002: "KEXEC_PRESERVE_CONTEXT", + 0x00000004: "KEXEC_UPDATE_ELFCOREHDR", + 0x00000008: "KEXEC_CRASH_HOTPLUG_SUPPORT", + 0xFFFF0000: "KEXEC_ARCH_MASK", + }, + "sequential_flags": { + 0x0: "KEXEC_ARCH_DEFAULT", + 0x30000: "KEXEC_ARCH_386", + 0x40000: "KEXEC_ARCH_68K", + 0xF0000: "KEXEC_ARCH_PARISC", + 0x3E0000: "KEXEC_ARCH_X86_64", + 0x140000: "KEXEC_ARCH_PPC", + 0x150000: "KEXEC_ARCH_PPC64", + 0x320000: "KEXEC_ARCH_IA_64", + 0x280000: "KEXEC_ARCH_ARM", + 0x160000: "KEXEC_ARCH_S390", + 0x2A0000: "KEXEC_ARCH_SH", + 0xA0000: "KEXEC_ARCH_MIPS_LE", + 0x80000: "KEXEC_ARCH_MIPS", + 0xB70000: "KEXEC_ARCH_AARCH64", + 0xF30000: "KEXEC_ARCH_RISCV", + 0x1020000: "KEXEC_ARCH_LOONGARCH", + }, + "parsing_mode": "mixed", + } + + WAITID_WHICH = { + 0: "P_ALL", + 1: "P_PID", + 2: "P_PGID", + "parsing_mode": "sequential", + } + + WAITID_OPTIONS = { + 0x00000001: "WNOHANG", + 0x00000002: "WUNTRACED / WSTOPPED", + 0x00000004: "WEXITED", + 0x00000008: "WCONTINUED", + 0x01000000: "WNOWAIT", + 0x20000000: "__WNOTHREAD", + 0x40000000: "__WALL", + 0x80000000: "__WCLONE", + } + + KEYCTL_OPTIONS = { + 0: "KEYCTL_GET_KEYRING_ID", + 1: "KEYCTL_JOIN_SESSION_KEYRING", + 2: "KEYCTL_UPDATE", + 3: "KEYCTL_REVOKE", + 4: "KEYCTL_CHOWN", + 5: "KEYCTL_SETPERM", + 6: "KEYCTL_DESCRIBE", + 7: "KEYCTL_CLEAR", + 8: "KEYCTL_LINK", + 9: "KEYCTL_UNLINK", + 10: "KEYCTL_SEARCH", + 11: "KEYCTL_READ", + 12: "KEYCTL_INSTANTIATE", + 13: "KEYCTL_NEGATE", + 14: "KEYCTL_SET_REQKEY_KEYRING", + 15: "KEYCTL_SET_TIMEOUT", + 16: "KEYCTL_ASSUME_AUTHORITY", + 17: "KEYCTL_GET_SECURITY", + 18: "KEYCTL_SESSION_TO_PARENT", + 19: "KEYCTL_REJECT", + 20: "KEYCTL_INSTANTIATE_IOV", + 21: "KEYCTL_INVALIDATE", + 22: "KEYCTL_GET_PERSISTENT", + 23: "KEYCTL_DH_COMPUTE", + 24: "KEYCTL_PKEY_QUERY", + 25: "KEYCTL_PKEY_ENCRYPT", + 26: "KEYCTL_PKEY_DECRYPT", + 27: "KEYCTL_PKEY_SIGN", + 28: "KEYCTL_PKEY_VERIFY", + 29: "KEYCTL_RESTRICT_KEYRING", + 30: "KEYCTL_MOVE", + 31: "KEYCTL_CAPABILITIES", + 32: "KEYCTL_WATCH_KEY", + "parsing_mode": "sequential", + } + + IOPRIO_WHICH = { + 1: "IOPRIO_WHO_PROCESS", + 2: "IOPRIO_WHO_PGRP", + 3: "IOPRIO_WHO_USER", + "parsing_mode": "sequential", + } + + FCHOWNAT_FLAGS = { + 0x1000: "AT_EMPTY_PATH", + 0x100: "AT_SYMLINK_NOFOLLOW", + } + + NEWSTATFS_FLAGS = { + 0x1000: "AT_EMPTY_PATH", + 0x100: "AT_SYMLINK_NOFOLLOW", + 0x800: "AT_NO_AUTOMOUNT", + } + + UNLINKAT_FLAGS = { + 0x200: "AT_REMOVEDIR", + } + + LINKAT_FLAGS = { + 0x1000: "AT_EMPTY_PATH", + 0x400: "AT_SYMLINK_FOLLOW", + } + + UNSHARE_FLAGS = { + 0x00000400: "CLONE_FILES", + 0x00000200: "CLONE_FS", + 0x02000000: "CLONE_NEWCGROUP", + 0x08000000: "CLONE_NEWIPC", + 0x40000000: "CLONE_NEWNET", + 0x00020000: "CLONE_NEWNS", + 0x20000000: "CLONE_NEWPID", + 0x00000080: "CLONE_NEWTIME", + 0x10000000: "CLONE_NEWUSER", + 0x04000000: "CLONE_NEWUTS", + 0x00040000: "CLONE_SYSVSEM", + 0x00000100: "CLONE_VM", + 0x00010000: "CLONE_THREAD", + 0x00000800: "CLONE_SIGHAND", + } + + SYNC_FILE_RANGE_FLAGS = { + 1: "SYNC_FILE_RANGE_WAIT_BEFORE", + 2: "SYNC_FILE_RANGE_WRITE", + 4: "SYNC_FILE_RANGE_WAIT_AFTER", + } + + MOVEPAGES_FLAGS = { + 0b10: "MPOL_MF_MOVE", + 0b100: "MPOL_MF_MOVE_ALL", + } + + UTIMENSAT_FLAGS = { + 0x1000: "AT_EMPTY_PATH", + 0x100: "AT_SYMLINK_NOFOLLOW", + } + + TIMERFD_CREATE_CLOCKS = { + 0: "CLOCK_REALTIME", + 1: "CLOCK_MONOTONIC", + 7: "CLOCK_BOOTTIME", + 8: "CLOCK_REALTIME_ALARM", + 9: "CLOCK_BOOTTIME_ALARM", + "parsing_mode": "sequential", + } + + TIMERFD_CREATE_FLAGS = { + 0o02000000: "TFD_CLOEXEC", + 0o00004000: "TFD_NONBLOCK", + } + + FALLOCATE_MODES = { + 0x00: "FALLOC_FL_ALLOCATE_RANGE", + 0x01: "FALLOC_FL_KEEP_SIZE", + 0x02: "FALLOC_FL_PUNCH_HOLE", + 0x04: "FALLOC_FL_NO_HIDE_STALE", + 0x08: "FALLOC_FL_COLLAPSE_RANGE", + 0x10: "FALLOC_FL_ZERO_RANGE", + 0x20: "FALLOC_FL_INSERT_RANGE", + 0x40: "FALLOC_FL_UNSHARE_RANGE", + } + + TIMERFD_SETTIME_FLAGS = { + 0x00000001: "TFD_TIMER_ABSTIME", + 0x00000002: "TFD_TIMER_CANCEL_ON_SET", + } + + ACCEPT_FLAGS = { + 0o02000000: "SOCK_CLOEXEC", + 0o00004000: "SOCK_NONBLOCK", + } + + SIGNALFD_FLAGS = { + 0o02000000: "SFD_CLOEXEC", + 0o00004000: "SFD_NONBLOCK", + } + + EVENTFD_FLAGS = { + 0o00000001: "EFD_SEMAPHORE", + 0o02000000: "EFD_CLOEXEC", + 0o00004000: "EFD_NONBLOCK", + } + + EPOLL_CREATE_FLAGS = { + 0o02000000: "EPOLL_CLOEXEC", + } + + DUP3_FLAGS = { + 0o02000000: "O_CLOEXEC", + } + + PIPE2_FLAGS = { + 0o02000000: "O_CLOEXEC", + 0o00004000: "O_NONBLOCK", + 0o00040000: "O_DIRECT", + 0o00000200: "O_EXCL", + } + + INOTIFY_INIT_FLAGS = { + 0o02000000: "IN_CLOEXEC", + 0o00004000: "IN_NONBLOCK", + } + + PERF_EVENT_OPEN_FLAGS = { + 0b0001: "PERF_FLAG_FD_NO_GROUP", + 0b0010: "PERF_FLAG_FD_OUTPUT", + 0b0100: "PERF_FLAG_PID_CGROUP", + 0b1000: "PERF_FLAG_FD_CLOEXEC", + } + + RECVMMSG_FLAGS = { + 0x40000000: "MSG_CMSG_CLOEXEC", + 0x00000040: "MSG_DONTWAIT", + 0x00002000: "MSG_ERRQUEUE", + 0x00000001: "MSG_OOB", + 0x00000002: "MSG_PEEK", + 0x00000020: "MSG_TRUNC", + 0x00000100: "MSG_WAITALL", + } + + FANOTIFY_INIT_FLAGS = { + "sequential_flags": { + 0x00000000: "FAN_CLASS_NOTIF", + 0x00000004: "FAN_CLASS_CONTENT", + 0x00000008: "FAN_CLASS_PRE_CONTENT", + }, + "or_flags": { + 0x00000001: "FAN_CLOEXEC", + 0x00000002: "FAN_NONBLOCK", + 0x00000010: "FAN_UNLIMITED_QUEUE", + 0x00000020: "FAN_UNLIMITED_MARKS", + 0x00000040: "FAN_ENABLE_AUDIT", + 0x00000100: "FAN_REPORT_TID", + 0x00000200: "FAN_REPORT_FID", + 0x00000400: "FAN_REPORT_DIR_FID", + 0x00000800: "FAN_REPORT_NAME", + 0x00001000: "FAN_REPORT_TARGET_FID", + 0x00000080: "FAN_REPORT_PIDFD", + }, + "parsing_mode": "mixed", + } + + FANOTIFY_EVENT_F_FLAGS = { + "or_flags": { + 0o00100000: "O_LARGEFILE", + 0o02000000: "O_CLOEXEC", + 0o00002000: "O_APPEND", + 0o00010000: "O_DSYNC", + 0o01000000: "O_NOATIME", + 0o00004000: "O_NONBLOCK", + }, + "sequential_flags": { + 0o00000000: "O_RDONLY", + 0o00000001: "O_WRONLY", + 0o00000002: "O_RDWR", + }, + "parsing_mode": "mixed", + } + + FANOTIFY_MARK_FLAGS = { + "sequential_flags": { + 0x00000001: "FAN_MARK_ADD", + 0x00000002: "FAN_MARK_REMOVE", + 0x00000080: "FAN_MARK_FLUSH", + }, + "or_flags": { + 0x00000004: "FAN_MARK_DONT_FOLLOW", + 0x00000008: "FAN_MARK_ONLYDIR", + 0x00000010: "FAN_MARK_MOUNT", + 0x00000100: "FAN_MARK_FILESYSTEM", + 0x00000020: "FAN_MARK_IGNORED_MASK", + 0x00000400: "FAN_MARK_IGNORE", + 0x00000040: "FAN_MARK_IGNORED_SURV_MODIFY", + 0x00000200: "FAN_MARK_EVICTABLE", + }, + "parsing_mode": "mixed", + } + + FANOTIFY_MARK_MASK = { + 0x00000001: "FAN_ACCESS", + 0x00000002: "FAN_MODIFY", + 0x00000004: "FAN_ATTRIB", + 0x00000008: "FAN_CLOSE_WRITE", + 0x00000010: "FAN_CLOSE_NOWRITE", + 0x00000020: "FAN_OPEN", + 0x00000040: "FAN_MOVED_FROM", + 0x00000080: "FAN_MOVED_TO", + 0x00000100: "FAN_CREATE", + 0x00000200: "FAN_DELETE", + 0x00000400: "FAN_DELETE_SELF", + 0x00000800: "FAN_MOVE_SELF", + 0x00001000: "FAN_OPEN_EXEC", + 0x00008000: "FAN_FS_ERROR", + 0x10000000: "FAN_RENAME", + 0x00020000: "FAN_ACCESS_PERM", + 0x00040000: "FAN_OPEN_EXEC_PERM", + 0x40000000: "FAN_ONDIR", + 0x08000000: "FAN_EVENT_ON_CHILD", + } + + PRLIMIT_RESOURCES = { + 0: "RLIMIT_CPU", + 1: "RLIMIT_FSIZE", + 2: "RLIMIT_DATA", + 3: "RLIMIT_STACK", + 4: "RLIMIT_CORE", + 5: "RLIMIT_RSS", + 6: "RLIMIT_NPROC", + 7: "RLIMIT_NOFILE", + 8: "RLIMIT_MEMLOCK", + 9: "RLIMIT_AS", + 10: "RLIMIT_LOCKS", + 11: "RLIMIT_SIGPENDING", + 12: "RLIMIT_MSGQUEUE", + 13: "RLIMIT_NICE", + 14: "RLIMIT_RTPRIO", + 15: "RLIMIT_RTTIME", + 0xFFFFFFFF: "RLIM_INFINITY", + "parsing_mode": "sequential", + } + + NAME_TO_HANDLE_FLAGS = { + 0x200: "AT_HANDLE_FID", + 0x1000: "AT_EMPTY_PATH", + 0x400: "AT_SYMLINK_FOLLOW", + } + + SETNS_FLAGS = { + 0x02000000: "CLONE_NEWCGROUP", + 0x04000000: "CLONE_NEWUTS", + 0x08000000: "CLONE_NEWIPC", + 0x40000000: "CLONE_NEWNET", + 0x00000080: "CLONE_NEWTIME", + 0x00020000: "CLONE_NEWNS", + 0x20000000: "CLONE_NEWPID", + 0x10000000: "CLONE_NEWUSER", + } + + KCMP_TYPES = { + 0: "KCMP_FILE", + 1: "KCMP_VM", + 2: "KCMP_FILES", + 3: "KCMP_FS", + 4: "KCMP_SIGHAND", + 5: "KCMP_IO", + 6: "KCMP_SYSVSEM", + 7: "KCMP_EPOLL_TFD", + "parsing_mode": "sequential", + } + + FINIT_MODULE_FLAGS = { + 1: "MODULE_INIT_IGNORE_MODVERSIONS", + 2: "MODULE_INIT_IGNORE_VERMAGIC", + 4: "MODULE_INIT_COMPRESSED_FILE", + } + + RENAMEAT_FLAGS = { + 0b001: "RENAME_NOREPLACE", + 0b010: "RENAME_EXCHANGE", + 0b100: "RENAME_WHITEOUT", + } + + SECCOMP_OPS = { + 0: "SECCOMP_SET_MODE_STRICT", + 1: "SECCOMP_SET_MODE_FILTER", + 2: "SECCOMP_GET_ACTION_AVAIL", + 3: "SECCOMP_GET_NOTIF_SIZES", + } + + SECCOMP_FLAGS = { + 0b000001: "SECCOMP_FILTER_FLAG_TSYNC", + 0b000010: "SECCOMP_FILTER_FLAG_LOG", + 0b000100: "SECCOMP_FILTER_FLAG_SPEC_ALLOW", + 0b001000: "SECCOMP_FILTER_FLAG_NEW_LISTENER", + 0b010000: "SECCOMP_FILTER_FLAG_TSYNC_ESRCH", + 0b100000: "SECCOMP_FILTER_FLAG_WAIT_KILLABLE_RECV", + } + + GETRANDOM_FLAGS = { + 0x0001: "GRND_NONBLOCK", + 0x0002: "GRND_RANDOM", + 0x0004: "GRND_INSECURE", + } + + MEMFD_CREATE_FLAGS = { + 0x1: "MFD_CLOEXEC", + 0x2: "MFD_ALLOW_SEALING", + 0x4: "MFD_HUGETLB", + 0x8: "MFD_NOEXEC_SEAL", + 0x10: "MFD_EXEC", + 0x40000000: "MFD_HUGE_64KB", + 0x4C000000: "MFD_HUGE_512KB", + 0x50000000: "MFD_HUGE_1MB", + 0x54000000: "MFD_HUGE_2MB", + 0x5C000000: "MFD_HUGE_8MB", + 0x60000000: "MFD_HUGE_16MB", + 0x64000000: "MFD_HUGE_32MB", + 0x70000000: "MFD_HUGE_256MB", + 0x74000000: "MFD_HUGE_512MB", + 0x78000000: "MFD_HUGE_1GB", + 0x7C000000: "MFD_HUGE_2GB", + 0x88000000: "MFD_HUGE_16GB", + } + + KEXEC_FILE_LOAD_FLAGS = { + 0x00000001: "KEXEC_FILE_UNLOAD", + 0x00000002: "KEXEC_FILE_ON_CRASH", + 0x00000004: "KEXEC_FILE_NO_INITRAMFS", + 0x00000008: "KEXEC_FILE_DEBUG", + } + + BPF_CMDS = { + 0: "BPF_MAP_CREATE", + 1: "BPF_MAP_LOOKUP_ELEM", + 2: "BPF_MAP_UPDATE_ELEM", + 3: "BPF_MAP_DELETE_ELEM", + 4: "BPF_MAP_GET_NEXT_KEY", + 5: "BPF_PROG_LOAD", + 6: "BPF_OBJ_PIN", + 7: "BPF_OBJ_GET", + 8: "BPF_PROG_ATTACH", + 9: "BPF_PROG_DETACH", + 10: "BPF_PROG_RUN", + 11: "BPF_PROG_GET_NEXT_ID", + 12: "BPF_MAP_GET_NEXT_ID", + 13: "BPF_PROG_GET_FD_BY_ID", + 14: "BPF_MAP_GET_FD_BY_ID", + 15: "BPF_OBJ_GET_INFO_BY_FD", + 16: "BPF_PROG_QUERY", + 17: "BPF_RAW_TRACEPOINT_OPEN", + 18: "BPF_BTF_LOAD", + 19: "BPF_BTF_GET_FD_BY_ID", + 20: "BPF_TASK_FD_QUERY", + 21: "BPF_MAP_LOOKUP_AND_DELETE_ELEM", + 22: "BPF_MAP_FREEZE", + 23: "BPF_BTF_GET_NEXT_ID", + 24: "BPF_MAP_LOOKUP_BATCH", + 25: "BPF_MAP_LOOKUP_AND_DELETE_BATCH", + 26: "BPF_MAP_UPDATE_BATCH", + 27: "BPF_MAP_DELETE_BATCH", + 28: "BPF_LINK_CREATE", + 29: "BPF_LINK_UPDATE", + 30: "BPF_LINK_GET_FD_BY_ID", + 31: "BPF_LINK_GET_NEXT_ID", + 32: "BPF_ENABLE_STATS", + 33: "BPF_ITER_CREATE", + 34: "BPF_LINK_DETACH", + 35: "BPF_PROG_BIND_MAP", + 36: "BPF_TOKEN_CREATE", + "parsing_mode": "sequential", + } + + EXECVEAT_FLAGS = { + 0x1000: "AT_EMPTY_PATH", + 0x100: "AT_SYMLINK_NOFOLLOW", + } + + USERFAULTFD_FLAGS = { + 0x00000001: "UFFD_USER_MODE_ONLY", + 0o02000000: "O_CLOEXEC", + 0o00004000: "O_NONBLOCK", + } + + MEMBARRIER_CMDS = { + 0b0000000000: "MEMBARRIER_CMD_QUERY", + 0b0000000001: "MEMBARRIER_CMD_GLOBAL", + 0b0000000010: "MEMBARRIER_CMD_GLOBAL_EXPEDITED", + 0b0000000100: "MEMBARRIER_CMD_REGISTER_GLOBAL_EXPEDITED", + 0b0000001000: "MEMBARRIER_CMD_PRIVATE_EXPEDITED", + 0b0000010000: "MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED", + 0b0000100000: "MEMBARRIER_CMD_PRIVATE_EXPEDITED_SYNC_CORE", + 0b0001000000: "MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED_SYNC_CORE", + 0b0010000000: "MEMBARRIER_CMD_PRIVATE_EXPEDITED_RSEQ", + 0b0100000000: "MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED_RSEQ", + 0b1000000000: "MEMBARRIER_CMD_GET_REGISTRATIONS", + } + + MEMBARRIER_FLAGS = { + 0x00000001: "MEMBARRIER_CMD_FLAG_CPU", + } + + MLOCK_FLAGS = { + 1: "MCL_CURRENT", + 2: "MCL_FUTURE", + 4: "MCL_ONFAULT", + } + + PREADV_FLAGS = { + 0x00000001: "RWF_HIPRI", + 0x00000002: "RWF_DSYNC", + 0x00000004: "RWF_SYNC", + 0x00000008: "RWF_NOWAIT", + 0x00000010: "RWF_APPEND", + 0x00000020: "RWF_NOAPPEND", + 0x00000040: "RWF_ATOMIC", + 0x00000080: "RWF_DONTCACHE", + } + + PKEY_MPROTECT_PROTS = { + 0x0: "PROT_NONE", + 0x1: "PROT_READ", + 0x2: "PROT_WRITE", + 0x4: "PROT_EXEC", + 0x8: "PROT_SEM", + 0x10: "PROT_SAO", + 0x01000000: "PROT_GROWSDOWN", + 0x02000000: "PROT_GROWSUP", + } + + PKEY_ALLOC_INIT_VALS = { + 0x1: "PKEY_DISABLE_ACCESS", + 0x2: "PKEY_DISABLE_WRITE", + } + + STATX_FLAGS = { + 0x1000: "AT_EMPTY_PATH", + 0x800: "AT_NO_AUTOMOUNT", + 0x100: "AT_SYMLINK_NOFOLLOW", + 0x6000: "AT_STATX_SYNC_TYPE", + 0x0000: "AT_STATX_SYNC_AS_STAT", + 0x2000: "AT_STATX_FORCE_SYNC", + 0x4000: "AT_STATX_DONT_SYNC", + } + + STATX_MASKS = { + 0x00000001: "STATX_TYPE", + 0x00000002: "STATX_MODE", + 0x00000004: "STATX_NLINK", + 0x00000008: "STATX_UID", + 0x00000010: "STATX_GID", + 0x00000020: "STATX_ATIME", + 0x00000040: "STATX_MTIME", + 0x00000080: "STATX_CTIME", + 0x00000100: "STATX_INO", + 0x00000200: "STATX_SIZE", + 0x00000400: "STATX_BLOCKS", + 0x000007FF: "STATX_BASIC_STATS", + 0x00000800: "STATX_BTIME", + 0x00001000: "STATX_MNT_ID", + 0x00002000: "STATX_DIOALIGN", + 0x00004000: "STATX_MNT_ID_UNIQUE", + 0x00008000: "STATX_SUBVOL", + 0x00010000: "STATX_WRITE_ATOMIC", + 0x00020000: "STATX_DIO_READ_ALIGN", + } + + RSEQ_FLAGS = { + 0x00000001: "RSEQ_FLAG_UNREGISTER", + } + + PIDFD_SEND_SIGNAL_FLAGS = { + 0b0001: "PIDFD_SIGNAL_THREAD", + 0b0010: "PIDFD_SIGNAL_THREAD_GROUP", + 0b0100: "PIDFD_SIGNAL_PROCESS_GROUP", + } + + OPENTREE_FLAGS = { + 0x1000: "AT_EMPTY_PATH", + 0x800: "AT_NO_AUTOMOUNT", + 0x8000: "AT_RECURSIVE", + 0x100: "AT_SYMLINK_NOFOLLOW", + 0x1: "OPEN_TREE_CLONE", + 0o2000000: "OPEN_TREE_CLOEXEC", + } + + MOVE_MOUNT_FLAGS = { + 0x00000001: "MOVE_MOUNT_F_SYMLINKS", + 0x00000002: "MOVE_MOUNT_F_AUTOMOUNTS", + 0x00000004: "MOVE_MOUNT_F_EMPTY_PATH", + 0x00000010: "MOVE_MOUNT_T_SYMLINKS", + 0x00000020: "MOVE_MOUNT_T_AUTOMOUNTS", + 0x00000040: "MOVE_MOUNT_T_EMPTY_PATH", + 0x00000100: "MOVE_MOUNT_SET_GROUP", + 0x00000200: "MOVE_MOUNT_BENEATH", + } + + FSOPEN_FLAGS = { + 0x00000001: "FSOPEN_CLOEXEC", + } + + FSCONFIG_CMDS = { + 0: "FSCONFIG_SET_FLAG", + 1: "FSCONFIG_SET_STRING", + 2: "FSCONFIG_SET_BINARY", + 3: "FSCONFIG_SET_PATH", + 4: "FSCONFIG_SET_PATH_EMPTY", + 5: "FSCONFIG_SET_FD", + 6: "FSCONFIG_CMD_CREATE", + 7: "FSCONFIG_CMD_RECONFIGURE", + 8: "FSCONFIG_CMD_CREATE_EXCL", + "parsing_mode": "sequential", + } + + FSMOUNT_FLAGS = { + 0x00000001: "FSMOUNT_CLOEXEC", + } + + FSMOUNT_ATTR_FLAGS = { + 0x00000001: "MOUNT_ATTR_RDONLY", + 0x00000002: "MOUNT_ATTR_NOSUID", + 0x00000004: "MOUNT_ATTR_NODEV", + 0x00000008: "MOUNT_ATTR_NOEXEC", + 0x00000070: "MOUNT_ATTR__ATIME", + 0x00000000: "MOUNT_ATTR_RELATIME", + 0x00000010: "MOUNT_ATTR_NOATIME", + 0x00000020: "MOUNT_ATTR_STRICTATIME", + 0x00000080: "MOUNT_ATTR_NODIRATIME", + 0x00100000: "MOUNT_ATTR_IDMAP", + 0x00200000: "MOUNT_ATTR_NOSYMFOLLOW", + } + + FSPICK_FLAGS = { + 0x00000001: "FSPICK_CLOEXEC", + 0x00000002: "FSPICK_SYMLINK_NOFOLLOW", + 0x00000004: "FSPICK_NO_AUTOMOUNT", + 0x00000008: "FSPICK_EMPTY_PATH", + } + + PIDFD_OPEN_FLAGS = { + 0o00004000: "PIDFD_NONBLOCK", + 0o00000200: "PIDFD_THREAD", + } + + CLOSE_RANGE_FLAGS = { + 0b000000010: "CLOSE_RANGE_UNSHARE", + 0b000000100: "CLOSE_RANGE_CLOEXEC", + } + + FACCESSAT_FLAGS = { + 0x200: "AT_EACCESS", + 0x1000: "AT_EMPTY_PATH", + 0x100: "AT_SYMLINK_NOFOLLOW", + } + + MOUNT_SETATTR_FLAGS = { + 0x100: "AT_SYMLINK_NOFOLLOW", + 0x800: "AT_NO_AUTOMOUNT", + 0x1000: "AT_EMPTY_PATH", + 0x8000: "AT_RECURSIVE", + } + + LANDLOCK_CREATE_RULESET_FLAGS = { + 1: "LANDLOCK_CREATE_RULESET_VERSION", + } + + LANDLOCK_ADD_RULE_TYPES = { + 1: "LANDLOCK_RULE_PATH_BENEATH", + 2: "LANDLOCK_RULE_NET_PORT", + } + + MEMFD_SECRET_FLAGS = { + 0x00000001: "FD_CLOEXEC", + } + + FCHMODAT_FLAGS = { + 0x100: "AT_SYMLINK_NOFOLLOW", + } + + MAP_SHADOW_STACK_FLAGS = { + 1: "SHADOW_STACK_SET_TOKEN", + 2: "SHADOW_STACK_SET_MARKER", + } + + LISTMOUNT_FLAGS = { + 1: "LISTMOUNT_REVERSE", + } + + LSM_GET_SELF_ATTR_FLAGS = { + 0x0001: "LSM_FLAG_SINGLE", + } + + XATTRAT_FLAGS = { + 0x100: "AT_SYMLINK_NOFOLLOW", + 0x1000: "AT_EMPTY_PATH", + } + + MSGGET_KEYS = { + 0: "IPC_PRIVATE", + } + + MSGGET_FLAGS = { + 0o0001000: "IPC_CREAT", + 0o0002000: "IPC_EXCL", + } + + MSGSND_FLAGS = { + 0o0004000: "IPC_NOWAIT", + } + + MSGRCV_FLAGS = { + 0o010000: "MSG_NOERROR", + 0o020000: "MSG_EXCEPT", + 0o040000: "MSG_COPY", + 0o0004000: "IPC_NOWAIT", + } + + MSGCTL_CMDS = { + 0: "IPC_RMID", + 1: "IPC_SET", + 2: "IPC_STAT", + 3: "IPC_INFO", + 11: "MSG_STAT", + 12: "MSG_INFO", + 13: "MSG_STAT_ANY", + "parsing_mode": "sequential", + } + + IO_URING_ENTER_FLAGS = { + 0b00000001: "IORING_ENTER_GETEVENTS", + 0b00000010: "IORING_ENTER_SQ_WAKEUP", + 0b00000100: "IORING_ENTER_SQ_WAIT", + 0b00001000: "IORING_ENTER_EXT_ARG", + 0b00010000: "IORING_ENTER_REGISTERED_RING", + 0b00100000: "IORING_ENTER_ABS_TIMER", + 0b01000000: "IORING_ENTER_EXT_ARG_REG", + 0b10000000: "IORING_ENTER_NO_IOWAIT", + } + + IO_URING_REGISTER_OPCODES = { + "sequential_flags": { + 0: "IORING_REGISTER_BUFFERS", + 1: "IORING_UNREGISTER_BUFFERS", + 2: "IORING_REGISTER_FILES", + 3: "IORING_UNREGISTER_FILES", + 4: "IORING_REGISTER_EVENTFD", + 5: "IORING_UNREGISTER_EVENTFD", + 6: "IORING_REGISTER_FILES_UPDATE", + 7: "IORING_REGISTER_EVENTFD_ASYNC", + 8: "IORING_REGISTER_PROBE", + 9: "IORING_REGISTER_PERSONALITY", + 10: "IORING_UNREGISTER_PERSONALITY", + 11: "IORING_REGISTER_RESTRICTIONS", + 12: "IORING_REGISTER_ENABLE_RINGS", + 13: "IORING_REGISTER_FILES2", + 14: "IORING_REGISTER_FILES_UPDATE2", + 15: "IORING_REGISTER_BUFFERS2", + 16: "IORING_REGISTER_BUFFERS_UPDATE", + 17: "IORING_REGISTER_IOWQ_AFF", + 18: "IORING_UNREGISTER_IOWQ_AFF", + 19: "IORING_REGISTER_IOWQ_MAX_WORKERS", + 20: "IORING_REGISTER_RING_FDS", + 21: "IORING_UNREGISTER_RING_FDS", + 22: "IORING_REGISTER_PBUF_RING", + 23: "IORING_UNREGISTER_PBUF_RING", + 24: "IORING_REGISTER_SYNC_CANCEL", + 25: "IORING_REGISTER_FILE_ALLOC_RANGE", + 26: "IORING_REGISTER_PBUF_STATUS", + 27: "IORING_REGISTER_NAPI", + 28: "IORING_UNREGISTER_NAPI", + 29: "IORING_REGISTER_CLOCK", + 30: "IORING_REGISTER_CLONE_BUFFERS", + 31: "IORING_REGISTER_SEND_MSG_RING", + 32: "IORING_REGISTER_ZCRX_IFQ", + 33: "IORING_REGISTER_RESIZE_RINGS", + 34: "IORING_REGISTER_MEM_REGION", + }, + "or_flags": {0x80000000: "IORING_REGISTER_USE_REGISTERED_RING"}, + "parsing_mode": "mixed", + } + + FUTEX2_FLAGS = { + 128: "FUTEX_PRIVATE_FLAG", + "parsing_mode": "sequential", + } + + TIMER_CREATE_WHICH_CLOCK = { + 0: "CLOCK_REALTIME", + 1: "CLOCK_MONOTONIC", + 2: "CLOCK_PROCESS_CPUTIME_ID", + 3: "CLOCK_THREAD_CPUTIME_ID", + 5: "CLOCK_REALTIME_COARSE", + 7: "CLOCK_BOOTTIME", + 8: "CLOCK_REALTIME_ALARM", + 9: "CLOCK_BOOTTIME_ALARM", + 11: "CLOCK_TAI", + "parsing_mode": "sequential", + } + + def parse_fcntl_arg(self: GnuConstants, cmd: int, arg: int) -> str: + """ + Parse the fcntl command. + + Args: + cmd (int): The fcntl command. + arg (int): The argument to parse. + + Returns: + str: The parsed command. + """ + match cmd: + case 2: # F_SETFD + if arg == 1: + return "FD_CLOEXEC" + return f"{arg:#x}" + case 4: # F_SETFL + REDUCED_MAP = { + 0o00002000: "O_APPEND", + 0o00020000: "O_ASYNC", + 0o00040000: "O_DIRECT", + 0o01000000: "O_NOATIME", + 0o00004000: "O_NONBLOCK", + } + return or_parse(REDUCED_MAP, arg) + case 10: # F_SETSIG + return sequential_parse(GnuConstants.SIGNALS, arg) + case 1024: # F_SETLEASE + LEASES = { + 0: "F_RDLCK", + 1: "F_WRLCK", + 2: "F_UNLCK", + } + return sequential_parse(LEASES, arg) + case 1026: # F_NOTIFY + NOTIFY_FLAGS = { + 0x00000001: "DN_ACCESS", + 0x00000002: "DN_MODIFY", + 0x00000004: "DN_CREATE", + 0x00000008: "DN_DELETE", + 0x00000010: "DN_RENAME", + 0x00000020: "DN_ATTRIB", + 0x80000000: "DN_MULTISHOT", + } + return or_parse(NOTIFY_FLAGS, arg) + case 1033: # F_ADD_SEALS + SEALS = { + 0x0001: "F_SEAL_SEAL", + 0x0002: "F_SEAL_SHRINK", + 0x0004: "F_SEAL_GROW", + 0x0008: "F_SEAL_WRITE", + 0x0010: "F_SEAL_FUTURE_WRITE", + 0x0020: "F_SEAL_EXEC", + } + return or_parse(SEALS, arg) + case 1038: # F_SET_FILE_RW_HINT + RW_HINTS = { + 0: "RWH_WRITE_LIFE_NOT_SET", + 1: "RWH_WRITE_LIFE_NONE", + 2: "RWH_WRITE_LIFE_SHORT", + 3: "RWH_WRITE_LIFE_MEDIUM", + 4: "RWH_WRITE_LIFE_LONG", + 5: "RWH_WRITE_LIFE_EXTREME", + } + return sequential_parse(RW_HINTS, arg) + case _: + return f"{arg:#x}" diff --git a/libdebug/utils/libcontext.py b/libdebug/utils/libcontext.py index 7bfe7741a..af4105b1a 100644 --- a/libdebug/utils/libcontext.py +++ b/libdebug/utils/libcontext.py @@ -23,6 +23,7 @@ class LibContext: _debugger_logger_levels: list[str] _general_logger_levels: list[str] _debuginfod_server: str + _parse_pprint_constants: bool def __new__(cls: type): """Create a new instance of the class if it does not exist yet. @@ -68,6 +69,8 @@ def __init__(self: LibContext) -> None: self._terminal = [] + self._parse_pprint_constants = True + def _set_debug_level_for_all(self: LibContext) -> None: """Set the debug level for all the loggers to DEBUG.""" for logger in [ @@ -200,6 +203,23 @@ def update(self: LibContext, **kwargs: ...) -> None: if hasattr(self, key): setattr(self, key, value) + @property + def parse_pprint_constants(self: LibContext) -> bool: + """Property getter for parse_pprint_constants. + + Returns: + _parse_pprint_constants (bool): the current parse_pprint_constants value. + """ + return self._parse_pprint_constants + + @parse_pprint_constants.setter + def parse_pprint_constants(self: LibContext, value: bool) -> None: + """Property setter for parse_pprint_constants, ensuring it's a boolean.""" + if not isinstance(value, bool): + raise TypeError("parse_pprint_constants must be a boolean") + + self._parse_pprint_constants = value + @contextmanager def tmp(self: LibContext, **kwargs: ...) -> ...: """Context manager that temporarily changes the library context. Use "with" statement.""" diff --git a/libdebug/utils/parsing_utils.py b/libdebug/utils/parsing_utils.py new file mode 100644 index 000000000..470149888 --- /dev/null +++ b/libdebug/utils/parsing_utils.py @@ -0,0 +1,70 @@ +# +# This file is part of libdebug Python library (https://github.com/libdebug/libdebug). +# Copyright (c) 2025 Francesco Panebianco, Roberto Alessandro Bertolini. All rights reserved. +# Licensed under the MIT license. See LICENSE file in the project root for details. +# + + +def or_parse(arg_map: dict, value: int) -> str: + """Parse the syscall argument value using OR logic. + + Args: + arg_map (dict): The argument map containing mnemonics and masks. + value (int): The syscall argument value. + + Returns: + str: The parsed syscall argument value. + """ + # At this point than one mnemonic is likely + out_mnemonic = "" + + masked_bits = 0x000000000000000000 + + for mnemonic_mask, mnemonic in arg_map.items(): + if not isinstance(mnemonic_mask, int): + # If the mask is not an integer, skip it + # it's string metadata + continue + + if mnemonic_mask == 0 and value != 0: + # If the mask is 0 and the syscall argument value is not 0, skip it + continue + + # Check if the syscall argument value matches the mnemonic mask + if mnemonic_mask & value == mnemonic_mask: + if len(out_mnemonic) == 0: + out_mnemonic = mnemonic + else: + out_mnemonic += f" | {mnemonic}" + + masked_bits |= mnemonic_mask + + # If not all bits are masked, add the remaining bits to the mnemonic in OR + if ~masked_bits & value != 0 and len(out_mnemonic) > 0: + out_mnemonic += " | " + f"{value & ~masked_bits:#08x}" + + if out_mnemonic != "": + out_mnemonic += f" ({value:#x})" + + return out_mnemonic + + +def sequential_parse(arg_map: dict, value: int) -> str: + """Parse the syscall argument value using sequential logic. + + Args: + arg_map (dict): The argument map containing mnemonics and masks. + value (int): The syscall argument value. + + Returns: + str: The parsed syscall argument value. + """ + out_mnemonic = arg_map.get(value, None) + + if out_mnemonic != None: + out_mnemonic += f" ({value:#x})" + else: + # If the value is not found in the map, return the default value + out_mnemonic = f"{value:#x}" + + return out_mnemonic diff --git a/libdebug/utils/pprint_primitives.py b/libdebug/utils/pprint_primitives.py index af9f72f95..c04c84520 100644 --- a/libdebug/utils/pprint_primitives.py +++ b/libdebug/utils/pprint_primitives.py @@ -12,6 +12,7 @@ from libdebug.snapshots.memory.memory_map_snapshot_list import MemoryMapSnapshotList from libdebug.utils.ansi_escape_codes import ANSIColors from libdebug.utils.debugging_utils import resolve_symbol_name_in_maps_util +from libdebug.utils.parsing_utils import or_parse, sequential_parse def pprint_maps_util(maps: MemoryMapList | MemoryMapSnapshotList) -> None: