aboutsummaryrefslogtreecommitdiff
path: root/src/pkg/debug
diff options
context:
space:
mode:
Diffstat (limited to 'src/pkg/debug')
-rw-r--r--src/pkg/debug/dwarf/testdata/typedef.c8
-rwxr-xr-xsrc/pkg/debug/dwarf/testdata/typedef.elfbin10837 -> 12448 bytes
-rw-r--r--src/pkg/debug/dwarf/testdata/typedef.machobin5256 -> 5024 bytes
-rw-r--r--src/pkg/debug/dwarf/type.go36
-rw-r--r--src/pkg/debug/dwarf/type_test.go19
5 files changed, 56 insertions, 7 deletions
diff --git a/src/pkg/debug/dwarf/testdata/typedef.c b/src/pkg/debug/dwarf/testdata/typedef.c
index 664d021ced..f05f01564f 100644
--- a/src/pkg/debug/dwarf/testdata/typedef.c
+++ b/src/pkg/debug/dwarf/testdata/typedef.c
@@ -28,8 +28,13 @@ typedef struct my_struct {
volatile int vi;
char x : 1;
int y : 4;
+ int z[0];
long long array[40];
+ int zz[0];
} t_my_struct;
+typedef struct my_struct1 {
+ int zz [1];
+} t_my_struct1;
typedef union my_union {
volatile int vi;
char x : 1;
@@ -65,7 +70,8 @@ t_func_void_of_char *a9;
t_func_void_of_void *a10;
t_func_void_of_ptr_char_dots *a11;
t_my_struct *a12;
-t_my_union *a12a;
+t_my_struct1 *a12a;
+t_my_union *a12b;
t_my_enum *a13;
t_my_list *a14;
t_my_tree *a15;
diff --git a/src/pkg/debug/dwarf/testdata/typedef.elf b/src/pkg/debug/dwarf/testdata/typedef.elf
index 44df8da9bc..b2062d2c4b 100755
--- a/src/pkg/debug/dwarf/testdata/typedef.elf
+++ b/src/pkg/debug/dwarf/testdata/typedef.elf
Binary files differ
diff --git a/src/pkg/debug/dwarf/testdata/typedef.macho b/src/pkg/debug/dwarf/testdata/typedef.macho
index 41019c1e14..f75afcccbf 100644
--- a/src/pkg/debug/dwarf/testdata/typedef.macho
+++ b/src/pkg/debug/dwarf/testdata/typedef.macho
Binary files differ
diff --git a/src/pkg/debug/dwarf/type.go b/src/pkg/debug/dwarf/type.go
index 9be66658fe..4502355022 100644
--- a/src/pkg/debug/dwarf/type.go
+++ b/src/pkg/debug/dwarf/type.go
@@ -426,6 +426,8 @@ func (d *Data) Type(off Offset) (Type, error) {
t.StructName, _ = e.Val(AttrName).(string)
t.Incomplete = e.Val(AttrDeclaration) != nil
t.Field = make([]*StructField, 0, 8)
+ var lastFieldType Type
+ var lastFieldBitOffset int64
for kid := next(); kid != nil; kid = next() {
if kid.Tag == TagMember {
f := new(StructField)
@@ -444,11 +446,32 @@ func (d *Data) Type(off Offset) (Type, error) {
goto Error
}
}
+
+ haveBitOffset := false
f.Name, _ = kid.Val(AttrName).(string)
f.ByteSize, _ = kid.Val(AttrByteSize).(int64)
- f.BitOffset, _ = kid.Val(AttrBitOffset).(int64)
+ f.BitOffset, haveBitOffset = kid.Val(AttrBitOffset).(int64)
f.BitSize, _ = kid.Val(AttrBitSize).(int64)
t.Field = append(t.Field, f)
+
+ bito := f.BitOffset
+ if !haveBitOffset {
+ bito = f.ByteOffset * 8
+ }
+ if bito == lastFieldBitOffset && t.Kind != "union" {
+ // Last field was zero width. Fix array length.
+ // (DWARF writes out 0-length arrays as if they were 1-length arrays.)
+ zeroArray(lastFieldType)
+ }
+ lastFieldType = f.Type
+ lastFieldBitOffset = bito
+ }
+ }
+ if t.Kind != "union" {
+ b, ok := e.Val(AttrByteSize).(int64)
+ if ok && b*8 == lastFieldBitOffset {
+ // Final field must be zero width. Fix array length.
+ zeroArray(lastFieldType)
}
}
@@ -579,3 +602,14 @@ Error:
delete(d.typeCache, off)
return nil, err
}
+
+func zeroArray(t Type) {
+ for {
+ at, ok := t.(*ArrayType)
+ if !ok {
+ break
+ }
+ at.Count = 0
+ t = at.Type
+ }
+}
diff --git a/src/pkg/debug/dwarf/type_test.go b/src/pkg/debug/dwarf/type_test.go
index b9470a4fcb..b5b255f6f4 100644
--- a/src/pkg/debug/dwarf/type_test.go
+++ b/src/pkg/debug/dwarf/type_test.go
@@ -25,13 +25,22 @@ var typedefTests = map[string]string{
"t_func_void_of_char": "func(char) void",
"t_func_void_of_void": "func() void",
"t_func_void_of_ptr_char_dots": "func(*char, ...) void",
- "t_my_struct": "struct my_struct {vi volatile int@0; x char@4 : 1@7; y int@4 : 4@27; array [40]long long int@8}",
+ "t_my_struct": "struct my_struct {vi volatile int@0; x char@4 : 1@7; y int@4 : 4@27; z [0]int@8; array [40]long long int@8; zz [0]int@328}",
+ "t_my_struct1": "struct my_struct1 {zz [1]int@0}",
"t_my_union": "union my_union {vi volatile int@0; x char@0 : 1@7; y int@0 : 4@28; array [40]long long int@0}",
"t_my_enum": "enum my_enum {e1=1; e2=2; e3=-5; e4=1000000000000000}",
"t_my_list": "struct list {val short int@0; next *t_my_list@8}",
"t_my_tree": "struct tree {left *struct tree@0; right *struct tree@8; val long long unsigned int@16}",
}
+// As Apple converts gcc to a clang-based front end
+// they keep breaking the DWARF output. This map lists the
+// conversion from real answer to Apple answer.
+var machoBug = map[string]string{
+ "func(*char, ...) void": "func(*char) void",
+ "enum my_enum {e1=1; e2=2; e3=-5; e4=1000000000000000}": "enum my_enum {e1=1; e2=2; e3=-5; e4=-1530494976}",
+}
+
func elfData(t *testing.T, name string) *Data {
f, err := elf.Open(name)
if err != nil {
@@ -58,13 +67,13 @@ func machoData(t *testing.T, name string) *Data {
return d
}
-func TestTypedefsELF(t *testing.T) { testTypedefs(t, elfData(t, "testdata/typedef.elf")) }
+func TestTypedefsELF(t *testing.T) { testTypedefs(t, elfData(t, "testdata/typedef.elf"), "elf") }
func TestTypedefsMachO(t *testing.T) {
- testTypedefs(t, machoData(t, "testdata/typedef.macho"))
+ testTypedefs(t, machoData(t, "testdata/typedef.macho"), "macho")
}
-func testTypedefs(t *testing.T, d *Data) {
+func testTypedefs(t *testing.T, d *Data, kind string) {
r := d.Reader()
seen := make(map[string]bool)
for {
@@ -93,7 +102,7 @@ func testTypedefs(t *testing.T, d *Data) {
t.Errorf("multiple definitions for %s", t1.Name)
}
seen[t1.Name] = true
- if typstr != want {
+ if typstr != want && (kind != "macho" || typstr != machoBug[want]) {
t.Errorf("%s:\n\thave %s\n\twant %s", t1.Name, typstr, want)
}
}