@@ -8,8 +8,10 @@ use self::mmap::Mmap;
88use self :: stash:: Stash ;
99use super :: BytesOrWideString ;
1010use super :: ResolveWhat ;
11+ use super :: ShortBacktrace ;
1112use super :: SymbolName ;
1213use addr2line:: gimli;
14+ use addr2line:: { LookupContinuation , LookupResult } ;
1315use core:: convert:: TryInto ;
1416use core:: mem;
1517use core:: u32;
@@ -170,9 +172,24 @@ impl<'data> Context<'data> {
170172 stash : & ' data Stash ,
171173 probe : u64 ,
172174 ) -> gimli:: Result < addr2line:: FrameIter < ' _ , EndianSlice < ' data , Endian > > > {
173- use addr2line:: { LookupContinuation , LookupResult } ;
175+ let continuation = self . dwarf . find_frames ( probe) ;
176+ self . continuation_helper ( stash, continuation)
177+ }
178+
179+ fn find_dwarf_and_unit (
180+ & ' _ self ,
181+ stash : & ' data Stash ,
182+ probe : u64 ,
183+ ) -> Option < gimli:: UnitRef < ' _ , EndianSlice < ' data , Endian > > > {
184+ let continuation = self . dwarf . find_dwarf_and_unit ( probe) ;
185+ self . continuation_helper ( stash, continuation)
186+ }
174187
175- let mut l = self . dwarf . find_frames ( probe) ;
188+ fn continuation_helper < O > (
189+ & ' _ self ,
190+ stash : & ' data Stash ,
191+ mut l : LookupResult < impl LookupContinuation < Output = O , Buf = EndianSlice < ' data , Endian > > > ,
192+ ) -> O {
176193 loop {
177194 let ( load, continuation) = match l {
178195 LookupResult :: Output ( output) => break output,
@@ -409,6 +426,43 @@ impl Cache {
409426 }
410427}
411428
429+ impl ShortBacktrace {
430+ fn from_raw ( raw : u8 ) -> Option < Self > {
431+ let this = match raw {
432+ 0 => ShortBacktrace :: ThisFrameOnly ,
433+ 1 => ShortBacktrace :: Start ,
434+ 2 => ShortBacktrace :: End ,
435+ _ => return None ,
436+ } ;
437+ Some ( this)
438+ }
439+ }
440+
441+ #[ allow( non_upper_case_globals) ]
442+ const DW_AT_short_backtrace : gimli:: DwAt = gimli:: DwAt ( 0x3c00 ) ;
443+
444+ fn parse_short_backtrace < ' data , R : gimli:: Reader < Offset = usize > > (
445+ unit_ref : gimli:: UnitRef < ' _ , R > ,
446+ frame : & addr2line:: Frame < ' _ , R > ,
447+ ) -> Option < ShortBacktrace > {
448+ use core:: ops:: ControlFlow ;
449+
450+ let mut short_backtrace = None ;
451+ let _ = unit_ref. shared_attrs ( frame. dw_die_offset ?, 16 , |attr, _| {
452+ if attr. name ( ) == DW_AT_short_backtrace {
453+ let parsed = ShortBacktrace :: from_raw (
454+ attr. u8_value ( )
455+ . ok_or ( gimli:: Error :: UnsupportedAttributeForm ) ?,
456+ ) ;
457+ short_backtrace = Some ( parsed. expect ( "rustc generated invalid debuginfo?" ) ) ;
458+ return Ok ( ControlFlow :: Break ( ( ) ) ) ;
459+ }
460+ Ok ( ControlFlow :: Continue ( ( ) ) )
461+ } ) ;
462+
463+ short_backtrace
464+ }
465+
412466pub unsafe fn resolve ( what : ResolveWhat < ' _ > , cb : & mut dyn FnMut ( & super :: Symbol ) ) {
413467 let addr = what. address_or_ip ( ) ;
414468 let mut call = |sym : Symbol < ' _ > | {
@@ -435,24 +489,30 @@ pub unsafe fn resolve(what: ResolveWhat<'_>, cb: &mut dyn FnMut(&super::Symbol))
435489 if let Ok ( mut frames) = cx. find_frames ( stash, addr as u64 ) {
436490 while let Ok ( Some ( frame) ) = frames. next ( ) {
437491 any_frames = true ;
438- let name = match frame. function {
492+ let name = match & frame. function {
439493 Some ( f) => Some ( f. name . slice ( ) ) ,
440494 None => cx. object . search_symtab ( addr as u64 ) ,
441495 } ;
496+ let unit_ref = cx. find_dwarf_and_unit ( stash, addr as u64 ) ;
497+ let short_backtrace = unit_ref. and_then ( |unit| parse_short_backtrace ( unit, & frame) ) ;
442498 call ( Symbol :: Frame {
443499 addr : addr as * mut c_void ,
444500 location : frame. location ,
445501 name,
502+ short_backtrace,
446503 } ) ;
447504 }
448505 }
449506 if !any_frames {
450507 if let Some ( ( object_cx, object_addr) ) = cx. object . search_object_map ( addr as u64 ) {
508+ let unit_ref = None ;
451509 if let Ok ( mut frames) = object_cx. find_frames ( stash, object_addr) {
452510 while let Ok ( Some ( frame) ) = frames. next ( ) {
453511 any_frames = true ;
454512 call ( Symbol :: Frame {
455513 addr : addr as * mut c_void ,
514+ short_backtrace : unit_ref
515+ . and_then ( |unit| parse_short_backtrace ( unit, & frame) ) ,
456516 location : frame. location ,
457517 name : frame. function . map ( |f| f. name . slice ( ) ) ,
458518 } ) ;
@@ -475,6 +535,7 @@ pub enum Symbol<'a> {
475535 addr : * mut c_void ,
476536 location : Option < addr2line:: Location < ' a > > ,
477537 name : Option < & ' a [ u8 ] > ,
538+ short_backtrace : Option < ShortBacktrace > ,
478539 } ,
479540 /// Couldn't find debug information, but we found it in the symbol table of
480541 /// the elf executable.
@@ -532,4 +593,13 @@ impl Symbol<'_> {
532593 Symbol :: Symtab { .. } => None ,
533594 }
534595 }
596+
597+ pub fn short_backtrace ( & self ) -> Option < ShortBacktrace > {
598+ match self {
599+ Symbol :: Frame {
600+ short_backtrace, ..
601+ } => * short_backtrace,
602+ Symbol :: Symtab { .. } => None ,
603+ }
604+ }
535605}
0 commit comments