示例#1
0
def build_proc_of_protocol(g, syscalls):
    procs = []
    for syscall in syscalls:
        if drop_prefix(syscall.name) in g.manually_defined_syscalls:
            continue

        fmt = """private class {proc} extends CommandDispatcher.Proc {{

        public void call(Command command) throws IOException, SigkillException {{
            PayloadSize payloadSize = mIn.readPayloadSize();
            {decls};
            {params}
            SyscallResult.{rettype} result = mSlave.do{name}({args});
            writeResult(Command.{cmd}, result);
        }}
    }}"""
        proc = make_proc(syscall)
        decls = make_params_declarations(syscall)
        params = make_params_reading(syscall)
        rettype = rettype_class_of_syscall(syscall)
        name = make_class_prefix(syscall)
        args = make_params_passing(syscall)
        cmd = syscall.ret_name
        procs.append(fmt.format(**locals()))

    return ("\n\n" + make_indent(4)).join(procs)
示例#2
0
def print_fslave_head(p, syscall):
    args = ["struct slave_thread *slave_thread", "int *retval", "int *errnum"]
    for a in syscall.output_args:
        args.append(make_formal_arguments_of_execute_call(syscall, a))

    name = drop_prefix(syscall.name)
    print_caution(p)
    p("""\
#include <sys/types.h>
#include <sys/event.h>
#include <sys/resource.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/uio.h>
#include <sys/wait.h>
#include <errno.h>
#include <fcntl.h>
#include <signal.h>
#include <stdlib.h>
#include <unistd.h>

#include <fsyscall/private.h>
#include <fsyscall/private/command.h>
#include <fsyscall/private/encode.h>
#include <fsyscall/private/fslave.h>
#include <fsyscall/private/io.h>
#include <fsyscall/private/io_or_die.h>

static void
execute_call({args})
{{
""".format(args=", ".join(args)))
示例#3
0
def write_fslave(dirpath, syscalls):
    for syscall in [sc for sc in syscalls if sc.name in FSLAVE_SYSCALLS]:
        name = drop_prefix(syscall.name)
        path = join(dirpath, "fslave_{name}.c".format(**locals()))
        with open(path, "w") as fp:
            p, print_newline = partial_print(fp)
            print_fslave_head(p, syscall)
            print_fslave_call(p, print_newline, syscall)
            print_newline()
            if 0 < len(syscall.output_args):
                print_fslave_return(p, print_newline, syscall)
                print_newline()
            print_fslave_main(p, print_newline, syscall)
示例#4
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)
示例#5
0
def build_syscall_results(g, syscalls):
    stmts = []
    for syscall in syscalls:
        if syscall.name in g.manually_defined_syscalls:
            continue
        if len(syscall.output_args) == 0:
            continue
        name = drop_prefix(syscall.name).capitalize()
        size = datasize_of_datatype(syscall.rettype)
        base = "Generic{size}".format(**locals())
        members = build_members_of_result(syscall)

        stmts.append("""public static class {name} extends {base} {{

        {members};
    }}""".format(**locals()))

    return "\n\n    ".join(stmts)
示例#6
0
def print_wrapper(p, print_newline, syscall):
    name = syscall.name
    syscall_name = drop_prefix(name)
    fmt_args = make_args_format(syscall)
    args = make_log_args(syscall)
    p("""
int
sys_{name}(struct thread *td, struct {name}_args *uap)
{{
\tstruct timeval time_start;
\tint error;

\tfmaster_log(td, LOG_DEBUG, \"{syscall_name}: started{fmt_args}\"{args});
\tmicrotime(&time_start);

\terror = {name}_main(td, uap);

\tfmaster_log_syscall_end(td, \"{syscall_name}\", &time_start, error);

\treturn (error);
}}
""".format(**locals()))
示例#7
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()))
示例#8
0
def write_dummy(dirpath, name):
    with open(join(dirpath, "{name}.c".format(**locals())), "w") as fp:
        syscall = drop_prefix(name)
        print("""\
/*
 * Dummy implementation generated automatically. DO NOT EDIT THIS!
 */
#include <sys/param.h>
#include <sys/proc.h>
#include <sys/syslog.h>
#include <sys/systm.h>

#include <fsyscall/private/fmaster.h>
#include <sys/fmaster/fmaster_proto.h>

int
sys_{name}(struct thread *td, struct {name}_args *uap)
{{

\tfmaster_log(td, LOG_DEBUG, \"{syscall}: this is a dummy, unimplemented.\");

\treturn (ENOSYS);
}}""".format(**locals()), file=fp)
示例#9
0
def write_proto(dirpath, syscalls):
    try:
        mkdir(dirpath)
    except OSError:
        pass
    with open(join(dirpath, "proto.h"), "w") as fp:
        p, print_newline = partial_print(fp)
        print_caution(p)
        p("""\
#if !defined(FSYSCALL_PRIVATE_FSLAVE_PROTO_H_INCLUDED)
#define FSYSCALL_PRIVATE_FSLAVE_PROTO_H_INCLUDED
""")
        print_newline()
        for syscall in syscalls:
            if syscall.name not in FSLAVE_SYSCALLS:
                continue
            p("""\
void process_{name}(struct slave_thread *);
""".format(name=drop_prefix(syscall.name)))
        print_newline()
        p("""\
#endif
""")
示例#10
0
def print_master_call(p, print_newline, syscall):
    a = find_file_descriptor_argument(syscall)
    if a is None:
        return
    name = drop_prefix(syscall.name)
    p("""\
\terror = fmaster_get_vnode_info(td, uap->{a}, &place, &lfd);
\tif (error != 0)
\t\treturn (error);
\tswitch (place) {{
\tcase FFP_MASTER: {{
\t\tstruct {name}_args a;
\t\tmemcpy(&a, uap, sizeof(a));
\t\ta.{a} = lfd;
\t\terror = sys_{name}(td, &a);
\t\tif (error != 0)
\t\t\treturn (error);
""".format(**locals()))
    if syscall.post_common:
        p("""\
\t\terror = fmaster_{name}_post_common(td, uap);
\t\tif (error != 0)
\t\t\treturn (error);
""".format(**locals()))
    p("""\
\t\treturn (0);
\t\t}}
\tcase FFP_SLAVE:
\t\tbreak;
\tcase FFP_PENDING_SOCKET:
\t\tfmaster_log(td, LOG_INFO, "{name}: called for a pending socket: fd=%d, lfd=%d", uap->{a}, lfd);
\t\treturn (ENOTCONN);
\tdefault:
\t\treturn (EBADF);
\t}}
""".format(**locals()))
    print_newline()
示例#11
0
def make_class_prefix(syscall):
    return drop_prefix(syscall.name).title()
示例#12
0
def build_proc_of_writing_result(syscalls):
    stmts = []
    for syscall in syscalls:
        rettype = rettype_class_of_syscall(syscall)
        if rettype in ["Generic32", "Generic64"]:
            continue

        name = drop_prefix(syscall.name)
        if name == "readlink":
            d = { "annotation": name, "name": name.capitalize() }
            stmts.append("""private void writeResult(Command command, SyscallResult.{name} result) throws IOException {{
        String fmt = \"result ({annotation}): retval=%d, errno=%s\";
        mLogger.info(fmt, result.retval, result.errno);

        writeError(command, result);
    }}""".format(**d))
            continue

        if name in ["fstat", "lstat", "stat"]:
            d = {
                    "annotation": name,
                    "name": name.capitalize(),
                    "out": syscall.output_args[0].name }
            stmts.append("""private void writeResult(Command command, SyscallResult.{name} result) throws IOException {{
        String logHead = \"result ({annotation})\";

        if (result.retval == -1) {{
            String fmt = \"%s: retval=%d, errno=%s\";
            Errno errno = result.errno;
            mLogger.info(fmt, logHead, result.retval, errno);

            writeError(command, result);
            return;
        }}

        mLogger.info(\"%s: retval=%d\", logHead, result.retval);

        Payload payload = new Payload();
        payload.add(result.retval);
        payload.add(result.{out});

        writePayload(command, payload);
    }}""".format(**d))
            continue

        if name in ["pread", "read"]:
            d = { "annotation": name, "rettype": rettype }
            stmts.append("""private void writeResult(Command command, SyscallResult.{rettype} result) throws IOException {{
        String logHead = \"result ({annotation})\";

        if (result.retval == -1) {{
            String fmt = \"%s: retval=%d, errno=%s\";
            Errno errno = result.errno;
            mLogger.info(fmt, logHead, result.retval, errno);

            writeError(command, result);
            return;
        }}

        mLogger.info(\"%s: retval=%d\", logHead, result.retval);

        Payload payload = new Payload();
        payload.add(result.retval);
        payload.add(result.buf);

        writePayload(command, payload);
    }}""".format(**d))
            continue

    return "\n\n    ".join(stmts)
示例#13
0
def rettype_class_of_syscall(syscall):
    if len(syscall.output_args) == 0:
        fmt = "Generic{size}"
        return fmt.format(size=datasize_of_datatype(syscall.rettype))
    return drop_prefix(syscall.name).capitalize()
示例#14
0
 def get_const_name(self):
     return drop_prefix(self.name).upper()
示例#15
0
def print_fslave_call(p, print_newline, syscall):
    local_vars = []
    for datatype, name in (
            ("sigset_t", "oset"),
            ("payload_size_t", "payload_size"),
            ("payload_size_t", "actual_payload_size"),
            ("int", "rfd")):
        local_vars.append(Variable(datatype, name))
    input_arguments = syscall.input_args
    for a in input_arguments:
        if a.datatype == "void *":
            local_vars.append(Variable(a.datatype, a.name))
            continue

        if a.datatype == "struct iovec *":
            for datatype, name in (
                    (a.datatype, a.name),
                    ("payload_size_t *", "{name}_iov_len_len"),
                    ("int", "i"),
                    ("payload_size_t", "{name}_payload_size")):
                local_vars.append(Variable(datatype, name.format(**vars(a))))
            continue

        for datatype, name in (
                ("payload_size_t", "{name}_len"),
                ("{datatype}", "{name}")):
            d = vars(a)
            v = Variable(datatype.format(**d), name.format(**d))
            local_vars.append(v)

    print_locals(p, local_vars)
    print_newline()
    p("""\
\trfd = slave_thread->fsth_rfd;
\tpayload_size = read_payload_size(rfd);
""")
    print_newline()
    for a in syscall.input_args:
        name = a.name
        if a.datatype == "void *":
            size = SYSCALLS[syscall.name][name].size
            p("""\
\t{name} = alloca({size});
\tread_or_die(rfd, {name}, {size});
""".format(**locals()))
            continue

        if a.datatype == "struct iovec *":
            name = a.name
            size = data_of_argument(syscall, a).size
            p("""\
\t{name} = (struct iovec *)alloca(sizeof(*{name}) * {size});
\t{name}_iov_len_len = (payload_size_t *)alloca(sizeof(int) * {size});
\tfor (i = 0; i < {size}; i++) {{
\t\t{name}[i].iov_len = read_uint64(rfd, &{name}_iov_len_len[i]);
\t\t{name}[i].iov_base = alloca({name}[i].iov_len);
\t\tread_or_die(rfd, {name}[i].iov_base, {name}[i].iov_len);
\t}}
""".format(**locals()))
            continue

        f = {
                "char *": "read_string",
                "long": "read_int64",
                "int": "read_int32",
                "u_int": "read_uint32",
                "off_t": "read_int64",
                "size_t": "read_uint64" }[a.datatype]
        assignment = "{name} = {f}(rfd, &{name}_len)".format(**locals())
        opt = opt_of_syscall(FSLAVE_SYSCALLS, syscall, a)
        if opt is not None:
            p("""\
\tif ({opt})
\t\t{assignment};
\telse
\t\t{name} = {name}_len = 0;
""".format(**locals()))
        else:
            p("""\
\t{assignment};
""".format(**locals()))
    if 0 < len(syscall.args):
        print_newline()

    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()))
        continue

    payload_size = make_fslave_payload_size_expr(syscall)
    p("""\
\tactual_payload_size = {payload_size};
\tdie_if_payload_size_mismatched(payload_size, actual_payload_size);
""".format(**locals()))
    print_newline()

    malloced = False
    out_arguments = syscall.output_args
    for a in out_arguments:
        data = data_of_argument(syscall, a)
        if not data.is_array:
            continue
        name = a.name
        datatype = a.datatype
        size = data.size
        p("""\
\t*{name} = ({datatype})malloc({size});
""".format(**locals()))
        malloced = True
    if malloced:
        print_newline()

    args = []
    for a in syscall.args:
        data = data_of_argument(syscall, a)
        ast = (1 if data.out and data.is_array else 0) * "*"
        args.append("{ast}{name}".format(ast=ast, name=a.name))
    p("""\
\tsuspend_signal(slave_thread, &oset);
\t*retval = {name}({args});
\t*errnum = errno;
\tresume_signal(slave_thread, &oset);
""".format(name=drop_prefix(syscall.name), args=", ".join(args)))

    for a in syscall.args:
        if (a.datatype != "char *") or data_of_argument(syscall, a).out:
            continue
        p("""\
\tfree({name});
""".format(**vars(a)))
    p("""\
}}
""".format(**locals()))