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.
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.
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>
34 // These will be paths to the appropriate source directories.
38 const TempDir = "/tmp"
39 const IncludeDir = TempDir + "/include" // To hold our C headers
40 const BuildDir = TempDir + "/build" // To hold intermediate build files
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
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)
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{
62 GNUArch: "i686-linux-gnu", // Note "i686" not "i386"
68 GNUArch: "x86_64-linux-gnu",
74 GNUArch: "aarch64-linux-gnu",
81 GNUArch: "arm-linux-gnueabi",
87 GNUArch: "mips-linux-gnu",
94 GNUArch: "mipsel-linux-gnu",
100 GNUArch: "mips64-linux-gnuabi64",
107 GNUArch: "mips64el-linux-gnuabi64",
112 LinuxArch: "powerpc",
113 GNUArch: "powerpc64-linux-gnu",
119 LinuxArch: "powerpc",
120 GNUArch: "powerpc64le-linux-gnu",
126 GNUArch: "riscv64-linux-gnu",
132 GNUArch: "s390x-linux-gnu",
140 GNUArch: "sparc64-linux-gnu",
146 // ptracePairs is a list of pairs of targets that can, in some cases,
147 // run each other's binaries. 'archName' is the combined name of 'a1'
148 // and 'a2', which is used in the file name. Generally we use an 'x'
149 // suffix in the file name to indicate that the file works for both
150 // big-endian and little-endian, here we use 'nn' to indicate that this
151 // file is suitable for 32-bit and 64-bit.
152 var ptracePairs = []struct{ a1, a2, archName string }{
153 {"386", "amd64", "x86"},
154 {"arm", "arm64", "armnn"},
155 {"mips", "mips64", "mipsnn"},
156 {"mipsle", "mips64le", "mipsnnle"},
160 if runtime.GOOS != GOOS || runtime.GOARCH != BuildArch {
161 fmt.Printf("Build system has GOOS_GOARCH = %s_%s, need %s_%s\n",
162 runtime.GOOS, runtime.GOARCH, GOOS, BuildArch)
166 // Check that we are using the new build system if we should
167 if os.Getenv("GOLANG_SYS_BUILD") != "docker" {
168 fmt.Println("In the new build system, mkall.go should not be called directly.")
169 fmt.Println("See README.md")
173 // Parse the command line options
174 if len(os.Args) != 3 {
175 fmt.Println("USAGE: go run linux/mkall.go <linux_dir> <glibc_dir>")
178 LinuxDir = os.Args[1]
179 GlibcDir = os.Args[2]
181 for _, t := range targets {
182 fmt.Printf("----- GENERATING: %s -----\n", t.GoArch)
183 if err := t.generateFiles(); err != nil {
184 fmt.Printf("%v\n***** FAILURE: %s *****\n\n", err, t.GoArch)
186 fmt.Printf("----- SUCCESS: %s -----\n\n", t.GoArch)
190 fmt.Printf("----- GENERATING: merging generated files -----\n")
191 if err := mergeFiles(); err != nil {
192 fmt.Printf("%v\n***** FAILURE: merging generated files *****\n\n", err)
194 fmt.Printf("----- SUCCESS: merging generated files -----\n\n")
197 fmt.Printf("----- GENERATING ptrace pairs -----\n")
199 for _, p := range ptracePairs {
200 if err := generatePtracePair(p.a1, p.a2, p.archName); err != nil {
201 fmt.Printf("%v\n***** FAILURE: %s/%s *****\n\n", err, p.a1, p.a2)
205 // generate functions PtraceGetRegSetArm64 and PtraceSetRegSetArm64.
206 if err := generatePtraceRegSet("arm64"); err != nil {
207 fmt.Printf("%v\n***** FAILURE: generatePtraceRegSet(%q) *****\n\n", err, "arm64")
211 fmt.Printf("----- SUCCESS ptrace pairs -----\n\n")
215 // Makes an exec.Cmd with Stderr attached to os.Stderr
216 func makeCommand(name string, args ...string) *exec.Cmd {
217 cmd := exec.Command(name, args...)
218 cmd.Stderr = os.Stderr
222 // Set GOARCH for target and build environments.
223 func (t *target) setTargetBuildArch(cmd *exec.Cmd) {
224 // Set GOARCH_TARGET so command knows what GOARCH is..
225 cmd.Env = append(os.Environ(), "GOARCH_TARGET="+t.GoArch)
226 // Set GOARCH to host arch for command, so it can run natively.
227 for i, s := range cmd.Env {
228 if strings.HasPrefix(s, "GOARCH=") {
229 cmd.Env[i] = "GOARCH=" + BuildArch
234 // Runs the command, pipes output to a formatter, pipes that to an output file.
235 func (t *target) commandFormatOutput(formatter string, outputFile string,
236 name string, args ...string) (err error) {
237 mainCmd := makeCommand(name, args...)
238 if name == "mksyscall" {
239 args = append([]string{"run", "mksyscall.go"}, args...)
240 mainCmd = makeCommand("go", args...)
241 t.setTargetBuildArch(mainCmd)
242 } else if name == "mksysnum" {
243 args = append([]string{"run", "linux/mksysnum.go"}, args...)
244 mainCmd = makeCommand("go", args...)
245 t.setTargetBuildArch(mainCmd)
248 fmtCmd := makeCommand(formatter)
249 if formatter == "mkpost" {
250 fmtCmd = makeCommand("go", "run", "mkpost.go")
251 t.setTargetBuildArch(fmtCmd)
254 // mainCmd | fmtCmd > outputFile
255 if fmtCmd.Stdin, err = mainCmd.StdoutPipe(); err != nil {
258 if fmtCmd.Stdout, err = os.Create(outputFile); err != nil {
262 // Make sure the formatter eventually closes
263 if err = fmtCmd.Start(); err != nil {
267 fmtErr := fmtCmd.Wait()
276 // Generates all the files for a Linux target
277 func (t *target) generateFiles() error {
278 // Setup environment variables
279 os.Setenv("GOOS", GOOS)
280 os.Setenv("GOARCH", t.GoArch)
282 // Get appropriate compiler and emulator (unless on x86)
283 if t.LinuxArch != "x86" {
284 // Check/Setup cross compiler
285 compiler := t.GNUArch + "-gcc"
286 if _, err := exec.LookPath(compiler); err != nil {
289 os.Setenv("CC", compiler)
291 // Check/Setup emulator (usually first component of GNUArch)
292 qemuArchName := t.GNUArch[:strings.Index(t.GNUArch, "-")]
293 if t.LinuxArch == "powerpc" {
294 qemuArchName = t.GoArch
296 // Fake uname for QEMU to allow running on Host kernel version < 4.15
297 if t.LinuxArch == "riscv" {
298 os.Setenv("QEMU_UNAME", "4.15")
300 os.Setenv("GORUN", "qemu-"+qemuArchName)
302 os.Setenv("CC", "gcc")
305 // Make the include directory and fill it with headers
306 if err := os.MkdirAll(IncludeDir, os.ModePerm); err != nil {
309 defer os.RemoveAll(IncludeDir)
310 if err := t.makeHeaders(); err != nil {
311 return fmt.Errorf("could not make header files: %v", err)
313 fmt.Println("header files generated")
315 // Make each of the four files
316 if err := t.makeZSysnumFile(); err != nil {
317 return fmt.Errorf("could not make zsysnum file: %v", err)
319 fmt.Println("zsysnum file generated")
321 if err := t.makeZSyscallFile(); err != nil {
322 return fmt.Errorf("could not make zsyscall file: %v", err)
324 fmt.Println("zsyscall file generated")
326 if err := t.makeZTypesFile(); err != nil {
327 return fmt.Errorf("could not make ztypes file: %v", err)
329 fmt.Println("ztypes file generated")
331 if err := t.makeZErrorsFile(); err != nil {
332 return fmt.Errorf("could not make zerrors file: %v", err)
334 fmt.Println("zerrors file generated")
339 // Create the Linux, glibc and ABI (C compiler convention) headers in the include directory.
340 func (t *target) makeHeaders() error {
341 // Make the Linux headers we need for this architecture
342 linuxMake := makeCommand("make", "headers_install", "ARCH="+t.LinuxArch, "INSTALL_HDR_PATH="+TempDir)
343 linuxMake.Dir = LinuxDir
344 if err := linuxMake.Run(); err != nil {
348 // A Temporary build directory for glibc
349 if err := os.MkdirAll(BuildDir, os.ModePerm); err != nil {
352 defer os.RemoveAll(BuildDir)
354 // Make the glibc headers we need for this architecture
355 confScript := filepath.Join(GlibcDir, "configure")
356 glibcConf := makeCommand(confScript, "--prefix="+TempDir, "--host="+t.GNUArch, "--enable-kernel="+MinKernel)
357 glibcConf.Dir = BuildDir
358 if err := glibcConf.Run(); err != nil {
361 glibcMake := makeCommand("make", "install-headers")
362 glibcMake.Dir = BuildDir
363 if err := glibcMake.Run(); err != nil {
366 // We only need an empty stubs file
367 stubsFile := filepath.Join(IncludeDir, "gnu/stubs.h")
368 if file, err := os.Create(stubsFile); err != nil {
374 // ABI headers will specify C compiler behavior for the target platform.
375 return t.makeABIHeaders()
378 // makeABIHeaders generates C header files based on the platform's calling convention.
379 // While many platforms have formal Application Binary Interfaces, in practice, whatever the
380 // dominant C compilers generate is the de-facto calling convention.
382 // We generate C headers instead of a Go file, so as to enable references to the ABI from Cgo.
383 func (t *target) makeABIHeaders() (err error) {
384 abiDir := filepath.Join(IncludeDir, "abi")
385 if err = os.Mkdir(abiDir, os.ModePerm); err != nil {
389 cc := os.Getenv("CC")
391 return errors.New("CC (compiler) env var not set")
394 // Build a sacrificial ELF file, to mine for C compiler behavior.
395 binPath := filepath.Join(TempDir, "tmp_abi.o")
396 bin, err := t.buildELF(cc, cCode, binPath)
398 return fmt.Errorf("cannot build ELF to analyze: %v", err)
401 defer os.Remove(binPath)
403 // Right now, we put everything in abi.h, but we may change this later.
404 abiFile, err := os.Create(filepath.Join(abiDir, "abi.h"))
409 if cerr := abiFile.Close(); cerr != nil && err == nil {
414 if err = t.writeBitFieldMasks(bin, abiFile); err != nil {
415 return fmt.Errorf("cannot write bitfield masks: %v", err)
421 func (t *target) buildELF(cc, src, path string) (*elf.File, error) {
422 // Compile the cCode source using the set compiler - we will need its .data section.
423 // Do not link the binary, so that we can find .data section offsets from the symbol values.
424 ccCmd := makeCommand(cc, "-o", path, "-gdwarf", "-x", "c", "-c", "-")
425 ccCmd.Stdin = strings.NewReader(src)
426 ccCmd.Stdout = os.Stdout
427 if err := ccCmd.Run(); err != nil {
428 return nil, fmt.Errorf("compiler error: %v", err)
431 bin, err := elf.Open(path)
433 return nil, fmt.Errorf("cannot read ELF file %s: %v", path, err)
439 func (t *target) writeBitFieldMasks(bin *elf.File, out io.Writer) error {
440 symbols, err := bin.Symbols()
442 return fmt.Errorf("getting ELF symbols: %v", err)
444 var masksSym *elf.Symbol
446 for _, sym := range symbols {
447 if sym.Name == "masks" {
453 return errors.New("could not find the 'masks' symbol in ELF symtab")
456 dataSection := bin.Section(".data")
457 if dataSection == nil {
458 return errors.New("ELF file has no .data section")
461 data, err := dataSection.Data()
463 return fmt.Errorf("could not read .data section: %v\n", err)
466 var bo binary.ByteOrder
468 bo = binary.BigEndian
470 bo = binary.LittleEndian
473 // 64 bit masks of type uint64 are stored in the data section starting at masks.Value.
474 // Here we are running on AMD64, but these values may be big endian or little endian,
475 // depending on target architecture.
476 for i := uint64(0); i < 64; i++ {
477 off := masksSym.Value + i*8
478 // Define each mask in native by order, so as to match target endian.
479 fmt.Fprintf(out, "#define BITFIELD_MASK_%d %dULL\n", i, bo.Uint64(data[off:off+8]))
485 // makes the zsysnum_linux_$GOARCH.go file
486 func (t *target) makeZSysnumFile() error {
487 zsysnumFile := fmt.Sprintf("zsysnum_linux_%s.go", t.GoArch)
488 unistdFile := filepath.Join(IncludeDir, "asm/unistd.h")
490 args := append(t.cFlags(), unistdFile)
491 return t.commandFormatOutput("gofmt", zsysnumFile, "mksysnum", args...)
494 // makes the zsyscall_linux_$GOARCH.go file
495 func (t *target) makeZSyscallFile() error {
496 zsyscallFile := fmt.Sprintf("zsyscall_linux_%s.go", t.GoArch)
497 // Find the correct architecture syscall file (might end with x.go)
498 archSyscallFile := fmt.Sprintf("syscall_linux_%s.go", t.GoArch)
499 if _, err := os.Stat(archSyscallFile); os.IsNotExist(err) {
500 shortArch := strings.TrimSuffix(t.GoArch, "le")
501 archSyscallFile = fmt.Sprintf("syscall_linux_%sx.go", shortArch)
504 args := append(t.mksyscallFlags(), "-tags", "linux,"+t.GoArch,
505 "syscall_linux.go", archSyscallFile)
506 return t.commandFormatOutput("gofmt", zsyscallFile, "mksyscall", args...)
509 // makes the zerrors_linux_$GOARCH.go file
510 func (t *target) makeZErrorsFile() error {
511 zerrorsFile := fmt.Sprintf("zerrors_linux_%s.go", t.GoArch)
513 return t.commandFormatOutput("gofmt", zerrorsFile, "./mkerrors.sh", t.cFlags()...)
516 // makes the ztypes_linux_$GOARCH.go file
517 func (t *target) makeZTypesFile() error {
518 ztypesFile := fmt.Sprintf("ztypes_linux_%s.go", t.GoArch)
520 args := []string{"tool", "cgo", "-godefs", "--"}
521 args = append(args, t.cFlags()...)
522 args = append(args, "linux/types.go")
523 return t.commandFormatOutput("mkpost", ztypesFile, "go", args...)
526 // Flags that should be given to gcc and cgo for this target
527 func (t *target) cFlags() []string {
528 // Compile statically to avoid cross-architecture dynamic linking.
529 flags := []string{"-Wall", "-Werror", "-static", "-I" + IncludeDir}
531 // Architecture-specific flags
533 flags = append(flags, "-fsigned-char")
535 if t.LinuxArch == "x86" {
536 flags = append(flags, fmt.Sprintf("-m%d", t.Bits))
542 // Flags that should be given to mksyscall for this target
543 func (t *target) mksyscallFlags() (flags []string) {
546 flags = append(flags, "-b32")
548 flags = append(flags, "-l32")
552 // This flag means a 64-bit value should use (even, odd)-pair.
553 if t.GoArch == "arm" || (t.LinuxArch == "mips" && t.Bits == 32) {
554 flags = append(flags, "-arm")
559 // Merge all the generated files for Linux targets
560 func mergeFiles() error {
561 // Setup environment variables
562 os.Setenv("GOOS", runtime.GOOS)
563 os.Setenv("GOARCH", runtime.GOARCH)
565 // Merge each of the four type of files
566 for _, ztyp := range []string{"zerrors", "zsyscall", "zsysnum", "ztypes"} {
567 cmd := makeCommand("go", "run", "mkmerge.go", "-out", fmt.Sprintf("%s_%s.go", ztyp, GOOS), fmt.Sprintf("%s_%s_*.go", ztyp, GOOS))
570 return fmt.Errorf("could not merge %s files: %w", ztyp, err)
572 fmt.Printf("%s files merged\n", ztyp)
578 // generatePtracePair takes a pair of GOARCH values that can run each
579 // other's binaries, such as 386 and amd64. It extracts the PtraceRegs
580 // type for each one. It writes a new file defining the types
581 // PtraceRegsArch1 and PtraceRegsArch2 and the corresponding functions
582 // Ptrace{Get,Set}Regs{arch1,arch2}. This permits debugging the other
583 // binary on a native system. 'archName' is the combined name of 'arch1'
584 // and 'arch2', which is used in the file name.
585 func generatePtracePair(arch1, arch2, archName string) error {
586 def1, err := ptraceDef(arch1)
590 def2, err := ptraceDef(arch2)
594 f, err := os.Create(fmt.Sprintf("zptrace_%s_linux.go", archName))
598 buf := bufio.NewWriter(f)
599 fmt.Fprintf(buf, "// Code generated by linux/mkall.go generatePtracePair(%q, %q). DO NOT EDIT.\n", arch1, arch2)
600 fmt.Fprintf(buf, "\n")
601 fmt.Fprintf(buf, "// +build linux\n")
602 fmt.Fprintf(buf, "// +build %s %s\n", arch1, arch2)
603 fmt.Fprintf(buf, "\n")
604 fmt.Fprintf(buf, "package unix\n")
605 fmt.Fprintf(buf, "\n")
606 fmt.Fprintf(buf, "%s\n", `import "unsafe"`)
607 fmt.Fprintf(buf, "\n")
608 writeOnePtrace(buf, arch1, def1)
609 fmt.Fprintf(buf, "\n")
610 writeOnePtrace(buf, arch2, def2)
611 if err := buf.Flush(); err != nil {
614 if err := f.Close(); err != nil {
620 // generatePtraceRegSet takes a GOARCH value to generate a file zptrace_linux_{arch}.go
621 // containing functions PtraceGetRegSet{arch} and PtraceSetRegSet{arch}.
622 func generatePtraceRegSet(arch string) error {
623 f, err := os.Create(fmt.Sprintf("zptrace_linux_%s.go", arch))
627 buf := bufio.NewWriter(f)
628 fmt.Fprintf(buf, "// Code generated by linux/mkall.go generatePtraceRegSet(%q). DO NOT EDIT.\n", arch)
629 fmt.Fprintf(buf, "\n")
630 fmt.Fprintf(buf, "package unix\n")
631 fmt.Fprintf(buf, "\n")
632 fmt.Fprintf(buf, "%s\n", `import "unsafe"`)
633 fmt.Fprintf(buf, "\n")
634 uarch := string(unicode.ToUpper(rune(arch[0]))) + arch[1:]
635 fmt.Fprintf(buf, "// PtraceGetRegSet%s fetches the registers used by %s binaries.\n", uarch, arch)
636 fmt.Fprintf(buf, "func PtraceGetRegSet%s(pid, addr int, regsout *PtraceRegs%s) error {\n", uarch, uarch)
637 fmt.Fprintf(buf, "\tiovec := Iovec{(*byte)(unsafe.Pointer(regsout)), uint64(unsafe.Sizeof(*regsout))}\n")
638 fmt.Fprintf(buf, "\treturn ptrace(PTRACE_GETREGSET, pid, uintptr(addr), uintptr(unsafe.Pointer(&iovec)))\n")
639 fmt.Fprintf(buf, "}\n")
640 fmt.Fprintf(buf, "\n")
641 fmt.Fprintf(buf, "// PtraceSetRegSet%s sets the registers used by %s binaries.\n", uarch, arch)
642 fmt.Fprintf(buf, "func PtraceSetRegSet%s(pid, addr int, regs *PtraceRegs%s) error {\n", uarch, uarch)
643 fmt.Fprintf(buf, "\tiovec := Iovec{(*byte)(unsafe.Pointer(regs)), uint64(unsafe.Sizeof(*regs))}\n")
644 fmt.Fprintf(buf, "\treturn ptrace(PTRACE_SETREGSET, pid, uintptr(addr), uintptr(unsafe.Pointer(&iovec)))\n")
645 fmt.Fprintf(buf, "}\n")
646 if err := buf.Flush(); err != nil {
649 if err := f.Close(); err != nil {
655 // ptraceDef returns the definition of PtraceRegs for arch.
656 func ptraceDef(arch string) (string, error) {
657 filename := fmt.Sprintf("ztypes_linux_%s.go", arch)
658 data, err := ioutil.ReadFile(filename)
660 return "", fmt.Errorf("reading %s: %v", filename, err)
662 start := bytes.Index(data, []byte("type PtraceRegs struct"))
664 return "", fmt.Errorf("%s: no definition of PtraceRegs", filename)
667 end := bytes.Index(data, []byte("\n}\n"))
669 return "", fmt.Errorf("%s: can't find end of PtraceRegs definition", filename)
671 return string(data[:end+2]), nil
674 // writeOnePtrace writes out the ptrace definitions for arch.
675 func writeOnePtrace(w io.Writer, arch, def string) {
676 uarch := string(unicode.ToUpper(rune(arch[0]))) + arch[1:]
677 fmt.Fprintf(w, "// PtraceRegs%s is the registers used by %s binaries.\n", uarch, arch)
678 fmt.Fprintf(w, "%s\n", strings.Replace(def, "PtraceRegs", "PtraceRegs"+uarch, 1))
680 fmt.Fprintf(w, "// PtraceGetRegs%s fetches the registers used by %s binaries.\n", uarch, arch)
681 fmt.Fprintf(w, "func PtraceGetRegs%s(pid int, regsout *PtraceRegs%s) error {\n", uarch, uarch)
682 fmt.Fprintf(w, "\treturn ptrace(PTRACE_GETREGS, pid, 0, uintptr(unsafe.Pointer(regsout)))\n")
683 fmt.Fprintf(w, "}\n")
685 fmt.Fprintf(w, "// PtraceSetRegs%s sets the registers used by %s binaries.\n", uarch, arch)
686 fmt.Fprintf(w, "func PtraceSetRegs%s(pid int, regs *PtraceRegs%s) error {\n", uarch, uarch)
687 fmt.Fprintf(w, "\treturn ptrace(PTRACE_SETREGS, pid, 0, uintptr(unsafe.Pointer(regs)))\n")
688 fmt.Fprintf(w, "}\n")
691 // cCode is compiled for the target architecture, and the resulting data section is carved for
692 // the statically initialized bit masks.
694 // Bit fields are used in some system calls and other ABIs, but their memory layout is
695 // implementation-defined [1]. Even with formal ABIs, bit fields are a source of subtle bugs [2].
696 // Here we generate the offsets for all 64 bits in an uint64.
697 // 1: http://en.cppreference.com/w/c/language/bit_field
698 // 2: https://lwn.net/Articles/478657/
706 uint64_t u64_bit_0 : 1;
707 uint64_t u64_bit_1 : 1;
708 uint64_t u64_bit_2 : 1;
709 uint64_t u64_bit_3 : 1;
710 uint64_t u64_bit_4 : 1;
711 uint64_t u64_bit_5 : 1;
712 uint64_t u64_bit_6 : 1;
713 uint64_t u64_bit_7 : 1;
714 uint64_t u64_bit_8 : 1;
715 uint64_t u64_bit_9 : 1;
716 uint64_t u64_bit_10 : 1;
717 uint64_t u64_bit_11 : 1;
718 uint64_t u64_bit_12 : 1;
719 uint64_t u64_bit_13 : 1;
720 uint64_t u64_bit_14 : 1;
721 uint64_t u64_bit_15 : 1;
722 uint64_t u64_bit_16 : 1;
723 uint64_t u64_bit_17 : 1;
724 uint64_t u64_bit_18 : 1;
725 uint64_t u64_bit_19 : 1;
726 uint64_t u64_bit_20 : 1;
727 uint64_t u64_bit_21 : 1;
728 uint64_t u64_bit_22 : 1;
729 uint64_t u64_bit_23 : 1;
730 uint64_t u64_bit_24 : 1;
731 uint64_t u64_bit_25 : 1;
732 uint64_t u64_bit_26 : 1;
733 uint64_t u64_bit_27 : 1;
734 uint64_t u64_bit_28 : 1;
735 uint64_t u64_bit_29 : 1;
736 uint64_t u64_bit_30 : 1;
737 uint64_t u64_bit_31 : 1;
738 uint64_t u64_bit_32 : 1;
739 uint64_t u64_bit_33 : 1;
740 uint64_t u64_bit_34 : 1;
741 uint64_t u64_bit_35 : 1;
742 uint64_t u64_bit_36 : 1;
743 uint64_t u64_bit_37 : 1;
744 uint64_t u64_bit_38 : 1;
745 uint64_t u64_bit_39 : 1;
746 uint64_t u64_bit_40 : 1;
747 uint64_t u64_bit_41 : 1;
748 uint64_t u64_bit_42 : 1;
749 uint64_t u64_bit_43 : 1;
750 uint64_t u64_bit_44 : 1;
751 uint64_t u64_bit_45 : 1;
752 uint64_t u64_bit_46 : 1;
753 uint64_t u64_bit_47 : 1;
754 uint64_t u64_bit_48 : 1;
755 uint64_t u64_bit_49 : 1;
756 uint64_t u64_bit_50 : 1;
757 uint64_t u64_bit_51 : 1;
758 uint64_t u64_bit_52 : 1;
759 uint64_t u64_bit_53 : 1;
760 uint64_t u64_bit_54 : 1;
761 uint64_t u64_bit_55 : 1;
762 uint64_t u64_bit_56 : 1;
763 uint64_t u64_bit_57 : 1;
764 uint64_t u64_bit_58 : 1;
765 uint64_t u64_bit_59 : 1;
766 uint64_t u64_bit_60 : 1;
767 uint64_t u64_bit_61 : 1;
768 uint64_t u64_bit_62 : 1;
769 uint64_t u64_bit_63 : 1;
774 struct bitfield masks[] = {
841 int main(int argc, char **argv) {
842 struct bitfield *mask_ptr = &masks[0];
843 return mask_ptr->val;