示例#1
0
def write_cases(path, syscalls, suffix):
    with open(path, "w") as fp:
        p, _ = partial_print(fp)
        for syscall in syscalls:
            if syscall.name not in SYSCALLS:
                continue
            cmd = make_cmd_name(syscall.name)
            p("""\
\tcase {cmd}_{suffix}:
""".format(**locals()))
        write_c_footer(p)
示例#2
0
def write_dispatch(dirpath, syscalls):
    with open(join(dirpath, "dispatch.inc"), "w") as fp:
        p, _ = partial_print(fp)
        for syscall in syscalls:
            if syscall.name not in SYSCALLS:
                continue
            cmd = make_cmd_name(syscall.name)
            name = drop_prefix(syscall.name)
            p("""\
\t\t\tcase {cmd}_CALL:
\t\t\t\tprocess_{name}(slave_thread);
\t\t\t\tbreak;
""".format(**locals()))
        write_c_footer(p)
示例#3
0
def print_fslave_main(p, print_newline, syscall):
    name = drop_prefix(syscall.name)
    p("""\
void
process_{name}(struct slave_thread *slave_thread)
{{
""".format(**locals()))

    local_vars = []
    for datatype, name in (("int", "retval"), ("int", "errnum")):
        local_vars.append(Variable(datatype, name))

    out_arguments = syscall.output_args
    if len(out_arguments) == 0:
        cmd_name = make_cmd_name(syscall.name)
        print_locals(p, local_vars)
        print_newline()
        return_func = get_fslave_return_func(syscall)
        p("""\
\texecute_call(slave_thread, &retval, &errnum);
\t{return_func}(slave_thread, {cmd_name}_RETURN, retval, errnum);
}}
""".format(**locals()))
        return

    for a in out_arguments:
        data = data_of_argument(syscall, a)
        datatype = a.datatype if data.is_array else drop_pointer(a.datatype)
        local_vars.append(Variable(datatype, a.name))

    print_locals(p, local_vars)
    print_newline()
    call_args = ", ".join(["&{name}".format(**vars(a)) for a in out_arguments])
    ret_args = make_execute_return_actual_arguments(syscall, out_arguments)
    p("""\
\texecute_call(slave_thread, &retval, &errnum, {call_args});
\texecute_return(slave_thread, retval, errnum, {ret_args});
}}
""".format(**locals()))
示例#4
0
def print_generic_tail(p, print_newline, syscall):
    print_call_tail(p, print_newline)

    local_vars = make_basic_local_vars(syscall)
    name = syscall.name
    p("""\
static int
{name}_main(struct thread *td, struct {name}_args *uap)
{{
""".format(**locals()))
    print_locals(p, local_vars)
    print_newline()
    print_pre_execute(p, print_newline, syscall)
    print_master_call(p, print_newline, syscall)
    act_args = build_actual_args(syscall)
    cmd_name = make_cmd_name(name)
    bit_num = 32 if syscall.rettype == "int" else 64
    p("""\
\terror = execute_call({act_args});
\tif (error != 0)
\t\treturn (error);
\terror = fmaster_execute_return_generic{bit_num}(td, {cmd_name}_RETURN);
\tif (error != 0)
\t\treturn (error);
""".format(**locals()))
    print_post_execute(syscall, p)
    if syscall.post_common:
        p("""\
\terror = {name}_post_common(td, uap);
\tif (error != 0)
\t\treturn (error);
""".format(**locals()))
    p("""\
\treturn (0);
}}
""".format(**locals()))
    print_wrapper(p, print_newline, syscall)
示例#5
0
def print_execute_return(p, print_newline, syscall):
    name = syscall.name
    p("""\
static int
execute_return(struct thread *td, struct {name}_args *uap)
{{
""".format(**locals()))

    local_vars = []
    for datatype, name in (
            ("command_t", "cmd"),
            ("int", "errnum"),
            ("int", "errnum_len"),
            ("int", "error"),
            ("int", "retval_len"),
            ("int", "rfd"),
            ("payload_size_t", "expected_payload_size"),
            ("payload_size_t", "payload_size"),
            (syscall.rettype, "retval")):
        local_vars.append(Variable(datatype, name))
    out_arguments = syscall.output_args
    for a in out_arguments:
        if a.datatype in ("char *", "void *"):
            continue
        data = data_of_argument(syscall, a)
        st = data.struct
        if st is not None:
            local_vars.append(Variable(drop_pointer(a.datatype), a.name))

            for _, name in st.expand_all_members(a.name):
                n = "{name}_len".format(**locals())
                local_vars.append(Variable("int", n))
            continue
        assert data_of_argument(syscall, a).is_atom
        name = a.name
        local_vars.append(Variable("int", "{name}_len".format(**locals())))
        local_vars.append(Variable(drop_pointer(a.datatype), a.name))
    print_locals(p, local_vars)
    print_newline()

    cmd_name = make_cmd_name(syscall.name)
    t = concrete_datatype_of_abstract_datatype(syscall.rettype)
    p("""\
\terror = fmaster_read_command(td, &cmd);
\tif (error != 0)
\t\treturn (error);
\tif (cmd != {cmd_name}_RETURN) {{
\t\tfmaster_log(td, LOG_ERR, \"command mismatched: expected=%d, actual=%d\", {cmd_name}_RETURN, cmd);
\t\treturn (EPROTO);
\t}}
\terror = fmaster_read_payload_size(td, &payload_size);
\tif (error != 0)
\t\treturn (error);
\terror = fmaster_read_{t}(td, &retval, &retval_len);
\tif (error != 0)
\t\treturn (error);
\tif (retval == -1) {{
\t\terror = fmaster_read_int32(td, &errnum, &errnum_len);
\t\tif (error != 0)
\t\t\treturn (error);
\t\tif (retval_len + errnum_len != payload_size) {{
\t\tfmaster_log(td, LOG_ERR, \"payload size mismatched: expected=%d, actual=%d\", payload_size, retval_len + errnum_len);
\t\t\treturn (EPROTO);
\t\t}}
\t\treturn (errnum);
\t}}
""".format(**locals()))
    print_newline()
    p("""\
\trfd = fmaster_rfd_of_thread(td);
""")

    for a in out_arguments:
        if a.datatype in ("char *", "void *"):
            p("""\
\terror = fmaster_read_to_userspace(td, rfd, uap->{name}, {size});
\tif (error != 0)
\t\treturn (error);
""".format(name=a.name, size=data_of_argument(syscall, a).retsize))
            continue
        data = data_of_argument(syscall, a)
        st = data.struct
        if st is not None:
            for datatype, var, name in st.zip_members(a.name):
                t = concrete_datatype_of_abstract_datatype(datatype)
                p("""\
\terror = fmaster_read_{t}(td, &{name}, &{var}_len);
\tif (error != 0)
\t\treturn (error);
""".format(**locals()))
            continue
        assert data.is_atom
        t = concrete_datatype_of_abstract_datatype(drop_pointer(a.datatype))
        name = a.name
        p("""\
\terror = fmaster_read_{t}(td, &{name}, &{name}_len);
\tif (error != 0)
\t\treturn (error);
""".format(**locals()))
    print_newline()

    expected_payload_size = make_payload_size_expr(syscall, out_arguments, "retsize")
    p("""\
\texpected_payload_size = retval_len + {expected_payload_size};
\tif (expected_payload_size != payload_size) {{
\t\tfmaster_log(td, LOG_ERR, \"payload size mismatched: expected=%d, actual=%d\", expected_payload_size, payload_size);
\t\treturn (EPROTO);
\t}}
""".format(**locals()))
    print_newline()

    for a in syscall.output_args:
        data = data_of_argument(syscall, a)
        if data.is_array:
            continue
        p("""\
\tif (uap->{name} != NULL) {{
\t\terror = copyout(&{name}, uap->{name}, sizeof({name}));
\t\tif (error != 0)
\t\t\treturn (error);
\t}}
""".format(**vars(a)))
    p("""\
\ttd->td_retval[0] = retval;

\treturn (0);
}}
""".format(**locals()))
示例#6
0
def print_write(p, print_newline, syscall):
    cmd_name = make_cmd_name(syscall.name)
    p("""\
\terror = fmaster_write_command(td, {cmd_name}_CALL);
\tif (error != 0)
\t\treturn (error);
""".format(**locals()))

    input_arguments = syscall.input_args
    for a in [a for a in input_arguments if a.datatype == "struct iovec *"]:
        name = a.name
        size = data_of_argument(syscall, a).size
        p("""\
\t{name}_payload_size = 0;
\tfor (i = 0; i < {size}; i++)
\t\t{name}_payload_size += {name}_iov_len_len[i] + {name}[i].iov_len;
""".format(**locals()))

    payload_size_expr = make_payload_size_expr(syscall, input_arguments)
    p("""\
\tpayload_size = {payload_size_expr};
\terror = fmaster_write_payload_size(td, payload_size);
\tif (error != 0)
\t\treturn (error);
""".format(**locals()))
    if len(input_arguments) == 0:
        return

    p("""\
\twfd = fmaster_wfd_of_thread(td);
""".format(**locals()))
    for a in syscall.input_args:
        if a.datatype == "char *":
            buf = "{name}_len_buf".format(**vars(a))
            size = "{name}_len_len".format(**vars(a))
            print_fmaster_write(p, buf, size)
            print_fmaster_write(p, a.name, "{name}_len".format(**vars(a)))
            continue

        if a.datatype == "void *":
            name = a.name
            size = SYSCALLS[syscall.name][name].size
            p("""\
\terror = fmaster_write_from_userspace(td, wfd, uap->{name}, {size});
\tif (error != 0)
\t\treturn (error);
""".format(**locals()))
            continue

        if a.datatype == "struct iovec *":
            p("""\
\tfor (i = 0; i < iovcnt; i++) {{
""".format(**locals()))

            buf = "{name}_iov_len_buf[i]".format(**vars(a))
            size = "{name}_iov_len_len[i]".format(**vars(a))
            print_fmaster_write(p, buf, size, 2)

            buf = "{name}[i].iov_base".format(**vars(a))
            size = "{name}[i].iov_len".format(**vars(a))
            print_fmaster_write(p, buf, size, 2)

            p("""\
\t}}
""".format(**locals()))
            continue

        opt = opt_of_syscall(FMASTER_SYSCALLS, syscall, a)
        if opt is not None:
            p("""\
\tif (!({opt}))
\t\treturn (0);
""".format(**locals()))
        buf = "{name}_buf".format(**vars(a))
        size = "{name}_len".format(**vars(a))
        print_fmaster_write(p, buf, size)

    cleanup_args = [
            a
            for a in syscall.sending_order_args
            if a.datatype == "struct iovec *"]
    if len(cleanup_args) == 0:
        return
    print_newline()
    for a in cleanup_args:
        p("""\
\tfree({name}_iov_len_len, M_TEMP);
\tfree({name}_iov_len_buf, M_TEMP);
""".format(**vars(a)))
示例#7
0
def print_fslave_return(p, print_newline, syscall):
    output_args = syscall.output_args
    args = ", ".join([make_formal_arguments_of_execute_return(syscall, a)
                      for a in output_args])
    p("""\
static void
execute_return(struct slave_thread *slave_thread, int retval, int errnum, {args})
{{
""".format(**locals()))

    local_vars = [Variable(datatype, name, size) for datatype, name, size in (
        ("payload_size_t", "payload_size", None),
        ("char", "retval_buf", bufsize_of_datatype(syscall.rettype)),
        ("int", "retval_len", None),
        ("int", "wfd", None))]
    out_arguments = syscall.output_args
    for a in out_arguments:
        datatype = a.datatype
        if a.datatype in ("char *", "void *"):
            # in case of an array
            continue

        st = data_of_argument(syscall, a).struct
        append = local_vars.append
        if st is not None:
            for datatype, name in st.expand_all_members(a.name):
                fmt = "{name}_len"
                append(Variable("int", fmt.format(**locals())))

                fmt = "{name}_buf"
                size = bufsize_of_datatype(datatype)
                append(Variable("char", fmt.format(**locals()), size))
            continue

        name = a.name
        size = bufsize_of_datatype(drop_pointer(datatype))
        append(Variable("int", "{name}_len".format(**locals())))
        append(Variable("char", "{name}_buf".format(**locals()), size))

    print_locals(p, local_vars)
    print_newline()
    cmd_name = make_cmd_name(syscall.name)
    return_func = get_fslave_return_func(syscall)
    p("""\
\tif (retval == -1) {{
\t\t{return_func}(slave_thread, {cmd_name}_RETURN, retval, errnum);
\t\treturn;
\t}}
""".format(**locals()))
    print_newline()
    p("""\
\tretval_len = encode_{datatype}(retval, retval_buf, array_sizeof(retval_buf));
""".format(datatype=concrete_datatype_of_abstract_datatype(syscall.rettype)))
    for a in out_arguments:
        if a.datatype in ("char *", "void *"):
            continue
        st = data_of_argument(syscall, a).struct
        if st is not None:
            for datatype, var, name in st.zip_members(a.name, "->"):
                struct_name = a.name
                t = concrete_datatype_of_abstract_datatype(datatype)
                p("""\
\t{var}_len = encode_{t}({name}, {var}_buf, array_sizeof({var}_buf));
""".format(**locals()))
            continue
        name = a.name
        t = drop_pointer(a.datatype)
        datatype = concrete_datatype_of_abstract_datatype(t)
        p("""\
\t{name}_len = encode_{datatype}({name}, {name}_buf, sizeof({name}_buf));
""".format(**locals()))

    payload_size = make_payload_size_expr(syscall, out_arguments, "retsize")
    p("""\
\tpayload_size = retval_len + {payload_size};

\twfd = slave_thread->fsth_wfd;
\twrite_command(wfd, {cmd_name}_RETURN);
\twrite_payload_size(wfd, payload_size);
\twrite_or_die(wfd, retval_buf, retval_len);
""".format(**locals()))
    for a in out_arguments:
        if a.datatype in ("char *", "void *"):
            name = a.name
            size = data_of_argument(syscall, a).retsize
            p("""\
\twrite_or_die(wfd, {name}, {size});
""".format(**locals()))
            continue
        st = data_of_argument(syscall, a).struct
        if st is not None:
            for _, name in st.expand_all_members(a.name):
                p("""\
\twrite_or_die(wfd, {name}_buf, {name}_len);
""".format(**locals()))
            continue
        name = a.name
        p("""\
\twrite_or_die(wfd, {name}_buf, {name}_len);
""".format(**locals()))

    newlined = False
    for a in out_arguments:
        data = data_of_argument(syscall, a)
        if not data.is_array:
            continue
        if not newlined:
            print_newline()
            newlined = True
        p("""\
\tfree({name});
""".format(**vars(a)))
    p("""\
}}
""".format(**locals()))