Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: mruby_mbed_web mirb_mbed
dump.c
00001 /* 00002 ** dump.c - mruby binary dumper (mrbc binary format) 00003 ** 00004 ** See Copyright Notice in mruby.h 00005 */ 00006 00007 #include <ctype.h> 00008 #include <string.h> 00009 #include <limits.h> 00010 #include "mruby/dump.h" 00011 #include "mruby/string.h" 00012 #include "mruby/irep.h" 00013 #include "mruby/numeric.h" 00014 #include "mruby/debug.h" 00015 00016 #define FLAG_BYTEORDER_NATIVE 2 00017 #define FLAG_BYTEORDER_NONATIVE 0 00018 00019 #ifdef ENABLE_STDIO 00020 00021 static size_t get_irep_record_size_1(mrb_state *mrb, mrb_irep *irep); 00022 00023 #if UINT32_MAX > SIZE_MAX 00024 # error This code cannot be built on your environment. 00025 #endif 00026 00027 static size_t 00028 write_padding(uint8_t *buf) 00029 { 00030 const size_t align = MRB_DUMP_ALIGNMENT; 00031 size_t pad_len = -(intptr_t)buf & (align-1); 00032 if (pad_len > 0) { 00033 memset(buf, 0, pad_len); 00034 } 00035 return pad_len; 00036 } 00037 00038 static size_t 00039 get_irep_header_size(mrb_state *mrb) 00040 { 00041 size_t size = 0; 00042 00043 size += sizeof(uint32_t) * 1; 00044 size += sizeof(uint16_t) * 3; 00045 00046 return size; 00047 } 00048 00049 static ptrdiff_t 00050 write_irep_header(mrb_state *mrb, mrb_irep *irep, uint8_t *buf) 00051 { 00052 uint8_t *cur = buf; 00053 00054 cur += uint32_to_bin(get_irep_record_size_1(mrb, irep), cur); /* record size */ 00055 cur += uint16_to_bin((uint16_t)irep->nlocals, cur); /* number of local variable */ 00056 cur += uint16_to_bin((uint16_t)irep->nregs, cur); /* number of register variable */ 00057 cur += uint16_to_bin((uint16_t)irep->rlen, cur); /* number of child irep */ 00058 00059 return cur - buf; 00060 } 00061 00062 00063 static size_t 00064 get_iseq_block_size(mrb_state *mrb, mrb_irep *irep) 00065 { 00066 size_t size = 0; 00067 00068 size += sizeof(uint32_t); /* ilen */ 00069 size += sizeof(uint32_t); /* max padding */ 00070 size += sizeof(uint32_t) * irep->ilen; /* iseq(n) */ 00071 00072 return size; 00073 } 00074 00075 static ptrdiff_t 00076 write_iseq_block(mrb_state *mrb, mrb_irep *irep, uint8_t *buf, uint8_t flags) 00077 { 00078 uint8_t *cur = buf; 00079 uint32_t iseq_no; 00080 00081 cur += uint32_to_bin(irep->ilen, cur); /* number of opcode */ 00082 cur += write_padding(cur); 00083 if (flags & FLAG_BYTEORDER_NATIVE) { 00084 memcpy(cur, irep->iseq, irep->ilen * sizeof(mrb_code)); 00085 cur += irep->ilen * sizeof(mrb_code); 00086 } 00087 else { 00088 for (iseq_no = 0; iseq_no < irep->ilen; iseq_no++) { 00089 cur += uint32_to_bin(irep->iseq[iseq_no], cur); /* opcode */ 00090 } 00091 } 00092 00093 return cur - buf; 00094 } 00095 00096 00097 static size_t 00098 get_pool_block_size(mrb_state *mrb, mrb_irep *irep) 00099 { 00100 size_t size = 0; 00101 size_t pool_no; 00102 mrb_value str; 00103 char buf[32]; 00104 00105 size += sizeof(uint32_t); /* plen */ 00106 size += irep->plen * (sizeof(uint8_t) + sizeof(uint16_t)); /* len(n) */ 00107 00108 for (pool_no = 0; pool_no < irep->plen; pool_no++) { 00109 int ai = mrb_gc_arena_save(mrb); 00110 00111 switch (mrb_type(irep->pool[pool_no])) { 00112 case MRB_TT_FIXNUM: 00113 str = mrb_fixnum_to_str(mrb, irep->pool[pool_no], 10); 00114 { 00115 mrb_int len = RSTRING_LEN(str); 00116 mrb_assert_int_fit(mrb_int, len, size_t, SIZE_MAX); 00117 size += (size_t)len; 00118 } 00119 break; 00120 00121 case MRB_TT_FLOAT: 00122 { 00123 int len; 00124 len = mrb_float_to_str(buf, mrb_float(irep->pool[pool_no])); 00125 mrb_assert_int_fit(mrb_int, len, size_t, SIZE_MAX); 00126 size += (size_t)len; 00127 } 00128 break; 00129 00130 case MRB_TT_STRING: 00131 { 00132 mrb_int len = RSTRING_LEN(irep->pool[pool_no]); 00133 mrb_assert_int_fit(mrb_int, len, size_t, SIZE_MAX); 00134 size += (size_t)len; 00135 } 00136 break; 00137 00138 default: 00139 break; 00140 } 00141 mrb_gc_arena_restore(mrb, ai); 00142 } 00143 00144 return size; 00145 } 00146 00147 static ptrdiff_t 00148 write_pool_block(mrb_state *mrb, mrb_irep *irep, uint8_t *buf) 00149 { 00150 size_t pool_no; 00151 uint8_t *cur = buf; 00152 uint16_t len; 00153 mrb_value str; 00154 const char *char_ptr; 00155 char char_buf[30]; 00156 00157 cur += uint32_to_bin(irep->plen, cur); /* number of pool */ 00158 00159 for (pool_no = 0; pool_no < irep->plen; pool_no++) { 00160 int ai = mrb_gc_arena_save(mrb); 00161 00162 switch (mrb_type(irep->pool[pool_no])) { 00163 case MRB_TT_FIXNUM: 00164 cur += uint8_to_bin(IREP_TT_FIXNUM, cur); /* data type */ 00165 str = mrb_fixnum_to_str(mrb, irep->pool[pool_no], 10); 00166 char_ptr = RSTRING_PTR(str); 00167 { 00168 mrb_int tlen; 00169 00170 tlen = RSTRING_LEN(str); 00171 mrb_assert_int_fit(mrb_int, tlen, uint16_t, UINT16_MAX); 00172 len = (uint16_t)tlen; 00173 } 00174 break; 00175 00176 case MRB_TT_FLOAT: 00177 cur += uint8_to_bin(IREP_TT_FLOAT, cur); /* data type */ 00178 { 00179 int tlen; 00180 tlen = mrb_float_to_str(char_buf, mrb_float(irep->pool[pool_no])); 00181 mrb_assert_int_fit(int, tlen, uint16_t, UINT16_MAX); 00182 len = (uint16_t)tlen; 00183 } 00184 char_ptr = &char_buf[0]; 00185 break; 00186 00187 case MRB_TT_STRING: 00188 cur += uint8_to_bin(IREP_TT_STRING, cur); /* data type */ 00189 char_ptr = RSTRING_PTR(irep->pool[pool_no]); 00190 { 00191 mrb_int tlen; 00192 00193 tlen = RSTRING_LEN(irep->pool[pool_no]); 00194 mrb_assert_int_fit(mrb_int, tlen, uint16_t, UINT16_MAX); 00195 len = (uint16_t)tlen; 00196 } 00197 break; 00198 00199 default: 00200 continue; 00201 } 00202 00203 cur += uint16_to_bin(len, cur); /* data length */ 00204 memcpy(cur, char_ptr, (size_t)len); 00205 cur += len; 00206 00207 mrb_gc_arena_restore(mrb, ai); 00208 } 00209 00210 return cur - buf; 00211 } 00212 00213 00214 static size_t 00215 get_syms_block_size(mrb_state *mrb, mrb_irep *irep) 00216 { 00217 size_t size = 0; 00218 uint32_t sym_no; 00219 mrb_int len; 00220 00221 size += sizeof(uint32_t); /* slen */ 00222 for (sym_no = 0; sym_no < irep->slen; sym_no++) { 00223 size += sizeof(uint16_t); /* snl(n) */ 00224 if (irep->syms[sym_no] != 0) { 00225 mrb_sym2name_len(mrb, irep->syms[sym_no], &len); 00226 size += len + 1; /* sn(n) + null char */ 00227 } 00228 } 00229 00230 return size; 00231 } 00232 00233 static ptrdiff_t 00234 write_syms_block(mrb_state *mrb, mrb_irep *irep, uint8_t *buf) 00235 { 00236 uint32_t sym_no; 00237 uint8_t *cur = buf; 00238 const char *name; 00239 00240 cur += uint32_to_bin(irep->slen, cur); /* number of symbol */ 00241 00242 for (sym_no = 0; sym_no < irep->slen; sym_no++) { 00243 if (irep->syms[sym_no] != 0) { 00244 mrb_int len; 00245 00246 name = mrb_sym2name_len(mrb, irep->syms[sym_no], &len); 00247 00248 mrb_assert_int_fit(mrb_int, len, uint16_t, UINT16_MAX); 00249 cur += uint16_to_bin((uint16_t)len, cur); /* length of symbol name */ 00250 memcpy(cur, name, len); /* symbol name */ 00251 cur += (uint16_t)len; 00252 *cur++ = '\0'; 00253 } 00254 else { 00255 cur += uint16_to_bin(MRB_DUMP_NULL_SYM_LEN, cur); /* length of symbol name */ 00256 } 00257 } 00258 00259 return cur - buf; 00260 } 00261 00262 static size_t 00263 get_irep_record_size_1(mrb_state *mrb, mrb_irep *irep) 00264 { 00265 size_t size = 0; 00266 00267 size += get_irep_header_size(mrb); 00268 size += get_iseq_block_size(mrb, irep); 00269 size += get_pool_block_size(mrb, irep); 00270 size += get_syms_block_size(mrb, irep); 00271 return size; 00272 } 00273 00274 static size_t 00275 get_irep_record_size(mrb_state *mrb, mrb_irep *irep) 00276 { 00277 size_t size = 0; 00278 size_t irep_no; 00279 00280 size = get_irep_record_size_1(mrb, irep); 00281 for (irep_no = 0; irep_no < irep->rlen; irep_no++) { 00282 size += get_irep_record_size(mrb, irep->reps[irep_no]); 00283 } 00284 return size; 00285 } 00286 00287 static int 00288 write_irep_record(mrb_state *mrb, mrb_irep *irep, uint8_t *bin, size_t *irep_record_size, uint8_t flags) 00289 { 00290 uint32_t i; 00291 uint8_t *src = bin; 00292 00293 if (irep == NULL) { 00294 return MRB_DUMP_INVALID_IREP; 00295 } 00296 00297 *irep_record_size = get_irep_record_size_1(mrb, irep); 00298 if (*irep_record_size == 0) { 00299 return MRB_DUMP_GENERAL_FAILURE; 00300 } 00301 00302 bin += write_irep_header(mrb, irep, bin); 00303 bin += write_iseq_block(mrb, irep, bin, flags); 00304 bin += write_pool_block(mrb, irep, bin); 00305 bin += write_syms_block(mrb, irep, bin); 00306 00307 for (i = 0; i < irep->rlen; i++) { 00308 int result; 00309 size_t rsize; 00310 00311 result = write_irep_record(mrb, irep->reps[i], bin, &rsize, flags); 00312 if (result != MRB_DUMP_OK) { 00313 return result; 00314 } 00315 bin += rsize; 00316 } 00317 *irep_record_size = bin - src; 00318 return MRB_DUMP_OK; 00319 } 00320 00321 static uint32_t 00322 write_footer(mrb_state *mrb, uint8_t *bin) 00323 { 00324 struct rite_binary_footer footer; 00325 00326 memcpy(footer.section_identify, RITE_BINARY_EOF, sizeof(footer.section_identify)); 00327 uint32_to_bin(sizeof(struct rite_binary_footer), footer.section_size); 00328 memcpy(bin, &footer, sizeof(struct rite_binary_footer)); 00329 00330 return sizeof(struct rite_binary_footer); 00331 } 00332 00333 00334 static int 00335 write_section_irep_header(mrb_state *mrb, size_t section_size, uint8_t *bin) 00336 { 00337 struct rite_section_irep_header *header = (struct rite_section_irep_header*)bin; 00338 00339 memcpy(header->section_identify, RITE_SECTION_IREP_IDENTIFIER, sizeof(header->section_identify)); 00340 00341 mrb_assert_int_fit(size_t, section_size, uint32_t, UINT32_MAX); 00342 uint32_to_bin((uint32_t)section_size, header->section_size); 00343 memcpy(header->rite_version, RITE_VM_VER, sizeof(header->rite_version)); 00344 00345 return MRB_DUMP_OK; 00346 } 00347 00348 static int 00349 write_section_irep(mrb_state *mrb, mrb_irep *irep, uint8_t *bin, size_t *len_p, uint8_t flags) 00350 { 00351 int result; 00352 size_t rsize = 0; 00353 uint8_t *cur = bin; 00354 00355 if (mrb == NULL || bin == NULL) { 00356 return MRB_DUMP_INVALID_ARGUMENT; 00357 } 00358 00359 cur += sizeof(struct rite_section_irep_header); 00360 00361 result = write_irep_record(mrb, irep, cur, &rsize, flags); 00362 if (result != MRB_DUMP_OK) { 00363 return result; 00364 } 00365 *len_p = cur - bin + rsize; 00366 write_section_irep_header(mrb, *len_p, bin); 00367 00368 return MRB_DUMP_OK; 00369 } 00370 00371 static int 00372 write_section_lineno_header(mrb_state *mrb, size_t section_size, uint8_t *bin) 00373 { 00374 struct rite_section_lineno_header *header = (struct rite_section_lineno_header*)bin; 00375 00376 memcpy(header->section_identify, RITE_SECTION_LINENO_IDENTIFIER, sizeof(header->section_identify)); 00377 uint32_to_bin((uint32_t)section_size, header->section_size); 00378 00379 return MRB_DUMP_OK; 00380 } 00381 00382 static size_t 00383 get_lineno_record_size(mrb_state *mrb, mrb_irep *irep) 00384 { 00385 size_t size = 0; 00386 00387 size += sizeof(uint32_t); /* record size */ 00388 size += sizeof(uint16_t); /* filename size */ 00389 if (irep->filename) { 00390 size += strlen(irep->filename); /* filename */ 00391 } 00392 size += sizeof(uint32_t); /* niseq */ 00393 if (irep->lines) { 00394 size += sizeof(uint16_t) * irep->ilen; /* lineno */ 00395 } 00396 00397 return size; 00398 } 00399 00400 static size_t 00401 write_lineno_record_1(mrb_state *mrb, mrb_irep *irep, uint8_t* bin) 00402 { 00403 uint8_t *cur = bin; 00404 size_t iseq_no; 00405 size_t filename_len; 00406 ptrdiff_t diff; 00407 00408 cur += sizeof(uint32_t); /* record size */ 00409 00410 if (irep->filename) { 00411 filename_len = strlen(irep->filename); 00412 } else { 00413 filename_len = 0; 00414 } 00415 mrb_assert_int_fit(size_t, filename_len, uint16_t, UINT16_MAX); 00416 cur += uint16_to_bin((uint16_t)filename_len, cur); /* filename size */ 00417 00418 if (filename_len) { 00419 memcpy(cur, irep->filename, filename_len); 00420 cur += filename_len; /* filename */ 00421 } 00422 00423 if (irep->lines) { 00424 mrb_assert_int_fit(size_t, irep->ilen, uint32_t, UINT32_MAX); 00425 cur += uint32_to_bin((uint32_t)(irep->ilen), cur); /* niseq */ 00426 for (iseq_no = 0; iseq_no < irep->ilen; iseq_no++) { 00427 cur += uint16_to_bin(irep->lines[iseq_no], cur); /* opcode */ 00428 } 00429 } 00430 else { 00431 cur += uint32_to_bin(0, cur); /* niseq */ 00432 } 00433 00434 diff = cur - bin; 00435 mrb_assert_int_fit(ptrdiff_t, diff, uint32_t, UINT32_MAX); 00436 00437 uint32_to_bin((uint32_t)diff, bin); /* record size */ 00438 00439 mrb_assert_int_fit(ptrdiff_t, diff, size_t, SIZE_MAX); 00440 return (size_t)diff; 00441 } 00442 00443 static size_t 00444 write_lineno_record(mrb_state *mrb, mrb_irep *irep, uint8_t* bin) 00445 { 00446 size_t i; 00447 size_t rlen, size = 0; 00448 00449 rlen = write_lineno_record_1(mrb, irep, bin); 00450 bin += rlen; 00451 size += rlen; 00452 for (i=0; i<irep->rlen; i++) { 00453 rlen = write_lineno_record(mrb, irep, bin); 00454 bin += rlen; 00455 size += rlen; 00456 } 00457 return size; 00458 } 00459 00460 static int 00461 write_section_lineno(mrb_state *mrb, mrb_irep *irep, uint8_t *bin) 00462 { 00463 size_t section_size = 0; 00464 size_t rlen = 0; /* size of irep record */ 00465 uint8_t *cur = bin; 00466 00467 if (mrb == NULL || bin == NULL) { 00468 return MRB_DUMP_INVALID_ARGUMENT; 00469 } 00470 00471 cur += sizeof(struct rite_section_lineno_header); 00472 section_size += sizeof(struct rite_section_lineno_header); 00473 00474 rlen = write_lineno_record(mrb, irep, cur); 00475 section_size += rlen; 00476 00477 write_section_lineno_header(mrb, section_size, bin); 00478 00479 return MRB_DUMP_OK; 00480 } 00481 00482 static size_t 00483 get_debug_record_size(mrb_state *mrb, mrb_irep *irep) 00484 { 00485 size_t ret = 0; 00486 uint16_t f_idx; 00487 size_t i; 00488 00489 ret += sizeof(uint32_t); /* record size */ 00490 ret += sizeof(uint16_t); /* file count */ 00491 00492 for (f_idx = 0; f_idx < irep->debug_info->flen; ++f_idx) { 00493 mrb_irep_debug_info_file const* file = irep->debug_info->files[f_idx]; 00494 00495 ret += sizeof(uint32_t); /* position */ 00496 ret += sizeof(uint16_t); /* filename index */ 00497 00498 /* lines */ 00499 ret += sizeof(uint32_t); /* entry count */ 00500 ret += sizeof(uint8_t); /* line type */ 00501 switch (file->line_type) { 00502 case mrb_debug_line_ary: 00503 ret += sizeof(uint16_t) * (size_t)(file->line_entry_count); 00504 break; 00505 00506 case mrb_debug_line_flat_map: 00507 ret += (sizeof(uint32_t) + sizeof(uint16_t)) * (size_t)(file->line_entry_count); 00508 break; 00509 00510 default: mrb_assert(0); break; 00511 } 00512 } 00513 for (i=0; i<irep->rlen; i++) { 00514 ret += get_debug_record_size(mrb, irep->reps[i]); 00515 } 00516 00517 return ret; 00518 } 00519 00520 static int 00521 find_filename_index(const mrb_sym *ary, int ary_len, mrb_sym s) 00522 { 00523 int i; 00524 00525 for (i = 0; i < ary_len; ++i) { 00526 if (ary[i] == s) { return i; } 00527 } 00528 return -1; 00529 } 00530 00531 static size_t 00532 get_filename_table_size(mrb_state *mrb, mrb_irep *irep, mrb_sym **fp, uint16_t *lp) 00533 { 00534 mrb_sym *filenames = *fp; 00535 size_t i, size = 0; 00536 mrb_irep_debug_info *di = irep->debug_info; 00537 00538 mrb_assert(lp); 00539 for (i = 0; i < di->flen; ++i) { 00540 mrb_irep_debug_info_file *file; 00541 mrb_int filename_len; 00542 00543 file = di->files[i]; 00544 if (find_filename_index(filenames, *lp, file->filename_sym) == -1) { 00545 /* register filename */ 00546 *lp += 1; 00547 *fp = filenames = (mrb_sym *)mrb_realloc(mrb, filenames, sizeof(mrb_sym) * (*lp)); 00548 filenames[*lp - 1] = file->filename_sym; 00549 00550 /* filename */ 00551 mrb_sym2name_len(mrb, file->filename_sym, &filename_len); 00552 size += sizeof(uint16_t) + (size_t)filename_len; 00553 } 00554 } 00555 for (i=0; i<irep->rlen; i++) { 00556 size += get_filename_table_size(mrb, irep->reps[i], fp, lp); 00557 } 00558 return size; 00559 } 00560 00561 static size_t 00562 write_debug_record_1(mrb_state *mrb, mrb_irep *irep, uint8_t *bin, mrb_sym const* filenames, uint16_t filenames_len) 00563 { 00564 uint8_t *cur; 00565 uint16_t f_idx; 00566 ptrdiff_t ret; 00567 00568 cur = bin + sizeof(uint32_t); /* skip record size */ 00569 cur += uint16_to_bin(irep->debug_info->flen, cur); /* file count */ 00570 00571 for (f_idx = 0; f_idx < irep->debug_info->flen; ++f_idx) { 00572 int filename_idx; 00573 const mrb_irep_debug_info_file *file = irep->debug_info->files[f_idx]; 00574 00575 /* position */ 00576 cur += uint32_to_bin(file->start_pos, cur); 00577 00578 /* filename index */ 00579 filename_idx = find_filename_index(filenames, filenames_len, 00580 file->filename_sym); 00581 mrb_assert_int_fit(int, filename_idx, uint16_t, UINT16_MAX); 00582 cur += uint16_to_bin((uint16_t)filename_idx, cur); 00583 00584 /* lines */ 00585 cur += uint32_to_bin(file->line_entry_count, cur); 00586 cur += uint8_to_bin(file->line_type, cur); 00587 switch (file->line_type) { 00588 case mrb_debug_line_ary: { 00589 uint32_t l; 00590 for (l = 0; l < file->line_entry_count; ++l) { 00591 cur += uint16_to_bin(file->lines.ary[l], cur); 00592 } 00593 } break; 00594 00595 case mrb_debug_line_flat_map: { 00596 uint32_t line; 00597 for (line = 0; line < file->line_entry_count; ++line) { 00598 cur += uint32_to_bin(file->lines.flat_map[line].start_pos, cur); 00599 cur += uint16_to_bin(file->lines.flat_map[line].line, cur); 00600 } 00601 } break; 00602 00603 default: mrb_assert(0); break; 00604 } 00605 } 00606 00607 ret = cur - bin; 00608 mrb_assert_int_fit(ptrdiff_t, ret, uint32_t, UINT32_MAX); 00609 uint32_to_bin(ret, bin); 00610 00611 mrb_assert_int_fit(ptrdiff_t, ret, size_t, SIZE_MAX); 00612 return (size_t)ret; 00613 } 00614 00615 static size_t 00616 write_debug_record(mrb_state *mrb, mrb_irep *irep, uint8_t *bin, mrb_sym const* filenames, uint16_t filenames_len) 00617 { 00618 size_t size, len; 00619 size_t irep_no; 00620 00621 size = len = write_debug_record_1(mrb, irep, bin, filenames, filenames_len); 00622 bin += len; 00623 for (irep_no = 0; irep_no < irep->rlen; irep_no++) { 00624 len = write_debug_record(mrb, irep->reps[irep_no], bin, filenames, filenames_len); 00625 bin += len; 00626 size += len; 00627 } 00628 00629 mrb_assert(size == get_debug_record_size(mrb, irep)); 00630 return size; 00631 } 00632 00633 static int 00634 write_section_debug(mrb_state *mrb, mrb_irep *irep, uint8_t *cur, mrb_sym const *filenames, uint16_t filenames_len) 00635 { 00636 size_t section_size = 0; 00637 const uint8_t *bin = cur; 00638 struct rite_section_debug_header *header; 00639 size_t dlen; 00640 uint16_t i; 00641 char const *sym; mrb_int sym_len; 00642 00643 if (mrb == NULL || cur == NULL) { 00644 return MRB_DUMP_INVALID_ARGUMENT; 00645 } 00646 00647 header = (struct rite_section_debug_header *)bin; 00648 cur += sizeof(struct rite_section_debug_header); 00649 section_size += sizeof(struct rite_section_debug_header); 00650 00651 /* filename table */ 00652 cur += uint16_to_bin(filenames_len, cur); 00653 section_size += sizeof(uint16_t); 00654 for (i = 0; i < filenames_len; ++i) { 00655 sym = mrb_sym2name_len(mrb, filenames[i], &sym_len); 00656 mrb_assert(sym); 00657 cur += uint16_to_bin(sym_len, cur); 00658 memcpy(cur, sym, sym_len); 00659 cur += sym_len; 00660 section_size += sizeof(uint16_t) + sym_len; 00661 } 00662 00663 /* debug records */ 00664 dlen = write_debug_record(mrb, irep, cur, filenames, filenames_len); 00665 section_size += dlen; 00666 00667 memcpy(header->section_identify, RITE_SECTION_DEBUG_IDENTIFIER, sizeof(header->section_identify)); 00668 mrb_assert(section_size <= INT32_MAX); 00669 uint32_to_bin(section_size, header->section_size); 00670 00671 return MRB_DUMP_OK; 00672 } 00673 00674 static void 00675 create_lv_sym_table(mrb_state *mrb, const mrb_irep *irep, mrb_sym **syms, uint32_t *syms_len) 00676 { 00677 size_t i; 00678 00679 if (*syms == NULL) { 00680 *syms = (mrb_sym*)mrb_malloc(mrb, sizeof(mrb_sym) * 1); 00681 } 00682 00683 for (i = 0; i + 1 < irep->nlocals; ++i) { 00684 mrb_sym const name = irep->lv[i].name; 00685 if (name == 0) continue; 00686 if (find_filename_index(*syms, *syms_len, name) != -1) continue; 00687 00688 ++(*syms_len); 00689 *syms = (mrb_sym*)mrb_realloc(mrb, *syms, sizeof(mrb_sym) * (*syms_len)); 00690 (*syms)[*syms_len - 1] = name; 00691 } 00692 00693 for (i = 0; i < irep->rlen; ++i) { 00694 create_lv_sym_table(mrb, irep->reps[i], syms, syms_len); 00695 } 00696 } 00697 00698 static int 00699 write_lv_sym_table(mrb_state *mrb, uint8_t **start, mrb_sym const *syms, uint32_t syms_len) 00700 { 00701 uint8_t *cur = *start; 00702 uint32_t i; 00703 const char *str; 00704 mrb_int str_len; 00705 00706 cur += uint32_to_bin(syms_len, cur); 00707 00708 for (i = 0; i < syms_len; ++i) { 00709 str = mrb_sym2name_len(mrb, syms[i], &str_len); 00710 cur += uint16_to_bin(str_len, cur); 00711 memcpy(cur, str, str_len); 00712 cur += str_len; 00713 } 00714 00715 *start = cur; 00716 00717 return MRB_DUMP_OK; 00718 } 00719 00720 static int 00721 write_lv_record(mrb_state *mrb, const mrb_irep *irep, uint8_t **start, mrb_sym const *syms, uint32_t syms_len) 00722 { 00723 uint8_t *cur = *start; 00724 size_t i; 00725 00726 for (i = 0; i + 1 < irep->nlocals; ++i) { 00727 if (irep->lv[i].name == 0) { 00728 cur += uint16_to_bin(RITE_LV_NULL_MARK, cur); 00729 cur += uint16_to_bin(0, cur); 00730 } 00731 else { 00732 int const sym_idx = find_filename_index(syms, syms_len, irep->lv[i].name); 00733 mrb_assert(sym_idx != -1); /* local variable name must be in syms */ 00734 00735 cur += uint16_to_bin(sym_idx, cur); 00736 cur += uint16_to_bin(irep->lv[i].r, cur); 00737 } 00738 } 00739 00740 for (i = 0; i < irep->rlen; ++i) { 00741 write_lv_record(mrb, irep->reps[i], &cur, syms, syms_len); 00742 } 00743 00744 *start = cur; 00745 00746 return MRB_DUMP_OK; 00747 } 00748 00749 static size_t 00750 get_lv_record_size(mrb_state *mrb, mrb_irep *irep) 00751 { 00752 size_t ret = 0, i; 00753 00754 ret += (sizeof(uint16_t) + sizeof(uint16_t)) * (irep->nlocals - 1); 00755 00756 for (i = 0; i < irep->rlen; ++i) { 00757 ret += get_lv_record_size(mrb, irep->reps[i]); 00758 } 00759 00760 return ret; 00761 } 00762 00763 static size_t 00764 get_lv_section_size(mrb_state *mrb, mrb_irep *irep, mrb_sym const *syms, uint32_t syms_len) 00765 { 00766 size_t ret = 0, i; 00767 00768 ret += sizeof(uint32_t); /* syms_len */ 00769 ret += sizeof(uint16_t) * syms_len; /* symbol name lengths */ 00770 for (i = 0; i < syms_len; ++i) { 00771 mrb_int str_len; 00772 mrb_sym2name_len(mrb, syms[i], &str_len); 00773 ret += str_len; 00774 } 00775 00776 ret += get_lv_record_size(mrb, irep); 00777 00778 return ret; 00779 } 00780 00781 static int 00782 write_section_lv(mrb_state *mrb, mrb_irep *irep, uint8_t *start, mrb_sym const *syms, uint32_t const syms_len) 00783 { 00784 uint8_t *cur = start; 00785 struct rite_section_lv_header *header; 00786 ptrdiff_t diff; 00787 int result = MRB_DUMP_OK; 00788 00789 if (mrb == NULL || cur == NULL) { 00790 return MRB_DUMP_INVALID_ARGUMENT; 00791 } 00792 00793 header = (struct rite_section_lv_header*)cur; 00794 cur += sizeof(struct rite_section_lv_header); 00795 00796 result = write_lv_sym_table(mrb, &cur, syms, syms_len); 00797 if (result != MRB_DUMP_OK) { 00798 goto lv_section_exit; 00799 } 00800 00801 result = write_lv_record(mrb, irep, &cur, syms, syms_len); 00802 if (result != MRB_DUMP_OK) { 00803 goto lv_section_exit; 00804 } 00805 00806 memcpy(header->section_identify, RITE_SECTION_LV_IDENTIFIER, sizeof(header->section_identify)); 00807 00808 diff = cur - start; 00809 mrb_assert_int_fit(ptrdiff_t, diff, size_t, SIZE_MAX); 00810 uint32_to_bin(diff, header->section_size); 00811 00812 lv_section_exit: 00813 return result; 00814 } 00815 00816 static int 00817 write_rite_binary_header(mrb_state *mrb, size_t binary_size, uint8_t *bin, uint8_t flags) 00818 { 00819 struct rite_binary_header *header = (struct rite_binary_header *)bin; 00820 uint16_t crc; 00821 uint32_t offset; 00822 00823 if (flags & FLAG_BYTEORDER_NATIVE) { 00824 uint32_t ident = 0; 00825 size_t i; 00826 00827 for(i=0; i<sizeof(ident); i++) { 00828 ident<<=8; 00829 ident|=RITE_BINARY_IDENTIFIER[i]; 00830 } 00831 memcpy(header->binary_identify, (char*)&ident, sizeof(uint32_t)); 00832 } 00833 else { 00834 memcpy(header->binary_identify, RITE_BINARY_IDENTIFIER, sizeof(header->binary_identify)); 00835 } 00836 memcpy(header->binary_version, RITE_BINARY_FORMAT_VER, sizeof(header->binary_version)); 00837 memcpy(header->compiler_name, RITE_COMPILER_NAME, sizeof(header->compiler_name)); 00838 memcpy(header->compiler_version, RITE_COMPILER_VERSION, sizeof(header->compiler_version)); 00839 mrb_assert(binary_size <= UINT32_MAX); 00840 uint32_to_bin((uint32_t)binary_size, header->binary_size); 00841 00842 offset = (&(header->binary_crc[0]) - bin) + sizeof(uint16_t); 00843 crc = calc_crc_16_ccitt(bin + offset, binary_size - offset, 0); 00844 uint16_to_bin(crc, header->binary_crc); 00845 00846 return MRB_DUMP_OK; 00847 } 00848 00849 static mrb_bool 00850 is_debug_info_defined(mrb_irep *irep) 00851 { 00852 size_t i; 00853 00854 if (!irep->debug_info) return FALSE; 00855 for (i=0; i<irep->rlen; i++) { 00856 if (!is_debug_info_defined(irep->reps[i])) return FALSE; 00857 } 00858 return TRUE; 00859 } 00860 00861 static mrb_bool 00862 is_lv_defined(mrb_irep *irep) 00863 { 00864 size_t i; 00865 00866 if (irep->lv) { return TRUE; } 00867 00868 for (i = 0; i < irep->rlen; ++i) { 00869 if (is_lv_defined(irep->reps[i])) { return TRUE; } 00870 } 00871 00872 return FALSE; 00873 } 00874 00875 static int 00876 dump_irep(mrb_state *mrb, mrb_irep *irep, int debug_info, uint8_t **bin, size_t *bin_size, uint8_t flags) 00877 { 00878 int result = MRB_DUMP_GENERAL_FAILURE; 00879 size_t malloc_size; 00880 size_t section_irep_size; 00881 size_t section_lineno_size = 0, section_lv_size = 0; 00882 uint8_t *cur = NULL; 00883 mrb_bool const debug_info_defined = is_debug_info_defined(irep), lv_defined = is_lv_defined(irep); 00884 mrb_sym *lv_syms = NULL; uint32_t lv_syms_len = 0; 00885 mrb_sym *filenames = NULL; uint16_t filenames_len = 0; 00886 00887 if (mrb == NULL) { 00888 *bin = NULL; 00889 return MRB_DUMP_GENERAL_FAILURE; 00890 } 00891 00892 section_irep_size = sizeof(struct rite_section_irep_header); 00893 section_irep_size += get_irep_record_size(mrb, irep); 00894 00895 /* DEBUG section size */ 00896 if (debug_info) { 00897 if (debug_info_defined) { 00898 section_lineno_size += sizeof(struct rite_section_debug_header); 00899 /* filename table */ 00900 filenames = (mrb_sym*)mrb_malloc(mrb, sizeof(mrb_sym) + 1); 00901 00902 /* filename table size */ 00903 section_lineno_size += sizeof(uint16_t); 00904 section_lineno_size += get_filename_table_size(mrb, irep, &filenames, &filenames_len); 00905 00906 section_lineno_size += get_debug_record_size(mrb, irep); 00907 } 00908 else { 00909 section_lineno_size += sizeof(struct rite_section_lineno_header); 00910 section_lineno_size += get_lineno_record_size(mrb, irep); 00911 } 00912 } 00913 00914 if (lv_defined) { 00915 section_lv_size += sizeof(struct rite_section_lv_header); 00916 create_lv_sym_table(mrb, irep, &lv_syms, &lv_syms_len); 00917 section_lv_size += get_lv_section_size(mrb, irep, lv_syms, lv_syms_len); 00918 } 00919 00920 malloc_size = sizeof(struct rite_binary_header) + 00921 section_irep_size + section_lineno_size + section_lv_size + 00922 sizeof(struct rite_binary_footer); 00923 cur = *bin = (uint8_t*)mrb_malloc(mrb, malloc_size); 00924 cur += sizeof(struct rite_binary_header); 00925 00926 result = write_section_irep(mrb, irep, cur, §ion_irep_size, flags); 00927 if (result != MRB_DUMP_OK) { 00928 goto error_exit; 00929 } 00930 cur += section_irep_size; 00931 *bin_size = sizeof(struct rite_binary_header) + 00932 section_irep_size + section_lineno_size + section_lv_size + 00933 sizeof(struct rite_binary_footer); 00934 00935 /* write DEBUG section */ 00936 if (debug_info) { 00937 if (debug_info_defined) { 00938 result = write_section_debug(mrb, irep, cur, filenames, filenames_len); 00939 } 00940 else { 00941 result = write_section_lineno(mrb, irep, cur); 00942 } 00943 if (result != MRB_DUMP_OK) { 00944 goto error_exit; 00945 } 00946 cur += section_lineno_size; 00947 } 00948 00949 if (lv_defined) { 00950 result = write_section_lv(mrb, irep, cur, lv_syms, lv_syms_len); 00951 if (result != MRB_DUMP_OK) { 00952 goto error_exit; 00953 } 00954 cur += section_lv_size; 00955 } 00956 00957 write_footer(mrb, cur); 00958 write_rite_binary_header(mrb, *bin_size, *bin, flags); 00959 00960 error_exit: 00961 if (result != MRB_DUMP_OK) { 00962 mrb_free(mrb, *bin); 00963 *bin = NULL; 00964 } 00965 if (lv_syms) { 00966 mrb_free(mrb, lv_syms); 00967 } 00968 if (filenames) { 00969 mrb_free(mrb, filenames); 00970 } 00971 return result; 00972 } 00973 00974 int 00975 mrb_dump_irep(mrb_state *mrb, mrb_irep *irep, int debug_info, uint8_t **bin, size_t *bin_size) 00976 { 00977 return dump_irep(mrb, irep, debug_info, bin, bin_size, FLAG_BYTEORDER_NONATIVE); 00978 } 00979 00980 int 00981 mrb_dump_irep_binary(mrb_state *mrb, mrb_irep *irep, int debug_info, FILE* fp) 00982 { 00983 uint8_t *bin = NULL; 00984 size_t bin_size = 0; 00985 int result; 00986 00987 if (fp == NULL) { 00988 return MRB_DUMP_INVALID_ARGUMENT; 00989 } 00990 00991 result = dump_irep(mrb, irep, debug_info, &bin, &bin_size, FLAG_BYTEORDER_NONATIVE); 00992 if (result == MRB_DUMP_OK) { 00993 if (fwrite(bin, sizeof(bin[0]), bin_size, fp) != bin_size) { 00994 result = MRB_DUMP_WRITE_FAULT; 00995 } 00996 } 00997 00998 mrb_free(mrb, bin); 00999 return result; 01000 } 01001 01002 static mrb_bool 01003 is_valid_c_symbol_name(const char *name) 01004 { 01005 const char *c = NULL; 01006 01007 if (name == NULL || name[0] == '\0') return FALSE; 01008 if (!ISALPHA(name[0]) && name[0] != '_') return FALSE; 01009 01010 c = &name[1]; 01011 for (; *c != '\0'; ++c) { 01012 if (!ISALNUM(*c) && *c != '_') return FALSE; 01013 } 01014 01015 return TRUE; 01016 } 01017 01018 int 01019 mrb_dump_irep_cfunc(mrb_state *mrb, mrb_irep *irep, int debug_info, FILE *fp, const char *initname) 01020 { 01021 uint8_t *bin = NULL; 01022 size_t bin_size = 0, bin_idx = 0; 01023 int result; 01024 01025 if (fp == NULL || initname == NULL || !is_valid_c_symbol_name(initname)) { 01026 return MRB_DUMP_INVALID_ARGUMENT; 01027 } 01028 01029 result = dump_irep(mrb, irep, debug_info, &bin, &bin_size, FLAG_BYTEORDER_NATIVE); 01030 if (result == MRB_DUMP_OK) { 01031 if (fprintf(fp, "#include <stdint.h>\n") < 0) { /* for uint8_t under at least Darwin */ 01032 mrb_free(mrb, bin); 01033 return MRB_DUMP_WRITE_FAULT; 01034 } 01035 if (fprintf(fp, 01036 "const uint8_t\n" 01037 "#if defined __GNUC__\n" 01038 "__attribute__((aligned(%u)))\n" 01039 "#elif defined _MSC_VER\n" 01040 "__declspec(align(%u))\n" 01041 "#endif\n" 01042 "%s[] = {", 01043 (uint16_t)MRB_DUMP_ALIGNMENT, (uint16_t)MRB_DUMP_ALIGNMENT, initname) < 0) { 01044 mrb_free(mrb, bin); 01045 return MRB_DUMP_WRITE_FAULT; 01046 } 01047 while (bin_idx < bin_size) { 01048 if (bin_idx % 16 == 0) { 01049 if (fputs("\n", fp) == EOF) { 01050 mrb_free(mrb, bin); 01051 return MRB_DUMP_WRITE_FAULT; 01052 } 01053 } 01054 if (fprintf(fp, "0x%02x,", bin[bin_idx++]) < 0) { 01055 mrb_free(mrb, bin); 01056 return MRB_DUMP_WRITE_FAULT; 01057 } 01058 } 01059 if (fputs("\n};\n", fp) == EOF) { 01060 mrb_free(mrb, bin); 01061 return MRB_DUMP_WRITE_FAULT; 01062 } 01063 } 01064 01065 mrb_free(mrb, bin); 01066 return result; 01067 } 01068 01069 #endif /* ENABLE_STDIO */ 01070
Generated on Tue Jul 12 2022 18:00:34 by
1.7.2