def write_check_syscall_numbers(f):
    for name, obj in syscalls.all():
        # XXX hard-coded to x86 currently
        if not obj.x86:
            continue
        f.write("""static_assert(X86Arch::%s == SYS_%s, "Incorrect syscall number for %s");\n"""
                % (name, name, name))
Example #2
0
def write_is_always_emulated_syscall(f):
    semantics_to_retval = {
        syscalls.ReplaySemantics.EMU: 'true',
        syscalls.ReplaySemantics.EXEC: 'false',
        syscalls.ReplaySemantics.MAY_EXEC: 'false'
    }

    f.write(
        "template <typename Arch> static bool is_always_emulated_syscall_arch(int syscall);\n"
    )
    f.write("\n")
    for specializer, arch in [("X86Arch", "x86"), ("X64Arch", "x64")]:
        f.write(
            "template<> bool is_always_emulated_syscall_arch<%s>(int syscallno) {\n"
            % specializer)
        f.write("  switch (syscallno) {\n")
        for name, obj in syscalls.all():
            f.write("    case %s::%s: return %s;\n" %
                    (specializer, name, semantics_to_retval[obj.semantics]))
        f.write("    default:\n")
        f.write("      FATAL() << \"Unknown syscall \" << syscallno;\n")
        f.write("      return true;\n")
        f.write("  }\n")
        f.write("}\n")
        f.write("\n")
def write_syscall_helper_functions(f):
    def write_helpers(syscall):
        subs = { 'syscall': syscall }
        f.write(has_syscall.safe_substitute(subs))
        f.write(is_syscall.safe_substitute(subs))
        f.write(syscall_number.safe_substitute(subs))

    for name, obj in syscalls.all():
        write_helpers(name)
def write_syscall_record_cases(f):
    def write_recorder_for_arg(syscall, arg):
        arg_descriptor = getattr(syscall, 'arg' + str(arg), None)
        if isinstance(arg_descriptor, str):
            f.write("    syscall_state.reg_parameter<%s>(%d);\n"
                    % (arg_descriptor, arg))
    for name, obj in syscalls.all():
        # Irregular syscalls will be handled by hand-written code elsewhere.
        if isinstance(obj, syscalls.RegularSyscall):
            f.write("  case Arch::%s:\n" % name)
            for arg in range(1,6):
                write_recorder_for_arg(obj, arg)
            f.write("    return PREVENT_SWITCH;\n")
def write_syscall_enum_for_tests(f, arch):
    f.write("enum Syscalls {\n")
    undefined_syscall = -1
    for name, obj in sorted(syscalls.all(), key=lambda x: arch_syscall_number(arch, x)):
        syscall_number = getattr(obj, arch)
        if syscall_number is not None:
            enum_number = syscall_number
        else:
            enum_number = undefined_syscall
            undefined_syscall -= 1
        f.write("  RR_%s = %d,\n" % (name, enum_number))
    f.write("};\n")
    f.write("\n")
Example #6
0
def write_syscall_consts_for_tests(f, arch):
    f.write("// This file has been autogenerated. DO NOT MODIFY!\n")
    undefined_syscall = -1
    for name, obj in sorted(syscalls.all(),
                            key=lambda x: arch_syscall_number(arch, x)):
        syscall_number = getattr(obj, arch)
        if syscall_number is not None:
            enum_number = syscall_number
        else:
            enum_number = undefined_syscall
            undefined_syscall -= 1
        f.write("pub const RR_%s = %d,\n" % (name.upper(), enum_number))
    f.write("\n")
Example #7
0
def write_syscall_consts(f, arch, mode):
    f.write("// This file has been autogenerated. DO NOT MODIFY!\n")
    undefined_syscall = -1
    valid_syscalls = 0
    invalid_syscalls = 0
    for name, obj in sorted(syscalls.all(),
                            key=lambda x: arch_syscall_number(arch, x)):
        syscall_number = getattr(obj, arch)
        if syscall_number is not None:
            enum_number = syscall_number
            valid_syscalls += 1
        else:
            enum_number = undefined_syscall
            undefined_syscall -= 1
            invalid_syscalls += 1
        if mode == SyscallGen.CONST_ASSERTS:
            if arch == 'x86':
                f.write("const_assert_eq!(X86Arch::%s, %d);\n" %
                        (name.upper(), enum_number))
            elif arch == 'x64':
                f.write("const_assert_eq!(X64Arch::%s, %d);\n" %
                        (name.upper(), enum_number))
        elif mode == SyscallGen.DEFAULT:
            f.write("pub const %s: i32 = %d;\n" % (name.upper(), enum_number))
        elif mode == SyscallGen.TRAIT:
            f.write("const %s: i32;\n" % (name.upper()))
        elif mode == SyscallGen.TRAIT_IMPL:
            f.write("const %s: i32 = %d;\n" % (name.upper(), enum_number))
    if mode == SyscallGen.CONST_ASSERTS:
        if arch == 'x86':
            f.write("const_assert_eq!(X86Arch::VALID_SYSCALL_COUNT, %d);\n" %
                    (valid_syscalls))
            f.write("const_assert_eq!(X86Arch::INVALID_SYSCALL_COUNT, %d);\n" %
                    (invalid_syscalls))
        elif arch == 'x64':
            f.write("const_assert_eq!(X64Arch::VALID_SYSCALL_COUNT, %d);\n" %
                    (valid_syscalls))
            f.write("const_assert_eq!(X64Arch::INVALID_SYSCALL_COUNT, %d);\n" %
                    (invalid_syscalls))
    elif mode == SyscallGen.DEFAULT:
        f.write("pub const VALID_SYSCALL_COUNT: i32 = %d;\n" %
                (valid_syscalls))
        f.write("pub const INVALID_SYSCALL_COUNT: i32 = %d;\n" %
                (invalid_syscalls))
    elif mode == SyscallGen.TRAIT:
        f.write("const VALID_SYSCALL_COUNT: i32;\n")
        f.write("const INVALID_SYSCALL_COUNT: i32;\n")
    elif mode == SyscallGen.TRAIT_IMPL:
        f.write("const VALID_SYSCALL_COUNT: i32 = %d;\n" % (valid_syscalls))
        f.write("const INVALID_SYSCALL_COUNT: i32 = %d;\n" %
                (invalid_syscalls))
Example #8
0
def write_syscall_enum(f, arch):
    f.write("enum Syscalls {\n")
    undefined_syscall = -1
    for name, obj in sorted(syscalls.all(), key=lambda x: getattr(x[1], arch)):
        syscall_number = getattr(obj, arch)
        if syscall_number is not None:
            enum_number = syscall_number
        else:
            enum_number = undefined_syscall
            undefined_syscall -= 1
        f.write("  %s = %d,\n" % (name, enum_number))
    f.write("  SYSCALL_COUNT,\n")
    f.write("};\n")
    f.write("\n")
Example #9
0
def write_syscall_enum(f, arch):
    f.write("enum Syscalls {\n")
    undefined_syscall = -1
    for name, obj in sorted(syscalls.all(), key=lambda x: getattr(x[1], arch)):
        syscall_number = getattr(obj, arch)
        if syscall_number is not None:
            enum_number = syscall_number
        else:
            enum_number = undefined_syscall
            undefined_syscall -= 1
        f.write("  %s = %d,\n" % (name, enum_number))
    f.write("  SYSCALL_COUNT,\n")
    f.write("};\n")
    f.write("\n")
Example #10
0
def write_check_syscall_numbers(f):
    f.write("""use crate::arch::{Architecture, X86Arch, X64Arch};\n""")
    f.write("""use crate::kernel_abi::common::preload_interface;\n""")
    for name, obj in syscalls.all():
        # @TODO hard-coded to x64 currently
        # @TODO Note this is different from rr where it is hardcoded to x86
        if not obj.x64:
            continue
        if name.startswith("rdcall_"):
            f.write(
                """const_assert_eq!(X64Arch::%s, preload_interface::SYS_%s as i32);\n"""
                % (name.upper(), name))
        else:
            f.write(
                """const_assert_eq!(X64Arch::%s, libc::SYS_%s as i32);\n""" %
                (name.upper(), name))
Example #11
0
def write_syscall_helper_functions(f):
    def write_helpers(syscall):
        no_snake_case = ''
        if syscall.startswith('_') or syscall.endswith('_'):
            no_snake_case = '\n#[allow(non_snake_case)]'
        subs = {
            'syscall': syscall,
            'syscall_upper': syscall.upper(),
            'no_snake_case': no_snake_case
        }
        f.write(has_syscall.safe_substitute(subs))
        f.write(is_syscall.safe_substitute(subs))
        f.write(syscall_number.safe_substitute(subs))

    f.write("// This file has been autogenerated. DO NOT MODIFY!\n")
    f.write("use SupportedArch::*;\n")
    for name, obj in syscalls.all():
        write_helpers(name)
Example #12
0
def write_is_always_emulated_syscall(f):
    semantics_to_retval = { syscalls.ReplaySemantics.EMU: 'true',
                            syscalls.ReplaySemantics.EXEC: 'false',
                            syscalls.ReplaySemantics.MAY_EXEC: 'false' }

    f.write("template <typename Arch> static bool is_always_emulated_syscall_arch(int syscall);\n");
    f.write("\n");
    for specializer, arch in [("X86Arch", "x86"), ("X64Arch", "x64")]:
        f.write("template<> bool is_always_emulated_syscall_arch<%s>(int syscallno) {\n" % specializer)
        f.write("  switch (syscallno) {\n")
        for name, obj in syscalls.all():
            f.write("    case %s::%s: return %s;\n"
                    % (specializer, name, semantics_to_retval[obj.semantics]))
        f.write("    default:\n")
        f.write("      FATAL() << \"Unknown syscall \" << syscallno;\n")
        f.write("      return true;\n")
        f.write("  }\n")
        f.write("}\n")
        f.write("\n")
Example #13
0
def write_syscall_record_cases(f):
    def write_recorder_for_arg(syscall, arg):
        arg_descriptor = getattr(syscall, 'arg' + str(arg), None)
        if isinstance(arg_descriptor, str):
            f.write(
                "        syscall_state.reg_parameter::<%s>(%d, None, None);\n"
                % (arg_descriptor, arg))

    f.write("// This file has been autogenerated. DO NOT MODIFY!\n")
    f.write("{\n")
    f.write("    use crate::kernel_abi::common;\n")
    f.write("    use crate::kernel_abi::x64;\n")
    for name, obj in syscalls.all():
        # Irregular syscalls will be handled by hand-written code elsewhere.
        if isinstance(obj, syscalls.RegularSyscall):
            f.write("    if sys == Arch::%s {\n" % name.upper())
            for arg in range(1, 6):
                write_recorder_for_arg(obj, arg)
            f.write("        return Switchable::PreventSwitch;\n")
            f.write("    }\n")
    f.write("}\n")
Example #14
0
def write_syscall_record_cases(f):
    def write_recorder_for_arg(syscall, arg):
        arg_descriptor = getattr(syscall, arg, None)
        if arg_descriptor is None:
            return
        if isinstance(arg_descriptor, str):
            f.write("    t->record_remote(remote_ptr<%s>(t->regs().%s()));\n" % (arg_descriptor, arg))
        elif isinstance(arg_descriptor, syscalls.DynamicSize):
            f.write("    t->record_remote(remote_ptr<void>(t->regs().%s()), %s);\n" % (arg, arg_descriptor.size_expr))
        elif isinstance(arg_descriptor, syscalls.NullTerminatedString):
            f.write("    t->record_remote_str(remote_ptr<void>(t->regs().%s()));\n" % arg)
        else:
            # Not reached
            assert None

    for name, obj in syscalls.all():
        # Irregular syscalls will be handled by hand-written code elsewhere.
        if isinstance(obj, syscalls.RegularSyscall):
            f.write("  case Arch::%s:\n" % name)
            for arg in syscalls.RegularSyscall.ARGUMENT_SLOTS:
                write_recorder_for_arg(obj, arg)
            f.write("    break;\n")