Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / chrome / test / data / nacl / nonsfi / libc_free.c
1 /*
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.
5  */
6
7 /*
8  * This is a minimal NaCl program without libc. It uses NaCl's stable IRT ABI.
9  */
10
11 #include <stdint.h>
12
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"
21
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;
29
30 /*
31  * To support 64bit binary, we declare Elf_auxv_t by using uintptr_t.
32  * See also native_client/src/include/elf32.h.
33  */
34 typedef struct {
35   uintptr_t a_type;
36   union {
37     uintptr_t a_val;
38   } a_un;
39 } Elf_auxv_t;
40
41 /*
42  * This is simiplar to the one in
43  * native_client/src/untrusted/nacl/nacl_startup.h, but also supports 64 bit
44  * pointers.
45  */
46 static Elf_auxv_t* nacl_startup_auxv(const uintptr_t info[]) {
47   /* The layout of _start's argument is
48    * info[0]: fini.
49    * info[1]: envc
50    * info[2]: argc
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.
54    */
55   int envc = info[1];
56   int argc = info[2];
57   return (Elf_auxv_t*) (info + 3 + envc + 1 + argc + 1);
58 }
59
60 static void grok_auxv(const Elf_auxv_t* auxv) {
61   const Elf_auxv_t* av;
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;
65     }
66   }
67 }
68
69 #define DO_QUERY(ident, name) __nacl_irt_query(ident, &name, sizeof(name))
70
71 static int my_strcmp(const char* a, const char* b) {
72   while (*a == *b) {
73     if (*a == '\0')
74       return 0;
75     ++a;
76     ++b;
77   }
78   return (int) (unsigned char) *a - (int) (unsigned char) *b;
79 }
80
81 static int my_strncmp(const char* a, const char* b, size_t n) {
82   while (n > 0 && *a == *b) {
83     if (*a == '\0')
84       return 0;
85     ++a;
86     ++b;
87     --n;
88   }
89   if (n == 0) {
90     return 0;
91   }
92   return (int) (unsigned char) *a - (int) (unsigned char) *b;
93 }
94
95 static size_t my_strlen(const char* a) {
96   size_t size = 0;
97   while (*a++)
98     size++;
99   return size;
100 }
101
102 static PP_Bool DidCreate(PP_Instance instance,
103                          uint32_t argc,
104                          const char* argn[],
105                          const char* argv[]) {
106   return 1;
107 }
108
109 static void DidDestroy(PP_Instance instance) {
110 }
111
112 static void DidChangeView(PP_Instance instance,
113                           const struct PP_Rect* position,
114                           const struct PP_Rect* clip) {
115 }
116
117 static void DidChangeFocus(PP_Instance instance, PP_Bool has_focus) {
118 }
119
120 static PP_Bool HandleDocumentLoad(PP_Instance instance,
121                                   PP_Resource url_loader) {
122   return 0;
123 }
124
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);
129   return PP_OK;
130 }
131
132 static void MyPPP_ShutdownModule(void) {
133 }
134
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;
140   return NULL;
141 }
142
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);
150 }
151
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.
156
157   char random_buffer[512];
158   int i;
159   // zero-clear the buffer.
160   for (i = 0; i < sizeof random_buffer; ++i) {
161     random_buffer[i] = 0;
162   }
163
164   size_t read_len;
165   if (__libnacl_irt_random.get_random_bytes(random_buffer,
166                                             sizeof random_buffer,
167                                             &read_len) != 0) {
168     PostStringMessage(instance, "Get Random Bytes Failed.");
169     return;
170   }
171
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");
175     return;
176   }
177   int num_zeroes = 0;
178   for (i = 0; i < sizeof random_buffer; ++i) {
179     if (random_buffer[i] == 0) {
180       num_zeroes++;
181     }
182   }
183   if (num_zeroes > 100) {
184     PostStringMessage(instance, "Too many zeros in this random stream.");
185     return;
186   }
187
188   PostStringMessage(instance, "randomsuccess");
189 }
190
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);
196   }
197
198   uint32_t message_len;
199   const char* message_string = ppb_var->VarToUtf8(message, &message_len);
200
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);
207   } else {
208     // Unknown message came.
209     PostStringMessage(instance, "Unknown message type");
210   }
211 }
212
213 void _start(uintptr_t info[]) {
214   Elf_auxv_t* auxv = nacl_startup_auxv(info);
215   grok_auxv(auxv);
216   DO_QUERY(NACL_IRT_BASIC_v0_1, __libnacl_irt_basic);
217   DO_QUERY(NACL_IRT_RANDOM_v0_1, __libnacl_irt_random);
218
219   struct nacl_irt_ppapihook ppapihook;
220   DO_QUERY(NACL_IRT_PPAPIHOOK_v0_1, ppapihook);
221
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;
235
236   ppapihook.ppapi_start(&start_funcs);
237
238   __libnacl_irt_basic.exit(0);
239 }