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

View as plain text