2 * Copyright 2014 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.
8 * This is a minimal NaCl program without libc. It uses NaCl's stable IRT ABI.
13 #include "native_client/src/include/elf_auxv.h"
14 #include "native_client/src/untrusted/irt/irt.h"
15 #include "ppapi/c/pp_errors.h"
16 #include "ppapi/c/ppb_messaging.h"
17 #include "ppapi/c/ppb_var.h"
18 #include "ppapi/c/ppp_instance.h"
19 #include "ppapi/c/ppp_messaging.h"
20 #include "ppapi/nacl_irt/public/irt_ppapi.h"
22 static struct nacl_irt_basic __libnacl_irt_basic
;
23 static struct nacl_irt_random __libnacl_irt_random
;
24 static TYPE_nacl_irt_query __nacl_irt_query
;
25 static struct PPP_Instance_1_0 ppp_instance
;
26 static struct PPP_Messaging_1_0 ppp_messaging
;
27 static const struct PPB_Messaging_1_0
* ppb_messaging
;
28 static const struct PPB_Var_1_2
* ppb_var
;
31 * To support 64bit binary, we declare Elf_auxv_t by using uintptr_t.
32 * See also native_client/src/include/elf32.h.
42 * This is simiplar to the one in
43 * native_client/src/untrusted/nacl/nacl_startup.h, but also supports 64 bit
46 static Elf_auxv_t
* nacl_startup_auxv(const uintptr_t info
[]) {
47 /* The layout of _start's argument is
51 * info[3]...[3+argc]: argv (NULL terminated)
52 * info[3+argc+1]...[3+argc+1+envc]: envv (NULL terminated)
53 * info[3+argc+1+envc+1]: auxv pairs.
57 return (Elf_auxv_t
*) (info
+ 3 + envc
+ 1 + argc
+ 1);
60 static void grok_auxv(const Elf_auxv_t
* auxv
) {
62 for (av
= auxv
; av
->a_type
!= AT_NULL
; ++av
) {
63 if (av
->a_type
== AT_SYSINFO
) {
64 __nacl_irt_query
= (TYPE_nacl_irt_query
) av
->a_un
.a_val
;
69 #define DO_QUERY(ident, name) __nacl_irt_query(ident, &name, sizeof(name))
71 static int my_strcmp(const char* a
, const char* b
) {
78 return (int) (unsigned char) *a
- (int) (unsigned char) *b
;
81 static int my_strncmp(const char* a
, const char* b
, size_t n
) {
82 while (n
> 0 && *a
== *b
) {
92 return (int) (unsigned char) *a
- (int) (unsigned char) *b
;
95 static size_t my_strlen(const char* a
) {
102 static PP_Bool
DidCreate(PP_Instance instance
,
105 const char* argv
[]) {
109 static void DidDestroy(PP_Instance instance
) {
112 static void DidChangeView(PP_Instance instance
,
113 const struct PP_Rect
* position
,
114 const struct PP_Rect
* clip
) {
117 static void DidChangeFocus(PP_Instance instance
, PP_Bool has_focus
) {
120 static PP_Bool
HandleDocumentLoad(PP_Instance instance
,
121 PP_Resource url_loader
) {
125 static int32_t MyPPP_InitializeModule(PP_Module module_id
,
126 PPB_GetInterface get_browser_interface
) {
127 ppb_messaging
= get_browser_interface(PPB_MESSAGING_INTERFACE_1_0
);
128 ppb_var
= get_browser_interface(PPB_VAR_INTERFACE_1_2
);
132 static void MyPPP_ShutdownModule(void) {
135 static const void* MyPPP_GetInterface(const char* interface_name
) {
136 if (my_strcmp(interface_name
, PPP_INSTANCE_INTERFACE_1_0
) == 0)
137 return &ppp_instance
;
138 if (my_strcmp(interface_name
, PPP_MESSAGING_INTERFACE_1_0
) == 0)
139 return &ppp_messaging
;
143 static void PostStringMessage(PP_Instance instance
,
144 const char* message_string
) {
145 size_t message_length
= my_strlen(message_string
);
146 struct PP_Var message
= ppb_var
->VarFromUtf8(
147 message_string
, message_length
);
148 ppb_messaging
->PostMessage(instance
, message
);
149 ppb_var
->Release(message
);
152 static void TestRandom(PP_Instance instance
) {
153 // Javascript expects "randomsuccess", we will send back a different
154 // string via PostMessage to denote a failure, and that will be
155 // visible in the failure logs.
157 char random_buffer
[512];
159 // zero-clear the buffer.
160 for (i
= 0; i
< sizeof random_buffer
; ++i
) {
161 random_buffer
[i
] = 0;
165 if (__libnacl_irt_random
.get_random_bytes(random_buffer
,
166 sizeof random_buffer
,
168 PostStringMessage(instance
, "Get Random Bytes Failed.");
172 // Try to see if the buffer looks different from bunch of zeros.
173 if (read_len
!= sizeof random_buffer
) {
174 PostStringMessage(instance
, "Give me moar random bytes");
178 for (i
= 0; i
< sizeof random_buffer
; ++i
) {
179 if (random_buffer
[i
] == 0) {
183 if (num_zeroes
> 100) {
184 PostStringMessage(instance
, "Too many zeros in this random stream.");
188 PostStringMessage(instance
, "randomsuccess");
191 // Handle message from javascript, javascript side will tell me what
192 // kind of test it wants, and I will respond accordingly.
193 static void HandleMessage(PP_Instance instance
, struct PP_Var message
) {
194 if (!ppb_messaging
|| !ppb_var
|| message
.type
!= PP_VARTYPE_STRING
) {
195 __libnacl_irt_basic
.exit(1);
198 uint32_t message_len
;
199 const char* message_string
= ppb_var
->VarToUtf8(message
, &message_len
);
201 if (!my_strncmp("Message from Javascript to NaCl",
202 message_string
, message_len
)) {
203 // Reply back with what we received.
204 ppb_messaging
->PostMessage(instance
, message
);
205 } else if (!my_strncmp("random", message_string
, message_len
)) {
206 TestRandom(instance
);
208 // Unknown message came.
209 PostStringMessage(instance
, "Unknown message type");
213 void _start(uintptr_t info
[]) {
214 Elf_auxv_t
* auxv
= nacl_startup_auxv(info
);
216 DO_QUERY(NACL_IRT_BASIC_v0_1
, __libnacl_irt_basic
);
217 DO_QUERY(NACL_IRT_RANDOM_v0_1
, __libnacl_irt_random
);
219 struct nacl_irt_ppapihook ppapihook
;
220 DO_QUERY(NACL_IRT_PPAPIHOOK_v0_1
, ppapihook
);
222 /* This is local as a workaround to avoid having to apply
223 * relocations to global variables. */
224 struct PP_StartFunctions start_funcs
;
225 start_funcs
.PPP_InitializeModule
= MyPPP_InitializeModule
;
226 start_funcs
.PPP_ShutdownModule
= MyPPP_ShutdownModule
;
227 start_funcs
.PPP_GetInterface
= MyPPP_GetInterface
;
228 /* Similarly, initialize some global variables, avoiding relocations. */
229 ppp_instance
.DidCreate
= DidCreate
;
230 ppp_instance
.DidDestroy
= DidDestroy
;
231 ppp_instance
.DidChangeView
= DidChangeView
;
232 ppp_instance
.DidChangeFocus
= DidChangeFocus
;
233 ppp_instance
.HandleDocumentLoad
= HandleDocumentLoad
;
234 ppp_messaging
.HandleMessage
= HandleMessage
;
236 ppapihook
.ppapi_start(&start_funcs
);
238 __libnacl_irt_basic
.exit(0);