]> Cypherpunks.ru repositories - gostls13.git/blob - src/cmd/cgo/gcc.go
cmd/go: prepend builtin prolog when checking for preamble errors
[gostls13.git] / src / cmd / cgo / gcc.go
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.
4
5 // Annotate Ref in Prog with C types by parsing gcc debug output.
6 // Conversion of debug output to Go types.
7
8 package main
9
10 import (
11         "bytes"
12         "debug/dwarf"
13         "debug/elf"
14         "debug/macho"
15         "debug/pe"
16         "encoding/binary"
17         "errors"
18         "flag"
19         "fmt"
20         "go/ast"
21         "go/parser"
22         "go/token"
23         "internal/xcoff"
24         "math"
25         "os"
26         "os/exec"
27         "strconv"
28         "strings"
29         "unicode"
30         "unicode/utf8"
31
32         "cmd/internal/quoted"
33 )
34
35 var debugDefine = flag.Bool("debug-define", false, "print relevant #defines")
36 var debugGcc = flag.Bool("debug-gcc", false, "print gcc invocations")
37
38 var nameToC = map[string]string{
39         "schar":         "signed char",
40         "uchar":         "unsigned char",
41         "ushort":        "unsigned short",
42         "uint":          "unsigned int",
43         "ulong":         "unsigned long",
44         "longlong":      "long long",
45         "ulonglong":     "unsigned long long",
46         "complexfloat":  "float _Complex",
47         "complexdouble": "double _Complex",
48 }
49
50 // cname returns the C name to use for C.s.
51 // The expansions are listed in nameToC and also
52 // struct_foo becomes "struct foo", and similarly for
53 // union and enum.
54 func cname(s string) string {
55         if t, ok := nameToC[s]; ok {
56                 return t
57         }
58
59         if strings.HasPrefix(s, "struct_") {
60                 return "struct " + s[len("struct_"):]
61         }
62         if strings.HasPrefix(s, "union_") {
63                 return "union " + s[len("union_"):]
64         }
65         if strings.HasPrefix(s, "enum_") {
66                 return "enum " + s[len("enum_"):]
67         }
68         if strings.HasPrefix(s, "sizeof_") {
69                 return "sizeof(" + cname(s[len("sizeof_"):]) + ")"
70         }
71         return s
72 }
73
74 // DiscardCgoDirectives processes the import C preamble, and discards
75 // all #cgo CFLAGS and LDFLAGS directives, so they don't make their
76 // way into _cgo_export.h.
77 func (f *File) DiscardCgoDirectives() {
78         linesIn := strings.Split(f.Preamble, "\n")
79         linesOut := make([]string, 0, len(linesIn))
80         for _, line := range linesIn {
81                 l := strings.TrimSpace(line)
82                 if len(l) < 5 || l[:4] != "#cgo" || !unicode.IsSpace(rune(l[4])) {
83                         linesOut = append(linesOut, line)
84                 } else {
85                         linesOut = append(linesOut, "")
86                 }
87         }
88         f.Preamble = strings.Join(linesOut, "\n")
89 }
90
91 // addToFlag appends args to flag. All flags are later written out onto the
92 // _cgo_flags file for the build system to use.
93 func (p *Package) addToFlag(flag string, args []string) {
94         p.CgoFlags[flag] = append(p.CgoFlags[flag], args...)
95         if flag == "CFLAGS" {
96                 // We'll also need these when preprocessing for dwarf information.
97                 // However, discard any -g options: we need to be able
98                 // to parse the debug info, so stick to what we expect.
99                 for _, arg := range args {
100                         if !strings.HasPrefix(arg, "-g") {
101                                 p.GccOptions = append(p.GccOptions, arg)
102                         }
103                 }
104         }
105 }
106
107 // splitQuoted splits the string s around each instance of one or more consecutive
108 // white space characters while taking into account quotes and escaping, and
109 // returns an array of substrings of s or an empty list if s contains only white space.
110 // Single quotes and double quotes are recognized to prevent splitting within the
111 // quoted region, and are removed from the resulting substrings. If a quote in s
112 // isn't closed err will be set and r will have the unclosed argument as the
113 // last element. The backslash is used for escaping.
114 //
115 // For example, the following string:
116 //
117 //      `a b:"c d" 'e''f'  "g\""`
118 //
119 // Would be parsed as:
120 //
121 //      []string{"a", "b:c d", "ef", `g"`}
122 func splitQuoted(s string) (r []string, err error) {
123         var args []string
124         arg := make([]rune, len(s))
125         escaped := false
126         quoted := false
127         quote := '\x00'
128         i := 0
129         for _, r := range s {
130                 switch {
131                 case escaped:
132                         escaped = false
133                 case r == '\\':
134                         escaped = true
135                         continue
136                 case quote != 0:
137                         if r == quote {
138                                 quote = 0
139                                 continue
140                         }
141                 case r == '"' || r == '\'':
142                         quoted = true
143                         quote = r
144                         continue
145                 case unicode.IsSpace(r):
146                         if quoted || i > 0 {
147                                 quoted = false
148                                 args = append(args, string(arg[:i]))
149                                 i = 0
150                         }
151                         continue
152                 }
153                 arg[i] = r
154                 i++
155         }
156         if quoted || i > 0 {
157                 args = append(args, string(arg[:i]))
158         }
159         if quote != 0 {
160                 err = errors.New("unclosed quote")
161         } else if escaped {
162                 err = errors.New("unfinished escaping")
163         }
164         return args, err
165 }
166
167 // Translate rewrites f.AST, the original Go input, to remove
168 // references to the imported package C, replacing them with
169 // references to the equivalent Go types, functions, and variables.
170 func (p *Package) Translate(f *File) {
171         for _, cref := range f.Ref {
172                 // Convert C.ulong to C.unsigned long, etc.
173                 cref.Name.C = cname(cref.Name.Go)
174         }
175
176         var conv typeConv
177         conv.Init(p.PtrSize, p.IntSize)
178
179         p.loadDefines(f)
180         p.typedefs = map[string]bool{}
181         p.typedefList = nil
182         numTypedefs := -1
183         for len(p.typedefs) > numTypedefs {
184                 numTypedefs = len(p.typedefs)
185                 // Also ask about any typedefs we've seen so far.
186                 for _, info := range p.typedefList {
187                         if f.Name[info.typedef] != nil {
188                                 continue
189                         }
190                         n := &Name{
191                                 Go: info.typedef,
192                                 C:  info.typedef,
193                         }
194                         f.Name[info.typedef] = n
195                         f.NamePos[n] = info.pos
196                 }
197                 needType := p.guessKinds(f)
198                 if len(needType) > 0 {
199                         p.loadDWARF(f, &conv, needType)
200                 }
201
202                 // In godefs mode we're OK with the typedefs, which
203                 // will presumably also be defined in the file, we
204                 // don't want to resolve them to their base types.
205                 if *godefs {
206                         break
207                 }
208         }
209         p.prepareNames(f)
210         if p.rewriteCalls(f) {
211                 // Add `import _cgo_unsafe "unsafe"` after the package statement.
212                 f.Edit.Insert(f.offset(f.AST.Name.End()), "; import _cgo_unsafe \"unsafe\"")
213         }
214         p.rewriteRef(f)
215 }
216
217 // loadDefines coerces gcc into spitting out the #defines in use
218 // in the file f and saves relevant renamings in f.Name[name].Define.
219 func (p *Package) loadDefines(f *File) {
220         var b bytes.Buffer
221         b.WriteString(builtinProlog)
222         b.WriteString(f.Preamble)
223         stdout := p.gccDefines(b.Bytes())
224
225         for _, line := range strings.Split(stdout, "\n") {
226                 if len(line) < 9 || line[0:7] != "#define" {
227                         continue
228                 }
229
230                 line = strings.TrimSpace(line[8:])
231
232                 var key, val string
233                 spaceIndex := strings.Index(line, " ")
234                 tabIndex := strings.Index(line, "\t")
235
236                 if spaceIndex == -1 && tabIndex == -1 {
237                         continue
238                 } else if tabIndex == -1 || (spaceIndex != -1 && spaceIndex < tabIndex) {
239                         key = line[0:spaceIndex]
240                         val = strings.TrimSpace(line[spaceIndex:])
241                 } else {
242                         key = line[0:tabIndex]
243                         val = strings.TrimSpace(line[tabIndex:])
244                 }
245
246                 if key == "__clang__" {
247                         p.GccIsClang = true
248                 }
249
250                 if n := f.Name[key]; n != nil {
251                         if *debugDefine {
252                                 fmt.Fprintf(os.Stderr, "#define %s %s\n", key, val)
253                         }
254                         n.Define = val
255                 }
256         }
257 }
258
259 // guessKinds tricks gcc into revealing the kind of each
260 // name xxx for the references C.xxx in the Go input.
261 // The kind is either a constant, type, or variable.
262 func (p *Package) guessKinds(f *File) []*Name {
263         // Determine kinds for names we already know about,
264         // like #defines or 'struct foo', before bothering with gcc.
265         var names, needType []*Name
266         optional := map[*Name]bool{}
267         for _, key := range nameKeys(f.Name) {
268                 n := f.Name[key]
269                 // If we've already found this name as a #define
270                 // and we can translate it as a constant value, do so.
271                 if n.Define != "" {
272                         if i, err := strconv.ParseInt(n.Define, 0, 64); err == nil {
273                                 n.Kind = "iconst"
274                                 // Turn decimal into hex, just for consistency
275                                 // with enum-derived constants. Otherwise
276                                 // in the cgo -godefs output half the constants
277                                 // are in hex and half are in whatever the #define used.
278                                 n.Const = fmt.Sprintf("%#x", i)
279                         } else if n.Define[0] == '\'' {
280                                 if _, err := parser.ParseExpr(n.Define); err == nil {
281                                         n.Kind = "iconst"
282                                         n.Const = n.Define
283                                 }
284                         } else if n.Define[0] == '"' {
285                                 if _, err := parser.ParseExpr(n.Define); err == nil {
286                                         n.Kind = "sconst"
287                                         n.Const = n.Define
288                                 }
289                         }
290
291                         if n.IsConst() {
292                                 continue
293                         }
294                 }
295
296                 // If this is a struct, union, or enum type name, no need to guess the kind.
297                 if strings.HasPrefix(n.C, "struct ") || strings.HasPrefix(n.C, "union ") || strings.HasPrefix(n.C, "enum ") {
298                         n.Kind = "type"
299                         needType = append(needType, n)
300                         continue
301                 }
302
303                 if (goos == "darwin" || goos == "ios") && strings.HasSuffix(n.C, "Ref") {
304                         // For FooRef, find out if FooGetTypeID exists.
305                         s := n.C[:len(n.C)-3] + "GetTypeID"
306                         n := &Name{Go: s, C: s}
307                         names = append(names, n)
308                         optional[n] = true
309                 }
310
311                 // Otherwise, we'll need to find out from gcc.
312                 names = append(names, n)
313         }
314
315         // Bypass gcc if there's nothing left to find out.
316         if len(names) == 0 {
317                 return needType
318         }
319
320         // Coerce gcc into telling us whether each name is a type, a value, or undeclared.
321         // For names, find out whether they are integer constants.
322         // We used to look at specific warning or error messages here, but that tied the
323         // behavior too closely to specific versions of the compilers.
324         // Instead, arrange that we can infer what we need from only the presence or absence
325         // of an error on a specific line.
326         //
327         // For each name, we generate these lines, where xxx is the index in toSniff plus one.
328         //
329         //      #line xxx "not-declared"
330         //      void __cgo_f_xxx_1(void) { __typeof__(name) *__cgo_undefined__1; }
331         //      #line xxx "not-type"
332         //      void __cgo_f_xxx_2(void) { name *__cgo_undefined__2; }
333         //      #line xxx "not-int-const"
334         //      void __cgo_f_xxx_3(void) { enum { __cgo_undefined__3 = (name)*1 }; }
335         //      #line xxx "not-num-const"
336         //      void __cgo_f_xxx_4(void) { static const double __cgo_undefined__4 = (name); }
337         //      #line xxx "not-str-lit"
338         //      void __cgo_f_xxx_5(void) { static const char __cgo_undefined__5[] = (name); }
339         //
340         // If we see an error at not-declared:xxx, the corresponding name is not declared.
341         // If we see an error at not-type:xxx, the corresponding name is not a type.
342         // If we see an error at not-int-const:xxx, the corresponding name is not an integer constant.
343         // If we see an error at not-num-const:xxx, the corresponding name is not a number constant.
344         // If we see an error at not-str-lit:xxx, the corresponding name is not a string literal.
345         //
346         // The specific input forms are chosen so that they are valid C syntax regardless of
347         // whether name denotes a type or an expression.
348
349         var b bytes.Buffer
350         b.WriteString(builtinProlog)
351         b.WriteString(f.Preamble)
352
353         for i, n := range names {
354                 fmt.Fprintf(&b, "#line %d \"not-declared\"\n"+
355                         "void __cgo_f_%d_1(void) { __typeof__(%s) *__cgo_undefined__1; }\n"+
356                         "#line %d \"not-type\"\n"+
357                         "void __cgo_f_%d_2(void) { %s *__cgo_undefined__2; }\n"+
358                         "#line %d \"not-int-const\"\n"+
359                         "void __cgo_f_%d_3(void) { enum { __cgo_undefined__3 = (%s)*1 }; }\n"+
360                         "#line %d \"not-num-const\"\n"+
361                         "void __cgo_f_%d_4(void) { static const double __cgo_undefined__4 = (%s); }\n"+
362                         "#line %d \"not-str-lit\"\n"+
363                         "void __cgo_f_%d_5(void) { static const char __cgo_undefined__5[] = (%s); }\n",
364                         i+1, i+1, n.C,
365                         i+1, i+1, n.C,
366                         i+1, i+1, n.C,
367                         i+1, i+1, n.C,
368                         i+1, i+1, n.C,
369                 )
370         }
371         fmt.Fprintf(&b, "#line 1 \"completed\"\n"+
372                 "int __cgo__1 = __cgo__2;\n")
373
374         // We need to parse the output from this gcc command, so ensure that it
375         // doesn't have any ANSI escape sequences in it. (TERM=dumb is
376         // insufficient; if the user specifies CGO_CFLAGS=-fdiagnostics-color,
377         // GCC will ignore TERM, and GCC can also be configured at compile-time
378         // to ignore TERM.)
379         stderr := p.gccErrors(b.Bytes(), "-fdiagnostics-color=never")
380         if strings.Contains(stderr, "unrecognized command line option") {
381                 // We're using an old version of GCC that doesn't understand
382                 // -fdiagnostics-color. Those versions can't print color anyway,
383                 // so just rerun without that option.
384                 stderr = p.gccErrors(b.Bytes())
385         }
386         if stderr == "" {
387                 fatalf("%s produced no output\non input:\n%s", gccBaseCmd[0], b.Bytes())
388         }
389
390         completed := false
391         sniff := make([]int, len(names))
392         const (
393                 notType = 1 << iota
394                 notIntConst
395                 notNumConst
396                 notStrLiteral
397                 notDeclared
398         )
399         sawUnmatchedErrors := false
400         for _, line := range strings.Split(stderr, "\n") {
401                 // Ignore warnings and random comments, with one
402                 // exception: newer GCC versions will sometimes emit
403                 // an error on a macro #define with a note referring
404                 // to where the expansion occurs. We care about where
405                 // the expansion occurs, so in that case treat the note
406                 // as an error.
407                 isError := strings.Contains(line, ": error:")
408                 isErrorNote := strings.Contains(line, ": note:") && sawUnmatchedErrors
409                 if !isError && !isErrorNote {
410                         continue
411                 }
412
413                 c1 := strings.Index(line, ":")
414                 if c1 < 0 {
415                         continue
416                 }
417                 c2 := strings.Index(line[c1+1:], ":")
418                 if c2 < 0 {
419                         continue
420                 }
421                 c2 += c1 + 1
422
423                 filename := line[:c1]
424                 i, _ := strconv.Atoi(line[c1+1 : c2])
425                 i--
426                 if i < 0 || i >= len(names) {
427                         if isError {
428                                 sawUnmatchedErrors = true
429                         }
430                         continue
431                 }
432
433                 switch filename {
434                 case "completed":
435                         // Strictly speaking, there is no guarantee that seeing the error at completed:1
436                         // (at the end of the file) means we've seen all the errors from earlier in the file,
437                         // but usually it does. Certainly if we don't see the completed:1 error, we did
438                         // not get all the errors we expected.
439                         completed = true
440
441                 case "not-declared":
442                         sniff[i] |= notDeclared
443                 case "not-type":
444                         sniff[i] |= notType
445                 case "not-int-const":
446                         sniff[i] |= notIntConst
447                 case "not-num-const":
448                         sniff[i] |= notNumConst
449                 case "not-str-lit":
450                         sniff[i] |= notStrLiteral
451                 default:
452                         if isError {
453                                 sawUnmatchedErrors = true
454                         }
455                         continue
456                 }
457
458                 sawUnmatchedErrors = false
459         }
460
461         if !completed {
462                 fatalf("%s did not produce error at completed:1\non input:\n%s\nfull error output:\n%s", gccBaseCmd[0], b.Bytes(), stderr)
463         }
464
465         for i, n := range names {
466                 switch sniff[i] {
467                 default:
468                         if sniff[i]&notDeclared != 0 && optional[n] {
469                                 // Ignore optional undeclared identifiers.
470                                 // Don't report an error, and skip adding n to the needType array.
471                                 continue
472                         }
473                         error_(f.NamePos[n], "could not determine kind of name for C.%s", fixGo(n.Go))
474                 case notStrLiteral | notType:
475                         n.Kind = "iconst"
476                 case notIntConst | notStrLiteral | notType:
477                         n.Kind = "fconst"
478                 case notIntConst | notNumConst | notType:
479                         n.Kind = "sconst"
480                 case notIntConst | notNumConst | notStrLiteral:
481                         n.Kind = "type"
482                 case notIntConst | notNumConst | notStrLiteral | notType:
483                         n.Kind = "not-type"
484                 }
485                 needType = append(needType, n)
486         }
487         if nerrors > 0 {
488                 // Check if compiling the preamble by itself causes any errors,
489                 // because the messages we've printed out so far aren't helpful
490                 // to users debugging preamble mistakes. See issue 8442.
491                 preambleErrors := p.gccErrors([]byte(builtinProlog + f.Preamble))
492                 if len(preambleErrors) > 0 {
493                         error_(token.NoPos, "\n%s errors for preamble:\n%s", gccBaseCmd[0], preambleErrors)
494                 }
495
496                 fatalf("unresolved names")
497         }
498
499         return needType
500 }
501
502 // loadDWARF parses the DWARF debug information generated
503 // by gcc to learn the details of the constants, variables, and types
504 // being referred to as C.xxx.
505 func (p *Package) loadDWARF(f *File, conv *typeConv, names []*Name) {
506         // Extract the types from the DWARF section of an object
507         // from a well-formed C program. Gcc only generates DWARF info
508         // for symbols in the object file, so it is not enough to print the
509         // preamble and hope the symbols we care about will be there.
510         // Instead, emit
511         //      __typeof__(names[i]) *__cgo__i;
512         // for each entry in names and then dereference the type we
513         // learn for __cgo__i.
514         var b bytes.Buffer
515         b.WriteString(builtinProlog)
516         b.WriteString(f.Preamble)
517         b.WriteString("#line 1 \"cgo-dwarf-inference\"\n")
518         for i, n := range names {
519                 fmt.Fprintf(&b, "__typeof__(%s) *__cgo__%d;\n", n.C, i)
520                 if n.Kind == "iconst" {
521                         fmt.Fprintf(&b, "enum { __cgo_enum__%d = %s };\n", i, n.C)
522                 }
523         }
524
525         // We create a data block initialized with the values,
526         // so we can read them out of the object file.
527         fmt.Fprintf(&b, "long long __cgodebug_ints[] = {\n")
528         for _, n := range names {
529                 if n.Kind == "iconst" {
530                         fmt.Fprintf(&b, "\t%s,\n", n.C)
531                 } else {
532                         fmt.Fprintf(&b, "\t0,\n")
533                 }
534         }
535         // for the last entry, we cannot use 0, otherwise
536         // in case all __cgodebug_data is zero initialized,
537         // LLVM-based gcc will place the it in the __DATA.__common
538         // zero-filled section (our debug/macho doesn't support
539         // this)
540         fmt.Fprintf(&b, "\t1\n")
541         fmt.Fprintf(&b, "};\n")
542
543         // do the same work for floats.
544         fmt.Fprintf(&b, "double __cgodebug_floats[] = {\n")
545         for _, n := range names {
546                 if n.Kind == "fconst" {
547                         fmt.Fprintf(&b, "\t%s,\n", n.C)
548                 } else {
549                         fmt.Fprintf(&b, "\t0,\n")
550                 }
551         }
552         fmt.Fprintf(&b, "\t1\n")
553         fmt.Fprintf(&b, "};\n")
554
555         // do the same work for strings.
556         for i, n := range names {
557                 if n.Kind == "sconst" {
558                         fmt.Fprintf(&b, "const char __cgodebug_str__%d[] = %s;\n", i, n.C)
559                         fmt.Fprintf(&b, "const unsigned long long __cgodebug_strlen__%d = sizeof(%s)-1;\n", i, n.C)
560                 }
561         }
562
563         d, ints, floats, strs := p.gccDebug(b.Bytes(), len(names))
564
565         // Scan DWARF info for top-level TagVariable entries with AttrName __cgo__i.
566         types := make([]dwarf.Type, len(names))
567         r := d.Reader()
568         for {
569                 e, err := r.Next()
570                 if err != nil {
571                         fatalf("reading DWARF entry: %s", err)
572                 }
573                 if e == nil {
574                         break
575                 }
576                 switch e.Tag {
577                 case dwarf.TagVariable:
578                         name, _ := e.Val(dwarf.AttrName).(string)
579                         // As of https://reviews.llvm.org/D123534, clang
580                         // now emits DW_TAG_variable DIEs that have
581                         // no name (so as to be able to describe the
582                         // type and source locations of constant strings
583                         // like the second arg in the call below:
584                         //
585                         //     myfunction(42, "foo")
586                         //
587                         // If a var has no name we won't see attempts to
588                         // refer to it via "C.<name>", so skip these vars
589                         //
590                         // See issue 53000 for more context.
591                         if name == "" {
592                                 break
593                         }
594                         typOff, _ := e.Val(dwarf.AttrType).(dwarf.Offset)
595                         if typOff == 0 {
596                                 if e.Val(dwarf.AttrSpecification) != nil {
597                                         // Since we are reading all the DWARF,
598                                         // assume we will see the variable elsewhere.
599                                         break
600                                 }
601                                 fatalf("malformed DWARF TagVariable entry")
602                         }
603                         if !strings.HasPrefix(name, "__cgo__") {
604                                 break
605                         }
606                         typ, err := d.Type(typOff)
607                         if err != nil {
608                                 fatalf("loading DWARF type: %s", err)
609                         }
610                         t, ok := typ.(*dwarf.PtrType)
611                         if !ok || t == nil {
612                                 fatalf("internal error: %s has non-pointer type", name)
613                         }
614                         i, err := strconv.Atoi(name[7:])
615                         if err != nil {
616                                 fatalf("malformed __cgo__ name: %s", name)
617                         }
618                         types[i] = t.Type
619                         p.recordTypedefs(t.Type, f.NamePos[names[i]])
620                 }
621                 if e.Tag != dwarf.TagCompileUnit {
622                         r.SkipChildren()
623                 }
624         }
625
626         // Record types and typedef information.
627         for i, n := range names {
628                 if strings.HasSuffix(n.Go, "GetTypeID") && types[i].String() == "func() CFTypeID" {
629                         conv.getTypeIDs[n.Go[:len(n.Go)-9]] = true
630                 }
631         }
632         for i, n := range names {
633                 if types[i] == nil {
634                         continue
635                 }
636                 pos := f.NamePos[n]
637                 f, fok := types[i].(*dwarf.FuncType)
638                 if n.Kind != "type" && fok {
639                         n.Kind = "func"
640                         n.FuncType = conv.FuncType(f, pos)
641                 } else {
642                         n.Type = conv.Type(types[i], pos)
643                         switch n.Kind {
644                         case "iconst":
645                                 if i < len(ints) {
646                                         if _, ok := types[i].(*dwarf.UintType); ok {
647                                                 n.Const = fmt.Sprintf("%#x", uint64(ints[i]))
648                                         } else {
649                                                 n.Const = fmt.Sprintf("%#x", ints[i])
650                                         }
651                                 }
652                         case "fconst":
653                                 if i >= len(floats) {
654                                         break
655                                 }
656                                 switch base(types[i]).(type) {
657                                 case *dwarf.IntType, *dwarf.UintType:
658                                         // This has an integer type so it's
659                                         // not really a floating point
660                                         // constant. This can happen when the
661                                         // C compiler complains about using
662                                         // the value as an integer constant,
663                                         // but not as a general constant.
664                                         // Treat this as a variable of the
665                                         // appropriate type, not a constant,
666                                         // to get C-style type handling,
667                                         // avoiding the problem that C permits
668                                         // uint64(-1) but Go does not.
669                                         // See issue 26066.
670                                         n.Kind = "var"
671                                 default:
672                                         n.Const = fmt.Sprintf("%f", floats[i])
673                                 }
674                         case "sconst":
675                                 if i < len(strs) {
676                                         n.Const = fmt.Sprintf("%q", strs[i])
677                                 }
678                         }
679                 }
680                 conv.FinishType(pos)
681         }
682 }
683
684 // recordTypedefs remembers in p.typedefs all the typedefs used in dtypes and its children.
685 func (p *Package) recordTypedefs(dtype dwarf.Type, pos token.Pos) {
686         p.recordTypedefs1(dtype, pos, map[dwarf.Type]bool{})
687 }
688
689 func (p *Package) recordTypedefs1(dtype dwarf.Type, pos token.Pos, visited map[dwarf.Type]bool) {
690         if dtype == nil {
691                 return
692         }
693         if visited[dtype] {
694                 return
695         }
696         visited[dtype] = true
697         switch dt := dtype.(type) {
698         case *dwarf.TypedefType:
699                 if strings.HasPrefix(dt.Name, "__builtin") {
700                         // Don't look inside builtin types. There be dragons.
701                         return
702                 }
703                 if !p.typedefs[dt.Name] {
704                         p.typedefs[dt.Name] = true
705                         p.typedefList = append(p.typedefList, typedefInfo{dt.Name, pos})
706                         p.recordTypedefs1(dt.Type, pos, visited)
707                 }
708         case *dwarf.PtrType:
709                 p.recordTypedefs1(dt.Type, pos, visited)
710         case *dwarf.ArrayType:
711                 p.recordTypedefs1(dt.Type, pos, visited)
712         case *dwarf.QualType:
713                 p.recordTypedefs1(dt.Type, pos, visited)
714         case *dwarf.FuncType:
715                 p.recordTypedefs1(dt.ReturnType, pos, visited)
716                 for _, a := range dt.ParamType {
717                         p.recordTypedefs1(a, pos, visited)
718                 }
719         case *dwarf.StructType:
720                 for _, f := range dt.Field {
721                         p.recordTypedefs1(f.Type, pos, visited)
722                 }
723         }
724 }
725
726 // prepareNames finalizes the Kind field of not-type names and sets
727 // the mangled name of all names.
728 func (p *Package) prepareNames(f *File) {
729         for _, n := range f.Name {
730                 if n.Kind == "not-type" {
731                         if n.Define == "" {
732                                 n.Kind = "var"
733                         } else {
734                                 n.Kind = "macro"
735                                 n.FuncType = &FuncType{
736                                         Result: n.Type,
737                                         Go: &ast.FuncType{
738                                                 Results: &ast.FieldList{List: []*ast.Field{{Type: n.Type.Go}}},
739                                         },
740                                 }
741                         }
742                 }
743                 p.mangleName(n)
744                 if n.Kind == "type" && typedef[n.Mangle] == nil {
745                         typedef[n.Mangle] = n.Type
746                 }
747         }
748 }
749
750 // mangleName does name mangling to translate names
751 // from the original Go source files to the names
752 // used in the final Go files generated by cgo.
753 func (p *Package) mangleName(n *Name) {
754         // When using gccgo variables have to be
755         // exported so that they become global symbols
756         // that the C code can refer to.
757         prefix := "_C"
758         if *gccgo && n.IsVar() {
759                 prefix = "C"
760         }
761         n.Mangle = prefix + n.Kind + "_" + n.Go
762 }
763
764 func (f *File) isMangledName(s string) bool {
765         prefix := "_C"
766         if strings.HasPrefix(s, prefix) {
767                 t := s[len(prefix):]
768                 for _, k := range nameKinds {
769                         if strings.HasPrefix(t, k+"_") {
770                                 return true
771                         }
772                 }
773         }
774         return false
775 }
776
777 // rewriteCalls rewrites all calls that pass pointers to check that
778 // they follow the rules for passing pointers between Go and C.
779 // This reports whether the package needs to import unsafe as _cgo_unsafe.
780 func (p *Package) rewriteCalls(f *File) bool {
781         needsUnsafe := false
782         // Walk backward so that in C.f1(C.f2()) we rewrite C.f2 first.
783         for _, call := range f.Calls {
784                 if call.Done {
785                         continue
786                 }
787                 start := f.offset(call.Call.Pos())
788                 end := f.offset(call.Call.End())
789                 str, nu := p.rewriteCall(f, call)
790                 if str != "" {
791                         f.Edit.Replace(start, end, str)
792                         if nu {
793                                 needsUnsafe = true
794                         }
795                 }
796         }
797         return needsUnsafe
798 }
799
800 // rewriteCall rewrites one call to add pointer checks.
801 // If any pointer checks are required, we rewrite the call into a
802 // function literal that calls _cgoCheckPointer for each pointer
803 // argument and then calls the original function.
804 // This returns the rewritten call and whether the package needs to
805 // import unsafe as _cgo_unsafe.
806 // If it returns the empty string, the call did not need to be rewritten.
807 func (p *Package) rewriteCall(f *File, call *Call) (string, bool) {
808         // This is a call to C.xxx; set goname to "xxx".
809         // It may have already been mangled by rewriteName.
810         var goname string
811         switch fun := call.Call.Fun.(type) {
812         case *ast.SelectorExpr:
813                 goname = fun.Sel.Name
814         case *ast.Ident:
815                 goname = strings.TrimPrefix(fun.Name, "_C2func_")
816                 goname = strings.TrimPrefix(goname, "_Cfunc_")
817         }
818         if goname == "" || goname == "malloc" {
819                 return "", false
820         }
821         name := f.Name[goname]
822         if name == nil || name.Kind != "func" {
823                 // Probably a type conversion.
824                 return "", false
825         }
826
827         params := name.FuncType.Params
828         args := call.Call.Args
829         end := call.Call.End()
830
831         // Avoid a crash if the number of arguments doesn't match
832         // the number of parameters.
833         // This will be caught when the generated file is compiled.
834         if len(args) != len(params) {
835                 return "", false
836         }
837
838         any := false
839         for i, param := range params {
840                 if p.needsPointerCheck(f, param.Go, args[i]) {
841                         any = true
842                         break
843                 }
844         }
845         if !any {
846                 return "", false
847         }
848
849         // We need to rewrite this call.
850         //
851         // Rewrite C.f(p) to
852         //    func() {
853         //            _cgo0 := p
854         //            _cgoCheckPointer(_cgo0, nil)
855         //            C.f(_cgo0)
856         //    }()
857         // Using a function literal like this lets us evaluate the
858         // function arguments only once while doing pointer checks.
859         // This is particularly useful when passing additional arguments
860         // to _cgoCheckPointer, as done in checkIndex and checkAddr.
861         //
862         // When the function argument is a conversion to unsafe.Pointer,
863         // we unwrap the conversion before checking the pointer,
864         // and then wrap again when calling C.f. This lets us check
865         // the real type of the pointer in some cases. See issue #25941.
866         //
867         // When the call to C.f is deferred, we use an additional function
868         // literal to evaluate the arguments at the right time.
869         //    defer func() func() {
870         //            _cgo0 := p
871         //            return func() {
872         //                    _cgoCheckPointer(_cgo0, nil)
873         //                    C.f(_cgo0)
874         //            }
875         //    }()()
876         // This works because the defer statement evaluates the first
877         // function literal in order to get the function to call.
878
879         var sb bytes.Buffer
880         sb.WriteString("func() ")
881         if call.Deferred {
882                 sb.WriteString("func() ")
883         }
884
885         needsUnsafe := false
886         result := false
887         twoResults := false
888         if !call.Deferred {
889                 // Check whether this call expects two results.
890                 for _, ref := range f.Ref {
891                         if ref.Expr != &call.Call.Fun {
892                                 continue
893                         }
894                         if ref.Context == ctxCall2 {
895                                 sb.WriteString("(")
896                                 result = true
897                                 twoResults = true
898                         }
899                         break
900                 }
901
902                 // Add the result type, if any.
903                 if name.FuncType.Result != nil {
904                         rtype := p.rewriteUnsafe(name.FuncType.Result.Go)
905                         if rtype != name.FuncType.Result.Go {
906                                 needsUnsafe = true
907                         }
908                         sb.WriteString(gofmtLine(rtype))
909                         result = true
910                 }
911
912                 // Add the second result type, if any.
913                 if twoResults {
914                         if name.FuncType.Result == nil {
915                                 // An explicit void result looks odd but it
916                                 // seems to be how cgo has worked historically.
917                                 sb.WriteString("_Ctype_void")
918                         }
919                         sb.WriteString(", error)")
920                 }
921         }
922
923         sb.WriteString("{ ")
924
925         // Define _cgoN for each argument value.
926         // Write _cgoCheckPointer calls to sbCheck.
927         var sbCheck bytes.Buffer
928         for i, param := range params {
929                 origArg := args[i]
930                 arg, nu := p.mangle(f, &args[i], true)
931                 if nu {
932                         needsUnsafe = true
933                 }
934
935                 // Use "var x T = ..." syntax to explicitly convert untyped
936                 // constants to the parameter type, to avoid a type mismatch.
937                 ptype := p.rewriteUnsafe(param.Go)
938
939                 if !p.needsPointerCheck(f, param.Go, args[i]) || param.BadPointer {
940                         if ptype != param.Go {
941                                 needsUnsafe = true
942                         }
943                         fmt.Fprintf(&sb, "var _cgo%d %s = %s; ", i,
944                                 gofmtLine(ptype), gofmtPos(arg, origArg.Pos()))
945                         continue
946                 }
947
948                 // Check for &a[i].
949                 if p.checkIndex(&sb, &sbCheck, arg, i) {
950                         continue
951                 }
952
953                 // Check for &x.
954                 if p.checkAddr(&sb, &sbCheck, arg, i) {
955                         continue
956                 }
957
958                 fmt.Fprintf(&sb, "_cgo%d := %s; ", i, gofmtPos(arg, origArg.Pos()))
959                 fmt.Fprintf(&sbCheck, "_cgoCheckPointer(_cgo%d, nil); ", i)
960         }
961
962         if call.Deferred {
963                 sb.WriteString("return func() { ")
964         }
965
966         // Write out the calls to _cgoCheckPointer.
967         sb.WriteString(sbCheck.String())
968
969         if result {
970                 sb.WriteString("return ")
971         }
972
973         m, nu := p.mangle(f, &call.Call.Fun, false)
974         if nu {
975                 needsUnsafe = true
976         }
977         sb.WriteString(gofmtPos(m, end))
978
979         sb.WriteString("(")
980         for i := range params {
981                 if i > 0 {
982                         sb.WriteString(", ")
983                 }
984                 fmt.Fprintf(&sb, "_cgo%d", i)
985         }
986         sb.WriteString("); ")
987         if call.Deferred {
988                 sb.WriteString("}")
989         }
990         sb.WriteString("}")
991         if call.Deferred {
992                 sb.WriteString("()")
993         }
994         sb.WriteString("()")
995
996         return sb.String(), needsUnsafe
997 }
998
999 // needsPointerCheck reports whether the type t needs a pointer check.
1000 // This is true if t is a pointer and if the value to which it points
1001 // might contain a pointer.
1002 func (p *Package) needsPointerCheck(f *File, t ast.Expr, arg ast.Expr) bool {
1003         // An untyped nil does not need a pointer check, and when
1004         // _cgoCheckPointer returns the untyped nil the type assertion we
1005         // are going to insert will fail.  Easier to just skip nil arguments.
1006         // TODO: Note that this fails if nil is shadowed.
1007         if id, ok := arg.(*ast.Ident); ok && id.Name == "nil" {
1008                 return false
1009         }
1010
1011         return p.hasPointer(f, t, true)
1012 }
1013
1014 // hasPointer is used by needsPointerCheck. If top is true it returns
1015 // whether t is or contains a pointer that might point to a pointer.
1016 // If top is false it reports whether t is or contains a pointer.
1017 // f may be nil.
1018 func (p *Package) hasPointer(f *File, t ast.Expr, top bool) bool {
1019         switch t := t.(type) {
1020         case *ast.ArrayType:
1021                 if t.Len == nil {
1022                         if !top {
1023                                 return true
1024                         }
1025                         return p.hasPointer(f, t.Elt, false)
1026                 }
1027                 return p.hasPointer(f, t.Elt, top)
1028         case *ast.StructType:
1029                 for _, field := range t.Fields.List {
1030                         if p.hasPointer(f, field.Type, top) {
1031                                 return true
1032                         }
1033                 }
1034                 return false
1035         case *ast.StarExpr: // Pointer type.
1036                 if !top {
1037                         return true
1038                 }
1039                 // Check whether this is a pointer to a C union (or class)
1040                 // type that contains a pointer.
1041                 if unionWithPointer[t.X] {
1042                         return true
1043                 }
1044                 return p.hasPointer(f, t.X, false)
1045         case *ast.FuncType, *ast.InterfaceType, *ast.MapType, *ast.ChanType:
1046                 return true
1047         case *ast.Ident:
1048                 // TODO: Handle types defined within function.
1049                 for _, d := range p.Decl {
1050                         gd, ok := d.(*ast.GenDecl)
1051                         if !ok || gd.Tok != token.TYPE {
1052                                 continue
1053                         }
1054                         for _, spec := range gd.Specs {
1055                                 ts, ok := spec.(*ast.TypeSpec)
1056                                 if !ok {
1057                                         continue
1058                                 }
1059                                 if ts.Name.Name == t.Name {
1060                                         return p.hasPointer(f, ts.Type, top)
1061                                 }
1062                         }
1063                 }
1064                 if def := typedef[t.Name]; def != nil {
1065                         return p.hasPointer(f, def.Go, top)
1066                 }
1067                 if t.Name == "string" {
1068                         return !top
1069                 }
1070                 if t.Name == "error" {
1071                         return true
1072                 }
1073                 if goTypes[t.Name] != nil {
1074                         return false
1075                 }
1076                 // We can't figure out the type. Conservative
1077                 // approach is to assume it has a pointer.
1078                 return true
1079         case *ast.SelectorExpr:
1080                 if l, ok := t.X.(*ast.Ident); !ok || l.Name != "C" {
1081                         // Type defined in a different package.
1082                         // Conservative approach is to assume it has a
1083                         // pointer.
1084                         return true
1085                 }
1086                 if f == nil {
1087                         // Conservative approach: assume pointer.
1088                         return true
1089                 }
1090                 name := f.Name[t.Sel.Name]
1091                 if name != nil && name.Kind == "type" && name.Type != nil && name.Type.Go != nil {
1092                         return p.hasPointer(f, name.Type.Go, top)
1093                 }
1094                 // We can't figure out the type. Conservative
1095                 // approach is to assume it has a pointer.
1096                 return true
1097         default:
1098                 error_(t.Pos(), "could not understand type %s", gofmt(t))
1099                 return true
1100         }
1101 }
1102
1103 // mangle replaces references to C names in arg with the mangled names,
1104 // rewriting calls when it finds them.
1105 // It removes the corresponding references in f.Ref and f.Calls, so that we
1106 // don't try to do the replacement again in rewriteRef or rewriteCall.
1107 // If addPosition is true, add position info to the idents of C names in arg.
1108 func (p *Package) mangle(f *File, arg *ast.Expr, addPosition bool) (ast.Expr, bool) {
1109         needsUnsafe := false
1110         f.walk(arg, ctxExpr, func(f *File, arg interface{}, context astContext) {
1111                 px, ok := arg.(*ast.Expr)
1112                 if !ok {
1113                         return
1114                 }
1115                 sel, ok := (*px).(*ast.SelectorExpr)
1116                 if ok {
1117                         if l, ok := sel.X.(*ast.Ident); !ok || l.Name != "C" {
1118                                 return
1119                         }
1120
1121                         for _, r := range f.Ref {
1122                                 if r.Expr == px {
1123                                         *px = p.rewriteName(f, r, addPosition)
1124                                         r.Done = true
1125                                         break
1126                                 }
1127                         }
1128
1129                         return
1130                 }
1131
1132                 call, ok := (*px).(*ast.CallExpr)
1133                 if !ok {
1134                         return
1135                 }
1136
1137                 for _, c := range f.Calls {
1138                         if !c.Done && c.Call.Lparen == call.Lparen {
1139                                 cstr, nu := p.rewriteCall(f, c)
1140                                 if cstr != "" {
1141                                         // Smuggle the rewritten call through an ident.
1142                                         *px = ast.NewIdent(cstr)
1143                                         if nu {
1144                                                 needsUnsafe = true
1145                                         }
1146                                         c.Done = true
1147                                 }
1148                         }
1149                 }
1150         })
1151         return *arg, needsUnsafe
1152 }
1153
1154 // checkIndex checks whether arg has the form &a[i], possibly inside
1155 // type conversions. If so, then in the general case it writes
1156 //
1157 //      _cgoIndexNN := a
1158 //      _cgoNN := &cgoIndexNN[i] // with type conversions, if any
1159 //
1160 // to sb, and writes
1161 //
1162 //      _cgoCheckPointer(_cgoNN, _cgoIndexNN)
1163 //
1164 // to sbCheck, and returns true. If a is a simple variable or field reference,
1165 // it writes
1166 //
1167 //      _cgoIndexNN := &a
1168 //
1169 // and dereferences the uses of _cgoIndexNN. Taking the address avoids
1170 // making a copy of an array.
1171 //
1172 // This tells _cgoCheckPointer to check the complete contents of the
1173 // slice or array being indexed, but no other part of the memory allocation.
1174 func (p *Package) checkIndex(sb, sbCheck *bytes.Buffer, arg ast.Expr, i int) bool {
1175         // Strip type conversions.
1176         x := arg
1177         for {
1178                 c, ok := x.(*ast.CallExpr)
1179                 if !ok || len(c.Args) != 1 || !p.isType(c.Fun) {
1180                         break
1181                 }
1182                 x = c.Args[0]
1183         }
1184         u, ok := x.(*ast.UnaryExpr)
1185         if !ok || u.Op != token.AND {
1186                 return false
1187         }
1188         index, ok := u.X.(*ast.IndexExpr)
1189         if !ok {
1190                 return false
1191         }
1192
1193         addr := ""
1194         deref := ""
1195         if p.isVariable(index.X) {
1196                 addr = "&"
1197                 deref = "*"
1198         }
1199
1200         fmt.Fprintf(sb, "_cgoIndex%d := %s%s; ", i, addr, gofmtPos(index.X, index.X.Pos()))
1201         origX := index.X
1202         index.X = ast.NewIdent(fmt.Sprintf("_cgoIndex%d", i))
1203         if deref == "*" {
1204                 index.X = &ast.StarExpr{X: index.X}
1205         }
1206         fmt.Fprintf(sb, "_cgo%d := %s; ", i, gofmtPos(arg, arg.Pos()))
1207         index.X = origX
1208
1209         fmt.Fprintf(sbCheck, "_cgoCheckPointer(_cgo%d, %s_cgoIndex%d); ", i, deref, i)
1210
1211         return true
1212 }
1213
1214 // checkAddr checks whether arg has the form &x, possibly inside type
1215 // conversions. If so, it writes
1216 //
1217 //      _cgoBaseNN := &x
1218 //      _cgoNN := _cgoBaseNN // with type conversions, if any
1219 //
1220 // to sb, and writes
1221 //
1222 //      _cgoCheckPointer(_cgoBaseNN, true)
1223 //
1224 // to sbCheck, and returns true. This tells _cgoCheckPointer to check
1225 // just the contents of the pointer being passed, not any other part
1226 // of the memory allocation. This is run after checkIndex, which looks
1227 // for the special case of &a[i], which requires different checks.
1228 func (p *Package) checkAddr(sb, sbCheck *bytes.Buffer, arg ast.Expr, i int) bool {
1229         // Strip type conversions.
1230         px := &arg
1231         for {
1232                 c, ok := (*px).(*ast.CallExpr)
1233                 if !ok || len(c.Args) != 1 || !p.isType(c.Fun) {
1234                         break
1235                 }
1236                 px = &c.Args[0]
1237         }
1238         if u, ok := (*px).(*ast.UnaryExpr); !ok || u.Op != token.AND {
1239                 return false
1240         }
1241
1242         fmt.Fprintf(sb, "_cgoBase%d := %s; ", i, gofmtPos(*px, (*px).Pos()))
1243
1244         origX := *px
1245         *px = ast.NewIdent(fmt.Sprintf("_cgoBase%d", i))
1246         fmt.Fprintf(sb, "_cgo%d := %s; ", i, gofmtPos(arg, arg.Pos()))
1247         *px = origX
1248
1249         // Use "0 == 0" to do the right thing in the unlikely event
1250         // that "true" is shadowed.
1251         fmt.Fprintf(sbCheck, "_cgoCheckPointer(_cgoBase%d, 0 == 0); ", i)
1252
1253         return true
1254 }
1255
1256 // isType reports whether the expression is definitely a type.
1257 // This is conservative--it returns false for an unknown identifier.
1258 func (p *Package) isType(t ast.Expr) bool {
1259         switch t := t.(type) {
1260         case *ast.SelectorExpr:
1261                 id, ok := t.X.(*ast.Ident)
1262                 if !ok {
1263                         return false
1264                 }
1265                 if id.Name == "unsafe" && t.Sel.Name == "Pointer" {
1266                         return true
1267                 }
1268                 if id.Name == "C" && typedef["_Ctype_"+t.Sel.Name] != nil {
1269                         return true
1270                 }
1271                 return false
1272         case *ast.Ident:
1273                 // TODO: This ignores shadowing.
1274                 switch t.Name {
1275                 case "unsafe.Pointer", "bool", "byte",
1276                         "complex64", "complex128",
1277                         "error",
1278                         "float32", "float64",
1279                         "int", "int8", "int16", "int32", "int64",
1280                         "rune", "string",
1281                         "uint", "uint8", "uint16", "uint32", "uint64", "uintptr":
1282
1283                         return true
1284                 }
1285                 if strings.HasPrefix(t.Name, "_Ctype_") {
1286                         return true
1287                 }
1288         case *ast.ParenExpr:
1289                 return p.isType(t.X)
1290         case *ast.StarExpr:
1291                 return p.isType(t.X)
1292         case *ast.ArrayType, *ast.StructType, *ast.FuncType, *ast.InterfaceType,
1293                 *ast.MapType, *ast.ChanType:
1294
1295                 return true
1296         }
1297         return false
1298 }
1299
1300 // isVariable reports whether x is a variable, possibly with field references.
1301 func (p *Package) isVariable(x ast.Expr) bool {
1302         switch x := x.(type) {
1303         case *ast.Ident:
1304                 return true
1305         case *ast.SelectorExpr:
1306                 return p.isVariable(x.X)
1307         case *ast.IndexExpr:
1308                 return true
1309         }
1310         return false
1311 }
1312
1313 // rewriteUnsafe returns a version of t with references to unsafe.Pointer
1314 // rewritten to use _cgo_unsafe.Pointer instead.
1315 func (p *Package) rewriteUnsafe(t ast.Expr) ast.Expr {
1316         switch t := t.(type) {
1317         case *ast.Ident:
1318                 // We don't see a SelectorExpr for unsafe.Pointer;
1319                 // this is created by code in this file.
1320                 if t.Name == "unsafe.Pointer" {
1321                         return ast.NewIdent("_cgo_unsafe.Pointer")
1322                 }
1323         case *ast.ArrayType:
1324                 t1 := p.rewriteUnsafe(t.Elt)
1325                 if t1 != t.Elt {
1326                         r := *t
1327                         r.Elt = t1
1328                         return &r
1329                 }
1330         case *ast.StructType:
1331                 changed := false
1332                 fields := *t.Fields
1333                 fields.List = nil
1334                 for _, f := range t.Fields.List {
1335                         ft := p.rewriteUnsafe(f.Type)
1336                         if ft == f.Type {
1337                                 fields.List = append(fields.List, f)
1338                         } else {
1339                                 fn := *f
1340                                 fn.Type = ft
1341                                 fields.List = append(fields.List, &fn)
1342                                 changed = true
1343                         }
1344                 }
1345                 if changed {
1346                         r := *t
1347                         r.Fields = &fields
1348                         return &r
1349                 }
1350         case *ast.StarExpr: // Pointer type.
1351                 x1 := p.rewriteUnsafe(t.X)
1352                 if x1 != t.X {
1353                         r := *t
1354                         r.X = x1
1355                         return &r
1356                 }
1357         }
1358         return t
1359 }
1360
1361 // rewriteRef rewrites all the C.xxx references in f.AST to refer to the
1362 // Go equivalents, now that we have figured out the meaning of all
1363 // the xxx. In *godefs mode, rewriteRef replaces the names
1364 // with full definitions instead of mangled names.
1365 func (p *Package) rewriteRef(f *File) {
1366         // Keep a list of all the functions, to remove the ones
1367         // only used as expressions and avoid generating bridge
1368         // code for them.
1369         functions := make(map[string]bool)
1370
1371         for _, n := range f.Name {
1372                 if n.Kind == "func" {
1373                         functions[n.Go] = false
1374                 }
1375         }
1376
1377         // Now that we have all the name types filled in,
1378         // scan through the Refs to identify the ones that
1379         // are trying to do a ,err call. Also check that
1380         // functions are only used in calls.
1381         for _, r := range f.Ref {
1382                 if r.Name.IsConst() && r.Name.Const == "" {
1383                         error_(r.Pos(), "unable to find value of constant C.%s", fixGo(r.Name.Go))
1384                 }
1385
1386                 if r.Name.Kind == "func" {
1387                         switch r.Context {
1388                         case ctxCall, ctxCall2:
1389                                 functions[r.Name.Go] = true
1390                         }
1391                 }
1392
1393                 expr := p.rewriteName(f, r, false)
1394
1395                 if *godefs {
1396                         // Substitute definition for mangled type name.
1397                         if r.Name.Type != nil && r.Name.Kind == "type" {
1398                                 expr = r.Name.Type.Go
1399                         }
1400                         if id, ok := expr.(*ast.Ident); ok {
1401                                 if t := typedef[id.Name]; t != nil {
1402                                         expr = t.Go
1403                                 }
1404                                 if id.Name == r.Name.Mangle && r.Name.Const != "" {
1405                                         expr = ast.NewIdent(r.Name.Const)
1406                                 }
1407                         }
1408                 }
1409
1410                 // Copy position information from old expr into new expr,
1411                 // in case expression being replaced is first on line.
1412                 // See golang.org/issue/6563.
1413                 pos := (*r.Expr).Pos()
1414                 if x, ok := expr.(*ast.Ident); ok {
1415                         expr = &ast.Ident{NamePos: pos, Name: x.Name}
1416                 }
1417
1418                 // Change AST, because some later processing depends on it,
1419                 // and also because -godefs mode still prints the AST.
1420                 old := *r.Expr
1421                 *r.Expr = expr
1422
1423                 // Record source-level edit for cgo output.
1424                 if !r.Done {
1425                         // Prepend a space in case the earlier code ends
1426                         // with '/', which would give us a "//" comment.
1427                         repl := " " + gofmtPos(expr, old.Pos())
1428                         end := fset.Position(old.End())
1429                         // Subtract 1 from the column if we are going to
1430                         // append a close parenthesis. That will set the
1431                         // correct column for the following characters.
1432                         sub := 0
1433                         if r.Name.Kind != "type" {
1434                                 sub = 1
1435                         }
1436                         if end.Column > sub {
1437                                 repl = fmt.Sprintf("%s /*line :%d:%d*/", repl, end.Line, end.Column-sub)
1438                         }
1439                         if r.Name.Kind != "type" {
1440                                 repl = "(" + repl + ")"
1441                         }
1442                         f.Edit.Replace(f.offset(old.Pos()), f.offset(old.End()), repl)
1443                 }
1444         }
1445
1446         // Remove functions only used as expressions, so their respective
1447         // bridge functions are not generated.
1448         for name, used := range functions {
1449                 if !used {
1450                         delete(f.Name, name)
1451                 }
1452         }
1453 }
1454
1455 // rewriteName returns the expression used to rewrite a reference.
1456 // If addPosition is true, add position info in the ident name.
1457 func (p *Package) rewriteName(f *File, r *Ref, addPosition bool) ast.Expr {
1458         getNewIdent := ast.NewIdent
1459         if addPosition {
1460                 getNewIdent = func(newName string) *ast.Ident {
1461                         mangledIdent := ast.NewIdent(newName)
1462                         if len(newName) == len(r.Name.Go) {
1463                                 return mangledIdent
1464                         }
1465                         p := fset.Position((*r.Expr).End())
1466                         if p.Column == 0 {
1467                                 return mangledIdent
1468                         }
1469                         return ast.NewIdent(fmt.Sprintf("%s /*line :%d:%d*/", newName, p.Line, p.Column))
1470                 }
1471         }
1472         var expr ast.Expr = getNewIdent(r.Name.Mangle) // default
1473         switch r.Context {
1474         case ctxCall, ctxCall2:
1475                 if r.Name.Kind != "func" {
1476                         if r.Name.Kind == "type" {
1477                                 r.Context = ctxType
1478                                 if r.Name.Type == nil {
1479                                         error_(r.Pos(), "invalid conversion to C.%s: undefined C type '%s'", fixGo(r.Name.Go), r.Name.C)
1480                                 }
1481                                 break
1482                         }
1483                         error_(r.Pos(), "call of non-function C.%s", fixGo(r.Name.Go))
1484                         break
1485                 }
1486                 if r.Context == ctxCall2 {
1487                         if r.Name.Go == "_CMalloc" {
1488                                 error_(r.Pos(), "no two-result form for C.malloc")
1489                                 break
1490                         }
1491                         // Invent new Name for the two-result function.
1492                         n := f.Name["2"+r.Name.Go]
1493                         if n == nil {
1494                                 n = new(Name)
1495                                 *n = *r.Name
1496                                 n.AddError = true
1497                                 n.Mangle = "_C2func_" + n.Go
1498                                 f.Name["2"+r.Name.Go] = n
1499                         }
1500                         expr = getNewIdent(n.Mangle)
1501                         r.Name = n
1502                         break
1503                 }
1504         case ctxExpr:
1505                 switch r.Name.Kind {
1506                 case "func":
1507                         if builtinDefs[r.Name.C] != "" {
1508                                 error_(r.Pos(), "use of builtin '%s' not in function call", fixGo(r.Name.C))
1509                         }
1510
1511                         // Function is being used in an expression, to e.g. pass around a C function pointer.
1512                         // Create a new Name for this Ref which causes the variable to be declared in Go land.
1513                         fpName := "fp_" + r.Name.Go
1514                         name := f.Name[fpName]
1515                         if name == nil {
1516                                 name = &Name{
1517                                         Go:   fpName,
1518                                         C:    r.Name.C,
1519                                         Kind: "fpvar",
1520                                         Type: &Type{Size: p.PtrSize, Align: p.PtrSize, C: c("void*"), Go: ast.NewIdent("unsafe.Pointer")},
1521                                 }
1522                                 p.mangleName(name)
1523                                 f.Name[fpName] = name
1524                         }
1525                         r.Name = name
1526                         // Rewrite into call to _Cgo_ptr to prevent assignments. The _Cgo_ptr
1527                         // function is defined in out.go and simply returns its argument. See
1528                         // issue 7757.
1529                         expr = &ast.CallExpr{
1530                                 Fun:  &ast.Ident{NamePos: (*r.Expr).Pos(), Name: "_Cgo_ptr"},
1531                                 Args: []ast.Expr{getNewIdent(name.Mangle)},
1532                         }
1533                 case "type":
1534                         // Okay - might be new(T), T(x), Generic[T], etc.
1535                         if r.Name.Type == nil {
1536                                 error_(r.Pos(), "expression C.%s: undefined C type '%s'", fixGo(r.Name.Go), r.Name.C)
1537                         }
1538                 case "var":
1539                         expr = &ast.StarExpr{Star: (*r.Expr).Pos(), X: expr}
1540                 case "macro":
1541                         expr = &ast.CallExpr{Fun: expr}
1542                 }
1543         case ctxSelector:
1544                 if r.Name.Kind == "var" {
1545                         expr = &ast.StarExpr{Star: (*r.Expr).Pos(), X: expr}
1546                 } else {
1547                         error_(r.Pos(), "only C variables allowed in selector expression %s", fixGo(r.Name.Go))
1548                 }
1549         case ctxType:
1550                 if r.Name.Kind != "type" {
1551                         error_(r.Pos(), "expression C.%s used as type", fixGo(r.Name.Go))
1552                 } else if r.Name.Type == nil {
1553                         // Use of C.enum_x, C.struct_x or C.union_x without C definition.
1554                         // GCC won't raise an error when using pointers to such unknown types.
1555                         error_(r.Pos(), "type C.%s: undefined C type '%s'", fixGo(r.Name.Go), r.Name.C)
1556                 }
1557         default:
1558                 if r.Name.Kind == "func" {
1559                         error_(r.Pos(), "must call C.%s", fixGo(r.Name.Go))
1560                 }
1561         }
1562         return expr
1563 }
1564
1565 // gofmtPos returns the gofmt-formatted string for an AST node,
1566 // with a comment setting the position before the node.
1567 func gofmtPos(n ast.Expr, pos token.Pos) string {
1568         s := gofmtLine(n)
1569         p := fset.Position(pos)
1570         if p.Column == 0 {
1571                 return s
1572         }
1573         return fmt.Sprintf("/*line :%d:%d*/%s", p.Line, p.Column, s)
1574 }
1575
1576 // checkGCCBaseCmd returns the start of the compiler command line.
1577 // It uses $CC if set, or else $GCC, or else the compiler recorded
1578 // during the initial build as defaultCC.
1579 // defaultCC is defined in zdefaultcc.go, written by cmd/dist.
1580 //
1581 // The compiler command line is split into arguments on whitespace. Quotes
1582 // are understood, so arguments may contain whitespace.
1583 //
1584 // checkGCCBaseCmd confirms that the compiler exists in PATH, returning
1585 // an error if it does not.
1586 func checkGCCBaseCmd() ([]string, error) {
1587         // Use $CC if set, since that's what the build uses.
1588         value := os.Getenv("CC")
1589         if value == "" {
1590                 // Try $GCC if set, since that's what we used to use.
1591                 value = os.Getenv("GCC")
1592         }
1593         if value == "" {
1594                 value = defaultCC(goos, goarch)
1595         }
1596         args, err := quoted.Split(value)
1597         if err != nil {
1598                 return nil, err
1599         }
1600         if len(args) == 0 {
1601                 return nil, errors.New("CC not set and no default found")
1602         }
1603         if _, err := exec.LookPath(args[0]); err != nil {
1604                 return nil, fmt.Errorf("C compiler %q not found: %v", args[0], err)
1605         }
1606         return args[:len(args):len(args)], nil
1607 }
1608
1609 // gccMachine returns the gcc -m flag to use, either "-m32", "-m64" or "-marm".
1610 func (p *Package) gccMachine() []string {
1611         switch goarch {
1612         case "amd64":
1613                 if goos == "darwin" {
1614                         return []string{"-arch", "x86_64", "-m64"}
1615                 }
1616                 return []string{"-m64"}
1617         case "arm64":
1618                 if goos == "darwin" {
1619                         return []string{"-arch", "arm64"}
1620                 }
1621         case "386":
1622                 return []string{"-m32"}
1623         case "arm":
1624                 return []string{"-marm"} // not thumb
1625         case "s390":
1626                 return []string{"-m31"}
1627         case "s390x":
1628                 return []string{"-m64"}
1629         case "mips64", "mips64le":
1630                 if gomips64 == "hardfloat" {
1631                         return []string{"-mabi=64", "-mhard-float"}
1632                 } else if gomips64 == "softfloat" {
1633                         return []string{"-mabi=64", "-msoft-float"}
1634                 }
1635         case "mips", "mipsle":
1636                 if gomips == "hardfloat" {
1637                         return []string{"-mabi=32", "-mfp32", "-mhard-float", "-mno-odd-spreg"}
1638                 } else if gomips == "softfloat" {
1639                         return []string{"-mabi=32", "-msoft-float"}
1640                 }
1641         case "loong64":
1642                 return []string{"-mabi=lp64d"}
1643         }
1644         return nil
1645 }
1646
1647 func gccTmp() string {
1648         return *objDir + "_cgo_.o"
1649 }
1650
1651 // gccCmd returns the gcc command line to use for compiling
1652 // the input.
1653 func (p *Package) gccCmd() []string {
1654         c := append(gccBaseCmd,
1655                 "-w",          // no warnings
1656                 "-Wno-error",  // warnings are not errors
1657                 "-o"+gccTmp(), // write object to tmp
1658                 "-gdwarf-2",   // generate DWARF v2 debugging symbols
1659                 "-c",          // do not link
1660                 "-xc",         // input language is C
1661         )
1662         if p.GccIsClang {
1663                 c = append(c,
1664                         "-ferror-limit=0",
1665                         // Apple clang version 1.7 (tags/Apple/clang-77) (based on LLVM 2.9svn)
1666                         // doesn't have -Wno-unneeded-internal-declaration, so we need yet another
1667                         // flag to disable the warning. Yes, really good diagnostics, clang.
1668                         "-Wno-unknown-warning-option",
1669                         "-Wno-unneeded-internal-declaration",
1670                         "-Wno-unused-function",
1671                         "-Qunused-arguments",
1672                         // Clang embeds prototypes for some builtin functions,
1673                         // like malloc and calloc, but all size_t parameters are
1674                         // incorrectly typed unsigned long. We work around that
1675                         // by disabling the builtin functions (this is safe as
1676                         // it won't affect the actual compilation of the C code).
1677                         // See: https://golang.org/issue/6506.
1678                         "-fno-builtin",
1679                 )
1680         }
1681
1682         c = append(c, p.GccOptions...)
1683         c = append(c, p.gccMachine()...)
1684         if goos == "aix" {
1685                 c = append(c, "-maix64")
1686                 c = append(c, "-mcmodel=large")
1687         }
1688         // disable LTO so we get an object whose symbols we can read
1689         c = append(c, "-fno-lto")
1690         c = append(c, "-") //read input from standard input
1691         return c
1692 }
1693
1694 // gccDebug runs gcc -gdwarf-2 over the C program stdin and
1695 // returns the corresponding DWARF data and, if present, debug data block.
1696 func (p *Package) gccDebug(stdin []byte, nnames int) (d *dwarf.Data, ints []int64, floats []float64, strs []string) {
1697         runGcc(stdin, p.gccCmd())
1698
1699         isDebugInts := func(s string) bool {
1700                 // Some systems use leading _ to denote non-assembly symbols.
1701                 return s == "__cgodebug_ints" || s == "___cgodebug_ints"
1702         }
1703         isDebugFloats := func(s string) bool {
1704                 // Some systems use leading _ to denote non-assembly symbols.
1705                 return s == "__cgodebug_floats" || s == "___cgodebug_floats"
1706         }
1707         indexOfDebugStr := func(s string) int {
1708                 // Some systems use leading _ to denote non-assembly symbols.
1709                 if strings.HasPrefix(s, "___") {
1710                         s = s[1:]
1711                 }
1712                 if strings.HasPrefix(s, "__cgodebug_str__") {
1713                         if n, err := strconv.Atoi(s[len("__cgodebug_str__"):]); err == nil {
1714                                 return n
1715                         }
1716                 }
1717                 return -1
1718         }
1719         indexOfDebugStrlen := func(s string) int {
1720                 // Some systems use leading _ to denote non-assembly symbols.
1721                 if strings.HasPrefix(s, "___") {
1722                         s = s[1:]
1723                 }
1724                 if strings.HasPrefix(s, "__cgodebug_strlen__") {
1725                         if n, err := strconv.Atoi(s[len("__cgodebug_strlen__"):]); err == nil {
1726                                 return n
1727                         }
1728                 }
1729                 return -1
1730         }
1731
1732         strs = make([]string, nnames)
1733
1734         strdata := make(map[int]string, nnames)
1735         strlens := make(map[int]int, nnames)
1736
1737         buildStrings := func() {
1738                 for n, strlen := range strlens {
1739                         data := strdata[n]
1740                         if len(data) <= strlen {
1741                                 fatalf("invalid string literal")
1742                         }
1743                         strs[n] = data[:strlen]
1744                 }
1745         }
1746
1747         if f, err := macho.Open(gccTmp()); err == nil {
1748                 defer f.Close()
1749                 d, err := f.DWARF()
1750                 if err != nil {
1751                         fatalf("cannot load DWARF output from %s: %v", gccTmp(), err)
1752                 }
1753                 bo := f.ByteOrder
1754                 if f.Symtab != nil {
1755                         for i := range f.Symtab.Syms {
1756                                 s := &f.Symtab.Syms[i]
1757                                 switch {
1758                                 case isDebugInts(s.Name):
1759                                         // Found it. Now find data section.
1760                                         if i := int(s.Sect) - 1; 0 <= i && i < len(f.Sections) {
1761                                                 sect := f.Sections[i]
1762                                                 if sect.Addr <= s.Value && s.Value < sect.Addr+sect.Size {
1763                                                         if sdat, err := sect.Data(); err == nil {
1764                                                                 data := sdat[s.Value-sect.Addr:]
1765                                                                 ints = make([]int64, len(data)/8)
1766                                                                 for i := range ints {
1767                                                                         ints[i] = int64(bo.Uint64(data[i*8:]))
1768                                                                 }
1769                                                         }
1770                                                 }
1771                                         }
1772                                 case isDebugFloats(s.Name):
1773                                         // Found it. Now find data section.
1774                                         if i := int(s.Sect) - 1; 0 <= i && i < len(f.Sections) {
1775                                                 sect := f.Sections[i]
1776                                                 if sect.Addr <= s.Value && s.Value < sect.Addr+sect.Size {
1777                                                         if sdat, err := sect.Data(); err == nil {
1778                                                                 data := sdat[s.Value-sect.Addr:]
1779                                                                 floats = make([]float64, len(data)/8)
1780                                                                 for i := range floats {
1781                                                                         floats[i] = math.Float64frombits(bo.Uint64(data[i*8:]))
1782                                                                 }
1783                                                         }
1784                                                 }
1785                                         }
1786                                 default:
1787                                         if n := indexOfDebugStr(s.Name); n != -1 {
1788                                                 // Found it. Now find data section.
1789                                                 if i := int(s.Sect) - 1; 0 <= i && i < len(f.Sections) {
1790                                                         sect := f.Sections[i]
1791                                                         if sect.Addr <= s.Value && s.Value < sect.Addr+sect.Size {
1792                                                                 if sdat, err := sect.Data(); err == nil {
1793                                                                         data := sdat[s.Value-sect.Addr:]
1794                                                                         strdata[n] = string(data)
1795                                                                 }
1796                                                         }
1797                                                 }
1798                                                 break
1799                                         }
1800                                         if n := indexOfDebugStrlen(s.Name); n != -1 {
1801                                                 // Found it. Now find data section.
1802                                                 if i := int(s.Sect) - 1; 0 <= i && i < len(f.Sections) {
1803                                                         sect := f.Sections[i]
1804                                                         if sect.Addr <= s.Value && s.Value < sect.Addr+sect.Size {
1805                                                                 if sdat, err := sect.Data(); err == nil {
1806                                                                         data := sdat[s.Value-sect.Addr:]
1807                                                                         strlen := bo.Uint64(data[:8])
1808                                                                         if strlen > (1<<(uint(p.IntSize*8)-1) - 1) { // greater than MaxInt?
1809                                                                                 fatalf("string literal too big")
1810                                                                         }
1811                                                                         strlens[n] = int(strlen)
1812                                                                 }
1813                                                         }
1814                                                 }
1815                                                 break
1816                                         }
1817                                 }
1818                         }
1819
1820                         buildStrings()
1821                 }
1822                 return d, ints, floats, strs
1823         }
1824
1825         if f, err := elf.Open(gccTmp()); err == nil {
1826                 defer f.Close()
1827                 d, err := f.DWARF()
1828                 if err != nil {
1829                         fatalf("cannot load DWARF output from %s: %v", gccTmp(), err)
1830                 }
1831                 bo := f.ByteOrder
1832                 symtab, err := f.Symbols()
1833                 if err == nil {
1834                         // Check for use of -fsanitize=hwaddress (issue 53285).
1835                         removeTag := func(v uint64) uint64 { return v }
1836                         if goarch == "arm64" {
1837                                 for i := range symtab {
1838                                         if symtab[i].Name == "__hwasan_init" {
1839                                                 // -fsanitize=hwaddress on ARM
1840                                                 // uses the upper byte of a
1841                                                 // memory address as a hardware
1842                                                 // tag. Remove it so that
1843                                                 // we can find the associated
1844                                                 // data.
1845                                                 removeTag = func(v uint64) uint64 { return v &^ (0xff << (64 - 8)) }
1846                                                 break
1847                                         }
1848                                 }
1849                         }
1850
1851                         for i := range symtab {
1852                                 s := &symtab[i]
1853                                 switch {
1854                                 case isDebugInts(s.Name):
1855                                         // Found it. Now find data section.
1856                                         if i := int(s.Section); 0 <= i && i < len(f.Sections) {
1857                                                 sect := f.Sections[i]
1858                                                 val := removeTag(s.Value)
1859                                                 if sect.Addr <= val && val < sect.Addr+sect.Size {
1860                                                         if sdat, err := sect.Data(); err == nil {
1861                                                                 data := sdat[val-sect.Addr:]
1862                                                                 ints = make([]int64, len(data)/8)
1863                                                                 for i := range ints {
1864                                                                         ints[i] = int64(bo.Uint64(data[i*8:]))
1865                                                                 }
1866                                                         }
1867                                                 }
1868                                         }
1869                                 case isDebugFloats(s.Name):
1870                                         // Found it. Now find data section.
1871                                         if i := int(s.Section); 0 <= i && i < len(f.Sections) {
1872                                                 sect := f.Sections[i]
1873                                                 val := removeTag(s.Value)
1874                                                 if sect.Addr <= val && val < sect.Addr+sect.Size {
1875                                                         if sdat, err := sect.Data(); err == nil {
1876                                                                 data := sdat[val-sect.Addr:]
1877                                                                 floats = make([]float64, len(data)/8)
1878                                                                 for i := range floats {
1879                                                                         floats[i] = math.Float64frombits(bo.Uint64(data[i*8:]))
1880                                                                 }
1881                                                         }
1882                                                 }
1883                                         }
1884                                 default:
1885                                         if n := indexOfDebugStr(s.Name); n != -1 {
1886                                                 // Found it. Now find data section.
1887                                                 if i := int(s.Section); 0 <= i && i < len(f.Sections) {
1888                                                         sect := f.Sections[i]
1889                                                         val := removeTag(s.Value)
1890                                                         if sect.Addr <= val && val < sect.Addr+sect.Size {
1891                                                                 if sdat, err := sect.Data(); err == nil {
1892                                                                         data := sdat[val-sect.Addr:]
1893                                                                         strdata[n] = string(data)
1894                                                                 }
1895                                                         }
1896                                                 }
1897                                                 break
1898                                         }
1899                                         if n := indexOfDebugStrlen(s.Name); n != -1 {
1900                                                 // Found it. Now find data section.
1901                                                 if i := int(s.Section); 0 <= i && i < len(f.Sections) {
1902                                                         sect := f.Sections[i]
1903                                                         val := removeTag(s.Value)
1904                                                         if sect.Addr <= val && val < sect.Addr+sect.Size {
1905                                                                 if sdat, err := sect.Data(); err == nil {
1906                                                                         data := sdat[val-sect.Addr:]
1907                                                                         strlen := bo.Uint64(data[:8])
1908                                                                         if strlen > (1<<(uint(p.IntSize*8)-1) - 1) { // greater than MaxInt?
1909                                                                                 fatalf("string literal too big")
1910                                                                         }
1911                                                                         strlens[n] = int(strlen)
1912                                                                 }
1913                                                         }
1914                                                 }
1915                                                 break
1916                                         }
1917                                 }
1918                         }
1919
1920                         buildStrings()
1921                 }
1922                 return d, ints, floats, strs
1923         }
1924
1925         if f, err := pe.Open(gccTmp()); err == nil {
1926                 defer f.Close()
1927                 d, err := f.DWARF()
1928                 if err != nil {
1929                         fatalf("cannot load DWARF output from %s: %v", gccTmp(), err)
1930                 }
1931                 bo := binary.LittleEndian
1932                 for _, s := range f.Symbols {
1933                         switch {
1934                         case isDebugInts(s.Name):
1935                                 if i := int(s.SectionNumber) - 1; 0 <= i && i < len(f.Sections) {
1936                                         sect := f.Sections[i]
1937                                         if s.Value < sect.Size {
1938                                                 if sdat, err := sect.Data(); err == nil {
1939                                                         data := sdat[s.Value:]
1940                                                         ints = make([]int64, len(data)/8)
1941                                                         for i := range ints {
1942                                                                 ints[i] = int64(bo.Uint64(data[i*8:]))
1943                                                         }
1944                                                 }
1945                                         }
1946                                 }
1947                         case isDebugFloats(s.Name):
1948                                 if i := int(s.SectionNumber) - 1; 0 <= i && i < len(f.Sections) {
1949                                         sect := f.Sections[i]
1950                                         if s.Value < sect.Size {
1951                                                 if sdat, err := sect.Data(); err == nil {
1952                                                         data := sdat[s.Value:]
1953                                                         floats = make([]float64, len(data)/8)
1954                                                         for i := range floats {
1955                                                                 floats[i] = math.Float64frombits(bo.Uint64(data[i*8:]))
1956                                                         }
1957                                                 }
1958                                         }
1959                                 }
1960                         default:
1961                                 if n := indexOfDebugStr(s.Name); n != -1 {
1962                                         if i := int(s.SectionNumber) - 1; 0 <= i && i < len(f.Sections) {
1963                                                 sect := f.Sections[i]
1964                                                 if s.Value < sect.Size {
1965                                                         if sdat, err := sect.Data(); err == nil {
1966                                                                 data := sdat[s.Value:]
1967                                                                 strdata[n] = string(data)
1968                                                         }
1969                                                 }
1970                                         }
1971                                         break
1972                                 }
1973                                 if n := indexOfDebugStrlen(s.Name); n != -1 {
1974                                         if i := int(s.SectionNumber) - 1; 0 <= i && i < len(f.Sections) {
1975                                                 sect := f.Sections[i]
1976                                                 if s.Value < sect.Size {
1977                                                         if sdat, err := sect.Data(); err == nil {
1978                                                                 data := sdat[s.Value:]
1979                                                                 strlen := bo.Uint64(data[:8])
1980                                                                 if strlen > (1<<(uint(p.IntSize*8)-1) - 1) { // greater than MaxInt?
1981                                                                         fatalf("string literal too big")
1982                                                                 }
1983                                                                 strlens[n] = int(strlen)
1984                                                         }
1985                                                 }
1986                                         }
1987                                         break
1988                                 }
1989                         }
1990                 }
1991
1992                 buildStrings()
1993
1994                 return d, ints, floats, strs
1995         }
1996
1997         if f, err := xcoff.Open(gccTmp()); err == nil {
1998                 defer f.Close()
1999                 d, err := f.DWARF()
2000                 if err != nil {
2001                         fatalf("cannot load DWARF output from %s: %v", gccTmp(), err)
2002                 }
2003                 bo := binary.BigEndian
2004                 for _, s := range f.Symbols {
2005                         switch {
2006                         case isDebugInts(s.Name):
2007                                 if i := int(s.SectionNumber) - 1; 0 <= i && i < len(f.Sections) {
2008                                         sect := f.Sections[i]
2009                                         if s.Value < sect.Size {
2010                                                 if sdat, err := sect.Data(); err == nil {
2011                                                         data := sdat[s.Value:]
2012                                                         ints = make([]int64, len(data)/8)
2013                                                         for i := range ints {
2014                                                                 ints[i] = int64(bo.Uint64(data[i*8:]))
2015                                                         }
2016                                                 }
2017                                         }
2018                                 }
2019                         case isDebugFloats(s.Name):
2020                                 if i := int(s.SectionNumber) - 1; 0 <= i && i < len(f.Sections) {
2021                                         sect := f.Sections[i]
2022                                         if s.Value < sect.Size {
2023                                                 if sdat, err := sect.Data(); err == nil {
2024                                                         data := sdat[s.Value:]
2025                                                         floats = make([]float64, len(data)/8)
2026                                                         for i := range floats {
2027                                                                 floats[i] = math.Float64frombits(bo.Uint64(data[i*8:]))
2028                                                         }
2029                                                 }
2030                                         }
2031                                 }
2032                         default:
2033                                 if n := indexOfDebugStr(s.Name); n != -1 {
2034                                         if i := int(s.SectionNumber) - 1; 0 <= i && i < len(f.Sections) {
2035                                                 sect := f.Sections[i]
2036                                                 if s.Value < sect.Size {
2037                                                         if sdat, err := sect.Data(); err == nil {
2038                                                                 data := sdat[s.Value:]
2039                                                                 strdata[n] = string(data)
2040                                                         }
2041                                                 }
2042                                         }
2043                                         break
2044                                 }
2045                                 if n := indexOfDebugStrlen(s.Name); n != -1 {
2046                                         if i := int(s.SectionNumber) - 1; 0 <= i && i < len(f.Sections) {
2047                                                 sect := f.Sections[i]
2048                                                 if s.Value < sect.Size {
2049                                                         if sdat, err := sect.Data(); err == nil {
2050                                                                 data := sdat[s.Value:]
2051                                                                 strlen := bo.Uint64(data[:8])
2052                                                                 if strlen > (1<<(uint(p.IntSize*8)-1) - 1) { // greater than MaxInt?
2053                                                                         fatalf("string literal too big")
2054                                                                 }
2055                                                                 strlens[n] = int(strlen)
2056                                                         }
2057                                                 }
2058                                         }
2059                                         break
2060                                 }
2061                         }
2062                 }
2063
2064                 buildStrings()
2065                 return d, ints, floats, strs
2066         }
2067         fatalf("cannot parse gcc output %s as ELF, Mach-O, PE, XCOFF object", gccTmp())
2068         panic("not reached")
2069 }
2070
2071 // gccDefines runs gcc -E -dM -xc - over the C program stdin
2072 // and returns the corresponding standard output, which is the
2073 // #defines that gcc encountered while processing the input
2074 // and its included files.
2075 func (p *Package) gccDefines(stdin []byte) string {
2076         base := append(gccBaseCmd, "-E", "-dM", "-xc")
2077         base = append(base, p.gccMachine()...)
2078         stdout, _ := runGcc(stdin, append(append(base, p.GccOptions...), "-"))
2079         return stdout
2080 }
2081
2082 // gccErrors runs gcc over the C program stdin and returns
2083 // the errors that gcc prints. That is, this function expects
2084 // gcc to fail.
2085 func (p *Package) gccErrors(stdin []byte, extraArgs ...string) string {
2086         // TODO(rsc): require failure
2087         args := p.gccCmd()
2088
2089         // Optimization options can confuse the error messages; remove them.
2090         nargs := make([]string, 0, len(args)+len(extraArgs))
2091         for _, arg := range args {
2092                 if !strings.HasPrefix(arg, "-O") {
2093                         nargs = append(nargs, arg)
2094                 }
2095         }
2096
2097         // Force -O0 optimization and append extra arguments, but keep the
2098         // trailing "-" at the end.
2099         li := len(nargs) - 1
2100         last := nargs[li]
2101         nargs[li] = "-O0"
2102         nargs = append(nargs, extraArgs...)
2103         nargs = append(nargs, last)
2104
2105         if *debugGcc {
2106                 fmt.Fprintf(os.Stderr, "$ %s <<EOF\n", strings.Join(nargs, " "))
2107                 os.Stderr.Write(stdin)
2108                 fmt.Fprint(os.Stderr, "EOF\n")
2109         }
2110         stdout, stderr, _ := run(stdin, nargs)
2111         if *debugGcc {
2112                 os.Stderr.Write(stdout)
2113                 os.Stderr.Write(stderr)
2114         }
2115         return string(stderr)
2116 }
2117
2118 // runGcc runs the gcc command line args with stdin on standard input.
2119 // If the command exits with a non-zero exit status, runGcc prints
2120 // details about what was run and exits.
2121 // Otherwise runGcc returns the data written to standard output and standard error.
2122 // Note that for some of the uses we expect useful data back
2123 // on standard error, but for those uses gcc must still exit 0.
2124 func runGcc(stdin []byte, args []string) (string, string) {
2125         if *debugGcc {
2126                 fmt.Fprintf(os.Stderr, "$ %s <<EOF\n", strings.Join(args, " "))
2127                 os.Stderr.Write(stdin)
2128                 fmt.Fprint(os.Stderr, "EOF\n")
2129         }
2130         stdout, stderr, ok := run(stdin, args)
2131         if *debugGcc {
2132                 os.Stderr.Write(stdout)
2133                 os.Stderr.Write(stderr)
2134         }
2135         if !ok {
2136                 os.Stderr.Write(stderr)
2137                 os.Exit(2)
2138         }
2139         return string(stdout), string(stderr)
2140 }
2141
2142 // A typeConv is a translator from dwarf types to Go types
2143 // with equivalent memory layout.
2144 type typeConv struct {
2145         // Cache of already-translated or in-progress types.
2146         m map[string]*Type
2147
2148         // Map from types to incomplete pointers to those types.
2149         ptrs map[string][]*Type
2150         // Keys of ptrs in insertion order (deterministic worklist)
2151         // ptrKeys contains exactly the keys in ptrs.
2152         ptrKeys []dwarf.Type
2153
2154         // Type names X for which there exists an XGetTypeID function with type func() CFTypeID.
2155         getTypeIDs map[string]bool
2156
2157         // badStructs contains C structs that should be marked NotInHeap.
2158         notInHeapStructs map[string]bool
2159
2160         // Predeclared types.
2161         bool                                   ast.Expr
2162         byte                                   ast.Expr // denotes padding
2163         int8, int16, int32, int64              ast.Expr
2164         uint8, uint16, uint32, uint64, uintptr ast.Expr
2165         float32, float64                       ast.Expr
2166         complex64, complex128                  ast.Expr
2167         void                                   ast.Expr
2168         string                                 ast.Expr
2169         goVoid                                 ast.Expr // _Ctype_void, denotes C's void
2170         goVoidPtr                              ast.Expr // unsafe.Pointer or *byte
2171         goVoidPtrNoHeap                        ast.Expr // *_Ctype_void_notinheap, like goVoidPtr but marked NotInHeap
2172
2173         ptrSize int64
2174         intSize int64
2175 }
2176
2177 var tagGen int
2178 var typedef = make(map[string]*Type)
2179 var goIdent = make(map[string]*ast.Ident)
2180
2181 // unionWithPointer is true for a Go type that represents a C union (or class)
2182 // that may contain a pointer. This is used for cgo pointer checking.
2183 var unionWithPointer = make(map[ast.Expr]bool)
2184
2185 // anonymousStructTag provides a consistent tag for an anonymous struct.
2186 // The same dwarf.StructType pointer will always get the same tag.
2187 var anonymousStructTag = make(map[*dwarf.StructType]string)
2188
2189 func (c *typeConv) Init(ptrSize, intSize int64) {
2190         c.ptrSize = ptrSize
2191         c.intSize = intSize
2192         c.m = make(map[string]*Type)
2193         c.ptrs = make(map[string][]*Type)
2194         c.getTypeIDs = make(map[string]bool)
2195         c.notInHeapStructs = make(map[string]bool)
2196         c.bool = c.Ident("bool")
2197         c.byte = c.Ident("byte")
2198         c.int8 = c.Ident("int8")
2199         c.int16 = c.Ident("int16")
2200         c.int32 = c.Ident("int32")
2201         c.int64 = c.Ident("int64")
2202         c.uint8 = c.Ident("uint8")
2203         c.uint16 = c.Ident("uint16")
2204         c.uint32 = c.Ident("uint32")
2205         c.uint64 = c.Ident("uint64")
2206         c.uintptr = c.Ident("uintptr")
2207         c.float32 = c.Ident("float32")
2208         c.float64 = c.Ident("float64")
2209         c.complex64 = c.Ident("complex64")
2210         c.complex128 = c.Ident("complex128")
2211         c.void = c.Ident("void")
2212         c.string = c.Ident("string")
2213         c.goVoid = c.Ident("_Ctype_void")
2214         c.goVoidPtrNoHeap = c.Ident("*_Ctype_void_notinheap")
2215
2216         // Normally cgo translates void* to unsafe.Pointer,
2217         // but for historical reasons -godefs uses *byte instead.
2218         if *godefs {
2219                 c.goVoidPtr = &ast.StarExpr{X: c.byte}
2220         } else {
2221                 c.goVoidPtr = c.Ident("unsafe.Pointer")
2222         }
2223 }
2224
2225 // base strips away qualifiers and typedefs to get the underlying type
2226 func base(dt dwarf.Type) dwarf.Type {
2227         for {
2228                 if d, ok := dt.(*dwarf.QualType); ok {
2229                         dt = d.Type
2230                         continue
2231                 }
2232                 if d, ok := dt.(*dwarf.TypedefType); ok {
2233                         dt = d.Type
2234                         continue
2235                 }
2236                 break
2237         }
2238         return dt
2239 }
2240
2241 // unqual strips away qualifiers from a DWARF type.
2242 // In general we don't care about top-level qualifiers.
2243 func unqual(dt dwarf.Type) dwarf.Type {
2244         for {
2245                 if d, ok := dt.(*dwarf.QualType); ok {
2246                         dt = d.Type
2247                 } else {
2248                         break
2249                 }
2250         }
2251         return dt
2252 }
2253
2254 // Map from dwarf text names to aliases we use in package "C".
2255 var dwarfToName = map[string]string{
2256         "long int":               "long",
2257         "long unsigned int":      "ulong",
2258         "unsigned int":           "uint",
2259         "short unsigned int":     "ushort",
2260         "unsigned short":         "ushort", // Used by Clang; issue 13129.
2261         "short int":              "short",
2262         "long long int":          "longlong",
2263         "long long unsigned int": "ulonglong",
2264         "signed char":            "schar",
2265         "unsigned char":          "uchar",
2266         "unsigned long":          "ulong",     // Used by Clang 14; issue 53013.
2267         "unsigned long long":     "ulonglong", // Used by Clang 14; issue 53013.
2268 }
2269
2270 const signedDelta = 64
2271
2272 // String returns the current type representation. Format arguments
2273 // are assembled within this method so that any changes in mutable
2274 // values are taken into account.
2275 func (tr *TypeRepr) String() string {
2276         if len(tr.Repr) == 0 {
2277                 return ""
2278         }
2279         if len(tr.FormatArgs) == 0 {
2280                 return tr.Repr
2281         }
2282         return fmt.Sprintf(tr.Repr, tr.FormatArgs...)
2283 }
2284
2285 // Empty reports whether the result of String would be "".
2286 func (tr *TypeRepr) Empty() bool {
2287         return len(tr.Repr) == 0
2288 }
2289
2290 // Set modifies the type representation.
2291 // If fargs are provided, repr is used as a format for fmt.Sprintf.
2292 // Otherwise, repr is used unprocessed as the type representation.
2293 func (tr *TypeRepr) Set(repr string, fargs ...interface{}) {
2294         tr.Repr = repr
2295         tr.FormatArgs = fargs
2296 }
2297
2298 // FinishType completes any outstanding type mapping work.
2299 // In particular, it resolves incomplete pointer types.
2300 func (c *typeConv) FinishType(pos token.Pos) {
2301         // Completing one pointer type might produce more to complete.
2302         // Keep looping until they're all done.
2303         for len(c.ptrKeys) > 0 {
2304                 dtype := c.ptrKeys[0]
2305                 dtypeKey := dtype.String()
2306                 c.ptrKeys = c.ptrKeys[1:]
2307                 ptrs := c.ptrs[dtypeKey]
2308                 delete(c.ptrs, dtypeKey)
2309
2310                 // Note Type might invalidate c.ptrs[dtypeKey].
2311                 t := c.Type(dtype, pos)
2312                 for _, ptr := range ptrs {
2313                         ptr.Go.(*ast.StarExpr).X = t.Go
2314                         ptr.C.Set("%s*", t.C)
2315                 }
2316         }
2317 }
2318
2319 // Type returns a *Type with the same memory layout as
2320 // dtype when used as the type of a variable or a struct field.
2321 func (c *typeConv) Type(dtype dwarf.Type, pos token.Pos) *Type {
2322         return c.loadType(dtype, pos, "")
2323 }
2324
2325 // loadType recursively loads the requested dtype and its dependency graph.
2326 func (c *typeConv) loadType(dtype dwarf.Type, pos token.Pos, parent string) *Type {
2327         // Always recompute bad pointer typedefs, as the set of such
2328         // typedefs changes as we see more types.
2329         checkCache := true
2330         if dtt, ok := dtype.(*dwarf.TypedefType); ok && c.badPointerTypedef(dtt) {
2331                 checkCache = false
2332         }
2333
2334         // The cache key should be relative to its parent.
2335         // See issue https://golang.org/issue/31891
2336         key := parent + " > " + dtype.String()
2337
2338         if checkCache {
2339                 if t, ok := c.m[key]; ok {
2340                         if t.Go == nil {
2341                                 fatalf("%s: type conversion loop at %s", lineno(pos), dtype)
2342                         }
2343                         return t
2344                 }
2345         }
2346
2347         t := new(Type)
2348         t.Size = dtype.Size() // note: wrong for array of pointers, corrected below
2349         t.Align = -1
2350         t.C = &TypeRepr{Repr: dtype.Common().Name}
2351         c.m[key] = t
2352
2353         switch dt := dtype.(type) {
2354         default:
2355                 fatalf("%s: unexpected type: %s", lineno(pos), dtype)
2356
2357         case *dwarf.AddrType:
2358                 if t.Size != c.ptrSize {
2359                         fatalf("%s: unexpected: %d-byte address type - %s", lineno(pos), t.Size, dtype)
2360                 }
2361                 t.Go = c.uintptr
2362                 t.Align = t.Size
2363
2364         case *dwarf.ArrayType:
2365                 if dt.StrideBitSize > 0 {
2366                         // Cannot represent bit-sized elements in Go.
2367                         t.Go = c.Opaque(t.Size)
2368                         break
2369                 }
2370                 count := dt.Count
2371                 if count == -1 {
2372                         // Indicates flexible array member, which Go doesn't support.
2373                         // Translate to zero-length array instead.
2374                         count = 0
2375                 }
2376                 sub := c.Type(dt.Type, pos)
2377                 t.Align = sub.Align
2378                 t.Go = &ast.ArrayType{
2379                         Len: c.intExpr(count),
2380                         Elt: sub.Go,
2381                 }
2382                 // Recalculate t.Size now that we know sub.Size.
2383                 t.Size = count * sub.Size
2384                 t.C.Set("__typeof__(%s[%d])", sub.C, dt.Count)
2385
2386         case *dwarf.BoolType:
2387                 t.Go = c.bool
2388                 t.Align = 1
2389
2390         case *dwarf.CharType:
2391                 if t.Size != 1 {
2392                         fatalf("%s: unexpected: %d-byte char type - %s", lineno(pos), t.Size, dtype)
2393                 }
2394                 t.Go = c.int8
2395                 t.Align = 1
2396
2397         case *dwarf.EnumType:
2398                 if t.Align = t.Size; t.Align >= c.ptrSize {
2399                         t.Align = c.ptrSize
2400                 }
2401                 t.C.Set("enum " + dt.EnumName)
2402                 signed := 0
2403                 t.EnumValues = make(map[string]int64)
2404                 for _, ev := range dt.Val {
2405                         t.EnumValues[ev.Name] = ev.Val
2406                         if ev.Val < 0 {
2407                                 signed = signedDelta
2408                         }
2409                 }
2410                 switch t.Size + int64(signed) {
2411                 default:
2412                         fatalf("%s: unexpected: %d-byte enum type - %s", lineno(pos), t.Size, dtype)
2413                 case 1:
2414                         t.Go = c.uint8
2415                 case 2:
2416                         t.Go = c.uint16
2417                 case 4:
2418                         t.Go = c.uint32
2419                 case 8:
2420                         t.Go = c.uint64
2421                 case 1 + signedDelta:
2422                         t.Go = c.int8
2423                 case 2 + signedDelta:
2424                         t.Go = c.int16
2425                 case 4 + signedDelta:
2426                         t.Go = c.int32
2427                 case 8 + signedDelta:
2428                         t.Go = c.int64
2429                 }
2430
2431         case *dwarf.FloatType:
2432                 switch t.Size {
2433                 default:
2434                         fatalf("%s: unexpected: %d-byte float type - %s", lineno(pos), t.Size, dtype)
2435                 case 4:
2436                         t.Go = c.float32
2437                 case 8:
2438                         t.Go = c.float64
2439                 }
2440                 if t.Align = t.Size; t.Align >= c.ptrSize {
2441                         t.Align = c.ptrSize
2442                 }
2443
2444         case *dwarf.ComplexType:
2445                 switch t.Size {
2446                 default:
2447                         fatalf("%s: unexpected: %d-byte complex type - %s", lineno(pos), t.Size, dtype)
2448                 case 8:
2449                         t.Go = c.complex64
2450                 case 16:
2451                         t.Go = c.complex128
2452                 }
2453                 if t.Align = t.Size / 2; t.Align >= c.ptrSize {
2454                         t.Align = c.ptrSize
2455                 }
2456
2457         case *dwarf.FuncType:
2458                 // No attempt at translation: would enable calls
2459                 // directly between worlds, but we need to moderate those.
2460                 t.Go = c.uintptr
2461                 t.Align = c.ptrSize
2462
2463         case *dwarf.IntType:
2464                 if dt.BitSize > 0 {
2465                         fatalf("%s: unexpected: %d-bit int type - %s", lineno(pos), dt.BitSize, dtype)
2466                 }
2467                 switch t.Size {
2468                 default:
2469                         fatalf("%s: unexpected: %d-byte int type - %s", lineno(pos), t.Size, dtype)
2470                 case 1:
2471                         t.Go = c.int8
2472                 case 2:
2473                         t.Go = c.int16
2474                 case 4:
2475                         t.Go = c.int32
2476                 case 8:
2477                         t.Go = c.int64
2478                 case 16:
2479                         t.Go = &ast.ArrayType{
2480                                 Len: c.intExpr(t.Size),
2481                                 Elt: c.uint8,
2482                         }
2483                 }
2484                 if t.Align = t.Size; t.Align >= c.ptrSize {
2485                         t.Align = c.ptrSize
2486                 }
2487
2488         case *dwarf.PtrType:
2489                 // Clang doesn't emit DW_AT_byte_size for pointer types.
2490                 if t.Size != c.ptrSize && t.Size != -1 {
2491                         fatalf("%s: unexpected: %d-byte pointer type - %s", lineno(pos), t.Size, dtype)
2492                 }
2493                 t.Size = c.ptrSize
2494                 t.Align = c.ptrSize
2495
2496                 if _, ok := base(dt.Type).(*dwarf.VoidType); ok {
2497                         t.Go = c.goVoidPtr
2498                         t.C.Set("void*")
2499                         dq := dt.Type
2500                         for {
2501                                 if d, ok := dq.(*dwarf.QualType); ok {
2502                                         t.C.Set(d.Qual + " " + t.C.String())
2503                                         dq = d.Type
2504                                 } else {
2505                                         break
2506                                 }
2507                         }
2508                         break
2509                 }
2510
2511                 // Placeholder initialization; completed in FinishType.
2512                 t.Go = &ast.StarExpr{}
2513                 t.C.Set("<incomplete>*")
2514                 key := dt.Type.String()
2515                 if _, ok := c.ptrs[key]; !ok {
2516                         c.ptrKeys = append(c.ptrKeys, dt.Type)
2517                 }
2518                 c.ptrs[key] = append(c.ptrs[key], t)
2519
2520         case *dwarf.QualType:
2521                 t1 := c.Type(dt.Type, pos)
2522                 t.Size = t1.Size
2523                 t.Align = t1.Align
2524                 t.Go = t1.Go
2525                 if unionWithPointer[t1.Go] {
2526                         unionWithPointer[t.Go] = true
2527                 }
2528                 t.EnumValues = nil
2529                 t.Typedef = ""
2530                 t.C.Set("%s "+dt.Qual, t1.C)
2531                 return t
2532
2533         case *dwarf.StructType:
2534                 // Convert to Go struct, being careful about alignment.
2535                 // Have to give it a name to simulate C "struct foo" references.
2536                 tag := dt.StructName
2537                 if dt.ByteSize < 0 && tag == "" { // opaque unnamed struct - should not be possible
2538                         break
2539                 }
2540                 if tag == "" {
2541                         tag = anonymousStructTag[dt]
2542                         if tag == "" {
2543                                 tag = "__" + strconv.Itoa(tagGen)
2544                                 tagGen++
2545                                 anonymousStructTag[dt] = tag
2546                         }
2547                 } else if t.C.Empty() {
2548                         t.C.Set(dt.Kind + " " + tag)
2549                 }
2550                 name := c.Ident("_Ctype_" + dt.Kind + "_" + tag)
2551                 t.Go = name // publish before recursive calls
2552                 goIdent[name.Name] = name
2553                 if dt.ByteSize < 0 {
2554                         // Don't override old type
2555                         if _, ok := typedef[name.Name]; ok {
2556                                 break
2557                         }
2558
2559                         // Size calculation in c.Struct/c.Opaque will die with size=-1 (unknown),
2560                         // so execute the basic things that the struct case would do
2561                         // other than try to determine a Go representation.
2562                         tt := *t
2563                         tt.C = &TypeRepr{"%s %s", []interface{}{dt.Kind, tag}}
2564                         tt.Go = c.Ident("struct{}")
2565                         if dt.Kind == "struct" {
2566                                 // We don't know what the representation of this struct is, so don't let
2567                                 // anyone allocate one on the Go side. As a side effect of this annotation,
2568                                 // pointers to this type will not be considered pointers in Go. They won't
2569                                 // get writebarrier-ed or adjusted during a stack copy. This should handle
2570                                 // all the cases badPointerTypedef used to handle, but hopefully will
2571                                 // continue to work going forward without any more need for cgo changes.
2572                                 tt.NotInHeap = true
2573                                 // TODO: we should probably do the same for unions. Unions can't live
2574                                 // on the Go heap, right? It currently doesn't work for unions because
2575                                 // they are defined as a type alias for struct{}, not a defined type.
2576                         }
2577                         typedef[name.Name] = &tt
2578                         break
2579                 }
2580                 switch dt.Kind {
2581                 case "class", "union":
2582                         t.Go = c.Opaque(t.Size)
2583                         if c.dwarfHasPointer(dt, pos) {
2584                                 unionWithPointer[t.Go] = true
2585                         }
2586                         if t.C.Empty() {
2587                                 t.C.Set("__typeof__(unsigned char[%d])", t.Size)
2588                         }
2589                         t.Align = 1 // TODO: should probably base this on field alignment.
2590                         typedef[name.Name] = t
2591                 case "struct":
2592                         g, csyntax, align := c.Struct(dt, pos)
2593                         if t.C.Empty() {
2594                                 t.C.Set(csyntax)
2595                         }
2596                         t.Align = align
2597                         tt := *t
2598                         if tag != "" {
2599                                 tt.C = &TypeRepr{"struct %s", []interface{}{tag}}
2600                         }
2601                         tt.Go = g
2602                         tt.NotInHeap = c.notInHeapStructs[tag]
2603                         typedef[name.Name] = &tt
2604                 }
2605
2606         case *dwarf.TypedefType:
2607                 // Record typedef for printing.
2608                 if dt.Name == "_GoString_" {
2609                         // Special C name for Go string type.
2610                         // Knows string layout used by compilers: pointer plus length,
2611                         // which rounds up to 2 pointers after alignment.
2612                         t.Go = c.string
2613                         t.Size = c.ptrSize * 2
2614                         t.Align = c.ptrSize
2615                         break
2616                 }
2617                 if dt.Name == "_GoBytes_" {
2618                         // Special C name for Go []byte type.
2619                         // Knows slice layout used by compilers: pointer, length, cap.
2620                         t.Go = c.Ident("[]byte")
2621                         t.Size = c.ptrSize + 4 + 4
2622                         t.Align = c.ptrSize
2623                         break
2624                 }
2625                 name := c.Ident("_Ctype_" + dt.Name)
2626                 goIdent[name.Name] = name
2627                 akey := ""
2628                 if c.anonymousStructTypedef(dt) {
2629                         // only load type recursively for typedefs of anonymous
2630                         // structs, see issues 37479 and 37621.
2631                         akey = key
2632                 }
2633                 sub := c.loadType(dt.Type, pos, akey)
2634                 if c.badPointerTypedef(dt) {
2635                         // Treat this typedef as a uintptr.
2636                         s := *sub
2637                         s.Go = c.uintptr
2638                         s.BadPointer = true
2639                         sub = &s
2640                         // Make sure we update any previously computed type.
2641                         if oldType := typedef[name.Name]; oldType != nil {
2642                                 oldType.Go = sub.Go
2643                                 oldType.BadPointer = true
2644                         }
2645                 }
2646                 if c.badVoidPointerTypedef(dt) {
2647                         // Treat this typedef as a pointer to a NotInHeap void.
2648                         s := *sub
2649                         s.Go = c.goVoidPtrNoHeap
2650                         sub = &s
2651                         // Make sure we update any previously computed type.
2652                         if oldType := typedef[name.Name]; oldType != nil {
2653                                 oldType.Go = sub.Go
2654                         }
2655                 }
2656                 // Check for non-pointer "struct <tag>{...}; typedef struct <tag> *<name>"
2657                 // typedefs that should be marked NotInHeap.
2658                 if ptr, ok := dt.Type.(*dwarf.PtrType); ok {
2659                         if strct, ok := ptr.Type.(*dwarf.StructType); ok {
2660                                 if c.badStructPointerTypedef(dt.Name, strct) {
2661                                         c.notInHeapStructs[strct.StructName] = true
2662                                         // Make sure we update any previously computed type.
2663                                         name := "_Ctype_struct_" + strct.StructName
2664                                         if oldType := typedef[name]; oldType != nil {
2665                                                 oldType.NotInHeap = true
2666                                         }
2667                                 }
2668                         }
2669                 }
2670                 t.Go = name
2671                 t.BadPointer = sub.BadPointer
2672                 t.NotInHeap = sub.NotInHeap
2673                 if unionWithPointer[sub.Go] {
2674                         unionWithPointer[t.Go] = true
2675                 }
2676                 t.Size = sub.Size
2677                 t.Align = sub.Align
2678                 oldType := typedef[name.Name]
2679                 if oldType == nil {
2680                         tt := *t
2681                         tt.Go = sub.Go
2682                         tt.BadPointer = sub.BadPointer
2683                         tt.NotInHeap = sub.NotInHeap
2684                         typedef[name.Name] = &tt
2685                 }
2686
2687                 // If sub.Go.Name is "_Ctype_struct_foo" or "_Ctype_union_foo" or "_Ctype_class_foo",
2688                 // use that as the Go form for this typedef too, so that the typedef will be interchangeable
2689                 // with the base type.
2690                 // In -godefs mode, do this for all typedefs.
2691                 if isStructUnionClass(sub.Go) || *godefs {
2692                         t.Go = sub.Go
2693
2694                         if isStructUnionClass(sub.Go) {
2695                                 // Use the typedef name for C code.
2696                                 typedef[sub.Go.(*ast.Ident).Name].C = t.C
2697                         }
2698
2699                         // If we've seen this typedef before, and it
2700                         // was an anonymous struct/union/class before
2701                         // too, use the old definition.
2702                         // TODO: it would be safer to only do this if
2703                         // we verify that the types are the same.
2704                         if oldType != nil && isStructUnionClass(oldType.Go) {
2705                                 t.Go = oldType.Go
2706                         }
2707                 }
2708
2709         case *dwarf.UcharType:
2710                 if t.Size != 1 {
2711                         fatalf("%s: unexpected: %d-byte uchar type - %s", lineno(pos), t.Size, dtype)
2712                 }
2713                 t.Go = c.uint8
2714                 t.Align = 1
2715
2716         case *dwarf.UintType:
2717                 if dt.BitSize > 0 {
2718                         fatalf("%s: unexpected: %d-bit uint type - %s", lineno(pos), dt.BitSize, dtype)
2719                 }
2720                 switch t.Size {
2721                 default:
2722                         fatalf("%s: unexpected: %d-byte uint type - %s", lineno(pos), t.Size, dtype)
2723                 case 1:
2724                         t.Go = c.uint8
2725                 case 2:
2726                         t.Go = c.uint16
2727                 case 4:
2728                         t.Go = c.uint32
2729                 case 8:
2730                         t.Go = c.uint64
2731                 case 16:
2732                         t.Go = &ast.ArrayType{
2733                                 Len: c.intExpr(t.Size),
2734                                 Elt: c.uint8,
2735                         }
2736                 }
2737                 if t.Align = t.Size; t.Align >= c.ptrSize {
2738                         t.Align = c.ptrSize
2739                 }
2740
2741         case *dwarf.VoidType:
2742                 t.Go = c.goVoid
2743                 t.C.Set("void")
2744                 t.Align = 1
2745         }
2746
2747         switch dtype.(type) {
2748         case *dwarf.AddrType, *dwarf.BoolType, *dwarf.CharType, *dwarf.ComplexType, *dwarf.IntType, *dwarf.FloatType, *dwarf.UcharType, *dwarf.UintType:
2749                 s := dtype.Common().Name
2750                 if s != "" {
2751                         if ss, ok := dwarfToName[s]; ok {
2752                                 s = ss
2753                         }
2754                         s = strings.Replace(s, " ", "", -1)
2755                         name := c.Ident("_Ctype_" + s)
2756                         tt := *t
2757                         typedef[name.Name] = &tt
2758                         if !*godefs {
2759                                 t.Go = name
2760                         }
2761                 }
2762         }
2763
2764         if t.Size < 0 {
2765                 // Unsized types are [0]byte, unless they're typedefs of other types
2766                 // or structs with tags.
2767                 // if so, use the name we've already defined.
2768                 t.Size = 0
2769                 switch dt := dtype.(type) {
2770                 case *dwarf.TypedefType:
2771                         // ok
2772                 case *dwarf.StructType:
2773                         if dt.StructName != "" {
2774                                 break
2775                         }
2776                         t.Go = c.Opaque(0)
2777                 default:
2778                         t.Go = c.Opaque(0)
2779                 }
2780                 if t.C.Empty() {
2781                         t.C.Set("void")
2782                 }
2783         }
2784
2785         if t.C.Empty() {
2786                 fatalf("%s: internal error: did not create C name for %s", lineno(pos), dtype)
2787         }
2788
2789         return t
2790 }
2791
2792 // isStructUnionClass reports whether the type described by the Go syntax x
2793 // is a struct, union, or class with a tag.
2794 func isStructUnionClass(x ast.Expr) bool {
2795         id, ok := x.(*ast.Ident)
2796         if !ok {
2797                 return false
2798         }
2799         name := id.Name
2800         return strings.HasPrefix(name, "_Ctype_struct_") ||
2801                 strings.HasPrefix(name, "_Ctype_union_") ||
2802                 strings.HasPrefix(name, "_Ctype_class_")
2803 }
2804
2805 // FuncArg returns a Go type with the same memory layout as
2806 // dtype when used as the type of a C function argument.
2807 func (c *typeConv) FuncArg(dtype dwarf.Type, pos token.Pos) *Type {
2808         t := c.Type(unqual(dtype), pos)
2809         switch dt := dtype.(type) {
2810         case *dwarf.ArrayType:
2811                 // Arrays are passed implicitly as pointers in C.
2812                 // In Go, we must be explicit.
2813                 tr := &TypeRepr{}
2814                 tr.Set("%s*", t.C)
2815                 return &Type{
2816                         Size:  c.ptrSize,
2817                         Align: c.ptrSize,
2818                         Go:    &ast.StarExpr{X: t.Go},
2819                         C:     tr,
2820                 }
2821         case *dwarf.TypedefType:
2822                 // C has much more relaxed rules than Go for
2823                 // implicit type conversions. When the parameter
2824                 // is type T defined as *X, simulate a little of the
2825                 // laxness of C by making the argument *X instead of T.
2826                 if ptr, ok := base(dt.Type).(*dwarf.PtrType); ok {
2827                         // Unless the typedef happens to point to void* since
2828                         // Go has special rules around using unsafe.Pointer.
2829                         if _, void := base(ptr.Type).(*dwarf.VoidType); void {
2830                                 break
2831                         }
2832                         // ...or the typedef is one in which we expect bad pointers.
2833                         // It will be a uintptr instead of *X.
2834                         if c.baseBadPointerTypedef(dt) {
2835                                 break
2836                         }
2837
2838                         t = c.Type(ptr, pos)
2839                         if t == nil {
2840                                 return nil
2841                         }
2842
2843                         // For a struct/union/class, remember the C spelling,
2844                         // in case it has __attribute__((unavailable)).
2845                         // See issue 2888.
2846                         if isStructUnionClass(t.Go) {
2847                                 t.Typedef = dt.Name
2848                         }
2849                 }
2850         }
2851         return t
2852 }
2853
2854 // FuncType returns the Go type analogous to dtype.
2855 // There is no guarantee about matching memory layout.
2856 func (c *typeConv) FuncType(dtype *dwarf.FuncType, pos token.Pos) *FuncType {
2857         p := make([]*Type, len(dtype.ParamType))
2858         gp := make([]*ast.Field, len(dtype.ParamType))
2859         for i, f := range dtype.ParamType {
2860                 // gcc's DWARF generator outputs a single DotDotDotType parameter for
2861                 // function pointers that specify no parameters (e.g. void
2862                 // (*__cgo_0)()).  Treat this special case as void. This case is
2863                 // invalid according to ISO C anyway (i.e. void (*__cgo_1)(...) is not
2864                 // legal).
2865                 if _, ok := f.(*dwarf.DotDotDotType); ok && i == 0 {
2866                         p, gp = nil, nil
2867                         break
2868                 }
2869                 p[i] = c.FuncArg(f, pos)
2870                 gp[i] = &ast.Field{Type: p[i].Go}
2871         }
2872         var r *Type
2873         var gr []*ast.Field
2874         if _, ok := base(dtype.ReturnType).(*dwarf.VoidType); ok {
2875                 gr = []*ast.Field{{Type: c.goVoid}}
2876         } else if dtype.ReturnType != nil {
2877                 r = c.Type(unqual(dtype.ReturnType), pos)
2878                 gr = []*ast.Field{{Type: r.Go}}
2879         }
2880         return &FuncType{
2881                 Params: p,
2882                 Result: r,
2883                 Go: &ast.FuncType{
2884                         Params:  &ast.FieldList{List: gp},
2885                         Results: &ast.FieldList{List: gr},
2886                 },
2887         }
2888 }
2889
2890 // Identifier
2891 func (c *typeConv) Ident(s string) *ast.Ident {
2892         return ast.NewIdent(s)
2893 }
2894
2895 // Opaque type of n bytes.
2896 func (c *typeConv) Opaque(n int64) ast.Expr {
2897         return &ast.ArrayType{
2898                 Len: c.intExpr(n),
2899                 Elt: c.byte,
2900         }
2901 }
2902
2903 // Expr for integer n.
2904 func (c *typeConv) intExpr(n int64) ast.Expr {
2905         return &ast.BasicLit{
2906                 Kind:  token.INT,
2907                 Value: strconv.FormatInt(n, 10),
2908         }
2909 }
2910
2911 // Add padding of given size to fld.
2912 func (c *typeConv) pad(fld []*ast.Field, sizes []int64, size int64) ([]*ast.Field, []int64) {
2913         n := len(fld)
2914         fld = fld[0 : n+1]
2915         fld[n] = &ast.Field{Names: []*ast.Ident{c.Ident("_")}, Type: c.Opaque(size)}
2916         sizes = sizes[0 : n+1]
2917         sizes[n] = size
2918         return fld, sizes
2919 }
2920
2921 // Struct conversion: return Go and (gc) C syntax for type.
2922 func (c *typeConv) Struct(dt *dwarf.StructType, pos token.Pos) (expr *ast.StructType, csyntax string, align int64) {
2923         // Minimum alignment for a struct is 1 byte.
2924         align = 1
2925
2926         var buf bytes.Buffer
2927         buf.WriteString("struct {")
2928         fld := make([]*ast.Field, 0, 2*len(dt.Field)+1) // enough for padding around every field
2929         sizes := make([]int64, 0, 2*len(dt.Field)+1)
2930         off := int64(0)
2931
2932         // Rename struct fields that happen to be named Go keywords into
2933         // _{keyword}.  Create a map from C ident -> Go ident. The Go ident will
2934         // be mangled. Any existing identifier that already has the same name on
2935         // the C-side will cause the Go-mangled version to be prefixed with _.
2936         // (e.g. in a struct with fields '_type' and 'type', the latter would be
2937         // rendered as '__type' in Go).
2938         ident := make(map[string]string)
2939         used := make(map[string]bool)
2940         for _, f := range dt.Field {
2941                 ident[f.Name] = f.Name
2942                 used[f.Name] = true
2943         }
2944
2945         if !*godefs {
2946                 for cid, goid := range ident {
2947                         if token.Lookup(goid).IsKeyword() {
2948                                 // Avoid keyword
2949                                 goid = "_" + goid
2950
2951                                 // Also avoid existing fields
2952                                 for _, exist := used[goid]; exist; _, exist = used[goid] {
2953                                         goid = "_" + goid
2954                                 }
2955
2956                                 used[goid] = true
2957                                 ident[cid] = goid
2958                         }
2959                 }
2960         }
2961
2962         anon := 0
2963         for _, f := range dt.Field {
2964                 name := f.Name
2965                 ft := f.Type
2966
2967                 // In godefs mode, if this field is a C11
2968                 // anonymous union then treat the first field in the
2969                 // union as the field in the struct. This handles
2970                 // cases like the glibc <sys/resource.h> file; see
2971                 // issue 6677.
2972                 if *godefs {
2973                         if st, ok := f.Type.(*dwarf.StructType); ok && name == "" && st.Kind == "union" && len(st.Field) > 0 && !used[st.Field[0].Name] {
2974                                 name = st.Field[0].Name
2975                                 ident[name] = name
2976                                 ft = st.Field[0].Type
2977                         }
2978                 }
2979
2980                 // TODO: Handle fields that are anonymous structs by
2981                 // promoting the fields of the inner struct.
2982
2983                 t := c.Type(ft, pos)
2984                 tgo := t.Go
2985                 size := t.Size
2986                 talign := t.Align
2987                 if f.BitOffset > 0 || f.BitSize > 0 {
2988                         // The layout of bitfields is implementation defined,
2989                         // so we don't know how they correspond to Go fields
2990                         // even if they are aligned at byte boundaries.
2991                         continue
2992                 }
2993
2994                 if talign > 0 && f.ByteOffset%talign != 0 {
2995                         // Drop misaligned fields, the same way we drop integer bit fields.
2996                         // The goal is to make available what can be made available.
2997                         // Otherwise one bad and unneeded field in an otherwise okay struct
2998                         // makes the whole program not compile. Much of the time these
2999                         // structs are in system headers that cannot be corrected.
3000                         continue
3001                 }
3002
3003                 // Round off up to talign, assumed to be a power of 2.
3004                 off = (off + talign - 1) &^ (talign - 1)
3005
3006                 if f.ByteOffset > off {
3007                         fld, sizes = c.pad(fld, sizes, f.ByteOffset-off)
3008                         off = f.ByteOffset
3009                 }
3010                 if f.ByteOffset < off {
3011                         // Drop a packed field that we can't represent.
3012                         continue
3013                 }
3014
3015                 n := len(fld)
3016                 fld = fld[0 : n+1]
3017                 if name == "" {
3018                         name = fmt.Sprintf("anon%d", anon)
3019                         anon++
3020                         ident[name] = name
3021                 }
3022                 fld[n] = &ast.Field{Names: []*ast.Ident{c.Ident(ident[name])}, Type: tgo}
3023                 sizes = sizes[0 : n+1]
3024                 sizes[n] = size
3025                 off += size
3026                 buf.WriteString(t.C.String())
3027                 buf.WriteString(" ")
3028                 buf.WriteString(name)
3029                 buf.WriteString("; ")
3030                 if talign > align {
3031                         align = talign
3032                 }
3033         }
3034         if off < dt.ByteSize {
3035                 fld, sizes = c.pad(fld, sizes, dt.ByteSize-off)
3036                 off = dt.ByteSize
3037         }
3038
3039         // If the last field in a non-zero-sized struct is zero-sized
3040         // the compiler is going to pad it by one (see issue 9401).
3041         // We can't permit that, because then the size of the Go
3042         // struct will not be the same as the size of the C struct.
3043         // Our only option in such a case is to remove the field,
3044         // which means that it cannot be referenced from Go.
3045         for off > 0 && sizes[len(sizes)-1] == 0 {
3046                 n := len(sizes)
3047                 fld = fld[0 : n-1]
3048                 sizes = sizes[0 : n-1]
3049         }
3050
3051         if off != dt.ByteSize {
3052                 fatalf("%s: struct size calculation error off=%d bytesize=%d", lineno(pos), off, dt.ByteSize)
3053         }
3054         buf.WriteString("}")
3055         csyntax = buf.String()
3056
3057         if *godefs {
3058                 godefsFields(fld)
3059         }
3060         expr = &ast.StructType{Fields: &ast.FieldList{List: fld}}
3061         return
3062 }
3063
3064 // dwarfHasPointer reports whether the DWARF type dt contains a pointer.
3065 func (c *typeConv) dwarfHasPointer(dt dwarf.Type, pos token.Pos) bool {
3066         switch dt := dt.(type) {
3067         default:
3068                 fatalf("%s: unexpected type: %s", lineno(pos), dt)
3069                 return false
3070
3071         case *dwarf.AddrType, *dwarf.BoolType, *dwarf.CharType, *dwarf.EnumType,
3072                 *dwarf.FloatType, *dwarf.ComplexType, *dwarf.FuncType,
3073                 *dwarf.IntType, *dwarf.UcharType, *dwarf.UintType, *dwarf.VoidType:
3074
3075                 return false
3076
3077         case *dwarf.ArrayType:
3078                 return c.dwarfHasPointer(dt.Type, pos)
3079
3080         case *dwarf.PtrType:
3081                 return true
3082
3083         case *dwarf.QualType:
3084                 return c.dwarfHasPointer(dt.Type, pos)
3085
3086         case *dwarf.StructType:
3087                 for _, f := range dt.Field {
3088                         if c.dwarfHasPointer(f.Type, pos) {
3089                                 return true
3090                         }
3091                 }
3092                 return false
3093
3094         case *dwarf.TypedefType:
3095                 if dt.Name == "_GoString_" || dt.Name == "_GoBytes_" {
3096                         return true
3097                 }
3098                 return c.dwarfHasPointer(dt.Type, pos)
3099         }
3100 }
3101
3102 func upper(s string) string {
3103         if s == "" {
3104                 return ""
3105         }
3106         r, size := utf8.DecodeRuneInString(s)
3107         if r == '_' {
3108                 return "X" + s
3109         }
3110         return string(unicode.ToUpper(r)) + s[size:]
3111 }
3112
3113 // godefsFields rewrites field names for use in Go or C definitions.
3114 // It strips leading common prefixes (like tv_ in tv_sec, tv_usec)
3115 // converts names to upper case, and rewrites _ into Pad_godefs_n,
3116 // so that all fields are exported.
3117 func godefsFields(fld []*ast.Field) {
3118         prefix := fieldPrefix(fld)
3119
3120         // Issue 48396: check for duplicate field names.
3121         if prefix != "" {
3122                 names := make(map[string]bool)
3123         fldLoop:
3124                 for _, f := range fld {
3125                         for _, n := range f.Names {
3126                                 name := n.Name
3127                                 if name == "_" {
3128                                         continue
3129                                 }
3130                                 if name != prefix {
3131                                         name = strings.TrimPrefix(n.Name, prefix)
3132                                 }
3133                                 name = upper(name)
3134                                 if names[name] {
3135                                         // Field name conflict: don't remove prefix.
3136                                         prefix = ""
3137                                         break fldLoop
3138                                 }
3139                                 names[name] = true
3140                         }
3141                 }
3142         }
3143
3144         npad := 0
3145         for _, f := range fld {
3146                 for _, n := range f.Names {
3147                         if n.Name != prefix {
3148                                 n.Name = strings.TrimPrefix(n.Name, prefix)
3149                         }
3150                         if n.Name == "_" {
3151                                 // Use exported name instead.
3152                                 n.Name = "Pad_cgo_" + strconv.Itoa(npad)
3153                                 npad++
3154                         }
3155                         n.Name = upper(n.Name)
3156                 }
3157         }
3158 }
3159
3160 // fieldPrefix returns the prefix that should be removed from all the
3161 // field names when generating the C or Go code. For generated
3162 // C, we leave the names as is (tv_sec, tv_usec), since that's what
3163 // people are used to seeing in C.  For generated Go code, such as
3164 // package syscall's data structures, we drop a common prefix
3165 // (so sec, usec, which will get turned into Sec, Usec for exporting).
3166 func fieldPrefix(fld []*ast.Field) string {
3167         prefix := ""
3168         for _, f := range fld {
3169                 for _, n := range f.Names {
3170                         // Ignore field names that don't have the prefix we're
3171                         // looking for. It is common in C headers to have fields
3172                         // named, say, _pad in an otherwise prefixed header.
3173                         // If the struct has 3 fields tv_sec, tv_usec, _pad1, then we
3174                         // still want to remove the tv_ prefix.
3175                         // The check for "orig_" here handles orig_eax in the
3176                         // x86 ptrace register sets, which otherwise have all fields
3177                         // with reg_ prefixes.
3178                         if strings.HasPrefix(n.Name, "orig_") || strings.HasPrefix(n.Name, "_") {
3179                                 continue
3180                         }
3181                         i := strings.Index(n.Name, "_")
3182                         if i < 0 {
3183                                 continue
3184                         }
3185                         if prefix == "" {
3186                                 prefix = n.Name[:i+1]
3187                         } else if prefix != n.Name[:i+1] {
3188                                 return ""
3189                         }
3190                 }
3191         }
3192         return prefix
3193 }
3194
3195 // anonymousStructTypedef reports whether dt is a C typedef for an anonymous
3196 // struct.
3197 func (c *typeConv) anonymousStructTypedef(dt *dwarf.TypedefType) bool {
3198         st, ok := dt.Type.(*dwarf.StructType)
3199         return ok && st.StructName == ""
3200 }
3201
3202 // badPointerTypedef reports whether dt is a C typedef that should not be
3203 // considered a pointer in Go. A typedef is bad if C code sometimes stores
3204 // non-pointers in this type.
3205 // TODO: Currently our best solution is to find these manually and list them as
3206 // they come up. A better solution is desired.
3207 // Note: DEPRECATED. There is now a better solution. Search for NotInHeap in this file.
3208 func (c *typeConv) badPointerTypedef(dt *dwarf.TypedefType) bool {
3209         if c.badCFType(dt) {
3210                 return true
3211         }
3212         if c.badJNI(dt) {
3213                 return true
3214         }
3215         if c.badEGLType(dt) {
3216                 return true
3217         }
3218         return false
3219 }
3220
3221 // badVoidPointerTypedef is like badPointerTypeDef, but for "void *" typedefs that should be NotInHeap.
3222 func (c *typeConv) badVoidPointerTypedef(dt *dwarf.TypedefType) bool {
3223         // Match the Windows HANDLE type (#42018).
3224         if goos != "windows" || dt.Name != "HANDLE" {
3225                 return false
3226         }
3227         // Check that the typedef is "typedef void *<name>".
3228         if ptr, ok := dt.Type.(*dwarf.PtrType); ok {
3229                 if _, ok := ptr.Type.(*dwarf.VoidType); ok {
3230                         return true
3231                 }
3232         }
3233         return false
3234 }
3235
3236 // badStructPointerTypedef is like badVoidPointerTypedefs but for structs.
3237 func (c *typeConv) badStructPointerTypedef(name string, dt *dwarf.StructType) bool {
3238         // Windows handle types can all potentially contain non-pointers.
3239         // badVoidPointerTypedef handles the "void *" HANDLE type, but other
3240         // handles are defined as
3241         //
3242         // struct <name>__{int unused;}; typedef struct <name>__ *name;
3243         //
3244         // by the DECLARE_HANDLE macro in STRICT mode. The macro is declared in
3245         // the Windows ntdef.h header,
3246         //
3247         // https://github.com/tpn/winsdk-10/blob/master/Include/10.0.16299.0/shared/ntdef.h#L779
3248         if goos != "windows" {
3249                 return false
3250         }
3251         if len(dt.Field) != 1 {
3252                 return false
3253         }
3254         if dt.StructName != name+"__" {
3255                 return false
3256         }
3257         if f := dt.Field[0]; f.Name != "unused" || f.Type.Common().Name != "int" {
3258                 return false
3259         }
3260         return true
3261 }
3262
3263 // baseBadPointerTypedef reports whether the base of a chain of typedefs is a bad typedef
3264 // as badPointerTypedef reports.
3265 func (c *typeConv) baseBadPointerTypedef(dt *dwarf.TypedefType) bool {
3266         for {
3267                 if t, ok := dt.Type.(*dwarf.TypedefType); ok {
3268                         dt = t
3269                         continue
3270                 }
3271                 break
3272         }
3273         return c.badPointerTypedef(dt)
3274 }
3275
3276 func (c *typeConv) badCFType(dt *dwarf.TypedefType) bool {
3277         // The real bad types are CFNumberRef and CFDateRef.
3278         // Sometimes non-pointers are stored in these types.
3279         // CFTypeRef is a supertype of those, so it can have bad pointers in it as well.
3280         // We return true for the other *Ref types just so casting between them is easier.
3281         // We identify the correct set of types as those ending in Ref and for which
3282         // there exists a corresponding GetTypeID function.
3283         // See comment below for details about the bad pointers.
3284         if goos != "darwin" && goos != "ios" {
3285                 return false
3286         }
3287         s := dt.Name
3288         if !strings.HasSuffix(s, "Ref") {
3289                 return false
3290         }
3291         s = s[:len(s)-3]
3292         if s == "CFType" {
3293                 return true
3294         }
3295         if c.getTypeIDs[s] {
3296                 return true
3297         }
3298         if i := strings.Index(s, "Mutable"); i >= 0 && c.getTypeIDs[s[:i]+s[i+7:]] {
3299                 // Mutable and immutable variants share a type ID.
3300                 return true
3301         }
3302         return false
3303 }
3304
3305 // Comment from Darwin's CFInternal.h
3306 /*
3307 // Tagged pointer support
3308 // Low-bit set means tagged object, next 3 bits (currently)
3309 // define the tagged object class, next 4 bits are for type
3310 // information for the specific tagged object class.  Thus,
3311 // the low byte is for type info, and the rest of a pointer
3312 // (32 or 64-bit) is for payload, whatever the tagged class.
3313 //
3314 // Note that the specific integers used to identify the
3315 // specific tagged classes can and will change from release
3316 // to release (that's why this stuff is in CF*Internal*.h),
3317 // as can the definition of type info vs payload above.
3318 //
3319 #if __LP64__
3320 #define CF_IS_TAGGED_OBJ(PTR)   ((uintptr_t)(PTR) & 0x1)
3321 #define CF_TAGGED_OBJ_TYPE(PTR) ((uintptr_t)(PTR) & 0xF)
3322 #else
3323 #define CF_IS_TAGGED_OBJ(PTR)   0
3324 #define CF_TAGGED_OBJ_TYPE(PTR) 0
3325 #endif
3326
3327 enum {
3328     kCFTaggedObjectID_Invalid = 0,
3329     kCFTaggedObjectID_Atom = (0 << 1) + 1,
3330     kCFTaggedObjectID_Undefined3 = (1 << 1) + 1,
3331     kCFTaggedObjectID_Undefined2 = (2 << 1) + 1,
3332     kCFTaggedObjectID_Integer = (3 << 1) + 1,
3333     kCFTaggedObjectID_DateTS = (4 << 1) + 1,
3334     kCFTaggedObjectID_ManagedObjectID = (5 << 1) + 1, // Core Data
3335     kCFTaggedObjectID_Date = (6 << 1) + 1,
3336     kCFTaggedObjectID_Undefined7 = (7 << 1) + 1,
3337 };
3338 */
3339
3340 func (c *typeConv) badJNI(dt *dwarf.TypedefType) bool {
3341         // In Dalvik and ART, the jobject type in the JNI interface of the JVM has the
3342         // property that it is sometimes (always?) a small integer instead of a real pointer.
3343         // Note: although only the android JVMs are bad in this respect, we declare the JNI types
3344         // bad regardless of platform, so the same Go code compiles on both android and non-android.
3345         if parent, ok := jniTypes[dt.Name]; ok {
3346                 // Try to make sure we're talking about a JNI type, not just some random user's
3347                 // type that happens to use the same name.
3348                 // C doesn't have the notion of a package, so it's hard to be certain.
3349
3350                 // Walk up to jobject, checking each typedef on the way.
3351                 w := dt
3352                 for parent != "" {
3353                         t, ok := w.Type.(*dwarf.TypedefType)
3354                         if !ok || t.Name != parent {
3355                                 return false
3356                         }
3357                         w = t
3358                         parent, ok = jniTypes[w.Name]
3359                         if !ok {
3360                                 return false
3361                         }
3362                 }
3363
3364                 // Check that the typedef is either:
3365                 // 1:
3366                 //      struct _jobject;
3367                 //      typedef struct _jobject *jobject;
3368                 // 2: (in NDK16 in C++)
3369                 //      class _jobject {};
3370                 //      typedef _jobject* jobject;
3371                 // 3: (in NDK16 in C)
3372                 //      typedef void* jobject;
3373                 if ptr, ok := w.Type.(*dwarf.PtrType); ok {
3374                         switch v := ptr.Type.(type) {
3375                         case *dwarf.VoidType:
3376                                 return true
3377                         case *dwarf.StructType:
3378                                 if v.StructName == "_jobject" && len(v.Field) == 0 {
3379                                         switch v.Kind {
3380                                         case "struct":
3381                                                 if v.Incomplete {
3382                                                         return true
3383                                                 }
3384                                         case "class":
3385                                                 if !v.Incomplete {
3386                                                         return true
3387                                                 }
3388                                         }
3389                                 }
3390                         }
3391                 }
3392         }
3393         return false
3394 }
3395
3396 func (c *typeConv) badEGLType(dt *dwarf.TypedefType) bool {
3397         if dt.Name != "EGLDisplay" && dt.Name != "EGLConfig" {
3398                 return false
3399         }
3400         // Check that the typedef is "typedef void *<name>".
3401         if ptr, ok := dt.Type.(*dwarf.PtrType); ok {
3402                 if _, ok := ptr.Type.(*dwarf.VoidType); ok {
3403                         return true
3404                 }
3405         }
3406         return false
3407 }
3408
3409 // jniTypes maps from JNI types that we want to be uintptrs, to the underlying type to which
3410 // they are mapped. The base "jobject" maps to the empty string.
3411 var jniTypes = map[string]string{
3412         "jobject":       "",
3413         "jclass":        "jobject",
3414         "jthrowable":    "jobject",
3415         "jstring":       "jobject",
3416         "jarray":        "jobject",
3417         "jbooleanArray": "jarray",
3418         "jbyteArray":    "jarray",
3419         "jcharArray":    "jarray",
3420         "jshortArray":   "jarray",
3421         "jintArray":     "jarray",
3422         "jlongArray":    "jarray",
3423         "jfloatArray":   "jarray",
3424         "jdoubleArray":  "jarray",
3425         "jobjectArray":  "jarray",
3426         "jweak":         "jobject",
3427 }