github.com/varialus/godfly@v0.0.0-20130904042352-1934f9f095ab/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 "os" 24 "strconv" 25 "strings" 26 "unicode" 27 "unicode/utf8" 28 ) 29 30 var debugDefine = flag.Bool("debug-define", false, "print relevant #defines") 31 var debugGcc = flag.Bool("debug-gcc", false, "print gcc invocations") 32 33 var nameToC = map[string]string{ 34 "schar": "signed char", 35 "uchar": "unsigned char", 36 "ushort": "unsigned short", 37 "uint": "unsigned int", 38 "ulong": "unsigned long", 39 "longlong": "long long", 40 "ulonglong": "unsigned long long", 41 "complexfloat": "float complex", 42 "complexdouble": "double complex", 43 } 44 45 // cname returns the C name to use for C.s. 46 // The expansions are listed in nameToC and also 47 // struct_foo becomes "struct foo", and similarly for 48 // union and enum. 49 func cname(s string) string { 50 if t, ok := nameToC[s]; ok { 51 return t 52 } 53 54 if strings.HasPrefix(s, "struct_") { 55 return "struct " + s[len("struct_"):] 56 } 57 if strings.HasPrefix(s, "union_") { 58 return "union " + s[len("union_"):] 59 } 60 if strings.HasPrefix(s, "enum_") { 61 return "enum " + s[len("enum_"):] 62 } 63 if strings.HasPrefix(s, "sizeof_") { 64 return "sizeof(" + cname(s[len("sizeof_"):]) + ")" 65 } 66 return s 67 } 68 69 // DiscardCgoDirectives processes the import C preamble, and discards 70 // all #cgo CFLAGS and LDFLAGS directives, so they don't make their 71 // way into _cgo_export.h. 72 func (f *File) DiscardCgoDirectives() { 73 linesIn := strings.Split(f.Preamble, "\n") 74 linesOut := make([]string, 0, len(linesIn)) 75 for _, line := range linesIn { 76 l := strings.TrimSpace(line) 77 if len(l) < 5 || l[:4] != "#cgo" || !unicode.IsSpace(rune(l[4])) { 78 linesOut = append(linesOut, line) 79 } else { 80 linesOut = append(linesOut, "") 81 } 82 } 83 f.Preamble = strings.Join(linesOut, "\n") 84 } 85 86 // addToFlag appends args to flag. All flags are later written out onto the 87 // _cgo_flags file for the build system to use. 88 func (p *Package) addToFlag(flag string, args []string) { 89 p.CgoFlags[flag] = append(p.CgoFlags[flag], args...) 90 if flag == "CFLAGS" { 91 // We'll also need these when preprocessing for dwarf information. 92 p.GccOptions = append(p.GccOptions, args...) 93 } 94 } 95 96 // splitQuoted splits the string s around each instance of one or more consecutive 97 // white space characters while taking into account quotes and escaping, and 98 // returns an array of substrings of s or an empty list if s contains only white space. 99 // Single quotes and double quotes are recognized to prevent splitting within the 100 // quoted region, and are removed from the resulting substrings. If a quote in s 101 // isn't closed err will be set and r will have the unclosed argument as the 102 // last element. The backslash is used for escaping. 103 // 104 // For example, the following string: 105 // 106 // `a b:"c d" 'e''f' "g\""` 107 // 108 // Would be parsed as: 109 // 110 // []string{"a", "b:c d", "ef", `g"`} 111 // 112 func splitQuoted(s string) (r []string, err error) { 113 var args []string 114 arg := make([]rune, len(s)) 115 escaped := false 116 quoted := false 117 quote := '\x00' 118 i := 0 119 for _, r := range s { 120 switch { 121 case escaped: 122 escaped = false 123 case r == '\\': 124 escaped = true 125 continue 126 case quote != 0: 127 if r == quote { 128 quote = 0 129 continue 130 } 131 case r == '"' || r == '\'': 132 quoted = true 133 quote = r 134 continue 135 case unicode.IsSpace(r): 136 if quoted || i > 0 { 137 quoted = false 138 args = append(args, string(arg[:i])) 139 i = 0 140 } 141 continue 142 } 143 arg[i] = r 144 i++ 145 } 146 if quoted || i > 0 { 147 args = append(args, string(arg[:i])) 148 } 149 if quote != 0 { 150 err = errors.New("unclosed quote") 151 } else if escaped { 152 err = errors.New("unfinished escaping") 153 } 154 return args, err 155 } 156 157 var safeBytes = []byte(`+-.,/0123456789:=ABCDEFGHIJKLMNOPQRSTUVWXYZ\_abcdefghijklmnopqrstuvwxyz`) 158 159 func safeName(s string) bool { 160 if s == "" { 161 return false 162 } 163 for i := 0; i < len(s); i++ { 164 if c := s[i]; c < 0x80 && bytes.IndexByte(safeBytes, c) < 0 { 165 return false 166 } 167 } 168 return true 169 } 170 171 // Translate rewrites f.AST, the original Go input, to remove 172 // references to the imported package C, replacing them with 173 // references to the equivalent Go types, functions, and variables. 174 func (p *Package) Translate(f *File) { 175 for _, cref := range f.Ref { 176 // Convert C.ulong to C.unsigned long, etc. 177 cref.Name.C = cname(cref.Name.Go) 178 } 179 p.loadDefines(f) 180 needType := p.guessKinds(f) 181 if len(needType) > 0 { 182 p.loadDWARF(f, needType) 183 } 184 p.rewriteRef(f) 185 } 186 187 // loadDefines coerces gcc into spitting out the #defines in use 188 // in the file f and saves relevant renamings in f.Name[name].Define. 189 func (p *Package) loadDefines(f *File) { 190 var b bytes.Buffer 191 b.WriteString(builtinProlog) 192 b.WriteString(f.Preamble) 193 stdout := p.gccDefines(b.Bytes()) 194 195 for _, line := range strings.Split(stdout, "\n") { 196 if len(line) < 9 || line[0:7] != "#define" { 197 continue 198 } 199 200 line = strings.TrimSpace(line[8:]) 201 202 var key, val string 203 spaceIndex := strings.Index(line, " ") 204 tabIndex := strings.Index(line, "\t") 205 206 if spaceIndex == -1 && tabIndex == -1 { 207 continue 208 } else if tabIndex == -1 || (spaceIndex != -1 && spaceIndex < tabIndex) { 209 key = line[0:spaceIndex] 210 val = strings.TrimSpace(line[spaceIndex:]) 211 } else { 212 key = line[0:tabIndex] 213 val = strings.TrimSpace(line[tabIndex:]) 214 } 215 216 if n := f.Name[key]; n != nil { 217 if *debugDefine { 218 fmt.Fprintf(os.Stderr, "#define %s %s\n", key, val) 219 } 220 n.Define = val 221 } 222 } 223 } 224 225 // guessKinds tricks gcc into revealing the kind of each 226 // name xxx for the references C.xxx in the Go input. 227 // The kind is either a constant, type, or variable. 228 func (p *Package) guessKinds(f *File) []*Name { 229 // Coerce gcc into telling us whether each name is 230 // a type, a value, or undeclared. We compile a function 231 // containing the line: 232 // name; 233 // If name is a type, gcc will print: 234 // cgo-test:2: warning: useless type name in empty declaration 235 // If name is a value, gcc will print 236 // cgo-test:2: warning: statement with no effect 237 // If name is undeclared, gcc will print 238 // cgo-test:2: error: 'name' undeclared (first use in this function) 239 // A line number directive causes the line number to 240 // correspond to the index in the names array. 241 // 242 // The line also has an enum declaration: 243 // name; enum { _cgo_enum_1 = name }; 244 // If name is not a constant, gcc will print: 245 // cgo-test:4: error: enumerator value for '_cgo_enum_4' is not an integer constant 246 // we assume lines without that error are constants. 247 248 // Make list of names that need sniffing, type lookup. 249 toSniff := make([]*Name, 0, len(f.Name)) 250 needType := make([]*Name, 0, len(f.Name)) 251 252 for _, n := range f.Name { 253 // If we've already found this name as a #define 254 // and we can translate it as a constant value, do so. 255 if n.Define != "" { 256 ok := false 257 if _, err := strconv.Atoi(n.Define); err == nil { 258 ok = true 259 } else if n.Define[0] == '"' || n.Define[0] == '\'' { 260 if _, err := parser.ParseExpr(n.Define); err == nil { 261 ok = true 262 } 263 } 264 if ok { 265 n.Kind = "const" 266 // Turn decimal into hex, just for consistency 267 // with enum-derived constants. Otherwise 268 // in the cgo -godefs output half the constants 269 // are in hex and half are in whatever the #define used. 270 i, err := strconv.ParseInt(n.Define, 0, 64) 271 if err == nil { 272 n.Const = fmt.Sprintf("%#x", i) 273 } else { 274 n.Const = n.Define 275 } 276 continue 277 } 278 279 if isName(n.Define) { 280 n.C = n.Define 281 } 282 } 283 284 // If this is a struct, union, or enum type name, 285 // record the kind but also that we need type information. 286 if strings.HasPrefix(n.C, "struct ") || strings.HasPrefix(n.C, "union ") || strings.HasPrefix(n.C, "enum ") { 287 n.Kind = "type" 288 i := len(needType) 289 needType = needType[0 : i+1] 290 needType[i] = n 291 continue 292 } 293 294 i := len(toSniff) 295 toSniff = toSniff[0 : i+1] 296 toSniff[i] = n 297 } 298 299 if len(toSniff) == 0 { 300 return needType 301 } 302 303 var b bytes.Buffer 304 b.WriteString(builtinProlog) 305 b.WriteString(f.Preamble) 306 b.WriteString("void __cgo__f__(void) {\n") 307 b.WriteString("#line 1 \"cgo-test\"\n") 308 for i, n := range toSniff { 309 fmt.Fprintf(&b, "%s; /* #%d */\nenum { _cgo_enum_%d = %s }; /* #%d */\n", n.C, i, i, n.C, i) 310 } 311 b.WriteString("}\n") 312 stderr := p.gccErrors(b.Bytes()) 313 if stderr == "" { 314 fatalf("gcc produced no output\non input:\n%s", b.Bytes()) 315 } 316 317 names := make([]*Name, len(toSniff)) 318 copy(names, toSniff) 319 320 isConst := make([]bool, len(toSniff)) 321 for i := range isConst { 322 isConst[i] = true // until proven otherwise 323 } 324 325 for _, line := range strings.Split(stderr, "\n") { 326 if len(line) < 9 || line[0:9] != "cgo-test:" { 327 // the user will see any compiler errors when the code is compiled later. 328 continue 329 } 330 line = line[9:] 331 colon := strings.Index(line, ":") 332 if colon < 0 { 333 continue 334 } 335 i, err := strconv.Atoi(line[0:colon]) 336 if err != nil { 337 continue 338 } 339 i = (i - 1) / 2 340 what := "" 341 switch { 342 default: 343 continue 344 case strings.Contains(line, ": useless type name in empty declaration"), 345 strings.Contains(line, ": declaration does not declare anything"), 346 strings.Contains(line, ": unexpected type name"): 347 what = "type" 348 isConst[i] = false 349 case strings.Contains(line, ": statement with no effect"), 350 strings.Contains(line, ": expression result unused"): 351 what = "not-type" // const or func or var 352 case strings.Contains(line, "undeclared"): 353 error_(token.NoPos, "%s", strings.TrimSpace(line[colon+1:])) 354 case strings.Contains(line, "is not an integer constant"): 355 isConst[i] = false 356 continue 357 } 358 n := toSniff[i] 359 if n == nil { 360 continue 361 } 362 toSniff[i] = nil 363 n.Kind = what 364 365 j := len(needType) 366 needType = needType[0 : j+1] 367 needType[j] = n 368 } 369 for i, b := range isConst { 370 if b { 371 names[i].Kind = "const" 372 if toSniff[i] != nil && names[i].Const == "" { 373 j := len(needType) 374 needType = needType[0 : j+1] 375 needType[j] = names[i] 376 } 377 } 378 } 379 for _, n := range toSniff { 380 if n == nil { 381 continue 382 } 383 if n.Kind != "" { 384 continue 385 } 386 error_(token.NoPos, "could not determine kind of name for C.%s", n.Go) 387 } 388 if nerrors > 0 { 389 fatalf("unresolved names") 390 } 391 return needType 392 } 393 394 // loadDWARF parses the DWARF debug information generated 395 // by gcc to learn the details of the constants, variables, and types 396 // being referred to as C.xxx. 397 func (p *Package) loadDWARF(f *File, names []*Name) { 398 // Extract the types from the DWARF section of an object 399 // from a well-formed C program. Gcc only generates DWARF info 400 // for symbols in the object file, so it is not enough to print the 401 // preamble and hope the symbols we care about will be there. 402 // Instead, emit 403 // typeof(names[i]) *__cgo__i; 404 // for each entry in names and then dereference the type we 405 // learn for __cgo__i. 406 var b bytes.Buffer 407 b.WriteString(builtinProlog) 408 b.WriteString(f.Preamble) 409 for i, n := range names { 410 fmt.Fprintf(&b, "typeof(%s) *__cgo__%d;\n", n.C, i) 411 if n.Kind == "const" { 412 fmt.Fprintf(&b, "enum { __cgo_enum__%d = %s };\n", i, n.C) 413 } 414 } 415 416 // Apple's LLVM-based gcc does not include the enumeration 417 // names and values in its DWARF debug output. In case we're 418 // using such a gcc, create a data block initialized with the values. 419 // We can read them out of the object file. 420 fmt.Fprintf(&b, "long long __cgodebug_data[] = {\n") 421 for _, n := range names { 422 if n.Kind == "const" { 423 fmt.Fprintf(&b, "\t%s,\n", n.C) 424 } else { 425 fmt.Fprintf(&b, "\t0,\n") 426 } 427 } 428 // for the last entry, we can not use 0, otherwise 429 // in case all __cgodebug_data is zero initialized, 430 // LLVM-based gcc will place the it in the __DATA.__common 431 // zero-filled section (our debug/macho doesn't support 432 // this) 433 fmt.Fprintf(&b, "\t1\n") 434 fmt.Fprintf(&b, "};\n") 435 436 d, bo, debugData := p.gccDebug(b.Bytes()) 437 enumVal := make([]int64, len(debugData)/8) 438 for i := range enumVal { 439 enumVal[i] = int64(bo.Uint64(debugData[i*8:])) 440 } 441 442 // Scan DWARF info for top-level TagVariable entries with AttrName __cgo__i. 443 types := make([]dwarf.Type, len(names)) 444 enums := make([]dwarf.Offset, len(names)) 445 nameToIndex := make(map[*Name]int) 446 for i, n := range names { 447 nameToIndex[n] = i 448 } 449 nameToRef := make(map[*Name]*Ref) 450 for _, ref := range f.Ref { 451 nameToRef[ref.Name] = ref 452 } 453 r := d.Reader() 454 for { 455 e, err := r.Next() 456 if err != nil { 457 fatalf("reading DWARF entry: %s", err) 458 } 459 if e == nil { 460 break 461 } 462 switch e.Tag { 463 case dwarf.TagEnumerationType: 464 offset := e.Offset 465 for { 466 e, err := r.Next() 467 if err != nil { 468 fatalf("reading DWARF entry: %s", err) 469 } 470 if e.Tag == 0 { 471 break 472 } 473 if e.Tag == dwarf.TagEnumerator { 474 entryName := e.Val(dwarf.AttrName).(string) 475 if strings.HasPrefix(entryName, "__cgo_enum__") { 476 n, _ := strconv.Atoi(entryName[len("__cgo_enum__"):]) 477 if 0 <= n && n < len(names) { 478 enums[n] = offset 479 } 480 } 481 } 482 } 483 case dwarf.TagVariable: 484 name, _ := e.Val(dwarf.AttrName).(string) 485 typOff, _ := e.Val(dwarf.AttrType).(dwarf.Offset) 486 if name == "" || typOff == 0 { 487 fatalf("malformed DWARF TagVariable entry") 488 } 489 if !strings.HasPrefix(name, "__cgo__") { 490 break 491 } 492 typ, err := d.Type(typOff) 493 if err != nil { 494 fatalf("loading DWARF type: %s", err) 495 } 496 t, ok := typ.(*dwarf.PtrType) 497 if !ok || t == nil { 498 fatalf("internal error: %s has non-pointer type", name) 499 } 500 i, err := strconv.Atoi(name[7:]) 501 if err != nil { 502 fatalf("malformed __cgo__ name: %s", name) 503 } 504 if enums[i] != 0 { 505 t, err := d.Type(enums[i]) 506 if err != nil { 507 fatalf("loading DWARF type: %s", err) 508 } 509 types[i] = t 510 } else { 511 types[i] = t.Type 512 } 513 } 514 if e.Tag != dwarf.TagCompileUnit { 515 r.SkipChildren() 516 } 517 } 518 519 // Record types and typedef information. 520 var conv typeConv 521 conv.Init(p.PtrSize, p.IntSize) 522 for i, n := range names { 523 if types[i] == nil { 524 continue 525 } 526 pos := token.NoPos 527 if ref, ok := nameToRef[n]; ok { 528 pos = ref.Pos() 529 } 530 f, fok := types[i].(*dwarf.FuncType) 531 if n.Kind != "type" && fok { 532 n.Kind = "func" 533 n.FuncType = conv.FuncType(f, pos) 534 } else { 535 n.Type = conv.Type(types[i], pos) 536 if enums[i] != 0 && n.Type.EnumValues != nil { 537 k := fmt.Sprintf("__cgo_enum__%d", i) 538 n.Kind = "const" 539 n.Const = fmt.Sprintf("%#x", n.Type.EnumValues[k]) 540 // Remove injected enum to ensure the value will deep-compare 541 // equally in future loads of the same constant. 542 delete(n.Type.EnumValues, k) 543 } 544 // Prefer debug data over DWARF debug output, if we have it. 545 if n.Kind == "const" && i < len(enumVal) { 546 n.Const = fmt.Sprintf("%#x", enumVal[i]) 547 } 548 } 549 } 550 551 } 552 553 // mangleName does name mangling to translate names 554 // from the original Go source files to the names 555 // used in the final Go files generated by cgo. 556 func (p *Package) mangleName(n *Name) { 557 // When using gccgo variables have to be 558 // exported so that they become global symbols 559 // that the C code can refer to. 560 prefix := "_C" 561 if *gccgo && n.IsVar() { 562 prefix = "C" 563 } 564 n.Mangle = prefix + n.Kind + "_" + n.Go 565 } 566 567 // rewriteRef rewrites all the C.xxx references in f.AST to refer to the 568 // Go equivalents, now that we have figured out the meaning of all 569 // the xxx. In *godefs or *cdefs mode, rewriteRef replaces the names 570 // with full definitions instead of mangled names. 571 func (p *Package) rewriteRef(f *File) { 572 // Keep a list of all the functions, to remove the ones 573 // only used as expressions and avoid generating bridge 574 // code for them. 575 functions := make(map[string]bool) 576 577 // Assign mangled names. 578 for _, n := range f.Name { 579 if n.Kind == "not-type" { 580 n.Kind = "var" 581 } 582 if n.Mangle == "" { 583 p.mangleName(n) 584 } 585 if n.Kind == "func" { 586 functions[n.Go] = false 587 } 588 } 589 590 // Now that we have all the name types filled in, 591 // scan through the Refs to identify the ones that 592 // are trying to do a ,err call. Also check that 593 // functions are only used in calls. 594 for _, r := range f.Ref { 595 if r.Name.Kind == "const" && r.Name.Const == "" { 596 error_(r.Pos(), "unable to find value of constant C.%s", r.Name.Go) 597 } 598 var expr ast.Expr = ast.NewIdent(r.Name.Mangle) // default 599 switch r.Context { 600 case "call", "call2": 601 if r.Name.Kind != "func" { 602 if r.Name.Kind == "type" { 603 r.Context = "type" 604 expr = r.Name.Type.Go 605 break 606 } 607 error_(r.Pos(), "call of non-function C.%s", r.Name.Go) 608 break 609 } 610 functions[r.Name.Go] = true 611 if r.Context == "call2" { 612 // Invent new Name for the two-result function. 613 n := f.Name["2"+r.Name.Go] 614 if n == nil { 615 n = new(Name) 616 *n = *r.Name 617 n.AddError = true 618 n.Mangle = "_C2func_" + n.Go 619 f.Name["2"+r.Name.Go] = n 620 } 621 expr = ast.NewIdent(n.Mangle) 622 r.Name = n 623 break 624 } 625 case "expr": 626 if r.Name.Kind == "func" { 627 // Function is being used in an expression, to e.g. pass around a C function pointer. 628 // Create a new Name for this Ref which causes the variable to be declared in Go land. 629 fpName := "fp_" + r.Name.Go 630 name := f.Name[fpName] 631 if name == nil { 632 name = &Name{ 633 Go: fpName, 634 C: r.Name.C, 635 Kind: "fpvar", 636 Type: &Type{Size: p.PtrSize, Align: p.PtrSize, C: c("void*"), Go: ast.NewIdent("unsafe.Pointer")}, 637 } 638 p.mangleName(name) 639 f.Name[fpName] = name 640 } 641 r.Name = name 642 expr = ast.NewIdent(name.Mangle) 643 } else if r.Name.Kind == "type" { 644 // Okay - might be new(T) 645 expr = r.Name.Type.Go 646 } else if r.Name.Kind == "var" { 647 expr = &ast.StarExpr{X: expr} 648 } 649 650 case "type": 651 if r.Name.Kind != "type" { 652 error_(r.Pos(), "expression C.%s used as type", r.Name.Go) 653 } else if r.Name.Type == nil { 654 // Use of C.enum_x, C.struct_x or C.union_x without C definition. 655 // GCC won't raise an error when using pointers to such unknown types. 656 error_(r.Pos(), "type C.%s: undefined C type '%s'", r.Name.Go, r.Name.C) 657 } else { 658 expr = r.Name.Type.Go 659 } 660 default: 661 if r.Name.Kind == "func" { 662 error_(r.Pos(), "must call C.%s", r.Name.Go) 663 } 664 } 665 if *godefs || *cdefs { 666 // Substitute definition for mangled type name. 667 if id, ok := expr.(*ast.Ident); ok { 668 if t := typedef[id.Name]; t != nil { 669 expr = t.Go 670 } 671 if id.Name == r.Name.Mangle && r.Name.Const != "" { 672 expr = ast.NewIdent(r.Name.Const) 673 } 674 } 675 } 676 *r.Expr = expr 677 } 678 679 // Remove functions only used as expressions, so their respective 680 // bridge functions are not generated. 681 for name, used := range functions { 682 if !used { 683 delete(f.Name, name) 684 } 685 } 686 } 687 688 // gccBaseCmd returns the start of the compiler command line. 689 // It uses $CC if set, or else $GCC, or else the compiler recorded 690 // during the initial build as defaultCC. 691 // defaultCC is defined in zdefaultcc.go, written by cmd/dist. 692 func (p *Package) gccBaseCmd() []string { 693 // Use $CC if set, since that's what the build uses. 694 if ret := strings.Fields(os.Getenv("CC")); len(ret) > 0 { 695 return ret 696 } 697 // Try $GCC if set, since that's what we used to use. 698 if ret := strings.Fields(os.Getenv("GCC")); len(ret) > 0 { 699 return ret 700 } 701 return strings.Fields(defaultCC) 702 } 703 704 // gccMachine returns the gcc -m flag to use, either "-m32", "-m64" or "-marm". 705 func (p *Package) gccMachine() []string { 706 switch goarch { 707 case "amd64": 708 return []string{"-m64"} 709 case "386": 710 return []string{"-m32"} 711 case "arm": 712 return []string{"-marm"} // not thumb 713 } 714 return nil 715 } 716 717 func gccTmp() string { 718 return *objDir + "_cgo_.o" 719 } 720 721 // gccCmd returns the gcc command line to use for compiling 722 // the input. 723 func (p *Package) gccCmd() []string { 724 c := append(p.gccBaseCmd(), 725 "-Wall", // many warnings 726 "-Werror", // warnings are errors 727 "-o"+gccTmp(), // write object to tmp 728 "-gdwarf-2", // generate DWARF v2 debugging symbols 729 "-fno-eliminate-unused-debug-types", // gets rid of e.g. untyped enum otherwise 730 "-c", // do not link 731 "-xc", // input language is C 732 ) 733 if strings.Contains(c[0], "clang") { 734 c = append(c, 735 "-ferror-limit=0", 736 // Apple clang version 1.7 (tags/Apple/clang-77) (based on LLVM 2.9svn) 737 // doesn't have -Wno-unneeded-internal-declaration, so we need yet another 738 // flag to disable the warning. Yes, really good diagnostics, clang. 739 "-Wno-unknown-warning-option", 740 "-Wno-unneeded-internal-declaration", 741 "-Wno-unused-function", 742 "-Qunused-arguments", 743 ) 744 } 745 746 c = append(c, p.GccOptions...) 747 c = append(c, p.gccMachine()...) 748 c = append(c, "-") //read input from standard input 749 return c 750 } 751 752 // gccDebug runs gcc -gdwarf-2 over the C program stdin and 753 // returns the corresponding DWARF data and, if present, debug data block. 754 func (p *Package) gccDebug(stdin []byte) (*dwarf.Data, binary.ByteOrder, []byte) { 755 runGcc(stdin, p.gccCmd()) 756 757 if f, err := macho.Open(gccTmp()); err == nil { 758 defer f.Close() 759 d, err := f.DWARF() 760 if err != nil { 761 fatalf("cannot load DWARF output from %s: %v", gccTmp(), err) 762 } 763 var data []byte 764 if f.Symtab != nil { 765 for i := range f.Symtab.Syms { 766 s := &f.Symtab.Syms[i] 767 // Mach-O still uses a leading _ to denote non-assembly symbols. 768 if s.Name == "_"+"__cgodebug_data" { 769 // Found it. Now find data section. 770 if i := int(s.Sect) - 1; 0 <= i && i < len(f.Sections) { 771 sect := f.Sections[i] 772 if sect.Addr <= s.Value && s.Value < sect.Addr+sect.Size { 773 if sdat, err := sect.Data(); err == nil { 774 data = sdat[s.Value-sect.Addr:] 775 } 776 } 777 } 778 } 779 } 780 } 781 return d, f.ByteOrder, data 782 } 783 784 if f, err := elf.Open(gccTmp()); err == nil { 785 defer f.Close() 786 d, err := f.DWARF() 787 if err != nil { 788 fatalf("cannot load DWARF output from %s: %v", gccTmp(), err) 789 } 790 var data []byte 791 symtab, err := f.Symbols() 792 if err == nil { 793 for i := range symtab { 794 s := &symtab[i] 795 if s.Name == "__cgodebug_data" { 796 // Found it. Now find data section. 797 if i := int(s.Section); 0 <= i && i < len(f.Sections) { 798 sect := f.Sections[i] 799 if sect.Addr <= s.Value && s.Value < sect.Addr+sect.Size { 800 if sdat, err := sect.Data(); err == nil { 801 data = sdat[s.Value-sect.Addr:] 802 } 803 } 804 } 805 } 806 } 807 } 808 return d, f.ByteOrder, data 809 } 810 811 if f, err := pe.Open(gccTmp()); err == nil { 812 defer f.Close() 813 d, err := f.DWARF() 814 if err != nil { 815 fatalf("cannot load DWARF output from %s: %v", gccTmp(), err) 816 } 817 var data []byte 818 for _, s := range f.Symbols { 819 if s.Name == "_"+"__cgodebug_data" { 820 if i := int(s.SectionNumber) - 1; 0 <= i && i < len(f.Sections) { 821 sect := f.Sections[i] 822 if s.Value < sect.Size { 823 if sdat, err := sect.Data(); err == nil { 824 data = sdat[s.Value:] 825 } 826 } 827 } 828 } 829 } 830 return d, binary.LittleEndian, data 831 } 832 833 fatalf("cannot parse gcc output %s as ELF, Mach-O, PE object", gccTmp()) 834 panic("not reached") 835 } 836 837 // gccDefines runs gcc -E -dM -xc - over the C program stdin 838 // and returns the corresponding standard output, which is the 839 // #defines that gcc encountered while processing the input 840 // and its included files. 841 func (p *Package) gccDefines(stdin []byte) string { 842 base := append(p.gccBaseCmd(), "-E", "-dM", "-xc") 843 base = append(base, p.gccMachine()...) 844 stdout, _ := runGcc(stdin, append(append(base, p.GccOptions...), "-")) 845 return stdout 846 } 847 848 // gccErrors runs gcc over the C program stdin and returns 849 // the errors that gcc prints. That is, this function expects 850 // gcc to fail. 851 func (p *Package) gccErrors(stdin []byte) string { 852 // TODO(rsc): require failure 853 args := p.gccCmd() 854 855 // GCC 4.8.0 has a bug: it sometimes does not apply 856 // -Wunused-value to values that are macros defined in system 857 // headers. See issue 5118. Adding -Wsystem-headers avoids 858 // that problem. This will produce additional errors, but it 859 // doesn't matter because we will ignore all errors that are 860 // not marked for the cgo-test file. 861 args = append(args, "-Wsystem-headers") 862 863 if *debugGcc { 864 fmt.Fprintf(os.Stderr, "$ %s <<EOF\n", strings.Join(args, " ")) 865 os.Stderr.Write(stdin) 866 fmt.Fprint(os.Stderr, "EOF\n") 867 } 868 stdout, stderr, _ := run(stdin, args) 869 if *debugGcc { 870 os.Stderr.Write(stdout) 871 os.Stderr.Write(stderr) 872 } 873 return string(stderr) 874 } 875 876 // runGcc runs the gcc command line args with stdin on standard input. 877 // If the command exits with a non-zero exit status, runGcc prints 878 // details about what was run and exits. 879 // Otherwise runGcc returns the data written to standard output and standard error. 880 // Note that for some of the uses we expect useful data back 881 // on standard error, but for those uses gcc must still exit 0. 882 func runGcc(stdin []byte, args []string) (string, string) { 883 if *debugGcc { 884 fmt.Fprintf(os.Stderr, "$ %s <<EOF\n", strings.Join(args, " ")) 885 os.Stderr.Write(stdin) 886 fmt.Fprint(os.Stderr, "EOF\n") 887 } 888 stdout, stderr, ok := run(stdin, args) 889 if *debugGcc { 890 os.Stderr.Write(stdout) 891 os.Stderr.Write(stderr) 892 } 893 if !ok { 894 os.Stderr.Write(stderr) 895 os.Exit(2) 896 } 897 return string(stdout), string(stderr) 898 } 899 900 // A typeConv is a translator from dwarf types to Go types 901 // with equivalent memory layout. 902 type typeConv struct { 903 // Cache of already-translated or in-progress types. 904 m map[dwarf.Type]*Type 905 typedef map[string]ast.Expr 906 907 // Predeclared types. 908 bool ast.Expr 909 byte ast.Expr // denotes padding 910 int8, int16, int32, int64 ast.Expr 911 uint8, uint16, uint32, uint64, uintptr ast.Expr 912 float32, float64 ast.Expr 913 complex64, complex128 ast.Expr 914 void ast.Expr 915 unsafePointer ast.Expr 916 string ast.Expr 917 goVoid ast.Expr // _Ctype_void, denotes C's void 918 919 ptrSize int64 920 intSize int64 921 } 922 923 var tagGen int 924 var typedef = make(map[string]*Type) 925 var goIdent = make(map[string]*ast.Ident) 926 927 func (c *typeConv) Init(ptrSize, intSize int64) { 928 c.ptrSize = ptrSize 929 c.intSize = intSize 930 c.m = make(map[dwarf.Type]*Type) 931 c.bool = c.Ident("bool") 932 c.byte = c.Ident("byte") 933 c.int8 = c.Ident("int8") 934 c.int16 = c.Ident("int16") 935 c.int32 = c.Ident("int32") 936 c.int64 = c.Ident("int64") 937 c.uint8 = c.Ident("uint8") 938 c.uint16 = c.Ident("uint16") 939 c.uint32 = c.Ident("uint32") 940 c.uint64 = c.Ident("uint64") 941 c.uintptr = c.Ident("uintptr") 942 c.float32 = c.Ident("float32") 943 c.float64 = c.Ident("float64") 944 c.complex64 = c.Ident("complex64") 945 c.complex128 = c.Ident("complex128") 946 c.unsafePointer = c.Ident("unsafe.Pointer") 947 c.void = c.Ident("void") 948 c.string = c.Ident("string") 949 c.goVoid = c.Ident("_Ctype_void") 950 } 951 952 // base strips away qualifiers and typedefs to get the underlying type 953 func base(dt dwarf.Type) dwarf.Type { 954 for { 955 if d, ok := dt.(*dwarf.QualType); ok { 956 dt = d.Type 957 continue 958 } 959 if d, ok := dt.(*dwarf.TypedefType); ok { 960 dt = d.Type 961 continue 962 } 963 break 964 } 965 return dt 966 } 967 968 // Map from dwarf text names to aliases we use in package "C". 969 var dwarfToName = map[string]string{ 970 "long int": "long", 971 "long unsigned int": "ulong", 972 "unsigned int": "uint", 973 "short unsigned int": "ushort", 974 "short int": "short", 975 "long long int": "longlong", 976 "long long unsigned int": "ulonglong", 977 "signed char": "schar", 978 "float complex": "complexfloat", 979 "double complex": "complexdouble", 980 } 981 982 const signedDelta = 64 983 984 // String returns the current type representation. Format arguments 985 // are assembled within this method so that any changes in mutable 986 // values are taken into account. 987 func (tr *TypeRepr) String() string { 988 if len(tr.Repr) == 0 { 989 return "" 990 } 991 if len(tr.FormatArgs) == 0 { 992 return tr.Repr 993 } 994 return fmt.Sprintf(tr.Repr, tr.FormatArgs...) 995 } 996 997 // Empty returns true if the result of String would be "". 998 func (tr *TypeRepr) Empty() bool { 999 return len(tr.Repr) == 0 1000 } 1001 1002 // Set modifies the type representation. 1003 // If fargs are provided, repr is used as a format for fmt.Sprintf. 1004 // Otherwise, repr is used unprocessed as the type representation. 1005 func (tr *TypeRepr) Set(repr string, fargs ...interface{}) { 1006 tr.Repr = repr 1007 tr.FormatArgs = fargs 1008 } 1009 1010 // Type returns a *Type with the same memory layout as 1011 // dtype when used as the type of a variable or a struct field. 1012 func (c *typeConv) Type(dtype dwarf.Type, pos token.Pos) *Type { 1013 if t, ok := c.m[dtype]; ok { 1014 if t.Go == nil { 1015 fatalf("%s: type conversion loop at %s", lineno(pos), dtype) 1016 } 1017 return t 1018 } 1019 1020 // clang won't generate DW_AT_byte_size for pointer types, 1021 // so we have to fix it here. 1022 if dt, ok := base(dtype).(*dwarf.PtrType); ok && dt.ByteSize == -1 { 1023 dt.ByteSize = c.ptrSize 1024 } 1025 1026 t := new(Type) 1027 t.Size = dtype.Size() 1028 t.Align = -1 1029 t.C = &TypeRepr{Repr: dtype.Common().Name} 1030 c.m[dtype] = t 1031 1032 if t.Size < 0 { 1033 // Unsized types are [0]byte 1034 t.Size = 0 1035 t.Go = c.Opaque(0) 1036 if t.C.Empty() { 1037 t.C.Set("void") 1038 } 1039 return t 1040 } 1041 1042 switch dt := dtype.(type) { 1043 default: 1044 fatalf("%s: unexpected type: %s", lineno(pos), dtype) 1045 1046 case *dwarf.AddrType: 1047 if t.Size != c.ptrSize { 1048 fatalf("%s: unexpected: %d-byte address type - %s", lineno(pos), t.Size, dtype) 1049 } 1050 t.Go = c.uintptr 1051 t.Align = t.Size 1052 1053 case *dwarf.ArrayType: 1054 if dt.StrideBitSize > 0 { 1055 // Cannot represent bit-sized elements in Go. 1056 t.Go = c.Opaque(t.Size) 1057 break 1058 } 1059 gt := &ast.ArrayType{ 1060 Len: c.intExpr(dt.Count), 1061 } 1062 t.Go = gt // publish before recursive call 1063 sub := c.Type(dt.Type, pos) 1064 t.Align = sub.Align 1065 gt.Elt = sub.Go 1066 t.C.Set("typeof(%s[%d])", sub.C, dt.Count) 1067 1068 case *dwarf.BoolType: 1069 t.Go = c.bool 1070 t.Align = 1 1071 1072 case *dwarf.CharType: 1073 if t.Size != 1 { 1074 fatalf("%s: unexpected: %d-byte char type - %s", lineno(pos), t.Size, dtype) 1075 } 1076 t.Go = c.int8 1077 t.Align = 1 1078 1079 case *dwarf.EnumType: 1080 if t.Align = t.Size; t.Align >= c.ptrSize { 1081 t.Align = c.ptrSize 1082 } 1083 t.C.Set("enum " + dt.EnumName) 1084 signed := 0 1085 t.EnumValues = make(map[string]int64) 1086 for _, ev := range dt.Val { 1087 t.EnumValues[ev.Name] = ev.Val 1088 if ev.Val < 0 { 1089 signed = signedDelta 1090 } 1091 } 1092 switch t.Size + int64(signed) { 1093 default: 1094 fatalf("%s: unexpected: %d-byte enum type - %s", lineno(pos), t.Size, dtype) 1095 case 1: 1096 t.Go = c.uint8 1097 case 2: 1098 t.Go = c.uint16 1099 case 4: 1100 t.Go = c.uint32 1101 case 8: 1102 t.Go = c.uint64 1103 case 1 + signedDelta: 1104 t.Go = c.int8 1105 case 2 + signedDelta: 1106 t.Go = c.int16 1107 case 4 + signedDelta: 1108 t.Go = c.int32 1109 case 8 + signedDelta: 1110 t.Go = c.int64 1111 } 1112 1113 case *dwarf.FloatType: 1114 switch t.Size { 1115 default: 1116 fatalf("%s: unexpected: %d-byte float type - %s", lineno(pos), t.Size, dtype) 1117 case 4: 1118 t.Go = c.float32 1119 case 8: 1120 t.Go = c.float64 1121 } 1122 if t.Align = t.Size; t.Align >= c.ptrSize { 1123 t.Align = c.ptrSize 1124 } 1125 1126 case *dwarf.ComplexType: 1127 switch t.Size { 1128 default: 1129 fatalf("%s: unexpected: %d-byte complex type - %s", lineno(pos), t.Size, dtype) 1130 case 8: 1131 t.Go = c.complex64 1132 case 16: 1133 t.Go = c.complex128 1134 } 1135 if t.Align = t.Size; t.Align >= c.ptrSize { 1136 t.Align = c.ptrSize 1137 } 1138 1139 case *dwarf.FuncType: 1140 // No attempt at translation: would enable calls 1141 // directly between worlds, but we need to moderate those. 1142 t.Go = c.uintptr 1143 t.Align = c.ptrSize 1144 1145 case *dwarf.IntType: 1146 if dt.BitSize > 0 { 1147 fatalf("%s: unexpected: %d-bit int type - %s", lineno(pos), dt.BitSize, dtype) 1148 } 1149 switch t.Size { 1150 default: 1151 fatalf("%s: unexpected: %d-byte int type - %s", lineno(pos), t.Size, dtype) 1152 case 1: 1153 t.Go = c.int8 1154 case 2: 1155 t.Go = c.int16 1156 case 4: 1157 t.Go = c.int32 1158 case 8: 1159 t.Go = c.int64 1160 } 1161 if t.Align = t.Size; t.Align >= c.ptrSize { 1162 t.Align = c.ptrSize 1163 } 1164 1165 case *dwarf.PtrType: 1166 t.Align = c.ptrSize 1167 1168 // Translate void* as unsafe.Pointer 1169 if _, ok := base(dt.Type).(*dwarf.VoidType); ok { 1170 t.Go = c.unsafePointer 1171 t.C.Set("void*") 1172 break 1173 } 1174 1175 gt := &ast.StarExpr{} 1176 t.Go = gt // publish before recursive call 1177 sub := c.Type(dt.Type, pos) 1178 gt.X = sub.Go 1179 t.C.Set("%s*", sub.C) 1180 1181 case *dwarf.QualType: 1182 // Ignore qualifier. 1183 t = c.Type(dt.Type, pos) 1184 c.m[dtype] = t 1185 return t 1186 1187 case *dwarf.StructType: 1188 // Convert to Go struct, being careful about alignment. 1189 // Have to give it a name to simulate C "struct foo" references. 1190 tag := dt.StructName 1191 if tag == "" { 1192 tag = "__" + strconv.Itoa(tagGen) 1193 tagGen++ 1194 } else if t.C.Empty() { 1195 t.C.Set(dt.Kind + " " + tag) 1196 } 1197 name := c.Ident("_Ctype_" + dt.Kind + "_" + tag) 1198 t.Go = name // publish before recursive calls 1199 goIdent[name.Name] = name 1200 switch dt.Kind { 1201 case "class", "union": 1202 t.Go = c.Opaque(t.Size) 1203 if t.C.Empty() { 1204 t.C.Set("typeof(unsigned char[%d])", t.Size) 1205 } 1206 t.Align = 1 // TODO: should probably base this on field alignment. 1207 typedef[name.Name] = t 1208 case "struct": 1209 g, csyntax, align := c.Struct(dt, pos) 1210 if t.C.Empty() { 1211 t.C.Set(csyntax) 1212 } 1213 t.Align = align 1214 tt := *t 1215 if tag != "" { 1216 tt.C = &TypeRepr{"struct %s", []interface{}{tag}} 1217 } 1218 tt.Go = g 1219 typedef[name.Name] = &tt 1220 } 1221 1222 case *dwarf.TypedefType: 1223 // Record typedef for printing. 1224 if dt.Name == "_GoString_" { 1225 // Special C name for Go string type. 1226 // Knows string layout used by compilers: pointer plus length, 1227 // which rounds up to 2 pointers after alignment. 1228 t.Go = c.string 1229 t.Size = c.ptrSize * 2 1230 t.Align = c.ptrSize 1231 break 1232 } 1233 if dt.Name == "_GoBytes_" { 1234 // Special C name for Go []byte type. 1235 // Knows slice layout used by compilers: pointer, length, cap. 1236 t.Go = c.Ident("[]byte") 1237 t.Size = c.ptrSize + 4 + 4 1238 t.Align = c.ptrSize 1239 break 1240 } 1241 name := c.Ident("_Ctype_" + dt.Name) 1242 goIdent[name.Name] = name 1243 t.Go = name // publish before recursive call 1244 sub := c.Type(dt.Type, pos) 1245 t.Size = sub.Size 1246 t.Align = sub.Align 1247 if _, ok := typedef[name.Name]; !ok { 1248 tt := *t 1249 tt.Go = sub.Go 1250 typedef[name.Name] = &tt 1251 } 1252 if *godefs || *cdefs { 1253 t.Go = sub.Go 1254 } 1255 1256 case *dwarf.UcharType: 1257 if t.Size != 1 { 1258 fatalf("%s: unexpected: %d-byte uchar type - %s", lineno(pos), t.Size, dtype) 1259 } 1260 t.Go = c.uint8 1261 t.Align = 1 1262 1263 case *dwarf.UintType: 1264 if dt.BitSize > 0 { 1265 fatalf("%s: unexpected: %d-bit uint type - %s", lineno(pos), dt.BitSize, dtype) 1266 } 1267 switch t.Size { 1268 default: 1269 fatalf("%s: unexpected: %d-byte uint type - %s", lineno(pos), t.Size, dtype) 1270 case 1: 1271 t.Go = c.uint8 1272 case 2: 1273 t.Go = c.uint16 1274 case 4: 1275 t.Go = c.uint32 1276 case 8: 1277 t.Go = c.uint64 1278 } 1279 if t.Align = t.Size; t.Align >= c.ptrSize { 1280 t.Align = c.ptrSize 1281 } 1282 1283 case *dwarf.VoidType: 1284 t.Go = c.goVoid 1285 t.C.Set("void") 1286 t.Align = 1 1287 } 1288 1289 switch dtype.(type) { 1290 case *dwarf.AddrType, *dwarf.BoolType, *dwarf.CharType, *dwarf.IntType, *dwarf.FloatType, *dwarf.UcharType, *dwarf.UintType: 1291 s := dtype.Common().Name 1292 if s != "" { 1293 if ss, ok := dwarfToName[s]; ok { 1294 s = ss 1295 } 1296 s = strings.Join(strings.Split(s, " "), "") // strip spaces 1297 name := c.Ident("_Ctype_" + s) 1298 tt := *t 1299 typedef[name.Name] = &tt 1300 if !*godefs && !*cdefs { 1301 t.Go = name 1302 } 1303 } 1304 } 1305 1306 if t.C.Empty() { 1307 fatalf("%s: internal error: did not create C name for %s", lineno(pos), dtype) 1308 } 1309 1310 return t 1311 } 1312 1313 // FuncArg returns a Go type with the same memory layout as 1314 // dtype when used as the type of a C function argument. 1315 func (c *typeConv) FuncArg(dtype dwarf.Type, pos token.Pos) *Type { 1316 t := c.Type(dtype, pos) 1317 switch dt := dtype.(type) { 1318 case *dwarf.ArrayType: 1319 // Arrays are passed implicitly as pointers in C. 1320 // In Go, we must be explicit. 1321 tr := &TypeRepr{} 1322 tr.Set("%s*", t.C) 1323 return &Type{ 1324 Size: c.ptrSize, 1325 Align: c.ptrSize, 1326 Go: &ast.StarExpr{X: t.Go}, 1327 C: tr, 1328 } 1329 case *dwarf.TypedefType: 1330 // C has much more relaxed rules than Go for 1331 // implicit type conversions. When the parameter 1332 // is type T defined as *X, simulate a little of the 1333 // laxness of C by making the argument *X instead of T. 1334 if ptr, ok := base(dt.Type).(*dwarf.PtrType); ok { 1335 // Unless the typedef happens to point to void* since 1336 // Go has special rules around using unsafe.Pointer. 1337 if _, void := base(ptr.Type).(*dwarf.VoidType); void { 1338 break 1339 } 1340 1341 t = c.Type(ptr, pos) 1342 if t == nil { 1343 return nil 1344 } 1345 1346 // Remember the C spelling, in case the struct 1347 // has __attribute__((unavailable)) on it. See issue 2888. 1348 t.Typedef = dt.Name 1349 } 1350 } 1351 return t 1352 } 1353 1354 // FuncType returns the Go type analogous to dtype. 1355 // There is no guarantee about matching memory layout. 1356 func (c *typeConv) FuncType(dtype *dwarf.FuncType, pos token.Pos) *FuncType { 1357 p := make([]*Type, len(dtype.ParamType)) 1358 gp := make([]*ast.Field, len(dtype.ParamType)) 1359 for i, f := range dtype.ParamType { 1360 // gcc's DWARF generator outputs a single DotDotDotType parameter for 1361 // function pointers that specify no parameters (e.g. void 1362 // (*__cgo_0)()). Treat this special case as void. This case is 1363 // invalid according to ISO C anyway (i.e. void (*__cgo_1)(...) is not 1364 // legal). 1365 if _, ok := f.(*dwarf.DotDotDotType); ok && i == 0 { 1366 p, gp = nil, nil 1367 break 1368 } 1369 p[i] = c.FuncArg(f, pos) 1370 gp[i] = &ast.Field{Type: p[i].Go} 1371 } 1372 var r *Type 1373 var gr []*ast.Field 1374 if _, ok := dtype.ReturnType.(*dwarf.VoidType); ok { 1375 gr = []*ast.Field{{Type: c.goVoid}} 1376 } else if dtype.ReturnType != nil { 1377 r = c.Type(dtype.ReturnType, pos) 1378 gr = []*ast.Field{{Type: r.Go}} 1379 } 1380 return &FuncType{ 1381 Params: p, 1382 Result: r, 1383 Go: &ast.FuncType{ 1384 Params: &ast.FieldList{List: gp}, 1385 Results: &ast.FieldList{List: gr}, 1386 }, 1387 } 1388 } 1389 1390 // Identifier 1391 func (c *typeConv) Ident(s string) *ast.Ident { 1392 return ast.NewIdent(s) 1393 } 1394 1395 // Opaque type of n bytes. 1396 func (c *typeConv) Opaque(n int64) ast.Expr { 1397 return &ast.ArrayType{ 1398 Len: c.intExpr(n), 1399 Elt: c.byte, 1400 } 1401 } 1402 1403 // Expr for integer n. 1404 func (c *typeConv) intExpr(n int64) ast.Expr { 1405 return &ast.BasicLit{ 1406 Kind: token.INT, 1407 Value: strconv.FormatInt(n, 10), 1408 } 1409 } 1410 1411 // Add padding of given size to fld. 1412 func (c *typeConv) pad(fld []*ast.Field, size int64) []*ast.Field { 1413 n := len(fld) 1414 fld = fld[0 : n+1] 1415 fld[n] = &ast.Field{Names: []*ast.Ident{c.Ident("_")}, Type: c.Opaque(size)} 1416 return fld 1417 } 1418 1419 // Struct conversion: return Go and (6g) C syntax for type. 1420 func (c *typeConv) Struct(dt *dwarf.StructType, pos token.Pos) (expr *ast.StructType, csyntax string, align int64) { 1421 var buf bytes.Buffer 1422 buf.WriteString("struct {") 1423 fld := make([]*ast.Field, 0, 2*len(dt.Field)+1) // enough for padding around every field 1424 off := int64(0) 1425 1426 // Rename struct fields that happen to be named Go keywords into 1427 // _{keyword}. Create a map from C ident -> Go ident. The Go ident will 1428 // be mangled. Any existing identifier that already has the same name on 1429 // the C-side will cause the Go-mangled version to be prefixed with _. 1430 // (e.g. in a struct with fields '_type' and 'type', the latter would be 1431 // rendered as '__type' in Go). 1432 ident := make(map[string]string) 1433 used := make(map[string]bool) 1434 for _, f := range dt.Field { 1435 ident[f.Name] = f.Name 1436 used[f.Name] = true 1437 } 1438 1439 if !*godefs && !*cdefs { 1440 for cid, goid := range ident { 1441 if token.Lookup(goid).IsKeyword() { 1442 // Avoid keyword 1443 goid = "_" + goid 1444 1445 // Also avoid existing fields 1446 for _, exist := used[goid]; exist; _, exist = used[goid] { 1447 goid = "_" + goid 1448 } 1449 1450 used[goid] = true 1451 ident[cid] = goid 1452 } 1453 } 1454 } 1455 1456 anon := 0 1457 for _, f := range dt.Field { 1458 if f.ByteOffset > off { 1459 fld = c.pad(fld, f.ByteOffset-off) 1460 off = f.ByteOffset 1461 } 1462 t := c.Type(f.Type, pos) 1463 tgo := t.Go 1464 size := t.Size 1465 1466 if f.BitSize > 0 { 1467 if f.BitSize%8 != 0 { 1468 continue 1469 } 1470 size = f.BitSize / 8 1471 name := tgo.(*ast.Ident).String() 1472 if strings.HasPrefix(name, "int") { 1473 name = "int" 1474 } else { 1475 name = "uint" 1476 } 1477 tgo = ast.NewIdent(name + fmt.Sprint(f.BitSize)) 1478 } 1479 1480 n := len(fld) 1481 fld = fld[0 : n+1] 1482 name := f.Name 1483 if name == "" { 1484 name = fmt.Sprintf("anon%d", anon) 1485 anon++ 1486 ident[name] = name 1487 } 1488 fld[n] = &ast.Field{Names: []*ast.Ident{c.Ident(ident[name])}, Type: tgo} 1489 off += size 1490 buf.WriteString(t.C.String()) 1491 buf.WriteString(" ") 1492 buf.WriteString(name) 1493 buf.WriteString("; ") 1494 if t.Align > align { 1495 align = t.Align 1496 } 1497 } 1498 if off < dt.ByteSize { 1499 fld = c.pad(fld, dt.ByteSize-off) 1500 off = dt.ByteSize 1501 } 1502 if off != dt.ByteSize { 1503 fatalf("%s: struct size calculation error off=%d bytesize=%d", lineno(pos), off, dt.ByteSize) 1504 } 1505 buf.WriteString("}") 1506 csyntax = buf.String() 1507 1508 if *godefs || *cdefs { 1509 godefsFields(fld) 1510 } 1511 expr = &ast.StructType{Fields: &ast.FieldList{List: fld}} 1512 return 1513 } 1514 1515 func upper(s string) string { 1516 if s == "" { 1517 return "" 1518 } 1519 r, size := utf8.DecodeRuneInString(s) 1520 if r == '_' { 1521 return "X" + s 1522 } 1523 return string(unicode.ToUpper(r)) + s[size:] 1524 } 1525 1526 // godefsFields rewrites field names for use in Go or C definitions. 1527 // It strips leading common prefixes (like tv_ in tv_sec, tv_usec) 1528 // converts names to upper case, and rewrites _ into Pad_godefs_n, 1529 // so that all fields are exported. 1530 func godefsFields(fld []*ast.Field) { 1531 prefix := fieldPrefix(fld) 1532 npad := 0 1533 for _, f := range fld { 1534 for _, n := range f.Names { 1535 if n.Name != prefix { 1536 n.Name = strings.TrimPrefix(n.Name, prefix) 1537 } 1538 if n.Name == "_" { 1539 // Use exported name instead. 1540 n.Name = "Pad_cgo_" + strconv.Itoa(npad) 1541 npad++ 1542 } 1543 if !*cdefs { 1544 n.Name = upper(n.Name) 1545 } 1546 } 1547 p := &f.Type 1548 t := *p 1549 if star, ok := t.(*ast.StarExpr); ok { 1550 star = &ast.StarExpr{X: star.X} 1551 *p = star 1552 p = &star.X 1553 t = *p 1554 } 1555 if id, ok := t.(*ast.Ident); ok { 1556 if id.Name == "unsafe.Pointer" { 1557 *p = ast.NewIdent("*byte") 1558 } 1559 } 1560 } 1561 } 1562 1563 // fieldPrefix returns the prefix that should be removed from all the 1564 // field names when generating the C or Go code. For generated 1565 // C, we leave the names as is (tv_sec, tv_usec), since that's what 1566 // people are used to seeing in C. For generated Go code, such as 1567 // package syscall's data structures, we drop a common prefix 1568 // (so sec, usec, which will get turned into Sec, Usec for exporting). 1569 func fieldPrefix(fld []*ast.Field) string { 1570 if *cdefs { 1571 return "" 1572 } 1573 prefix := "" 1574 for _, f := range fld { 1575 for _, n := range f.Names { 1576 // Ignore field names that don't have the prefix we're 1577 // looking for. It is common in C headers to have fields 1578 // named, say, _pad in an otherwise prefixed header. 1579 // If the struct has 3 fields tv_sec, tv_usec, _pad1, then we 1580 // still want to remove the tv_ prefix. 1581 // The check for "orig_" here handles orig_eax in the 1582 // x86 ptrace register sets, which otherwise have all fields 1583 // with reg_ prefixes. 1584 if strings.HasPrefix(n.Name, "orig_") || strings.HasPrefix(n.Name, "_") { 1585 continue 1586 } 1587 i := strings.Index(n.Name, "_") 1588 if i < 0 { 1589 continue 1590 } 1591 if prefix == "" { 1592 prefix = n.Name[:i+1] 1593 } else if prefix != n.Name[:i+1] { 1594 return "" 1595 } 1596 } 1597 } 1598 return prefix 1599 }