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.
5 // Annotate Ref in Prog with C types by parsing gcc debug output.
6 // Conversion of debug output to Go types.
35 var debugDefine = flag.Bool("debug-define", false, "print relevant #defines")
36 var debugGcc = flag.Bool("debug-gcc", false, "print gcc invocations")
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",
50 var incomplete = "_cgopackage.Incomplete"
52 // cname returns the C name to use for C.s.
53 // The expansions are listed in nameToC and also
54 // struct_foo becomes "struct foo", and similarly for
56 func cname(s string) string {
57 if t, ok := nameToC[s]; ok {
61 if strings.HasPrefix(s, "struct_") {
62 return "struct " + s[len("struct_"):]
64 if strings.HasPrefix(s, "union_") {
65 return "union " + s[len("union_"):]
67 if strings.HasPrefix(s, "enum_") {
68 return "enum " + s[len("enum_"):]
70 if strings.HasPrefix(s, "sizeof_") {
71 return "sizeof(" + cname(s[len("sizeof_"):]) + ")"
76 // ProcessCgoDirectives processes the import C preamble:
77 // 1. discards all #cgo CFLAGS, LDFLAGS, nocallback and noescape directives,
78 // so they don't make their way into _cgo_export.h.
79 // 2. parse the nocallback and noescape directives.
80 func (f *File) ProcessCgoDirectives() {
81 linesIn := strings.Split(f.Preamble, "\n")
82 linesOut := make([]string, 0, len(linesIn))
83 f.NoCallbacks = make(map[string]bool)
84 f.NoEscapes = make(map[string]bool)
85 for _, line := range linesIn {
86 l := strings.TrimSpace(line)
87 if len(l) < 5 || l[:4] != "#cgo" || !unicode.IsSpace(rune(l[4])) {
88 linesOut = append(linesOut, line)
90 linesOut = append(linesOut, "")
92 // #cgo (nocallback|noescape) <function name>
93 if fields := strings.Fields(l); len(fields) == 3 {
94 directive := fields[1]
96 if directive == "nocallback" {
97 fatalf("#cgo nocallback disabled until Go 1.23")
98 f.NoCallbacks[funcName] = true
99 } else if directive == "noescape" {
100 fatalf("#cgo noescape disabled until Go 1.23")
101 f.NoEscapes[funcName] = true
106 f.Preamble = strings.Join(linesOut, "\n")
109 // addToFlag appends args to flag.
110 func (p *Package) addToFlag(flag string, args []string) {
111 if flag == "CFLAGS" {
112 // We'll also need these when preprocessing for dwarf information.
113 // However, discard any -g options: we need to be able
114 // to parse the debug info, so stick to what we expect.
115 for _, arg := range args {
116 if !strings.HasPrefix(arg, "-g") {
117 p.GccOptions = append(p.GccOptions, arg)
121 if flag == "LDFLAGS" {
122 p.LdFlags = append(p.LdFlags, args...)
126 // splitQuoted splits the string s around each instance of one or more consecutive
127 // white space characters while taking into account quotes and escaping, and
128 // returns an array of substrings of s or an empty list if s contains only white space.
129 // Single quotes and double quotes are recognized to prevent splitting within the
130 // quoted region, and are removed from the resulting substrings. If a quote in s
131 // isn't closed err will be set and r will have the unclosed argument as the
132 // last element. The backslash is used for escaping.
134 // For example, the following string:
136 // `a b:"c d" 'e''f' "g\""`
138 // Would be parsed as:
140 // []string{"a", "b:c d", "ef", `g"`}
141 func splitQuoted(s string) (r []string, err error) {
143 arg := make([]rune, len(s))
148 for _, r := range s {
160 case r == '"' || r == '\'':
164 case unicode.IsSpace(r):
167 args = append(args, string(arg[:i]))
176 args = append(args, string(arg[:i]))
179 err = errors.New("unclosed quote")
181 err = errors.New("unfinished escaping")
186 // Translate rewrites f.AST, the original Go input, to remove
187 // references to the imported package C, replacing them with
188 // references to the equivalent Go types, functions, and variables.
189 func (p *Package) Translate(f *File) {
190 for _, cref := range f.Ref {
191 // Convert C.ulong to C.unsigned long, etc.
192 cref.Name.C = cname(cref.Name.Go)
196 conv.Init(p.PtrSize, p.IntSize)
199 p.typedefs = map[string]bool{}
202 for len(p.typedefs) > numTypedefs {
203 numTypedefs = len(p.typedefs)
204 // Also ask about any typedefs we've seen so far.
205 for _, info := range p.typedefList {
206 if f.Name[info.typedef] != nil {
213 f.Name[info.typedef] = n
214 f.NamePos[n] = info.pos
216 needType := p.guessKinds(f)
217 if len(needType) > 0 {
218 p.loadDWARF(f, &conv, needType)
221 // In godefs mode we're OK with the typedefs, which
222 // will presumably also be defined in the file, we
223 // don't want to resolve them to their base types.
229 if p.rewriteCalls(f) {
230 // Add `import _cgo_unsafe "unsafe"` after the package statement.
231 f.Edit.Insert(f.offset(f.AST.Name.End()), "; import _cgo_unsafe \"unsafe\"")
236 // loadDefines coerces gcc into spitting out the #defines in use
237 // in the file f and saves relevant renamings in f.Name[name].Define.
238 func (p *Package) loadDefines(f *File) {
240 b.WriteString(builtinProlog)
241 b.WriteString(f.Preamble)
242 stdout := p.gccDefines(b.Bytes())
244 for _, line := range strings.Split(stdout, "\n") {
245 if len(line) < 9 || line[0:7] != "#define" {
249 line = strings.TrimSpace(line[8:])
252 spaceIndex := strings.Index(line, " ")
253 tabIndex := strings.Index(line, "\t")
255 if spaceIndex == -1 && tabIndex == -1 {
257 } else if tabIndex == -1 || (spaceIndex != -1 && spaceIndex < tabIndex) {
258 key = line[0:spaceIndex]
259 val = strings.TrimSpace(line[spaceIndex:])
261 key = line[0:tabIndex]
262 val = strings.TrimSpace(line[tabIndex:])
265 if key == "__clang__" {
269 if n := f.Name[key]; n != nil {
271 fmt.Fprintf(os.Stderr, "#define %s %s\n", key, val)
278 // guessKinds tricks gcc into revealing the kind of each
279 // name xxx for the references C.xxx in the Go input.
280 // The kind is either a constant, type, or variable.
281 func (p *Package) guessKinds(f *File) []*Name {
282 // Determine kinds for names we already know about,
283 // like #defines or 'struct foo', before bothering with gcc.
284 var names, needType []*Name
285 optional := map[*Name]bool{}
286 for _, key := range nameKeys(f.Name) {
288 // If we've already found this name as a #define
289 // and we can translate it as a constant value, do so.
291 if i, err := strconv.ParseInt(n.Define, 0, 64); err == nil {
293 // Turn decimal into hex, just for consistency
294 // with enum-derived constants. Otherwise
295 // in the cgo -godefs output half the constants
296 // are in hex and half are in whatever the #define used.
297 n.Const = fmt.Sprintf("%#x", i)
298 } else if n.Define[0] == '\'' {
299 if _, err := parser.ParseExpr(n.Define); err == nil {
303 } else if n.Define[0] == '"' {
304 if _, err := parser.ParseExpr(n.Define); err == nil {
315 // If this is a struct, union, or enum type name, no need to guess the kind.
316 if strings.HasPrefix(n.C, "struct ") || strings.HasPrefix(n.C, "union ") || strings.HasPrefix(n.C, "enum ") {
318 needType = append(needType, n)
322 if (goos == "darwin" || goos == "ios") && strings.HasSuffix(n.C, "Ref") {
323 // For FooRef, find out if FooGetTypeID exists.
324 s := n.C[:len(n.C)-3] + "GetTypeID"
325 n := &Name{Go: s, C: s}
326 names = append(names, n)
330 // Otherwise, we'll need to find out from gcc.
331 names = append(names, n)
334 // Bypass gcc if there's nothing left to find out.
339 // Coerce gcc into telling us whether each name is a type, a value, or undeclared.
340 // For names, find out whether they are integer constants.
341 // We used to look at specific warning or error messages here, but that tied the
342 // behavior too closely to specific versions of the compilers.
343 // Instead, arrange that we can infer what we need from only the presence or absence
344 // of an error on a specific line.
346 // For each name, we generate these lines, where xxx is the index in toSniff plus one.
348 // #line xxx "not-declared"
349 // void __cgo_f_xxx_1(void) { __typeof__(name) *__cgo_undefined__1; }
350 // #line xxx "not-type"
351 // void __cgo_f_xxx_2(void) { name *__cgo_undefined__2; }
352 // #line xxx "not-int-const"
353 // void __cgo_f_xxx_3(void) { enum { __cgo_undefined__3 = (name)*1 }; }
354 // #line xxx "not-num-const"
355 // void __cgo_f_xxx_4(void) { static const double __cgo_undefined__4 = (name); }
356 // #line xxx "not-str-lit"
357 // void __cgo_f_xxx_5(void) { static const char __cgo_undefined__5[] = (name); }
359 // If we see an error at not-declared:xxx, the corresponding name is not declared.
360 // If we see an error at not-type:xxx, the corresponding name is not a type.
361 // If we see an error at not-int-const:xxx, the corresponding name is not an integer constant.
362 // If we see an error at not-num-const:xxx, the corresponding name is not a number constant.
363 // If we see an error at not-str-lit:xxx, the corresponding name is not a string literal.
365 // The specific input forms are chosen so that they are valid C syntax regardless of
366 // whether name denotes a type or an expression.
369 b.WriteString(builtinProlog)
370 b.WriteString(f.Preamble)
372 for i, n := range names {
373 fmt.Fprintf(&b, "#line %d \"not-declared\"\n"+
374 "void __cgo_f_%d_1(void) { __typeof__(%s) *__cgo_undefined__1; }\n"+
375 "#line %d \"not-type\"\n"+
376 "void __cgo_f_%d_2(void) { %s *__cgo_undefined__2; }\n"+
377 "#line %d \"not-int-const\"\n"+
378 "void __cgo_f_%d_3(void) { enum { __cgo_undefined__3 = (%s)*1 }; }\n"+
379 "#line %d \"not-num-const\"\n"+
380 "void __cgo_f_%d_4(void) { static const double __cgo_undefined__4 = (%s); }\n"+
381 "#line %d \"not-str-lit\"\n"+
382 "void __cgo_f_%d_5(void) { static const char __cgo_undefined__5[] = (%s); }\n",
390 fmt.Fprintf(&b, "#line 1 \"completed\"\n"+
391 "int __cgo__1 = __cgo__2;\n")
393 // We need to parse the output from this gcc command, so ensure that it
394 // doesn't have any ANSI escape sequences in it. (TERM=dumb is
395 // insufficient; if the user specifies CGO_CFLAGS=-fdiagnostics-color,
396 // GCC will ignore TERM, and GCC can also be configured at compile-time
398 stderr := p.gccErrors(b.Bytes(), "-fdiagnostics-color=never")
399 if strings.Contains(stderr, "unrecognized command line option") {
400 // We're using an old version of GCC that doesn't understand
401 // -fdiagnostics-color. Those versions can't print color anyway,
402 // so just rerun without that option.
403 stderr = p.gccErrors(b.Bytes())
406 fatalf("%s produced no output\non input:\n%s", gccBaseCmd[0], b.Bytes())
410 sniff := make([]int, len(names))
418 sawUnmatchedErrors := false
419 for _, line := range strings.Split(stderr, "\n") {
420 // Ignore warnings and random comments, with one
421 // exception: newer GCC versions will sometimes emit
422 // an error on a macro #define with a note referring
423 // to where the expansion occurs. We care about where
424 // the expansion occurs, so in that case treat the note
426 isError := strings.Contains(line, ": error:")
427 isErrorNote := strings.Contains(line, ": note:") && sawUnmatchedErrors
428 if !isError && !isErrorNote {
432 c1 := strings.Index(line, ":")
436 c2 := strings.Index(line[c1+1:], ":")
442 filename := line[:c1]
443 i, _ := strconv.Atoi(line[c1+1 : c2])
445 if i < 0 || i >= len(names) {
447 sawUnmatchedErrors = true
454 // Strictly speaking, there is no guarantee that seeing the error at completed:1
455 // (at the end of the file) means we've seen all the errors from earlier in the file,
456 // but usually it does. Certainly if we don't see the completed:1 error, we did
457 // not get all the errors we expected.
461 sniff[i] |= notDeclared
464 case "not-int-const":
465 sniff[i] |= notIntConst
466 case "not-num-const":
467 sniff[i] |= notNumConst
469 sniff[i] |= notStrLiteral
472 sawUnmatchedErrors = true
477 sawUnmatchedErrors = false
481 fatalf("%s did not produce error at completed:1\non input:\n%s\nfull error output:\n%s", gccBaseCmd[0], b.Bytes(), stderr)
484 for i, n := range names {
487 if sniff[i]¬Declared != 0 && optional[n] {
488 // Ignore optional undeclared identifiers.
489 // Don't report an error, and skip adding n to the needType array.
492 error_(f.NamePos[n], "could not determine kind of name for C.%s", fixGo(n.Go))
493 case notStrLiteral | notType:
495 case notIntConst | notStrLiteral | notType:
497 case notIntConst | notNumConst | notType:
499 case notIntConst | notNumConst | notStrLiteral:
501 case notIntConst | notNumConst | notStrLiteral | notType:
504 needType = append(needType, n)
507 // Check if compiling the preamble by itself causes any errors,
508 // because the messages we've printed out so far aren't helpful
509 // to users debugging preamble mistakes. See issue 8442.
510 preambleErrors := p.gccErrors([]byte(builtinProlog + f.Preamble))
511 if len(preambleErrors) > 0 {
512 error_(token.NoPos, "\n%s errors for preamble:\n%s", gccBaseCmd[0], preambleErrors)
515 fatalf("unresolved names")
521 // loadDWARF parses the DWARF debug information generated
522 // by gcc to learn the details of the constants, variables, and types
523 // being referred to as C.xxx.
524 func (p *Package) loadDWARF(f *File, conv *typeConv, names []*Name) {
525 // Extract the types from the DWARF section of an object
526 // from a well-formed C program. Gcc only generates DWARF info
527 // for symbols in the object file, so it is not enough to print the
528 // preamble and hope the symbols we care about will be there.
530 // __typeof__(names[i]) *__cgo__i;
531 // for each entry in names and then dereference the type we
532 // learn for __cgo__i.
534 b.WriteString(builtinProlog)
535 b.WriteString(f.Preamble)
536 b.WriteString("#line 1 \"cgo-dwarf-inference\"\n")
537 for i, n := range names {
538 fmt.Fprintf(&b, "__typeof__(%s) *__cgo__%d;\n", n.C, i)
539 if n.Kind == "iconst" {
540 fmt.Fprintf(&b, "enum { __cgo_enum__%d = %s };\n", i, n.C)
544 // We create a data block initialized with the values,
545 // so we can read them out of the object file.
546 fmt.Fprintf(&b, "long long __cgodebug_ints[] = {\n")
547 for _, n := range names {
548 if n.Kind == "iconst" {
549 fmt.Fprintf(&b, "\t%s,\n", n.C)
551 fmt.Fprintf(&b, "\t0,\n")
554 // for the last entry, we cannot use 0, otherwise
555 // in case all __cgodebug_data is zero initialized,
556 // LLVM-based gcc will place the it in the __DATA.__common
557 // zero-filled section (our debug/macho doesn't support
559 fmt.Fprintf(&b, "\t1\n")
560 fmt.Fprintf(&b, "};\n")
562 // do the same work for floats.
563 fmt.Fprintf(&b, "double __cgodebug_floats[] = {\n")
564 for _, n := range names {
565 if n.Kind == "fconst" {
566 fmt.Fprintf(&b, "\t%s,\n", n.C)
568 fmt.Fprintf(&b, "\t0,\n")
571 fmt.Fprintf(&b, "\t1\n")
572 fmt.Fprintf(&b, "};\n")
574 // do the same work for strings.
575 for i, n := range names {
576 if n.Kind == "sconst" {
577 fmt.Fprintf(&b, "const char __cgodebug_str__%d[] = %s;\n", i, n.C)
578 fmt.Fprintf(&b, "const unsigned long long __cgodebug_strlen__%d = sizeof(%s)-1;\n", i, n.C)
582 d, ints, floats, strs := p.gccDebug(b.Bytes(), len(names))
584 // Scan DWARF info for top-level TagVariable entries with AttrName __cgo__i.
585 types := make([]dwarf.Type, len(names))
590 fatalf("reading DWARF entry: %s", err)
596 case dwarf.TagVariable:
597 name, _ := e.Val(dwarf.AttrName).(string)
598 // As of https://reviews.llvm.org/D123534, clang
599 // now emits DW_TAG_variable DIEs that have
600 // no name (so as to be able to describe the
601 // type and source locations of constant strings)
602 // like the second arg in the call below:
604 // myfunction(42, "foo")
606 // If a var has no name we won't see attempts to
607 // refer to it via "C.<name>", so skip these vars
609 // See issue 53000 for more context.
613 typOff, _ := e.Val(dwarf.AttrType).(dwarf.Offset)
615 if e.Val(dwarf.AttrSpecification) != nil {
616 // Since we are reading all the DWARF,
617 // assume we will see the variable elsewhere.
620 fatalf("malformed DWARF TagVariable entry")
622 if !strings.HasPrefix(name, "__cgo__") {
625 typ, err := d.Type(typOff)
627 fatalf("loading DWARF type: %s", err)
629 t, ok := typ.(*dwarf.PtrType)
631 fatalf("internal error: %s has non-pointer type", name)
633 i, err := strconv.Atoi(name[7:])
635 fatalf("malformed __cgo__ name: %s", name)
638 p.recordTypedefs(t.Type, f.NamePos[names[i]])
640 if e.Tag != dwarf.TagCompileUnit {
645 // Record types and typedef information.
646 for i, n := range names {
647 if strings.HasSuffix(n.Go, "GetTypeID") && types[i].String() == "func() CFTypeID" {
648 conv.getTypeIDs[n.Go[:len(n.Go)-9]] = true
651 for i, n := range names {
656 f, fok := types[i].(*dwarf.FuncType)
657 if n.Kind != "type" && fok {
659 n.FuncType = conv.FuncType(f, pos)
661 n.Type = conv.Type(types[i], pos)
665 if _, ok := types[i].(*dwarf.UintType); ok {
666 n.Const = fmt.Sprintf("%#x", uint64(ints[i]))
668 n.Const = fmt.Sprintf("%#x", ints[i])
672 if i >= len(floats) {
675 switch base(types[i]).(type) {
676 case *dwarf.IntType, *dwarf.UintType:
677 // This has an integer type so it's
678 // not really a floating point
679 // constant. This can happen when the
680 // C compiler complains about using
681 // the value as an integer constant,
682 // but not as a general constant.
683 // Treat this as a variable of the
684 // appropriate type, not a constant,
685 // to get C-style type handling,
686 // avoiding the problem that C permits
687 // uint64(-1) but Go does not.
691 n.Const = fmt.Sprintf("%f", floats[i])
695 n.Const = fmt.Sprintf("%q", strs[i])
703 // recordTypedefs remembers in p.typedefs all the typedefs used in dtypes and its children.
704 func (p *Package) recordTypedefs(dtype dwarf.Type, pos token.Pos) {
705 p.recordTypedefs1(dtype, pos, map[dwarf.Type]bool{})
708 func (p *Package) recordTypedefs1(dtype dwarf.Type, pos token.Pos, visited map[dwarf.Type]bool) {
715 visited[dtype] = true
716 switch dt := dtype.(type) {
717 case *dwarf.TypedefType:
718 if strings.HasPrefix(dt.Name, "__builtin") {
719 // Don't look inside builtin types. There be dragons.
722 if !p.typedefs[dt.Name] {
723 p.typedefs[dt.Name] = true
724 p.typedefList = append(p.typedefList, typedefInfo{dt.Name, pos})
725 p.recordTypedefs1(dt.Type, pos, visited)
728 p.recordTypedefs1(dt.Type, pos, visited)
729 case *dwarf.ArrayType:
730 p.recordTypedefs1(dt.Type, pos, visited)
731 case *dwarf.QualType:
732 p.recordTypedefs1(dt.Type, pos, visited)
733 case *dwarf.FuncType:
734 p.recordTypedefs1(dt.ReturnType, pos, visited)
735 for _, a := range dt.ParamType {
736 p.recordTypedefs1(a, pos, visited)
738 case *dwarf.StructType:
739 for _, f := range dt.Field {
740 p.recordTypedefs1(f.Type, pos, visited)
745 // prepareNames finalizes the Kind field of not-type names and sets
746 // the mangled name of all names.
747 func (p *Package) prepareNames(f *File) {
748 for _, n := range f.Name {
749 if n.Kind == "not-type" {
754 n.FuncType = &FuncType{
757 Results: &ast.FieldList{List: []*ast.Field{{Type: n.Type.Go}}},
763 if n.Kind == "type" && typedef[n.Mangle] == nil {
764 typedef[n.Mangle] = n.Type
769 // mangleName does name mangling to translate names
770 // from the original Go source files to the names
771 // used in the final Go files generated by cgo.
772 func (p *Package) mangleName(n *Name) {
773 // When using gccgo variables have to be
774 // exported so that they become global symbols
775 // that the C code can refer to.
777 if *gccgo && n.IsVar() {
780 n.Mangle = prefix + n.Kind + "_" + n.Go
783 func (f *File) isMangledName(s string) bool {
785 if strings.HasPrefix(s, prefix) {
787 for _, k := range nameKinds {
788 if strings.HasPrefix(t, k+"_") {
796 // rewriteCalls rewrites all calls that pass pointers to check that
797 // they follow the rules for passing pointers between Go and C.
798 // This reports whether the package needs to import unsafe as _cgo_unsafe.
799 func (p *Package) rewriteCalls(f *File) bool {
801 // Walk backward so that in C.f1(C.f2()) we rewrite C.f2 first.
802 for _, call := range f.Calls {
806 start := f.offset(call.Call.Pos())
807 end := f.offset(call.Call.End())
808 str, nu := p.rewriteCall(f, call)
810 f.Edit.Replace(start, end, str)
819 // rewriteCall rewrites one call to add pointer checks.
820 // If any pointer checks are required, we rewrite the call into a
821 // function literal that calls _cgoCheckPointer for each pointer
822 // argument and then calls the original function.
823 // This returns the rewritten call and whether the package needs to
824 // import unsafe as _cgo_unsafe.
825 // If it returns the empty string, the call did not need to be rewritten.
826 func (p *Package) rewriteCall(f *File, call *Call) (string, bool) {
827 // This is a call to C.xxx; set goname to "xxx".
828 // It may have already been mangled by rewriteName.
830 switch fun := call.Call.Fun.(type) {
831 case *ast.SelectorExpr:
832 goname = fun.Sel.Name
834 goname = strings.TrimPrefix(fun.Name, "_C2func_")
835 goname = strings.TrimPrefix(goname, "_Cfunc_")
837 if goname == "" || goname == "malloc" {
840 name := f.Name[goname]
841 if name == nil || name.Kind != "func" {
842 // Probably a type conversion.
846 params := name.FuncType.Params
847 args := call.Call.Args
848 end := call.Call.End()
850 // Avoid a crash if the number of arguments doesn't match
851 // the number of parameters.
852 // This will be caught when the generated file is compiled.
853 if len(args) != len(params) {
858 for i, param := range params {
859 if p.needsPointerCheck(f, param.Go, args[i]) {
868 // We need to rewrite this call.
873 // _cgoCheckPointer(_cgo0, nil)
876 // Using a function literal like this lets us evaluate the
877 // function arguments only once while doing pointer checks.
878 // This is particularly useful when passing additional arguments
879 // to _cgoCheckPointer, as done in checkIndex and checkAddr.
881 // When the function argument is a conversion to unsafe.Pointer,
882 // we unwrap the conversion before checking the pointer,
883 // and then wrap again when calling C.f. This lets us check
884 // the real type of the pointer in some cases. See issue #25941.
886 // When the call to C.f is deferred, we use an additional function
887 // literal to evaluate the arguments at the right time.
888 // defer func() func() {
891 // _cgoCheckPointer(_cgo0, nil)
895 // This works because the defer statement evaluates the first
896 // function literal in order to get the function to call.
899 sb.WriteString("func() ")
901 sb.WriteString("func() ")
908 // Check whether this call expects two results.
909 for _, ref := range f.Ref {
910 if ref.Expr != &call.Call.Fun {
913 if ref.Context == ctxCall2 {
921 // Add the result type, if any.
922 if name.FuncType.Result != nil {
923 rtype := p.rewriteUnsafe(name.FuncType.Result.Go)
924 if rtype != name.FuncType.Result.Go {
927 sb.WriteString(gofmtLine(rtype))
931 // Add the second result type, if any.
933 if name.FuncType.Result == nil {
934 // An explicit void result looks odd but it
935 // seems to be how cgo has worked historically.
936 sb.WriteString("_Ctype_void")
938 sb.WriteString(", error)")
944 // Define _cgoN for each argument value.
945 // Write _cgoCheckPointer calls to sbCheck.
946 var sbCheck bytes.Buffer
947 for i, param := range params {
949 arg, nu := p.mangle(f, &args[i], true)
954 // Use "var x T = ..." syntax to explicitly convert untyped
955 // constants to the parameter type, to avoid a type mismatch.
956 ptype := p.rewriteUnsafe(param.Go)
958 if !p.needsPointerCheck(f, param.Go, args[i]) || param.BadPointer || p.checkUnsafeStringData(args[i]) {
959 if ptype != param.Go {
962 fmt.Fprintf(&sb, "var _cgo%d %s = %s; ", i,
963 gofmtLine(ptype), gofmtPos(arg, origArg.Pos()))
968 if p.checkIndex(&sb, &sbCheck, arg, i) {
973 if p.checkAddr(&sb, &sbCheck, arg, i) {
978 if p.checkSlice(&sb, &sbCheck, arg, i) {
982 fmt.Fprintf(&sb, "_cgo%d := %s; ", i, gofmtPos(arg, origArg.Pos()))
983 fmt.Fprintf(&sbCheck, "_cgoCheckPointer(_cgo%d, nil); ", i)
987 sb.WriteString("return func() { ")
990 // Write out the calls to _cgoCheckPointer.
991 sb.WriteString(sbCheck.String())
994 sb.WriteString("return ")
997 m, nu := p.mangle(f, &call.Call.Fun, false)
1001 sb.WriteString(gofmtPos(m, end))
1004 for i := range params {
1006 sb.WriteString(", ")
1008 fmt.Fprintf(&sb, "_cgo%d", i)
1010 sb.WriteString("); ")
1016 sb.WriteString("()")
1018 sb.WriteString("()")
1020 return sb.String(), needsUnsafe
1023 // needsPointerCheck reports whether the type t needs a pointer check.
1024 // This is true if t is a pointer and if the value to which it points
1025 // might contain a pointer.
1026 func (p *Package) needsPointerCheck(f *File, t ast.Expr, arg ast.Expr) bool {
1027 // An untyped nil does not need a pointer check, and when
1028 // _cgoCheckPointer returns the untyped nil the type assertion we
1029 // are going to insert will fail. Easier to just skip nil arguments.
1030 // TODO: Note that this fails if nil is shadowed.
1031 if id, ok := arg.(*ast.Ident); ok && id.Name == "nil" {
1035 return p.hasPointer(f, t, true)
1038 // hasPointer is used by needsPointerCheck. If top is true it returns
1039 // whether t is or contains a pointer that might point to a pointer.
1040 // If top is false it reports whether t is or contains a pointer.
1042 func (p *Package) hasPointer(f *File, t ast.Expr, top bool) bool {
1043 switch t := t.(type) {
1044 case *ast.ArrayType:
1049 return p.hasPointer(f, t.Elt, false)
1051 return p.hasPointer(f, t.Elt, top)
1052 case *ast.StructType:
1053 for _, field := range t.Fields.List {
1054 if p.hasPointer(f, field.Type, top) {
1059 case *ast.StarExpr: // Pointer type.
1063 // Check whether this is a pointer to a C union (or class)
1064 // type that contains a pointer.
1065 if unionWithPointer[t.X] {
1068 return p.hasPointer(f, t.X, false)
1069 case *ast.FuncType, *ast.InterfaceType, *ast.MapType, *ast.ChanType:
1072 // TODO: Handle types defined within function.
1073 for _, d := range p.Decl {
1074 gd, ok := d.(*ast.GenDecl)
1075 if !ok || gd.Tok != token.TYPE {
1078 for _, spec := range gd.Specs {
1079 ts, ok := spec.(*ast.TypeSpec)
1083 if ts.Name.Name == t.Name {
1084 return p.hasPointer(f, ts.Type, top)
1088 if def := typedef[t.Name]; def != nil {
1089 return p.hasPointer(f, def.Go, top)
1091 if t.Name == "string" {
1094 if t.Name == "error" {
1097 if goTypes[t.Name] != nil {
1100 // We can't figure out the type. Conservative
1101 // approach is to assume it has a pointer.
1103 case *ast.SelectorExpr:
1104 if l, ok := t.X.(*ast.Ident); !ok || l.Name != "C" {
1105 // Type defined in a different package.
1106 // Conservative approach is to assume it has a
1111 // Conservative approach: assume pointer.
1114 name := f.Name[t.Sel.Name]
1115 if name != nil && name.Kind == "type" && name.Type != nil && name.Type.Go != nil {
1116 return p.hasPointer(f, name.Type.Go, top)
1118 // We can't figure out the type. Conservative
1119 // approach is to assume it has a pointer.
1122 error_(t.Pos(), "could not understand type %s", gofmt(t))
1127 // mangle replaces references to C names in arg with the mangled names,
1128 // rewriting calls when it finds them.
1129 // It removes the corresponding references in f.Ref and f.Calls, so that we
1130 // don't try to do the replacement again in rewriteRef or rewriteCall.
1131 // If addPosition is true, add position info to the idents of C names in arg.
1132 func (p *Package) mangle(f *File, arg *ast.Expr, addPosition bool) (ast.Expr, bool) {
1133 needsUnsafe := false
1134 f.walk(arg, ctxExpr, func(f *File, arg interface{}, context astContext) {
1135 px, ok := arg.(*ast.Expr)
1139 sel, ok := (*px).(*ast.SelectorExpr)
1141 if l, ok := sel.X.(*ast.Ident); !ok || l.Name != "C" {
1145 for _, r := range f.Ref {
1147 *px = p.rewriteName(f, r, addPosition)
1156 call, ok := (*px).(*ast.CallExpr)
1161 for _, c := range f.Calls {
1162 if !c.Done && c.Call.Lparen == call.Lparen {
1163 cstr, nu := p.rewriteCall(f, c)
1165 // Smuggle the rewritten call through an ident.
1166 *px = ast.NewIdent(cstr)
1175 return *arg, needsUnsafe
1178 // checkIndex checks whether arg has the form &a[i], possibly inside
1179 // type conversions. If so, then in the general case it writes
1182 // _cgoNN := &cgoIndexNN[i] // with type conversions, if any
1184 // to sb, and writes
1186 // _cgoCheckPointer(_cgoNN, _cgoIndexNN)
1188 // to sbCheck, and returns true. If a is a simple variable or field reference,
1191 // _cgoIndexNN := &a
1193 // and dereferences the uses of _cgoIndexNN. Taking the address avoids
1194 // making a copy of an array.
1196 // This tells _cgoCheckPointer to check the complete contents of the
1197 // slice or array being indexed, but no other part of the memory allocation.
1198 func (p *Package) checkIndex(sb, sbCheck *bytes.Buffer, arg ast.Expr, i int) bool {
1199 // Strip type conversions.
1202 c, ok := x.(*ast.CallExpr)
1203 if !ok || len(c.Args) != 1 {
1206 if !p.isType(c.Fun) && !p.isUnsafeData(c.Fun, false) {
1211 u, ok := x.(*ast.UnaryExpr)
1212 if !ok || u.Op != token.AND {
1215 index, ok := u.X.(*ast.IndexExpr)
1222 if p.isVariable(index.X) {
1227 fmt.Fprintf(sb, "_cgoIndex%d := %s%s; ", i, addr, gofmtPos(index.X, index.X.Pos()))
1229 index.X = ast.NewIdent(fmt.Sprintf("_cgoIndex%d", i))
1231 index.X = &ast.StarExpr{X: index.X}
1233 fmt.Fprintf(sb, "_cgo%d := %s; ", i, gofmtPos(arg, arg.Pos()))
1236 fmt.Fprintf(sbCheck, "_cgoCheckPointer(_cgo%d, %s_cgoIndex%d); ", i, deref, i)
1241 // checkAddr checks whether arg has the form &x, possibly inside type
1242 // conversions. If so, it writes
1245 // _cgoNN := _cgoBaseNN // with type conversions, if any
1247 // to sb, and writes
1249 // _cgoCheckPointer(_cgoBaseNN, true)
1251 // to sbCheck, and returns true. This tells _cgoCheckPointer to check
1252 // just the contents of the pointer being passed, not any other part
1253 // of the memory allocation. This is run after checkIndex, which looks
1254 // for the special case of &a[i], which requires different checks.
1255 func (p *Package) checkAddr(sb, sbCheck *bytes.Buffer, arg ast.Expr, i int) bool {
1256 // Strip type conversions.
1259 c, ok := (*px).(*ast.CallExpr)
1260 if !ok || len(c.Args) != 1 {
1263 if !p.isType(c.Fun) && !p.isUnsafeData(c.Fun, false) {
1268 if u, ok := (*px).(*ast.UnaryExpr); !ok || u.Op != token.AND {
1272 fmt.Fprintf(sb, "_cgoBase%d := %s; ", i, gofmtPos(*px, (*px).Pos()))
1275 *px = ast.NewIdent(fmt.Sprintf("_cgoBase%d", i))
1276 fmt.Fprintf(sb, "_cgo%d := %s; ", i, gofmtPos(arg, arg.Pos()))
1279 // Use "0 == 0" to do the right thing in the unlikely event
1280 // that "true" is shadowed.
1281 fmt.Fprintf(sbCheck, "_cgoCheckPointer(_cgoBase%d, 0 == 0); ", i)
1286 // checkSlice checks whether arg has the form x[i:j], possibly inside
1287 // type conversions. If so, it writes
1289 // _cgoSliceNN := x[i:j]
1290 // _cgoNN := _cgoSliceNN // with type conversions, if any
1292 // to sb, and writes
1294 // _cgoCheckPointer(_cgoSliceNN, true)
1296 // to sbCheck, and returns true. This tells _cgoCheckPointer to check
1297 // just the contents of the slice being passed, not any other part
1298 // of the memory allocation.
1299 func (p *Package) checkSlice(sb, sbCheck *bytes.Buffer, arg ast.Expr, i int) bool {
1300 // Strip type conversions.
1303 c, ok := (*px).(*ast.CallExpr)
1304 if !ok || len(c.Args) != 1 {
1307 if !p.isType(c.Fun) && !p.isUnsafeData(c.Fun, false) {
1312 if _, ok := (*px).(*ast.SliceExpr); !ok {
1316 fmt.Fprintf(sb, "_cgoSlice%d := %s; ", i, gofmtPos(*px, (*px).Pos()))
1319 *px = ast.NewIdent(fmt.Sprintf("_cgoSlice%d", i))
1320 fmt.Fprintf(sb, "_cgo%d := %s; ", i, gofmtPos(arg, arg.Pos()))
1323 // Use 0 == 0 to do the right thing in the unlikely event
1324 // that "true" is shadowed.
1325 fmt.Fprintf(sbCheck, "_cgoCheckPointer(_cgoSlice%d, 0 == 0); ", i)
1330 // checkUnsafeStringData checks for a call to unsafe.StringData.
1331 // The result of that call can't contain a pointer so there is
1332 // no need to call _cgoCheckPointer.
1333 func (p *Package) checkUnsafeStringData(arg ast.Expr) bool {
1336 c, ok := x.(*ast.CallExpr)
1337 if !ok || len(c.Args) != 1 {
1340 if p.isUnsafeData(c.Fun, true) {
1343 if !p.isType(c.Fun) {
1351 // isType reports whether the expression is definitely a type.
1352 // This is conservative--it returns false for an unknown identifier.
1353 func (p *Package) isType(t ast.Expr) bool {
1354 switch t := t.(type) {
1355 case *ast.SelectorExpr:
1356 id, ok := t.X.(*ast.Ident)
1360 if id.Name == "unsafe" && t.Sel.Name == "Pointer" {
1363 if id.Name == "C" && typedef["_Ctype_"+t.Sel.Name] != nil {
1368 // TODO: This ignores shadowing.
1370 case "unsafe.Pointer", "bool", "byte",
1371 "complex64", "complex128",
1373 "float32", "float64",
1374 "int", "int8", "int16", "int32", "int64",
1376 "uint", "uint8", "uint16", "uint32", "uint64", "uintptr":
1380 if strings.HasPrefix(t.Name, "_Ctype_") {
1383 case *ast.ParenExpr:
1384 return p.isType(t.X)
1386 return p.isType(t.X)
1387 case *ast.ArrayType, *ast.StructType, *ast.FuncType, *ast.InterfaceType,
1388 *ast.MapType, *ast.ChanType:
1395 // isUnsafeData reports whether the expression is unsafe.StringData
1396 // or unsafe.SliceData. We can ignore these when checking for pointers
1397 // because they don't change whether or not their argument contains
1398 // any Go pointers. If onlyStringData is true we only check for StringData.
1399 func (p *Package) isUnsafeData(x ast.Expr, onlyStringData bool) bool {
1400 st, ok := x.(*ast.SelectorExpr)
1404 id, ok := st.X.(*ast.Ident)
1408 if id.Name != "unsafe" {
1411 if !onlyStringData && st.Sel.Name == "SliceData" {
1414 return st.Sel.Name == "StringData"
1417 // isVariable reports whether x is a variable, possibly with field references.
1418 func (p *Package) isVariable(x ast.Expr) bool {
1419 switch x := x.(type) {
1422 case *ast.SelectorExpr:
1423 return p.isVariable(x.X)
1424 case *ast.IndexExpr:
1430 // rewriteUnsafe returns a version of t with references to unsafe.Pointer
1431 // rewritten to use _cgo_unsafe.Pointer instead.
1432 func (p *Package) rewriteUnsafe(t ast.Expr) ast.Expr {
1433 switch t := t.(type) {
1435 // We don't see a SelectorExpr for unsafe.Pointer;
1436 // this is created by code in this file.
1437 if t.Name == "unsafe.Pointer" {
1438 return ast.NewIdent("_cgo_unsafe.Pointer")
1440 case *ast.ArrayType:
1441 t1 := p.rewriteUnsafe(t.Elt)
1447 case *ast.StructType:
1451 for _, f := range t.Fields.List {
1452 ft := p.rewriteUnsafe(f.Type)
1454 fields.List = append(fields.List, f)
1458 fields.List = append(fields.List, &fn)
1467 case *ast.StarExpr: // Pointer type.
1468 x1 := p.rewriteUnsafe(t.X)
1478 // rewriteRef rewrites all the C.xxx references in f.AST to refer to the
1479 // Go equivalents, now that we have figured out the meaning of all
1480 // the xxx. In *godefs mode, rewriteRef replaces the names
1481 // with full definitions instead of mangled names.
1482 func (p *Package) rewriteRef(f *File) {
1483 // Keep a list of all the functions, to remove the ones
1484 // only used as expressions and avoid generating bridge
1486 functions := make(map[string]bool)
1488 for _, n := range f.Name {
1489 if n.Kind == "func" {
1490 functions[n.Go] = false
1494 // Now that we have all the name types filled in,
1495 // scan through the Refs to identify the ones that
1496 // are trying to do a ,err call. Also check that
1497 // functions are only used in calls.
1498 for _, r := range f.Ref {
1499 if r.Name.IsConst() && r.Name.Const == "" {
1500 error_(r.Pos(), "unable to find value of constant C.%s", fixGo(r.Name.Go))
1503 if r.Name.Kind == "func" {
1505 case ctxCall, ctxCall2:
1506 functions[r.Name.Go] = true
1510 expr := p.rewriteName(f, r, false)
1513 // Substitute definition for mangled type name.
1514 if r.Name.Type != nil && r.Name.Kind == "type" {
1515 expr = r.Name.Type.Go
1517 if id, ok := expr.(*ast.Ident); ok {
1518 if t := typedef[id.Name]; t != nil {
1521 if id.Name == r.Name.Mangle && r.Name.Const != "" {
1522 expr = ast.NewIdent(r.Name.Const)
1527 // Copy position information from old expr into new expr,
1528 // in case expression being replaced is first on line.
1529 // See golang.org/issue/6563.
1530 pos := (*r.Expr).Pos()
1531 if x, ok := expr.(*ast.Ident); ok {
1532 expr = &ast.Ident{NamePos: pos, Name: x.Name}
1535 // Change AST, because some later processing depends on it,
1536 // and also because -godefs mode still prints the AST.
1540 // Record source-level edit for cgo output.
1542 // Prepend a space in case the earlier code ends
1543 // with '/', which would give us a "//" comment.
1544 repl := " " + gofmtPos(expr, old.Pos())
1545 end := fset.Position(old.End())
1546 // Subtract 1 from the column if we are going to
1547 // append a close parenthesis. That will set the
1548 // correct column for the following characters.
1550 if r.Name.Kind != "type" {
1553 if end.Column > sub {
1554 repl = fmt.Sprintf("%s /*line :%d:%d*/", repl, end.Line, end.Column-sub)
1556 if r.Name.Kind != "type" {
1557 repl = "(" + repl + ")"
1559 f.Edit.Replace(f.offset(old.Pos()), f.offset(old.End()), repl)
1563 // Remove functions only used as expressions, so their respective
1564 // bridge functions are not generated.
1565 for name, used := range functions {
1567 delete(f.Name, name)
1572 // rewriteName returns the expression used to rewrite a reference.
1573 // If addPosition is true, add position info in the ident name.
1574 func (p *Package) rewriteName(f *File, r *Ref, addPosition bool) ast.Expr {
1575 getNewIdent := ast.NewIdent
1577 getNewIdent = func(newName string) *ast.Ident {
1578 mangledIdent := ast.NewIdent(newName)
1579 if len(newName) == len(r.Name.Go) {
1582 p := fset.Position((*r.Expr).End())
1586 return ast.NewIdent(fmt.Sprintf("%s /*line :%d:%d*/", newName, p.Line, p.Column))
1589 var expr ast.Expr = getNewIdent(r.Name.Mangle) // default
1591 case ctxCall, ctxCall2:
1592 if r.Name.Kind != "func" {
1593 if r.Name.Kind == "type" {
1595 if r.Name.Type == nil {
1596 error_(r.Pos(), "invalid conversion to C.%s: undefined C type '%s'", fixGo(r.Name.Go), r.Name.C)
1600 error_(r.Pos(), "call of non-function C.%s", fixGo(r.Name.Go))
1603 if r.Context == ctxCall2 {
1604 if r.Name.Go == "_CMalloc" {
1605 error_(r.Pos(), "no two-result form for C.malloc")
1608 // Invent new Name for the two-result function.
1609 n := f.Name["2"+r.Name.Go]
1614 n.Mangle = "_C2func_" + n.Go
1615 f.Name["2"+r.Name.Go] = n
1617 expr = getNewIdent(n.Mangle)
1622 switch r.Name.Kind {
1624 if builtinDefs[r.Name.C] != "" {
1625 error_(r.Pos(), "use of builtin '%s' not in function call", fixGo(r.Name.C))
1628 // Function is being used in an expression, to e.g. pass around a C function pointer.
1629 // Create a new Name for this Ref which causes the variable to be declared in Go land.
1630 fpName := "fp_" + r.Name.Go
1631 name := f.Name[fpName]
1637 Type: &Type{Size: p.PtrSize, Align: p.PtrSize, C: c("void*"), Go: ast.NewIdent("unsafe.Pointer")},
1640 f.Name[fpName] = name
1643 // Rewrite into call to _Cgo_ptr to prevent assignments. The _Cgo_ptr
1644 // function is defined in out.go and simply returns its argument. See
1646 expr = &ast.CallExpr{
1647 Fun: &ast.Ident{NamePos: (*r.Expr).Pos(), Name: "_Cgo_ptr"},
1648 Args: []ast.Expr{getNewIdent(name.Mangle)},
1651 // Okay - might be new(T), T(x), Generic[T], etc.
1652 if r.Name.Type == nil {
1653 error_(r.Pos(), "expression C.%s: undefined C type '%s'", fixGo(r.Name.Go), r.Name.C)
1656 expr = &ast.StarExpr{Star: (*r.Expr).Pos(), X: expr}
1658 expr = &ast.CallExpr{Fun: expr}
1661 if r.Name.Kind == "var" {
1662 expr = &ast.StarExpr{Star: (*r.Expr).Pos(), X: expr}
1664 error_(r.Pos(), "only C variables allowed in selector expression %s", fixGo(r.Name.Go))
1667 if r.Name.Kind != "type" {
1668 error_(r.Pos(), "expression C.%s used as type", fixGo(r.Name.Go))
1669 } else if r.Name.Type == nil {
1670 // Use of C.enum_x, C.struct_x or C.union_x without C definition.
1671 // GCC won't raise an error when using pointers to such unknown types.
1672 error_(r.Pos(), "type C.%s: undefined C type '%s'", fixGo(r.Name.Go), r.Name.C)
1675 if r.Name.Kind == "func" {
1676 error_(r.Pos(), "must call C.%s", fixGo(r.Name.Go))
1682 // gofmtPos returns the gofmt-formatted string for an AST node,
1683 // with a comment setting the position before the node.
1684 func gofmtPos(n ast.Expr, pos token.Pos) string {
1686 p := fset.Position(pos)
1690 return fmt.Sprintf("/*line :%d:%d*/%s", p.Line, p.Column, s)
1693 // checkGCCBaseCmd returns the start of the compiler command line.
1694 // It uses $CC if set, or else $GCC, or else the compiler recorded
1695 // during the initial build as defaultCC.
1696 // defaultCC is defined in zdefaultcc.go, written by cmd/dist.
1698 // The compiler command line is split into arguments on whitespace. Quotes
1699 // are understood, so arguments may contain whitespace.
1701 // checkGCCBaseCmd confirms that the compiler exists in PATH, returning
1702 // an error if it does not.
1703 func checkGCCBaseCmd() ([]string, error) {
1704 // Use $CC if set, since that's what the build uses.
1705 value := os.Getenv("CC")
1707 // Try $GCC if set, since that's what we used to use.
1708 value = os.Getenv("GCC")
1711 value = defaultCC(goos, goarch)
1713 args, err := quoted.Split(value)
1718 return nil, errors.New("CC not set and no default found")
1720 if _, err := exec.LookPath(args[0]); err != nil {
1721 return nil, fmt.Errorf("C compiler %q not found: %v", args[0], err)
1723 return args[:len(args):len(args)], nil
1726 // gccMachine returns the gcc -m flag to use, either "-m32", "-m64" or "-marm".
1727 func (p *Package) gccMachine() []string {
1730 if goos == "darwin" {
1731 return []string{"-arch", "x86_64", "-m64"}
1733 return []string{"-m64"}
1735 if goos == "darwin" {
1736 return []string{"-arch", "arm64"}
1739 return []string{"-m32"}
1741 return []string{"-marm"} // not thumb
1743 return []string{"-m31"}
1745 return []string{"-m64"}
1746 case "mips64", "mips64le":
1747 if gomips64 == "hardfloat" {
1748 return []string{"-mabi=64", "-mhard-float"}
1749 } else if gomips64 == "softfloat" {
1750 return []string{"-mabi=64", "-msoft-float"}
1752 case "mips", "mipsle":
1753 if gomips == "hardfloat" {
1754 return []string{"-mabi=32", "-mfp32", "-mhard-float", "-mno-odd-spreg"}
1755 } else if gomips == "softfloat" {
1756 return []string{"-mabi=32", "-msoft-float"}
1759 return []string{"-mabi=lp64d"}
1764 func gccTmp() string {
1765 return *objDir + "_cgo_.o"
1768 // gccCmd returns the gcc command line to use for compiling
1770 func (p *Package) gccCmd() []string {
1771 c := append(gccBaseCmd,
1772 "-w", // no warnings
1773 "-Wno-error", // warnings are not errors
1774 "-o"+gccTmp(), // write object to tmp
1775 "-gdwarf-2", // generate DWARF v2 debugging symbols
1776 "-c", // do not link
1777 "-xc", // input language is C
1782 // Apple clang version 1.7 (tags/Apple/clang-77) (based on LLVM 2.9svn)
1783 // doesn't have -Wno-unneeded-internal-declaration, so we need yet another
1784 // flag to disable the warning. Yes, really good diagnostics, clang.
1785 "-Wno-unknown-warning-option",
1786 "-Wno-unneeded-internal-declaration",
1787 "-Wno-unused-function",
1788 "-Qunused-arguments",
1789 // Clang embeds prototypes for some builtin functions,
1790 // like malloc and calloc, but all size_t parameters are
1791 // incorrectly typed unsigned long. We work around that
1792 // by disabling the builtin functions (this is safe as
1793 // it won't affect the actual compilation of the C code).
1794 // See: https://golang.org/issue/6506.
1799 c = append(c, p.GccOptions...)
1800 c = append(c, p.gccMachine()...)
1802 c = append(c, "-maix64")
1803 c = append(c, "-mcmodel=large")
1805 // disable LTO so we get an object whose symbols we can read
1806 c = append(c, "-fno-lto")
1807 c = append(c, "-") //read input from standard input
1811 // gccDebug runs gcc -gdwarf-2 over the C program stdin and
1812 // returns the corresponding DWARF data and, if present, debug data block.
1813 func (p *Package) gccDebug(stdin []byte, nnames int) (d *dwarf.Data, ints []int64, floats []float64, strs []string) {
1814 runGcc(stdin, p.gccCmd())
1816 isDebugInts := func(s string) bool {
1817 // Some systems use leading _ to denote non-assembly symbols.
1818 return s == "__cgodebug_ints" || s == "___cgodebug_ints"
1820 isDebugFloats := func(s string) bool {
1821 // Some systems use leading _ to denote non-assembly symbols.
1822 return s == "__cgodebug_floats" || s == "___cgodebug_floats"
1824 indexOfDebugStr := func(s string) int {
1825 // Some systems use leading _ to denote non-assembly symbols.
1826 if strings.HasPrefix(s, "___") {
1829 if strings.HasPrefix(s, "__cgodebug_str__") {
1830 if n, err := strconv.Atoi(s[len("__cgodebug_str__"):]); err == nil {
1836 indexOfDebugStrlen := func(s string) int {
1837 // Some systems use leading _ to denote non-assembly symbols.
1838 if strings.HasPrefix(s, "___") {
1841 if strings.HasPrefix(s, "__cgodebug_strlen__") {
1842 if n, err := strconv.Atoi(s[len("__cgodebug_strlen__"):]); err == nil {
1849 strs = make([]string, nnames)
1851 strdata := make(map[int]string, nnames)
1852 strlens := make(map[int]int, nnames)
1854 buildStrings := func() {
1855 for n, strlen := range strlens {
1857 if len(data) <= strlen {
1858 fatalf("invalid string literal")
1860 strs[n] = data[:strlen]
1864 if f, err := macho.Open(gccTmp()); err == nil {
1868 fatalf("cannot load DWARF output from %s: %v", gccTmp(), err)
1871 if f.Symtab != nil {
1872 for i := range f.Symtab.Syms {
1873 s := &f.Symtab.Syms[i]
1875 case isDebugInts(s.Name):
1876 // Found it. Now find data section.
1877 if i := int(s.Sect) - 1; 0 <= i && i < len(f.Sections) {
1878 sect := f.Sections[i]
1879 if sect.Addr <= s.Value && s.Value < sect.Addr+sect.Size {
1880 if sdat, err := sect.Data(); err == nil {
1881 data := sdat[s.Value-sect.Addr:]
1882 ints = make([]int64, len(data)/8)
1883 for i := range ints {
1884 ints[i] = int64(bo.Uint64(data[i*8:]))
1889 case isDebugFloats(s.Name):
1890 // Found it. Now find data section.
1891 if i := int(s.Sect) - 1; 0 <= i && i < len(f.Sections) {
1892 sect := f.Sections[i]
1893 if sect.Addr <= s.Value && s.Value < sect.Addr+sect.Size {
1894 if sdat, err := sect.Data(); err == nil {
1895 data := sdat[s.Value-sect.Addr:]
1896 floats = make([]float64, len(data)/8)
1897 for i := range floats {
1898 floats[i] = math.Float64frombits(bo.Uint64(data[i*8:]))
1904 if n := indexOfDebugStr(s.Name); n != -1 {
1905 // Found it. Now find data section.
1906 if i := int(s.Sect) - 1; 0 <= i && i < len(f.Sections) {
1907 sect := f.Sections[i]
1908 if sect.Addr <= s.Value && s.Value < sect.Addr+sect.Size {
1909 if sdat, err := sect.Data(); err == nil {
1910 data := sdat[s.Value-sect.Addr:]
1911 strdata[n] = string(data)
1917 if n := indexOfDebugStrlen(s.Name); n != -1 {
1918 // Found it. Now find data section.
1919 if i := int(s.Sect) - 1; 0 <= i && i < len(f.Sections) {
1920 sect := f.Sections[i]
1921 if sect.Addr <= s.Value && s.Value < sect.Addr+sect.Size {
1922 if sdat, err := sect.Data(); err == nil {
1923 data := sdat[s.Value-sect.Addr:]
1924 strlen := bo.Uint64(data[:8])
1925 if strlen > (1<<(uint(p.IntSize*8)-1) - 1) { // greater than MaxInt?
1926 fatalf("string literal too big")
1928 strlens[n] = int(strlen)
1939 return d, ints, floats, strs
1942 if f, err := elf.Open(gccTmp()); err == nil {
1946 fatalf("cannot load DWARF output from %s: %v", gccTmp(), err)
1949 symtab, err := f.Symbols()
1951 // Check for use of -fsanitize=hwaddress (issue 53285).
1952 removeTag := func(v uint64) uint64 { return v }
1953 if goarch == "arm64" {
1954 for i := range symtab {
1955 if symtab[i].Name == "__hwasan_init" {
1956 // -fsanitize=hwaddress on ARM
1957 // uses the upper byte of a
1958 // memory address as a hardware
1959 // tag. Remove it so that
1960 // we can find the associated
1962 removeTag = func(v uint64) uint64 { return v &^ (0xff << (64 - 8)) }
1968 for i := range symtab {
1971 case isDebugInts(s.Name):
1972 // Found it. Now find data section.
1973 if i := int(s.Section); 0 <= i && i < len(f.Sections) {
1974 sect := f.Sections[i]
1975 val := removeTag(s.Value)
1976 if sect.Addr <= val && val < sect.Addr+sect.Size {
1977 if sdat, err := sect.Data(); err == nil {
1978 data := sdat[val-sect.Addr:]
1979 ints = make([]int64, len(data)/8)
1980 for i := range ints {
1981 ints[i] = int64(bo.Uint64(data[i*8:]))
1986 case isDebugFloats(s.Name):
1987 // Found it. Now find data section.
1988 if i := int(s.Section); 0 <= i && i < len(f.Sections) {
1989 sect := f.Sections[i]
1990 val := removeTag(s.Value)
1991 if sect.Addr <= val && val < sect.Addr+sect.Size {
1992 if sdat, err := sect.Data(); err == nil {
1993 data := sdat[val-sect.Addr:]
1994 floats = make([]float64, len(data)/8)
1995 for i := range floats {
1996 floats[i] = math.Float64frombits(bo.Uint64(data[i*8:]))
2002 if n := indexOfDebugStr(s.Name); n != -1 {
2003 // Found it. Now find data section.
2004 if i := int(s.Section); 0 <= i && i < len(f.Sections) {
2005 sect := f.Sections[i]
2006 val := removeTag(s.Value)
2007 if sect.Addr <= val && val < sect.Addr+sect.Size {
2008 if sdat, err := sect.Data(); err == nil {
2009 data := sdat[val-sect.Addr:]
2010 strdata[n] = string(data)
2016 if n := indexOfDebugStrlen(s.Name); n != -1 {
2017 // Found it. Now find data section.
2018 if i := int(s.Section); 0 <= i && i < len(f.Sections) {
2019 sect := f.Sections[i]
2020 val := removeTag(s.Value)
2021 if sect.Addr <= val && val < sect.Addr+sect.Size {
2022 if sdat, err := sect.Data(); err == nil {
2023 data := sdat[val-sect.Addr:]
2024 strlen := bo.Uint64(data[:8])
2025 if strlen > (1<<(uint(p.IntSize*8)-1) - 1) { // greater than MaxInt?
2026 fatalf("string literal too big")
2028 strlens[n] = int(strlen)
2039 return d, ints, floats, strs
2042 if f, err := pe.Open(gccTmp()); err == nil {
2046 fatalf("cannot load DWARF output from %s: %v", gccTmp(), err)
2048 bo := binary.LittleEndian
2049 for _, s := range f.Symbols {
2051 case isDebugInts(s.Name):
2052 if i := int(s.SectionNumber) - 1; 0 <= i && i < len(f.Sections) {
2053 sect := f.Sections[i]
2054 if s.Value < sect.Size {
2055 if sdat, err := sect.Data(); err == nil {
2056 data := sdat[s.Value:]
2057 ints = make([]int64, len(data)/8)
2058 for i := range ints {
2059 ints[i] = int64(bo.Uint64(data[i*8:]))
2064 case isDebugFloats(s.Name):
2065 if i := int(s.SectionNumber) - 1; 0 <= i && i < len(f.Sections) {
2066 sect := f.Sections[i]
2067 if s.Value < sect.Size {
2068 if sdat, err := sect.Data(); err == nil {
2069 data := sdat[s.Value:]
2070 floats = make([]float64, len(data)/8)
2071 for i := range floats {
2072 floats[i] = math.Float64frombits(bo.Uint64(data[i*8:]))
2078 if n := indexOfDebugStr(s.Name); n != -1 {
2079 if i := int(s.SectionNumber) - 1; 0 <= i && i < len(f.Sections) {
2080 sect := f.Sections[i]
2081 if s.Value < sect.Size {
2082 if sdat, err := sect.Data(); err == nil {
2083 data := sdat[s.Value:]
2084 strdata[n] = string(data)
2090 if n := indexOfDebugStrlen(s.Name); n != -1 {
2091 if i := int(s.SectionNumber) - 1; 0 <= i && i < len(f.Sections) {
2092 sect := f.Sections[i]
2093 if s.Value < sect.Size {
2094 if sdat, err := sect.Data(); err == nil {
2095 data := sdat[s.Value:]
2096 strlen := bo.Uint64(data[:8])
2097 if strlen > (1<<(uint(p.IntSize*8)-1) - 1) { // greater than MaxInt?
2098 fatalf("string literal too big")
2100 strlens[n] = int(strlen)
2111 return d, ints, floats, strs
2114 if f, err := xcoff.Open(gccTmp()); err == nil {
2118 fatalf("cannot load DWARF output from %s: %v", gccTmp(), err)
2120 bo := binary.BigEndian
2121 for _, s := range f.Symbols {
2123 case isDebugInts(s.Name):
2124 if i := int(s.SectionNumber) - 1; 0 <= i && i < len(f.Sections) {
2125 sect := f.Sections[i]
2126 if s.Value < sect.Size {
2127 if sdat, err := sect.Data(); err == nil {
2128 data := sdat[s.Value:]
2129 ints = make([]int64, len(data)/8)
2130 for i := range ints {
2131 ints[i] = int64(bo.Uint64(data[i*8:]))
2136 case isDebugFloats(s.Name):
2137 if i := int(s.SectionNumber) - 1; 0 <= i && i < len(f.Sections) {
2138 sect := f.Sections[i]
2139 if s.Value < sect.Size {
2140 if sdat, err := sect.Data(); err == nil {
2141 data := sdat[s.Value:]
2142 floats = make([]float64, len(data)/8)
2143 for i := range floats {
2144 floats[i] = math.Float64frombits(bo.Uint64(data[i*8:]))
2150 if n := indexOfDebugStr(s.Name); n != -1 {
2151 if i := int(s.SectionNumber) - 1; 0 <= i && i < len(f.Sections) {
2152 sect := f.Sections[i]
2153 if s.Value < sect.Size {
2154 if sdat, err := sect.Data(); err == nil {
2155 data := sdat[s.Value:]
2156 strdata[n] = string(data)
2162 if n := indexOfDebugStrlen(s.Name); n != -1 {
2163 if i := int(s.SectionNumber) - 1; 0 <= i && i < len(f.Sections) {
2164 sect := f.Sections[i]
2165 if s.Value < sect.Size {
2166 if sdat, err := sect.Data(); err == nil {
2167 data := sdat[s.Value:]
2168 strlen := bo.Uint64(data[:8])
2169 if strlen > (1<<(uint(p.IntSize*8)-1) - 1) { // greater than MaxInt?
2170 fatalf("string literal too big")
2172 strlens[n] = int(strlen)
2182 return d, ints, floats, strs
2184 fatalf("cannot parse gcc output %s as ELF, Mach-O, PE, XCOFF object", gccTmp())
2185 panic("not reached")
2188 // gccDefines runs gcc -E -dM -xc - over the C program stdin
2189 // and returns the corresponding standard output, which is the
2190 // #defines that gcc encountered while processing the input
2191 // and its included files.
2192 func (p *Package) gccDefines(stdin []byte) string {
2193 base := append(gccBaseCmd, "-E", "-dM", "-xc")
2194 base = append(base, p.gccMachine()...)
2195 stdout, _ := runGcc(stdin, append(append(base, p.GccOptions...), "-"))
2199 // gccErrors runs gcc over the C program stdin and returns
2200 // the errors that gcc prints. That is, this function expects
2202 func (p *Package) gccErrors(stdin []byte, extraArgs ...string) string {
2203 // TODO(rsc): require failure
2206 // Optimization options can confuse the error messages; remove them.
2207 nargs := make([]string, 0, len(args)+len(extraArgs))
2208 for _, arg := range args {
2209 if !strings.HasPrefix(arg, "-O") {
2210 nargs = append(nargs, arg)
2214 // Force -O0 optimization and append extra arguments, but keep the
2215 // trailing "-" at the end.
2216 li := len(nargs) - 1
2219 nargs = append(nargs, extraArgs...)
2220 nargs = append(nargs, last)
2223 fmt.Fprintf(os.Stderr, "$ %s <<EOF\n", strings.Join(nargs, " "))
2224 os.Stderr.Write(stdin)
2225 fmt.Fprint(os.Stderr, "EOF\n")
2227 stdout, stderr, _ := run(stdin, nargs)
2229 os.Stderr.Write(stdout)
2230 os.Stderr.Write(stderr)
2232 return string(stderr)
2235 // runGcc runs the gcc command line args with stdin on standard input.
2236 // If the command exits with a non-zero exit status, runGcc prints
2237 // details about what was run and exits.
2238 // Otherwise runGcc returns the data written to standard output and standard error.
2239 // Note that for some of the uses we expect useful data back
2240 // on standard error, but for those uses gcc must still exit 0.
2241 func runGcc(stdin []byte, args []string) (string, string) {
2243 fmt.Fprintf(os.Stderr, "$ %s <<EOF\n", strings.Join(args, " "))
2244 os.Stderr.Write(stdin)
2245 fmt.Fprint(os.Stderr, "EOF\n")
2247 stdout, stderr, ok := run(stdin, args)
2249 os.Stderr.Write(stdout)
2250 os.Stderr.Write(stderr)
2253 os.Stderr.Write(stderr)
2256 return string(stdout), string(stderr)
2259 // A typeConv is a translator from dwarf types to Go types
2260 // with equivalent memory layout.
2261 type typeConv struct {
2262 // Cache of already-translated or in-progress types.
2265 // Map from types to incomplete pointers to those types.
2266 ptrs map[string][]*Type
2267 // Keys of ptrs in insertion order (deterministic worklist)
2268 // ptrKeys contains exactly the keys in ptrs.
2269 ptrKeys []dwarf.Type
2271 // Type names X for which there exists an XGetTypeID function with type func() CFTypeID.
2272 getTypeIDs map[string]bool
2274 // incompleteStructs contains C structs that should be marked Incomplete.
2275 incompleteStructs map[string]bool
2277 // Predeclared types.
2279 byte ast.Expr // denotes padding
2280 int8, int16, int32, int64 ast.Expr
2281 uint8, uint16, uint32, uint64, uintptr ast.Expr
2282 float32, float64 ast.Expr
2283 complex64, complex128 ast.Expr
2286 goVoid ast.Expr // _Ctype_void, denotes C's void
2287 goVoidPtr ast.Expr // unsafe.Pointer or *byte
2294 var typedef = make(map[string]*Type)
2295 var goIdent = make(map[string]*ast.Ident)
2297 // unionWithPointer is true for a Go type that represents a C union (or class)
2298 // that may contain a pointer. This is used for cgo pointer checking.
2299 var unionWithPointer = make(map[ast.Expr]bool)
2301 // anonymousStructTag provides a consistent tag for an anonymous struct.
2302 // The same dwarf.StructType pointer will always get the same tag.
2303 var anonymousStructTag = make(map[*dwarf.StructType]string)
2305 func (c *typeConv) Init(ptrSize, intSize int64) {
2308 c.m = make(map[string]*Type)
2309 c.ptrs = make(map[string][]*Type)
2310 c.getTypeIDs = make(map[string]bool)
2311 c.incompleteStructs = make(map[string]bool)
2312 c.bool = c.Ident("bool")
2313 c.byte = c.Ident("byte")
2314 c.int8 = c.Ident("int8")
2315 c.int16 = c.Ident("int16")
2316 c.int32 = c.Ident("int32")
2317 c.int64 = c.Ident("int64")
2318 c.uint8 = c.Ident("uint8")
2319 c.uint16 = c.Ident("uint16")
2320 c.uint32 = c.Ident("uint32")
2321 c.uint64 = c.Ident("uint64")
2322 c.uintptr = c.Ident("uintptr")
2323 c.float32 = c.Ident("float32")
2324 c.float64 = c.Ident("float64")
2325 c.complex64 = c.Ident("complex64")
2326 c.complex128 = c.Ident("complex128")
2327 c.void = c.Ident("void")
2328 c.string = c.Ident("string")
2329 c.goVoid = c.Ident("_Ctype_void")
2331 // Normally cgo translates void* to unsafe.Pointer,
2332 // but for historical reasons -godefs uses *byte instead.
2334 c.goVoidPtr = &ast.StarExpr{X: c.byte}
2336 c.goVoidPtr = c.Ident("unsafe.Pointer")
2340 // base strips away qualifiers and typedefs to get the underlying type.
2341 func base(dt dwarf.Type) dwarf.Type {
2343 if d, ok := dt.(*dwarf.QualType); ok {
2347 if d, ok := dt.(*dwarf.TypedefType); ok {
2356 // unqual strips away qualifiers from a DWARF type.
2357 // In general we don't care about top-level qualifiers.
2358 func unqual(dt dwarf.Type) dwarf.Type {
2360 if d, ok := dt.(*dwarf.QualType); ok {
2369 // Map from dwarf text names to aliases we use in package "C".
2370 var dwarfToName = map[string]string{
2372 "long unsigned int": "ulong",
2373 "unsigned int": "uint",
2374 "short unsigned int": "ushort",
2375 "unsigned short": "ushort", // Used by Clang; issue 13129.
2376 "short int": "short",
2377 "long long int": "longlong",
2378 "long long unsigned int": "ulonglong",
2379 "signed char": "schar",
2380 "unsigned char": "uchar",
2381 "unsigned long": "ulong", // Used by Clang 14; issue 53013.
2382 "unsigned long long": "ulonglong", // Used by Clang 14; issue 53013.
2385 const signedDelta = 64
2387 // String returns the current type representation. Format arguments
2388 // are assembled within this method so that any changes in mutable
2389 // values are taken into account.
2390 func (tr *TypeRepr) String() string {
2391 if len(tr.Repr) == 0 {
2394 if len(tr.FormatArgs) == 0 {
2397 return fmt.Sprintf(tr.Repr, tr.FormatArgs...)
2400 // Empty reports whether the result of String would be "".
2401 func (tr *TypeRepr) Empty() bool {
2402 return len(tr.Repr) == 0
2405 // Set modifies the type representation.
2406 // If fargs are provided, repr is used as a format for fmt.Sprintf.
2407 // Otherwise, repr is used unprocessed as the type representation.
2408 func (tr *TypeRepr) Set(repr string, fargs ...interface{}) {
2410 tr.FormatArgs = fargs
2413 // FinishType completes any outstanding type mapping work.
2414 // In particular, it resolves incomplete pointer types.
2415 func (c *typeConv) FinishType(pos token.Pos) {
2416 // Completing one pointer type might produce more to complete.
2417 // Keep looping until they're all done.
2418 for len(c.ptrKeys) > 0 {
2419 dtype := c.ptrKeys[0]
2420 dtypeKey := dtype.String()
2421 c.ptrKeys = c.ptrKeys[1:]
2422 ptrs := c.ptrs[dtypeKey]
2423 delete(c.ptrs, dtypeKey)
2425 // Note Type might invalidate c.ptrs[dtypeKey].
2426 t := c.Type(dtype, pos)
2427 for _, ptr := range ptrs {
2428 ptr.Go.(*ast.StarExpr).X = t.Go
2429 ptr.C.Set("%s*", t.C)
2434 // Type returns a *Type with the same memory layout as
2435 // dtype when used as the type of a variable or a struct field.
2436 func (c *typeConv) Type(dtype dwarf.Type, pos token.Pos) *Type {
2437 return c.loadType(dtype, pos, "")
2440 // loadType recursively loads the requested dtype and its dependency graph.
2441 func (c *typeConv) loadType(dtype dwarf.Type, pos token.Pos, parent string) *Type {
2442 // Always recompute bad pointer typedefs, as the set of such
2443 // typedefs changes as we see more types.
2445 if dtt, ok := dtype.(*dwarf.TypedefType); ok && c.badPointerTypedef(dtt) {
2449 // The cache key should be relative to its parent.
2450 // See issue https://golang.org/issue/31891
2451 key := parent + " > " + dtype.String()
2454 if t, ok := c.m[key]; ok {
2456 fatalf("%s: type conversion loop at %s", lineno(pos), dtype)
2463 t.Size = dtype.Size() // note: wrong for array of pointers, corrected below
2465 t.C = &TypeRepr{Repr: dtype.Common().Name}
2468 switch dt := dtype.(type) {
2470 fatalf("%s: unexpected type: %s", lineno(pos), dtype)
2472 case *dwarf.AddrType:
2473 if t.Size != c.ptrSize {
2474 fatalf("%s: unexpected: %d-byte address type - %s", lineno(pos), t.Size, dtype)
2479 case *dwarf.ArrayType:
2480 if dt.StrideBitSize > 0 {
2481 // Cannot represent bit-sized elements in Go.
2482 t.Go = c.Opaque(t.Size)
2487 // Indicates flexible array member, which Go doesn't support.
2488 // Translate to zero-length array instead.
2491 sub := c.Type(dt.Type, pos)
2493 t.Go = &ast.ArrayType{
2494 Len: c.intExpr(count),
2497 // Recalculate t.Size now that we know sub.Size.
2498 t.Size = count * sub.Size
2499 t.C.Set("__typeof__(%s[%d])", sub.C, dt.Count)
2501 case *dwarf.BoolType:
2505 case *dwarf.CharType:
2507 fatalf("%s: unexpected: %d-byte char type - %s", lineno(pos), t.Size, dtype)
2512 case *dwarf.EnumType:
2513 if t.Align = t.Size; t.Align >= c.ptrSize {
2516 t.C.Set("enum " + dt.EnumName)
2518 t.EnumValues = make(map[string]int64)
2519 for _, ev := range dt.Val {
2520 t.EnumValues[ev.Name] = ev.Val
2522 signed = signedDelta
2525 switch t.Size + int64(signed) {
2527 fatalf("%s: unexpected: %d-byte enum type - %s", lineno(pos), t.Size, dtype)
2536 case 1 + signedDelta:
2538 case 2 + signedDelta:
2540 case 4 + signedDelta:
2542 case 8 + signedDelta:
2546 case *dwarf.FloatType:
2549 fatalf("%s: unexpected: %d-byte float type - %s", lineno(pos), t.Size, dtype)
2555 if t.Align = t.Size; t.Align >= c.ptrSize {
2559 case *dwarf.ComplexType:
2562 fatalf("%s: unexpected: %d-byte complex type - %s", lineno(pos), t.Size, dtype)
2568 if t.Align = t.Size / 2; t.Align >= c.ptrSize {
2572 case *dwarf.FuncType:
2573 // No attempt at translation: would enable calls
2574 // directly between worlds, but we need to moderate those.
2578 case *dwarf.IntType:
2580 fatalf("%s: unexpected: %d-bit int type - %s", lineno(pos), dt.BitSize, dtype)
2584 fatalf("%s: unexpected: %d-byte int type - %s", lineno(pos), t.Size, dtype)
2594 t.Go = &ast.ArrayType{
2595 Len: c.intExpr(t.Size),
2599 if t.Align = t.Size; t.Align >= c.ptrSize {
2603 case *dwarf.PtrType:
2604 // Clang doesn't emit DW_AT_byte_size for pointer types.
2605 if t.Size != c.ptrSize && t.Size != -1 {
2606 fatalf("%s: unexpected: %d-byte pointer type - %s", lineno(pos), t.Size, dtype)
2611 if _, ok := base(dt.Type).(*dwarf.VoidType); ok {
2616 if d, ok := dq.(*dwarf.QualType); ok {
2617 t.C.Set(d.Qual + " " + t.C.String())
2626 // Placeholder initialization; completed in FinishType.
2627 t.Go = &ast.StarExpr{}
2628 t.C.Set("<incomplete>*")
2629 key := dt.Type.String()
2630 if _, ok := c.ptrs[key]; !ok {
2631 c.ptrKeys = append(c.ptrKeys, dt.Type)
2633 c.ptrs[key] = append(c.ptrs[key], t)
2635 case *dwarf.QualType:
2636 t1 := c.Type(dt.Type, pos)
2640 if unionWithPointer[t1.Go] {
2641 unionWithPointer[t.Go] = true
2645 t.C.Set("%s "+dt.Qual, t1.C)
2648 case *dwarf.StructType:
2649 // Convert to Go struct, being careful about alignment.
2650 // Have to give it a name to simulate C "struct foo" references.
2651 tag := dt.StructName
2652 if dt.ByteSize < 0 && tag == "" { // opaque unnamed struct - should not be possible
2656 tag = anonymousStructTag[dt]
2658 tag = "__" + strconv.Itoa(tagGen)
2660 anonymousStructTag[dt] = tag
2662 } else if t.C.Empty() {
2663 t.C.Set(dt.Kind + " " + tag)
2665 name := c.Ident("_Ctype_" + dt.Kind + "_" + tag)
2666 t.Go = name // publish before recursive calls
2667 goIdent[name.Name] = name
2668 if dt.ByteSize < 0 {
2669 // Don't override old type
2670 if _, ok := typedef[name.Name]; ok {
2674 // Size calculation in c.Struct/c.Opaque will die with size=-1 (unknown),
2675 // so execute the basic things that the struct case would do
2676 // other than try to determine a Go representation.
2678 tt.C = &TypeRepr{"%s %s", []interface{}{dt.Kind, tag}}
2679 // We don't know what the representation of this struct is, so don't let
2680 // anyone allocate one on the Go side. As a side effect of this annotation,
2681 // pointers to this type will not be considered pointers in Go. They won't
2682 // get writebarrier-ed or adjusted during a stack copy. This should handle
2683 // all the cases badPointerTypedef used to handle, but hopefully will
2684 // continue to work going forward without any more need for cgo changes.
2685 tt.Go = c.Ident(incomplete)
2686 typedef[name.Name] = &tt
2690 case "class", "union":
2691 t.Go = c.Opaque(t.Size)
2692 if c.dwarfHasPointer(dt, pos) {
2693 unionWithPointer[t.Go] = true
2696 t.C.Set("__typeof__(unsigned char[%d])", t.Size)
2698 t.Align = 1 // TODO: should probably base this on field alignment.
2699 typedef[name.Name] = t
2701 g, csyntax, align := c.Struct(dt, pos)
2708 tt.C = &TypeRepr{"struct %s", []interface{}{tag}}
2711 if c.incompleteStructs[tag] {
2712 tt.Go = c.Ident(incomplete)
2714 typedef[name.Name] = &tt
2717 case *dwarf.TypedefType:
2718 // Record typedef for printing.
2719 if dt.Name == "_GoString_" {
2720 // Special C name for Go string type.
2721 // Knows string layout used by compilers: pointer plus length,
2722 // which rounds up to 2 pointers after alignment.
2724 t.Size = c.ptrSize * 2
2728 if dt.Name == "_GoBytes_" {
2729 // Special C name for Go []byte type.
2730 // Knows slice layout used by compilers: pointer, length, cap.
2731 t.Go = c.Ident("[]byte")
2732 t.Size = c.ptrSize + 4 + 4
2736 name := c.Ident("_Ctype_" + dt.Name)
2737 goIdent[name.Name] = name
2739 if c.anonymousStructTypedef(dt) {
2740 // only load type recursively for typedefs of anonymous
2741 // structs, see issues 37479 and 37621.
2744 sub := c.loadType(dt.Type, pos, akey)
2745 if c.badPointerTypedef(dt) {
2746 // Treat this typedef as a uintptr.
2751 // Make sure we update any previously computed type.
2752 if oldType := typedef[name.Name]; oldType != nil {
2754 oldType.BadPointer = true
2757 if c.badVoidPointerTypedef(dt) {
2758 // Treat this typedef as a pointer to a _cgopackage.Incomplete.
2760 s.Go = c.Ident("*" + incomplete)
2762 // Make sure we update any previously computed type.
2763 if oldType := typedef[name.Name]; oldType != nil {
2767 // Check for non-pointer "struct <tag>{...}; typedef struct <tag> *<name>"
2768 // typedefs that should be marked Incomplete.
2769 if ptr, ok := dt.Type.(*dwarf.PtrType); ok {
2770 if strct, ok := ptr.Type.(*dwarf.StructType); ok {
2771 if c.badStructPointerTypedef(dt.Name, strct) {
2772 c.incompleteStructs[strct.StructName] = true
2773 // Make sure we update any previously computed type.
2774 name := "_Ctype_struct_" + strct.StructName
2775 if oldType := typedef[name]; oldType != nil {
2776 oldType.Go = c.Ident(incomplete)
2782 t.BadPointer = sub.BadPointer
2783 if unionWithPointer[sub.Go] {
2784 unionWithPointer[t.Go] = true
2788 oldType := typedef[name.Name]
2792 tt.BadPointer = sub.BadPointer
2793 typedef[name.Name] = &tt
2796 // If sub.Go.Name is "_Ctype_struct_foo" or "_Ctype_union_foo" or "_Ctype_class_foo",
2797 // use that as the Go form for this typedef too, so that the typedef will be interchangeable
2798 // with the base type.
2799 // In -godefs mode, do this for all typedefs.
2800 if isStructUnionClass(sub.Go) || *godefs {
2803 if isStructUnionClass(sub.Go) {
2804 // Use the typedef name for C code.
2805 typedef[sub.Go.(*ast.Ident).Name].C = t.C
2808 // If we've seen this typedef before, and it
2809 // was an anonymous struct/union/class before
2810 // too, use the old definition.
2811 // TODO: it would be safer to only do this if
2812 // we verify that the types are the same.
2813 if oldType != nil && isStructUnionClass(oldType.Go) {
2818 case *dwarf.UcharType:
2820 fatalf("%s: unexpected: %d-byte uchar type - %s", lineno(pos), t.Size, dtype)
2825 case *dwarf.UintType:
2827 fatalf("%s: unexpected: %d-bit uint type - %s", lineno(pos), dt.BitSize, dtype)
2831 fatalf("%s: unexpected: %d-byte uint type - %s", lineno(pos), t.Size, dtype)
2841 t.Go = &ast.ArrayType{
2842 Len: c.intExpr(t.Size),
2846 if t.Align = t.Size; t.Align >= c.ptrSize {
2850 case *dwarf.VoidType:
2856 switch dtype.(type) {
2857 case *dwarf.AddrType, *dwarf.BoolType, *dwarf.CharType, *dwarf.ComplexType, *dwarf.IntType, *dwarf.FloatType, *dwarf.UcharType, *dwarf.UintType:
2858 s := dtype.Common().Name
2860 if ss, ok := dwarfToName[s]; ok {
2863 s = strings.Replace(s, " ", "", -1)
2864 name := c.Ident("_Ctype_" + s)
2866 typedef[name.Name] = &tt
2874 // Unsized types are [0]byte, unless they're typedefs of other types
2875 // or structs with tags.
2876 // if so, use the name we've already defined.
2878 switch dt := dtype.(type) {
2879 case *dwarf.TypedefType:
2881 case *dwarf.StructType:
2882 if dt.StructName != "" {
2895 fatalf("%s: internal error: did not create C name for %s", lineno(pos), dtype)
2901 // isStructUnionClass reports whether the type described by the Go syntax x
2902 // is a struct, union, or class with a tag.
2903 func isStructUnionClass(x ast.Expr) bool {
2904 id, ok := x.(*ast.Ident)
2909 return strings.HasPrefix(name, "_Ctype_struct_") ||
2910 strings.HasPrefix(name, "_Ctype_union_") ||
2911 strings.HasPrefix(name, "_Ctype_class_")
2914 // FuncArg returns a Go type with the same memory layout as
2915 // dtype when used as the type of a C function argument.
2916 func (c *typeConv) FuncArg(dtype dwarf.Type, pos token.Pos) *Type {
2917 t := c.Type(unqual(dtype), pos)
2918 switch dt := dtype.(type) {
2919 case *dwarf.ArrayType:
2920 // Arrays are passed implicitly as pointers in C.
2921 // In Go, we must be explicit.
2927 Go: &ast.StarExpr{X: t.Go},
2930 case *dwarf.TypedefType:
2931 // C has much more relaxed rules than Go for
2932 // implicit type conversions. When the parameter
2933 // is type T defined as *X, simulate a little of the
2934 // laxness of C by making the argument *X instead of T.
2935 if ptr, ok := base(dt.Type).(*dwarf.PtrType); ok {
2936 // Unless the typedef happens to point to void* since
2937 // Go has special rules around using unsafe.Pointer.
2938 if _, void := base(ptr.Type).(*dwarf.VoidType); void {
2941 // ...or the typedef is one in which we expect bad pointers.
2942 // It will be a uintptr instead of *X.
2943 if c.baseBadPointerTypedef(dt) {
2947 t = c.Type(ptr, pos)
2952 // For a struct/union/class, remember the C spelling,
2953 // in case it has __attribute__((unavailable)).
2955 if isStructUnionClass(t.Go) {
2963 // FuncType returns the Go type analogous to dtype.
2964 // There is no guarantee about matching memory layout.
2965 func (c *typeConv) FuncType(dtype *dwarf.FuncType, pos token.Pos) *FuncType {
2966 p := make([]*Type, len(dtype.ParamType))
2967 gp := make([]*ast.Field, len(dtype.ParamType))
2968 for i, f := range dtype.ParamType {
2969 // gcc's DWARF generator outputs a single DotDotDotType parameter for
2970 // function pointers that specify no parameters (e.g. void
2971 // (*__cgo_0)()). Treat this special case as void. This case is
2972 // invalid according to ISO C anyway (i.e. void (*__cgo_1)(...) is not
2974 if _, ok := f.(*dwarf.DotDotDotType); ok && i == 0 {
2978 p[i] = c.FuncArg(f, pos)
2979 gp[i] = &ast.Field{Type: p[i].Go}
2983 if _, ok := base(dtype.ReturnType).(*dwarf.VoidType); ok {
2984 gr = []*ast.Field{{Type: c.goVoid}}
2985 } else if dtype.ReturnType != nil {
2986 r = c.Type(unqual(dtype.ReturnType), pos)
2987 gr = []*ast.Field{{Type: r.Go}}
2993 Params: &ast.FieldList{List: gp},
2994 Results: &ast.FieldList{List: gr},
3000 func (c *typeConv) Ident(s string) *ast.Ident {
3001 return ast.NewIdent(s)
3004 // Opaque type of n bytes.
3005 func (c *typeConv) Opaque(n int64) ast.Expr {
3006 return &ast.ArrayType{
3012 // Expr for integer n.
3013 func (c *typeConv) intExpr(n int64) ast.Expr {
3014 return &ast.BasicLit{
3016 Value: strconv.FormatInt(n, 10),
3020 // Add padding of given size to fld.
3021 func (c *typeConv) pad(fld []*ast.Field, sizes []int64, size int64) ([]*ast.Field, []int64) {
3024 fld[n] = &ast.Field{Names: []*ast.Ident{c.Ident("_")}, Type: c.Opaque(size)}
3025 sizes = sizes[0 : n+1]
3030 // Struct conversion: return Go and (gc) C syntax for type.
3031 func (c *typeConv) Struct(dt *dwarf.StructType, pos token.Pos) (expr *ast.StructType, csyntax string, align int64) {
3032 // Minimum alignment for a struct is 1 byte.
3035 var buf strings.Builder
3036 buf.WriteString("struct {")
3037 fld := make([]*ast.Field, 0, 2*len(dt.Field)+1) // enough for padding around every field
3038 sizes := make([]int64, 0, 2*len(dt.Field)+1)
3041 // Rename struct fields that happen to be named Go keywords into
3042 // _{keyword}. Create a map from C ident -> Go ident. The Go ident will
3043 // be mangled. Any existing identifier that already has the same name on
3044 // the C-side will cause the Go-mangled version to be prefixed with _.
3045 // (e.g. in a struct with fields '_type' and 'type', the latter would be
3046 // rendered as '__type' in Go).
3047 ident := make(map[string]string)
3048 used := make(map[string]bool)
3049 for _, f := range dt.Field {
3050 ident[f.Name] = f.Name
3055 for cid, goid := range ident {
3056 if token.Lookup(goid).IsKeyword() {
3060 // Also avoid existing fields
3061 for _, exist := used[goid]; exist; _, exist = used[goid] {
3072 for _, f := range dt.Field {
3076 // In godefs mode, if this field is a C11
3077 // anonymous union then treat the first field in the
3078 // union as the field in the struct. This handles
3079 // cases like the glibc <sys/resource.h> file; see
3082 if st, ok := f.Type.(*dwarf.StructType); ok && name == "" && st.Kind == "union" && len(st.Field) > 0 && !used[st.Field[0].Name] {
3083 name = st.Field[0].Name
3085 ft = st.Field[0].Type
3089 // TODO: Handle fields that are anonymous structs by
3090 // promoting the fields of the inner struct.
3092 t := c.Type(ft, pos)
3096 if f.BitOffset > 0 || f.BitSize > 0 {
3097 // The layout of bitfields is implementation defined,
3098 // so we don't know how they correspond to Go fields
3099 // even if they are aligned at byte boundaries.
3103 if talign > 0 && f.ByteOffset%talign != 0 {
3104 // Drop misaligned fields, the same way we drop integer bit fields.
3105 // The goal is to make available what can be made available.
3106 // Otherwise one bad and unneeded field in an otherwise okay struct
3107 // makes the whole program not compile. Much of the time these
3108 // structs are in system headers that cannot be corrected.
3112 // Round off up to talign, assumed to be a power of 2.
3113 off = (off + talign - 1) &^ (talign - 1)
3115 if f.ByteOffset > off {
3116 fld, sizes = c.pad(fld, sizes, f.ByteOffset-off)
3119 if f.ByteOffset < off {
3120 // Drop a packed field that we can't represent.
3127 name = fmt.Sprintf("anon%d", anon)
3131 fld[n] = &ast.Field{Names: []*ast.Ident{c.Ident(ident[name])}, Type: tgo}
3132 sizes = sizes[0 : n+1]
3135 buf.WriteString(t.C.String())
3136 buf.WriteString(" ")
3137 buf.WriteString(name)
3138 buf.WriteString("; ")
3143 if off < dt.ByteSize {
3144 fld, sizes = c.pad(fld, sizes, dt.ByteSize-off)
3148 // If the last field in a non-zero-sized struct is zero-sized
3149 // the compiler is going to pad it by one (see issue 9401).
3150 // We can't permit that, because then the size of the Go
3151 // struct will not be the same as the size of the C struct.
3152 // Our only option in such a case is to remove the field,
3153 // which means that it cannot be referenced from Go.
3154 for off > 0 && sizes[len(sizes)-1] == 0 {
3157 sizes = sizes[0 : n-1]
3160 if off != dt.ByteSize {
3161 fatalf("%s: struct size calculation error off=%d bytesize=%d", lineno(pos), off, dt.ByteSize)
3163 buf.WriteString("}")
3164 csyntax = buf.String()
3169 expr = &ast.StructType{Fields: &ast.FieldList{List: fld}}
3173 // dwarfHasPointer reports whether the DWARF type dt contains a pointer.
3174 func (c *typeConv) dwarfHasPointer(dt dwarf.Type, pos token.Pos) bool {
3175 switch dt := dt.(type) {
3177 fatalf("%s: unexpected type: %s", lineno(pos), dt)
3180 case *dwarf.AddrType, *dwarf.BoolType, *dwarf.CharType, *dwarf.EnumType,
3181 *dwarf.FloatType, *dwarf.ComplexType, *dwarf.FuncType,
3182 *dwarf.IntType, *dwarf.UcharType, *dwarf.UintType, *dwarf.VoidType:
3186 case *dwarf.ArrayType:
3187 return c.dwarfHasPointer(dt.Type, pos)
3189 case *dwarf.PtrType:
3192 case *dwarf.QualType:
3193 return c.dwarfHasPointer(dt.Type, pos)
3195 case *dwarf.StructType:
3196 for _, f := range dt.Field {
3197 if c.dwarfHasPointer(f.Type, pos) {
3203 case *dwarf.TypedefType:
3204 if dt.Name == "_GoString_" || dt.Name == "_GoBytes_" {
3207 return c.dwarfHasPointer(dt.Type, pos)
3211 func upper(s string) string {
3215 r, size := utf8.DecodeRuneInString(s)
3219 return string(unicode.ToUpper(r)) + s[size:]
3222 // godefsFields rewrites field names for use in Go or C definitions.
3223 // It strips leading common prefixes (like tv_ in tv_sec, tv_usec)
3224 // converts names to upper case, and rewrites _ into Pad_godefs_n,
3225 // so that all fields are exported.
3226 func godefsFields(fld []*ast.Field) {
3227 prefix := fieldPrefix(fld)
3229 // Issue 48396: check for duplicate field names.
3231 names := make(map[string]bool)
3233 for _, f := range fld {
3234 for _, n := range f.Names {
3240 name = strings.TrimPrefix(n.Name, prefix)
3244 // Field name conflict: don't remove prefix.
3254 for _, f := range fld {
3255 for _, n := range f.Names {
3256 if n.Name != prefix {
3257 n.Name = strings.TrimPrefix(n.Name, prefix)
3260 // Use exported name instead.
3261 n.Name = "Pad_cgo_" + strconv.Itoa(npad)
3264 n.Name = upper(n.Name)
3269 // fieldPrefix returns the prefix that should be removed from all the
3270 // field names when generating the C or Go code. For generated
3271 // C, we leave the names as is (tv_sec, tv_usec), since that's what
3272 // people are used to seeing in C. For generated Go code, such as
3273 // package syscall's data structures, we drop a common prefix
3274 // (so sec, usec, which will get turned into Sec, Usec for exporting).
3275 func fieldPrefix(fld []*ast.Field) string {
3277 for _, f := range fld {
3278 for _, n := range f.Names {
3279 // Ignore field names that don't have the prefix we're
3280 // looking for. It is common in C headers to have fields
3281 // named, say, _pad in an otherwise prefixed header.
3282 // If the struct has 3 fields tv_sec, tv_usec, _pad1, then we
3283 // still want to remove the tv_ prefix.
3284 // The check for "orig_" here handles orig_eax in the
3285 // x86 ptrace register sets, which otherwise have all fields
3286 // with reg_ prefixes.
3287 if strings.HasPrefix(n.Name, "orig_") || strings.HasPrefix(n.Name, "_") {
3290 i := strings.Index(n.Name, "_")
3295 prefix = n.Name[:i+1]
3296 } else if prefix != n.Name[:i+1] {
3304 // anonymousStructTypedef reports whether dt is a C typedef for an anonymous
3306 func (c *typeConv) anonymousStructTypedef(dt *dwarf.TypedefType) bool {
3307 st, ok := dt.Type.(*dwarf.StructType)
3308 return ok && st.StructName == ""
3311 // badPointerTypedef reports whether dt is a C typedef that should not be
3312 // considered a pointer in Go. A typedef is bad if C code sometimes stores
3313 // non-pointers in this type.
3314 // TODO: Currently our best solution is to find these manually and list them as
3315 // they come up. A better solution is desired.
3316 // Note: DEPRECATED. There is now a better solution. Search for incomplete in this file.
3317 func (c *typeConv) badPointerTypedef(dt *dwarf.TypedefType) bool {
3318 if c.badCFType(dt) {
3324 if c.badEGLType(dt) {
3330 // badVoidPointerTypedef is like badPointerTypeDef, but for "void *" typedefs that should be _cgopackage.Incomplete.
3331 func (c *typeConv) badVoidPointerTypedef(dt *dwarf.TypedefType) bool {
3332 // Match the Windows HANDLE type (#42018).
3333 if goos != "windows" || dt.Name != "HANDLE" {
3336 // Check that the typedef is "typedef void *<name>".
3337 if ptr, ok := dt.Type.(*dwarf.PtrType); ok {
3338 if _, ok := ptr.Type.(*dwarf.VoidType); ok {
3345 // badStructPointerTypedef is like badVoidPointerTypedef but for structs.
3346 func (c *typeConv) badStructPointerTypedef(name string, dt *dwarf.StructType) bool {
3347 // Windows handle types can all potentially contain non-pointers.
3348 // badVoidPointerTypedef handles the "void *" HANDLE type, but other
3349 // handles are defined as
3351 // struct <name>__{int unused;}; typedef struct <name>__ *name;
3353 // by the DECLARE_HANDLE macro in STRICT mode. The macro is declared in
3354 // the Windows ntdef.h header,
3356 // https://github.com/tpn/winsdk-10/blob/master/Include/10.0.16299.0/shared/ntdef.h#L779
3357 if goos != "windows" {
3360 if len(dt.Field) != 1 {
3363 if dt.StructName != name+"__" {
3366 if f := dt.Field[0]; f.Name != "unused" || f.Type.Common().Name != "int" {
3372 // baseBadPointerTypedef reports whether the base of a chain of typedefs is a bad typedef
3373 // as badPointerTypedef reports.
3374 func (c *typeConv) baseBadPointerTypedef(dt *dwarf.TypedefType) bool {
3376 if t, ok := dt.Type.(*dwarf.TypedefType); ok {
3382 return c.badPointerTypedef(dt)
3385 func (c *typeConv) badCFType(dt *dwarf.TypedefType) bool {
3386 // The real bad types are CFNumberRef and CFDateRef.
3387 // Sometimes non-pointers are stored in these types.
3388 // CFTypeRef is a supertype of those, so it can have bad pointers in it as well.
3389 // We return true for the other *Ref types just so casting between them is easier.
3390 // We identify the correct set of types as those ending in Ref and for which
3391 // there exists a corresponding GetTypeID function.
3392 // See comment below for details about the bad pointers.
3393 if goos != "darwin" && goos != "ios" {
3397 if !strings.HasSuffix(s, "Ref") {
3404 if c.getTypeIDs[s] {
3407 if i := strings.Index(s, "Mutable"); i >= 0 && c.getTypeIDs[s[:i]+s[i+7:]] {
3408 // Mutable and immutable variants share a type ID.
3414 // Comment from Darwin's CFInternal.h
3416 // Tagged pointer support
3417 // Low-bit set means tagged object, next 3 bits (currently)
3418 // define the tagged object class, next 4 bits are for type
3419 // information for the specific tagged object class. Thus,
3420 // the low byte is for type info, and the rest of a pointer
3421 // (32 or 64-bit) is for payload, whatever the tagged class.
3423 // Note that the specific integers used to identify the
3424 // specific tagged classes can and will change from release
3425 // to release (that's why this stuff is in CF*Internal*.h),
3426 // as can the definition of type info vs payload above.
3429 #define CF_IS_TAGGED_OBJ(PTR) ((uintptr_t)(PTR) & 0x1)
3430 #define CF_TAGGED_OBJ_TYPE(PTR) ((uintptr_t)(PTR) & 0xF)
3432 #define CF_IS_TAGGED_OBJ(PTR) 0
3433 #define CF_TAGGED_OBJ_TYPE(PTR) 0
3437 kCFTaggedObjectID_Invalid = 0,
3438 kCFTaggedObjectID_Atom = (0 << 1) + 1,
3439 kCFTaggedObjectID_Undefined3 = (1 << 1) + 1,
3440 kCFTaggedObjectID_Undefined2 = (2 << 1) + 1,
3441 kCFTaggedObjectID_Integer = (3 << 1) + 1,
3442 kCFTaggedObjectID_DateTS = (4 << 1) + 1,
3443 kCFTaggedObjectID_ManagedObjectID = (5 << 1) + 1, // Core Data
3444 kCFTaggedObjectID_Date = (6 << 1) + 1,
3445 kCFTaggedObjectID_Undefined7 = (7 << 1) + 1,
3449 func (c *typeConv) badJNI(dt *dwarf.TypedefType) bool {
3450 // In Dalvik and ART, the jobject type in the JNI interface of the JVM has the
3451 // property that it is sometimes (always?) a small integer instead of a real pointer.
3452 // Note: although only the android JVMs are bad in this respect, we declare the JNI types
3453 // bad regardless of platform, so the same Go code compiles on both android and non-android.
3454 if parent, ok := jniTypes[dt.Name]; ok {
3455 // Try to make sure we're talking about a JNI type, not just some random user's
3456 // type that happens to use the same name.
3457 // C doesn't have the notion of a package, so it's hard to be certain.
3459 // Walk up to jobject, checking each typedef on the way.
3462 t, ok := w.Type.(*dwarf.TypedefType)
3463 if !ok || t.Name != parent {
3467 parent, ok = jniTypes[w.Name]
3473 // Check that the typedef is either:
3476 // typedef struct _jobject *jobject;
3477 // 2: (in NDK16 in C++)
3478 // class _jobject {};
3479 // typedef _jobject* jobject;
3480 // 3: (in NDK16 in C)
3481 // typedef void* jobject;
3482 if ptr, ok := w.Type.(*dwarf.PtrType); ok {
3483 switch v := ptr.Type.(type) {
3484 case *dwarf.VoidType:
3486 case *dwarf.StructType:
3487 if v.StructName == "_jobject" && len(v.Field) == 0 {
3505 func (c *typeConv) badEGLType(dt *dwarf.TypedefType) bool {
3506 if dt.Name != "EGLDisplay" && dt.Name != "EGLConfig" {
3509 // Check that the typedef is "typedef void *<name>".
3510 if ptr, ok := dt.Type.(*dwarf.PtrType); ok {
3511 if _, ok := ptr.Type.(*dwarf.VoidType); ok {
3518 // jniTypes maps from JNI types that we want to be uintptrs, to the underlying type to which
3519 // they are mapped. The base "jobject" maps to the empty string.
3520 var jniTypes = map[string]string{
3522 "jclass": "jobject",
3523 "jthrowable": "jobject",
3524 "jstring": "jobject",
3525 "jarray": "jobject",
3526 "jbooleanArray": "jarray",
3527 "jbyteArray": "jarray",
3528 "jcharArray": "jarray",
3529 "jshortArray": "jarray",
3530 "jintArray": "jarray",
3531 "jlongArray": "jarray",
3532 "jfloatArray": "jarray",
3533 "jdoubleArray": "jarray",
3534 "jobjectArray": "jarray",