def _process_fchownat(s: Syscall) -> CanonicalForm:
    return CanonicalForm('chown', [
        get_full_path(_get_value(s.arguments[0]), _get_value(s.arguments[1])),
        _get_value(s.arguments[2]),
        _get_value(s.arguments[3]),
        _get_value(s.arguments[4]),
    ])
 def _default_process_at(self, s: Syscall):
     path = get_full_path(s.arguments[0].value.value,
                          s.arguments[1].value.value)
     if isinstance(path, tuple):
         _, path = path
     if path.startswith('/etc/') and path.endswith(f'.{s.pid}'):
         s.arguments[1].value.value = path[:-len(str(s.pid))] + 'PID'
def _process_execveat(s: Syscall) -> CanonicalForm:
    path = Path(get_full_path(
        _get_value(s.arguments[0]),
        _get_value(s.arguments[1])
    ))
    return CanonicalForm('execve', [
        path.name,
        _get_value(s.arguments[2])[1:]
    ])
def _process_unlinkat(s: Syscall) -> CanonicalForm:
    dir_fd = _get_value(s.arguments[0])
    pathname = _get_value(s.arguments[1])
    s_flags = _get_value(s.arguments[2])
    path = get_full_path(dir_fd, pathname)
    if int(s_flags) & flags.AT_REMOVEDIR:
        return CanonicalForm('rmdir', [path])
    else:
        return CanonicalForm('unlink', [path])
def _process_openat(s: Syscall) -> CanonicalForm:
    # The mode is required when opening with the flags O_CREATE or O_TMPFILE.
    # Check flags for equality because TMPFILE is composed of multiple values.
    arg2 = s.arguments[2].value
    if isinstance(arg2, SyntheticValue):
        f = _get_value(arg2.original_value)
    else:
        f = _get_value(arg2)
    create = f & flags.O_CREAT == flags.O_CREAT
    tmpfile = f & flags.O_TMPFILE == flags.O_TMPFILE
    if create or tmpfile:
        return CanonicalForm('open', [
            get_full_path(
                _get_value(s.arguments[0]), _get_value(s.arguments[1])
            ),
            _get_value(s.arguments[3])
        ])
    else:
        return CanonicalForm('open', [
            get_full_path(
                _get_value(s.arguments[0]), _get_value(s.arguments[1])
            ),
        ])
    def _process_openat(self, s: Syscall, fd: Dict[int, str]):
        # Do nothing if open failed
        if s.exit_code == -1:
            return

        # Get parameters
        dir_fd = s.arguments[0].value.value
        path = s.arguments[1].value.value

        # Record file descriptor
        fd[s.exit_code] = get_full_path(dir_fd, path)

        # Replace dir_fd
        if dir_fd in fd:
            s.arguments[0].value = StringLiteral(fd[dir_fd])
def _process_mkdirat(s: Syscall) -> CanonicalForm:
    return CanonicalForm('mkdir', [
        get_full_path(_get_value(s.arguments[0]), _get_value(s.arguments[1])),
        _get_value(s.arguments[2])
    ])
def _process_linkat(s: Syscall) -> CanonicalForm:
    return CanonicalForm('link', [
        get_full_path(_get_value(s.arguments[0]), _get_value(s.arguments[1])),
        get_full_path(_get_value(s.arguments[2]), _get_value(s.arguments[3]))
    ])
def _process_utimensat(s: Syscall) -> CanonicalForm:
    return CanonicalForm('utimensat', [
        get_full_path(_get_value(s.arguments[0]), _get_value(s.arguments[1]))
    ])