gitee.com/johng/gf@v1.4.7/third/golang.org/x/sys/unix/linux/mkall.go (about) 1 // Copyright 2017 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 // linux/mkall.go - Generates all Linux zsysnum, zsyscall, zerror, and ztype 6 // files for all 11 linux architectures supported by the go compiler. See 7 // README.md for more information about the build system. 8 9 // To run it you must have a git checkout of the Linux kernel and glibc. Once 10 // the appropriate sources are ready, the program is run as: 11 // go run linux/mkall.go <linux_dir> <glibc_dir> 12 13 // +build ignore 14 15 package main 16 17 import ( 18 "bufio" 19 "bytes" 20 "debug/elf" 21 "encoding/binary" 22 "errors" 23 "fmt" 24 "io" 25 "io/ioutil" 26 "os" 27 "os/exec" 28 "path/filepath" 29 "runtime" 30 "strings" 31 "unicode" 32 ) 33 34 // These will be paths to the appropriate source directories. 35 var LinuxDir string 36 var GlibcDir string 37 38 const TempDir = "/tmp" 39 const IncludeDir = TempDir + "/include" // To hold our C headers 40 const BuildDir = TempDir + "/build" // To hold intermediate build files 41 42 const GOOS = "linux" // Only for Linux targets 43 const BuildArch = "amd64" // Must be built on this architecture 44 const MinKernel = "2.6.23" // https://golang.org/doc/install#requirements 45 46 type target struct { 47 GoArch string // Architecture name according to Go 48 LinuxArch string // Architecture name according to the Linux Kernel 49 GNUArch string // Architecture name according to GNU tools (https://wiki.debian.org/Multiarch/Tuples) 50 BigEndian bool // Default Little Endian 51 SignedChar bool // Is -fsigned-char needed (default no) 52 Bits int 53 } 54 55 // List of the 11 Linux targets supported by the go compiler. sparc64 is not 56 // currently supported, though a port is in progress. 57 var targets = []target{ 58 { 59 GoArch: "386", 60 LinuxArch: "x86", 61 GNUArch: "i686-linux-gnu", // Note "i686" not "i386" 62 Bits: 32, 63 }, 64 { 65 GoArch: "amd64", 66 LinuxArch: "x86", 67 GNUArch: "x86_64-linux-gnu", 68 Bits: 64, 69 }, 70 { 71 GoArch: "arm64", 72 LinuxArch: "arm64", 73 GNUArch: "aarch64-linux-gnu", 74 SignedChar: true, 75 Bits: 64, 76 }, 77 { 78 GoArch: "arm", 79 LinuxArch: "arm", 80 GNUArch: "arm-linux-gnueabi", 81 Bits: 32, 82 }, 83 { 84 GoArch: "mips", 85 LinuxArch: "mips", 86 GNUArch: "mips-linux-gnu", 87 BigEndian: true, 88 Bits: 32, 89 }, 90 { 91 GoArch: "mipsle", 92 LinuxArch: "mips", 93 GNUArch: "mipsel-linux-gnu", 94 Bits: 32, 95 }, 96 { 97 GoArch: "mips64", 98 LinuxArch: "mips", 99 GNUArch: "mips64-linux-gnuabi64", 100 BigEndian: true, 101 Bits: 64, 102 }, 103 { 104 GoArch: "mips64le", 105 LinuxArch: "mips", 106 GNUArch: "mips64el-linux-gnuabi64", 107 Bits: 64, 108 }, 109 { 110 GoArch: "ppc64", 111 LinuxArch: "powerpc", 112 GNUArch: "powerpc64-linux-gnu", 113 BigEndian: true, 114 Bits: 64, 115 }, 116 { 117 GoArch: "ppc64le", 118 LinuxArch: "powerpc", 119 GNUArch: "powerpc64le-linux-gnu", 120 Bits: 64, 121 }, 122 { 123 GoArch: "s390x", 124 LinuxArch: "s390", 125 GNUArch: "s390x-linux-gnu", 126 BigEndian: true, 127 SignedChar: true, 128 Bits: 64, 129 }, 130 // { 131 // GoArch: "sparc64", 132 // LinuxArch: "sparc", 133 // GNUArch: "sparc64-linux-gnu", 134 // BigEndian: true, 135 // Bits: 64, 136 // }, 137 } 138 139 // ptracePairs is a list of pairs of targets that can, in some cases, 140 // run each other's binaries. 141 var ptracePairs = []struct{ a1, a2 string }{ 142 {"386", "amd64"}, 143 {"arm", "arm64"}, 144 {"mips", "mips64"}, 145 {"mipsle", "mips64le"}, 146 } 147 148 func main() { 149 if runtime.GOOS != GOOS || runtime.GOARCH != BuildArch { 150 fmt.Printf("Build system has GOOS_GOARCH = %s_%s, need %s_%s\n", 151 runtime.GOOS, runtime.GOARCH, GOOS, BuildArch) 152 return 153 } 154 155 // Check that we are using the new build system if we should 156 if os.Getenv("GOLANG_SYS_BUILD") != "docker" { 157 fmt.Println("In the new build system, mkall.go should not be called directly.") 158 fmt.Println("See README.md") 159 return 160 } 161 162 // Parse the command line options 163 if len(os.Args) != 3 { 164 fmt.Println("USAGE: go run linux/mkall.go <linux_dir> <glibc_dir>") 165 return 166 } 167 LinuxDir = os.Args[1] 168 GlibcDir = os.Args[2] 169 170 for _, t := range targets { 171 fmt.Printf("----- GENERATING: %s -----\n", t.GoArch) 172 if err := t.generateFiles(); err != nil { 173 fmt.Printf("%v\n***** FAILURE: %s *****\n\n", err, t.GoArch) 174 } else { 175 fmt.Printf("----- SUCCESS: %s -----\n\n", t.GoArch) 176 } 177 } 178 179 fmt.Printf("----- GENERATING ptrace pairs -----\n") 180 ok := true 181 for _, p := range ptracePairs { 182 if err := generatePtracePair(p.a1, p.a2); err != nil { 183 fmt.Printf("%v\n***** FAILURE: %s/%s *****\n\n", err, p.a1, p.a2) 184 ok = false 185 } 186 } 187 if ok { 188 fmt.Printf("----- SUCCESS ptrace pairs -----\n\n") 189 } 190 } 191 192 // Makes an exec.Cmd with Stderr attached to os.Stderr 193 func makeCommand(name string, args ...string) *exec.Cmd { 194 cmd := exec.Command(name, args...) 195 cmd.Stderr = os.Stderr 196 return cmd 197 } 198 199 // Runs the command, pipes output to a formatter, pipes that to an output file. 200 func (t *target) commandFormatOutput(formatter string, outputFile string, 201 name string, args ...string) (err error) { 202 mainCmd := makeCommand(name, args...) 203 204 fmtCmd := makeCommand(formatter) 205 if formatter == "mkpost" { 206 fmtCmd = makeCommand("go", "run", "mkpost.go") 207 // Set GOARCH_TARGET so mkpost knows what GOARCH is.. 208 fmtCmd.Env = append(os.Environ(), "GOARCH_TARGET="+t.GoArch) 209 // Set GOARCH to host arch for mkpost, so it can run natively. 210 for i, s := range fmtCmd.Env { 211 if strings.HasPrefix(s, "GOARCH=") { 212 fmtCmd.Env[i] = "GOARCH=" + BuildArch 213 } 214 } 215 } 216 217 // mainCmd | fmtCmd > outputFile 218 if fmtCmd.Stdin, err = mainCmd.StdoutPipe(); err != nil { 219 return 220 } 221 if fmtCmd.Stdout, err = os.Create(outputFile); err != nil { 222 return 223 } 224 225 // Make sure the formatter eventually closes 226 if err = fmtCmd.Start(); err != nil { 227 return 228 } 229 defer func() { 230 fmtErr := fmtCmd.Wait() 231 if err == nil { 232 err = fmtErr 233 } 234 }() 235 236 return mainCmd.Run() 237 } 238 239 // Generates all the files for a Linux target 240 func (t *target) generateFiles() error { 241 // Setup environment variables 242 os.Setenv("GOOS", GOOS) 243 os.Setenv("GOARCH", t.GoArch) 244 245 // Get appropriate compiler and emulator (unless on x86) 246 if t.LinuxArch != "x86" { 247 // Check/Setup cross compiler 248 compiler := t.GNUArch + "-gcc" 249 if _, err := exec.LookPath(compiler); err != nil { 250 return err 251 } 252 os.Setenv("CC", compiler) 253 254 // Check/Setup emulator (usually first component of GNUArch) 255 qemuArchName := t.GNUArch[:strings.Index(t.GNUArch, "-")] 256 if t.LinuxArch == "powerpc" { 257 qemuArchName = t.GoArch 258 } 259 os.Setenv("GORUN", "qemu-"+qemuArchName) 260 } else { 261 os.Setenv("CC", "gcc") 262 } 263 264 // Make the include directory and fill it with headers 265 if err := os.MkdirAll(IncludeDir, os.ModePerm); err != nil { 266 return err 267 } 268 defer os.RemoveAll(IncludeDir) 269 if err := t.makeHeaders(); err != nil { 270 return fmt.Errorf("could not make header files: %v", err) 271 } 272 fmt.Println("header files generated") 273 274 // Make each of the four files 275 if err := t.makeZSysnumFile(); err != nil { 276 return fmt.Errorf("could not make zsysnum file: %v", err) 277 } 278 fmt.Println("zsysnum file generated") 279 280 if err := t.makeZSyscallFile(); err != nil { 281 return fmt.Errorf("could not make zsyscall file: %v", err) 282 } 283 fmt.Println("zsyscall file generated") 284 285 if err := t.makeZTypesFile(); err != nil { 286 return fmt.Errorf("could not make ztypes file: %v", err) 287 } 288 fmt.Println("ztypes file generated") 289 290 if err := t.makeZErrorsFile(); err != nil { 291 return fmt.Errorf("could not make zerrors file: %v", err) 292 } 293 fmt.Println("zerrors file generated") 294 295 return nil 296 } 297 298 // Create the Linux, glibc and ABI (C compiler convention) headers in the include directory. 299 func (t *target) makeHeaders() error { 300 // Make the Linux headers we need for this architecture 301 linuxMake := makeCommand("make", "headers_install", "ARCH="+t.LinuxArch, "INSTALL_HDR_PATH="+TempDir) 302 linuxMake.Dir = LinuxDir 303 if err := linuxMake.Run(); err != nil { 304 return err 305 } 306 307 // A Temporary build directory for glibc 308 if err := os.MkdirAll(BuildDir, os.ModePerm); err != nil { 309 return err 310 } 311 defer os.RemoveAll(BuildDir) 312 313 // Make the glibc headers we need for this architecture 314 confScript := filepath.Join(GlibcDir, "configure") 315 glibcConf := makeCommand(confScript, "--prefix="+TempDir, "--host="+t.GNUArch, "--enable-kernel="+MinKernel) 316 glibcConf.Dir = BuildDir 317 if err := glibcConf.Run(); err != nil { 318 return err 319 } 320 glibcMake := makeCommand("make", "install-headers") 321 glibcMake.Dir = BuildDir 322 if err := glibcMake.Run(); err != nil { 323 return err 324 } 325 // We only need an empty stubs file 326 stubsFile := filepath.Join(IncludeDir, "gnu/stubs.h") 327 if file, err := os.Create(stubsFile); err != nil { 328 return err 329 } else { 330 file.Close() 331 } 332 333 // ABI headers will specify C compiler behavior for the target platform. 334 return t.makeABIHeaders() 335 } 336 337 // makeABIHeaders generates C header files based on the platform's calling convention. 338 // While many platforms have formal Application Binary Interfaces, in practice, whatever the 339 // dominant C compilers generate is the de-facto calling convention. 340 // 341 // We generate C headers instead of a Go file, so as to enable references to the ABI from Cgo. 342 func (t *target) makeABIHeaders() (err error) { 343 abiDir := filepath.Join(IncludeDir, "abi") 344 if err = os.Mkdir(abiDir, os.ModePerm); err != nil { 345 return err 346 } 347 348 cc := os.Getenv("CC") 349 if cc == "" { 350 return errors.New("CC (compiler) env var not set") 351 } 352 353 // Build a sacrificial ELF file, to mine for C compiler behavior. 354 binPath := filepath.Join(TempDir, "tmp_abi.o") 355 bin, err := t.buildELF(cc, cCode, binPath) 356 if err != nil { 357 return fmt.Errorf("cannot build ELF to analyze: %v", err) 358 } 359 defer bin.Close() 360 defer os.Remove(binPath) 361 362 // Right now, we put everything in abi.h, but we may change this later. 363 abiFile, err := os.Create(filepath.Join(abiDir, "abi.h")) 364 if err != nil { 365 return err 366 } 367 defer func() { 368 if cerr := abiFile.Close(); cerr != nil && err == nil { 369 err = cerr 370 } 371 }() 372 373 if err = t.writeBitFieldMasks(bin, abiFile); err != nil { 374 return fmt.Errorf("cannot write bitfield masks: %v", err) 375 } 376 377 return nil 378 } 379 380 func (t *target) buildELF(cc, src, path string) (*elf.File, error) { 381 // Compile the cCode source using the set compiler - we will need its .data section. 382 // Do not link the binary, so that we can find .data section offsets from the symbol values. 383 ccCmd := makeCommand(cc, "-o", path, "-gdwarf", "-x", "c", "-c", "-") 384 ccCmd.Stdin = strings.NewReader(src) 385 ccCmd.Stdout = os.Stdout 386 if err := ccCmd.Run(); err != nil { 387 return nil, fmt.Errorf("compiler error: %v", err) 388 } 389 390 bin, err := elf.Open(path) 391 if err != nil { 392 return nil, fmt.Errorf("cannot read ELF file %s: %v", path, err) 393 } 394 395 return bin, nil 396 } 397 398 func (t *target) writeBitFieldMasks(bin *elf.File, out io.Writer) error { 399 symbols, err := bin.Symbols() 400 if err != nil { 401 return fmt.Errorf("getting ELF symbols: %v", err) 402 } 403 var masksSym *elf.Symbol 404 405 for _, sym := range symbols { 406 if sym.Name == "masks" { 407 masksSym = &sym 408 } 409 } 410 411 if masksSym == nil { 412 return errors.New("could not find the 'masks' symbol in ELF symtab") 413 } 414 415 dataSection := bin.Section(".data") 416 if dataSection == nil { 417 return errors.New("ELF file has no .data section") 418 } 419 420 data, err := dataSection.Data() 421 if err != nil { 422 return fmt.Errorf("could not read .data section: %v\n", err) 423 } 424 425 var bo binary.ByteOrder 426 if t.BigEndian { 427 bo = binary.BigEndian 428 } else { 429 bo = binary.LittleEndian 430 } 431 432 // 64 bit masks of type uint64 are stored in the data section starting at masks.Value. 433 // Here we are running on AMD64, but these values may be big endian or little endian, 434 // depending on target architecture. 435 for i := uint64(0); i < 64; i++ { 436 off := masksSym.Value + i*8 437 // Define each mask in native by order, so as to match target endian. 438 fmt.Fprintf(out, "#define BITFIELD_MASK_%d %dULL\n", i, bo.Uint64(data[off:off+8])) 439 } 440 441 return nil 442 } 443 444 // makes the zsysnum_linux_$GOARCH.go file 445 func (t *target) makeZSysnumFile() error { 446 zsysnumFile := fmt.Sprintf("zsysnum_linux_%s.go", t.GoArch) 447 unistdFile := filepath.Join(IncludeDir, "asm/unistd.h") 448 449 args := append(t.cFlags(), unistdFile) 450 return t.commandFormatOutput("gofmt", zsysnumFile, "linux/mksysnum.pl", args...) 451 } 452 453 // makes the zsyscall_linux_$GOARCH.go file 454 func (t *target) makeZSyscallFile() error { 455 zsyscallFile := fmt.Sprintf("zsyscall_linux_%s.go", t.GoArch) 456 // Find the correct architecture syscall file (might end with x.go) 457 archSyscallFile := fmt.Sprintf("syscall_linux_%s.go", t.GoArch) 458 if _, err := os.Stat(archSyscallFile); os.IsNotExist(err) { 459 shortArch := strings.TrimSuffix(t.GoArch, "le") 460 archSyscallFile = fmt.Sprintf("syscall_linux_%sx.go", shortArch) 461 } 462 463 args := append(t.mksyscallFlags(), "-tags", "linux,"+t.GoArch, 464 "syscall_linux.go", archSyscallFile) 465 return t.commandFormatOutput("gofmt", zsyscallFile, "./mksyscall.pl", args...) 466 } 467 468 // makes the zerrors_linux_$GOARCH.go file 469 func (t *target) makeZErrorsFile() error { 470 zerrorsFile := fmt.Sprintf("zerrors_linux_%s.go", t.GoArch) 471 472 return t.commandFormatOutput("gofmt", zerrorsFile, "./mkerrors.sh", t.cFlags()...) 473 } 474 475 // makes the ztypes_linux_$GOARCH.go file 476 func (t *target) makeZTypesFile() error { 477 ztypesFile := fmt.Sprintf("ztypes_linux_%s.go", t.GoArch) 478 479 args := []string{"tool", "cgo", "-godefs", "--"} 480 args = append(args, t.cFlags()...) 481 args = append(args, "linux/types.go") 482 return t.commandFormatOutput("mkpost", ztypesFile, "go", args...) 483 } 484 485 // Flags that should be given to gcc and cgo for this target 486 func (t *target) cFlags() []string { 487 // Compile statically to avoid cross-architecture dynamic linking. 488 flags := []string{"-Wall", "-Werror", "-static", "-I" + IncludeDir} 489 490 // Architecture-specific flags 491 if t.SignedChar { 492 flags = append(flags, "-fsigned-char") 493 } 494 if t.LinuxArch == "x86" { 495 flags = append(flags, fmt.Sprintf("-m%d", t.Bits)) 496 } 497 498 return flags 499 } 500 501 // Flags that should be given to mksyscall for this target 502 func (t *target) mksyscallFlags() (flags []string) { 503 if t.Bits == 32 { 504 if t.BigEndian { 505 flags = append(flags, "-b32") 506 } else { 507 flags = append(flags, "-l32") 508 } 509 } 510 511 // This flag menas a 64-bit value should use (even, odd)-pair. 512 if t.GoArch == "arm" || (t.LinuxArch == "mips" && t.Bits == 32) { 513 flags = append(flags, "-arm") 514 } 515 return 516 } 517 518 // generatePtracePair takes a pair of GOARCH values that can run each 519 // other's binaries, such as 386 and amd64. It extracts the PtraceRegs 520 // type for each one. It writes a new file defining the types 521 // PtraceRegsArch1 and PtraceRegsArch2 and the corresponding functions 522 // Ptrace{Get,Set}Regs{arch1,arch2}. This permits debugging the other 523 // binary on a native system. 524 func generatePtracePair(arch1, arch2 string) error { 525 def1, err := ptraceDef(arch1) 526 if err != nil { 527 return err 528 } 529 def2, err := ptraceDef(arch2) 530 if err != nil { 531 return err 532 } 533 f, err := os.Create(fmt.Sprintf("zptrace%s_linux.go", arch1)) 534 if err != nil { 535 return err 536 } 537 buf := bufio.NewWriter(f) 538 fmt.Fprintf(buf, "// Code generated by linux/mkall.go generatePtracePair(%s, %s). DO NOT EDIT.\n", arch1, arch2) 539 fmt.Fprintf(buf, "\n") 540 fmt.Fprintf(buf, "// +build linux\n") 541 fmt.Fprintf(buf, "// +build %s %s\n", arch1, arch2) 542 fmt.Fprintf(buf, "\n") 543 fmt.Fprintf(buf, "package unix\n") 544 fmt.Fprintf(buf, "\n") 545 fmt.Fprintf(buf, "%s\n", `import "unsafe"`) 546 fmt.Fprintf(buf, "\n") 547 writeOnePtrace(buf, arch1, def1) 548 fmt.Fprintf(buf, "\n") 549 writeOnePtrace(buf, arch2, def2) 550 if err := buf.Flush(); err != nil { 551 return err 552 } 553 if err := f.Close(); err != nil { 554 return err 555 } 556 return nil 557 } 558 559 // ptraceDef returns the definition of PtraceRegs for arch. 560 func ptraceDef(arch string) (string, error) { 561 filename := fmt.Sprintf("ztypes_linux_%s.go", arch) 562 data, err := ioutil.ReadFile(filename) 563 if err != nil { 564 return "", fmt.Errorf("reading %s: %v", filename, err) 565 } 566 start := bytes.Index(data, []byte("type PtraceRegs struct")) 567 if start < 0 { 568 return "", fmt.Errorf("%s: no definition of PtraceRegs", filename) 569 } 570 data = data[start:] 571 end := bytes.Index(data, []byte("\n}\n")) 572 if end < 0 { 573 return "", fmt.Errorf("%s: can't find end of PtraceRegs definition", filename) 574 } 575 return string(data[:end+2]), nil 576 } 577 578 // writeOnePtrace writes out the ptrace definitions for arch. 579 func writeOnePtrace(w io.Writer, arch, def string) { 580 uarch := string(unicode.ToUpper(rune(arch[0]))) + arch[1:] 581 fmt.Fprintf(w, "// PtraceRegs%s is the registers used by %s binaries.\n", uarch, arch) 582 fmt.Fprintf(w, "%s\n", strings.Replace(def, "PtraceRegs", "PtraceRegs"+uarch, 1)) 583 fmt.Fprintf(w, "\n") 584 fmt.Fprintf(w, "// PtraceGetRegs%s fetches the registers used by %s binaries.\n", uarch, arch) 585 fmt.Fprintf(w, "func PtraceGetRegs%s(pid int, regsout *PtraceRegs%s) error {\n", uarch, uarch) 586 fmt.Fprintf(w, "\treturn ptrace(PTRACE_GETREGS, pid, 0, uintptr(unsafe.Pointer(regsout)))\n") 587 fmt.Fprintf(w, "}\n") 588 fmt.Fprintf(w, "\n") 589 fmt.Fprintf(w, "// PtraceSetRegs%s sets the registers used by %s binaries.\n", uarch, arch) 590 fmt.Fprintf(w, "func PtraceSetRegs%s(pid int, regs *PtraceRegs%s) error {\n", uarch, uarch) 591 fmt.Fprintf(w, "\treturn ptrace(PTRACE_SETREGS, pid, 0, uintptr(unsafe.Pointer(regs)))\n") 592 fmt.Fprintf(w, "}\n") 593 } 594 595 // cCode is compiled for the target architecture, and the resulting data section is carved for 596 // the statically initialized bit masks. 597 const cCode = ` 598 // Bit fields are used in some system calls and other ABIs, but their memory layout is 599 // implementation-defined [1]. Even with formal ABIs, bit fields are a source of subtle bugs [2]. 600 // Here we generate the offsets for all 64 bits in an uint64. 601 // 1: http://en.cppreference.com/w/c/language/bit_field 602 // 2: https://lwn.net/Articles/478657/ 603 604 #include <stdint.h> 605 606 struct bitfield { 607 union { 608 uint64_t val; 609 struct { 610 uint64_t u64_bit_0 : 1; 611 uint64_t u64_bit_1 : 1; 612 uint64_t u64_bit_2 : 1; 613 uint64_t u64_bit_3 : 1; 614 uint64_t u64_bit_4 : 1; 615 uint64_t u64_bit_5 : 1; 616 uint64_t u64_bit_6 : 1; 617 uint64_t u64_bit_7 : 1; 618 uint64_t u64_bit_8 : 1; 619 uint64_t u64_bit_9 : 1; 620 uint64_t u64_bit_10 : 1; 621 uint64_t u64_bit_11 : 1; 622 uint64_t u64_bit_12 : 1; 623 uint64_t u64_bit_13 : 1; 624 uint64_t u64_bit_14 : 1; 625 uint64_t u64_bit_15 : 1; 626 uint64_t u64_bit_16 : 1; 627 uint64_t u64_bit_17 : 1; 628 uint64_t u64_bit_18 : 1; 629 uint64_t u64_bit_19 : 1; 630 uint64_t u64_bit_20 : 1; 631 uint64_t u64_bit_21 : 1; 632 uint64_t u64_bit_22 : 1; 633 uint64_t u64_bit_23 : 1; 634 uint64_t u64_bit_24 : 1; 635 uint64_t u64_bit_25 : 1; 636 uint64_t u64_bit_26 : 1; 637 uint64_t u64_bit_27 : 1; 638 uint64_t u64_bit_28 : 1; 639 uint64_t u64_bit_29 : 1; 640 uint64_t u64_bit_30 : 1; 641 uint64_t u64_bit_31 : 1; 642 uint64_t u64_bit_32 : 1; 643 uint64_t u64_bit_33 : 1; 644 uint64_t u64_bit_34 : 1; 645 uint64_t u64_bit_35 : 1; 646 uint64_t u64_bit_36 : 1; 647 uint64_t u64_bit_37 : 1; 648 uint64_t u64_bit_38 : 1; 649 uint64_t u64_bit_39 : 1; 650 uint64_t u64_bit_40 : 1; 651 uint64_t u64_bit_41 : 1; 652 uint64_t u64_bit_42 : 1; 653 uint64_t u64_bit_43 : 1; 654 uint64_t u64_bit_44 : 1; 655 uint64_t u64_bit_45 : 1; 656 uint64_t u64_bit_46 : 1; 657 uint64_t u64_bit_47 : 1; 658 uint64_t u64_bit_48 : 1; 659 uint64_t u64_bit_49 : 1; 660 uint64_t u64_bit_50 : 1; 661 uint64_t u64_bit_51 : 1; 662 uint64_t u64_bit_52 : 1; 663 uint64_t u64_bit_53 : 1; 664 uint64_t u64_bit_54 : 1; 665 uint64_t u64_bit_55 : 1; 666 uint64_t u64_bit_56 : 1; 667 uint64_t u64_bit_57 : 1; 668 uint64_t u64_bit_58 : 1; 669 uint64_t u64_bit_59 : 1; 670 uint64_t u64_bit_60 : 1; 671 uint64_t u64_bit_61 : 1; 672 uint64_t u64_bit_62 : 1; 673 uint64_t u64_bit_63 : 1; 674 }; 675 }; 676 }; 677 678 struct bitfield masks[] = { 679 {.u64_bit_0 = 1}, 680 {.u64_bit_1 = 1}, 681 {.u64_bit_2 = 1}, 682 {.u64_bit_3 = 1}, 683 {.u64_bit_4 = 1}, 684 {.u64_bit_5 = 1}, 685 {.u64_bit_6 = 1}, 686 {.u64_bit_7 = 1}, 687 {.u64_bit_8 = 1}, 688 {.u64_bit_9 = 1}, 689 {.u64_bit_10 = 1}, 690 {.u64_bit_11 = 1}, 691 {.u64_bit_12 = 1}, 692 {.u64_bit_13 = 1}, 693 {.u64_bit_14 = 1}, 694 {.u64_bit_15 = 1}, 695 {.u64_bit_16 = 1}, 696 {.u64_bit_17 = 1}, 697 {.u64_bit_18 = 1}, 698 {.u64_bit_19 = 1}, 699 {.u64_bit_20 = 1}, 700 {.u64_bit_21 = 1}, 701 {.u64_bit_22 = 1}, 702 {.u64_bit_23 = 1}, 703 {.u64_bit_24 = 1}, 704 {.u64_bit_25 = 1}, 705 {.u64_bit_26 = 1}, 706 {.u64_bit_27 = 1}, 707 {.u64_bit_28 = 1}, 708 {.u64_bit_29 = 1}, 709 {.u64_bit_30 = 1}, 710 {.u64_bit_31 = 1}, 711 {.u64_bit_32 = 1}, 712 {.u64_bit_33 = 1}, 713 {.u64_bit_34 = 1}, 714 {.u64_bit_35 = 1}, 715 {.u64_bit_36 = 1}, 716 {.u64_bit_37 = 1}, 717 {.u64_bit_38 = 1}, 718 {.u64_bit_39 = 1}, 719 {.u64_bit_40 = 1}, 720 {.u64_bit_41 = 1}, 721 {.u64_bit_42 = 1}, 722 {.u64_bit_43 = 1}, 723 {.u64_bit_44 = 1}, 724 {.u64_bit_45 = 1}, 725 {.u64_bit_46 = 1}, 726 {.u64_bit_47 = 1}, 727 {.u64_bit_48 = 1}, 728 {.u64_bit_49 = 1}, 729 {.u64_bit_50 = 1}, 730 {.u64_bit_51 = 1}, 731 {.u64_bit_52 = 1}, 732 {.u64_bit_53 = 1}, 733 {.u64_bit_54 = 1}, 734 {.u64_bit_55 = 1}, 735 {.u64_bit_56 = 1}, 736 {.u64_bit_57 = 1}, 737 {.u64_bit_58 = 1}, 738 {.u64_bit_59 = 1}, 739 {.u64_bit_60 = 1}, 740 {.u64_bit_61 = 1}, 741 {.u64_bit_62 = 1}, 742 {.u64_bit_63 = 1} 743 }; 744 745 int main(int argc, char **argv) { 746 struct bitfield *mask_ptr = &masks[0]; 747 return mask_ptr->val; 748 } 749 750 `