You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

751 regels
20 KiB

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