github.com/riscv/riscv-go@v0.0.0-20200123204226-124ebd6fcc8e/src/debug/dwarf/entry_test.go (about) 1 // Copyright 2009 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package dwarf_test 6 7 import ( 8 . "debug/dwarf" 9 "reflect" 10 "testing" 11 ) 12 13 func TestSplit(t *testing.T) { 14 // debug/dwarf doesn't (currently) support split DWARF, but 15 // the attributes that pointed to the split DWARF used to 16 // cause loading the DWARF data to fail entirely (issue 17 // #12592). Test that we can at least read the DWARF data. 18 d := elfData(t, "testdata/split.elf") 19 r := d.Reader() 20 e, err := r.Next() 21 if err != nil { 22 t.Fatal(err) 23 } 24 if e.Tag != TagCompileUnit { 25 t.Fatalf("bad tag: have %s, want %s", e.Tag, TagCompileUnit) 26 } 27 // Check that we were able to parse the unknown section offset 28 // field, even if we can't figure out its DWARF class. 29 const AttrGNUAddrBase Attr = 0x2133 30 f := e.AttrField(AttrGNUAddrBase) 31 if _, ok := f.Val.(int64); !ok { 32 t.Fatalf("bad attribute value type: have %T, want int64", f.Val) 33 } 34 if f.Class != ClassUnknown { 35 t.Fatalf("bad class: have %s, want %s", f.Class, ClassUnknown) 36 } 37 } 38 39 // wantRange maps from a PC to the ranges of the compilation unit 40 // containing that PC. 41 type wantRange struct { 42 pc uint64 43 ranges [][2]uint64 44 } 45 46 func TestReaderSeek(t *testing.T) { 47 want := []wantRange{ 48 {0x40059d, [][2]uint64{{0x40059d, 0x400601}}}, 49 {0x400600, [][2]uint64{{0x40059d, 0x400601}}}, 50 {0x400601, [][2]uint64{{0x400601, 0x400611}}}, 51 {0x4005f0, [][2]uint64{{0x40059d, 0x400601}}}, // loop test 52 {0x10, nil}, 53 {0x400611, nil}, 54 } 55 testRanges(t, "testdata/line-gcc.elf", want) 56 } 57 58 func TestRangesSection(t *testing.T) { 59 want := []wantRange{ 60 {0x400500, [][2]uint64{{0x400500, 0x400549}, {0x400400, 0x400408}}}, 61 {0x400400, [][2]uint64{{0x400500, 0x400549}, {0x400400, 0x400408}}}, 62 {0x400548, [][2]uint64{{0x400500, 0x400549}, {0x400400, 0x400408}}}, 63 {0x400407, [][2]uint64{{0x400500, 0x400549}, {0x400400, 0x400408}}}, 64 {0x400408, nil}, 65 {0x400449, nil}, 66 {0x4003ff, nil}, 67 } 68 testRanges(t, "testdata/ranges.elf", want) 69 } 70 71 func testRanges(t *testing.T, name string, want []wantRange) { 72 d := elfData(t, name) 73 r := d.Reader() 74 for _, w := range want { 75 entry, err := r.SeekPC(w.pc) 76 if err != nil { 77 if w.ranges != nil { 78 t.Errorf("%s: missing Entry for %#x", name, w.pc) 79 } 80 if err != ErrUnknownPC { 81 t.Errorf("%s: expected ErrUnknownPC for %#x, got %v", name, w.pc, err) 82 } 83 continue 84 } 85 86 ranges, err := d.Ranges(entry) 87 if err != nil { 88 t.Errorf("%s: %v", name, err) 89 continue 90 } 91 if !reflect.DeepEqual(ranges, w.ranges) { 92 t.Errorf("%s: for %#x got %x, expected %x", name, w.pc, ranges, w.ranges) 93 } 94 } 95 } 96 97 func TestReaderRanges(t *testing.T) { 98 d := elfData(t, "testdata/line-gcc.elf") 99 100 subprograms := []struct { 101 name string 102 ranges [][2]uint64 103 }{ 104 {"f1", [][2]uint64{{0x40059d, 0x4005e7}}}, 105 {"main", [][2]uint64{{0x4005e7, 0x400601}}}, 106 {"f2", [][2]uint64{{0x400601, 0x400611}}}, 107 } 108 109 r := d.Reader() 110 i := 0 111 for entry, err := r.Next(); entry != nil && err == nil; entry, err = r.Next() { 112 if entry.Tag != TagSubprogram { 113 continue 114 } 115 116 if i > len(subprograms) { 117 t.Fatalf("too many subprograms (expected at most %d)", i) 118 } 119 120 if got := entry.Val(AttrName).(string); got != subprograms[i].name { 121 t.Errorf("subprogram %d name is %s, expected %s", i, got, subprograms[i].name) 122 } 123 ranges, err := d.Ranges(entry) 124 if err != nil { 125 t.Errorf("subprogram %d: %v", i, err) 126 continue 127 } 128 if !reflect.DeepEqual(ranges, subprograms[i].ranges) { 129 t.Errorf("subprogram %d ranges are %x, expected %x", i, ranges, subprograms[i].ranges) 130 } 131 i++ 132 } 133 134 if i < len(subprograms) { 135 t.Errorf("saw only %d subprograms, expected %d", i, len(subprograms)) 136 } 137 }