From 16396059784f32fa1b4db61ff1607bb4358dd08b Mon Sep 17 00:00:00 2001 From: Alessandro Arzilli Date: Fri, 26 Jul 2019 20:24:35 +0200 Subject: [PATCH] proc: ignore DW_TAG_inlined_subroutine entries without abstract origin (#1637) GCC produces DW_TAG_inlined_subroutine entries without a DW_AT_abstract_origin attribute. From the bug report: <1><1fe6c7c>: Abbrev Number: 41 (DW_TAG_subprogram) <1fe6c7d> DW_AT_external : 1 <1fe6c7d> DW_AT_name : (indirect string, offset: 0x485814): MultiGetImpl (omissis) <2><1fe6c9e>: Abbrev Number: 65 (DW_TAG_inlined_subroutine) <1fe6c9f> DW_AT_low_pc : 0x311023a <1fe6ca7> DW_AT_high_pc : 0x5 <1fe6caf> DW_AT_call_file : 10 <1fe6cb0> DW_AT_call_line : 1690 <2><1fe6cb2>: Abbrev Number: 20 (DW_TAG_inlined_subroutine) <1fe6cb3> DW_AT_abstract_origin: <0x1ffb534> <1fe6cb7> DW_AT_entry_pc : 0x311023f <1fe6cbf> DW_AT_ranges : 0xe9bf20 <1fe6cc3> DW_AT_call_file : 10 <1fe6cc4> DW_AT_call_line : 1690 Inlined subroutine at 1fe6c9e doesn't have abstract origin, a name or a declaration location. It's unclear whether this is in-standard and what it even means. Let's ignore it. Fixes #1636 --- pkg/dwarf/dwarfbuilder/info.go | 4 +++- pkg/proc/dwarf_expr_test.go | 15 +++++++++++++++ pkg/proc/types.go | 2 +- 3 files changed, 19 insertions(+), 2 deletions(-) diff --git a/pkg/dwarf/dwarfbuilder/info.go b/pkg/dwarf/dwarfbuilder/info.go index 3288046715..7d264b01cd 100644 --- a/pkg/dwarf/dwarfbuilder/info.go +++ b/pkg/dwarf/dwarfbuilder/info.go @@ -92,7 +92,9 @@ func (b *Builder) TagOpen(tag dwarf.Tag, name string) dwarf.Offset { ts.tag = tag b.info.WriteByte(0) b.tagStack = append(b.tagStack, ts) - b.Attr(dwarf.AttrName, name) + if name != "" { + b.Attr(dwarf.AttrName, name) + } return ts.off } diff --git a/pkg/proc/dwarf_expr_test.go b/pkg/proc/dwarf_expr_test.go index 34aeb7c161..fe4ecc9e51 100644 --- a/pkg/proc/dwarf_expr_test.go +++ b/pkg/proc/dwarf_expr_test.go @@ -292,3 +292,18 @@ func TestLocationCovers(t *testing.T) { } } + +func TestIssue1636_InlineWithoutOrigin(t *testing.T) { + // Gcc (specifically GNU C++11 6.3.0) will emit DW_TAG_inlined_subroutine + // without a DW_AT_abstract_origin or a name. What is an inlined subroutine + // without a reference to an abstract origin or even a name? Regardless, + // Delve shouldn't crash. + dwb := dwarfbuilder.New() + dwb.AddCompileUnit("main", 0x0) + dwb.AddSubprogram("main.main", 0x40100, 0x41000) + dwb.TagOpen(dwarf.TagInlinedSubroutine, "") + dwb.TagClose() + dwb.TagClose() + dwb.TagClose() + fakeBinaryInfo(t, dwb) +} diff --git a/pkg/proc/types.go b/pkg/proc/types.go index b560d29e04..6cf29568c9 100644 --- a/pkg/proc/types.go +++ b/pkg/proc/types.go @@ -410,7 +410,7 @@ func (bi *BinaryInfo) loadDebugInfoMapsCompileUnit(ctxt *loadDebugInfoMapsContex if entry.Tag == 0 { break } - if entry.Tag == dwarf.TagInlinedSubroutine { + if entry.Tag == dwarf.TagInlinedSubroutine && entry.Val(dwarf.AttrAbstractOrigin) != nil { originOffset := entry.Val(dwarf.AttrAbstractOrigin).(dwarf.Offset) name := ctxt.abstractOriginNameTable[originOffset] if ranges, _ := image.dwarf.Ranges(entry); len(ranges) == 1 {