mirror of
https://github.com/golang/go
synced 2024-11-24 10:40:10 -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
|
// ParseAbbrev returns the abbreviation table that starts at byte off
|
||||||
// in the .debug_abbrev section.
|
// 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 {
|
if m, ok := d.abbrevCache[off]; ok {
|
||||||
return m, nil
|
return m, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
data := d.abbrev
|
data := d.abbrev
|
||||||
if off > uint32(len(data)) {
|
if off > uint64(len(data)) {
|
||||||
data = nil
|
data = nil
|
||||||
} else {
|
} else {
|
||||||
data = data[off:]
|
data = data[off:]
|
||||||
|
@ -135,3 +135,63 @@ func TestReaderRanges(t *testing.T) {
|
|||||||
t.Errorf("saw only %d subprograms, expected %d", i, len(subprograms))
|
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
|
str []byte
|
||||||
|
|
||||||
// parsed data
|
// parsed data
|
||||||
abbrevCache map[uint32]abbrevTable
|
abbrevCache map[uint64]abbrevTable
|
||||||
order binary.ByteOrder
|
order binary.ByteOrder
|
||||||
typeCache map[Offset]Type
|
typeCache map[Offset]Type
|
||||||
typeSigs map[uint64]*typeUnit
|
typeSigs map[uint64]*typeUnit
|
||||||
@ -48,17 +48,26 @@ func New(abbrev, aranges, frame, info, line, pubnames, ranges, str []byte) (*Dat
|
|||||||
pubnames: pubnames,
|
pubnames: pubnames,
|
||||||
ranges: ranges,
|
ranges: ranges,
|
||||||
str: str,
|
str: str,
|
||||||
abbrevCache: make(map[uint32]abbrevTable),
|
abbrevCache: make(map[uint64]abbrevTable),
|
||||||
typeCache: make(map[Offset]Type),
|
typeCache: make(map[Offset]Type),
|
||||||
typeSigs: make(map[uint64]*typeUnit),
|
typeSigs: make(map[uint64]*typeUnit),
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sniff .debug_info to figure out byte order.
|
// 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 {
|
if len(d.info) < 6 {
|
||||||
return nil, DecodeError{"info", Offset(len(d.info)), "too short"}
|
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 {
|
switch {
|
||||||
case x == 0 && y == 0:
|
case x == 0 && y == 0:
|
||||||
return nil, DecodeError{"info", 4, "unsupported version 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))
|
b.error("unsupported DWARF version " + strconv.Itoa(vers))
|
||||||
return b.err
|
return b.err
|
||||||
}
|
}
|
||||||
var ao uint32
|
var ao uint64
|
||||||
if !dwarf64 {
|
if !dwarf64 {
|
||||||
ao = b.uint32()
|
ao = uint64(b.uint32())
|
||||||
} else {
|
} else {
|
||||||
ao64 := b.uint64()
|
ao = b.uint64()
|
||||||
if ao64 != uint64(uint32(ao64)) {
|
|
||||||
b.error("type unit abbrev offset overflow")
|
|
||||||
return b.err
|
|
||||||
}
|
|
||||||
ao = uint32(ao64)
|
|
||||||
}
|
}
|
||||||
atable, err := d.parseAbbrev(ao, vers)
|
atable, err := d.parseAbbrev(ao, vers)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -61,13 +61,20 @@ func (d *Data) parseUnits() ([]unit, error) {
|
|||||||
u.base = b.off
|
u.base = b.off
|
||||||
var n Offset
|
var n Offset
|
||||||
n, u.is64 = b.unitLength()
|
n, u.is64 = b.unitLength()
|
||||||
|
dataOff := b.off
|
||||||
vers := b.uint16()
|
vers := b.uint16()
|
||||||
if vers != 2 && vers != 3 && vers != 4 {
|
if vers != 2 && vers != 3 && vers != 4 {
|
||||||
b.error("unsupported DWARF version " + strconv.Itoa(int(vers)))
|
b.error("unsupported DWARF version " + strconv.Itoa(int(vers)))
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
u.vers = int(vers)
|
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 err != nil {
|
||||||
if b.err == nil {
|
if b.err == nil {
|
||||||
b.err = err
|
b.err = err
|
||||||
@ -77,7 +84,7 @@ func (d *Data) parseUnits() ([]unit, error) {
|
|||||||
u.atable = atable
|
u.atable = atable
|
||||||
u.asize = int(b.uint8())
|
u.asize = int(b.uint8())
|
||||||
u.off = b.off
|
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 {
|
if b.err != nil {
|
||||||
return nil, b.err
|
return nil, b.err
|
||||||
|
Loading…
Reference in New Issue
Block a user