2 ** load.c - mruby binary loader
4 ** See Copyright Notice in mruby.h
8 #include <mruby/dump.h>
9 #include <mruby/irep.h>
10 #include <mruby/proc.h>
11 #include <mruby/string.h>
12 #include <mruby/debug.h>
13 #include <mruby/error.h>
14 #include <mruby/data.h>
15 #include <mruby/endian.h>
16 #include <mruby/internal.h>
19 #if SIZE_MAX < UINT32_MAX
20 # error size_t must be at least 32 bits wide
23 #define FLAG_SRC_MALLOC 1
24 #define FLAG_SRC_STATIC 0
26 #define SIZE_ERROR_MUL(nmemb, size) ((size_t)(nmemb) > SIZE_MAX / (size))
28 #define DEFINE_READ_IREP_FUNC(funcdecl, basecall) \
31 int ai = mrb_gc_arena_save(mrb); \
32 struct RProc *proc = basecall; \
33 struct mrb_irep *irep = (mrb_irep*)(proc ? proc->body.irep : NULL); \
34 if (irep) proc->body.irep = NULL; \
35 mrb_gc_arena_restore(mrb, ai); \
41 str_to_double(mrb_state
*mrb
, const char *p
)
43 /* dump IEEE754 little endian binary */
45 char s
[sizeof(double)];
50 memcpy(u
.s
, p
, sizeof(double));
54 for (i
=0; i
<sizeof(double); i
++) {
55 u
.s
[i
] = p
[sizeof(double)-i
-1];
63 read_irep_record_1(mrb_state
*mrb
, const uint8_t *bin
, const uint8_t *end
, size_t *len
, uint8_t flags
, mrb_irep
**irepp
)
66 const uint8_t *src
= bin
;
68 uint16_t tt
, pool_data_len
, snl
;
72 int ai
= mrb_gc_arena_save(mrb
);
73 mrb_irep
*irep
= mrb_add_irep(mrb
);
77 /* skip record size */
78 src
+= sizeof(uint32_t);
80 /* number of local variable */
81 irep
->nlocals
= bin_to_uint16(src
);
82 src
+= sizeof(uint16_t);
84 /* number of register variable */
85 irep
->nregs
= bin_to_uint16(src
);
86 src
+= sizeof(uint16_t);
88 /* number of child irep */
89 irep
->rlen
= bin_to_uint16(src
);
90 src
+= sizeof(uint16_t);
92 /* Binary Data Section */
93 /* ISEQ BLOCK (and CATCH HANDLER TABLE BLOCK) */
94 irep
->clen
= bin_to_uint16(src
); /* number of catch handler */
95 src
+= sizeof(uint16_t);
96 irep
->ilen
= bin_to_uint32(src
);
97 src
+= sizeof(uint32_t);
100 size_t data_len
= sizeof(mrb_code
) * irep
->ilen
+
101 sizeof(struct mrb_irep_catch_handler
) * irep
->clen
;
102 mrb_static_assert(sizeof(struct mrb_irep_catch_handler
) == 13);
103 if (SIZE_ERROR_MUL(irep
->ilen
, sizeof(mrb_code
))) {
106 if (src
+ data_len
> end
) return FALSE
;
107 if ((flags
& FLAG_SRC_MALLOC
) == 0) {
108 irep
->iseq
= (mrb_code
*)src
;
109 irep
->flags
|= MRB_ISEQ_NO_FREE
;
112 void *buf
= mrb_malloc(mrb
, data_len
);
113 irep
->iseq
= (mrb_code
*)buf
;
114 memcpy(buf
, src
, data_len
);
120 plen
= bin_to_uint16(src
); /* number of pool */
121 src
+= sizeof(uint16_t);
122 if (src
> end
) return FALSE
;
124 if (SIZE_ERROR_MUL(plen
, sizeof(mrb_value
))) {
127 irep
->pool
= pool
= (mrb_pool_value
*)mrb_calloc(mrb
, sizeof(mrb_pool_value
), plen
);
129 for (i
= 0; i
< plen
; i
++) {
130 mrb_bool st
= (flags
& FLAG_SRC_MALLOC
)==0;
132 tt
= *src
++; /* pool TT */
133 switch (tt
) { /* pool data */
136 if (src
+ sizeof(uint32_t) > end
) return FALSE
;
137 mrb_int v
= (int32_t)bin_to_uint32(src
);
138 src
+= sizeof(uint32_t);
140 pool
[i
].tt
= IREP_TT_INT64
;
141 pool
[i
].u
.i64
= (int64_t)v
;
143 pool
[i
].tt
= IREP_TT_INT32
;
151 if (src
+ sizeof(uint32_t)*2 > end
) return FALSE
;
152 uint64_t i64
= bin_to_uint32(src
);
153 src
+= sizeof(uint32_t);
155 i64
|= bin_to_uint32(src
);
156 src
+= sizeof(uint32_t);
158 pool
[i
].u
.i64
= (int64_t)i64
;
166 pool_data_len
= bin_to_uint8(src
) + 2; /* pool data length */
167 if (src
+ pool_data_len
> end
) return FALSE
;
170 pool
[i
].tt
= IREP_TT_BIGINT
;
171 p
= (char*)mrb_malloc(mrb
, pool_data_len
);
172 memcpy(p
, src
, pool_data_len
);
173 pool
[i
].u
.str
= (const char*)p
;
175 src
+= pool_data_len
;
180 if (src
+ sizeof(double) > end
) return FALSE
;
182 pool
[i
].u
.f
= str_to_double(mrb
, (const char*)src
);
183 src
+= sizeof(double);
186 return FALSE
; /* MRB_NO_FLOAT */
190 pool_data_len
= bin_to_uint16(src
); /* pool data length */
191 src
+= sizeof(uint16_t);
192 if (src
+ pool_data_len
> end
) return FALSE
;
194 pool
[i
].tt
= (pool_data_len
<<2) | IREP_TT_SSTR
;
195 pool
[i
].u
.str
= (const char*)src
;
199 pool
[i
].tt
= (pool_data_len
<<2) | IREP_TT_STR
;
200 p
= (char*)mrb_malloc(mrb
, pool_data_len
+1);
201 memcpy(p
, src
, pool_data_len
+1);
202 pool
[i
].u
.str
= (const char*)p
;
204 src
+= pool_data_len
+ 1;
208 /* should not happen */
216 irep
->slen
= bin_to_uint16(src
); /* syms length */
217 src
+= sizeof(uint16_t);
218 if (src
> end
) return FALSE
;
219 if (irep
->slen
> 0) {
220 if (SIZE_ERROR_MUL(irep
->slen
, sizeof(mrb_sym
))) {
223 irep
->syms
= syms
= (mrb_sym
*)mrb_malloc(mrb
, sizeof(mrb_sym
) * irep
->slen
);
225 for (i
= 0; i
< irep
->slen
; i
++) {
226 snl
= bin_to_uint16(src
); /* symbol name length */
227 src
+= sizeof(uint16_t);
229 if (snl
== MRB_DUMP_NULL_SYM_LEN
) {
234 if (src
+ snl
> end
) return FALSE
;
235 if (flags
& FLAG_SRC_MALLOC
) {
236 syms
[i
] = mrb_intern(mrb
, (char*)src
, snl
);
239 syms
[i
] = mrb_intern_static(mrb
, (char*)src
, snl
);
242 mrb_gc_arena_restore(mrb
, ai
);
247 mrb_assert_int_fit(ptrdiff_t, diff
, size_t, SIZE_MAX
);
254 read_irep_record(mrb_state
*mrb
, const uint8_t *bin
, const uint8_t *end
, size_t *len
, uint8_t flags
, mrb_irep
**irepp
)
256 int ai
= mrb_gc_arena_save(mrb
);
257 mrb_bool readsuccess
= read_irep_record_1(mrb
, bin
, end
, len
, flags
, irepp
);
261 mrb_gc_arena_restore(mrb
, ai
);
266 reps
= (mrb_irep
**)mrb_calloc(mrb
, (*irepp
)->rlen
, sizeof(mrb_irep
*));
267 (*irepp
)->reps
= (const mrb_irep
**)reps
;
270 for (i
=0; i
<(*irepp
)->rlen
; i
++) {
273 readsuccess
= read_irep_record(mrb
, bin
, end
, &rlen
, flags
, &reps
[i
]);
274 mrb_gc_arena_restore(mrb
, ai
);
286 read_section_irep(mrb_state
*mrb
, const uint8_t *bin
, size_t size
, uint8_t flags
, struct RProc
**proc
)
288 if (size
< sizeof(struct rite_section_irep_header
)) return NULL
;
290 * This proc object keeps all the data in progress to avoid memory leaks
291 * if something goes wrong while reading irep.
293 *proc
= mrb_proc_new(mrb
, NULL
);
295 mrb_irep
**irepp
= (mrb_irep
**)&(*proc
)->body
.irep
;
297 bin
+= sizeof(struct rite_section_irep_header
);
298 if (read_irep_record(mrb
, bin
, bin
+size
, &len
, flags
, irepp
)) {
307 read_debug_record(mrb_state
*mrb
, const uint8_t *start
, const uint8_t *end
, mrb_irep
* irep
, size_t *record_len
, const mrb_sym
*filenames
, size_t filenames_len
)
309 const uint8_t *bin
= start
;
314 mrb_irep_debug_info
*debug
;
316 if (irep
->debug_info
) { return MRB_DUMP_INVALID_IREP
; }
318 irep
->debug_info
= debug
= (mrb_irep_debug_info
*)mrb_calloc(mrb
, 1, sizeof(mrb_irep_debug_info
));
319 debug
->pc_count
= (uint32_t)irep
->ilen
;
321 record_size
= (size_t)bin_to_uint32(bin
);
322 bin
+= sizeof(uint32_t);
324 debug
->flen
= bin_to_uint16(bin
);
325 bin
+= sizeof(uint16_t);
326 if (bin
> end
) return MRB_DUMP_GENERAL_FAILURE
;
327 debug
->files
= (mrb_irep_debug_info_file
**)mrb_calloc(mrb
, irep
->debug_info
->flen
, sizeof(mrb_irep_debug_info
*));
329 for (f_idx
= 0; f_idx
< debug
->flen
; f_idx
++) {
330 mrb_irep_debug_info_file
*file
;
331 uint16_t filename_idx
;
333 if (bin
> end
) return MRB_DUMP_GENERAL_FAILURE
;
334 file
= (mrb_irep_debug_info_file
*)mrb_calloc(mrb
, 1, sizeof(*file
));
335 debug
->files
[f_idx
] = file
;
337 file
->start_pos
= bin_to_uint32(bin
);
338 bin
+= sizeof(uint32_t);
341 filename_idx
= bin_to_uint16(bin
);
342 bin
+= sizeof(uint16_t);
343 mrb_assert(filename_idx
< filenames_len
);
344 file
->filename_sym
= filenames
[filename_idx
];
346 file
->line_entry_count
= bin_to_uint32(bin
);
347 bin
+= sizeof(uint32_t);
348 file
->line_type
= (mrb_debug_line_type
)bin_to_uint8(bin
);
349 bin
+= sizeof(uint8_t);
350 switch (file
->line_type
) {
351 case mrb_debug_line_ary
: {
352 size_t l
= sizeof(uint16_t) * (size_t)file
->line_entry_count
;
354 if (bin
+ l
> end
) return MRB_DUMP_GENERAL_FAILURE
;
355 uint16_t *ary
= (uint16_t*)mrb_malloc(mrb
, l
);
356 for (l
= 0; l
< file
->line_entry_count
; l
++) {
357 ary
[l
] = bin_to_uint16(bin
);
358 bin
+= sizeof(uint16_t);
360 file
->lines
.ary
= ary
;
363 case mrb_debug_line_flat_map
: {
364 size_t c
= (size_t)file
->line_entry_count
;
365 size_t n
= sizeof(mrb_irep_debug_info_line
);
367 if (bin
+ c
*n
> end
) return MRB_DUMP_GENERAL_FAILURE
;
368 mrb_irep_debug_info_line
*flat_map
= (mrb_irep_debug_info_line
*)mrb_calloc(mrb
, c
, n
);
369 for (size_t l
= 0; l
< file
->line_entry_count
; l
++) {
370 flat_map
[l
].start_pos
= bin_to_uint32(bin
);
371 bin
+= sizeof(uint32_t);
372 flat_map
[l
].line
= bin_to_uint16(bin
);
373 bin
+= sizeof(uint16_t);
375 file
->lines
.flat_map
= flat_map
;
378 case mrb_debug_line_packed_map
: {
379 size_t l
= (size_t)file
->line_entry_count
;
381 if (bin
+ l
> end
) return MRB_DUMP_GENERAL_FAILURE
;
382 uint8_t *packed_map
= (uint8_t*)mrb_malloc(mrb
, l
);
383 memcpy(packed_map
, bin
, file
->line_entry_count
);
384 file
->lines
.packed_map
= packed_map
;
385 bin
+= file
->line_entry_count
;
388 default: return MRB_DUMP_GENERAL_FAILURE
;
393 mrb_assert_int_fit(ptrdiff_t, diff
, size_t, SIZE_MAX
);
395 if (record_size
!= (size_t)diff
) {
396 return MRB_DUMP_GENERAL_FAILURE
;
399 for (i
= 0; i
< irep
->rlen
; i
++) {
403 ret
= read_debug_record(mrb
, bin
, end
, (mrb_irep
*)irep
->reps
[i
], &len
, filenames
, filenames_len
);
404 if (ret
!= MRB_DUMP_OK
) return ret
;
409 mrb_assert_int_fit(ptrdiff_t, diff
, size_t, SIZE_MAX
);
410 *record_len
= (size_t)diff
;
416 read_section_debug(mrb_state
*mrb
, const uint8_t *start
, size_t size
, mrb_irep
*irep
, uint8_t flags
)
419 const uint8_t *end
= start
+ size
;
421 struct rite_section_debug_header
*header
;
425 uint16_t filenames_len
;
427 mrb_value filenames_obj
;
430 header
= (struct rite_section_debug_header
*)bin
;
431 bin
+= sizeof(struct rite_section_debug_header
);
433 filenames_len
= bin_to_uint16(bin
);
434 bin
+= sizeof(uint16_t);
435 if (bin
> end
) return MRB_DUMP_GENERAL_FAILURE
;
436 filenames_obj
= mrb_str_new(mrb
, NULL
, sizeof(mrb_sym
) * (size_t)filenames_len
);
437 filenames
= (mrb_sym
*)RSTRING_PTR(filenames_obj
);
438 for (i
= 0; i
< filenames_len
; i
++) {
439 uint16_t f_len
= bin_to_uint16(bin
);
440 bin
+= sizeof(uint16_t);
441 if (bin
+ f_len
> end
) {
442 result
= MRB_DUMP_GENERAL_FAILURE
;
445 if (flags
& FLAG_SRC_MALLOC
) {
446 filenames
[i
] = mrb_intern(mrb
, (const char*)bin
, (size_t)f_len
);
449 filenames
[i
] = mrb_intern_static(mrb
, (const char*)bin
, (size_t)f_len
);
454 result
= read_debug_record(mrb
, bin
, end
, irep
, &len
, filenames
, filenames_len
);
455 if (result
!= MRB_DUMP_OK
) goto debug_exit
;
459 mrb_assert_int_fit(ptrdiff_t, diff
, size_t, SIZE_MAX
);
460 if ((uint32_t)diff
!= bin_to_uint32(header
->section_size
)) {
461 result
= MRB_DUMP_GENERAL_FAILURE
;
465 mrb_str_resize(mrb
, filenames_obj
, 0);
470 read_lv_record(mrb_state
*mrb
, const uint8_t *start
, mrb_irep
*irep
, size_t *record_len
, mrb_sym
const *syms
, uint32_t syms_len
)
472 const uint8_t *bin
= start
;
477 if (irep
->nlocals
== 0) return MRB_DUMP_GENERAL_FAILURE
;
478 irep
->lv
= lv
= (mrb_sym
*)mrb_malloc(mrb
, sizeof(mrb_sym
) * (irep
->nlocals
- 1));
480 for (i
= 0; i
+ 1 < irep
->nlocals
; i
++) {
481 uint16_t const sym_idx
= bin_to_uint16(bin
);
482 bin
+= sizeof(uint16_t);
483 if (sym_idx
== RITE_LV_NULL_MARK
) {
487 if (sym_idx
>= syms_len
) {
488 return MRB_DUMP_GENERAL_FAILURE
;
490 lv
[i
] = syms
[sym_idx
];
494 for (i
= 0; i
< irep
->rlen
; i
++) {
498 ret
= read_lv_record(mrb
, bin
, (mrb_irep
*)irep
->reps
[i
], &len
, syms
, syms_len
);
499 if (ret
!= MRB_DUMP_OK
) return ret
;
504 mrb_assert_int_fit(ptrdiff_t, diff
, size_t, SIZE_MAX
);
505 *record_len
= (size_t)diff
;
511 read_section_lv(mrb_state
*mrb
, const uint8_t *start
, size_t size
, mrb_irep
*irep
, uint8_t flags
)
514 const uint8_t *end
= start
+ size
;
516 struct rite_section_lv_header
const *header
;
523 mrb_sym (*intern_func
)(mrb_state
*, const char*, size_t) =
524 (flags
& FLAG_SRC_MALLOC
)? mrb_intern
: mrb_intern_static
;
527 header
= (struct rite_section_lv_header
const*)bin
;
528 bin
+= sizeof(struct rite_section_lv_header
);
530 syms_len
= bin_to_uint32(bin
);
531 bin
+= sizeof(uint32_t);
532 if (bin
> end
) return MRB_DUMP_READ_FAULT
;
533 syms_obj
= mrb_str_new(mrb
, NULL
, sizeof(mrb_sym
) * (size_t)syms_len
);
534 syms
= (mrb_sym
*)RSTRING_PTR(syms_obj
);
535 for (i
= 0; i
< syms_len
; i
++) {
536 uint16_t const str_len
= bin_to_uint16(bin
);
537 bin
+= sizeof(uint16_t);
538 if (bin
> end
) return MRB_DUMP_READ_FAULT
;
539 syms
[i
] = intern_func(mrb
, (const char*)bin
, str_len
);
543 result
= read_lv_record(mrb
, bin
, irep
, &len
, syms
, syms_len
);
544 if (result
!= MRB_DUMP_OK
) goto lv_exit
;
548 mrb_assert_int_fit(ptrdiff_t, diff
, size_t, SIZE_MAX
);
549 if ((uint32_t)diff
!= bin_to_uint32(header
->section_size
)) {
550 result
= MRB_DUMP_GENERAL_FAILURE
;
554 mrb_str_resize(mrb
, syms_obj
, 0);
559 read_binary_header(const uint8_t *bin
, size_t bufsize
, size_t *bin_size
, uint8_t *flags
)
561 const struct rite_binary_header
*header
= (const struct rite_binary_header
*)bin
;
563 if (bufsize
< sizeof(struct rite_binary_header
)) {
564 return MRB_DUMP_READ_FAULT
;
567 if (memcmp(header
->binary_ident
, RITE_BINARY_IDENT
, sizeof(header
->binary_ident
)) != 0) {
568 return MRB_DUMP_INVALID_FILE_HEADER
;
571 /* if major version is different, they are incompatible */
572 if (memcmp(header
->major_version
, RITE_BINARY_MAJOR_VER
, sizeof(header
->major_version
)) != 0) {
573 return MRB_DUMP_INVALID_FILE_HEADER
;
575 /* if minor version is different, we can accept the older version */
576 if (memcmp(header
->minor_version
, RITE_BINARY_MINOR_VER
, sizeof(header
->minor_version
)) > 0) {
577 return MRB_DUMP_INVALID_FILE_HEADER
;
580 *bin_size
= (size_t)bin_to_uint32(header
->binary_size
);
582 if (bufsize
< *bin_size
) {
583 return MRB_DUMP_READ_FAULT
;
590 read_irep(mrb_state
*mrb
, const uint8_t *bin
, size_t bufsize
, uint8_t flags
)
593 struct RProc
*proc
= NULL
;
594 mrb_irep
*irep
= NULL
;
595 const struct rite_section_header
*section_header
;
598 if ((mrb
== NULL
) || (bin
== NULL
)) {
602 result
= read_binary_header(bin
, bufsize
, &bin_size
, &flags
);
603 if (result
!= MRB_DUMP_OK
) {
607 bin
+= sizeof(struct rite_binary_header
);
608 bin_size
-= sizeof(struct rite_binary_header
);
609 while (bin_size
> sizeof(struct rite_section_header
)) {
610 section_header
= (const struct rite_section_header
*)bin
;
611 uint32_t section_size
= bin_to_uint32(section_header
->section_size
);
612 if (bin_size
< section_size
) return NULL
;
613 if (memcmp(section_header
->section_ident
, RITE_SECTION_IREP_IDENT
, sizeof(section_header
->section_ident
)) == 0) {
614 irep
= read_section_irep(mrb
, bin
, bin_size
, flags
, &proc
);
615 if (!irep
) return NULL
;
617 else if (memcmp(section_header
->section_ident
, RITE_SECTION_DEBUG_IDENT
, sizeof(section_header
->section_ident
)) == 0) {
618 if (!irep
) return NULL
; /* corrupted data */
619 result
= read_section_debug(mrb
, bin
, bin_size
, irep
, flags
);
620 if (result
< MRB_DUMP_OK
) {
624 else if (memcmp(section_header
->section_ident
, RITE_SECTION_LV_IDENT
, sizeof(section_header
->section_ident
)) == 0) {
625 if (!irep
) return NULL
;
626 result
= read_section_lv(mrb
, bin
, bin_size
, irep
, flags
);
627 if (result
< MRB_DUMP_OK
) {
631 else if (memcmp(section_header
->section_ident
, RITE_BINARY_EOF
, sizeof(section_header
->section_ident
)) != 0) {
636 bin_size
-= section_size
;
643 mrb_proc_read_irep(mrb_state
*mrb
, const uint8_t *bin
)
645 uint8_t flags
= mrb_ro_data_p((char*)bin
) ? FLAG_SRC_STATIC
: FLAG_SRC_MALLOC
;
647 return read_irep(mrb
, bin
, (size_t)UINT32_MAX
, flags
);
650 DEFINE_READ_IREP_FUNC(
651 mrb_irep
*mrb_read_irep(mrb_state
*mrb
, const uint8_t *bin
),
652 mrb_proc_read_irep(mrb
, bin
))
655 mrb_proc_read_irep_buf(mrb_state
*mrb
, const void *buf
, size_t bufsize
)
657 return read_irep(mrb
, (const uint8_t*)buf
, bufsize
, FLAG_SRC_MALLOC
);
660 DEFINE_READ_IREP_FUNC(
661 MRB_API mrb_irep
*mrb_read_irep_buf(mrb_state
*mrb
, const void *buf
, size_t bufsize
),
662 mrb_proc_read_irep_buf(mrb
, buf
, bufsize
))
664 void mrb_exc_set(mrb_state
*mrb
, mrb_value exc
);
667 irep_error(mrb_state
*mrb
)
669 mrb_exc_set(mrb
, mrb_exc_new_lit(mrb
, E_SCRIPT_ERROR
, "irep load error"));
673 load_irep(mrb_state
*mrb
, struct RProc
*proc
, mrb_ccontext
*c
)
675 if (!proc
|| !proc
->body
.irep
) {
677 return mrb_nil_value();
680 if (c
&& c
->dump_result
) mrb_codedump_all(mrb
, proc
);
681 if (c
&& c
->no_exec
) return mrb_obj_value(proc
);
682 return mrb_top_run(mrb
, proc
, mrb_top_self(mrb
), 0);
686 mrb_load_irep_cxt(mrb_state
*mrb
, const uint8_t *bin
, mrb_ccontext
*c
)
688 struct RProc
*proc
= mrb_proc_read_irep(mrb
, bin
);
689 if (!proc
) return mrb_undef_value();
690 return load_irep(mrb
, proc
, c
);
694 mrb_load_irep_buf_cxt(mrb_state
*mrb
, const void *buf
, size_t bufsize
, mrb_ccontext
*c
)
696 return load_irep(mrb
, mrb_proc_read_irep_buf(mrb
, buf
, bufsize
), c
);
700 mrb_load_irep(mrb_state
*mrb
, const uint8_t *bin
)
702 return mrb_load_irep_cxt(mrb
, bin
, NULL
);
706 mrb_load_irep_buf(mrb_state
*mrb
, const void *buf
, size_t bufsize
)
708 return mrb_load_irep_buf_cxt(mrb
, buf
, bufsize
, NULL
);
712 mrb_load_proc(mrb_state
*mrb
, const struct RProc
*proc
)
714 return mrb_top_run(mrb
, proc
, mrb_top_self(mrb
), 0);
720 mrb_proc_read_irep_file(mrb_state
*mrb
, FILE *fp
)
722 struct RProc
*proc
= NULL
;
724 const size_t header_size
= sizeof(struct rite_binary_header
);
729 if ((mrb
== NULL
) || (fp
== NULL
)) {
733 buf
= (uint8_t*)mrb_malloc(mrb
, header_size
);
734 if (fread(buf
, header_size
, 1, fp
) == 0) {
737 result
= read_binary_header(buf
, (size_t)-1, &buf_size
, &flags
);
738 if (result
!= MRB_DUMP_OK
|| buf_size
<= header_size
) {
742 buf
= (uint8_t*)mrb_realloc(mrb
, buf
, buf_size
);
743 if (fread(buf
+header_size
, buf_size
-header_size
, 1, fp
) == 0) {
746 proc
= read_irep(mrb
, buf
, (size_t)-1, FLAG_SRC_MALLOC
);
753 DEFINE_READ_IREP_FUNC(
754 mrb_irep
*mrb_read_irep_file(mrb_state
*mrb
, FILE *fp
),
755 mrb_proc_read_irep_file(mrb
, fp
))
758 mrb_load_irep_file_cxt(mrb_state
*mrb
, FILE* fp
, mrb_ccontext
*c
)
760 return load_irep(mrb
, mrb_proc_read_irep_file(mrb
, fp
), c
);
764 mrb_load_irep_file(mrb_state
*mrb
, FILE* fp
)
766 return mrb_load_irep_file_cxt(mrb
, fp
, NULL
);
768 #endif /* MRB_NO_STDIO */