@@ -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