From 53e847035a13ffeed2916679d24dee8ae69a35eb Mon Sep 17 00:00:00 2001 From: Derek Parker Date: Thu, 4 Apr 2024 16:00:43 -0700 Subject: [PATCH] pkg/proc: defend better against missing DWARF The `scope.Locals` function did not have any guard checks against missing DWARF information. This patch adds a check, which likely will need to be added to other functions as well. --- pkg/dwarf/godwarf/tree.go | 4 ++++ pkg/proc/eval.go | 4 ++++ pkg/proc/proc_test.go | 10 +++++++++- 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/pkg/dwarf/godwarf/tree.go b/pkg/dwarf/godwarf/tree.go index b9be92ba1f..0023ba18e1 100644 --- a/pkg/dwarf/godwarf/tree.go +++ b/pkg/dwarf/godwarf/tree.go @@ -2,6 +2,7 @@ package godwarf import ( "debug/dwarf" + "errors" "fmt" "sort" ) @@ -90,6 +91,9 @@ type Tree struct { // range of addresses that is not covered by its parent LoadTree will fix // the parent entry. func LoadTree(off dwarf.Offset, dw *dwarf.Data, staticBase uint64) (*Tree, error) { + if dw == nil { + return nil, errors.New("unable to load DWARF tree: no DWARF information present") + } rdr := dw.Reader() rdr.Seek(off) diff --git a/pkg/proc/eval.go b/pkg/proc/eval.go index 81b0828c9e..51f6aa8a48 100644 --- a/pkg/proc/eval.go +++ b/pkg/proc/eval.go @@ -371,6 +371,10 @@ func (scope *EvalScope) Locals(flags localsFlags) ([]*Variable, error) { return nil, errors.New("unable to find function context") } + if scope.image().Stripped() { + return nil, errors.New("unable to find locals: no debug information present in binary") + } + trustArgOrder := (flags&localsTrustArgOrder != 0) && scope.BinInfo.Producer() != "" && goversion.ProducerAfterOrEqual(scope.BinInfo.Producer(), 1, 12) && scope.Fn != nil && (scope.PC == scope.Fn.Entry) dwarfTree, err := scope.image().getDwarfTree(scope.Fn.offset) diff --git a/pkg/proc/proc_test.go b/pkg/proc/proc_test.go index ffb9d0b188..70f3a30014 100644 --- a/pkg/proc/proc_test.go +++ b/pkg/proc/proc_test.go @@ -3216,11 +3216,19 @@ func TestDebugStripped(t *testing.T) { assertLineNumber(p, t, 37, "first continue") assertNoError(grp.Next(), t, "Next") assertLineNumber(p, t, 38, "after next") + + // Assert that commands like "args", "locals", etc... will + // return an error instead of panic. + s, err := proc.ThreadScope(p, p.CurrentThread()) + assertNoError(err, t, "ThreadScope") + _, err = s.Locals(0) + if err == nil { + t.Error("expected an error to be returned from scope.Locals in stripped binary") + } }) } func TestDebugStripped2(t *testing.T) { - // Currently only implemented for Linux ELF executables. // TODO(derekparker): Add support for PE. skipOn(t, "not working on windows", "windows") skipOn(t, "not working on freebsd", "freebsd")