1 // Copyright 2009 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
17 var typedefTests
= map[string]string{
18 "t_ptr_volatile_int": "*volatile int",
19 "t_ptr_const_char": "*const char",
21 "t_ushort": "short unsigned int",
22 "t_func_int_of_float_double": "func(float, double) int",
23 "t_ptr_func_int_of_float_double": "*func(float, double) int",
24 "t_ptr_func_int_of_float_complex": "*func(complex float) int",
25 "t_ptr_func_int_of_double_complex": "*func(complex double) int",
26 "t_ptr_func_int_of_long_double_complex": "*func(complex long double) int",
27 "t_func_ptr_int_of_char_schar_uchar": "func(char, signed char, unsigned char) *int",
28 "t_func_void_of_char": "func(char) void",
29 "t_func_void_of_void": "func() void",
30 "t_func_void_of_ptr_char_dots": "func(*char, ...) void",
31 "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}",
32 "t_my_struct1": "struct my_struct1 {zz [1]int@0}",
33 "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}",
34 "t_my_enum": "enum my_enum {e1=1; e2=2; e3=-5; e4=1000000000000000}",
35 "t_my_list": "struct list {val short int@0; next *t_my_list@8}",
36 "t_my_tree": "struct tree {left *struct tree@0; right *struct tree@8; val long long unsigned int@16}",
39 // As Apple converts gcc to a clang-based front end
40 // they keep breaking the DWARF output. This map lists the
41 // conversion from real answer to Apple answer.
42 var machoBug
= map[string]string{
43 "func(*char, ...) void": "func(*char) void",
44 "enum my_enum {e1=1; e2=2; e3=-5; e4=1000000000000000}": "enum my_enum {e1=1; e2=2; e3=-5; e4=-1530494976}",
47 func elfData(t
*testing
.T
, name
string) *Data
{
48 f
, err
:= elf
.Open(name
)
60 func machoData(t
*testing
.T
, name
string) *Data
{
61 f
, err
:= macho
.Open(name
)
73 func peData(t
*testing
.T
, name
string) *Data
{
74 f
, err
:= pe
.Open(name
)
86 func TestTypedefsELF(t
*testing
.T
) {
87 testTypedefs(t
, elfData(t
, "testdata/typedef.elf"), "elf", typedefTests
)
90 func TestTypedefsMachO(t
*testing
.T
) {
91 testTypedefs(t
, machoData(t
, "testdata/typedef.macho"), "macho", typedefTests
)
94 func TestTypedefsELFDwarf4(t
*testing
.T
) {
95 testTypedefs(t
, elfData(t
, "testdata/typedef.elf4"), "elf", typedefTests
)
98 func testTypedefs(t
*testing
.T
, d
*Data
, kind
string, testcases
map[string]string) {
100 seen
:= make(map[string]bool)
104 t
.Fatal("r.Next:", err
)
109 if e
.Tag
== TagTypedef
{
110 typ
, err
:= d
.Type(e
.Offset
)
112 t
.Fatal("d.Type:", err
)
114 t1
:= typ
.(*TypedefType
)
116 if ts
, ok
:= t1
.Type
.(*StructType
); ok
{
119 typstr
= t1
.Type
.String()
122 if want
, ok
:= testcases
[t1
.Name
]; ok
{
124 t
.Errorf("multiple definitions for %s", t1
.Name
)
127 if typstr
!= want
&& (kind
!= "macho" || typstr
!= machoBug
[want
]) {
128 t
.Errorf("%s:\n\thave %s\n\twant %s", t1
.Name
, typstr
, want
)
132 if e
.Tag
!= TagCompileUnit
{
137 for k
:= range testcases
{
139 t
.Errorf("missing %s", k
)
144 func TestTypedefCycle(t
*testing
.T
) {
145 // See issue #13039: reading a typedef cycle starting from a
146 // different place than the size needed to be computed from
149 // cycle.elf built with GCC 4.8.4:
150 // gcc -g -c -o cycle.elf cycle.c
151 d
:= elfData(t
, "testdata/cycle.elf")
153 offsets
:= []Offset
{}
157 t
.Fatal("r.Next:", err
)
163 case TagBaseType
, TagTypedef
, TagPointerType
, TagStructType
:
164 offsets
= append(offsets
, e
.Offset
)
168 // Parse each type with a fresh type cache.
169 for _
, offset
:= range offsets
{
170 d
:= elfData(t
, "testdata/cycle.elf")
171 _
, err
:= d
.Type(offset
)
173 t
.Fatalf("d.Type(0x%x): %s", offset
, err
)
178 var unsupportedTypeTests
= []string{
179 // varname:typename:string:size
180 "culprit::(unsupported type ReferenceType):8",
181 "pdm::(unsupported type PtrToMemberType):-1",
184 func TestUnsupportedTypes(t
*testing
.T
) {
186 // When reading DWARF from C++ load modules, we can encounter
187 // oddball type DIEs. These will be returned as "UnsupportedType"
188 // objects; check to make sure this works properly.
189 d
:= elfData(t
, "testdata/cppunsuptypes.elf")
191 seen
:= make(map[string]bool)
195 t
.Fatal("r.Next:", err
)
200 if e
.Tag
== TagVariable
{
201 vname
, _
:= e
.Val(AttrName
).(string)
202 tAttr
:= e
.Val(AttrType
)
203 typOff
, ok
:= tAttr
.(Offset
)
205 t
.Errorf("variable at offset %v has no type", e
.Offset
)
208 typ
, err
:= d
.Type(typOff
)
210 t
.Errorf("err in type decode: %v\n", err
)
213 unsup
, isok
:= typ
.(*UnsupportedType
)
217 tag
:= vname
+ ":" + unsup
.Name
+ ":" + unsup
.String() +
218 ":" + strconv
.FormatInt(unsup
.Size(), 10)
223 for _
, v
:= range unsupportedTypeTests
{
225 t
.Errorf("missing %s", v
)
230 for k
:= range seen
{
231 fmt
.Printf("seen: %s\n", k
)
236 var expectedBitOffsets1
= map[string]string{
241 var expectedBitOffsets2
= map[string]string{
246 func TestBitOffsetsELF(t
*testing
.T
) {
247 f
:= "testdata/typedef.elf"
248 testBitOffsets(t
, elfData(t
, f
), f
, expectedBitOffsets2
)
251 func TestBitOffsetsMachO(t
*testing
.T
) {
252 f
:= "testdata/typedef.macho"
253 testBitOffsets(t
, machoData(t
, f
), f
, expectedBitOffsets2
)
256 func TestBitOffsetsMachO4(t
*testing
.T
) {
257 f
:= "testdata/typedef.macho4"
258 testBitOffsets(t
, machoData(t
, f
), f
, expectedBitOffsets1
)
261 func TestBitOffsetsELFDwarf4(t
*testing
.T
) {
262 f
:= "testdata/typedef.elf4"
263 testBitOffsets(t
, elfData(t
, f
), f
, expectedBitOffsets1
)
266 func TestBitOffsetsELFDwarf5(t
*testing
.T
) {
267 f
:= "testdata/typedef.elf5"
268 testBitOffsets(t
, elfData(t
, f
), f
, expectedBitOffsets1
)
271 func testBitOffsets(t
*testing
.T
, d
*Data
, tag
string, expectedBitOffsets
map[string]string) {
276 t
.Fatal("r.Next:", err
)
282 if e
.Tag
== TagStructType
{
283 typ
, err
:= d
.Type(e
.Offset
)
285 t
.Fatal("d.Type:", err
)
288 t1
:= typ
.(*StructType
)
290 bitInfoDump
:= func(f
*StructField
) string {
291 res
:= fmt
.Sprintf("S:%d", f
.BitSize
)
292 if f
.BitOffset
!= 0 {
293 res
+= fmt
.Sprintf(" BO:%d", f
.BitOffset
)
295 if f
.DataBitOffset
!= 0 {
296 res
+= fmt
.Sprintf(" DBO:%d", f
.DataBitOffset
)
301 for _
, field
:= range t1
.Field
{
302 // We're only testing for bitfields
303 if field
.BitSize
== 0 {
306 got
:= bitInfoDump(field
)
307 want
:= expectedBitOffsets
[field
.Name
]
309 t
.Errorf("%s: field %s in %s: got info %q want %q", tag
, field
.Name
, t1
.StructName
, got
, want
)
313 if e
.Tag
!= TagCompileUnit
{
319 var bitfieldTests
= map[string]string{
320 "t_another_struct": "struct another_struct {quix short unsigned int@0; xyz [0]int@4; x unsigned int@4 : 1@31; array [40]long long int@8}",
323 // TestBitFieldZeroArrayIssue50685 checks to make sure that the DWARF
324 // type reading code doesn't get confused by the presence of a
325 // specifically-sized bitfield member immediately following a field
326 // whose type is a zero-length array. Prior to the fix for issue
327 // 50685, we would get this type for the case in testdata/bitfields.c:
329 // another_struct {quix short unsigned int@0; xyz [-1]int@4; x unsigned int@4 : 1@31; array [40]long long int@8}
331 // Note the "-1" for the xyz field, which should be zero.
333 func TestBitFieldZeroArrayIssue50685(t
*testing
.T
) {
334 f
:= "testdata/bitfields.elf4"
335 testTypedefs(t
, elfData(t
, f
), "elf", bitfieldTests
)