github.com/sean-/go@v0.0.0-20151219100004-97f854cd7bb6/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 // Translate rewrites f.AST, the original Go input, to remove 158 // references to the imported package C, replacing them with 159 // references to the equivalent Go types, functions, and variables. 160 func (p *Package) Translate(f *File) { 161 for _, cref := range f.Ref { 162 // Convert C.ulong to C.unsigned long, etc. 163 cref.Name.C = cname(cref.Name.Go) 164 } 165 p.loadDefines(f) 166 needType := p.guessKinds(f) 167 if len(needType) > 0 { 168 p.loadDWARF(f, needType) 169 } 170 p.rewriteCalls(f) 171 p.rewriteRef(f) 172 } 173 174 // loadDefines coerces gcc into spitting out the #defines in use 175 // in the file f and saves relevant renamings in f.Name[name].Define. 176 func (p *Package) loadDefines(f *File) { 177 var b bytes.Buffer 178 b.WriteString(f.Preamble) 179 b.WriteString(builtinProlog) 180 stdout := p.gccDefines(b.Bytes()) 181 182 for _, line := range strings.Split(stdout, "\n") { 183 if len(line) < 9 || line[0:7] != "#define" { 184 continue 185 } 186 187 line = strings.TrimSpace(line[8:]) 188 189 var key, val string 190 spaceIndex := strings.Index(line, " ") 191 tabIndex := strings.Index(line, "\t") 192 193 if spaceIndex == -1 && tabIndex == -1 { 194 continue 195 } else if tabIndex == -1 || (spaceIndex != -1 && spaceIndex < tabIndex) { 196 key = line[0:spaceIndex] 197 val = strings.TrimSpace(line[spaceIndex:]) 198 } else { 199 key = line[0:tabIndex] 200 val = strings.TrimSpace(line[tabIndex:]) 201 } 202 203 if key == "__clang__" { 204 p.GccIsClang = true 205 } 206 207 if n := f.Name[key]; n != nil { 208 if *debugDefine { 209 fmt.Fprintf(os.Stderr, "#define %s %s\n", key, val) 210 } 211 n.Define = val 212 } 213 } 214 } 215 216 // guessKinds tricks gcc into revealing the kind of each 217 // name xxx for the references C.xxx in the Go input. 218 // The kind is either a constant, type, or variable. 219 func (p *Package) guessKinds(f *File) []*Name { 220 // Determine kinds for names we already know about, 221 // like #defines or 'struct foo', before bothering with gcc. 222 var names, needType []*Name 223 for _, key := range nameKeys(f.Name) { 224 n := f.Name[key] 225 // If we've already found this name as a #define 226 // and we can translate it as a constant value, do so. 227 if n.Define != "" { 228 isConst := false 229 if _, err := strconv.Atoi(n.Define); err == nil { 230 isConst = true 231 } else if n.Define[0] == '"' || n.Define[0] == '\'' { 232 if _, err := parser.ParseExpr(n.Define); err == nil { 233 isConst = true 234 } 235 } 236 if isConst { 237 n.Kind = "const" 238 // Turn decimal into hex, just for consistency 239 // with enum-derived constants. Otherwise 240 // in the cgo -godefs output half the constants 241 // are in hex and half are in whatever the #define used. 242 i, err := strconv.ParseInt(n.Define, 0, 64) 243 if err == nil { 244 n.Const = fmt.Sprintf("%#x", i) 245 } else { 246 n.Const = n.Define 247 } 248 continue 249 } 250 251 if isName(n.Define) { 252 n.C = n.Define 253 } 254 } 255 256 needType = append(needType, n) 257 258 // If this is a struct, union, or enum type name, no need to guess the kind. 259 if strings.HasPrefix(n.C, "struct ") || strings.HasPrefix(n.C, "union ") || strings.HasPrefix(n.C, "enum ") { 260 n.Kind = "type" 261 continue 262 } 263 264 // Otherwise, we'll need to find out from gcc. 265 names = append(names, n) 266 } 267 268 // Bypass gcc if there's nothing left to find out. 269 if len(names) == 0 { 270 return needType 271 } 272 273 // Coerce gcc into telling us whether each name is a type, a value, or undeclared. 274 // For names, find out whether they are integer constants. 275 // We used to look at specific warning or error messages here, but that tied the 276 // behavior too closely to specific versions of the compilers. 277 // Instead, arrange that we can infer what we need from only the presence or absence 278 // of an error on a specific line. 279 // 280 // For each name, we generate these lines, where xxx is the index in toSniff plus one. 281 // 282 // #line xxx "not-declared" 283 // void __cgo_f_xxx_1(void) { __typeof__(name) *__cgo_undefined__; } 284 // #line xxx "not-type" 285 // void __cgo_f_xxx_2(void) { name *__cgo_undefined__; } 286 // #line xxx "not-const" 287 // void __cgo_f_xxx_3(void) { enum { __cgo_undefined__ = (name)*1 }; } 288 // 289 // If we see an error at not-declared:xxx, the corresponding name is not declared. 290 // If we see an error at not-type:xxx, the corresponding name is a type. 291 // If we see an error at not-const:xxx, the corresponding name is not an integer constant. 292 // If we see no errors, we assume the name is an expression but not a constant 293 // (so a variable or a function). 294 // 295 // The specific input forms are chosen so that they are valid C syntax regardless of 296 // whether name denotes a type or an expression. 297 298 var b bytes.Buffer 299 b.WriteString(f.Preamble) 300 b.WriteString(builtinProlog) 301 302 for i, n := range names { 303 fmt.Fprintf(&b, "#line %d \"not-declared\"\n"+ 304 "void __cgo_f_%d_1(void) { __typeof__(%s) *__cgo_undefined__; }\n"+ 305 "#line %d \"not-type\"\n"+ 306 "void __cgo_f_%d_2(void) { %s *__cgo_undefined__; }\n"+ 307 "#line %d \"not-const\"\n"+ 308 "void __cgo_f_%d_3(void) { enum { __cgo__undefined__ = (%s)*1 }; }\n", 309 i+1, i+1, n.C, 310 i+1, i+1, n.C, 311 i+1, i+1, n.C) 312 } 313 fmt.Fprintf(&b, "#line 1 \"completed\"\n"+ 314 "int __cgo__1 = __cgo__2;\n") 315 316 stderr := p.gccErrors(b.Bytes()) 317 if stderr == "" { 318 fatalf("%s produced no output\non input:\n%s", p.gccBaseCmd()[0], b.Bytes()) 319 } 320 321 completed := false 322 sniff := make([]int, len(names)) 323 const ( 324 notType = 1 << iota 325 notConst 326 notDeclared 327 ) 328 for _, line := range strings.Split(stderr, "\n") { 329 if !strings.Contains(line, ": error:") { 330 // we only care about errors. 331 // we tried to turn off warnings on the command line, but one never knows. 332 continue 333 } 334 335 c1 := strings.Index(line, ":") 336 if c1 < 0 { 337 continue 338 } 339 c2 := strings.Index(line[c1+1:], ":") 340 if c2 < 0 { 341 continue 342 } 343 c2 += c1 + 1 344 345 filename := line[:c1] 346 i, _ := strconv.Atoi(line[c1+1 : c2]) 347 i-- 348 if i < 0 || i >= len(names) { 349 continue 350 } 351 352 switch filename { 353 case "completed": 354 // Strictly speaking, there is no guarantee that seeing the error at completed:1 355 // (at the end of the file) means we've seen all the errors from earlier in the file, 356 // but usually it does. Certainly if we don't see the completed:1 error, we did 357 // not get all the errors we expected. 358 completed = true 359 360 case "not-declared": 361 sniff[i] |= notDeclared 362 case "not-type": 363 sniff[i] |= notType 364 case "not-const": 365 sniff[i] |= notConst 366 } 367 } 368 369 if !completed { 370 fatalf("%s did not produce error at completed:1\non input:\n%s\nfull error output:\n%s", p.gccBaseCmd()[0], b.Bytes(), stderr) 371 } 372 373 for i, n := range names { 374 switch sniff[i] { 375 default: 376 error_(token.NoPos, "could not determine kind of name for C.%s", fixGo(n.Go)) 377 case notType: 378 n.Kind = "const" 379 case notConst: 380 n.Kind = "type" 381 case notConst | notType: 382 n.Kind = "not-type" 383 } 384 } 385 if nerrors > 0 { 386 // Check if compiling the preamble by itself causes any errors, 387 // because the messages we've printed out so far aren't helpful 388 // to users debugging preamble mistakes. See issue 8442. 389 preambleErrors := p.gccErrors([]byte(f.Preamble)) 390 if len(preambleErrors) > 0 { 391 error_(token.NoPos, "\n%s errors for preamble:\n%s", p.gccBaseCmd()[0], preambleErrors) 392 } 393 394 fatalf("unresolved names") 395 } 396 397 needType = append(needType, names...) 398 return needType 399 } 400 401 // loadDWARF parses the DWARF debug information generated 402 // by gcc to learn the details of the constants, variables, and types 403 // being referred to as C.xxx. 404 func (p *Package) loadDWARF(f *File, names []*Name) { 405 // Extract the types from the DWARF section of an object 406 // from a well-formed C program. Gcc only generates DWARF info 407 // for symbols in the object file, so it is not enough to print the 408 // preamble and hope the symbols we care about will be there. 409 // Instead, emit 410 // __typeof__(names[i]) *__cgo__i; 411 // for each entry in names and then dereference the type we 412 // learn for __cgo__i. 413 var b bytes.Buffer 414 b.WriteString(f.Preamble) 415 b.WriteString(builtinProlog) 416 for i, n := range names { 417 fmt.Fprintf(&b, "__typeof__(%s) *__cgo__%d;\n", n.C, i) 418 if n.Kind == "const" { 419 fmt.Fprintf(&b, "enum { __cgo_enum__%d = %s };\n", i, n.C) 420 } 421 } 422 423 // Apple's LLVM-based gcc does not include the enumeration 424 // names and values in its DWARF debug output. In case we're 425 // using such a gcc, create a data block initialized with the values. 426 // We can read them out of the object file. 427 fmt.Fprintf(&b, "long long __cgodebug_data[] = {\n") 428 for _, n := range names { 429 if n.Kind == "const" { 430 fmt.Fprintf(&b, "\t%s,\n", n.C) 431 } else { 432 fmt.Fprintf(&b, "\t0,\n") 433 } 434 } 435 // for the last entry, we can not use 0, otherwise 436 // in case all __cgodebug_data is zero initialized, 437 // LLVM-based gcc will place the it in the __DATA.__common 438 // zero-filled section (our debug/macho doesn't support 439 // this) 440 fmt.Fprintf(&b, "\t1\n") 441 fmt.Fprintf(&b, "};\n") 442 443 d, bo, debugData := p.gccDebug(b.Bytes()) 444 enumVal := make([]int64, len(debugData)/8) 445 for i := range enumVal { 446 enumVal[i] = int64(bo.Uint64(debugData[i*8:])) 447 } 448 449 // Scan DWARF info for top-level TagVariable entries with AttrName __cgo__i. 450 types := make([]dwarf.Type, len(names)) 451 enums := make([]dwarf.Offset, len(names)) 452 nameToIndex := make(map[*Name]int) 453 for i, n := range names { 454 nameToIndex[n] = i 455 } 456 nameToRef := make(map[*Name]*Ref) 457 for _, ref := range f.Ref { 458 nameToRef[ref.Name] = ref 459 } 460 r := d.Reader() 461 for { 462 e, err := r.Next() 463 if err != nil { 464 fatalf("reading DWARF entry: %s", err) 465 } 466 if e == nil { 467 break 468 } 469 switch e.Tag { 470 case dwarf.TagEnumerationType: 471 offset := e.Offset 472 for { 473 e, err := r.Next() 474 if err != nil { 475 fatalf("reading DWARF entry: %s", err) 476 } 477 if e.Tag == 0 { 478 break 479 } 480 if e.Tag == dwarf.TagEnumerator { 481 entryName := e.Val(dwarf.AttrName).(string) 482 if strings.HasPrefix(entryName, "__cgo_enum__") { 483 n, _ := strconv.Atoi(entryName[len("__cgo_enum__"):]) 484 if 0 <= n && n < len(names) { 485 enums[n] = offset 486 } 487 } 488 } 489 } 490 case dwarf.TagVariable: 491 name, _ := e.Val(dwarf.AttrName).(string) 492 typOff, _ := e.Val(dwarf.AttrType).(dwarf.Offset) 493 if name == "" || typOff == 0 { 494 if e.Val(dwarf.AttrSpecification) != nil { 495 // Since we are reading all the DWARF, 496 // assume we will see the variable elsewhere. 497 break 498 } 499 fatalf("malformed DWARF TagVariable entry") 500 } 501 if !strings.HasPrefix(name, "__cgo__") { 502 break 503 } 504 typ, err := d.Type(typOff) 505 if err != nil { 506 fatalf("loading DWARF type: %s", err) 507 } 508 t, ok := typ.(*dwarf.PtrType) 509 if !ok || t == nil { 510 fatalf("internal error: %s has non-pointer type", name) 511 } 512 i, err := strconv.Atoi(name[7:]) 513 if err != nil { 514 fatalf("malformed __cgo__ name: %s", name) 515 } 516 if enums[i] != 0 { 517 t, err := d.Type(enums[i]) 518 if err != nil { 519 fatalf("loading DWARF type: %s", err) 520 } 521 types[i] = t 522 } else { 523 types[i] = t.Type 524 } 525 } 526 if e.Tag != dwarf.TagCompileUnit { 527 r.SkipChildren() 528 } 529 } 530 531 // Record types and typedef information. 532 var conv typeConv 533 conv.Init(p.PtrSize, p.IntSize) 534 for i, n := range names { 535 if types[i] == nil { 536 continue 537 } 538 pos := token.NoPos 539 if ref, ok := nameToRef[n]; ok { 540 pos = ref.Pos() 541 } 542 f, fok := types[i].(*dwarf.FuncType) 543 if n.Kind != "type" && fok { 544 n.Kind = "func" 545 n.FuncType = conv.FuncType(f, pos) 546 } else { 547 n.Type = conv.Type(types[i], pos) 548 if enums[i] != 0 && n.Type.EnumValues != nil { 549 k := fmt.Sprintf("__cgo_enum__%d", i) 550 n.Kind = "const" 551 n.Const = fmt.Sprintf("%#x", n.Type.EnumValues[k]) 552 // Remove injected enum to ensure the value will deep-compare 553 // equally in future loads of the same constant. 554 delete(n.Type.EnumValues, k) 555 } 556 // Prefer debug data over DWARF debug output, if we have it. 557 if n.Kind == "const" && i < len(enumVal) { 558 n.Const = fmt.Sprintf("%#x", enumVal[i]) 559 } 560 } 561 conv.FinishType(pos) 562 } 563 } 564 565 // mangleName does name mangling to translate names 566 // from the original Go source files to the names 567 // used in the final Go files generated by cgo. 568 func (p *Package) mangleName(n *Name) { 569 // When using gccgo variables have to be 570 // exported so that they become global symbols 571 // that the C code can refer to. 572 prefix := "_C" 573 if *gccgo && n.IsVar() { 574 prefix = "C" 575 } 576 n.Mangle = prefix + n.Kind + "_" + n.Go 577 } 578 579 // rewriteCalls rewrites all calls that pass pointers to check that 580 // they follow the rules for passing pointers between Go and C. 581 func (p *Package) rewriteCalls(f *File) { 582 for _, call := range f.Calls { 583 // This is a call to C.xxx; set goname to "xxx". 584 goname := call.Fun.(*ast.SelectorExpr).Sel.Name 585 if goname == "malloc" { 586 continue 587 } 588 name := f.Name[goname] 589 if name.Kind != "func" { 590 // Probably a type conversion. 591 continue 592 } 593 p.rewriteCall(f, call, name) 594 } 595 } 596 597 // rewriteCall rewrites one call to add pointer checks. We replace 598 // each pointer argument x with _cgoCheckPointer(x).(T). 599 func (p *Package) rewriteCall(f *File, call *ast.CallExpr, name *Name) { 600 for i, param := range name.FuncType.Params { 601 if len(call.Args) <= i { 602 // Avoid a crash; this will be caught when the 603 // generated file is compiled. 604 return 605 } 606 607 // An untyped nil does not need a pointer check, and 608 // when _cgoCheckPointer returns the untyped nil the 609 // type assertion we are going to insert will fail. 610 // Easier to just skip nil arguments. 611 // TODO: Note that this fails if nil is shadowed. 612 if id, ok := call.Args[i].(*ast.Ident); ok && id.Name == "nil" { 613 continue 614 } 615 616 if !p.needsPointerCheck(f, param.Go) { 617 continue 618 } 619 620 c := &ast.CallExpr{ 621 Fun: ast.NewIdent("_cgoCheckPointer"), 622 Args: []ast.Expr{ 623 call.Args[i], 624 }, 625 } 626 627 // Add optional additional arguments for an address 628 // expression. 629 if u, ok := call.Args[i].(*ast.UnaryExpr); ok && u.Op == token.AND { 630 c.Args = p.checkAddrArgs(f, c.Args, u.X) 631 } 632 633 // _cgoCheckPointer returns interface{}. 634 // We need to type assert that to the type we want. 635 // If the Go version of this C type uses 636 // unsafe.Pointer, we can't use a type assertion, 637 // because the Go file might not import unsafe. 638 // Instead we use a local variant of _cgoCheckPointer. 639 640 var arg ast.Expr 641 if n := p.unsafeCheckPointerName(param.Go); n != "" { 642 c.Fun = ast.NewIdent(n) 643 arg = c 644 } else { 645 // In order for the type assertion to succeed, 646 // we need it to match the actual type of the 647 // argument. The only type we have is the 648 // type of the function parameter. We know 649 // that the argument type must be assignable 650 // to the function parameter type, or the code 651 // would not compile, but there is nothing 652 // requiring that the types be exactly the 653 // same. Add a type conversion to the 654 // argument so that the type assertion will 655 // succeed. 656 c.Args[0] = &ast.CallExpr{ 657 Fun: param.Go, 658 Args: []ast.Expr{ 659 c.Args[0], 660 }, 661 } 662 663 arg = &ast.TypeAssertExpr{ 664 X: c, 665 Type: param.Go, 666 } 667 } 668 669 call.Args[i] = arg 670 } 671 } 672 673 // needsPointerCheck returns whether the type t needs a pointer check. 674 // This is true if t is a pointer and if the value to which it points 675 // might contain a pointer. 676 func (p *Package) needsPointerCheck(f *File, t ast.Expr) bool { 677 return p.hasPointer(f, t, true) 678 } 679 680 // hasPointer is used by needsPointerCheck. If top is true it returns 681 // whether t is or contains a pointer that might point to a pointer. 682 // If top is false it returns whether t is or contains a pointer. 683 // f may be nil. 684 func (p *Package) hasPointer(f *File, t ast.Expr, top bool) bool { 685 switch t := t.(type) { 686 case *ast.ArrayType: 687 if t.Len == nil { 688 if !top { 689 return true 690 } 691 return p.hasPointer(f, t.Elt, false) 692 } 693 return p.hasPointer(f, t.Elt, top) 694 case *ast.StructType: 695 for _, field := range t.Fields.List { 696 if p.hasPointer(f, field.Type, top) { 697 return true 698 } 699 } 700 return false 701 case *ast.StarExpr: // Pointer type. 702 if !top { 703 return true 704 } 705 return p.hasPointer(f, t.X, false) 706 case *ast.FuncType, *ast.InterfaceType, *ast.MapType, *ast.ChanType: 707 return true 708 case *ast.Ident: 709 // TODO: Handle types defined within function. 710 for _, d := range p.Decl { 711 gd, ok := d.(*ast.GenDecl) 712 if !ok || gd.Tok != token.TYPE { 713 continue 714 } 715 for _, spec := range gd.Specs { 716 ts, ok := spec.(*ast.TypeSpec) 717 if !ok { 718 continue 719 } 720 if ts.Name.Name == t.Name { 721 return p.hasPointer(f, ts.Type, top) 722 } 723 } 724 } 725 if def := typedef[t.Name]; def != nil { 726 return p.hasPointer(f, def.Go, top) 727 } 728 if t.Name == "string" { 729 return !top 730 } 731 if t.Name == "error" { 732 return true 733 } 734 if goTypes[t.Name] != nil { 735 return false 736 } 737 // We can't figure out the type. Conservative 738 // approach is to assume it has a pointer. 739 return true 740 case *ast.SelectorExpr: 741 if l, ok := t.X.(*ast.Ident); !ok || l.Name != "C" { 742 // Type defined in a different package. 743 // Conservative approach is to assume it has a 744 // pointer. 745 return true 746 } 747 if f == nil { 748 // Conservative approach: assume pointer. 749 return true 750 } 751 name := f.Name[t.Sel.Name] 752 if name != nil && name.Kind == "type" && name.Type != nil && name.Type.Go != nil { 753 return p.hasPointer(f, name.Type.Go, top) 754 } 755 // We can't figure out the type. Conservative 756 // approach is to assume it has a pointer. 757 return true 758 default: 759 error_(t.Pos(), "could not understand type %s", gofmt(t)) 760 return true 761 } 762 } 763 764 // checkAddrArgs tries to add arguments to the call of 765 // _cgoCheckPointer when the argument is an address expression. We 766 // pass true to mean that the argument is an address operation of 767 // something other than a slice index, which means that it's only 768 // necessary to check the specific element pointed to, not the entire 769 // object. This is for &s.f, where f is a field in a struct. We can 770 // pass a slice or array, meaning that we should check the entire 771 // slice or array but need not check any other part of the object. 772 // This is for &s.a[i], where we need to check all of a. However, we 773 // only pass the slice or array if we can refer to it without side 774 // effects. 775 func (p *Package) checkAddrArgs(f *File, args []ast.Expr, x ast.Expr) []ast.Expr { 776 index, ok := x.(*ast.IndexExpr) 777 if !ok { 778 // This is the address of something that is not an 779 // index expression. We only need to examine the 780 // single value to which it points. 781 // TODO: what if true is shadowed? 782 return append(args, ast.NewIdent("true")) 783 } 784 if !p.hasSideEffects(f, index.X) { 785 // Examine the entire slice. 786 return append(args, index.X) 787 } 788 // Treat the pointer as unknown. 789 return args 790 } 791 792 // hasSideEffects returns whether the expression x has any side 793 // effects. x is an expression, not a statement, so the only side 794 // effect is a function call. 795 func (p *Package) hasSideEffects(f *File, x ast.Expr) bool { 796 found := false 797 f.walk(x, "expr", 798 func(f *File, x interface{}, context string) { 799 switch x.(type) { 800 case *ast.CallExpr: 801 found = true 802 } 803 }) 804 return found 805 } 806 807 // unsafeCheckPointerName is given the Go version of a C type. If the 808 // type uses unsafe.Pointer, we arrange to build a version of 809 // _cgoCheckPointer that returns that type. This avoids using a type 810 // assertion to unsafe.Pointer in our copy of user code. We return 811 // the name of the _cgoCheckPointer function we are going to build, or 812 // the empty string if the type does not use unsafe.Pointer. 813 func (p *Package) unsafeCheckPointerName(t ast.Expr) string { 814 if !p.hasUnsafePointer(t) { 815 return "" 816 } 817 var buf bytes.Buffer 818 conf.Fprint(&buf, fset, t) 819 s := buf.String() 820 for i, t := range p.CgoChecks { 821 if s == t { 822 return p.unsafeCheckPointerNameIndex(i) 823 } 824 } 825 p.CgoChecks = append(p.CgoChecks, s) 826 return p.unsafeCheckPointerNameIndex(len(p.CgoChecks) - 1) 827 } 828 829 // hasUnsafePointer returns whether the Go type t uses unsafe.Pointer. 830 // t is the Go version of a C type, so we don't need to handle every case. 831 // We only care about direct references, not references via typedefs. 832 func (p *Package) hasUnsafePointer(t ast.Expr) bool { 833 switch t := t.(type) { 834 case *ast.Ident: 835 return t.Name == "unsafe.Pointer" 836 case *ast.ArrayType: 837 return p.hasUnsafePointer(t.Elt) 838 case *ast.StructType: 839 for _, f := range t.Fields.List { 840 if p.hasUnsafePointer(f.Type) { 841 return true 842 } 843 } 844 case *ast.StarExpr: // Pointer type. 845 return p.hasUnsafePointer(t.X) 846 } 847 return false 848 } 849 850 // unsafeCheckPointerNameIndex returns the name to use for a 851 // _cgoCheckPointer variant based on the index in the CgoChecks slice. 852 func (p *Package) unsafeCheckPointerNameIndex(i int) string { 853 return fmt.Sprintf("_cgoCheckPointer%d", i) 854 } 855 856 // rewriteRef rewrites all the C.xxx references in f.AST to refer to the 857 // Go equivalents, now that we have figured out the meaning of all 858 // the xxx. In *godefs mode, rewriteRef replaces the names 859 // with full definitions instead of mangled names. 860 func (p *Package) rewriteRef(f *File) { 861 // Keep a list of all the functions, to remove the ones 862 // only used as expressions and avoid generating bridge 863 // code for them. 864 functions := make(map[string]bool) 865 866 // Assign mangled names. 867 for _, n := range f.Name { 868 if n.Kind == "not-type" { 869 n.Kind = "var" 870 } 871 if n.Mangle == "" { 872 p.mangleName(n) 873 } 874 if n.Kind == "func" { 875 functions[n.Go] = false 876 } 877 } 878 879 // Now that we have all the name types filled in, 880 // scan through the Refs to identify the ones that 881 // are trying to do a ,err call. Also check that 882 // functions are only used in calls. 883 for _, r := range f.Ref { 884 if r.Name.Kind == "const" && r.Name.Const == "" { 885 error_(r.Pos(), "unable to find value of constant C.%s", fixGo(r.Name.Go)) 886 } 887 var expr ast.Expr = ast.NewIdent(r.Name.Mangle) // default 888 switch r.Context { 889 case "call", "call2": 890 if r.Name.Kind != "func" { 891 if r.Name.Kind == "type" { 892 r.Context = "type" 893 if r.Name.Type == nil { 894 error_(r.Pos(), "invalid conversion to C.%s: undefined C type '%s'", fixGo(r.Name.Go), r.Name.C) 895 break 896 } 897 expr = r.Name.Type.Go 898 break 899 } 900 error_(r.Pos(), "call of non-function C.%s", fixGo(r.Name.Go)) 901 break 902 } 903 functions[r.Name.Go] = true 904 if r.Context == "call2" { 905 if r.Name.Go == "_CMalloc" { 906 error_(r.Pos(), "no two-result form for C.malloc") 907 break 908 } 909 // Invent new Name for the two-result function. 910 n := f.Name["2"+r.Name.Go] 911 if n == nil { 912 n = new(Name) 913 *n = *r.Name 914 n.AddError = true 915 n.Mangle = "_C2func_" + n.Go 916 f.Name["2"+r.Name.Go] = n 917 } 918 expr = ast.NewIdent(n.Mangle) 919 r.Name = n 920 break 921 } 922 case "expr": 923 if r.Name.Kind == "func" { 924 // Function is being used in an expression, to e.g. pass around a C function pointer. 925 // Create a new Name for this Ref which causes the variable to be declared in Go land. 926 fpName := "fp_" + r.Name.Go 927 name := f.Name[fpName] 928 if name == nil { 929 name = &Name{ 930 Go: fpName, 931 C: r.Name.C, 932 Kind: "fpvar", 933 Type: &Type{Size: p.PtrSize, Align: p.PtrSize, C: c("void*"), Go: ast.NewIdent("unsafe.Pointer")}, 934 } 935 p.mangleName(name) 936 f.Name[fpName] = name 937 } 938 r.Name = name 939 // Rewrite into call to _Cgo_ptr to prevent assignments. The _Cgo_ptr 940 // function is defined in out.go and simply returns its argument. See 941 // issue 7757. 942 expr = &ast.CallExpr{ 943 Fun: &ast.Ident{NamePos: (*r.Expr).Pos(), Name: "_Cgo_ptr"}, 944 Args: []ast.Expr{ast.NewIdent(name.Mangle)}, 945 } 946 } else if r.Name.Kind == "type" { 947 // Okay - might be new(T) 948 if r.Name.Type == nil { 949 error_(r.Pos(), "expression C.%s: undefined C type '%s'", fixGo(r.Name.Go), r.Name.C) 950 break 951 } 952 expr = r.Name.Type.Go 953 } else if r.Name.Kind == "var" { 954 expr = &ast.StarExpr{Star: (*r.Expr).Pos(), X: expr} 955 } 956 957 case "selector": 958 if r.Name.Kind == "var" { 959 expr = &ast.StarExpr{Star: (*r.Expr).Pos(), X: expr} 960 } else { 961 error_(r.Pos(), "only C variables allowed in selector expression", fixGo(r.Name.Go)) 962 } 963 964 case "type": 965 if r.Name.Kind != "type" { 966 error_(r.Pos(), "expression C.%s used as type", fixGo(r.Name.Go)) 967 } else if r.Name.Type == nil { 968 // Use of C.enum_x, C.struct_x or C.union_x without C definition. 969 // GCC won't raise an error when using pointers to such unknown types. 970 error_(r.Pos(), "type C.%s: undefined C type '%s'", fixGo(r.Name.Go), r.Name.C) 971 } else { 972 expr = r.Name.Type.Go 973 } 974 default: 975 if r.Name.Kind == "func" { 976 error_(r.Pos(), "must call C.%s", fixGo(r.Name.Go)) 977 } 978 } 979 if *godefs { 980 // Substitute definition for mangled type name. 981 if id, ok := expr.(*ast.Ident); ok { 982 if t := typedef[id.Name]; t != nil { 983 expr = t.Go 984 } 985 if id.Name == r.Name.Mangle && r.Name.Const != "" { 986 expr = ast.NewIdent(r.Name.Const) 987 } 988 } 989 } 990 991 // Copy position information from old expr into new expr, 992 // in case expression being replaced is first on line. 993 // See golang.org/issue/6563. 994 pos := (*r.Expr).Pos() 995 switch x := expr.(type) { 996 case *ast.Ident: 997 expr = &ast.Ident{NamePos: pos, Name: x.Name} 998 } 999 1000 *r.Expr = expr 1001 } 1002 1003 // Remove functions only used as expressions, so their respective 1004 // bridge functions are not generated. 1005 for name, used := range functions { 1006 if !used { 1007 delete(f.Name, name) 1008 } 1009 } 1010 } 1011 1012 // gccBaseCmd returns the start of the compiler command line. 1013 // It uses $CC if set, or else $GCC, or else the compiler recorded 1014 // during the initial build as defaultCC. 1015 // defaultCC is defined in zdefaultcc.go, written by cmd/dist. 1016 func (p *Package) gccBaseCmd() []string { 1017 // Use $CC if set, since that's what the build uses. 1018 if ret := strings.Fields(os.Getenv("CC")); len(ret) > 0 { 1019 return ret 1020 } 1021 // Try $GCC if set, since that's what we used to use. 1022 if ret := strings.Fields(os.Getenv("GCC")); len(ret) > 0 { 1023 return ret 1024 } 1025 return strings.Fields(defaultCC) 1026 } 1027 1028 // gccMachine returns the gcc -m flag to use, either "-m32", "-m64" or "-marm". 1029 func (p *Package) gccMachine() []string { 1030 switch goarch { 1031 case "amd64": 1032 return []string{"-m64"} 1033 case "386": 1034 return []string{"-m32"} 1035 case "arm": 1036 return []string{"-marm"} // not thumb 1037 case "s390": 1038 return []string{"-m31"} 1039 case "s390x": 1040 return []string{"-m64"} 1041 } 1042 return nil 1043 } 1044 1045 func gccTmp() string { 1046 return *objDir + "_cgo_.o" 1047 } 1048 1049 // gccCmd returns the gcc command line to use for compiling 1050 // the input. 1051 func (p *Package) gccCmd() []string { 1052 c := append(p.gccBaseCmd(), 1053 "-w", // no warnings 1054 "-Wno-error", // warnings are not errors 1055 "-o"+gccTmp(), // write object to tmp 1056 "-gdwarf-2", // generate DWARF v2 debugging symbols 1057 "-c", // do not link 1058 "-xc", // input language is C 1059 ) 1060 if p.GccIsClang { 1061 c = append(c, 1062 "-ferror-limit=0", 1063 // Apple clang version 1.7 (tags/Apple/clang-77) (based on LLVM 2.9svn) 1064 // doesn't have -Wno-unneeded-internal-declaration, so we need yet another 1065 // flag to disable the warning. Yes, really good diagnostics, clang. 1066 "-Wno-unknown-warning-option", 1067 "-Wno-unneeded-internal-declaration", 1068 "-Wno-unused-function", 1069 "-Qunused-arguments", 1070 // Clang embeds prototypes for some builtin functions, 1071 // like malloc and calloc, but all size_t parameters are 1072 // incorrectly typed unsigned long. We work around that 1073 // by disabling the builtin functions (this is safe as 1074 // it won't affect the actual compilation of the C code). 1075 // See: https://golang.org/issue/6506. 1076 "-fno-builtin", 1077 ) 1078 } 1079 1080 c = append(c, p.GccOptions...) 1081 c = append(c, p.gccMachine()...) 1082 c = append(c, "-") //read input from standard input 1083 return c 1084 } 1085 1086 // gccDebug runs gcc -gdwarf-2 over the C program stdin and 1087 // returns the corresponding DWARF data and, if present, debug data block. 1088 func (p *Package) gccDebug(stdin []byte) (*dwarf.Data, binary.ByteOrder, []byte) { 1089 runGcc(stdin, p.gccCmd()) 1090 1091 isDebugData := func(s string) bool { 1092 // Some systems use leading _ to denote non-assembly symbols. 1093 return s == "__cgodebug_data" || s == "___cgodebug_data" 1094 } 1095 1096 if f, err := macho.Open(gccTmp()); err == nil { 1097 defer f.Close() 1098 d, err := f.DWARF() 1099 if err != nil { 1100 fatalf("cannot load DWARF output from %s: %v", gccTmp(), err) 1101 } 1102 var data []byte 1103 if f.Symtab != nil { 1104 for i := range f.Symtab.Syms { 1105 s := &f.Symtab.Syms[i] 1106 if isDebugData(s.Name) { 1107 // Found it. Now find data section. 1108 if i := int(s.Sect) - 1; 0 <= i && i < len(f.Sections) { 1109 sect := f.Sections[i] 1110 if sect.Addr <= s.Value && s.Value < sect.Addr+sect.Size { 1111 if sdat, err := sect.Data(); err == nil { 1112 data = sdat[s.Value-sect.Addr:] 1113 } 1114 } 1115 } 1116 } 1117 } 1118 } 1119 return d, f.ByteOrder, data 1120 } 1121 1122 if f, err := elf.Open(gccTmp()); err == nil { 1123 defer f.Close() 1124 d, err := f.DWARF() 1125 if err != nil { 1126 fatalf("cannot load DWARF output from %s: %v", gccTmp(), err) 1127 } 1128 var data []byte 1129 symtab, err := f.Symbols() 1130 if err == nil { 1131 for i := range symtab { 1132 s := &symtab[i] 1133 if isDebugData(s.Name) { 1134 // Found it. Now find data section. 1135 if i := int(s.Section); 0 <= i && i < len(f.Sections) { 1136 sect := f.Sections[i] 1137 if sect.Addr <= s.Value && s.Value < sect.Addr+sect.Size { 1138 if sdat, err := sect.Data(); err == nil { 1139 data = sdat[s.Value-sect.Addr:] 1140 } 1141 } 1142 } 1143 } 1144 } 1145 } 1146 return d, f.ByteOrder, data 1147 } 1148 1149 if f, err := pe.Open(gccTmp()); err == nil { 1150 defer f.Close() 1151 d, err := f.DWARF() 1152 if err != nil { 1153 fatalf("cannot load DWARF output from %s: %v", gccTmp(), err) 1154 } 1155 var data []byte 1156 for _, s := range f.Symbols { 1157 if isDebugData(s.Name) { 1158 if i := int(s.SectionNumber) - 1; 0 <= i && i < len(f.Sections) { 1159 sect := f.Sections[i] 1160 if s.Value < sect.Size { 1161 if sdat, err := sect.Data(); err == nil { 1162 data = sdat[s.Value:] 1163 } 1164 } 1165 } 1166 } 1167 } 1168 return d, binary.LittleEndian, data 1169 } 1170 1171 fatalf("cannot parse gcc output %s as ELF, Mach-O, PE object", gccTmp()) 1172 panic("not reached") 1173 } 1174 1175 // gccDefines runs gcc -E -dM -xc - over the C program stdin 1176 // and returns the corresponding standard output, which is the 1177 // #defines that gcc encountered while processing the input 1178 // and its included files. 1179 func (p *Package) gccDefines(stdin []byte) string { 1180 base := append(p.gccBaseCmd(), "-E", "-dM", "-xc") 1181 base = append(base, p.gccMachine()...) 1182 stdout, _ := runGcc(stdin, append(append(base, p.GccOptions...), "-")) 1183 return stdout 1184 } 1185 1186 // gccErrors runs gcc over the C program stdin and returns 1187 // the errors that gcc prints. That is, this function expects 1188 // gcc to fail. 1189 func (p *Package) gccErrors(stdin []byte) string { 1190 // TODO(rsc): require failure 1191 args := p.gccCmd() 1192 1193 if *debugGcc { 1194 fmt.Fprintf(os.Stderr, "$ %s <<EOF\n", strings.Join(args, " ")) 1195 os.Stderr.Write(stdin) 1196 fmt.Fprint(os.Stderr, "EOF\n") 1197 } 1198 stdout, stderr, _ := run(stdin, args) 1199 if *debugGcc { 1200 os.Stderr.Write(stdout) 1201 os.Stderr.Write(stderr) 1202 } 1203 return string(stderr) 1204 } 1205 1206 // runGcc runs the gcc command line args with stdin on standard input. 1207 // If the command exits with a non-zero exit status, runGcc prints 1208 // details about what was run and exits. 1209 // Otherwise runGcc returns the data written to standard output and standard error. 1210 // Note that for some of the uses we expect useful data back 1211 // on standard error, but for those uses gcc must still exit 0. 1212 func runGcc(stdin []byte, args []string) (string, string) { 1213 if *debugGcc { 1214 fmt.Fprintf(os.Stderr, "$ %s <<EOF\n", strings.Join(args, " ")) 1215 os.Stderr.Write(stdin) 1216 fmt.Fprint(os.Stderr, "EOF\n") 1217 } 1218 stdout, stderr, ok := run(stdin, args) 1219 if *debugGcc { 1220 os.Stderr.Write(stdout) 1221 os.Stderr.Write(stderr) 1222 } 1223 if !ok { 1224 os.Stderr.Write(stderr) 1225 os.Exit(2) 1226 } 1227 return string(stdout), string(stderr) 1228 } 1229 1230 // A typeConv is a translator from dwarf types to Go types 1231 // with equivalent memory layout. 1232 type typeConv struct { 1233 // Cache of already-translated or in-progress types. 1234 m map[dwarf.Type]*Type 1235 typedef map[string]ast.Expr 1236 1237 // Map from types to incomplete pointers to those types. 1238 ptrs map[dwarf.Type][]*Type 1239 // Keys of ptrs in insertion order (deterministic worklist) 1240 ptrKeys []dwarf.Type 1241 1242 // Predeclared types. 1243 bool ast.Expr 1244 byte ast.Expr // denotes padding 1245 int8, int16, int32, int64 ast.Expr 1246 uint8, uint16, uint32, uint64, uintptr ast.Expr 1247 float32, float64 ast.Expr 1248 complex64, complex128 ast.Expr 1249 void ast.Expr 1250 string ast.Expr 1251 goVoid ast.Expr // _Ctype_void, denotes C's void 1252 goVoidPtr ast.Expr // unsafe.Pointer or *byte 1253 1254 ptrSize int64 1255 intSize int64 1256 } 1257 1258 var tagGen int 1259 var typedef = make(map[string]*Type) 1260 var goIdent = make(map[string]*ast.Ident) 1261 1262 func (c *typeConv) Init(ptrSize, intSize int64) { 1263 c.ptrSize = ptrSize 1264 c.intSize = intSize 1265 c.m = make(map[dwarf.Type]*Type) 1266 c.ptrs = make(map[dwarf.Type][]*Type) 1267 c.bool = c.Ident("bool") 1268 c.byte = c.Ident("byte") 1269 c.int8 = c.Ident("int8") 1270 c.int16 = c.Ident("int16") 1271 c.int32 = c.Ident("int32") 1272 c.int64 = c.Ident("int64") 1273 c.uint8 = c.Ident("uint8") 1274 c.uint16 = c.Ident("uint16") 1275 c.uint32 = c.Ident("uint32") 1276 c.uint64 = c.Ident("uint64") 1277 c.uintptr = c.Ident("uintptr") 1278 c.float32 = c.Ident("float32") 1279 c.float64 = c.Ident("float64") 1280 c.complex64 = c.Ident("complex64") 1281 c.complex128 = c.Ident("complex128") 1282 c.void = c.Ident("void") 1283 c.string = c.Ident("string") 1284 c.goVoid = c.Ident("_Ctype_void") 1285 1286 // Normally cgo translates void* to unsafe.Pointer, 1287 // but for historical reasons -godefs uses *byte instead. 1288 if *godefs { 1289 c.goVoidPtr = &ast.StarExpr{X: c.byte} 1290 } else { 1291 c.goVoidPtr = c.Ident("unsafe.Pointer") 1292 } 1293 } 1294 1295 // base strips away qualifiers and typedefs to get the underlying type 1296 func base(dt dwarf.Type) dwarf.Type { 1297 for { 1298 if d, ok := dt.(*dwarf.QualType); ok { 1299 dt = d.Type 1300 continue 1301 } 1302 if d, ok := dt.(*dwarf.TypedefType); ok { 1303 dt = d.Type 1304 continue 1305 } 1306 break 1307 } 1308 return dt 1309 } 1310 1311 // Map from dwarf text names to aliases we use in package "C". 1312 var dwarfToName = map[string]string{ 1313 "long int": "long", 1314 "long unsigned int": "ulong", 1315 "unsigned int": "uint", 1316 "short unsigned int": "ushort", 1317 "unsigned short": "ushort", // Used by Clang; issue 13129. 1318 "short int": "short", 1319 "long long int": "longlong", 1320 "long long unsigned int": "ulonglong", 1321 "signed char": "schar", 1322 "unsigned char": "uchar", 1323 } 1324 1325 const signedDelta = 64 1326 1327 // String returns the current type representation. Format arguments 1328 // are assembled within this method so that any changes in mutable 1329 // values are taken into account. 1330 func (tr *TypeRepr) String() string { 1331 if len(tr.Repr) == 0 { 1332 return "" 1333 } 1334 if len(tr.FormatArgs) == 0 { 1335 return tr.Repr 1336 } 1337 return fmt.Sprintf(tr.Repr, tr.FormatArgs...) 1338 } 1339 1340 // Empty reports whether the result of String would be "". 1341 func (tr *TypeRepr) Empty() bool { 1342 return len(tr.Repr) == 0 1343 } 1344 1345 // Set modifies the type representation. 1346 // If fargs are provided, repr is used as a format for fmt.Sprintf. 1347 // Otherwise, repr is used unprocessed as the type representation. 1348 func (tr *TypeRepr) Set(repr string, fargs ...interface{}) { 1349 tr.Repr = repr 1350 tr.FormatArgs = fargs 1351 } 1352 1353 // FinishType completes any outstanding type mapping work. 1354 // In particular, it resolves incomplete pointer types. 1355 func (c *typeConv) FinishType(pos token.Pos) { 1356 // Completing one pointer type might produce more to complete. 1357 // Keep looping until they're all done. 1358 for len(c.ptrKeys) > 0 { 1359 dtype := c.ptrKeys[0] 1360 c.ptrKeys = c.ptrKeys[1:] 1361 1362 // Note Type might invalidate c.ptrs[dtype]. 1363 t := c.Type(dtype, pos) 1364 for _, ptr := range c.ptrs[dtype] { 1365 ptr.Go.(*ast.StarExpr).X = t.Go 1366 ptr.C.Set("%s*", t.C) 1367 } 1368 c.ptrs[dtype] = nil // retain the map key 1369 } 1370 } 1371 1372 // Type returns a *Type with the same memory layout as 1373 // dtype when used as the type of a variable or a struct field. 1374 func (c *typeConv) Type(dtype dwarf.Type, pos token.Pos) *Type { 1375 if t, ok := c.m[dtype]; ok { 1376 if t.Go == nil { 1377 fatalf("%s: type conversion loop at %s", lineno(pos), dtype) 1378 } 1379 return t 1380 } 1381 1382 t := new(Type) 1383 t.Size = dtype.Size() // note: wrong for array of pointers, corrected below 1384 t.Align = -1 1385 t.C = &TypeRepr{Repr: dtype.Common().Name} 1386 c.m[dtype] = t 1387 1388 switch dt := dtype.(type) { 1389 default: 1390 fatalf("%s: unexpected type: %s", lineno(pos), dtype) 1391 1392 case *dwarf.AddrType: 1393 if t.Size != c.ptrSize { 1394 fatalf("%s: unexpected: %d-byte address type - %s", lineno(pos), t.Size, dtype) 1395 } 1396 t.Go = c.uintptr 1397 t.Align = t.Size 1398 1399 case *dwarf.ArrayType: 1400 if dt.StrideBitSize > 0 { 1401 // Cannot represent bit-sized elements in Go. 1402 t.Go = c.Opaque(t.Size) 1403 break 1404 } 1405 count := dt.Count 1406 if count == -1 { 1407 // Indicates flexible array member, which Go doesn't support. 1408 // Translate to zero-length array instead. 1409 count = 0 1410 } 1411 sub := c.Type(dt.Type, pos) 1412 t.Align = sub.Align 1413 t.Go = &ast.ArrayType{ 1414 Len: c.intExpr(count), 1415 Elt: sub.Go, 1416 } 1417 // Recalculate t.Size now that we know sub.Size. 1418 t.Size = count * sub.Size 1419 t.C.Set("__typeof__(%s[%d])", sub.C, dt.Count) 1420 1421 case *dwarf.BoolType: 1422 t.Go = c.bool 1423 t.Align = 1 1424 1425 case *dwarf.CharType: 1426 if t.Size != 1 { 1427 fatalf("%s: unexpected: %d-byte char type - %s", lineno(pos), t.Size, dtype) 1428 } 1429 t.Go = c.int8 1430 t.Align = 1 1431 1432 case *dwarf.EnumType: 1433 if t.Align = t.Size; t.Align >= c.ptrSize { 1434 t.Align = c.ptrSize 1435 } 1436 t.C.Set("enum " + dt.EnumName) 1437 signed := 0 1438 t.EnumValues = make(map[string]int64) 1439 for _, ev := range dt.Val { 1440 t.EnumValues[ev.Name] = ev.Val 1441 if ev.Val < 0 { 1442 signed = signedDelta 1443 } 1444 } 1445 switch t.Size + int64(signed) { 1446 default: 1447 fatalf("%s: unexpected: %d-byte enum type - %s", lineno(pos), t.Size, dtype) 1448 case 1: 1449 t.Go = c.uint8 1450 case 2: 1451 t.Go = c.uint16 1452 case 4: 1453 t.Go = c.uint32 1454 case 8: 1455 t.Go = c.uint64 1456 case 1 + signedDelta: 1457 t.Go = c.int8 1458 case 2 + signedDelta: 1459 t.Go = c.int16 1460 case 4 + signedDelta: 1461 t.Go = c.int32 1462 case 8 + signedDelta: 1463 t.Go = c.int64 1464 } 1465 1466 case *dwarf.FloatType: 1467 switch t.Size { 1468 default: 1469 fatalf("%s: unexpected: %d-byte float type - %s", lineno(pos), t.Size, dtype) 1470 case 4: 1471 t.Go = c.float32 1472 case 8: 1473 t.Go = c.float64 1474 } 1475 if t.Align = t.Size; t.Align >= c.ptrSize { 1476 t.Align = c.ptrSize 1477 } 1478 1479 case *dwarf.ComplexType: 1480 switch t.Size { 1481 default: 1482 fatalf("%s: unexpected: %d-byte complex type - %s", lineno(pos), t.Size, dtype) 1483 case 8: 1484 t.Go = c.complex64 1485 case 16: 1486 t.Go = c.complex128 1487 } 1488 if t.Align = t.Size; t.Align >= c.ptrSize { 1489 t.Align = c.ptrSize 1490 } 1491 1492 case *dwarf.FuncType: 1493 // No attempt at translation: would enable calls 1494 // directly between worlds, but we need to moderate those. 1495 t.Go = c.uintptr 1496 t.Align = c.ptrSize 1497 1498 case *dwarf.IntType: 1499 if dt.BitSize > 0 { 1500 fatalf("%s: unexpected: %d-bit int type - %s", lineno(pos), dt.BitSize, dtype) 1501 } 1502 switch t.Size { 1503 default: 1504 fatalf("%s: unexpected: %d-byte int type - %s", lineno(pos), t.Size, dtype) 1505 case 1: 1506 t.Go = c.int8 1507 case 2: 1508 t.Go = c.int16 1509 case 4: 1510 t.Go = c.int32 1511 case 8: 1512 t.Go = c.int64 1513 case 16: 1514 t.Go = &ast.ArrayType{ 1515 Len: c.intExpr(t.Size), 1516 Elt: c.uint8, 1517 } 1518 } 1519 if t.Align = t.Size; t.Align >= c.ptrSize { 1520 t.Align = c.ptrSize 1521 } 1522 1523 case *dwarf.PtrType: 1524 // Clang doesn't emit DW_AT_byte_size for pointer types. 1525 if t.Size != c.ptrSize && t.Size != -1 { 1526 fatalf("%s: unexpected: %d-byte pointer type - %s", lineno(pos), t.Size, dtype) 1527 } 1528 t.Size = c.ptrSize 1529 t.Align = c.ptrSize 1530 1531 if _, ok := base(dt.Type).(*dwarf.VoidType); ok { 1532 t.Go = c.goVoidPtr 1533 t.C.Set("void*") 1534 break 1535 } 1536 1537 // Placeholder initialization; completed in FinishType. 1538 t.Go = &ast.StarExpr{} 1539 t.C.Set("<incomplete>*") 1540 if _, ok := c.ptrs[dt.Type]; !ok { 1541 c.ptrKeys = append(c.ptrKeys, dt.Type) 1542 } 1543 c.ptrs[dt.Type] = append(c.ptrs[dt.Type], t) 1544 1545 case *dwarf.QualType: 1546 // Ignore qualifier. 1547 t = c.Type(dt.Type, pos) 1548 c.m[dtype] = t 1549 return t 1550 1551 case *dwarf.StructType: 1552 // Convert to Go struct, being careful about alignment. 1553 // Have to give it a name to simulate C "struct foo" references. 1554 tag := dt.StructName 1555 if dt.ByteSize < 0 && tag == "" { // opaque unnamed struct - should not be possible 1556 break 1557 } 1558 if tag == "" { 1559 tag = "__" + strconv.Itoa(tagGen) 1560 tagGen++ 1561 } else if t.C.Empty() { 1562 t.C.Set(dt.Kind + " " + tag) 1563 } 1564 name := c.Ident("_Ctype_" + dt.Kind + "_" + tag) 1565 t.Go = name // publish before recursive calls 1566 goIdent[name.Name] = name 1567 if dt.ByteSize < 0 { 1568 // Size calculation in c.Struct/c.Opaque will die with size=-1 (unknown), 1569 // so execute the basic things that the struct case would do 1570 // other than try to determine a Go representation. 1571 tt := *t 1572 tt.C = &TypeRepr{"%s %s", []interface{}{dt.Kind, tag}} 1573 tt.Go = c.Ident("struct{}") 1574 typedef[name.Name] = &tt 1575 break 1576 } 1577 switch dt.Kind { 1578 case "class", "union": 1579 t.Go = c.Opaque(t.Size) 1580 if t.C.Empty() { 1581 t.C.Set("__typeof__(unsigned char[%d])", t.Size) 1582 } 1583 t.Align = 1 // TODO: should probably base this on field alignment. 1584 typedef[name.Name] = t 1585 case "struct": 1586 g, csyntax, align := c.Struct(dt, pos) 1587 if t.C.Empty() { 1588 t.C.Set(csyntax) 1589 } 1590 t.Align = align 1591 tt := *t 1592 if tag != "" { 1593 tt.C = &TypeRepr{"struct %s", []interface{}{tag}} 1594 } 1595 tt.Go = g 1596 typedef[name.Name] = &tt 1597 } 1598 1599 case *dwarf.TypedefType: 1600 // Record typedef for printing. 1601 if dt.Name == "_GoString_" { 1602 // Special C name for Go string type. 1603 // Knows string layout used by compilers: pointer plus length, 1604 // which rounds up to 2 pointers after alignment. 1605 t.Go = c.string 1606 t.Size = c.ptrSize * 2 1607 t.Align = c.ptrSize 1608 break 1609 } 1610 if dt.Name == "_GoBytes_" { 1611 // Special C name for Go []byte type. 1612 // Knows slice layout used by compilers: pointer, length, cap. 1613 t.Go = c.Ident("[]byte") 1614 t.Size = c.ptrSize + 4 + 4 1615 t.Align = c.ptrSize 1616 break 1617 } 1618 name := c.Ident("_Ctype_" + dt.Name) 1619 goIdent[name.Name] = name 1620 sub := c.Type(dt.Type, pos) 1621 t.Go = name 1622 t.Size = sub.Size 1623 t.Align = sub.Align 1624 oldType := typedef[name.Name] 1625 if oldType == nil { 1626 tt := *t 1627 tt.Go = sub.Go 1628 typedef[name.Name] = &tt 1629 } 1630 1631 // If sub.Go.Name is "_Ctype_struct_foo" or "_Ctype_union_foo" or "_Ctype_class_foo", 1632 // use that as the Go form for this typedef too, so that the typedef will be interchangeable 1633 // with the base type. 1634 // In -godefs mode, do this for all typedefs. 1635 if isStructUnionClass(sub.Go) || *godefs { 1636 t.Go = sub.Go 1637 1638 if isStructUnionClass(sub.Go) { 1639 // Use the typedef name for C code. 1640 typedef[sub.Go.(*ast.Ident).Name].C = t.C 1641 } 1642 1643 // If we've seen this typedef before, and it 1644 // was an anonymous struct/union/class before 1645 // too, use the old definition. 1646 // TODO: it would be safer to only do this if 1647 // we verify that the types are the same. 1648 if oldType != nil && isStructUnionClass(oldType.Go) { 1649 t.Go = oldType.Go 1650 } 1651 } 1652 1653 case *dwarf.UcharType: 1654 if t.Size != 1 { 1655 fatalf("%s: unexpected: %d-byte uchar type - %s", lineno(pos), t.Size, dtype) 1656 } 1657 t.Go = c.uint8 1658 t.Align = 1 1659 1660 case *dwarf.UintType: 1661 if dt.BitSize > 0 { 1662 fatalf("%s: unexpected: %d-bit uint type - %s", lineno(pos), dt.BitSize, dtype) 1663 } 1664 switch t.Size { 1665 default: 1666 fatalf("%s: unexpected: %d-byte uint type - %s", lineno(pos), t.Size, dtype) 1667 case 1: 1668 t.Go = c.uint8 1669 case 2: 1670 t.Go = c.uint16 1671 case 4: 1672 t.Go = c.uint32 1673 case 8: 1674 t.Go = c.uint64 1675 case 16: 1676 t.Go = &ast.ArrayType{ 1677 Len: c.intExpr(t.Size), 1678 Elt: c.uint8, 1679 } 1680 } 1681 if t.Align = t.Size; t.Align >= c.ptrSize { 1682 t.Align = c.ptrSize 1683 } 1684 1685 case *dwarf.VoidType: 1686 t.Go = c.goVoid 1687 t.C.Set("void") 1688 t.Align = 1 1689 } 1690 1691 switch dtype.(type) { 1692 case *dwarf.AddrType, *dwarf.BoolType, *dwarf.CharType, *dwarf.ComplexType, *dwarf.IntType, *dwarf.FloatType, *dwarf.UcharType, *dwarf.UintType: 1693 s := dtype.Common().Name 1694 if s != "" { 1695 if ss, ok := dwarfToName[s]; ok { 1696 s = ss 1697 } 1698 s = strings.Join(strings.Split(s, " "), "") // strip spaces 1699 name := c.Ident("_Ctype_" + s) 1700 tt := *t 1701 typedef[name.Name] = &tt 1702 if !*godefs { 1703 t.Go = name 1704 } 1705 } 1706 } 1707 1708 if t.Size < 0 { 1709 // Unsized types are [0]byte, unless they're typedefs of other types 1710 // or structs with tags. 1711 // if so, use the name we've already defined. 1712 t.Size = 0 1713 switch dt := dtype.(type) { 1714 case *dwarf.TypedefType: 1715 // ok 1716 case *dwarf.StructType: 1717 if dt.StructName != "" { 1718 break 1719 } 1720 t.Go = c.Opaque(0) 1721 default: 1722 t.Go = c.Opaque(0) 1723 } 1724 if t.C.Empty() { 1725 t.C.Set("void") 1726 } 1727 } 1728 1729 if t.C.Empty() { 1730 fatalf("%s: internal error: did not create C name for %s", lineno(pos), dtype) 1731 } 1732 1733 return t 1734 } 1735 1736 // isStructUnionClass reports whether the type described by the Go syntax x 1737 // is a struct, union, or class with a tag. 1738 func isStructUnionClass(x ast.Expr) bool { 1739 id, ok := x.(*ast.Ident) 1740 if !ok { 1741 return false 1742 } 1743 name := id.Name 1744 return strings.HasPrefix(name, "_Ctype_struct_") || 1745 strings.HasPrefix(name, "_Ctype_union_") || 1746 strings.HasPrefix(name, "_Ctype_class_") 1747 } 1748 1749 // FuncArg returns a Go type with the same memory layout as 1750 // dtype when used as the type of a C function argument. 1751 func (c *typeConv) FuncArg(dtype dwarf.Type, pos token.Pos) *Type { 1752 t := c.Type(dtype, pos) 1753 switch dt := dtype.(type) { 1754 case *dwarf.ArrayType: 1755 // Arrays are passed implicitly as pointers in C. 1756 // In Go, we must be explicit. 1757 tr := &TypeRepr{} 1758 tr.Set("%s*", t.C) 1759 return &Type{ 1760 Size: c.ptrSize, 1761 Align: c.ptrSize, 1762 Go: &ast.StarExpr{X: t.Go}, 1763 C: tr, 1764 } 1765 case *dwarf.TypedefType: 1766 // C has much more relaxed rules than Go for 1767 // implicit type conversions. When the parameter 1768 // is type T defined as *X, simulate a little of the 1769 // laxness of C by making the argument *X instead of T. 1770 if ptr, ok := base(dt.Type).(*dwarf.PtrType); ok { 1771 // Unless the typedef happens to point to void* since 1772 // Go has special rules around using unsafe.Pointer. 1773 if _, void := base(ptr.Type).(*dwarf.VoidType); void { 1774 break 1775 } 1776 1777 t = c.Type(ptr, pos) 1778 if t == nil { 1779 return nil 1780 } 1781 1782 // Remember the C spelling, in case the struct 1783 // has __attribute__((unavailable)) on it. See issue 2888. 1784 t.Typedef = dt.Name 1785 } 1786 } 1787 return t 1788 } 1789 1790 // FuncType returns the Go type analogous to dtype. 1791 // There is no guarantee about matching memory layout. 1792 func (c *typeConv) FuncType(dtype *dwarf.FuncType, pos token.Pos) *FuncType { 1793 p := make([]*Type, len(dtype.ParamType)) 1794 gp := make([]*ast.Field, len(dtype.ParamType)) 1795 for i, f := range dtype.ParamType { 1796 // gcc's DWARF generator outputs a single DotDotDotType parameter for 1797 // function pointers that specify no parameters (e.g. void 1798 // (*__cgo_0)()). Treat this special case as void. This case is 1799 // invalid according to ISO C anyway (i.e. void (*__cgo_1)(...) is not 1800 // legal). 1801 if _, ok := f.(*dwarf.DotDotDotType); ok && i == 0 { 1802 p, gp = nil, nil 1803 break 1804 } 1805 p[i] = c.FuncArg(f, pos) 1806 gp[i] = &ast.Field{Type: p[i].Go} 1807 } 1808 var r *Type 1809 var gr []*ast.Field 1810 if _, ok := dtype.ReturnType.(*dwarf.VoidType); ok { 1811 gr = []*ast.Field{{Type: c.goVoid}} 1812 } else if dtype.ReturnType != nil { 1813 r = c.Type(dtype.ReturnType, pos) 1814 gr = []*ast.Field{{Type: r.Go}} 1815 } 1816 return &FuncType{ 1817 Params: p, 1818 Result: r, 1819 Go: &ast.FuncType{ 1820 Params: &ast.FieldList{List: gp}, 1821 Results: &ast.FieldList{List: gr}, 1822 }, 1823 } 1824 } 1825 1826 // Identifier 1827 func (c *typeConv) Ident(s string) *ast.Ident { 1828 return ast.NewIdent(s) 1829 } 1830 1831 // Opaque type of n bytes. 1832 func (c *typeConv) Opaque(n int64) ast.Expr { 1833 return &ast.ArrayType{ 1834 Len: c.intExpr(n), 1835 Elt: c.byte, 1836 } 1837 } 1838 1839 // Expr for integer n. 1840 func (c *typeConv) intExpr(n int64) ast.Expr { 1841 return &ast.BasicLit{ 1842 Kind: token.INT, 1843 Value: strconv.FormatInt(n, 10), 1844 } 1845 } 1846 1847 // Add padding of given size to fld. 1848 func (c *typeConv) pad(fld []*ast.Field, sizes []int64, size int64) ([]*ast.Field, []int64) { 1849 n := len(fld) 1850 fld = fld[0 : n+1] 1851 fld[n] = &ast.Field{Names: []*ast.Ident{c.Ident("_")}, Type: c.Opaque(size)} 1852 sizes = sizes[0 : n+1] 1853 sizes[n] = size 1854 return fld, sizes 1855 } 1856 1857 // Struct conversion: return Go and (gc) C syntax for type. 1858 func (c *typeConv) Struct(dt *dwarf.StructType, pos token.Pos) (expr *ast.StructType, csyntax string, align int64) { 1859 // Minimum alignment for a struct is 1 byte. 1860 align = 1 1861 1862 var buf bytes.Buffer 1863 buf.WriteString("struct {") 1864 fld := make([]*ast.Field, 0, 2*len(dt.Field)+1) // enough for padding around every field 1865 sizes := make([]int64, 0, 2*len(dt.Field)+1) 1866 off := int64(0) 1867 1868 // Rename struct fields that happen to be named Go keywords into 1869 // _{keyword}. Create a map from C ident -> Go ident. The Go ident will 1870 // be mangled. Any existing identifier that already has the same name on 1871 // the C-side will cause the Go-mangled version to be prefixed with _. 1872 // (e.g. in a struct with fields '_type' and 'type', the latter would be 1873 // rendered as '__type' in Go). 1874 ident := make(map[string]string) 1875 used := make(map[string]bool) 1876 for _, f := range dt.Field { 1877 ident[f.Name] = f.Name 1878 used[f.Name] = true 1879 } 1880 1881 if !*godefs { 1882 for cid, goid := range ident { 1883 if token.Lookup(goid).IsKeyword() { 1884 // Avoid keyword 1885 goid = "_" + goid 1886 1887 // Also avoid existing fields 1888 for _, exist := used[goid]; exist; _, exist = used[goid] { 1889 goid = "_" + goid 1890 } 1891 1892 used[goid] = true 1893 ident[cid] = goid 1894 } 1895 } 1896 } 1897 1898 anon := 0 1899 for _, f := range dt.Field { 1900 if f.ByteOffset > off { 1901 fld, sizes = c.pad(fld, sizes, f.ByteOffset-off) 1902 off = f.ByteOffset 1903 } 1904 1905 name := f.Name 1906 ft := f.Type 1907 1908 // In godefs mode, if this field is a C11 1909 // anonymous union then treat the first field in the 1910 // union as the field in the struct. This handles 1911 // cases like the glibc <sys/resource.h> file; see 1912 // issue 6677. 1913 if *godefs { 1914 if st, ok := f.Type.(*dwarf.StructType); ok && name == "" && st.Kind == "union" && len(st.Field) > 0 && !used[st.Field[0].Name] { 1915 name = st.Field[0].Name 1916 ident[name] = name 1917 ft = st.Field[0].Type 1918 } 1919 } 1920 1921 // TODO: Handle fields that are anonymous structs by 1922 // promoting the fields of the inner struct. 1923 1924 t := c.Type(ft, pos) 1925 tgo := t.Go 1926 size := t.Size 1927 talign := t.Align 1928 if f.BitSize > 0 { 1929 if f.BitSize%8 != 0 { 1930 continue 1931 } 1932 size = f.BitSize / 8 1933 name := tgo.(*ast.Ident).String() 1934 if strings.HasPrefix(name, "int") { 1935 name = "int" 1936 } else { 1937 name = "uint" 1938 } 1939 tgo = ast.NewIdent(name + fmt.Sprint(f.BitSize)) 1940 talign = size 1941 } 1942 1943 if talign > 0 && f.ByteOffset%talign != 0 { 1944 // Drop misaligned fields, the same way we drop integer bit fields. 1945 // The goal is to make available what can be made available. 1946 // Otherwise one bad and unneeded field in an otherwise okay struct 1947 // makes the whole program not compile. Much of the time these 1948 // structs are in system headers that cannot be corrected. 1949 continue 1950 } 1951 n := len(fld) 1952 fld = fld[0 : n+1] 1953 if name == "" { 1954 name = fmt.Sprintf("anon%d", anon) 1955 anon++ 1956 ident[name] = name 1957 } 1958 fld[n] = &ast.Field{Names: []*ast.Ident{c.Ident(ident[name])}, Type: tgo} 1959 sizes = sizes[0 : n+1] 1960 sizes[n] = size 1961 off += size 1962 buf.WriteString(t.C.String()) 1963 buf.WriteString(" ") 1964 buf.WriteString(name) 1965 buf.WriteString("; ") 1966 if talign > align { 1967 align = talign 1968 } 1969 } 1970 if off < dt.ByteSize { 1971 fld, sizes = c.pad(fld, sizes, dt.ByteSize-off) 1972 off = dt.ByteSize 1973 } 1974 1975 // If the last field in a non-zero-sized struct is zero-sized 1976 // the compiler is going to pad it by one (see issue 9401). 1977 // We can't permit that, because then the size of the Go 1978 // struct will not be the same as the size of the C struct. 1979 // Our only option in such a case is to remove the field, 1980 // which means that it can not be referenced from Go. 1981 for off > 0 && sizes[len(sizes)-1] == 0 { 1982 n := len(sizes) 1983 fld = fld[0 : n-1] 1984 sizes = sizes[0 : n-1] 1985 } 1986 1987 if off != dt.ByteSize { 1988 fatalf("%s: struct size calculation error off=%d bytesize=%d", lineno(pos), off, dt.ByteSize) 1989 } 1990 buf.WriteString("}") 1991 csyntax = buf.String() 1992 1993 if *godefs { 1994 godefsFields(fld) 1995 } 1996 expr = &ast.StructType{Fields: &ast.FieldList{List: fld}} 1997 return 1998 } 1999 2000 func upper(s string) string { 2001 if s == "" { 2002 return "" 2003 } 2004 r, size := utf8.DecodeRuneInString(s) 2005 if r == '_' { 2006 return "X" + s 2007 } 2008 return string(unicode.ToUpper(r)) + s[size:] 2009 } 2010 2011 // godefsFields rewrites field names for use in Go or C definitions. 2012 // It strips leading common prefixes (like tv_ in tv_sec, tv_usec) 2013 // converts names to upper case, and rewrites _ into Pad_godefs_n, 2014 // so that all fields are exported. 2015 func godefsFields(fld []*ast.Field) { 2016 prefix := fieldPrefix(fld) 2017 npad := 0 2018 for _, f := range fld { 2019 for _, n := range f.Names { 2020 if n.Name != prefix { 2021 n.Name = strings.TrimPrefix(n.Name, prefix) 2022 } 2023 if n.Name == "_" { 2024 // Use exported name instead. 2025 n.Name = "Pad_cgo_" + strconv.Itoa(npad) 2026 npad++ 2027 } 2028 n.Name = upper(n.Name) 2029 } 2030 } 2031 } 2032 2033 // fieldPrefix returns the prefix that should be removed from all the 2034 // field names when generating the C or Go code. For generated 2035 // C, we leave the names as is (tv_sec, tv_usec), since that's what 2036 // people are used to seeing in C. For generated Go code, such as 2037 // package syscall's data structures, we drop a common prefix 2038 // (so sec, usec, which will get turned into Sec, Usec for exporting). 2039 func fieldPrefix(fld []*ast.Field) string { 2040 prefix := "" 2041 for _, f := range fld { 2042 for _, n := range f.Names { 2043 // Ignore field names that don't have the prefix we're 2044 // looking for. It is common in C headers to have fields 2045 // named, say, _pad in an otherwise prefixed header. 2046 // If the struct has 3 fields tv_sec, tv_usec, _pad1, then we 2047 // still want to remove the tv_ prefix. 2048 // The check for "orig_" here handles orig_eax in the 2049 // x86 ptrace register sets, which otherwise have all fields 2050 // with reg_ prefixes. 2051 if strings.HasPrefix(n.Name, "orig_") || strings.HasPrefix(n.Name, "_") { 2052 continue 2053 } 2054 i := strings.Index(n.Name, "_") 2055 if i < 0 { 2056 continue 2057 } 2058 if prefix == "" { 2059 prefix = n.Name[:i+1] 2060 } else if prefix != n.Name[:i+1] { 2061 return "" 2062 } 2063 } 2064 } 2065 return prefix 2066 }