@@ -57,6 +57,12 @@ static void module_add_label(Module *mod, int index, const uint8_t *ptr);
57
57
static enum ModuleLoadResult module_build_imported_functions_table (Module * this_module , uint8_t * table_data , GlobalContext * glb );
58
58
static void module_parse_line_table (Module * mod , const uint8_t * data , size_t len );
59
59
60
+ struct LineRefOffset
61
+ {
62
+ struct ListHead head ;
63
+ unsigned int offset ;
64
+ };
65
+
60
66
#define IMPL_CODE_LOADER 1
61
67
#include "opcodesswitch.h"
62
68
#undef TRACE
@@ -276,7 +282,6 @@ Module *module_new_from_iff_binary(GlobalContext *global, const void *iff_binary
276
282
}
277
283
278
284
module_parse_line_table (mod , beam_file + offsets [LINT ] + 8 , sizes [LINT ]);
279
- list_init (& mod -> line_ref_offsets );
280
285
281
286
if (offsets [LITT ]) {
282
287
#ifdef WITH_ZLIB
@@ -305,7 +310,40 @@ Module *module_new_from_iff_binary(GlobalContext *global, const void *iff_binary
305
310
mod -> free_literals_data = 0 ;
306
311
}
307
312
308
- mod -> end_instruction_ii = read_core_chunk (mod );
313
+ struct ListHead line_refs ;
314
+ list_init (& line_refs );
315
+ mod -> end_instruction_ii = read_core_chunk (mod , & line_refs );
316
+
317
+ // Create the list of offsets if the module has line informations.
318
+ if (mod -> line_refs_table != NULL ) {
319
+ // Compute the size of the list
320
+ size_t num_offsets = 0 ;
321
+ struct ListHead * item = line_refs .next ;
322
+ while (item != & line_refs ) {
323
+ num_offsets ++ ;
324
+ item = item -> next ;
325
+ }
326
+ mod -> line_refs_offsets = malloc (num_offsets * sizeof (unsigned int ));
327
+ if (IS_NULL_PTR (mod -> line_refs_offsets )) {
328
+ fprintf (stderr , "Warning: Unable to allocate space for line refs offset, module has %zu offsets. Line information in stacktraces may be missing\n" , num_offsets );
329
+ } else {
330
+ size_t index = 0 ;
331
+ item = line_refs .next ;
332
+ while (item != & line_refs ) {
333
+ struct LineRefOffset * offset = CONTAINER_OF (item , struct LineRefOffset , head );
334
+ mod -> line_refs_offsets [index ] = offset -> offset ;
335
+ index ++ ;
336
+ item = item -> next ;
337
+ }
338
+ mod -> line_refs_offsets_count = num_offsets ;
339
+ }
340
+ }
341
+ // Empty the list
342
+ while (!list_is_empty (& line_refs )) {
343
+ struct ListHead * item = line_refs .next ;
344
+ list_remove (item );
345
+ free (item );
346
+ }
309
347
310
348
return mod ;
311
349
}
@@ -316,6 +354,7 @@ COLD_FUNC void module_destroy(Module *module)
316
354
free (module -> imported_funcs );
317
355
free (module -> literals_table );
318
356
free (module -> local_atoms_to_global_table );
357
+ free (module -> line_refs_offsets );
319
358
if (module -> free_literals_data ) {
320
359
free (module -> literals_data );
321
360
}
@@ -697,19 +736,28 @@ static void module_parse_line_table(Module *mod, const uint8_t *data, size_t len
697
736
}
698
737
}
699
738
700
- void module_insert_line_ref_offset (Module * mod , int line_ref , int offset )
739
+ void module_insert_line_ref_offset (Module * mod , struct ListHead * line_refs , uint32_t line_ref , int offset )
701
740
{
702
741
if (IS_NULL_PTR (mod -> line_refs_table ) || line_ref == 0 ) {
703
742
return ;
704
743
}
705
744
struct LineRefOffset * ref_offset = malloc (sizeof (struct LineRefOffset ));
706
745
if (IS_NULL_PTR (ref_offset )) {
707
- fprintf (stderr , "Warning: Unable to allocate space for line ref offset. Line information in stacktraces may be missing\n" );
746
+ size_t num_refs = 0 ;
747
+ // Empty the list
748
+ while (!list_is_empty (line_refs )) {
749
+ struct ListHead * item = line_refs -> next ;
750
+ list_remove (item );
751
+ free (item );
752
+ num_refs ++ ;
753
+ }
754
+ fprintf (stderr , "Warning: Unable to allocate space for an additional line ref offset (we had %zu). Line information in stacktraces may be missing\n" , num_refs );
755
+ // Give up having line numbers for this module.
756
+ mod -> line_refs_table = NULL ;
708
757
return ;
709
758
}
710
- ref_offset -> line_ref = line_ref ;
711
759
ref_offset -> offset = offset ;
712
- list_append (& mod -> line_ref_offsets , & ref_offset -> head );
760
+ list_append (line_refs , & ref_offset -> head );
713
761
}
714
762
715
763
static bool module_find_line_ref (Module * mod , uint16_t line_ref , uint32_t * line , size_t * filename_len , const uint8_t * * filename )
@@ -723,30 +771,30 @@ static bool module_find_line_ref(Module *mod, uint16_t line_ref, uint32_t *line,
723
771
724
772
bool module_find_line (Module * mod , unsigned int offset , uint32_t * line , size_t * filename_len , const uint8_t * * filename )
725
773
{
726
- int i = 0 ;
727
- struct LineRefOffset * head = GET_LIST_ENTRY (& mod -> line_ref_offsets , struct LineRefOffset , head );
728
- struct ListHead * item ;
729
- LIST_FOR_EACH (item , & mod -> line_ref_offsets ) {
730
- struct LineRefOffset * ref_offset = GET_LIST_ENTRY (item , struct LineRefOffset , head );
731
-
732
- if (offset == ref_offset -> offset ) {
733
- return module_find_line_ref (mod , ref_offset -> line_ref , line , filename_len , filename );
734
- } else if (i == 0 && offset < ref_offset -> offset ) {
774
+ size_t i ;
775
+ unsigned int ref_offset ;
776
+ uint32_t line_ref ;
777
+ const uint8_t * ref_pc ;
778
+ if (IS_NULL_PTR (mod -> line_refs_offsets )) {
779
+ return false;
780
+ }
781
+ for (i = 0 ; i < mod -> line_refs_offsets_count ; i ++ ) {
782
+ ref_offset = mod -> line_refs_offsets [i ];
783
+ if (offset == ref_offset ) {
784
+ ref_pc = & mod -> code -> code [ref_offset ];
785
+ DECODE_LITERAL (line_ref , ref_pc );
786
+ return module_find_line_ref (mod , line_ref , line , filename_len , filename );
787
+ } else if (i == 0 && offset < ref_offset ) {
735
788
return false;
736
- } else {
737
-
738
- struct LineRefOffset * prev_ref_offset = GET_LIST_ENTRY (ref_offset -> head .prev , struct LineRefOffset , head );
739
- if (prev_ref_offset -> offset <= offset && offset < ref_offset -> offset ) {
740
- return module_find_line_ref (mod , prev_ref_offset -> line_ref , line , filename_len , filename );
741
- }
742
-
743
- struct LineRefOffset * next_ref_offset = GET_LIST_ENTRY (ref_offset -> head .next , struct LineRefOffset , head );
744
- if (next_ref_offset == head && ref_offset -> offset <= offset ) {
745
- return module_find_line_ref (mod , ref_offset -> line_ref , line , filename_len , filename );
746
- }
789
+ } else if (offset < ref_offset ) {
790
+ ref_offset = mod -> line_refs_offsets [i - 1 ];
791
+ ref_pc = & mod -> code -> code [ref_offset ];
792
+ DECODE_LITERAL (line_ref , ref_pc );
793
+ return module_find_line_ref (mod , line_ref , line , filename_len , filename );
747
794
}
748
-
749
- ++ i ;
750
795
}
751
- return false;
796
+ ref_offset = mod -> line_refs_offsets [i - 1 ];
797
+ ref_pc = & mod -> code -> code [ref_offset ];
798
+ DECODE_LITERAL (line_ref , ref_pc );
799
+ return module_find_line_ref (mod , line_ref , line , filename_len , filename );
752
800
}
0 commit comments