@@ -3,7 +3,8 @@ use super::mystd::fs;
33use super :: mystd:: os:: unix:: ffi:: { OsStrExt , OsStringExt } ;
44use super :: mystd:: path:: { Path , PathBuf } ;
55use super :: Either ;
6- use super :: { Context , Mapping , Stash , Vec } ;
6+ use super :: { gimli, Context , Endian , EndianSlice , Mapping , Stash , Vec } ;
7+ use alloc:: sync:: Arc ;
78use core:: convert:: { TryFrom , TryInto } ;
89use core:: str;
910use object:: elf:: { ELFCOMPRESS_ZLIB , ELF_NOTE_GNU , NT_GNU_BUILD_ID , SHF_COMPRESSED } ;
@@ -24,24 +25,26 @@ impl Mapping {
2425
2526 // Try to locate an external debug file using the build ID.
2627 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 ) {
2829 return Some ( Either :: A ( mapping) ) ;
2930 }
3031 }
3132
3233 // Try to locate an external debug file using the GNU debug link section.
3334 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) ) {
3536 return Some ( Either :: A ( mapping) ) ;
3637 }
3738 }
3839
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 )
4043 } )
4144 }
4245
4346 /// 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 > {
4548 let map = super :: mmap ( & path) ?;
4649 Mapping :: mk ( map, |map, stash| {
4750 let object = Object :: parse ( & map) ?;
@@ -51,20 +54,45 @@ impl Mapping {
5154 }
5255
5356 // Try to locate a supplementary object file.
57+ let mut sup = None ;
5458 if let Some ( ( path_sup, build_id_sup) ) = object. gnu_debugaltlink_path ( & path) {
5559 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_ ) ;
6064 }
6165 }
6266 }
6367 }
6468
65- Context :: new ( stash, object, None )
69+ let dwp = Mapping :: load_dwarf_package ( original_path, stash) ;
70+
71+ Context :: new ( stash, object, sup, dwp)
6672 } )
6773 }
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+ }
6896}
6997
7098struct ParsedSym {
@@ -421,3 +449,47 @@ fn locate_debugaltlink(path: &Path, filename: &[u8], build_id: &[u8]) -> Option<
421449
422450 locate_build_id ( build_id)
423451}
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