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  }