Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1677)

Unified Diff: sysdeps/nacl/receive_args.c

Issue 7282019: Adjust for new NaCl startup ABI (Closed) Base URL: http://git.chromium.org/native_client/nacl-glibc.git@master
Patch Set: Created 9 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: sysdeps/nacl/receive_args.c
diff --git a/sysdeps/nacl/receive_args.c b/sysdeps/nacl/receive_args.c
index bf67f3f76f3d7a386713fab8a0da1c58be865d7f..995eea2f1b43bc16d3204921420be3185e25aaed 100644
--- a/sysdeps/nacl/receive_args.c
+++ b/sysdeps/nacl/receive_args.c
@@ -3,11 +3,14 @@
#include <assert.h>
#include <errno.h>
+#include <elf.h>
#include <string.h>
#include <sys/mman.h>
#include <unistd.h>
+#include <ldsodefs.h>
#include <nacl_rpc.h>
+#include <nacl_syscalls.h>
/* We expect to receive an IMC message with the following format:
@@ -41,21 +44,9 @@ struct args_message
char string_data[];
};
-struct process_args
-{
- int received_size;
- struct args_message message;
-};
-
#define MESSAGE_SIZE_MAX 0x10000
-static void fail (const char *message)
-{
- __write (2, message, strlen (message));
- _exit (127);
-}
-
/* The NaCl plugin blocks waiting for us to accept an SRPC connection.
If we reject the connection, the "onload" Javascript hook is not run.
See http://code.google.com/p/nativeclient/issues/detail?id=1501
@@ -111,7 +102,7 @@ static int keep_plugin_happy (int socket_fd)
/* Send reply, listing no SRPC methods. */
struct NaClImcMsgIoVec send_iov = {
- srpc_reply_message,
+ (void *) srpc_reply_message,
sizeof (srpc_reply_message)
};
struct NaClImcMsgHdr send_message = { &send_iov, 1, NULL, 0, 0 };
@@ -158,7 +149,7 @@ static void decode_hex (unsigned char *dest, int *dest_size,
*dest_size = src_size / 2;
}
-struct process_args *argmsg_fetch ()
+uint32_t *argmsg_fetch (uint32_t *info)
{
/* The NaCl browser plugin does not give us a good way to detect
that we are running under it. We detect that we are running
@@ -192,129 +183,110 @@ struct process_args *argmsg_fetch ()
{
/* We are not running under the NaCl browser plugin or in a
similar environment. */
- return NULL;
+ return info;
}
keep_plugin_happy (socket_fd);
- struct process_args *args =
- mmap (NULL, MESSAGE_SIZE_MAX, PROT_READ | PROT_WRITE,
- MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
- if (args == MAP_FAILED)
- fail ("Failed to allocate memory to receive startup message\n");
- struct NaClImcMsgIoVec iov;
- struct NaClImcMsgHdr message;
- iov.base = (void *) &args->message;
- iov.length = MESSAGE_SIZE_MAX - offsetof (struct process_args, message);
- message.iov = &iov;
- message.iov_length = 1;
- message.descv = NULL;
- message.desc_length = 0;
- message.flags = 0;
- args->received_size = imc_recvmsg (NACL_PLUGIN_ASYNC_TO_CHILD_FD,
- &message, 0);
+
+ union
+ {
+ unsigned char buffer[MESSAGE_SIZE_MAX];
+ struct args_message message;
+ } msgbuf;
+
+ struct NaClImcMsgIoVec iov = { .base = &msgbuf, .length = sizeof(msgbuf) };
+ struct NaClImcMsgHdr message = { .iov = &iov, .iov_length = 1 };
+
+ int received_size = imc_recvmsg (NACL_PLUGIN_ASYNC_TO_CHILD_FD,
+ &message, 0);
/* As a workaround for a limitation in the NaCl plugin, allow the
message to be hex-encoded. This is because __sendAsyncMessage*()
does not support null bytes in messages.
See http://code.google.com/p/nativeclient/issues/detail?id=1535
TODO(mseaborn): Fix this limitation. */
- if (args->received_size >= 4 &&
- memcmp (args->message.tag, "HEXD", 4) == 0)
- decode_hex ((unsigned char *) &args->message, &args->received_size,
- (unsigned char *) &args->message + 4, args->received_size - 4);
-
- if (args->received_size < 0)
- fail ("Error receiving startup message\n");
- if (args->received_size < 4 ||
- memcmp (args->message.tag, "ARGS", 4) != 0)
- fail ("Startup message does not have the expected tag\n");
- if (args->received_size < offsetof (struct args_message, string_data))
- fail ("Startup message too small\n");
- /* Check for an attempt to allocate too much space on the stack. */
- if (args->message.argc > MESSAGE_SIZE_MAX ||
- args->message.envc > MESSAGE_SIZE_MAX ||
- args->message.argc + args->message.envc > MESSAGE_SIZE_MAX)
- fail ("argv/env too large\n");
- return args;
-}
-
-static size_t arrays_size (struct process_args *args)
-{
- return (sizeof(argc_type) +
- sizeof(char *) * (args->message.argc + 1 +
- args->message.envc + 1 +
- 2 /* for empty auxv */));
-}
-
-static size_t strings_size (struct process_args *args)
-{
- return args->received_size - offsetof (struct args_message, string_data);
-}
-
-size_t argmsg_get_size_on_stack (struct process_args *args)
-{
- return arrays_size (args) + strings_size (args);
-}
-
-void argmsg_move_to_stack (struct process_args *args,
- void *buf, size_t buf_size)
-{
- char *buf_end = (char *) buf + buf_size;
- char *strings = (char *) buf + arrays_size (args);
- memcpy (strings, args->message.string_data, strings_size (args));
-
- *(argc_type *) buf = args->message.argc;
- char **dest = (char **) ((char *) buf + sizeof(argc_type));
- char *next_str = strings;
- int i;
- /* Set up argv array */
- for (i = 0; i < args->message.argc; i++)
+ if (received_size >= 4 &&
+ memcmp (msgbuf.message.tag, "HEXD", 4) == 0)
+ decode_hex (msgbuf.buffer, &received_size,
+ &msgbuf.buffer[4], received_size - 4);
+
+ if (received_size < 0)
+ _dl_fatal_printf ("Error receiving startup message (%u)\n", errno);
+ if (received_size < 4 ||
+ memcmp (msgbuf.message.tag, "ARGS", 4) != 0)
+ _dl_fatal_printf ("Startup message (%u bytes) lacks the expected tag\n",
+ received_size);
+ if (received_size < offsetof (struct args_message, string_data))
+ _dl_fatal_printf ("Startup message too small (%u bytes)\n", received_size);
+
+ /* Count the original auxv size so we know how big to make the new buffer. */
+ size_t nauxv = 0;
+ Elf32_auxv_t *const auxv = (void *) &info[3 + info[2] + 1 + info[1] + 1];
+ Elf32_auxv_t *av = auxv;
+ do
+ ++nauxv;
+ while (av++->a_type != AT_NULL);
+
+ /* Allocate a new information block in the heap.
+ We will pass this pointer to the user program rather than
+ the original argument (which was a pointer onto our stack). */
+ size_t infosize = ((3 + msgbuf.message.argc + 1 +
+ msgbuf.message.envc + 1) * sizeof(uint32_t) +
+ nauxv * sizeof(Elf32_auxv_t) +
+ (received_size -
+ offsetof (struct args_message, string_data)));
+ uint32_t *newinfo = __mmap (NULL, infosize, PROT_READ|PROT_WRITE,
+ MAP_PRIVATE|MAP_ANON, -1, 0);
+ if (newinfo == NULL)
+ _dl_fatal_printf ("Cannot allocate %u bytes for startup information\n",
+ infosize);
+
+ /* Fill in the new information block.
+ We replace the arguments and environment with what we got from IPC,
+ and copy the rest from the original block. */
+ newinfo[0] = info[0];
+ newinfo[1] = msgbuf.message.envc;
+ newinfo[2] = msgbuf.message.argc;
+
+ /* Copy the auxiliary vector, which sits after the string vectors. */
+ char **argv = (char **) &newinfo[3];
+ char **envp = &argv[msgbuf.message.argc + 1];
+ char *copy = __mempcpy (&envp[msgbuf.message.envc + 1],
+ auxv, nauxv * sizeof(auxv[0]));
+
+ /* Now copy the strings into place and fill in the string vectors. */
+ const char *p = msgbuf.message.string_data;
+ const char *endp = (char *) &msgbuf.buffer[received_size];
+
+ /* First, the argument vector. */
+ for (int i = 0; i < msgbuf.message.argc; ++i)
{
- *dest++ = next_str;
- next_str = (char *) memchr (next_str, 0, buf_end - next_str);
- if (next_str == NULL)
- fail ("Missing null terminator in argv list\n");
- next_str++;
+ const char *elt_end = memchr (p, '\0', endp - p);
+ if (elt_end == NULL)
+ _dl_fatal_printf ("Unterminated argument string in startup message\n");
+ ++elt_end;
+ argv[i] = copy;
+ copy = __mempcpy (copy, p, elt_end - p);
+ p = elt_end;
}
- *dest++ = NULL;
- /* Set up environment array */
- for (i = 0; i < args->message.envc; i++)
+ argv[msgbuf.message.argc] = NULL;
+
+ /* Finally, the environment vector. */
+ for (int i = 0; i < msgbuf.message.envc; ++i)
{
- *dest++ = next_str;
- next_str = (char *) memchr (next_str, 0, buf_end - next_str);
- if (next_str == NULL)
- fail ("Missing null terminator in env list\n");
- next_str++;
+ const char *elt_end = memchr (p, '\0', endp - p);
+ if (elt_end == NULL)
+ _dl_fatal_printf ("\
+Unterminated environment string in startup message\n");
+ ++elt_end;
+ envp[i] = copy;
+ copy = __mempcpy (copy, p, elt_end - p);
+ p = elt_end;
}
- *dest++ = NULL;
- /* Set up an empty auxv */
- *dest++ = NULL;
- *dest++ = NULL;
- if ((char *) dest != strings)
- fail ("Internal error: mismatch in array size\n");
- if (next_str != buf_end)
- fail ("Excess data in message body\n");
-
- if (munmap (args, MESSAGE_SIZE_MAX) != 0)
- fail ("Failed to munmap() startup message\n");
-}
+ envp[msgbuf.message.envc] = NULL;
-void jump_to_elf_start (void *buf, uintptr_t entry_func, uintptr_t atexit_func)
-{
- /* The ELF entry point ABI is such that assembly code is required to
- call the entry point.
- See http://code.google.com/p/nativeclient/issues/detail?id=1131
- TODO(mseaborn): Switch to using the normal function call ABI. */
-#if defined(__i386__)
- __asm__ ("mov %0, %%esp\n"
- "nacljmp %1\n"
- : : "m" (buf), "r" (entry_func),
- "d" (atexit_func) /* %edx */);
-#elif defined(__x86_64__)
- __asm__ ("naclrestsp %0, %%r15\n"
- "nacljmp %1, %%r15\n"
- : : "m" (buf), "r" (entry_func),
- "d" (atexit_func) /* %rdx */);
-#else
-# error Unsupported architecture
-#endif
+ if (p != endp)
+ _dl_fatal_printf ("Excess data (%u bytes) in startup message body\n",
+ endp - p);
+
+ return newinfo;
}
« make_sysd_rules.py ('K') | « sysdeps/nacl/receive_args.h ('k') | sysdeps/nacl/start.c » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698