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