10
10
use std:: borrow:: Cow ;
11
11
use std:: fmt;
12
12
use std:: marker:: PhantomData ;
13
- use std:: ops:: Deref ;
13
+ use std:: ops:: { Deref , RangeBounds } ;
14
14
15
15
use fallible_iterator:: FallibleIterator ;
16
16
use gimli:: read:: { AttributeValue , Range } ;
@@ -317,7 +317,7 @@ impl<'d, 'a> UnitRef<'d, 'a> {
317
317
/// abbrev can only be temporarily accessed in the callback.
318
318
fn resolve_reference < T , F > ( & self , attr : Attribute < ' d > , f : F ) -> Result < Option < T > , DwarfError >
319
319
where
320
- F : FnOnce ( UnitRef < ' d , ' _ > , & Die < ' d , ' _ > ) -> Result < Option < T > , DwarfError > ,
320
+ F : FnOnce ( Self , & Die < ' d , ' _ > ) -> Result < Option < T > , DwarfError > ,
321
321
{
322
322
let ( unit, offset) = match attr. value ( ) {
323
323
AttributeValue :: UnitRef ( offset) => ( * self , offset) ,
@@ -337,7 +337,11 @@ impl<'d, 'a> UnitRef<'d, 'a> {
337
337
}
338
338
339
339
/// Resolves the function name of a debug entry.
340
- fn resolve_function_name ( & self , entry : & Die < ' d , ' _ > ) -> Result < Option < Name < ' d > > , DwarfError > {
340
+ fn resolve_function_name (
341
+ & self ,
342
+ entry : & Die < ' d , ' _ > ,
343
+ language : Language ,
344
+ ) -> Result < Option < Name < ' d > > , DwarfError > {
341
345
let mut attrs = entry. attrs ( ) ;
342
346
let mut fallback_name = None ;
343
347
let mut reference_target = None ;
@@ -348,7 +352,7 @@ impl<'d, 'a> UnitRef<'d, 'a> {
348
352
constants:: DW_AT_linkage_name | constants:: DW_AT_MIPS_linkage_name => {
349
353
return Ok ( self
350
354
. string_value ( attr. value ( ) )
351
- . map ( |n| Name :: new ( n, NameMangling :: Mangled , Language :: Unknown ) ) ) ;
355
+ . map ( |n| Name :: new ( n, NameMangling :: Mangled , language ) ) ) ;
352
356
}
353
357
constants:: DW_AT_name => {
354
358
fallback_name = Some ( attr) ;
@@ -363,14 +367,14 @@ impl<'d, 'a> UnitRef<'d, 'a> {
363
367
if let Some ( attr) = fallback_name {
364
368
return Ok ( self
365
369
. string_value ( attr. value ( ) )
366
- . map ( |n| Name :: new ( n, NameMangling :: Unmangled , Language :: Unknown ) ) ) ;
370
+ . map ( |n| Name :: new ( n, NameMangling :: Unmangled , language ) ) ) ;
367
371
}
368
372
369
373
if let Some ( attr) = reference_target {
370
374
return self . resolve_reference ( attr, |ref_unit, ref_entry| {
371
375
if self . unit . offset != ref_unit. unit . offset || entry. offset ( ) != ref_entry. offset ( )
372
376
{
373
- ref_unit. resolve_function_name ( ref_entry)
377
+ ref_unit. resolve_function_name ( ref_entry, language )
374
378
} else {
375
379
Ok ( None )
376
380
}
@@ -387,6 +391,7 @@ struct DwarfUnit<'d, 'a> {
387
391
inner : UnitRef < ' d , ' a > ,
388
392
language : Language ,
389
393
line_program : Option < DwarfLineProgram < ' d > > ,
394
+ prefer_dwarf_names : bool ,
390
395
}
391
396
392
397
impl < ' d , ' a > DwarfUnit < ' d , ' a > {
@@ -419,10 +424,20 @@ impl<'d, 'a> DwarfUnit<'d, 'a> {
419
424
None => None ,
420
425
} ;
421
426
427
+ let producer = match entry. attr_value ( constants:: DW_AT_producer ) ? {
428
+ Some ( AttributeValue :: String ( string) ) => Some ( string) ,
429
+ _ => None ,
430
+ } ;
431
+
432
+ // Trust the symbol table more to contain accurate mangled names. However, since Dart's name
433
+ // mangling is lossy, we need to load the demangled name instead.
434
+ let prefer_dwarf_names = producer. as_deref ( ) == Some ( b"Dart VM" ) ;
435
+
422
436
Ok ( Some ( DwarfUnit {
423
437
inner : UnitRef { info, unit } ,
424
438
language,
425
439
line_program,
440
+ prefer_dwarf_names,
426
441
} ) )
427
442
}
428
443
@@ -621,6 +636,24 @@ impl<'d, 'a> DwarfUnit<'d, 'a> {
621
636
. map ( |file| self . file_info ( line_program, file) )
622
637
}
623
638
639
+ /// Resolves the name of a function from the symbol table.
640
+ fn resolve_symbol_name < R > ( & self , range : R ) -> Option < Name < ' d > >
641
+ where
642
+ R : RangeBounds < u64 > ,
643
+ {
644
+ let symbol = self . inner . info . symbol_map . lookup_range ( range) ?;
645
+ let name = symbol. name . clone ( ) ?;
646
+ Some ( Name :: new ( name, NameMangling :: Mangled , self . language ) )
647
+ }
648
+
649
+ /// Resolves the name of a function from DWARF debug information.
650
+ fn resolve_dwarf_name ( & self , entry : & Die < ' d , ' _ > ) -> Option < Name < ' d > > {
651
+ self . inner
652
+ . resolve_function_name ( entry, self . language )
653
+ . ok ( )
654
+ . flatten ( )
655
+ }
656
+
624
657
/// Collects all functions within this compilation unit.
625
658
fn functions ( & self , range_buf : & mut Vec < Range > ) -> Result < Vec < Function < ' d > > , DwarfError > {
626
659
let mut depth = 0 ;
@@ -684,25 +717,15 @@ impl<'d, 'a> DwarfUnit<'d, 'a> {
684
717
//
685
718
// XXX: Maybe we should actually parse the ranges in the resolve function and always
686
719
// look at the symbol table based on the start of the DIE range.
687
- let symbol_name = if !inline {
688
- self . inner
689
- . info
690
- . symbol_map
691
- . lookup_range ( function_address..function_end)
692
- . and_then ( |symbol| {
693
- symbol
694
- . name
695
- . clone ( )
696
- . map ( |n| Name :: new ( n, NameMangling :: Mangled , self . language ) )
697
- } )
698
- } else {
720
+ let symbol_name = if self . prefer_dwarf_names || inline {
699
721
None
722
+ } else {
723
+ self . resolve_symbol_name ( function_address..function_end)
700
724
} ;
701
725
702
- let mut name = symbol_name
703
- . or_else ( || self . inner . resolve_function_name ( entry) . ok ( ) . flatten ( ) )
704
- . unwrap_or_else ( || Name :: from ( "" ) ) ;
705
- name. set_language ( self . language ) ;
726
+ let name = symbol_name
727
+ . or_else ( || self . resolve_dwarf_name ( entry) )
728
+ . unwrap_or_else ( || Name :: new ( "" , NameMangling :: Unmangled , self . language ) ) ;
706
729
707
730
// Avoid constant allocations by collecting repeatedly into the same buffer and
708
731
// draining the results out of it. This keeps the original buffer allocated and
0 commit comments