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