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