Index: src/untrusted/irt/irt_pnacl_translator_compile.c |
diff --git a/src/untrusted/irt/irt_pnacl_translator_compile.c b/src/untrusted/irt/irt_pnacl_translator_compile.c |
new file mode 100644 |
index 0000000000000000000000000000000000000000..c77c7a11f5bed09f188ce7e1f405d8095e63344a |
--- /dev/null |
+++ b/src/untrusted/irt/irt_pnacl_translator_compile.c |
@@ -0,0 +1,118 @@ |
+/* |
+ * Copyright (c) 2015 The Native Client Authors. All rights reserved. |
+ * Use of this source code is governed by a BSD-style license that can be |
+ * found in the LICENSE file. |
+ */ |
+ |
+#include "native_client/src/shared/platform/nacl_log.h" |
+#include "native_client/src/shared/srpc/nacl_srpc.h" |
+#include "native_client/src/untrusted/irt/irt_dev.h" |
+#include "native_client/src/untrusted/irt/irt_interfaces.h" |
+ |
+#include <argz.h> |
+#include <string.h> |
+ |
+static const int kMaxObjectFiles = 16; |
+ |
+static const struct nacl_irt_pnacl_compile_funcs *g_funcs; |
+ |
+static void stream_init_with_split( |
+ NaClSrpcRpc *rpc, NaClSrpcArg **in_args, |
+ NaClSrpcArg **out_args, NaClSrpcClosure *done) { |
+ int num_threads = in_args[0]->u.ival; |
+ if (num_threads < 0 || num_threads > kMaxObjectFiles) { |
+ NaClLog(LOG_FATAL, "Invalid # of threads (%d)\n", num_threads); |
+ } |
+ int fd_start = 1; |
+ int i = fd_start; |
+ int num_valid_fds = 0; |
+ int obj_fds[kMaxObjectFiles]; |
+ while (num_valid_fds < kMaxObjectFiles && in_args[i]->u.hval >= 0) { |
+ obj_fds[num_valid_fds] = in_args[i]->u.hval; |
+ ++i; |
+ ++num_valid_fds; |
+ } |
+ /* |
+ * Convert the null-delimited strings into an array of |
+ * null-terminated strings. |
+ */ |
+ char *cmd_argz = in_args[kMaxObjectFiles + fd_start]->arrays.carr; |
+ size_t cmd_argz_len = in_args[kMaxObjectFiles + fd_start]->u.count; |
+ size_t argc = argz_count(cmd_argz, cmd_argz_len); |
+ char **argv = (char **)malloc((argc + 1) * sizeof(char *)); |
+ argz_extract(cmd_argz, cmd_argz_len, argv); |
+ char *result = g_funcs->init_callback(num_threads, obj_fds, num_valid_fds, |
+ argv, argc); |
+ free(argv); |
+ if (result != NULL) { |
+ rpc->result = NACL_SRPC_RESULT_APP_ERROR; |
+ /* |
+ * SRPC wants to free() the string, so just strdup here so that the |
+ * init_callback implementation doesn't have to know if the string |
+ * comes from malloc or new. On error, we don't care so much |
+ * about leaking this bit of memory. |
+ */ |
+ out_args[0]->arrays.str = strdup(result); |
+ } else { |
+ rpc->result = NACL_SRPC_RESULT_OK; |
+ out_args[0]->arrays.str = strdup(""); |
+ } |
+ done->Run(done); |
+} |
+ |
+static void stream_chunk(NaClSrpcRpc *rpc, NaClSrpcArg **in_args, |
+ NaClSrpcArg **out_args, NaClSrpcClosure *done) { |
+ int result = g_funcs->data_callback( |
+ in_args[0]->arrays.carr, |
+ in_args[0]->u.count); |
+ rpc->result = result == 0 ? NACL_SRPC_RESULT_OK : NACL_SRPC_RESULT_APP_ERROR; |
+ done->Run(done); |
+} |
+ |
+static void stream_end(NaClSrpcRpc *rpc, NaClSrpcArg **in_args, |
+ NaClSrpcArg **out_args, NaClSrpcClosure *done) { |
+ char *result = g_funcs->end_callback(); |
+ /* Fill in the deprecated return values with dummy values. */ |
+ out_args[0]->u.ival = 0; |
+ out_args[1]->arrays.str = strdup(""); |
+ out_args[2]->arrays.str = strdup(""); |
+ if (result != NULL) { |
+ rpc->result = NACL_SRPC_RESULT_APP_ERROR; |
+ /* SRPC wants to free(), so strdup() and leak to hide this detail. */ |
+ out_args[3]->arrays.str = strdup(result); |
+ } else { |
+ rpc->result = NACL_SRPC_RESULT_OK; |
+ out_args[3]->arrays.str = strdup(""); |
+ } |
+ done->Run(done); |
+} |
+ |
+static const struct NaClSrpcHandlerDesc srpc_methods[] = { |
+ /* |
+ * Protocol for streaming: |
+ * StreamInitWithSplit(num_threads, obj_fd x 16, cmdline_flags) -> error_str |
+ * StreamChunk(data) + |
+ * TODO(jvoung): remove these is_shared_lib, etc. |
+ * StreamEnd() -> (is_shared_lib, soname, dependencies, error_str) |
+ */ |
+ { "StreamInitWithSplit:ihhhhhhhhhhhhhhhhC:s", stream_init_with_split }, |
+ { "StreamChunk:C:", stream_chunk }, |
+ { "StreamEnd::isss", stream_end }, |
+ { NULL, NULL }, |
+}; |
+ |
+static void serve_translate_request( |
+ const struct nacl_irt_pnacl_compile_funcs *funcs) { |
+ g_funcs = funcs; |
+ if (!NaClSrpcModuleInit()) { |
+ NaClLog(LOG_FATAL, "NaClSrpcModuleInit() failed\n"); |
+ } |
+ if (!NaClSrpcAcceptClientConnection(srpc_methods)) { |
+ NaClLog(LOG_FATAL, "NaClSrpcAcceptClientConnection() failed\n"); |
+ } |
+} |
+ |
+const struct nacl_irt_private_pnacl_translator_compile |
+ nacl_irt_private_pnacl_translator_compile = { |
+ serve_translate_request |
+}; |