github.com/epfl-dcsl/gotee@v0.0.0-20200909122901-014b35f5e5e9/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 } 138 139 func Test64Bit(t *testing.T) { 140 // I don't know how to generate a 64-bit DWARF debug 141 // compilation unit except by using XCOFF, so this is 142 // hand-written. 143 tests := []struct { 144 name string 145 info []byte 146 }{ 147 { 148 "32-bit little", 149 []byte{0x30, 0, 0, 0, // comp unit length 150 4, 0, // DWARF version 4 151 0, 0, 0, 0, // abbrev offset 152 8, // address size 153 0, 154 0, 0, 0, 0, 0, 0, 0, 0, 155 0, 0, 0, 0, 0, 0, 0, 0, 156 0, 0, 0, 0, 0, 0, 0, 0, 157 0, 0, 0, 0, 0, 0, 0, 0, 158 0, 0, 0, 0, 0, 0, 0, 0, 159 }, 160 }, 161 { 162 "64-bit little", 163 []byte{0xff, 0xff, 0xff, 0xff, // 64-bit DWARF 164 0x30, 0, 0, 0, 0, 0, 0, 0, // comp unit length 165 4, 0, // DWARF version 4 166 0, 0, 0, 0, 0, 0, 0, 0, // abbrev offset 167 8, // address size 168 0, 0, 0, 0, 0, 169 0, 0, 0, 0, 0, 0, 0, 0, 170 0, 0, 0, 0, 0, 0, 0, 0, 171 0, 0, 0, 0, 0, 0, 0, 0, 172 0, 0, 0, 0, 0, 0, 0, 0, 173 }, 174 }, 175 { 176 "64-bit big", 177 []byte{0xff, 0xff, 0xff, 0xff, // 64-bit DWARF 178 0, 0, 0, 0, 0, 0, 0, 0x30, // comp unit length 179 0, 4, // DWARF version 4 180 0, 0, 0, 0, 0, 0, 0, 0, // abbrev offset 181 8, // address size 182 0, 0, 0, 0, 0, 183 0, 0, 0, 0, 0, 0, 0, 0, 184 0, 0, 0, 0, 0, 0, 0, 0, 185 0, 0, 0, 0, 0, 0, 0, 0, 186 0, 0, 0, 0, 0, 0, 0, 0, 187 }, 188 }, 189 } 190 191 for _, test := range tests { 192 _, err := New(nil, nil, nil, test.info, nil, nil, nil, nil) 193 if err != nil { 194 t.Errorf("%s: %v", test.name, err) 195 } 196 } 197 }