Commit 9dfbcd8f authored by Austin Clements's avatar Austin Clements

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/7281Reviewed-by: default avatarNigel Tao <nigeltao@golang.org>
Reviewed-by: default avatarIan Lance Taylor <iant@golang.org>
parent d533e395
...@@ -163,6 +163,17 @@ func (b *buf) addr() uint64 { ...@@ -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 { ...@@ -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,17 +27,11 @@ func (d *Data) parseTypes(name string, types []byte) error { ...@@ -27,17 +27,11 @@ 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 {
n64 := b.uint64()
if n64 != uint64(uint32(n64)) {
b.error("type unit length overflow") b.error("type unit length overflow")
return b.err return b.err
} }
n = uint32(n64)
dwarf64 = true
}
hdroff := b.off hdroff := b.off
vers := b.uint16() vers := b.uint16()
if vers != 4 { if vers != 4 {
...@@ -79,7 +73,7 @@ func (d *Data) parseTypes(name string, types []byte) error { ...@@ -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,15 +41,11 @@ func (d *Data) parseUnits() ([]unit, error) { ...@@ -41,15 +41,11 @@ 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()
if len64 != uint64(uint32(len64)) {
b.error("unit length overflow") b.error("unit length overflow")
break break
} }
len = uint32(len64)
}
b.skip(int(len)) b.skip(int(len))
nunit++ nunit++
} }
...@@ -63,11 +59,8 @@ func (d *Data) parseUnits() ([]unit, error) { ...@@ -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)))
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment