def print_encoding(p, syscall): for a in syscall.input_args: if a.datatype == "void *": continue if data_of_argument(syscall, a).fd: fmt = "{name} = lfd" else: fmt = "{name} = uap->{name}" p("\t" + fmt.format(**vars(a)) + ";\n") if a.datatype == "struct iovec *": concrete_datatype = concrete_datatype_of_abstract_datatype("size_t") size = data_of_argument(syscall, a).size name = a.name p("""\ \t{name}_iov_len_buf = (char (*)[FSYSCALL_BUFSIZE_UINT64])malloc( \t\tsizeof(char [FSYSCALL_BUFSIZE_UINT64]) * {size}, \t\tM_TEMP, \t\tM_WAITOK); \t{name}_iov_len_len = (int *)malloc( \t\tsizeof(u_int) * iovcnt, \t\tM_TEMP, \t\tM_WAITOK); \tfor (i = 0; i < iovcnt; i++) {{ \t\t{name}_iov_len_len[i] = fsyscall_encode_{concrete_datatype}( \t\t\t{name}[i].iov_len, \t\t\t{name}_iov_len_buf[i], \t\t\tarray_sizeof({name}_iov_len_buf[i])); \t\tif ({name}_iov_len_len[i] < 0) \t\t\treturn (EMSGSIZE); \t}} """.format(**locals())) continue if a.datatype == "char *": p("""\ \t{name}_len = strlen({name}); """.format(name=a.name)) name = "{name}_len".format(**vars(a)) else: name = a.name concrete_datatype = concrete_datatype_of_abstract_datatype(a.datatype) opt = opt_of_syscall(FMASTER_SYSCALLS, syscall, a) if opt is not None: expr_head = "{opt} ? ".format(**locals()) expr_tail = " : 0" else: expr_head = expr_tail = "" p("""\ \t{name}_len = {expr_head}fsyscall_encode_{concrete_datatype}( \t\t{name}, \t\t{name}_buf, \t\tarray_sizeof({name}_buf)){expr_tail}; \tif ({name}_len < 0) \t\treturn (EMSGSIZE); """.format(**locals()))
def make_args_format(syscall): msgs = [] msg_fmt = "{name}={fmt}" for a in syscall.args: name = a.name if a in syscall.output_args: fmt = "%p" msgs.append(msg_fmt.format(**locals())) continue datatype = a.datatype if datatype[-1] == "*": fmt = "\\\"%s\\\"" if datatype == "char *" else "%p" msgs.append(msg_fmt.format(**locals())) continue type_ = concrete_datatype_of_abstract_datatype(datatype) fmt = { "int32": "%d", "uint32": "%u", "int64": "%ld", "uint64": "%lu" }[type_] msgs.append(msg_fmt.format(**locals())) s = ", ".join(msgs) return ": {s}".format(**locals()) if 0 < len(s) else ""
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()))
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()))