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