1 /*
2  * Copyright (c) 2011 The Chromium Authors. All rights reserved.
3  * Use of this source code is governed by a BSD-style license that can be
4  * found in the LICENSE file.
5  */
6 
7 #include <stddef.h>
8 #include <stdlib.h>
9 #include <string.h>
10 #include <unistd.h>
11 
12 #include "native_client/src/include/elf32.h"
13 #include "native_client/src/include/elf_auxv.h"
14 #include "native_client/src/untrusted/irt/irt.h"
15 #include "ppapi/nacl_irt/public/irt_ppapi.h"
16 #include "ppapi/native_client/src/shared/ppapi_proxy/ppruntime.h"
17 #include "ppapi/native_client/src/untrusted/irt_stub/thread_creator.h"
18 
fatal_error(const char * message)19 static void fatal_error(const char *message) {
20   ssize_t wrote __attribute__((unused));
21   wrote = write(2, message, strlen(message));
22   _exit(127);
23 }
24 
25 /*
26  * TODO(mcgrathr): This extremely stupid function should not exist.
27  * If the startup calling sequence were sane, this would be done
28  * someplace that has the initial pointer locally rather than stealing
29  * it from environ.
30  * See http://code.google.com/p/nativeclient/issues/detail?id=651
31  */
find_auxv(void)32 static Elf32_auxv_t *find_auxv(void) {
33   /*
34    * This presumes environ has its startup-time value on the stack.
35    */
36   char **ep = environ;
37   while (*ep != NULL)
38     ++ep;
39   return (void *) (ep + 1);
40 }
41 
42 /*
43  * Scan the auxv for AT_SYSINFO, which is the pointer to the IRT query function.
44  * TODO(mcgrathr): Could get this from __nacl_irt_query, where the libnacl
45  * startup code stored it, but that would have to be also added as part of
46  * the glibc ABI.
47  */
grok_auxv(const Elf32_auxv_t * auxv)48 static TYPE_nacl_irt_query grok_auxv(const Elf32_auxv_t *auxv) {
49   const Elf32_auxv_t *av;
50   for (av = auxv; av->a_type != AT_NULL; ++av) {
51     if (av->a_type == AT_SYSINFO)
52       return (TYPE_nacl_irt_query) av->a_un.a_val;
53   }
54   return NULL;
55 }
56 
PpapiPluginStart(const struct PP_StartFunctions * funcs)57 int PpapiPluginStart(const struct PP_StartFunctions *funcs) {
58   TYPE_nacl_irt_query query_func = grok_auxv(find_auxv());
59 
60   if (NULL == query_func)
61     fatal_error("PpapiPluginStart: No AT_SYSINFO item found in auxv, "
62                 "so cannot start PPAPI.  Is the IRT library not present?\n");
63 
64   struct nacl_irt_ppapihook hooks;
65   if (sizeof(hooks) != query_func(NACL_IRT_PPAPIHOOK_v0_1,
66                                   &hooks, sizeof(hooks)))
67     fatal_error("PpapiPluginStart: PPAPI hooks not found\n");
68 
69   __nacl_register_thread_creator(&hooks);
70 
71   return hooks.ppapi_start(funcs);
72 }
73