aboutsummaryrefslogtreecommitdiff
path: root/libgo/go/debug/dwarf
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@google.com>2016-02-03 21:58:02 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2016-02-03 21:58:02 +0000
commitf98dd1a338867a408f7c72d73fbad7fe7fc93e3a (patch)
tree2f8da9862a9c1fe0df138917f997b03439c02773 /libgo/go/debug/dwarf
parentb081ed4efc144da0c45a6484aebfd10e0eb9fda3 (diff)
downloadgcc-f98dd1a338867a408f7c72d73fbad7fe7fc93e3a.zip
gcc-f98dd1a338867a408f7c72d73fbad7fe7fc93e3a.tar.gz
gcc-f98dd1a338867a408f7c72d73fbad7fe7fc93e3a.tar.bz2
libgo: Update to go1.6rc1.
Reviewed-on: https://go-review.googlesource.com/19200 From-SVN: r233110
Diffstat (limited to 'libgo/go/debug/dwarf')
-rw-r--r--libgo/go/debug/dwarf/class_string.go7
-rw-r--r--libgo/go/debug/dwarf/entry.go11
-rw-r--r--libgo/go/debug/dwarf/entry_test.go36
-rw-r--r--libgo/go/debug/dwarf/testdata/cycle.c7
-rw-r--r--libgo/go/debug/dwarf/testdata/cycle.elfbin0 -> 2624 bytes
-rw-r--r--libgo/go/debug/dwarf/testdata/split.c5
-rw-r--r--libgo/go/debug/dwarf/testdata/split.elfbin0 -> 9509 bytes
-rw-r--r--libgo/go/debug/dwarf/type.go34
-rw-r--r--libgo/go/debug/dwarf/type_test.go34
-rw-r--r--libgo/go/debug/dwarf/typeunit.go2
10 files changed, 121 insertions, 15 deletions
diff --git a/libgo/go/debug/dwarf/class_string.go b/libgo/go/debug/dwarf/class_string.go
index 0b1206b..d57d9f7 100644
--- a/libgo/go/debug/dwarf/class_string.go
+++ b/libgo/go/debug/dwarf/class_string.go
@@ -4,14 +4,13 @@ package dwarf
import "fmt"
-const _Class_name = "ClassAddressClassBlockClassConstantClassExprLocClassFlagClassLinePtrClassLocListPtrClassMacPtrClassRangeListPtrClassReferenceClassReferenceSigClassStringClassReferenceAltClassStringAlt"
+const _Class_name = "ClassUnknownClassAddressClassBlockClassConstantClassExprLocClassFlagClassLinePtrClassLocListPtrClassMacPtrClassRangeListPtrClassReferenceClassReferenceSigClassStringClassReferenceAltClassStringAlt"
-var _Class_index = [...]uint8{0, 12, 22, 35, 47, 56, 68, 83, 94, 111, 125, 142, 153, 170, 184}
+var _Class_index = [...]uint8{0, 12, 24, 34, 47, 59, 68, 80, 95, 106, 123, 137, 154, 165, 182, 196}
func (i Class) String() string {
- i -= 1
if i < 0 || i+1 >= Class(len(_Class_index)) {
- return fmt.Sprintf("Class(%d)", i+1)
+ return fmt.Sprintf("Class(%d)", i)
}
return _Class_name[_Class_index[i]:_Class_index[i+1]]
}
diff --git a/libgo/go/debug/dwarf/entry.go b/libgo/go/debug/dwarf/entry.go
index d607e5b..5ca8667 100644
--- a/libgo/go/debug/dwarf/entry.go
+++ b/libgo/go/debug/dwarf/entry.go
@@ -193,8 +193,7 @@ func formToClass(form format, attr Attr, vers int, b *buf) Class {
if class, ok := attrPtrClass[attr]; ok {
return class
}
- b.error("cannot determine class of unknown attribute with formSecOffset")
- return 0
+ return ClassUnknown
case formExprloc:
return ClassExprLoc
@@ -235,6 +234,9 @@ type Entry struct {
// loclistptr int64 ClassLocListPtr
// macptr int64 ClassMacPtr
// rangelistptr int64 ClassRangeListPtr
+//
+// For unrecognized or vendor-defined attributes, Class may be
+// ClassUnknown.
type Field struct {
Attr Attr
Val interface{}
@@ -258,9 +260,12 @@ type Field struct {
type Class int
const (
+ // ClassUnknown represents values of unknown DWARF class.
+ ClassUnknown Class = iota
+
// ClassAddress represents values of type uint64 that are
// addresses on the target machine.
- ClassAddress Class = 1 + iota
+ ClassAddress
// ClassBlock represents values of type []byte whose
// interpretation depends on the attribute.
diff --git a/libgo/go/debug/dwarf/entry_test.go b/libgo/go/debug/dwarf/entry_test.go
new file mode 100644
index 0000000..8bd2d2a
--- /dev/null
+++ b/libgo/go/debug/dwarf/entry_test.go
@@ -0,0 +1,36 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package dwarf_test
+
+import (
+ . "debug/dwarf"
+ "testing"
+)
+
+func TestSplit(t *testing.T) {
+ // debug/dwarf doesn't (currently) support split DWARF, but
+ // the attributes that pointed to the split DWARF used to
+ // cause loading the DWARF data to fail entirely (issue
+ // #12592). Test that we can at least read the DWARF data.
+ d := elfData(t, "testdata/split.elf")
+ r := d.Reader()
+ e, err := r.Next()
+ if err != nil {
+ t.Fatal(err)
+ }
+ if e.Tag != TagCompileUnit {
+ t.Fatalf("bad tag: have %s, want %s", e.Tag, TagCompileUnit)
+ }
+ // Check that we were able to parse the unknown section offset
+ // field, even if we can't figure out its DWARF class.
+ const AttrGNUAddrBase Attr = 0x2133
+ f := e.AttrField(AttrGNUAddrBase)
+ if _, ok := f.Val.(int64); !ok {
+ t.Fatalf("bad attribute value type: have %T, want int64", f.Val)
+ }
+ if f.Class != ClassUnknown {
+ t.Fatalf("bad class: have %s, want %s", f.Class, ClassUnknown)
+ }
+}
diff --git a/libgo/go/debug/dwarf/testdata/cycle.c b/libgo/go/debug/dwarf/testdata/cycle.c
new file mode 100644
index 0000000..a0b53df
--- /dev/null
+++ b/libgo/go/debug/dwarf/testdata/cycle.c
@@ -0,0 +1,7 @@
+typedef struct aaa *AAA;
+typedef AAA BBB;
+struct aaa { BBB val; };
+
+AAA x(void) {
+ return (AAA)0;
+}
diff --git a/libgo/go/debug/dwarf/testdata/cycle.elf b/libgo/go/debug/dwarf/testdata/cycle.elf
new file mode 100644
index 0000000..e0b66ca
--- /dev/null
+++ b/libgo/go/debug/dwarf/testdata/cycle.elf
Binary files differ
diff --git a/libgo/go/debug/dwarf/testdata/split.c b/libgo/go/debug/dwarf/testdata/split.c
new file mode 100644
index 0000000..0ef3427
--- /dev/null
+++ b/libgo/go/debug/dwarf/testdata/split.c
@@ -0,0 +1,5 @@
+// gcc -gsplit-dwarf split.c -o split.elf
+
+int main()
+{
+}
diff --git a/libgo/go/debug/dwarf/testdata/split.elf b/libgo/go/debug/dwarf/testdata/split.elf
new file mode 100644
index 0000000..99ee2c2
--- /dev/null
+++ b/libgo/go/debug/dwarf/testdata/split.elf
Binary files differ
diff --git a/libgo/go/debug/dwarf/type.go b/libgo/go/debug/dwarf/type.go
index a5daa1d..c76a472 100644
--- a/libgo/go/debug/dwarf/type.go
+++ b/libgo/go/debug/dwarf/type.go
@@ -275,12 +275,14 @@ type typeReader interface {
// Type reads the type at off in the DWARF ``info'' section.
func (d *Data) Type(off Offset) (Type, error) {
- return d.readType("info", d.Reader(), off, d.typeCache)
+ return d.readType("info", d.Reader(), off, d.typeCache, nil)
}
-// readType reads a type from r at off of name using and updating a
-// type cache.
-func (d *Data) readType(name string, r typeReader, off Offset, typeCache map[Offset]Type) (Type, error) {
+// readType reads a type from r at off of name. It adds types to the
+// type cache, appends new typedef types to typedefs, and computes the
+// sizes of types. Callers should pass nil for typedefs; this is used
+// for internal recursion.
+func (d *Data) readType(name string, r typeReader, off Offset, typeCache map[Offset]Type, typedefs *[]*TypedefType) (Type, error) {
if t, ok := typeCache[off]; ok {
return t, nil
}
@@ -294,9 +296,24 @@ func (d *Data) readType(name string, r typeReader, off Offset, typeCache map[Off
return nil, DecodeError{name, off, "no type at offset"}
}
+ // If this is the root of the recursion, prepare to resolve
+ // typedef sizes once the recursion is done. This must be done
+ // after the type graph is constructed because it may need to
+ // resolve cycles in a different order than readType
+ // encounters them.
+ if typedefs == nil {
+ var typedefList []*TypedefType
+ defer func() {
+ for _, t := range typedefList {
+ t.Common().ByteSize = t.Type.Size()
+ }
+ }()
+ typedefs = &typedefList
+ }
+
// Parse type from Entry.
// Must always set typeCache[off] before calling
- // d.Type recursively, to handle circular types correctly.
+ // d.readType recursively, to handle circular types correctly.
var typ Type
nextDepth := 0
@@ -345,7 +362,7 @@ func (d *Data) readType(name string, r typeReader, off Offset, typeCache map[Off
var t Type
switch toff := tval.(type) {
case Offset:
- if t, err = d.readType(name, r.clone(), toff, typeCache); err != nil {
+ if t, err = d.readType(name, r.clone(), toff, typeCache, typedefs); err != nil {
return nil
}
case uint64:
@@ -674,7 +691,10 @@ func (d *Data) readType(name string, r typeReader, off Offset, typeCache map[Off
b = -1
switch t := typ.(type) {
case *TypedefType:
- b = t.Type.Size()
+ // Record that we need to resolve this
+ // type's size once the type graph is
+ // constructed.
+ *typedefs = append(*typedefs, t)
case *PtrType:
b = int64(addressSize)
}
diff --git a/libgo/go/debug/dwarf/type_test.go b/libgo/go/debug/dwarf/type_test.go
index 2cb85e7..ad6308d 100644
--- a/libgo/go/debug/dwarf/type_test.go
+++ b/libgo/go/debug/dwarf/type_test.go
@@ -120,3 +120,37 @@ func testTypedefs(t *testing.T, d *Data, kind string) {
}
}
}
+
+func TestTypedefCycle(t *testing.T) {
+ // See issue #13039: reading a typedef cycle starting from a
+ // different place than the size needed to be computed from
+ // used to crash.
+ //
+ // cycle.elf built with GCC 4.8.4:
+ // gcc -g -c -o cycle.elf cycle.c
+ d := elfData(t, "testdata/cycle.elf")
+ r := d.Reader()
+ offsets := []Offset{}
+ for {
+ e, err := r.Next()
+ if err != nil {
+ t.Fatal("r.Next:", err)
+ }
+ if e == nil {
+ break
+ }
+ switch e.Tag {
+ case TagBaseType, TagTypedef, TagPointerType, TagStructType:
+ offsets = append(offsets, e.Offset)
+ }
+ }
+
+ // Parse each type with a fresh type cache.
+ for _, offset := range offsets {
+ d := elfData(t, "testdata/cycle.elf")
+ _, err := d.Type(offset)
+ if err != nil {
+ t.Fatalf("d.Type(0x%x): %s", offset, err)
+ }
+ }
+}
diff --git a/libgo/go/debug/dwarf/typeunit.go b/libgo/go/debug/dwarf/typeunit.go
index 9cfb4a8..0f4e07e 100644
--- a/libgo/go/debug/dwarf/typeunit.go
+++ b/libgo/go/debug/dwarf/typeunit.go
@@ -101,7 +101,7 @@ func (d *Data) sigToType(sig uint64) (Type, error) {
b := makeBuf(d, tu, tu.name, tu.off, tu.data)
r := &typeUnitReader{d: d, tu: tu, b: b}
- t, err := d.readType(tu.name, r, Offset(tu.toff), make(map[Offset]Type))
+ t, err := d.readType(tu.name, r, Offset(tu.toff), make(map[Offset]Type), nil)
if err != nil {
return nil, err
}