mirror of
https://github.com/golang/go
synced 2024-11-24 08:20:03 -07:00
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. Change-Id: Idc22e59ffb354d58e9973b62fdbd342acf695859 Reviewed-on: https://go-review.googlesource.com/71171 Reviewed-by: Austin Clements <austin@google.com>
This commit is contained in:
parent
4fe43f8146
commit
151c66b59f
@ -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:]
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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"}
|
||||
|
@ -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 {
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user