From: Ian Lance Taylor Date: Fri, 20 Oct 2017 18:34:36 +0000 (+0000) Subject: debug/dwarf: support 64-bit DWARF in byte order check X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=001cbba0efcd44aa1c955c5e6fbbb118aec55440;p=gcc.git debug/dwarf: support 64-bit DWARF in byte order check Also fix 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 in the Go 1.10 release, to the gofrontend copy. Doing it now because AIX is pretty much the only system that uses 64-bit DWARF. Reviewed-on: https://go-review.googlesource.com/72250 From-SVN: r253955 --- diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE index 418e1274fdf..8b1846d07c4 100644 --- a/gcc/go/gofrontend/MERGE +++ b/gcc/go/gofrontend/MERGE @@ -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. diff --git a/libgo/go/debug/dwarf/entry.go b/libgo/go/debug/dwarf/entry.go index 80bf14cb22f..ffa61c28d15 100644 --- a/libgo/go/debug/dwarf/entry.go +++ b/libgo/go/debug/dwarf/entry.go @@ -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:] diff --git a/libgo/go/debug/dwarf/entry_test.go b/libgo/go/debug/dwarf/entry_test.go index 58a5d570be5..58f3023d296 100644 --- a/libgo/go/debug/dwarf/entry_test.go +++ b/libgo/go/debug/dwarf/entry_test.go @@ -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) + } + } +} diff --git a/libgo/go/debug/dwarf/open.go b/libgo/go/debug/dwarf/open.go index 253a43cf579..938186998ff 100644 --- a/libgo/go/debug/dwarf/open.go +++ b/libgo/go/debug/dwarf/open.go @@ -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, line, pubnames, ranges, str []byte) (*Dat 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"} diff --git a/libgo/go/debug/dwarf/typeunit.go b/libgo/go/debug/dwarf/typeunit.go index 652e02d9172..76b357ce28b 100644 --- a/libgo/go/debug/dwarf/typeunit.go +++ b/libgo/go/debug/dwarf/typeunit.go @@ -38,16 +38,11 @@ func (d *Data) parseTypes(name string, types []byte) error { 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 { diff --git a/libgo/go/debug/dwarf/unit.go b/libgo/go/debug/dwarf/unit.go index e45aed7ad1d..98024ca1f84 100644 --- a/libgo/go/debug/dwarf/unit.go +++ b/libgo/go/debug/dwarf/unit.go @@ -61,13 +61,20 @@ func (d *Data) parseUnits() ([]unit, error) { 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, error) { 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