github.com/guyezi/gofrontend@v0.0.0-20200228202240-7a62a49e62c0/libgo/go/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 "encoding/binary" 10 "reflect" 11 "testing" 12 ) 13 14 func TestSplit(t *testing.T) { 15 // debug/dwarf doesn't (currently) support split DWARF, but 16 // the attributes that pointed to the split DWARF used to 17 // cause loading the DWARF data to fail entirely (issue 18 // #12592). Test that we can at least read the DWARF data. 19 d := elfData(t, "testdata/split.elf") 20 r := d.Reader() 21 e, err := r.Next() 22 if err != nil { 23 t.Fatal(err) 24 } 25 if e.Tag != TagCompileUnit { 26 t.Fatalf("bad tag: have %s, want %s", e.Tag, TagCompileUnit) 27 } 28 // Check that we were able to parse the unknown section offset 29 // field, even if we can't figure out its DWARF class. 30 const AttrGNUAddrBase Attr = 0x2133 31 f := e.AttrField(AttrGNUAddrBase) 32 if _, ok := f.Val.(int64); !ok { 33 t.Fatalf("bad attribute value type: have %T, want int64", f.Val) 34 } 35 if f.Class != ClassUnknown { 36 t.Fatalf("bad class: have %s, want %s", f.Class, ClassUnknown) 37 } 38 } 39 40 // wantRange maps from a PC to the ranges of the compilation unit 41 // containing that PC. 42 type wantRange struct { 43 pc uint64 44 ranges [][2]uint64 45 } 46 47 func TestReaderSeek(t *testing.T) { 48 want := []wantRange{ 49 {0x40059d, [][2]uint64{{0x40059d, 0x400601}}}, 50 {0x400600, [][2]uint64{{0x40059d, 0x400601}}}, 51 {0x400601, [][2]uint64{{0x400601, 0x400611}}}, 52 {0x4005f0, [][2]uint64{{0x40059d, 0x400601}}}, // loop test 53 {0x10, nil}, 54 {0x400611, nil}, 55 } 56 testRanges(t, "testdata/line-gcc.elf", want) 57 } 58 59 func TestRangesSection(t *testing.T) { 60 want := []wantRange{ 61 {0x400500, [][2]uint64{{0x400500, 0x400549}, {0x400400, 0x400408}}}, 62 {0x400400, [][2]uint64{{0x400500, 0x400549}, {0x400400, 0x400408}}}, 63 {0x400548, [][2]uint64{{0x400500, 0x400549}, {0x400400, 0x400408}}}, 64 {0x400407, [][2]uint64{{0x400500, 0x400549}, {0x400400, 0x400408}}}, 65 {0x400408, nil}, 66 {0x400449, nil}, 67 {0x4003ff, nil}, 68 } 69 testRanges(t, "testdata/ranges.elf", want) 70 } 71 72 func testRanges(t *testing.T, name string, want []wantRange) { 73 d := elfData(t, name) 74 r := d.Reader() 75 for _, w := range want { 76 entry, err := r.SeekPC(w.pc) 77 if err != nil { 78 if w.ranges != nil { 79 t.Errorf("%s: missing Entry for %#x", name, w.pc) 80 } 81 if err != ErrUnknownPC { 82 t.Errorf("%s: expected ErrUnknownPC for %#x, got %v", name, w.pc, err) 83 } 84 continue 85 } 86 87 ranges, err := d.Ranges(entry) 88 if err != nil { 89 t.Errorf("%s: %v", name, err) 90 continue 91 } 92 if !reflect.DeepEqual(ranges, w.ranges) { 93 t.Errorf("%s: for %#x got %x, expected %x", name, w.pc, ranges, w.ranges) 94 } 95 } 96 } 97 98 func TestReaderRanges(t *testing.T) { 99 d := elfData(t, "testdata/line-gcc.elf") 100 101 subprograms := []struct { 102 name string 103 ranges [][2]uint64 104 }{ 105 {"f1", [][2]uint64{{0x40059d, 0x4005e7}}}, 106 {"main", [][2]uint64{{0x4005e7, 0x400601}}}, 107 {"f2", [][2]uint64{{0x400601, 0x400611}}}, 108 } 109 110 r := d.Reader() 111 i := 0 112 for entry, err := r.Next(); entry != nil && err == nil; entry, err = r.Next() { 113 if entry.Tag != TagSubprogram { 114 continue 115 } 116 117 if i > len(subprograms) { 118 t.Fatalf("too many subprograms (expected at most %d)", i) 119 } 120 121 if got := entry.Val(AttrName).(string); got != subprograms[i].name { 122 t.Errorf("subprogram %d name is %s, expected %s", i, got, subprograms[i].name) 123 } 124 ranges, err := d.Ranges(entry) 125 if err != nil { 126 t.Errorf("subprogram %d: %v", i, err) 127 continue 128 } 129 if !reflect.DeepEqual(ranges, subprograms[i].ranges) { 130 t.Errorf("subprogram %d ranges are %x, expected %x", i, ranges, subprograms[i].ranges) 131 } 132 i++ 133 } 134 135 if i < len(subprograms) { 136 t.Errorf("saw only %d subprograms, expected %d", i, len(subprograms)) 137 } 138 } 139 140 func Test64Bit(t *testing.T) { 141 // I don't know how to generate a 64-bit DWARF debug 142 // compilation unit except by using XCOFF, so this is 143 // hand-written. 144 tests := []struct { 145 name string 146 info []byte 147 addrSize int 148 byteOrder binary.ByteOrder 149 }{ 150 { 151 "32-bit little", 152 []byte{0x30, 0, 0, 0, // comp unit length 153 4, 0, // DWARF version 4 154 0, 0, 0, 0, // abbrev offset 155 8, // address size 156 0, 157 0, 0, 0, 0, 0, 0, 0, 0, 158 0, 0, 0, 0, 0, 0, 0, 0, 159 0, 0, 0, 0, 0, 0, 0, 0, 160 0, 0, 0, 0, 0, 0, 0, 0, 161 0, 0, 0, 0, 0, 0, 0, 0, 162 }, 163 8, binary.LittleEndian, 164 }, 165 { 166 "64-bit little", 167 []byte{0xff, 0xff, 0xff, 0xff, // 64-bit DWARF 168 0x30, 0, 0, 0, 0, 0, 0, 0, // comp unit length 169 4, 0, // DWARF version 4 170 0, 0, 0, 0, 0, 0, 0, 0, // abbrev offset 171 8, // address size 172 0, 0, 0, 0, 0, 173 0, 0, 0, 0, 0, 0, 0, 0, 174 0, 0, 0, 0, 0, 0, 0, 0, 175 0, 0, 0, 0, 0, 0, 0, 0, 176 0, 0, 0, 0, 0, 0, 0, 0, 177 }, 178 8, binary.LittleEndian, 179 }, 180 { 181 "64-bit big", 182 []byte{0xff, 0xff, 0xff, 0xff, // 64-bit DWARF 183 0, 0, 0, 0, 0, 0, 0, 0x30, // comp unit length 184 0, 4, // DWARF version 4 185 0, 0, 0, 0, 0, 0, 0, 0, // abbrev offset 186 8, // address size 187 0, 0, 0, 0, 0, 188 0, 0, 0, 0, 0, 0, 0, 0, 189 0, 0, 0, 0, 0, 0, 0, 0, 190 0, 0, 0, 0, 0, 0, 0, 0, 191 0, 0, 0, 0, 0, 0, 0, 0, 192 }, 193 8, binary.BigEndian, 194 }, 195 } 196 197 for _, test := range tests { 198 data, err := New(nil, nil, nil, test.info, nil, nil, nil, nil) 199 if err != nil { 200 t.Errorf("%s: %v", test.name, err) 201 } 202 203 r := data.Reader() 204 if r.AddressSize() != test.addrSize { 205 t.Errorf("%s: got address size %d, want %d", test.name, r.AddressSize(), test.addrSize) 206 } 207 if r.ByteOrder() != test.byteOrder { 208 t.Errorf("%s: got byte order %s, want %s", test.name, r.ByteOrder(), test.byteOrder) 209 } 210 } 211 }