mirror of
https://github.com/golang/go
synced 2024-11-19 07:04:43 -07:00
debug/dwarf: factor parsing of unit lengths
Many headers in DWARF sections have a "unit length" that can be either 4 bytes or 12 bytes and indicates both the length of the unit and whether the unit is in 32-bit or 64-bit format. Currently, we implement unit length parsing in four different places. Add a "unitLength" method to buf that parses a unit length and use it in these four places. Change-Id: I7950b91caaa92aa5e19aa63debc8ae46178ecc4d Reviewed-on: https://go-review.googlesource.com/7281 Reviewed-by: Nigel Tao <nigeltao@golang.org> Reviewed-by: Ian Lance Taylor <iant@golang.org>
This commit is contained in:
parent
d533e3955d
commit
9dfbcd8fac
@ -163,6 +163,17 @@ func (b *buf) addr() uint64 {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (b *buf) unitLength() (length Offset, dwarf64 bool) {
|
||||||
|
length = Offset(b.uint32())
|
||||||
|
if length == 0xffffffff {
|
||||||
|
dwarf64 = true
|
||||||
|
length = Offset(b.uint64())
|
||||||
|
} else if length >= 0xfffffff0 {
|
||||||
|
b.error("unit length has reserved value")
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
func (b *buf) error(s string) {
|
func (b *buf) error(s string) {
|
||||||
if b.err == nil {
|
if b.err == nil {
|
||||||
b.data = nil
|
b.data = nil
|
||||||
|
@ -177,14 +177,7 @@ func (r *LineReader) readHeader() error {
|
|||||||
|
|
||||||
// Read basic header fields [DWARF2 6.2.4].
|
// Read basic header fields [DWARF2 6.2.4].
|
||||||
hdrOffset := buf.off
|
hdrOffset := buf.off
|
||||||
dwarf64 := false
|
unitLength, dwarf64 := buf.unitLength()
|
||||||
unitLength := Offset(buf.uint32())
|
|
||||||
if unitLength == 0xffffffff {
|
|
||||||
dwarf64 = true
|
|
||||||
unitLength = Offset(buf.uint64())
|
|
||||||
} else if unitLength >= 0xfffffff0 {
|
|
||||||
return DecodeError{"line", hdrOffset, fmt.Sprintf("total length field has reserved value %#x", unitLength)}
|
|
||||||
}
|
|
||||||
r.endOffset = buf.off + unitLength
|
r.endOffset = buf.off + unitLength
|
||||||
if r.endOffset > buf.off+Offset(len(buf.data)) {
|
if r.endOffset > buf.off+Offset(len(buf.data)) {
|
||||||
return DecodeError{"line", hdrOffset, fmt.Sprintf("line table end %d exceeds section size %d", r.endOffset, buf.off+Offset(len(buf.data)))}
|
return DecodeError{"line", hdrOffset, fmt.Sprintf("line table end %d exceeds section size %d", r.endOffset, buf.off+Offset(len(buf.data)))}
|
||||||
|
@ -27,16 +27,10 @@ func (d *Data) parseTypes(name string, types []byte) error {
|
|||||||
b := makeBuf(d, unknownFormat{}, name, 0, types)
|
b := makeBuf(d, unknownFormat{}, name, 0, types)
|
||||||
for len(b.data) > 0 {
|
for len(b.data) > 0 {
|
||||||
base := b.off
|
base := b.off
|
||||||
dwarf64 := false
|
n, dwarf64 := b.unitLength()
|
||||||
n := b.uint32()
|
if n != Offset(uint32(n)) {
|
||||||
if n == 0xffffffff {
|
b.error("type unit length overflow")
|
||||||
n64 := b.uint64()
|
return b.err
|
||||||
if n64 != uint64(uint32(n64)) {
|
|
||||||
b.error("type unit length overflow")
|
|
||||||
return b.err
|
|
||||||
}
|
|
||||||
n = uint32(n64)
|
|
||||||
dwarf64 = true
|
|
||||||
}
|
}
|
||||||
hdroff := b.off
|
hdroff := b.off
|
||||||
vers := b.uint16()
|
vers := b.uint16()
|
||||||
@ -79,7 +73,7 @@ func (d *Data) parseTypes(name string, types []byte) error {
|
|||||||
unit: unit{
|
unit: unit{
|
||||||
base: base,
|
base: base,
|
||||||
off: boff,
|
off: boff,
|
||||||
data: b.bytes(int(Offset(n) - (b.off - hdroff))),
|
data: b.bytes(int(n - (b.off - hdroff))),
|
||||||
atable: atable,
|
atable: atable,
|
||||||
asize: int(asize),
|
asize: int(asize),
|
||||||
vers: int(vers),
|
vers: int(vers),
|
||||||
|
@ -41,14 +41,10 @@ func (d *Data) parseUnits() ([]unit, error) {
|
|||||||
nunit := 0
|
nunit := 0
|
||||||
b := makeBuf(d, unknownFormat{}, "info", 0, d.info)
|
b := makeBuf(d, unknownFormat{}, "info", 0, d.info)
|
||||||
for len(b.data) > 0 {
|
for len(b.data) > 0 {
|
||||||
len := b.uint32()
|
len, _ := b.unitLength()
|
||||||
if len == 0xffffffff {
|
if len != Offset(uint32(len)) {
|
||||||
len64 := b.uint64()
|
b.error("unit length overflow")
|
||||||
if len64 != uint64(uint32(len64)) {
|
break
|
||||||
b.error("unit length overflow")
|
|
||||||
break
|
|
||||||
}
|
|
||||||
len = uint32(len64)
|
|
||||||
}
|
}
|
||||||
b.skip(int(len))
|
b.skip(int(len))
|
||||||
nunit++
|
nunit++
|
||||||
@ -63,11 +59,8 @@ func (d *Data) parseUnits() ([]unit, error) {
|
|||||||
for i := range units {
|
for i := range units {
|
||||||
u := &units[i]
|
u := &units[i]
|
||||||
u.base = b.off
|
u.base = b.off
|
||||||
n := b.uint32()
|
var n Offset
|
||||||
if n == 0xffffffff {
|
n, u.is64 = b.unitLength()
|
||||||
u.is64 = true
|
|
||||||
n = uint32(b.uint64())
|
|
||||||
}
|
|
||||||
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)))
|
||||||
|
Loading…
Reference in New Issue
Block a user