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