@@ -3,7 +3,8 @@ use super::mystd::fs;
3
3
use super :: mystd:: os:: unix:: ffi:: { OsStrExt , OsStringExt } ;
4
4
use super :: mystd:: path:: { Path , PathBuf } ;
5
5
use super :: Either ;
6
- use super :: { Context , Mapping , Stash , Vec } ;
6
+ use super :: { gimli, Context , Endian , EndianSlice , Mapping , Stash , Vec } ;
7
+ use alloc:: sync:: Arc ;
7
8
use core:: convert:: { TryFrom , TryInto } ;
8
9
use core:: str;
9
10
use object:: elf:: { ELFCOMPRESS_ZLIB , ELF_NOTE_GNU , NT_GNU_BUILD_ID , SHF_COMPRESSED } ;
@@ -24,24 +25,26 @@ impl Mapping {
24
25
25
26
// Try to locate an external debug file using the build ID.
26
27
if let Some ( path_debug) = object. build_id ( ) . and_then ( locate_build_id) {
27
- if let Some ( mapping) = Mapping :: new_debug ( path_debug, None ) {
28
+ if let Some ( mapping) = Mapping :: new_debug ( path , path_debug, None ) {
28
29
return Some ( Either :: A ( mapping) ) ;
29
30
}
30
31
}
31
32
32
33
// Try to locate an external debug file using the GNU debug link section.
33
34
if let Some ( ( path_debug, crc) ) = object. gnu_debuglink_path ( path) {
34
- if let Some ( mapping) = Mapping :: new_debug ( path_debug, Some ( crc) ) {
35
+ if let Some ( mapping) = Mapping :: new_debug ( path , path_debug, Some ( crc) ) {
35
36
return Some ( Either :: A ( mapping) ) ;
36
37
}
37
38
}
38
39
39
- Context :: new ( stash, object, None ) . map ( Either :: B )
40
+ let dwp = Mapping :: load_dwarf_package ( path, stash) ;
41
+
42
+ Context :: new ( stash, object, None , dwp) . map ( Either :: B )
40
43
} )
41
44
}
42
45
43
46
/// Load debuginfo from an external debug file.
44
- fn new_debug ( path : PathBuf , crc : Option < u32 > ) -> Option < Mapping > {
47
+ fn new_debug ( original_path : & Path , path : PathBuf , crc : Option < u32 > ) -> Option < Mapping > {
45
48
let map = super :: mmap ( & path) ?;
46
49
Mapping :: mk ( map, |map, stash| {
47
50
let object = Object :: parse ( & map) ?;
@@ -51,20 +54,45 @@ impl Mapping {
51
54
}
52
55
53
56
// Try to locate a supplementary object file.
57
+ let mut sup = None ;
54
58
if let Some ( ( path_sup, build_id_sup) ) = object. gnu_debugaltlink_path ( & path) {
55
59
if let Some ( map_sup) = super :: mmap ( & path_sup) {
56
- let map_sup = stash. set_mmap_aux ( map_sup) ;
57
- if let Some ( sup ) = Object :: parse ( map_sup) {
58
- if sup . build_id ( ) == Some ( build_id_sup) {
59
- return Context :: new ( stash , object , Some ( sup ) ) ;
60
+ let map_sup = stash. cache_mmap ( map_sup) ;
61
+ if let Some ( sup_ ) = Object :: parse ( map_sup) {
62
+ if sup_ . build_id ( ) == Some ( build_id_sup) {
63
+ sup = Some ( sup_ ) ;
60
64
}
61
65
}
62
66
}
63
67
}
64
68
65
- Context :: new ( stash, object, None )
69
+ let dwp = Mapping :: load_dwarf_package ( original_path, stash) ;
70
+
71
+ Context :: new ( stash, object, sup, dwp)
66
72
} )
67
73
}
74
+
75
+ /// Try to locate a DWARF package file.
76
+ fn load_dwarf_package < ' data > ( path : & Path , stash : & ' data Stash ) -> Option < Object < ' data > > {
77
+ let mut path_dwp = path. to_path_buf ( ) ;
78
+ let dwp_extension = path
79
+ . extension ( )
80
+ . map ( |previous_extension| {
81
+ let mut previous_extension = previous_extension. to_os_string ( ) ;
82
+ previous_extension. push ( ".dwp" ) ;
83
+ previous_extension
84
+ } )
85
+ . unwrap_or_else ( || "dwp" . into ( ) ) ;
86
+ path_dwp. set_extension ( dwp_extension) ;
87
+ if let Some ( map_dwp) = super :: mmap ( & path_dwp) {
88
+ let map_dwp = stash. cache_mmap ( map_dwp) ;
89
+ if let Some ( dwp_) = Object :: parse ( map_dwp) {
90
+ return Some ( dwp_) ;
91
+ }
92
+ }
93
+
94
+ None
95
+ }
68
96
}
69
97
70
98
struct ParsedSym {
@@ -421,3 +449,47 @@ fn locate_debugaltlink(path: &Path, filename: &[u8], build_id: &[u8]) -> Option<
421
449
422
450
locate_build_id ( build_id)
423
451
}
452
+
453
+ fn convert_path < R : gimli:: Reader > ( r : & R ) -> Result < PathBuf , gimli:: Error > {
454
+ let bytes = r. to_slice ( ) ?;
455
+ Ok ( PathBuf :: from ( OsStr :: from_bytes ( & bytes) ) )
456
+ }
457
+
458
+ pub ( super ) fn handle_split_dwarf < ' data > (
459
+ package : Option < & gimli:: DwarfPackage < EndianSlice < ' data , Endian > > > ,
460
+ stash : & ' data Stash ,
461
+ load : addr2line:: SplitDwarfLoad < EndianSlice < ' data , Endian > > ,
462
+ ) -> Option < Arc < gimli:: Dwarf < EndianSlice < ' data , Endian > > > > {
463
+ if let Some ( dwp) = package. as_ref ( ) {
464
+ if let Ok ( Some ( cu) ) = dwp. find_cu ( load. dwo_id , & load. parent ) {
465
+ return Some ( Arc :: new ( cu) ) ;
466
+ }
467
+ }
468
+
469
+ let mut path = PathBuf :: new ( ) ;
470
+ if let Some ( p) = load. comp_dir . as_ref ( ) {
471
+ path. push ( convert_path ( p) . ok ( ) ?) ;
472
+ }
473
+
474
+ path. push ( convert_path ( load. path . as_ref ( ) ?) . ok ( ) ?) ;
475
+
476
+ if let Some ( map_dwo) = super :: mmap ( & path) {
477
+ let map_dwo = stash. cache_mmap ( map_dwo) ;
478
+ if let Some ( dwo) = Object :: parse ( map_dwo) {
479
+ return gimli:: Dwarf :: load ( |id| -> Result < _ , ( ) > {
480
+ let data = id
481
+ . dwo_name ( )
482
+ . and_then ( |name| dwo. section ( stash, name) )
483
+ . unwrap_or ( & [ ] ) ;
484
+ Ok ( EndianSlice :: new ( data, Endian ) )
485
+ } )
486
+ . ok ( )
487
+ . map ( |mut dwo_dwarf| {
488
+ dwo_dwarf. make_dwo ( & load. parent ) ;
489
+ Arc :: new ( dwo_dwarf)
490
+ } ) ;
491
+ }
492
+ }
493
+
494
+ None
495
+ }
0 commit comments