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