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