• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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