diff options
| author | Ian Lance Taylor <iant@golang.org> | 2016-03-16 14:15:54 -0700 |
|---|---|---|
| committer | Ian Lance Taylor <iant@golang.org> | 2016-03-22 14:06:09 +0000 |
| commit | d1b8871f13203cd99d5e7d686170f0e266760084 (patch) | |
| tree | 7458f93ff93d8c7b849eab786932a1682657337b /src/debug/dwarf/entry_test.go | |
| parent | 77f4b773e72b0840a1ce0b314cba44dff9fbaf31 (diff) | |
| download | go-d1b8871f13203cd99d5e7d686170f0e266760084.tar.xz | |
debug/dwarf: add Reader.SeekPC and Data.Ranges
These new methods help find the compilation unit to pass to the
LineReader method in order to find the line information for a PC.
The Ranges method also helps identify the specific function for a PC,
needed to determine the function name.
This uses the .debug.ranges section if necessary, and changes the object
file format packages to pass in the section contents if available.
Change-Id: I5ebc3d27faaf1a126ffb17a1e6027efdf64af836
Reviewed-on: https://go-review.googlesource.com/20769
Reviewed-by: Austin Clements <austin@google.com>
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Diffstat (limited to 'src/debug/dwarf/entry_test.go')
| -rw-r--r-- | src/debug/dwarf/entry_test.go | 101 |
1 files changed, 101 insertions, 0 deletions
diff --git a/src/debug/dwarf/entry_test.go b/src/debug/dwarf/entry_test.go index 8bd2d2a8ad..58a5d570be 100644 --- a/src/debug/dwarf/entry_test.go +++ b/src/debug/dwarf/entry_test.go @@ -6,6 +6,7 @@ package dwarf_test import ( . "debug/dwarf" + "reflect" "testing" ) @@ -34,3 +35,103 @@ func TestSplit(t *testing.T) { t.Fatalf("bad class: have %s, want %s", f.Class, ClassUnknown) } } + +// wantRange maps from a PC to the ranges of the compilation unit +// containing that PC. +type wantRange struct { + pc uint64 + ranges [][2]uint64 +} + +func TestReaderSeek(t *testing.T) { + want := []wantRange{ + {0x40059d, [][2]uint64{{0x40059d, 0x400601}}}, + {0x400600, [][2]uint64{{0x40059d, 0x400601}}}, + {0x400601, [][2]uint64{{0x400601, 0x400611}}}, + {0x4005f0, [][2]uint64{{0x40059d, 0x400601}}}, // loop test + {0x10, nil}, + {0x400611, nil}, + } + testRanges(t, "testdata/line-gcc.elf", want) +} + +func TestRangesSection(t *testing.T) { + want := []wantRange{ + {0x400500, [][2]uint64{{0x400500, 0x400549}, {0x400400, 0x400408}}}, + {0x400400, [][2]uint64{{0x400500, 0x400549}, {0x400400, 0x400408}}}, + {0x400548, [][2]uint64{{0x400500, 0x400549}, {0x400400, 0x400408}}}, + {0x400407, [][2]uint64{{0x400500, 0x400549}, {0x400400, 0x400408}}}, + {0x400408, nil}, + {0x400449, nil}, + {0x4003ff, nil}, + } + testRanges(t, "testdata/ranges.elf", want) +} + +func testRanges(t *testing.T, name string, want []wantRange) { + d := elfData(t, name) + r := d.Reader() + for _, w := range want { + entry, err := r.SeekPC(w.pc) + if err != nil { + if w.ranges != nil { + t.Errorf("%s: missing Entry for %#x", name, w.pc) + } + if err != ErrUnknownPC { + t.Errorf("%s: expected ErrUnknownPC for %#x, got %v", name, w.pc, err) + } + continue + } + + ranges, err := d.Ranges(entry) + if err != nil { + t.Errorf("%s: %v", name, err) + continue + } + if !reflect.DeepEqual(ranges, w.ranges) { + t.Errorf("%s: for %#x got %x, expected %x", name, w.pc, ranges, w.ranges) + } + } +} + +func TestReaderRanges(t *testing.T) { + d := elfData(t, "testdata/line-gcc.elf") + + subprograms := []struct { + name string + ranges [][2]uint64 + }{ + {"f1", [][2]uint64{{0x40059d, 0x4005e7}}}, + {"main", [][2]uint64{{0x4005e7, 0x400601}}}, + {"f2", [][2]uint64{{0x400601, 0x400611}}}, + } + + r := d.Reader() + i := 0 + for entry, err := r.Next(); entry != nil && err == nil; entry, err = r.Next() { + if entry.Tag != TagSubprogram { + continue + } + + if i > len(subprograms) { + t.Fatalf("too many subprograms (expected at most %d)", i) + } + + if got := entry.Val(AttrName).(string); got != subprograms[i].name { + t.Errorf("subprogram %d name is %s, expected %s", i, got, subprograms[i].name) + } + ranges, err := d.Ranges(entry) + if err != nil { + t.Errorf("subprogram %d: %v", i, err) + continue + } + if !reflect.DeepEqual(ranges, subprograms[i].ranges) { + t.Errorf("subprogram %d ranges are %x, expected %x", i, ranges, subprograms[i].ranges) + } + i++ + } + + if i < len(subprograms) { + t.Errorf("saw only %d subprograms, expected %d", i, len(subprograms)) + } +} |
