@@ -8,8 +8,10 @@ use self::mmap::Mmap;
8
8
use self :: stash:: Stash ;
9
9
use super :: BytesOrWideString ;
10
10
use super :: ResolveWhat ;
11
+ use super :: ShortBacktrace ;
11
12
use super :: SymbolName ;
12
13
use addr2line:: gimli;
14
+ use addr2line:: { LookupContinuation , LookupResult } ;
13
15
use core:: convert:: TryInto ;
14
16
use core:: mem;
15
17
use core:: u32;
@@ -170,9 +172,24 @@ impl<'data> Context<'data> {
170
172
stash : & ' data Stash ,
171
173
probe : u64 ,
172
174
) -> 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
+ }
174
187
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 {
176
193
loop {
177
194
let ( load, continuation) = match l {
178
195
LookupResult :: Output ( output) => break output,
@@ -409,6 +426,43 @@ impl Cache {
409
426
}
410
427
}
411
428
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
+
412
466
pub unsafe fn resolve ( what : ResolveWhat < ' _ > , cb : & mut dyn FnMut ( & super :: Symbol ) ) {
413
467
let addr = what. address_or_ip ( ) ;
414
468
let mut call = |sym : Symbol < ' _ > | {
@@ -435,24 +489,30 @@ pub unsafe fn resolve(what: ResolveWhat<'_>, cb: &mut dyn FnMut(&super::Symbol))
435
489
if let Ok ( mut frames) = cx. find_frames ( stash, addr as u64 ) {
436
490
while let Ok ( Some ( frame) ) = frames. next ( ) {
437
491
any_frames = true ;
438
- let name = match frame. function {
492
+ let name = match & frame. function {
439
493
Some ( f) => Some ( f. name . slice ( ) ) ,
440
494
None => cx. object . search_symtab ( addr as u64 ) ,
441
495
} ;
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) ) ;
442
498
call ( Symbol :: Frame {
443
499
addr : addr as * mut c_void ,
444
500
location : frame. location ,
445
501
name,
502
+ short_backtrace,
446
503
} ) ;
447
504
}
448
505
}
449
506
if !any_frames {
450
507
if let Some ( ( object_cx, object_addr) ) = cx. object . search_object_map ( addr as u64 ) {
508
+ let unit_ref = None ;
451
509
if let Ok ( mut frames) = object_cx. find_frames ( stash, object_addr) {
452
510
while let Ok ( Some ( frame) ) = frames. next ( ) {
453
511
any_frames = true ;
454
512
call ( Symbol :: Frame {
455
513
addr : addr as * mut c_void ,
514
+ short_backtrace : unit_ref
515
+ . and_then ( |unit| parse_short_backtrace ( unit, & frame) ) ,
456
516
location : frame. location ,
457
517
name : frame. function . map ( |f| f. name . slice ( ) ) ,
458
518
} ) ;
@@ -475,6 +535,7 @@ pub enum Symbol<'a> {
475
535
addr : * mut c_void ,
476
536
location : Option < addr2line:: Location < ' a > > ,
477
537
name : Option < & ' a [ u8 ] > ,
538
+ short_backtrace : Option < ShortBacktrace > ,
478
539
} ,
479
540
/// Couldn't find debug information, but we found it in the symbol table of
480
541
/// the elf executable.
@@ -532,4 +593,13 @@ impl Symbol<'_> {
532
593
Symbol :: Symtab { .. } => None ,
533
594
}
534
595
}
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
+ }
535
605
}
0 commit comments