github.com/s1s1ty/go@v0.0.0-20180207192209-104445e3140f/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  }