@@ -58,6 +58,12 @@ static void module_add_label(Module *mod, int index, const uint8_t *ptr);
58
58
static enum ModuleLoadResult module_build_imported_functions_table (Module * this_module , uint8_t * table_data , GlobalContext * glb );
59
59
static void module_parse_line_table (Module * mod , const uint8_t * data , size_t len );
60
60
61
+ struct LineRefOffset
62
+ {
63
+ struct ListHead head ;
64
+ unsigned int offset ;
65
+ };
66
+
61
67
#define IMPL_CODE_LOADER 1
62
68
#include "opcodesswitch.h"
63
69
#undef TRACE
@@ -285,7 +291,6 @@ Module *module_new_from_iff_binary(GlobalContext *global, const void *iff_binary
285
291
}
286
292
287
293
module_parse_line_table (mod , beam_file + offsets [LINT ] + 8 , sizes [LINT ]);
288
- list_init (& mod -> line_ref_offsets );
289
294
290
295
if (offsets [LITT ]) {
291
296
if (!module_are_literals_compressed (beam_file + offsets [LITT ])) {
@@ -320,7 +325,40 @@ Module *module_new_from_iff_binary(GlobalContext *global, const void *iff_binary
320
325
mod -> free_literals_data = 0 ;
321
326
}
322
327
323
- mod -> end_instruction_ii = read_core_chunk (mod );
328
+ struct ListHead line_refs ;
329
+ list_init (& line_refs );
330
+ mod -> end_instruction_ii = read_core_chunk (mod , & line_refs );
331
+
332
+ // Create the list of offsets if the module has line informations.
333
+ if (mod -> line_refs_table != NULL ) {
334
+ // Compute the size of the list
335
+ size_t num_offsets = 0 ;
336
+ struct ListHead * item = line_refs .next ;
337
+ while (item != & line_refs ) {
338
+ num_offsets ++ ;
339
+ item = item -> next ;
340
+ }
341
+ mod -> line_refs_offsets = malloc (num_offsets * sizeof (unsigned int ));
342
+ if (IS_NULL_PTR (mod -> line_refs_offsets )) {
343
+ 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 );
344
+ } else {
345
+ size_t index = 0 ;
346
+ item = line_refs .next ;
347
+ while (item != & line_refs ) {
348
+ struct LineRefOffset * offset = CONTAINER_OF (item , struct LineRefOffset , head );
349
+ mod -> line_refs_offsets [index ] = offset -> offset ;
350
+ index ++ ;
351
+ item = item -> next ;
352
+ }
353
+ mod -> line_refs_offsets_count = num_offsets ;
354
+ }
355
+ }
356
+ // Empty the list
357
+ while (!list_is_empty (& line_refs )) {
358
+ struct ListHead * item = line_refs .next ;
359
+ list_remove (item );
360
+ free (item );
361
+ }
324
362
325
363
return mod ;
326
364
}
@@ -331,6 +369,7 @@ COLD_FUNC void module_destroy(Module *module)
331
369
free (module -> imported_funcs );
332
370
free (module -> literals_table );
333
371
free (module -> local_atoms_to_global_table );
372
+ free (module -> line_refs_offsets );
334
373
if (module -> free_literals_data ) {
335
374
free (module -> literals_data );
336
375
}
@@ -718,19 +757,28 @@ static void module_parse_line_table(Module *mod, const uint8_t *data, size_t len
718
757
}
719
758
}
720
759
721
- void module_insert_line_ref_offset (Module * mod , int line_ref , int offset )
760
+ void module_insert_line_ref_offset (Module * mod , struct ListHead * line_refs , uint32_t line_ref , int offset )
722
761
{
723
762
if (IS_NULL_PTR (mod -> line_refs_table ) || line_ref == 0 ) {
724
763
return ;
725
764
}
726
765
struct LineRefOffset * ref_offset = malloc (sizeof (struct LineRefOffset ));
727
766
if (IS_NULL_PTR (ref_offset )) {
728
- fprintf (stderr , "Warning: Unable to allocate space for line ref offset. Line information in stacktraces may be missing\n" );
767
+ size_t num_refs = 0 ;
768
+ // Empty the list
769
+ while (!list_is_empty (line_refs )) {
770
+ struct ListHead * item = line_refs -> next ;
771
+ list_remove (item );
772
+ free (item );
773
+ num_refs ++ ;
774
+ }
775
+ 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 );
776
+ // Give up having line numbers for this module.
777
+ mod -> line_refs_table = NULL ;
729
778
return ;
730
779
}
731
- ref_offset -> line_ref = line_ref ;
732
780
ref_offset -> offset = offset ;
733
- list_append (& mod -> line_ref_offsets , & ref_offset -> head );
781
+ list_append (line_refs , & ref_offset -> head );
734
782
}
735
783
736
784
static bool module_find_line_ref (Module * mod , uint16_t line_ref , uint32_t * line , size_t * filename_len , const uint8_t * * filename )
@@ -744,30 +792,30 @@ static bool module_find_line_ref(Module *mod, uint16_t line_ref, uint32_t *line,
744
792
745
793
bool module_find_line (Module * mod , unsigned int offset , uint32_t * line , size_t * filename_len , const uint8_t * * filename )
746
794
{
747
- int i = 0 ;
748
- struct LineRefOffset * head = GET_LIST_ENTRY (& mod -> line_ref_offsets , struct LineRefOffset , head );
749
- struct ListHead * item ;
750
- LIST_FOR_EACH (item , & mod -> line_ref_offsets ) {
751
- struct LineRefOffset * ref_offset = GET_LIST_ENTRY (item , struct LineRefOffset , head );
752
-
753
- if (offset == ref_offset -> offset ) {
754
- return module_find_line_ref (mod , ref_offset -> line_ref , line , filename_len , filename );
755
- } else if (i == 0 && offset < ref_offset -> offset ) {
795
+ size_t i ;
796
+ unsigned int ref_offset ;
797
+ uint32_t line_ref ;
798
+ const uint8_t * ref_pc ;
799
+ if (IS_NULL_PTR (mod -> line_refs_offsets )) {
800
+ return false;
801
+ }
802
+ for (i = 0 ; i < mod -> line_refs_offsets_count ; i ++ ) {
803
+ ref_offset = mod -> line_refs_offsets [i ];
804
+ if (offset == ref_offset ) {
805
+ ref_pc = & mod -> code -> code [ref_offset ];
806
+ DECODE_LITERAL (line_ref , ref_pc );
807
+ return module_find_line_ref (mod , line_ref , line , filename_len , filename );
808
+ } else if (i == 0 && offset < ref_offset ) {
756
809
return false;
757
- } else {
758
-
759
- struct LineRefOffset * prev_ref_offset = GET_LIST_ENTRY (ref_offset -> head .prev , struct LineRefOffset , head );
760
- if (prev_ref_offset -> offset <= offset && offset < ref_offset -> offset ) {
761
- return module_find_line_ref (mod , prev_ref_offset -> line_ref , line , filename_len , filename );
762
- }
763
-
764
- struct LineRefOffset * next_ref_offset = GET_LIST_ENTRY (ref_offset -> head .next , struct LineRefOffset , head );
765
- if (next_ref_offset == head && ref_offset -> offset <= offset ) {
766
- return module_find_line_ref (mod , ref_offset -> line_ref , line , filename_len , filename );
767
- }
810
+ } else if (offset < ref_offset ) {
811
+ ref_offset = mod -> line_refs_offsets [i - 1 ];
812
+ ref_pc = & mod -> code -> code [ref_offset ];
813
+ DECODE_LITERAL (line_ref , ref_pc );
814
+ return module_find_line_ref (mod , line_ref , line , filename_len , filename );
768
815
}
769
-
770
- ++ i ;
771
816
}
772
- return false;
817
+ ref_offset = mod -> line_refs_offsets [i - 1 ];
818
+ ref_pc = & mod -> code -> code [ref_offset ];
819
+ DECODE_LITERAL (line_ref , ref_pc );
820
+ return module_find_line_ref (mod , line_ref , line , filename_len , filename );
773
821
}
0 commit comments