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  }