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

View as plain text