Patchwork libgo patch committed: DWARF line reader fixes

login
register
mail settings
Submitter Ian Taylor
Date Sept. 6, 2012, 5:28 a.m.
Message ID <mcrfw6vafeu.fsf@dhcp-172-18-216-180.mtv.corp.google.com>
Download mbox | patch
Permalink /patch/182012/
State New
Headers show

Comments

Ian Taylor - Sept. 6, 2012, 5:28 a.m.
This patch to libgo fixes a couple of things in the DWARF line reader.
It adds support for DW_AT_high_pc as a constant offset from
DW_AT_low_pc.  It adds support for DW_AT_ranges.  Bootstrapped and ran
Go testsuite on x86_64-unknown-linux-gnu.  Committed to mainline and 4.7
branch.

This fixes some testsuite failures reported in PR gcc/52583, although
that PR was originally just for Solaris issues.

Ian

Patch

diff -r e4c5f4a31350 libgo/go/debug/dwarf/line.go
--- a/libgo/go/debug/dwarf/line.go	Wed Aug 22 21:54:46 2012 -0700
+++ b/libgo/go/debug/dwarf/line.go	Wed Sep 05 22:20:02 2012 -0700
@@ -67,12 +67,22 @@ 
 		switch e.Tag {
 		case TagCompileUnit, TagSubprogram, TagEntryPoint, TagInlinedSubroutine:
 			low, lowok := e.Val(AttrLowpc).(uint64)
-			high, highok := e.Val(AttrHighpc).(uint64)
+			var high uint64
+			var highok bool
+			switch v := e.Val(AttrHighpc).(type) {
+			case uint64:
+				high = v
+				highok = true
+			case int64:
+				high = low + uint64(v)
+				highok = true
+			}
 			if lowok && highok {
 				u.pc = append(u.pc, addrRange{low, high})
-			} else if f, ok := e.Val(AttrRanges).(Offset); ok {
-				// TODO: Handle AttrRanges and .debug_ranges.
-				_ = f
+			} else if off, ok := e.Val(AttrRanges).(Offset); ok {
+				if err := d.readAddressRanges(off, low, u); err != nil {
+					return err
+				}
 			}
 			val := e.Val(AttrStmtList)
 			if val != nil {
@@ -98,6 +108,38 @@ 
 	return nil
 }
 
+// readAddressRanges adds address ranges to a unit.
+func (d *Data) readAddressRanges(off Offset, base uint64, u *unit) error {
+	b := makeBuf(d, u, "ranges", off, d.ranges[off:])
+	var highest uint64
+	switch u.addrsize {
+	case 1:
+		highest = 0xff
+	case 2:
+		highest = 0xffff
+	case 4:
+		highest = 0xffffffff
+	case 8:
+		highest = 0xffffffffffffffff
+	default:
+		return errors.New("unknown address size")
+	}
+	for {
+		if b.err != nil {
+			return b.err
+		}
+		low := b.addr()
+		high := b.addr()
+		if low == 0 && high == 0 {
+			return b.err
+		} else if low == highest {
+			base = high
+		} else {
+			u.pc = append(u.pc, addrRange{low + base, high + base})
+		}
+	}
+}
+
 // findLine finds the line information for a PC value, given the unit
 // containing the information.
 func (d *Data) findLine(u *unit, pc uint64) ([]*Line, error) {
diff -r e4c5f4a31350 libgo/go/debug/elf/file.go
--- a/libgo/go/debug/elf/file.go	Wed Aug 22 21:54:46 2012 -0700
+++ b/libgo/go/debug/elf/file.go	Wed Sep 05 22:20:02 2012 -0700
@@ -563,7 +563,7 @@ 
 	// There are many other DWARF sections, but these
 	// are the required ones, and the debug/dwarf package
 	// does not use the others, so don't bother loading them.
-	var names = [...]string{"abbrev", "info", "line", "str"}
+	var names = [...]string{"abbrev", "info", "line", "ranges", "str"}
 	var dat [len(names)][]byte
 	for i, name := range names {
 		name = ".debug_" + name
@@ -592,8 +592,8 @@ 
 		}
 	}
 
-	abbrev, info, line, str := dat[0], dat[1], dat[2], dat[3]
-	return dwarf.New(abbrev, nil, nil, info, line, nil, nil, str)
+	abbrev, info, line, ranges, str := dat[0], dat[1], dat[2], dat[3], dat[4]
+	return dwarf.New(abbrev, nil, nil, info, line, nil, ranges, str)
 }
 
 // Symbols returns the symbol table for f.