diff mbox series

libgo patch committed: Support 64-bit DWARF in version check, elsewhere

Message ID CAOyqgcULMr02GkxsKbwXas_B+TbhLP1DWWpXDdzRmt13hvsn9g@mail.gmail.com
State New
Headers show
Series libgo patch committed: Support 64-bit DWARF in version check, elsewhere | expand

Commit Message

Ian Lance Taylor Oct. 20, 2017, 6:34 p.m. UTC
This patch to libgo supports 64-bit DWARF in byte order check.  It
also fixes 64-bit DWARF to read a 64-bit abbrev offset in the
compilation unit.

This is a backport of https://golang.org/cl/71171, which will be inthe
Go 1.10 release, to the gofrontend copy. Doing it now because AIX is
pretty much the only system that uses 64-bit DWARF.

Bootstrapped and ran Go testsuite on x86_64-pc-linux-gnu.  Committed
to mainline.

Ian
diff mbox series

Patch

Index: gcc/go/gofrontend/MERGE
===================================================================
--- gcc/go/gofrontend/MERGE	(revision 253694)
+++ gcc/go/gofrontend/MERGE	(working copy)
@@ -1,4 +1,4 @@ 
-44132970e4b6c1186036bf8eda8982fb6e905d6f
+a409ac2c78899e638a014c97891925bec93cb3ad
 
 The first line of this file holds the git revision number of the last
 merge done from the gofrontend repository.
Index: libgo/go/debug/dwarf/entry.go
===================================================================
--- libgo/go/debug/dwarf/entry.go	(revision 253311)
+++ libgo/go/debug/dwarf/entry.go	(working copy)
@@ -33,13 +33,13 @@  type abbrevTable map[uint32]abbrev
 
 // ParseAbbrev returns the abbreviation table that starts at byte off
 // in the .debug_abbrev section.
-func (d *Data) parseAbbrev(off uint32, vers int) (abbrevTable, error) {
+func (d *Data) parseAbbrev(off uint64, vers int) (abbrevTable, error) {
 	if m, ok := d.abbrevCache[off]; ok {
 		return m, nil
 	}
 
 	data := d.abbrev
-	if off > uint32(len(data)) {
+	if off > uint64(len(data)) {
 		data = nil
 	} else {
 		data = data[off:]
Index: libgo/go/debug/dwarf/entry_test.go
===================================================================
--- libgo/go/debug/dwarf/entry_test.go	(revision 253311)
+++ libgo/go/debug/dwarf/entry_test.go	(working copy)
@@ -135,3 +135,63 @@  func TestReaderRanges(t *testing.T) {
 		t.Errorf("saw only %d subprograms, expected %d", i, len(subprograms))
 	}
 }
+
+func Test64Bit(t *testing.T) {
+	// I don't know how to generate a 64-bit DWARF debug
+	// compilation unit except by using XCOFF, so this is
+	// hand-written.
+	tests := []struct {
+		name string
+		info []byte
+	}{
+		{
+			"32-bit little",
+			[]byte{0x30, 0, 0, 0, // comp unit length
+				4, 0, // DWARF version 4
+				0, 0, 0, 0, // abbrev offset
+				8, // address size
+				0,
+				0, 0, 0, 0, 0, 0, 0, 0,
+				0, 0, 0, 0, 0, 0, 0, 0,
+				0, 0, 0, 0, 0, 0, 0, 0,
+				0, 0, 0, 0, 0, 0, 0, 0,
+				0, 0, 0, 0, 0, 0, 0, 0,
+			},
+		},
+		{
+			"64-bit little",
+			[]byte{0xff, 0xff, 0xff, 0xff, // 64-bit DWARF
+				0x30, 0, 0, 0, 0, 0, 0, 0, // comp unit length
+				4, 0, // DWARF version 4
+				0, 0, 0, 0, 0, 0, 0, 0, // abbrev offset
+				8, // address size
+				0, 0, 0, 0, 0,
+				0, 0, 0, 0, 0, 0, 0, 0,
+				0, 0, 0, 0, 0, 0, 0, 0,
+				0, 0, 0, 0, 0, 0, 0, 0,
+				0, 0, 0, 0, 0, 0, 0, 0,
+			},
+		},
+		{
+			"64-bit big",
+			[]byte{0xff, 0xff, 0xff, 0xff, // 64-bit DWARF
+				0, 0, 0, 0, 0, 0, 0, 0x30, // comp unit length
+				0, 4, // DWARF version 4
+				0, 0, 0, 0, 0, 0, 0, 0, // abbrev offset
+				8, // address size
+				0, 0, 0, 0, 0,
+				0, 0, 0, 0, 0, 0, 0, 0,
+				0, 0, 0, 0, 0, 0, 0, 0,
+				0, 0, 0, 0, 0, 0, 0, 0,
+				0, 0, 0, 0, 0, 0, 0, 0,
+			},
+		},
+	}
+
+	for _, test := range tests {
+		_, err := New(nil, nil, nil, test.info, nil, nil, nil, nil)
+		if err != nil {
+			t.Errorf("%s: %v", test.name, err)
+		}
+	}
+}
Index: libgo/go/debug/dwarf/open.go
===================================================================
--- libgo/go/debug/dwarf/open.go	(revision 253311)
+++ libgo/go/debug/dwarf/open.go	(working copy)
@@ -23,7 +23,7 @@  type Data struct {
 	str      []byte
 
 	// parsed data
-	abbrevCache map[uint32]abbrevTable
+	abbrevCache map[uint64]abbrevTable
 	order       binary.ByteOrder
 	typeCache   map[Offset]Type
 	typeSigs    map[uint64]*typeUnit
@@ -48,17 +48,26 @@  func New(abbrev, aranges, frame, info, l
 		pubnames:    pubnames,
 		ranges:      ranges,
 		str:         str,
-		abbrevCache: make(map[uint32]abbrevTable),
+		abbrevCache: make(map[uint64]abbrevTable),
 		typeCache:   make(map[Offset]Type),
 		typeSigs:    make(map[uint64]*typeUnit),
 	}
 
 	// Sniff .debug_info to figure out byte order.
-	// bytes 4:6 are the version, a tiny 16-bit number (1, 2, 3).
+	// 32-bit DWARF: 4 byte length, 2 byte version.
+	// 64-bit DWARf: 4 bytes of 0xff, 8 byte length, 2 byte version.
 	if len(d.info) < 6 {
 		return nil, DecodeError{"info", Offset(len(d.info)), "too short"}
 	}
-	x, y := d.info[4], d.info[5]
+	offset := 4
+	if d.info[0] == 0xff && d.info[1] == 0xff && d.info[2] == 0xff && d.info[3] == 0xff {
+		if len(d.info) < 14 {
+			return nil, DecodeError{"info", Offset(len(d.info)), "too short"}
+		}
+		offset = 12
+	}
+	// Fetch the version, a tiny 16-bit number (1, 2, 3, 4, 5).
+	x, y := d.info[offset], d.info[offset+1]
 	switch {
 	case x == 0 && y == 0:
 		return nil, DecodeError{"info", 4, "unsupported version 0"}
Index: libgo/go/debug/dwarf/typeunit.go
===================================================================
--- libgo/go/debug/dwarf/typeunit.go	(revision 253311)
+++ libgo/go/debug/dwarf/typeunit.go	(working copy)
@@ -38,16 +38,11 @@  func (d *Data) parseTypes(name string, t
 			b.error("unsupported DWARF version " + strconv.Itoa(vers))
 			return b.err
 		}
-		var ao uint32
+		var ao uint64
 		if !dwarf64 {
-			ao = b.uint32()
+			ao = uint64(b.uint32())
 		} else {
-			ao64 := b.uint64()
-			if ao64 != uint64(uint32(ao64)) {
-				b.error("type unit abbrev offset overflow")
-				return b.err
-			}
-			ao = uint32(ao64)
+			ao = b.uint64()
 		}
 		atable, err := d.parseAbbrev(ao, vers)
 		if err != nil {
Index: libgo/go/debug/dwarf/unit.go
===================================================================
--- libgo/go/debug/dwarf/unit.go	(revision 253311)
+++ libgo/go/debug/dwarf/unit.go	(working copy)
@@ -61,13 +61,20 @@  func (d *Data) parseUnits() ([]unit, err
 		u.base = b.off
 		var n Offset
 		n, u.is64 = b.unitLength()
+		dataOff := b.off
 		vers := b.uint16()
 		if vers != 2 && vers != 3 && vers != 4 {
 			b.error("unsupported DWARF version " + strconv.Itoa(int(vers)))
 			break
 		}
 		u.vers = int(vers)
-		atable, err := d.parseAbbrev(b.uint32(), u.vers)
+		var abbrevOff uint64
+		if u.is64 {
+			abbrevOff = b.uint64()
+		} else {
+			abbrevOff = uint64(b.uint32())
+		}
+		atable, err := d.parseAbbrev(abbrevOff, u.vers)
 		if err != nil {
 			if b.err == nil {
 				b.err = err
@@ -77,7 +84,7 @@  func (d *Data) parseUnits() ([]unit, err
 		u.atable = atable
 		u.asize = int(b.uint8())
 		u.off = b.off
-		u.data = b.bytes(int(n - (2 + 4 + 1)))
+		u.data = b.bytes(int(n - (b.off - dataOff)))
 	}
 	if b.err != nil {
 		return nil, b.err