3 #include <mruby/irep.h>
4 #include <mruby/debug.h>
6 static mrb_irep_debug_info_file
*
7 get_file(mrb_irep_debug_info
*info
, uint32_t pc
)
9 if (pc
>= info
->pc_count
) { return NULL
; }
11 mrb_irep_debug_info_file
**ret
= info
->files
;
12 int32_t count
= info
->flen
;
15 int32_t step
= count
/ 2;
16 mrb_irep_debug_info_file
**it
= ret
+ step
;
17 if (!(pc
< (*it
)->start_pos
)) {
21 else { count
= step
; }
26 /* check returning file exists inside debug info */
27 mrb_assert(info
->files
<= ret
&& ret
< (info
->files
+ info
->flen
));
28 /* check pc is within the range of returning file */
29 mrb_assert((*ret
)->start_pos
<= pc
&&
30 pc
< (((ret
+ 1 - info
->files
) < info
->flen
)
31 ? (*(ret
+1))->start_pos
: info
->pc_count
));
37 mrb_packed_int_len(uint32_t num
)
48 mrb_packed_int_encode(uint32_t num
, uint8_t *p
)
53 uint8_t byte
= num
& 0x7f;
55 if (num
!= 0) byte
|= 0x80;
64 mrb_packed_int_decode(const uint8_t *p
, const uint8_t **newpos
)
66 size_t i
= 0, shift
= 0;
70 n
|= ((uint32_t)(p
[i
] & 0x7f)) << shift
;
73 } while (shift
< sizeof(uint32_t) * 8 && (p
[i
- 1] & 0x80));
74 if (newpos
) *newpos
= p
+ i
;
79 debug_get_filename(mrb_state
*mrb
, mrb_irep_debug_info_file
* f
)
81 if (f
== NULL
) return NULL
;
82 return mrb_sym_name_len(mrb
, f
->filename_sym
, NULL
);
86 debug_get_line(mrb_state
*mrb
, mrb_irep_debug_info_file
* f
, uint32_t pc
)
88 if (f
== NULL
) return -1;
89 switch (f
->line_type
) {
90 case mrb_debug_line_ary
:
91 case mrb_debug_line_flat_map
:
95 case mrb_debug_line_packed_map
:
97 const uint8_t *p
= f
->lines
.packed_map
;
98 const uint8_t *pend
= p
+ f
->line_entry_count
;
99 uint32_t pos
= 0, line
= 0;
101 pos
+= mrb_packed_int_decode(p
, &p
);
102 uint32_t line_diff
= mrb_packed_int_decode(p
, &p
);
113 mrb_debug_get_filename(mrb_state
*mrb
, const mrb_irep
*irep
, uint32_t pc
)
115 if (irep
&& pc
< irep
->ilen
) {
116 if (!irep
->debug_info
) return NULL
;
117 return debug_get_filename(mrb
, get_file(irep
->debug_info
, pc
));
123 mrb_debug_get_line(mrb_state
*mrb
, const mrb_irep
*irep
, uint32_t pc
)
125 if (irep
&& pc
< irep
->ilen
) {
126 if (!irep
->debug_info
) return -1;
127 return debug_get_line(mrb
, get_file(irep
->debug_info
, pc
), pc
);
133 mrb_debug_get_position(mrb_state
*mrb
, const mrb_irep
*irep
, uint32_t pc
, int32_t *lp
, const char **fp
)
135 if (irep
&& pc
< irep
->ilen
&& irep
->debug_info
) {
136 mrb_irep_debug_info_file
*f
= get_file(irep
->debug_info
, pc
);
137 *lp
= debug_get_line(mrb
, f
, pc
);
139 *fp
= debug_get_filename(mrb
, f
);
140 if (*fp
) return TRUE
;
143 *lp
= -1; *fp
= NULL
;
147 MRB_API mrb_irep_debug_info
*
148 mrb_debug_info_alloc(mrb_state
*mrb
, mrb_irep
*irep
)
150 static const mrb_irep_debug_info initial
= { 0, 0, NULL
};
152 mrb_assert(!irep
->debug_info
);
153 mrb_irep_debug_info
*ret
= (mrb_irep_debug_info
*)mrb_malloc(mrb
, sizeof(*ret
));
155 irep
->debug_info
= ret
;
159 MRB_API mrb_irep_debug_info_file
*
160 mrb_debug_info_append_file(mrb_state
*mrb
, mrb_irep_debug_info
*d
,
161 const char *filename
, uint16_t *lines
,
162 uint32_t start_pos
, uint32_t end_pos
)
165 if (start_pos
== end_pos
) return NULL
;
167 mrb_assert(filename
);
171 const char *fn
= mrb_sym_name_len(mrb
, d
->files
[d
->flen
- 1]->filename_sym
, NULL
);
172 if (strcmp(filename
, fn
) == 0)
176 mrb_irep_debug_info_file
*f
= (mrb_irep_debug_info_file
*)mrb_malloc(mrb
, sizeof(*f
));
177 d
->files
= (mrb_irep_debug_info_file
**)mrb_realloc(mrb
, d
->files
, sizeof(mrb_irep_debug_info_file
*) * (d
->flen
+ 1));
178 d
->files
[d
->flen
++] = f
;
180 uint32_t file_pc_count
= end_pos
- start_pos
;
181 f
->start_pos
= start_pos
;
182 d
->pc_count
= end_pos
;
184 size_t fn_len
= strlen(filename
);
185 f
->filename_sym
= mrb_intern(mrb
, filename
, fn_len
);
186 f
->line_type
= mrb_debug_line_packed_map
;
189 uint16_t prev_line
= 0;
190 uint32_t prev_pc
= 0;
191 size_t packed_size
= 0;
194 for (uint32_t i
= 0; i
< file_pc_count
; i
++) {
195 if (lines
[start_pos
+ i
] == prev_line
) continue;
196 packed_size
+= mrb_packed_int_len(start_pos
+i
-prev_pc
);
197 prev_pc
= start_pos
+i
;
198 packed_size
+= mrb_packed_int_len(lines
[start_pos
+i
]-prev_line
);
199 prev_line
= lines
[start_pos
+ i
];
201 f
->lines
.packed_map
= p
= (uint8_t*)mrb_malloc(mrb
, packed_size
);
202 prev_line
= 0; prev_pc
= 0;
203 for (uint32_t i
= 0; i
< file_pc_count
; i
++) {
204 if (lines
[start_pos
+ i
] == prev_line
) continue;
205 p
+= mrb_packed_int_encode(start_pos
+i
-prev_pc
, p
);
206 prev_pc
= start_pos
+ i
;
207 p
+= mrb_packed_int_encode(lines
[start_pos
+ i
]-prev_line
, p
);
208 prev_line
= lines
[start_pos
+ i
];
210 f
->line_entry_count
= (uint32_t)packed_size
;
216 mrb_debug_info_free(mrb_state
*mrb
, mrb_irep_debug_info
*d
)
221 for (uint32_t i
= 0; i
< d
->flen
; i
++) {
223 mrb_free(mrb
, d
->files
[i
]->lines
.ptr
);
224 mrb_free(mrb
, d
->files
[i
]);
227 mrb_free(mrb
, d
->files
);