1 /*
2 * Copyright (c) Huawei Technologies Co., Ltd. 2020-2020. All rights reserved.
3 * Description: Definition of source file for generating bytecode.
4 * Create: 2020/09/07
5 */
6
7 #ifdef JERRY_FOR_IAR_CONFIG
8
9 #include "generate-bytecode.h"
10
11 #include <string.h>
12
13 #include "config-gt.h"
14 #include "config-jupiter.h"
15
16 #define VERSION_LEN 30
17 #define ONETIME_MAX_OPTBYTES 4096 // max size for reading and writing at onetime
18
19 // jerry version code
20 char version_str[VERSION_LEN];
21
22 // secure functions
23 extern int memset_s(void *dest, size_t destMax, int c, size_t count);
24 extern int strcpy_s(char *strDest, size_t destMax, const char *strSrc);
25 extern int strcat_s(char *strDest, size_t destMax, const char *strSrc);
26 extern int strncat_s(char *strDest, size_t destMax, const char *strSrc, size_t count);
27 extern int sprintf_s(char *strDest, size_t destMax, const char *format, ...);
28 extern int strncpy_s(char *strDest, size_t destMax, const char *strSrc, size_t count);
29
30 #ifdef JERRY_IAR_JUPITER
31 extern uint8_t* input_buffer;
32 extern uint8_t* snapshot_buffer;
33 #endif // JERRY_IAR_JUPITER
34
35 /**
36 * jerry snapshot format version
37 */
get_jerry_version_no()38 char* get_jerry_version_no() {
39 if (sprintf_s(version_str, sizeof(version_str),
40 "JERRY_SNAPSHOT_VERSION_%u", JERRY_SNAPSHOT_VERSION) < 0) {
41 return NULL;
42 }
43 return version_str;
44 } /* get_jerry_version_no */
45
46 /**
47 * splice path and filename
48 */
splice_path(char * str1,char * str2)49 char* splice_path(char* str1, char* str2) {
50 int len1 = strlen(str1);
51 int len2 = strlen(str2);
52 int res_len = len1 + len2 + 1; // str1 + "/" + str2
53
54 char* res = (char*)OhosMalloc(MEM_TYPE_JERRY, (res_len + 1) * sizeof(char));
55 if (res == NULL) {
56 return NULL;
57 }
58 if (memset_s(res, res_len + 1, 0, res_len + 1) != 0) {
59 OhosFree(res);
60 res = NULL;
61 return NULL;
62 }
63 if (strcpy_s(res, len1 + 1, str1) != 0) {
64 OhosFree(res);
65 res = NULL;
66 return NULL;
67 }
68 if ((strcat_s(res, len1 + strlen("/") + 1, "/") != 0)
69 || (strcat_s(res, res_len + 1, str2) != 0)) {
70 OhosFree(res);
71 res = NULL;
72 return NULL;
73 }
74 return res;
75 } /* splice_path */
76
77 /**
78 * judge if is template(js/bc) file
79 */
is_template_file(char * filename,char * template)80 bool is_template_file(char* filename, char* template) {
81 const char* pFile;
82 pFile = strrchr(filename, '.');
83 if ((pFile != NULL) && (strcmp(pFile, template) == 0)) {
84 return true;
85 }
86 return false;
87 } /* is_template_file */
88
89 /**
90 * get output snapshot file absolutely path
91 */
get_output_file_path(char * input_file_path)92 char* get_output_file_path(char* input_file_path) {
93 int len = strlen(input_file_path);
94 char* output_file_path = (char*)OhosMalloc(MEM_TYPE_JERRY, (len + 1) * sizeof(char));
95 if (output_file_path == NULL) {
96 return NULL;
97 }
98 if (memset_s(output_file_path, len + 1, 0, len + 1) != 0) {
99 OhosFree(output_file_path);
100 output_file_path = NULL;
101 return NULL;
102 }
103 if (strncpy_s(output_file_path, len, input_file_path, len - strlen(".js")) != 0) {
104 OhosFree(output_file_path);
105 output_file_path = NULL;
106 return NULL;
107 }
108 output_file_path[len-3] = '.';
109 output_file_path[len-2] = 'b';
110 output_file_path[len-1] = 'c';
111 output_file_path[len] = '\0';
112 return output_file_path;
113 } /* get_output_file_path */
114
115 /**
116 * read js bundle file by Fragement
117 */
read_js_file(char * filename,uint8_t * target_Js,int * file_bytesize)118 EXECRES read_js_file(char* filename, uint8_t* target_Js, int* file_bytesize) {
119 int fd = 0;
120 struct stat file_stat = { 0 };
121 int remain_to_read = 0;
122 int here_to_read = 0;
123 int tmp_read = 0;
124 int read_offset = 0;
125 fd = open(filename, O_RDONLY, S_IREAD);
126 if (fd < 0) {
127 // Error: failed to open file
128 return EXCE_ACE_JERRY_OPEN_FILE_FAILED;
129 }
130 if (fstat(fd, &file_stat) < 0) {
131 close(fd);
132 return EXCE_ACE_JERRY_GET_FILE_STAT_ERROR;
133 }
134 *file_bytesize = file_stat.st_size;
135 if (*file_bytesize > INPUTJS_BUFFER_SIZE) {
136 close(fd);
137 return EXCE_ACE_JERRY_JSFILE_TOO_LARGE;
138 }
139 remain_to_read = *file_bytesize;
140 while (remain_to_read > 0) {
141 here_to_read = (remain_to_read > ONETIME_MAX_OPTBYTES) ?
142 ONETIME_MAX_OPTBYTES : remain_to_read;
143 tmp_read = read(fd, target_Js + read_offset, here_to_read);
144 if (tmp_read < 0 || tmp_read != here_to_read) {
145 close(fd);
146 // Error: failed to read file
147 return EXCE_ACE_JERRY_READ_JSFILE_FAILED;
148 }
149 read_offset = read_offset + here_to_read;
150 remain_to_read = remain_to_read - here_to_read;
151 }
152 if (read_offset != *file_bytesize) {
153 close(fd);
154 // Error: failed to successfully read file
155 return EXCE_ACE_JERRY_READ_JSFILE_FAILED;
156 }
157 close(fd);
158 return EXCE_ACE_JERRY_EXEC_OK;
159 } /* read_js_file */
160
161 /**
162 * write snapshot file by Fragment
163 */
write_snapshot(char * output_file_name_path,size_t snapshot_size)164 EXECRES write_snapshot(char* output_file_name_path, size_t snapshot_size) {
165 int fd = 0;
166 int res = 0;
167 int remain_to_write = 0;
168 int here_to_write = 0;
169 int write_offset = 0;
170
171 fd = open(output_file_name_path, O_RDWR | O_CREAT, S_IREAD | S_IWRITE);
172 if (fd < 0) {
173 // Error: Unable to open snapshot file
174 return EXCE_ACE_JERRY_OPEN_FILE_FAILED;
175 }
176 remain_to_write = snapshot_size;
177 while (remain_to_write > 0) {
178 here_to_write = (remain_to_write > ONETIME_MAX_OPTBYTES) ?
179 ONETIME_MAX_OPTBYTES : remain_to_write;
180 res = write(fd, snapshot_buffer + write_offset, here_to_write);
181 if (res <= 0 || res != here_to_write) {
182 close(fd);
183 // Error: Unable to write snapshot file
184 return EXCE_ACE_JERRY_WRITE_SNAPSHOT_FILE_FAILED;
185 }
186 write_offset = write_offset + here_to_write;
187 remain_to_write = remain_to_write - here_to_write;
188 }
189 if (write_offset != snapshot_size) {
190 close(fd);
191 // Error: Unable to successfully write snapshot file
192 return EXCE_ACE_JERRY_WRITE_SNAPSHOT_FILE_FAILED;
193 }
194 close(fd);
195 return EXCE_ACE_JERRY_EXEC_OK;
196 } /* write_snapshot */
197
198 /**
199 * struct for Directory Node
200 */
201 typedef struct Node {
202 char* dir_name;
203 struct Node* next;
204 } dir_node;
205
206 /**
207 * free the memory for linkedlist
208 */
free_link(dir_node * head)209 void free_link(dir_node* head) {
210 dir_node* tmp = NULL;
211 while (head != NULL) {
212 tmp = head;
213 head = head->next;
214 if (tmp->dir_name != NULL) {
215 OhosFree(tmp->dir_name);
216 tmp->dir_name = NULL;
217 }
218 OhosFree(tmp);
219 tmp = NULL;
220 }
221 } /* free_link */
222
223 /**
224 * generate snapshot file
225 */
generate_snapshot_file(char * input_file,char * output_file)226 EXECRES generate_snapshot_file(char* input_file, char* output_file) {
227 uint8_t* target_Js = input_buffer;
228 jerry_value_t generate_result;
229 size_t snapshot_size = 0;
230 EXECRES write_res = EXCE_ACE_JERRY_EXEC_OK;
231 bool convert_state = false;
232 int file_bytesize = 0;
233 EXECRES read_res = EXCE_ACE_JERRY_EXEC_OK;
234
235 if (input_file == NULL || output_file == NULL) {
236 return EXCE_ACE_JERRY_NULL_PATH;
237 }
238 read_res = read_js_file(input_file, target_Js, &file_bytesize);
239 if (read_res != EXCE_ACE_JERRY_EXEC_OK) {
240 return read_res;
241 }
242
243 generate_result = jerry_generate_snapshot (
244 NULL,
245 0,
246 target_Js,
247 file_bytesize,
248 0,
249 (uint32_t* )snapshot_buffer,
250 SNAPSHOT_BUFFER_SIZE);
251
252 convert_state = jerry_value_is_error(generate_result)
253 || !jerry_value_is_number(generate_result);
254 if (convert_state) {
255 // Error: Generating snapshot failed
256 jerry_release_value(generate_result);
257 return EXCE_ACE_JERRY_GENERATE_SNAPSHOT_FAILED;
258 }
259 snapshot_size = (size_t)jerry_get_number_value(generate_result);
260 jerry_release_value(generate_result);
261
262 write_res = write_snapshot(output_file, snapshot_size);
263 if (write_res != EXCE_ACE_JERRY_EXEC_OK) {
264 // Error: Writing snapshot file failed
265 return write_res;
266 }
267 return EXCE_ACE_JERRY_EXEC_OK;
268 }/* generate_snapshot_file */
269
270 /**
271 * traverse directory and do js to bytecode conversion ON IAR
272 */
walk_directory(char * filefolder)273 EXECRES walk_directory(char* filefolder) {
274 EXECRES generate_val = EXCE_ACE_JERRY_EXEC_OK;
275 DIR* dir;
276 struct dirent* direntp;
277 struct stat file_stat = { 0 };
278 char* filename = NULL;
279 char* current_path = NULL;
280 char* input_file_path = NULL;
281 char* output_file_path = NULL;
282 char* start_folder = NULL;
283 dir_node *head, *curr, *end, *new_node;
284 int filefolder_len = strlen(filefolder) + 1;
285
286 if ((filefolder == NULL) || (stat(filefolder, &file_stat) < 0)) {
287 return EXCE_ACE_JERRY_INPUT_PATH_ERROR;
288 }
289 if ((start_folder = (char*)OhosMalloc(MEM_TYPE_JERRY, filefolder_len)) == NULL) {
290 return EXCE_ACE_JERRY_MALLOC_ERROR;
291 }
292 if (strcpy_s(start_folder, filefolder_len, filefolder) != 0) {
293 OhosFree(start_folder);
294 start_folder = NULL;
295 return EXCE_ACE_JERRY_INPUT_PATH_ERROR;
296 }
297 if ((head = (dir_node*)OhosMalloc(MEM_TYPE_JERRY, sizeof(dir_node))) == NULL) {
298 OhosFree(start_folder);
299 start_folder = NULL;
300 return EXCE_ACE_JERRY_LINKLIST_ERROR;
301 }
302 if ((end = (dir_node*)OhosMalloc(MEM_TYPE_JERRY, sizeof(dir_node))) == NULL) {
303 OhosFree(start_folder);
304 start_folder = NULL;
305 OhosFree(head);
306 head = NULL;
307 return EXCE_ACE_JERRY_LINKLIST_ERROR;
308 }
309 head->dir_name = NULL;
310 head->next = end;
311 end->dir_name = start_folder;
312 end->next = NULL;
313
314 jerry_init_flag_t flags = JERRY_INIT_EMPTY;
315 jerry_init (flags);
316
317 while (head->next != NULL) {
318 curr = head->next;
319 current_path = curr->dir_name;
320 if ((dir = (DIR*)opendir(current_path)) == NULL) {
321 free_link(head);
322 curr = NULL;
323 end = NULL;
324 jerry_cleanup();
325 return EXCE_ACE_JERRY_OPEN_DIR_FAILED;
326 }
327 while ((direntp = (struct dirent*)readdir(dir)) != NULL) {
328 filename = direntp->d_name;
329 if (strncmp(filename, ".", 1) == 0) {
330 continue;
331 }
332 if ((input_file_path = splice_path(current_path, filename)) == NULL) {
333 closedir(dir);
334 free_link(head);
335 curr = NULL;
336 end = NULL;
337 jerry_cleanup();
338 return EXCE_ACE_JERRY_SPLICE_PATH_ERROR;
339 }
340 if (stat(input_file_path, &file_stat) < 0) {
341 closedir(dir);
342 OhosFree(input_file_path);
343 input_file_path = NULL;
344 free_link(head);
345 curr = NULL;
346 end = NULL;
347 jerry_cleanup();
348 return EXCE_ACE_JERRY_GET_FILE_STAT_ERROR;
349 }
350 if (file_stat.st_mode & S_IFDIR) {
351 // file now is file folder
352 if ((new_node = (dir_node*)OhosMalloc(MEM_TYPE_JERRY, sizeof(dir_node))) == NULL) {
353 closedir(dir);
354 OhosFree(input_file_path);
355 input_file_path = NULL;
356 free_link(head);
357 curr = NULL;
358 end = NULL;
359 jerry_cleanup();
360 return EXCE_ACE_JERRY_LINKLIST_ERROR;
361 }
362 // input_file_path for dir will be freed when that node is freed
363 new_node->dir_name = input_file_path;
364 new_node->next = NULL;
365 end->next = new_node;
366 end = new_node;
367 new_node = NULL;
368 } else if (is_template_file(filename, ".js")) {
369 //filename now is .js file
370 if ((output_file_path = get_output_file_path(input_file_path)) == NULL) {
371 closedir(dir);
372 OhosFree(input_file_path);
373 input_file_path = NULL;
374 free_link(head);
375 curr = NULL;
376 end = NULL;
377 jerry_cleanup();
378 return EXCE_ACE_JERRY_SPLICE_OUTPUT_PATH_ERROR;
379 }
380 generate_val = generate_snapshot_file(input_file_path, output_file_path);
381 OhosFree(output_file_path);
382 output_file_path = NULL;
383 OhosFree(input_file_path);
384 input_file_path = NULL;
385 if (generate_val != EXCE_ACE_JERRY_EXEC_OK) {
386 closedir(dir);
387 free_link(head);
388 curr = NULL;
389 end = NULL;
390 jerry_cleanup();
391 return generate_val; // return error_code
392 }
393 } else {
394 OhosFree(input_file_path);
395 input_file_path = NULL;
396 }
397 }
398 closedir(dir);
399 head->next = curr->next;
400 OhosFree(curr->dir_name);
401 curr->dir_name = NULL;
402 OhosFree(curr);
403 curr = NULL;
404 }
405 OhosFree(head);
406 head = NULL;
407 end = NULL;
408 jerry_cleanup();
409 return EXCE_ACE_JERRY_EXEC_OK;
410 } /* walk_directory */
411
412 /**
413 * when convertion failed, traverse directory and delete all created bytecode files
414 */
walk_del_bytecode(char * filefolder)415 EXECRES walk_del_bytecode(char* filefolder) {
416 DIR* dir;
417 struct dirent* direntp;
418 struct stat file_stat = { 0 };
419 char* filename = NULL;
420 char* current_path = NULL;
421 char* input_file_path = NULL;
422 char* start_folder = NULL;
423 dir_node *head, *curr, *end, *new_node;
424 int filefolder_len = strlen(filefolder) + 1;
425
426 if ((filefolder == NULL) || (stat(filefolder, &file_stat) < 0)) {
427 return EXCE_ACE_JERRY_INPUT_PATH_ERROR;
428 }
429 if ((start_folder = (char*)OhosMalloc(MEM_TYPE_JERRY, filefolder_len)) == NULL) {
430 return EXCE_ACE_JERRY_MALLOC_ERROR;
431 }
432 if (strcpy_s(start_folder, filefolder_len, filefolder) != 0) {
433 OhosFree(start_folder);
434 start_folder = NULL;
435 return EXCE_ACE_JERRY_INPUT_PATH_ERROR;
436 }
437 if ((head = (dir_node*)OhosMalloc(MEM_TYPE_JERRY, sizeof(dir_node))) == NULL) {
438 OhosFree(start_folder);
439 start_folder = NULL;
440 return EXCE_ACE_JERRY_LINKLIST_ERROR;
441 }
442 if ((end = (dir_node*)OhosMalloc(MEM_TYPE_JERRY, sizeof(dir_node))) == NULL) {
443 OhosFree(start_folder);
444 start_folder = NULL;
445 OhosFree(head);
446 head = NULL;
447 return EXCE_ACE_JERRY_LINKLIST_ERROR;
448 }
449 head->dir_name = NULL;
450 head->next = end;
451 end->dir_name = start_folder;
452 end->next = NULL;
453
454 while (head->next != NULL) {
455 curr = head->next;
456 current_path = curr->dir_name;
457 if ((dir = (DIR*)opendir(current_path)) == NULL) {
458 free_link(head);
459 curr = NULL;
460 end = NULL;
461 return EXCE_ACE_JERRY_OPEN_DIR_FAILED;
462 }
463 while ((direntp = (struct dirent*)readdir(dir)) != NULL) {
464 filename = direntp->d_name;
465 if (strncmp(filename, ".", 1) == 0) {
466 continue;
467 }
468 if ((input_file_path = splice_path(current_path, filename)) == NULL) {
469 closedir(dir);
470 free_link(head);
471 curr = NULL;
472 end = NULL;
473 return EXCE_ACE_JERRY_SPLICE_PATH_ERROR;
474 }
475 if (stat(input_file_path, &file_stat) < 0) {
476 closedir(dir);
477 OhosFree(input_file_path);
478 input_file_path = NULL;
479 free_link(head);
480 curr = NULL;
481 end = NULL;
482 return EXCE_ACE_JERRY_GET_FILE_STAT_ERROR;
483 }
484 if (file_stat.st_mode & S_IFDIR) {
485 // file now is file folder
486 if ((new_node = (dir_node*)OhosMalloc(MEM_TYPE_JERRY, sizeof(dir_node))) == NULL) {
487 closedir(dir);
488 OhosFree(input_file_path);
489 input_file_path = NULL;
490 free_link(head);
491 curr = NULL;
492 end = NULL;
493 return EXCE_ACE_JERRY_LINKLIST_ERROR;
494 }
495 // input_file_path for dir will be freed when that node is freed
496 new_node->dir_name = input_file_path;
497 new_node->next = NULL;
498 end->next = new_node;
499 end = new_node;
500 new_node = NULL;
501 } else if ((is_template_file(filename, ".bc")) && (unlink(input_file_path) != F_OK)) {
502 //file now is .bc file and unlink file failed
503 closedir(dir);
504 OhosFree(input_file_path);
505 input_file_path = NULL;
506 free_link(head);
507 curr = NULL;
508 end = NULL;
509 return EXCE_ACE_JERRY_UNLINKFILE_ERROR;
510 } else {
511 OhosFree(input_file_path);
512 input_file_path = NULL;
513 }
514 }
515 closedir(dir);
516 head->next = curr->next;
517 OhosFree(curr->dir_name);
518 curr->dir_name = NULL;
519 OhosFree(curr);
520 curr = NULL;
521 }
522 OhosFree(head);
523 head = NULL;
524 end = NULL;
525 return EXCE_ACE_JERRY_EXEC_OK;
526 } /* walk_del_bytecode */
527
528 #endif // end JERRY_FOR_IAR_CONFIG
529