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