Merge tag 'go1.12.5' into HEAD
Change-Id: I7fe9cd66c8b2c196054e81e3a8c07de36fd76839
diff --git a/BUILD.gn b/BUILD.gn
new file mode 100644
index 0000000..21cd2a7
--- /dev/null
+++ b/BUILD.gn
@@ -0,0 +1,166 @@
+# Copyright 2016 The Fuchsia Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//build/config/clang/clang.gni")
+import("//build/config/sysroot.gni")
+import("//build/fidl/fidl.gni")
+import("//build/go/go_test.gni")
+import("//build/host.gni")
+import("//build/package.gni")
+import("//build/test/test_package.gni")
+
+if (current_toolchain == target_toolchain) {
+ _go_root = "$host_tools_dir/goroot"
+ _bootstrap_goroot = "//buildtools/${host_platform}/go"
+
+ action("makeroot") {
+ visibility = [ ":makefuchsia" ]
+
+ inputs = [
+ "makeroot.go",
+ ]
+
+ depfile = "$target_gen_dir/$target_name.d"
+ outputs = [
+ "$target_gen_dir/$target_name.stamp",
+ ]
+
+ script = rebase_path(_bootstrap_goroot + "/bin/go")
+ args = [
+ "run",
+ rebase_path("makeroot.go", root_build_dir),
+ "-source-goroot",
+ rebase_path(".", root_build_dir),
+ "-target-goroot",
+ rebase_path(_go_root, root_build_dir),
+
+ "-depfile",
+ rebase_path(depfile, root_build_dir),
+ "-depfile-root",
+ rebase_path(root_build_dir),
+ "-stamp-file",
+ rebase_path(outputs[0], root_build_dir),
+ ]
+ }
+
+ action("makefuchsia") {
+ visibility = [ ":go_runtime" ]
+ deps = [
+ ":makeroot",
+ ]
+
+ depfile = "$target_gen_dir/$target_name.d"
+ outputs = [
+ "$target_gen_dir/$target_name.stamp",
+ ]
+
+ script = rebase_path(_bootstrap_goroot + "/bin/go")
+ args = [
+ "run",
+ rebase_path("makefuchsia.go", root_build_dir),
+ "-bootstrap-goroot",
+ rebase_path(_bootstrap_goroot),
+ "-goroot",
+ rebase_path(_go_root, root_build_dir),
+
+ "-depfile",
+ rebase_path(depfile, root_build_dir),
+ "-depfile-root",
+ rebase_path(root_build_dir),
+ "-stamp-file",
+ rebase_path(outputs[0], root_build_dir),
+ ]
+ }
+}
+
+group("go_runtime") {
+ public_deps = [
+ ":makefuchsia(${target_toolchain})",
+ ]
+}
+
+go_test("go_dispatch_test") {
+ gopackage = "syscall/zx/dispatch"
+}
+
+go_test("go_fidl_test") {
+ gopackage = "syscall/zx/fidl"
+}
+
+go_test("go_extended_fidl_test") {
+ # N.B. these tests are not in the fidl package to avoid having to rebuild the
+ # go toolchain while iterating on them.
+ gopackage = "syscall/zx/fidl/fidl_test"
+ # TODO(pascallouis): Currently, while we take a dependency, the output of
+ # this FIDL rule is not directly used, rather the generated bindings were
+ # copied and checked in.
+ #
+ # Not being able to depend on automated generation is due to where code is
+ # placed, and how this relates to the tree structure of the toolchain.
+ # Disabling while fidlgen table generation is pending.
+ #deps = [
+ # "src/syscall/zx/fidl/bindingstest($go_toolchain)",
+ #]
+}
+
+go_test("go_zxwait_test") {
+ gopackage = "syscall/zx/zxwait"
+}
+
+go_test("go_os_test") {
+ gopackage = "os"
+}
+
+go_test("go_net_test") {
+ gopackage = "net"
+}
+
+go_test("go_pprof_test") {
+ gopackage = "runtime/pprof"
+ skip_vet = true
+}
+
+test_package("go_stdlib_tests") {
+ deps = [
+ ":go_dispatch_test",
+ ":go_net_test",
+ ":go_os_test",
+ ":go_pprof_test",
+ ":go_zxwait_test",
+ ]
+
+ tests = [
+ {
+ name = "go_dispatch_test"
+ },
+ {
+ name = "go_net_test"
+ },
+ {
+ name = "go_os_test"
+ },
+ {
+ name = "go_pprof_test"
+ },
+ {
+ name = "go_zxwait_test"
+ },
+ ]
+}
+
+unittest_package("go_fidl_tests") {
+ deps = [
+ ":go_extended_fidl_test",
+ ":go_fidl_test",
+ ]
+
+ tests = [
+ {
+ name = "go_fidl_test"
+ },
+ {
+ name = "go_extended_fidl_test"
+ },
+ ]
+}
diff --git a/VERSION b/VERSION
index ad3e3c3..47fe908 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-go1.12.5
\ No newline at end of file
+go1.12.5
diff --git a/makefuchsia.go b/makefuchsia.go
new file mode 100644
index 0000000..941fb11
--- /dev/null
+++ b/makefuchsia.go
@@ -0,0 +1,94 @@
+// Copyright 2017 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// The makefuchsia.go script builds a GOROOT in the out/ build directory
+// using sources from third_party/go.
+package main
+
+import (
+ "bytes"
+ "flag"
+ "fmt"
+ "io/ioutil"
+ "log"
+ "os"
+ "os/exec"
+ "path/filepath"
+ "strings"
+ "time"
+)
+
+var (
+ flagBootstrapGoroot = flag.String("bootstrap-goroot", "", "Path to go root used for bootstrap")
+ flagGoroot = flag.String("goroot", "", "Path to the output GOROOT")
+
+ flagDepfilePath = flag.String("depfile", "", "depfile to write into")
+ flagDepfileTarget = flag.String("depfile-target", "", "depfile `make` target")
+ flagDepfileRoot = flag.String("depfile-root", "", "Path from which dependency paths should be rooted")
+
+ flagStampPath = flag.String("stamp-file", "", "Path of a file to create upon completion")
+)
+
+func join(path ...string) string { return filepath.Join(path...) }
+
+func main() {
+ log.SetFlags(0)
+ log.SetPrefix("makefuchsia.go: ")
+ flag.Parse()
+
+ versionFile := join(*flagGoroot, "VERSION")
+ origVersion, err := ioutil.ReadFile(versionFile)
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ // Do not repeat the updating of the VERSION file if it was previously performed.
+ if bytes.Index(origVersion, []byte("fuchsia")) == -1 {
+ if err := ioutil.WriteFile(versionFile, []byte(fmt.Sprintf("devel(%s) third_party/go fuchsia", bytes.TrimSpace(origVersion))), os.ModePerm); err != nil {
+ log.Fatal(err)
+ }
+ }
+
+ env := os.Environ()
+ if *flagBootstrapGoroot == "" {
+ log.Fatal("-bootstrap-goroot is required")
+ }
+ env = append(env, "GOROOT_BOOTSTRAP="+strings.TrimSpace(*flagBootstrapGoroot))
+
+ abs, err := filepath.Abs(join(*flagGoroot, "src", "make.bash"))
+ if err != nil {
+ log.Fatal(err)
+ }
+ cmd := exec.Command(abs, "--no-clean")
+ cmd.Dir = join(*flagGoroot, "src")
+ cmd.Env = env
+ buf := new(bytes.Buffer)
+ cmd.Stdout = buf
+ cmd.Stderr = buf
+ if err := cmd.Run(); err != nil {
+ log.Fatalf("make.bash failed: %v\n%s", err, buf.String())
+ }
+
+ depfile, err := os.Create(*flagDepfilePath)
+ if err != nil {
+ log.Fatal(err)
+ }
+ fmt.Fprintf(depfile, "%s:", *flagStampPath)
+
+ if err := filepath.Walk(*flagGoroot, func(path string, info os.FileInfo, err error) error {
+ if err != nil || info.IsDir() {
+ return err
+ }
+ fmt.Fprintf(depfile, " %s", path)
+ return err
+ }); err != nil {
+ log.Fatal(err)
+ }
+
+ fmt.Fprint(depfile, "\n")
+
+ if err := ioutil.WriteFile(*flagStampPath, []byte(fmt.Sprintf("%s", time.Now())), os.ModePerm); err != nil {
+ log.Fatal(err)
+ }
+}
diff --git a/makeroot.go b/makeroot.go
new file mode 100644
index 0000000..6e8562b
--- /dev/null
+++ b/makeroot.go
@@ -0,0 +1,153 @@
+// Copyright 2018 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// The makeroot.go script copies a GOROOT. It is a precursor to makefuchsia.go,
+// used to stage a clean GOROOT into the build directory.
+// Note: this script exists because the `go` tool globs for inputs, as such, a
+// copy tool is required that will actively remove files that are not found in
+// the source.
+
+package main
+
+import (
+ "bytes"
+ "flag"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "log"
+ "os"
+ "path/filepath"
+ "strings"
+ "time"
+)
+
+var (
+ sourceGoroot = flag.String("source-goroot", "", "GOROOT to copy from")
+ targetGoroot = flag.String("target-goroot", "", "GOROOT to copy into")
+ depfilePath = flag.String("depfile", "", "depfile to write into")
+ depfileRoot = flag.String("depfile-root", "", "Path from which dependency paths should be rooted")
+ stampPath = flag.String("stamp-file", "", "Path of a file to create upon completion")
+)
+
+func mkdir(path ...string) {
+ if err := os.MkdirAll(join(path...), 0755); err != nil {
+ log.Fatal(err)
+ }
+}
+
+func join(path ...string) string { return filepath.Join(path...) }
+
+func copyfile(src, dst string) {
+ srcfile, err := os.Open(src)
+ if err != nil {
+ log.Fatal(err)
+ }
+ defer srcfile.Close()
+
+ fi, err := srcfile.Stat()
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ mkdir(filepath.Dir(dst))
+ f, err := os.OpenFile(dst, os.O_CREATE|os.O_RDWR|os.O_TRUNC, fi.Mode())
+ if err != nil {
+ log.Fatal(err)
+ }
+ if _, err := io.Copy(f, srcfile); err != nil {
+ log.Fatalf("cp %s %s: %v", src, dst, err)
+ }
+ if err := f.Close(); err != nil {
+ log.Fatalf("cp %s %s: close: %v", src, dst, err)
+ }
+}
+
+// allFilesIn recursively walks a set of files, returning the entire tree in
+// paths relative to the given root. A map is returned for convenience. If
+// prefix is given, only files that match the prefix are considered.
+func allFilesIn(root string, paths map[string]struct{}, prefix ...string) error {
+ return filepath.Walk(root, func(path string, info os.FileInfo, err error) error {
+ if err != nil || info.IsDir() {
+ return err
+ }
+ for _, pfx := range prefix {
+ if strings.HasPrefix(path, join(root, pfx)) {
+ relPath := strings.TrimPrefix(path, root)[1:]
+ paths[relPath] = struct{}{}
+ return err
+ }
+ }
+ return err
+ })
+}
+
+func main() {
+ log.SetFlags(0)
+ log.SetPrefix("makeroot.go: ")
+ flag.Parse()
+
+ srcFiles := map[string]struct{}{}
+
+ // The list of files included below should include everything that Go itself
+ // cares about. It used to avoid containing some of the "extraneous" files such
+ // as doc/ and test/, however, eliding those files results in `go doc -http`
+ // not presenting well for the user, so it's simply better to include
+ // everything.
+ err := allFilesIn(join(*sourceGoroot), srcFiles,
+ "AUTHORS",
+ "CONTRIBUTING.md",
+ "CONTRIBUTORS",
+ "LICENSE",
+ "PATENTS",
+ "README.md",
+ "VERSION",
+ "makefuchsia.go",
+ "api/",
+ "doc/",
+ "favicon.ico",
+ "lib/",
+ "misc/",
+ "robots.txt",
+ "src/",
+ "test/",
+ )
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ dstFiles := map[string]struct{}{}
+ if _, err := os.Stat(join(*targetGoroot)); err == nil {
+ if err := allFilesIn(join(*targetGoroot), dstFiles, ""); err != nil {
+ log.Fatal(err)
+ }
+ }
+
+ for f := range dstFiles {
+ if _, ok := srcFiles[f]; !ok {
+ // try to preserve the bin/ and pkg/ trees, as they can be used to do faster
+ // rebuilds of the toolchain.
+ if strings.HasPrefix(f, "src/") || strings.HasPrefix(f, "misc/fuchsia/") {
+ os.Remove(filepath.Join(*targetGoroot, f))
+ }
+ }
+ }
+
+ buf := bytes.NewBuffer(nil)
+ fmt.Fprintf(buf, "%s:", *stampPath)
+ for f := range srcFiles {
+ src, dst := join(*sourceGoroot, f), join(*targetGoroot, f)
+ copyfile(src, dst)
+ fmt.Fprintf(buf, " %s", src)
+ }
+ fmt.Fprintf(buf, "\n")
+
+ if err := ioutil.WriteFile(*depfilePath, buf.Bytes(), os.ModePerm); err != nil {
+ log.Fatal(err)
+ }
+
+ if err := ioutil.WriteFile(*stampPath, []byte(fmt.Sprintf("%s", time.Now())), os.ModePerm); err != nil {
+ log.Fatal(err)
+ }
+}
diff --git a/meta/go_dispatch_test.cmx b/meta/go_dispatch_test.cmx
new file mode 100644
index 0000000..2d81275
--- /dev/null
+++ b/meta/go_dispatch_test.cmx
@@ -0,0 +1,5 @@
+{
+ "program": {
+ "binary": "test/go_dispatch_test"
+ }
+}
diff --git a/meta/go_net_test.cmx b/meta/go_net_test.cmx
new file mode 100644
index 0000000..1b30e49
--- /dev/null
+++ b/meta/go_net_test.cmx
@@ -0,0 +1,23 @@
+{
+ "facets": {
+ "fuchsia.test": {
+ "system-services": [
+ "fuchsia.net.Connectivity",
+ "fuchsia.net.SocketProvider",
+ "fuchsia.net.stack.Stack",
+ "fuchsia.netstack.Netstack"
+ ]
+ }
+ },
+ "program": {
+ "binary": "test/go_net_test"
+ },
+ "sandbox": {
+ "features": [
+ "system-temp"
+ ],
+ "services": [
+ "fuchsia.net.SocketProvider"
+ ]
+ }
+}
diff --git a/meta/go_os_test.cmx b/meta/go_os_test.cmx
new file mode 100644
index 0000000..67c425d
--- /dev/null
+++ b/meta/go_os_test.cmx
@@ -0,0 +1,20 @@
+{
+ "program": {
+ "binary": "test/go_os_test"
+ },
+ "sandbox": {
+ "boot": [
+ "bin",
+ "lib"
+ ],
+ "dev": [
+ "null"
+ ],
+ "features": [
+ "system-temp"
+ ],
+ "services": [
+ "fuchsia.process.Launcher"
+ ]
+ }
+}
diff --git a/meta/go_pprof_test.cmx b/meta/go_pprof_test.cmx
new file mode 100644
index 0000000..1fd3938
--- /dev/null
+++ b/meta/go_pprof_test.cmx
@@ -0,0 +1,13 @@
+{
+ "program": {
+ "binary": "test/go_pprof_test"
+ },
+ "sandbox": {
+ "features": [
+ "system-temp"
+ ],
+ "services": [
+ "fuchsia.process.Launcher"
+ ]
+ }
+}
diff --git a/meta/go_zxwait_test.cmx b/meta/go_zxwait_test.cmx
new file mode 100644
index 0000000..b9d4400
--- /dev/null
+++ b/meta/go_zxwait_test.cmx
@@ -0,0 +1,5 @@
+{
+ "program": {
+ "binary": "test/go_zxwait_test"
+ }
+}
diff --git a/misc/fuchsia/README.md b/misc/fuchsia/README.md
new file mode 100644
index 0000000..e26e84b
--- /dev/null
+++ b/misc/fuchsia/README.md
@@ -0,0 +1,47 @@
+Go on Fuchsia
+=========
+
+To build a toolchain on Linux for Fuchsia, first follow the
+instructions on
+
+ https://fuchsia.googlesource.com/manifest/
+
+Then,
+* Set the SDK environment variable to the location of the Fuchsia SDK:
+ If you downloaded fuchsia to your ${HOME} directory:
+ ```
+ export SDK=${HOME}/fuchsia/buildtools
+ ```
+
+* Identify where a host version of go exists, with:
+ ```
+ export GOROOT_BOOTSTRAP=`path to directory containing go`
+ ```
+ On my machine, `which go` returned /usr/lib/golang/bin/go, so I set
+ GOROOT_BOOTSTRAP=/usr/lib/golang/
+
+* Build Go in `fuchsia/third_party/go/src` using
+ ```
+ GOOS=fuchsia CC_FOR_TARGET=../misc/fuchsia/clangwrap.sh ./make.bash
+ ```
+
+* To build a program, junk.go in go/src, use:
+ ```
+ GOOS=fuchsia ../bin/go build junk.go
+ ```
+ This program can be put in a bootfs and run on qemu with:
+ ```
+ echo bin/junk=junk > junk.manifest
+ fuchsia/buildtools/mkbootfs -o junk.bootfs junk.manifest
+ ./scripts/run-zircon-x64 -x path/to/fuchsia/third_party/go/src/junk.bootfs
+ ```
+ A cgo variant can be build by adding CGO_ENABLED=1 to both
+ the make.bash command and the go build command.
+
+* To build a program using just the zircon prebuild toolchain
+ (useful for debugging if the fuchsia sysroot is out of sync
+ with your zircon) set the environment variable ZIRCON to
+ the location of your zircon and build with the gccwrap.sh
+ script:
+ ```
+ ZIRCON=$HOME/zircon CGO_ENABLED=1 CC_FOR_TARGET=$(pwd)/../misc/fuchsia/gccwrap.sh GOOS=fuchsia ./make.bash
diff --git a/misc/fuchsia/clangwrap.sh b/misc/fuchsia/clangwrap.sh
new file mode 100755
index 0000000..e0122c6
--- /dev/null
+++ b/misc/fuchsia/clangwrap.sh
@@ -0,0 +1,30 @@
+#!/bin/bash
+set -eu
+
+clangbin="clang"
+if [[ -n "${CLANG_PREFIX}" ]]; then
+ clangbin="${CLANG_PREFIX}/${clangbin}"
+fi
+
+if [[ "${GOOS}" != "fuchsia" ]]; then
+ exec "${clangbin}" "$@"
+fi
+
+case "${GOARCH}" in
+arm64)
+ CLANG_TRIPLE="aarch64-fuchsia";;
+amd64)
+ CLANG_TRIPLE="x86_64-fuchsia";;
+*)
+ echo >&2 "Unsupported architecture: ${GOARCH}"
+ exit 1;;
+esac
+
+extra_args=()
+# -Qunused-arguments is used to avoid issues with intermediate builds that don't directly link fdio.
+extra_args+=(-Qunused-arguments)
+extra_args+=(--sysroot="${ZIRCON_SYSROOT}")
+extra_args+=(-I"${FDIO_INCLUDE}")
+extra_args+=(-L"${FUCHSIA_SHARED_LIBS}")
+
+exec "${clangbin}" --target="${CLANG_TRIPLE}" "${extra_args[@]}" "$@"
diff --git a/misc/fuchsia/gccwrap.sh b/misc/fuchsia/gccwrap.sh
new file mode 100755
index 0000000..93c86cd
--- /dev/null
+++ b/misc/fuchsia/gccwrap.sh
@@ -0,0 +1,66 @@
+#!/bin/bash
+# This uses the zircon prebuild C++ toolchain
+
+if [ -z "${ZIRCON}" ]; then
+ echo "gccwrap.sh: missing ZIRCON env variable" >&2
+ exit 1
+fi
+
+zirconsysroot="${ZIRCON_SYSROOT}"
+if [ -z "${zirconsysroot}" ]; then
+ echo "gccwrap.sh: missing ZIRCON_SYSROOT env variable" >&2
+ exit 1
+fi
+
+if [ -z "${FUCHSIA_ROOT_OUT_DIR}" ]; then
+ echo "gccwrap.sh: missing FUCHSIA_ROOT_OUT_DIR env variable" >&2
+ exit 1
+fi
+
+if [ "$GOARCH" == "amd64" ]; then
+ libdir="x64-shared"
+ gccbin="$ZIRCON/prebuilt/downloads/gcc/bin/x86_64-elf-gcc"
+elif [ "$GOARCH" == "arm64" ]; then
+ libdir="arm64-shared"
+ gccbin="$ZIRCON/prebuilt/downloads/gcc/bin/aarch64-elf-gcc"
+else
+ echo "gccwrap.sh: unsupported GOARCH: $GOARCH" >&2
+ exit 1
+fi
+
+compiler=false
+extra_args=""
+
+for var in "$@"
+do
+ if [[ "$var" == "-r" || "$var" == "-c" ]]; then
+ compiler=true
+ fi
+done
+
+if ! $compiler; then
+ extra_args="-lc $zirconsysroot/lib/Scrt1.o $zirconsysroot/lib/libzircon.so -lfdio"
+fi
+
+exec $gccbin \
+ --sysroot=$zirconsysroot \
+ -I$zirconsysroot/include \
+ -I${ZIRCON}/system/ulib/fdio/include \
+ -L$zirconsysroot/lib \
+ -L${FUCHSIA_ROOT_OUT_DIR}/${libdir} \
+ -nostdlib \
+ -fuse-ld=gold \
+ -fno-use-linker-plugin \
+ -Wl,-nostdlib \
+ -Wl,--build-id \
+ -Wl,-z,max-page-size=4096 \
+ -Wl,-z,combreloc \
+ -Wl,-z,relro \
+ -Wl,-z,now \
+ -Wl,-z,text \
+ -Wl,-z,noexecstack \
+ -Wl,--hash-style=gnu \
+ -Wl,--eh-frame-hdr \
+ -Wl,-dynamic-linker=ld.so.1 \
+ $extra_args \
+ "$@"
diff --git a/misc/fuchsia/go_stdlib_tests.json b/misc/fuchsia/go_stdlib_tests.json
new file mode 100644
index 0000000..e52c708
--- /dev/null
+++ b/misc/fuchsia/go_stdlib_tests.json
@@ -0,0 +1,8 @@
+{
+ "tests":[
+ {
+ "name":"go_os_test",
+ "exec":"/system/bin/report_result /system/test/go_os_test"
+ }
+ ]
+}
diff --git a/regen-fidl b/regen-fidl
new file mode 100755
index 0000000..041b0e1
--- /dev/null
+++ b/regen-fidl
@@ -0,0 +1,71 @@
+#!/usr/bin/env bash
+
+# TODO(pascallouis): better automate this.
+
+set -euxo pipefail
+
+if [[ ! -d "${FUCHSIA_DIR}" ]]; then
+ echo "FUCHSIA_DIR environment variable not a directory"
+ exit 1
+fi
+
+pushd $FUCHSIA_DIR
+
+./scripts/fx build garnet/go/src/fidl
+
+tmpout=$(mktemp -d 2>/dev/null || mktemp -d -t 'tmpout')
+ir_file="${tmpout}/out.json"
+
+trap 'rm -rf -- "${tmpout}" && popd > /dev/null' EXIT
+
+# Parameters:
+# $1 = directory where fidl file is found.
+# $2 = output of subdirectory of syscall/zx
+# $3..n = additional fidl dependencies needed to generate this target.
+function generate_file {
+ local source_dir=$1
+ shift
+ local package_dir=$1
+ shift
+ local additional_files=""
+ while (( "$#" )); do
+ additional_files+="--files $1"
+ shift
+ done
+ out_file=third_party/go/src/syscall/zx/"${package_dir}"/impl.go
+ copyright_line=$(grep -E "^// Copyright [0-9]+" "${out_file}" || \
+ echo "// Copyright $(date +%Y) The Fuchsia Authors. All rights reserved.")
+ ./out/default/host_x64/fidlc \
+ --json "${ir_file}" \
+ ${additional_files} \
+ --files "${source_dir}"/*.fidl
+ ./out/default/host_x64/fidlgen \
+ --json "${ir_file}" \
+ --generators go \
+ --include-base notused \
+ --output-base "${tmpout}"
+
+ tmpfile=$(mktemp ${tmpout}/tmp.XXXXXXXX)
+ echo "${copyright_line}" > "${tmpfile}"
+ cat << EOF >> "${tmpfile}"
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// GENERATED FILE: Do not edit!
+//
+// To rebuild this file, invoke third_party/go/regen-fidl.
+
+// +build fuchsia
+EOF
+ cat "${tmpout}"/impl.go >> "${tmpfile}"
+ perl -pi -e 's|^// WARNING: This file is machine generated by fidlgen.\n$||' "${tmpfile}"
+ perl -pi -e 's|fidl/fuchsia/mem|syscall/zx/mem|' "${tmpfile}"
+ ./out/default/tools/goroot/bin/gofmt -s -w "${tmpfile}"
+ mv -- "${tmpfile}" "${out_file}"
+}
+
+generate_file third_party/go/src/syscall/zx/fidl/bindingstest/ fidl/bindingstest
+generate_file zircon/system/fidl/fuchsia-net net
+generate_file zircon/system/fidl/fuchsia-mem mem
+generate_file zircon/system/fidl/fuchsia-io io \
+ zircon/system/fidl/fuchsia-mem/*.fidl
diff --git a/src/cmd/dist/build.go b/src/cmd/dist/build.go
index ad2c964..65f10e1 100644
--- a/src/cmd/dist/build.go
+++ b/src/cmd/dist/build.go
@@ -83,6 +83,7 @@
"android",
"solaris",
"freebsd",
+ "fuchsia",
"nacl",
"netbsd",
"openbsd",
@@ -1065,6 +1066,8 @@
xremoveall(pathf("%s/pkg/%s_%s", goroot, goos, goarch))
xremoveall(pathf("%s/pkg/%s_%s_race", goroot, gohostos, gohostarch))
xremoveall(pathf("%s/pkg/%s_%s_race", goroot, goos, goarch))
+ xremoveall(pathf("%s/pkg/%s_%s_shared", goroot, gohostos, gohostarch))
+ xremoveall(pathf("%s/pkg/%s_%s_shared", goroot, goos, goarch))
xremoveall(tooldir)
// Remove cached version info.
@@ -1422,6 +1425,8 @@
"freebsd/386": true,
"freebsd/amd64": true,
"freebsd/arm": false,
+ "fuchsia/amd64": true,
+ "fuchsia/arm64": true,
"linux/386": true,
"linux/amd64": true,
"linux/arm": true,
diff --git a/src/cmd/go/internal/base/signal_notunix.go b/src/cmd/go/internal/base/signal_notunix.go
index 9e869b0..a8e5a34 100644
--- a/src/cmd/go/internal/base/signal_notunix.go
+++ b/src/cmd/go/internal/base/signal_notunix.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build plan9 windows
+// +build plan9 fuchsia windows
package base
diff --git a/src/cmd/go/internal/load/pkg.go b/src/cmd/go/internal/load/pkg.go
index cb35d3c..3e056fe 100644
--- a/src/cmd/go/internal/load/pkg.go
+++ b/src/cmd/go/internal/load/pkg.go
@@ -1560,6 +1560,11 @@
// LinkerDeps returns the list of linker-induced dependencies for main package p.
func LinkerDeps(p *Package) []string {
+ // Don't add deps to Fuchsia internal syscall stuff.
+ if p != nil && p.ImportPath == "syscall/zx" {
+ return []string{}
+ }
+
// Everything links runtime.
deps := []string{"runtime"}
@@ -1588,7 +1593,7 @@
func externalLinkingForced(p *Package) bool {
// Some targets must use external linking even inside GOROOT.
switch cfg.BuildContext.GOOS {
- case "android":
+ case "android", "fuchsia":
return true
case "darwin":
switch cfg.BuildContext.GOARCH {
diff --git a/src/cmd/go/internal/work/exec.go b/src/cmd/go/internal/work/exec.go
index 0ab7976..af9565b 100644
--- a/src/cmd/go/internal/work/exec.go
+++ b/src/cmd/go/internal/work/exec.go
@@ -2253,6 +2253,7 @@
switch cfg.Goos {
case "windows":
a = append(a, "-mthreads")
+ case "fuchsia":
default:
a = append(a, "-pthread")
}
diff --git a/src/cmd/go/internal/work/gccgo.go b/src/cmd/go/internal/work/gccgo.go
index 69a25be..d4a4283 100644
--- a/src/cmd/go/internal/work/gccgo.go
+++ b/src/cmd/go/internal/work/gccgo.go
@@ -428,7 +428,12 @@
// split-stack and non-split-stack code in a single -r
// link, and libgo picks up non-split-stack code from
// libffi.
- ldflags = append(ldflags, "-Wl,-r", "-nostdlib", "-Wl,--whole-archive", "-lgolibbegin", "-Wl,--no-whole-archive")
+ if cfg.Goos == "fuchsia" {
+ ldflags = append(ldflags, "-r")
+ } else {
+ ldflags = append(ldflags, "-Wl,-r")
+ }
+ ldflags = append(ldflags, "-nostdlib", "-Wl,--whole-archive", "-lgolibbegin", "-Wl,--no-whole-archive")
if nopie := b.gccNoPie([]string{tools.linker()}); nopie != "" {
ldflags = append(ldflags, nopie)
diff --git a/src/cmd/go/internal/work/init.go b/src/cmd/go/internal/work/init.go
index 693a53e..6136c04 100644
--- a/src/cmd/go/internal/work/init.go
+++ b/src/cmd/go/internal/work/init.go
@@ -124,7 +124,8 @@
ldBuildmode = "c-shared"
case "default":
switch platform {
- case "android/arm", "android/arm64", "android/amd64", "android/386":
+ case "android/arm", "android/arm64", "android/amd64", "android/386",
+ "fuchsia/amd64", "fuchsia/arm64":
codegenArg = "-shared"
ldBuildmode = "pie"
case "darwin/arm", "darwin/arm64":
@@ -155,7 +156,8 @@
switch platform {
case "linux/386", "linux/amd64", "linux/arm", "linux/arm64", "linux/ppc64le", "linux/s390x",
"android/amd64", "android/arm", "android/arm64", "android/386",
- "freebsd/amd64":
+ "freebsd/amd64",
+ "fuchsia/amd64", "fuchsia/arm64":
codegenArg = "-shared"
case "darwin/amd64":
codegenArg = "-shared"
diff --git a/src/cmd/internal/obj/x86/asm6.go b/src/cmd/internal/obj/x86/asm6.go
index c3da29c..398dc47 100644
--- a/src/cmd/internal/obj/x86/asm6.go
+++ b/src/cmd/internal/obj/x86/asm6.go
@@ -2350,6 +2350,9 @@
return 0x64 // FS
}
+ case objabi.Hfuchsia:
+ log.Fatalf("unknown TLS base register, fuchsia requires PIC code")
+
case objabi.Hdragonfly,
objabi.Hfreebsd,
objabi.Hnetbsd,
@@ -4979,7 +4982,7 @@
default:
log.Fatalf("unknown TLS base location for %v", ctxt.Headtype)
- case objabi.Hlinux, objabi.Hfreebsd:
+ case objabi.Hlinux, objabi.Hfreebsd, objabi.Hfuchsia:
if !ctxt.Flag_shared {
log.Fatalf("unknown TLS base location for linux/freebsd without -shared")
}
diff --git a/src/cmd/internal/obj/x86/obj6.go b/src/cmd/internal/obj/x86/obj6.go
index babfd38..5bc2e81 100644
--- a/src/cmd/internal/obj/x86/obj6.go
+++ b/src/cmd/internal/obj/x86/obj6.go
@@ -67,6 +67,8 @@
return false
case objabi.Hlinux, objabi.Hfreebsd:
return !ctxt.Flag_shared
+ case objabi.Hfuchsia:
+ return false
}
return true
diff --git a/src/cmd/internal/objabi/head.go b/src/cmd/internal/objabi/head.go
index db2221d..366cabf 100644
--- a/src/cmd/internal/objabi/head.go
+++ b/src/cmd/internal/objabi/head.go
@@ -40,6 +40,7 @@
Hdarwin
Hdragonfly
Hfreebsd
+ Hfuchsia
Hjs
Hlinux
Hnacl
@@ -61,6 +62,8 @@
*h = Hdragonfly
case "freebsd":
*h = Hfreebsd
+ case "fuchsia":
+ *h = Hfuchsia
case "js":
*h = Hjs
case "linux", "android":
@@ -93,6 +96,8 @@
return "dragonfly"
case Hfreebsd:
return "freebsd"
+ case Hfuchsia:
+ return "fuchsia"
case Hjs:
return "js"
case Hlinux:
diff --git a/src/cmd/link/internal/amd64/asm.go b/src/cmd/link/internal/amd64/asm.go
index e922fe2..6cb0197 100644
--- a/src/cmd/link/internal/amd64/asm.go
+++ b/src/cmd/link/internal/amd64/asm.go
@@ -37,6 +37,7 @@
"cmd/link/internal/sym"
"debug/elf"
"log"
+ "strings"
)
func PADDR(x uint32) uint32 {
@@ -412,6 +413,8 @@
if r.Siz == 4 {
if r.Xsym.Type == sym.SDYNIMPORT && r.Xsym.ElfType() == elf.STT_FUNC {
ctxt.Out.Write64(uint64(elf.R_X86_64_PLT32) | uint64(elfsym)<<32)
+ } else if r.Xsym.Type == sym.SDYNIMPORT && ctxt.HeadType == objabi.Hfuchsia && strings.HasPrefix(r.Xsym.Name, "vdso_") {
+ ctxt.Out.Write64(uint64(elf.R_X86_64_GOTPCREL) | uint64(elfsym)<<32)
} else {
ctxt.Out.Write64(uint64(elf.R_X86_64_PC32) | uint64(elfsym)<<32)
}
@@ -721,6 +724,7 @@
case objabi.Hlinux,
objabi.Hfreebsd,
+ objabi.Hfuchsia,
objabi.Hnetbsd,
objabi.Hopenbsd,
objabi.Hdragonfly,
@@ -751,6 +755,7 @@
case objabi.Hlinux,
objabi.Hfreebsd,
+ objabi.Hfuchsia,
objabi.Hnetbsd,
objabi.Hopenbsd,
objabi.Hdragonfly,
@@ -831,6 +836,7 @@
case objabi.Hlinux,
objabi.Hfreebsd,
+ objabi.Hfuchsia,
objabi.Hnetbsd,
objabi.Hopenbsd,
objabi.Hdragonfly,
diff --git a/src/cmd/link/internal/amd64/obj.go b/src/cmd/link/internal/amd64/obj.go
index 87e8091..96f5e66 100644
--- a/src/cmd/link/internal/amd64/obj.go
+++ b/src/cmd/link/internal/amd64/obj.go
@@ -105,6 +105,7 @@
case objabi.Hlinux, /* elf64 executable */
objabi.Hfreebsd, /* freebsd */
+ objabi.Hfuchsia, /* fuchsia */
objabi.Hnetbsd, /* netbsd */
objabi.Hopenbsd, /* openbsd */
objabi.Hdragonfly, /* dragonfly */
diff --git a/src/cmd/link/internal/arm64/asm.go b/src/cmd/link/internal/arm64/asm.go
index 5ba038d..78f47c3 100644
--- a/src/cmd/link/internal/arm64/asm.go
+++ b/src/cmd/link/internal/arm64/asm.go
@@ -359,7 +359,7 @@
return int64(o1)<<32 | int64(o0), true
case objabi.R_ARM64_TLS_LE:
r.Done = false
- if ctxt.HeadType != objabi.Hlinux {
+ if ctxt.HeadType != objabi.Hlinux && ctxt.HeadType != objabi.Hfuchsia {
ld.Errorf(s, "TLS reloc on unsupported OS %v", ctxt.HeadType)
}
// The TCB is two pointers. This is not documented anywhere, but is
@@ -508,6 +508,7 @@
case objabi.Hlinux,
objabi.Hfreebsd,
+ objabi.Hfuchsia,
objabi.Hnetbsd,
objabi.Hopenbsd,
objabi.Hnacl:
diff --git a/src/cmd/link/internal/arm64/obj.go b/src/cmd/link/internal/arm64/obj.go
index 405d22d..3a14d43 100644
--- a/src/cmd/link/internal/arm64/obj.go
+++ b/src/cmd/link/internal/arm64/obj.go
@@ -87,7 +87,7 @@
*ld.FlagRound = 4096
}
- case objabi.Hlinux: /* arm64 elf */
+ case objabi.Hlinux, objabi.Hfuchsia: /* arm64 elf */
ld.Elfinit(ctxt)
ld.HEADR = ld.ELFRESERVE
if *ld.FlagTextAddr == -1 {
diff --git a/src/cmd/link/internal/ld/config.go b/src/cmd/link/internal/ld/config.go
index 60b6491..9080d73 100644
--- a/src/cmd/link/internal/ld/config.go
+++ b/src/cmd/link/internal/ld/config.go
@@ -35,10 +35,13 @@
default:
return fmt.Errorf("invalid buildmode: %q", s)
case "exe":
+ if objabi.GOOS == "fuchsia" {
+ return badmode()
+ }
*mode = BuildModeExe
case "pie":
switch objabi.GOOS {
- case "android", "linux":
+ case "android", "linux", "fuchsia":
case "darwin", "freebsd":
switch objabi.GOARCH {
case "amd64":
diff --git a/src/cmd/link/internal/ld/data.go b/src/cmd/link/internal/ld/data.go
index e0fad1a..a110060 100644
--- a/src/cmd/link/internal/ld/data.go
+++ b/src/cmd/link/internal/ld/data.go
@@ -175,8 +175,8 @@
}
// We need to be able to reference dynimport symbols when linking against
- // shared libraries, and Solaris, Darwin and AIX need it always
- if ctxt.HeadType != objabi.Hsolaris && ctxt.HeadType != objabi.Hdarwin && ctxt.HeadType != objabi.Haix && r.Sym != nil && r.Sym.Type == sym.SDYNIMPORT && !ctxt.DynlinkingGo() && !r.Sym.Attr.SubSymbol() {
+ // shared libraries, and Solaris, Darwin, AIX, and Fuchsia need it always
+ if ctxt.HeadType != objabi.Hsolaris && ctxt.HeadType != objabi.Hdarwin && ctxt.HeadType != objabi.Haix && ctxt.HeadType != objabi.Hfuchsia && r.Sym != nil && r.Sym.Type == sym.SDYNIMPORT && !ctxt.DynlinkingGo() && !r.Sym.Attr.SubSymbol() {
if !(ctxt.Arch.Family == sys.PPC64 && ctxt.LinkMode == LinkExternal && r.Sym.Name == ".TOC.") {
Errorf(s, "unhandled relocation for %s (type %d (%s) rtype %d (%s))", r.Sym.Name, r.Sym.Type, r.Sym.Type, r.Type, sym.RelocName(ctxt.Arch, r.Type))
}
diff --git a/src/cmd/link/internal/ld/elf.go b/src/cmd/link/internal/ld/elf.go
index c2a2b3a..1199393 100644
--- a/src/cmd/link/internal/ld/elf.go
+++ b/src/cmd/link/internal/ld/elf.go
@@ -1848,6 +1848,9 @@
case objabi.Hfreebsd:
interpreter = thearch.Freebsddynld
+ case objabi.Hfuchsia:
+ interpreter = "lib/ld.so.1"
+
case objabi.Hnetbsd:
interpreter = thearch.Netbsddynld
@@ -2085,7 +2088,7 @@
}
}
- if ctxt.HeadType == objabi.Hlinux {
+ if ctxt.HeadType == objabi.Hlinux || ctxt.HeadType == objabi.Hfuchsia {
ph := newElfPhdr()
ph.type_ = PT_GNU_STACK
ph.flags = PF_W + PF_R
diff --git a/src/cmd/link/internal/ld/lib.go b/src/cmd/link/internal/ld/lib.go
index 2cb7ae7..e205628 100644
--- a/src/cmd/link/internal/ld/lib.go
+++ b/src/cmd/link/internal/ld/lib.go
@@ -1257,7 +1257,10 @@
}
// Force global symbols to be exported for dlopen, etc.
- if ctxt.IsELF {
+ if ctxt.HeadType == objabi.Hfuchsia && !strings.Contains(argv[0], "clang") {
+ // Find libgcc
+ argv = append(argv, ctxt.findLibPathCmd("--print-libgcc-file-name", "libgcc"))
+ } else if ctxt.IsELF {
argv = append(argv, "-rdynamic")
}
@@ -1358,6 +1361,9 @@
argv = append(argv, "-Wl,--start-group", "-lmingwex", "-lmingw32", "-Wl,--end-group")
argv = append(argv, peimporteddlls()...)
}
+ if ctxt.HeadType == objabi.Hfuchsia && strings.Contains(argv[0], "clang") {
+ argv = append(argv, "-lzircon", "-lfdio")
+ }
if ctxt.Debugvlog != 0 {
ctxt.Logf("%5.2f host link:", Cputime())
diff --git a/src/cmd/link/internal/ld/sym.go b/src/cmd/link/internal/ld/sym.go
index a487b5e..cc47281 100644
--- a/src/cmd/link/internal/ld/sym.go
+++ b/src/cmd/link/internal/ld/sym.go
@@ -96,6 +96,9 @@
ctxt.Tlsoffset = -1 * ctxt.Arch.PtrSize
}
+ case objabi.Hfuchsia:
+ ctxt.Tlsoffset = -1 * ctxt.Arch.PtrSize
+
case objabi.Hnacl:
switch ctxt.Arch.Family {
default:
diff --git a/src/crypto/rand/rand_fuchsia.go b/src/crypto/rand/rand_fuchsia.go
new file mode 100644
index 0000000..40be276
--- /dev/null
+++ b/src/crypto/rand/rand_fuchsia.go
@@ -0,0 +1,25 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build fuchsia
+
+package rand
+
+import "syscall/zx"
+
+func init() {
+ Reader = new(cprngReader)
+}
+
+// cprngReader uses the PRNG exposed by zircon syscall.
+//
+// TODO(crawshaw): does it perform as well as /dev/urandom?
+// If not, borrow newReader from rand_unix.go and use this
+// as the entropy source.
+type cprngReader struct{}
+
+func (r *cprngReader) Read(b []byte) (n int, err error) {
+ zx.RandRead(b)
+ return len(b), nil
+}
diff --git a/src/crypto/x509/root_darwin_armx.go b/src/crypto/x509/root_darwin_armx.go
index fcbbd6b..87c9334 100644
--- a/src/crypto/x509/root_darwin_armx.go
+++ b/src/crypto/x509/root_darwin_armx.go
@@ -4,9 +4,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build cgo
-// +build darwin
-// +build arm arm64 ios
+// +build cgo,darwin,arm cgo,darwin,arm64 ios fuchsia
package x509
diff --git a/src/crypto/x509/root_fuchsia.go b/src/crypto/x509/root_fuchsia.go
new file mode 100644
index 0000000..bf37319
--- /dev/null
+++ b/src/crypto/x509/root_fuchsia.go
@@ -0,0 +1,9 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package x509
+
+func (c *Certificate) systemVerify(opts *VerifyOptions) (chains [][]*Certificate, err error) {
+ return nil, nil
+}
diff --git a/src/go/build/deps_test.go b/src/go/build/deps_test.go
index 2c29a3e..792ee71 100644
--- a/src/go/build/deps_test.go
+++ b/src/go/build/deps_test.go
@@ -35,8 +35,8 @@
var pkgDeps = map[string][]string{
// L0 is the lowest level, core, nearly unavoidable packages.
"errors": {},
- "io": {"errors", "sync", "sync/atomic"},
- "runtime": {"unsafe", "runtime/internal/atomic", "runtime/internal/sys", "runtime/internal/math", "internal/cpu", "internal/bytealg"},
+ "io": {"errors", "sync", "sync/atomic", "syscall/zx"},
+ "runtime": {"unsafe", "runtime/internal/atomic", "runtime/internal/sys", "runtime/internal/math", "internal/cpu", "internal/bytealg", "syscall/zx"},
"runtime/internal/sys": {},
"runtime/internal/atomic": {"unsafe", "internal/cpu"},
"runtime/internal/math": {"runtime/internal/sys"},
@@ -46,6 +46,7 @@
"unsafe": {},
"internal/cpu": {},
"internal/bytealg": {"unsafe", "internal/cpu"},
+ "internal/fuchsia/abigen": {"fmt", "strings", "unicode/utf8"},
"L0": {
"errors",
@@ -57,6 +58,16 @@
"unsafe",
"internal/cpu",
"internal/bytealg",
+ "syscall/zx",
+ "syscall/zx/dispatch",
+ "syscall/zx/fdio",
+ "syscall/zx/fidl",
+ "syscall/zx/io",
+ "syscall/zx/mem",
+ "syscall/zx/mxnet",
+ "syscall/zx/net",
+ "syscall/zx/zxsocket",
+ "syscall/zx/zxwait",
},
// L1 adds simple functions and strings processing,
@@ -143,8 +154,23 @@
// End of linear dependency definitions.
// Operating system access.
- "syscall": {"L0", "internal/race", "internal/syscall/windows/sysdll", "syscall/js", "unicode/utf16"},
- "syscall/js": {"L0"},
+ "syscall": {"L0", "internal/race", "internal/syscall/windows/sysdll", "syscall/js", "unicode/utf16", "path", "strings"},
+ "syscall/js": {"L0"},
+
+ "syscall/zx": {"L0"},
+ "syscall/zx/dispatch": {"L0", "strconv"},
+ "syscall/zx/fdio": {"L0"},
+ "syscall/zx/fdio/mxc": {"L0", "C", "syscall"},
+ "syscall/zx/fidl": {"L0", "math", "reflect", "strconv", "strings"},
+ "syscall/zx/fidl/bindingstest": {"L0"},
+ "syscall/zx/fidl/conformance": {"L0"},
+ "syscall/zx/io": {"L0"},
+ "syscall/zx/mem": {"L0"},
+ "syscall/zx/mxnet": {"L0"},
+ "syscall/zx/net": {"L0"},
+ "syscall/zx/zxsocket": {"L0", "syscall"},
+ "syscall/zx/zxwait": {"L0"},
+
"internal/syscall/unix": {"L0", "syscall"},
"internal/syscall/windows": {"L0", "syscall", "internal/syscall/windows/sysdll"},
"internal/syscall/windows/registry": {"L0", "syscall", "internal/syscall/windows/sysdll", "unicode/utf16"},
@@ -164,7 +190,7 @@
"internal/poll": {"L0", "internal/race", "syscall", "time", "unicode/utf16", "unicode/utf8", "internal/syscall/windows"},
"internal/testlog": {"L0"},
- "os": {"L1", "os", "syscall", "time", "internal/poll", "internal/syscall/windows", "internal/syscall/unix", "internal/testlog"},
+ "os": {"L1", "os", "syscall", "time", "internal/poll", "internal/syscall/windows", "internal/syscall/unix", "internal/testlog", "C"},
"path/filepath": {"L2", "os", "syscall", "internal/syscall/windows"},
"io/ioutil": {"L2", "os", "path/filepath", "time"},
"os/exec": {"L2", "os", "context", "path/filepath", "syscall"},
diff --git a/src/go/build/syslist.go b/src/go/build/syslist.go
index d13fe9c..7041cca 100644
--- a/src/go/build/syslist.go
+++ b/src/go/build/syslist.go
@@ -4,5 +4,5 @@
package build
-const goosList = "aix android darwin dragonfly freebsd hurd js linux nacl netbsd openbsd plan9 solaris windows zos "
+const goosList = "aix android darwin dragonfly freebsd fuchsia hurd js linux nacl netbsd openbsd plan9 solaris windows zos "
const goarchList = "386 amd64 amd64p32 arm armbe arm64 arm64be ppc64 ppc64le mips mipsle mips64 mips64le mips64p32 mips64p32le ppc riscv riscv64 s390 s390x sparc sparc64 wasm "
diff --git a/src/internal/fuchsia/abigen/defs.go b/src/internal/fuchsia/abigen/defs.go
new file mode 100644
index 0000000..5546bc6
--- /dev/null
+++ b/src/internal/fuchsia/abigen/defs.go
@@ -0,0 +1,75 @@
+package abigen
+
+// SysArg represents an arg to a vDSO-exported syscall.
+type SysArg struct {
+ Name string // Name represents the name of the argument.
+ Type SysType // Type represents the type of the argument.
+ Constraint string // Constraint represents constraints on the argument (in/out/inout).
+}
+
+// SysDef represents a definition of a vDSO-exported syscall.
+type SysDef struct {
+ Name string // Name is the name of this syscall definition.
+ Ret SysType // Ret is the return type of the syscall.
+ Attrs []string // Attrs contains one or more attributes of the syscall.
+ Args []SysArg // Args represents the arguments taken by the syscall.
+ VDSOCall bool // VDSOCall represents whether the syscall is returned directly from the vDSO.
+}
+
+// GoName returns a string representing the Go name of the syscall in the syscall package.
+func (d *SysDef) GoName() string {
+ if d.Exported() {
+ return "Sys_" + d.Name
+ }
+ return "sys_" + d.Name
+}
+
+// Exported determines whether a particular syscall definition should be exported.
+func (d *SysDef) Exported() bool {
+ switch d.Name {
+ case "handle_duplicate",
+ "object_set_profile",
+ "object_wait_many",
+ "channel_create",
+ "channel_read",
+ "channel_read_etc",
+ "channel_write",
+ "pci_get_bar",
+ "pci_map_interrupt",
+ "pci_query_irq_mode",
+ "pci_set_irq_mode",
+ "pci_init",
+ "pci_add_subtract_to_range",
+ "socket_create",
+ "socket_read",
+ "socket_write",
+ "socket_accept",
+ "socket_share",
+ "system_get_dcache_line_size",
+ "system_get_features",
+ "vmar_allocate",
+ "vmar_destroy",
+ "vmo_read",
+ "vmo_write",
+ "vmo_get_size",
+ "vmo_set_size",
+ "vmo_op_range",
+ "vmo_replace_as_executable":
+ return false
+ default:
+ return true
+ }
+}
+
+func (d *SysDef) Deprecated() bool {
+ switch d.Name {
+ case "vmar_allocate_old",
+ "vmar_map_old",
+ "vmar_protect_old",
+ "futex_wait_deprecated",
+ "futex_requeue_deprecated":
+ return true
+ default:
+ return false
+ }
+}
diff --git a/src/internal/fuchsia/abigen/doc.go b/src/internal/fuchsia/abigen/doc.go
new file mode 100644
index 0000000..18b13fb
--- /dev/null
+++ b/src/internal/fuchsia/abigen/doc.go
@@ -0,0 +1,9 @@
+// The abigen package provides functionality for parsing Fuchsia's syscalls.abigen file,
+// which contains information on syscalls exposed through the vDSO. This file is used to
+// generate stubs and implementation in the syscall package.
+//
+// Example usage:
+//
+// p := abigen.NewParser(buffer, "/path/to/syscalls.abigen")
+// syscalls, err := p.Parse()
+package abigen
diff --git a/src/internal/fuchsia/abigen/parser.go b/src/internal/fuchsia/abigen/parser.go
new file mode 100644
index 0000000..8d68240
--- /dev/null
+++ b/src/internal/fuchsia/abigen/parser.go
@@ -0,0 +1,331 @@
+package abigen
+
+import (
+ "fmt"
+ "strings"
+ "unicode/utf8"
+)
+
+// Parser is a type that is able to parse a syscalls.abigen file.
+type Parser struct {
+ buf []byte
+ off int
+ line, col int
+ name string
+
+ r rune
+}
+
+type token rune
+
+const (
+ tokenEOF token = iota
+ tokenBad
+ tokenIdent
+ tokenNumber
+)
+
+// String implements fmt.Stringer on the token type.
+func (t token) String() string {
+ switch t {
+ case tokenEOF:
+ return "token(EOF)"
+ case tokenBad:
+ return "token(BAD)"
+ case tokenIdent:
+ return "token(Ident)"
+ case tokenNumber:
+ return "token(Number)"
+ default:
+ return "token(" + string(t) + ")"
+ }
+}
+
+func NewParser(buf []byte, fn string) *Parser {
+ return &Parser{
+ buf: buf,
+ line: 1,
+ name: fn,
+ }
+}
+
+func (p *Parser) Parse() (defs []SysDef, err error) {
+ if len(p.buf) == 0 {
+ return nil, nil
+ }
+
+ p.nextRune()
+ for {
+ t, lit := p.nextToken()
+ if t == tokenEOF {
+ return defs, nil
+ } else if t == tokenBad {
+ return nil, p.errorf("bad token: %s", lit)
+ }
+
+ if lit == "syscall" {
+ def, err := p.parseSyscall()
+ if err != nil {
+ return nil, err
+ }
+
+ // The PCI syscalls are DDK-only and temporary. The hypervisor syscalls
+ // have complex parameter and return types. Exclude all of these.
+ // helpers for them.
+ if strings.Contains(def.Name, "_test") || strings.HasPrefix(def.Name, "pci_") || strings.HasPrefix(def.Name, "guest_") || strings.HasPrefix(def.Name, "vcpu_") {
+ continue
+ }
+
+ // Ignore syscalls that are left just for compatibility.
+ if def.Deprecated() {
+ continue
+ }
+
+ defs = append(defs, def)
+ } else {
+ return nil, p.errorf("unexpected token: %q (literal %q)", t, lit)
+ }
+ }
+
+ return defs, nil
+}
+
+func (p *Parser) expect(want token) {
+ t, lit := p.nextToken()
+ if t != want {
+ p.panicf("expected %q but got %q (literal %q)", want, t, lit)
+ }
+}
+
+func (p *Parser) parseAttributes() (attr []string, err error) {
+ for {
+ p.skipWhitespace()
+ if p.r == '(' {
+ return
+ }
+ attr = append(attr, p.nextIdent())
+ p.skipWhitespace()
+ if p.r == ',' {
+ p.nextRune()
+ }
+ }
+}
+
+func (p *Parser) parseArg() (arg SysArg, err error) {
+ if p.r == ')' {
+ return
+ }
+ arg.Name = p.nextIdent()
+ p.expect(':')
+ arg.Type, err = p.parseType()
+ if err != nil {
+ return SysArg{}, err
+ }
+ p.skipWhitespace()
+ if isLetter(p.r) {
+ arg.Constraint = p.nextIdent()
+ p.skipWhitespace()
+ }
+ return
+}
+
+func (p *Parser) parseSyscall() (d SysDef, err error) {
+ d.Name = p.nextIdent()
+ d.Attrs, err = p.parseAttributes()
+ if err != nil {
+ return SysDef{}, err
+ }
+ for _, a := range d.Attrs {
+ if a == "vdsocall" {
+ d.VDSOCall = true
+ }
+ }
+ p.expect('(')
+ for {
+ p.skipWhitespace()
+ if p.r == ')' {
+ p.nextRune()
+ break
+ }
+ arg, err := p.parseArg()
+ if err != nil {
+ return SysDef{}, err
+ }
+ if arg.Name == "" {
+ break
+ }
+ d.Args = append(d.Args, arg)
+ if p.r == ',' {
+ p.nextRune()
+ }
+ }
+ p.skipWhitespace()
+ if p.r != ';' {
+ kw := p.nextIdent()
+ if kw != "returns" {
+ p.panicf("expected \"returns\" but got \"%s\"", kw)
+ }
+ p.expect('(')
+ first := true
+ for {
+ p.skipWhitespace()
+ if p.r == ')' {
+ p.nextRune()
+ break
+ }
+ if first {
+ first = false
+ rtype, err := p.parseType()
+ if err != nil {
+ return SysDef{}, err
+ }
+ d.Ret = rtype
+ } else {
+ arg, err := p.parseArg()
+ if err != nil {
+ return SysDef{}, err
+ }
+ // Extra return types are returned as pointers.
+ arg.Type.Array = true
+ arg.Type.ArraySize = "1"
+ d.Args = append(d.Args, arg)
+ }
+ if p.r == ',' {
+ p.nextRune()
+ }
+ }
+ }
+ p.skipWhitespace()
+ p.expect(';')
+ return d, nil
+}
+
+func (p *Parser) parseType() (t SysType, err error) {
+ ident := p.nextIdent()
+ n, ok := sysTypeNames[ident]
+ if !ok {
+ return t, p.errorf("unknown type name: %s", ident)
+ }
+ t.Name = n
+ p.skipWhitespace()
+ if p.r == '[' {
+ p.nextRune()
+ t.Array = true
+ t.ArraySize = p.nextIdent()
+ p.skipWhitespace()
+ for p.r == '*' {
+ p.nextRune()
+ t.ArraySize += " * " + p.nextIdent()
+ }
+ p.expect(']')
+ }
+ return t, nil
+}
+
+func (p *Parser) nextToken() (t token, lit string) {
+ p.skipWhitespace()
+
+ if isLetter(p.r) {
+ lit = p.nextIdent()
+ return tokenIdent, lit
+ }
+ if isNumber(p.r) {
+ lit = p.nextNumber()
+ return tokenNumber, lit
+ }
+
+ r := p.r
+ p.nextRune()
+ switch r {
+ case -1:
+ return tokenEOF, ""
+ case '(', ')', '*', ',', ';', ':', '[', ']':
+ return token(r), ""
+ case '#':
+ p.skipComment()
+ return p.nextToken()
+ }
+ return tokenBad, fmt.Sprintf("%q", r)
+}
+
+func (p *Parser) nextIdent() string {
+ p.skipWhitespace()
+ if !isLetter(p.r) && !isNumber(p.r) {
+ p.panicf("expected ident but got %q", p.r)
+ }
+ off := p.off - 1
+ for isLetter(p.r) || isNumber(p.r) {
+ p.nextRune()
+ }
+ r := string(p.buf[off : p.off-1])
+ if r == "type" {
+ // "type" is a reserved word in Go.
+ return "typ"
+ }
+ return r
+}
+
+func (p *Parser) nextNumber() string {
+ p.skipWhitespace()
+ if !isNumber(p.r) {
+ p.panicf("expected number but got %q", p.r)
+ }
+ off := p.off - 1
+ for isNumber(p.r) {
+ p.nextRune()
+ }
+ return string(p.buf[off : p.off-1])
+}
+
+func (p *Parser) skipWhitespace() {
+ for p.r == ' ' || p.r == '\t' || p.r == '\n' {
+ p.nextRune()
+ }
+}
+
+func (p *Parser) skipComment() {
+ // skip until end of line
+ p.nextRune()
+ for p.r != '\n' && p.r >= 0 {
+ p.nextRune()
+ }
+}
+
+func (p *Parser) nextRune() {
+ if p.off >= len(p.buf) {
+ p.r = -1
+ return
+ }
+ if p.r == '\n' {
+ p.line++
+ p.col = 0
+ } else {
+ p.col += utf8.RuneLen(p.r)
+ }
+
+ r, w := utf8.DecodeRune(p.buf[p.off:])
+ if r == utf8.RuneError && w == 1 {
+ p.r = -1
+ p.panicf("input is not UTF-8")
+ return
+ }
+ p.r = r
+ p.off += w
+}
+
+func (p *Parser) panicf(format string, args ...interface{}) {
+ panic(parsePanic{err: p.errorf(format, args...)})
+}
+
+func (p *Parser) errorf(format string, args ...interface{}) error {
+ return fmt.Errorf("%s:%d:%d: %s", p.name, p.line, p.col, fmt.Sprintf(format, args...))
+}
+
+func isLetter(r rune) bool { return 'a' <= r && r <= 'z' || 'A' <= r && r <= 'Z' || r == '_' }
+func isNumber(r rune) bool { return '0' <= r && r <= '9' }
+
+type parsePanic struct {
+ err error
+}
+
+func (pp parsePanic) String() string { return pp.err.Error() }
diff --git a/src/internal/fuchsia/abigen/types.go b/src/internal/fuchsia/abigen/types.go
new file mode 100644
index 0000000..f746741
--- /dev/null
+++ b/src/internal/fuchsia/abigen/types.go
@@ -0,0 +1,330 @@
+package abigen
+
+import "fmt"
+
+// SysType represents the type of an argument or vDSO-exported syscall function
+// return value.
+type SysType struct {
+ Name SysTypeName // Name represents the name of the type.
+ Array bool // Array is true when the type represents an array.
+ ArraySize string // When Array is true, ArraySize represents the size of the array.
+}
+
+// SysTypeName represents the name of a SysType.
+type SysTypeName int
+
+const (
+ zxVoid SysTypeName = iota
+ zxAny
+ zxBool
+ zxUint
+ zxInt
+ zxChar
+ zxUint8
+ zxInt16
+ zxUint16
+ zxInt32
+ zxUint32
+ zxInt64
+ zxUint64
+ zxUintptr
+ zxSize
+ zxStatus
+ zxClock
+ zxTime
+ zxDuration
+ zxKOID
+ zxHandle
+ zxSignals
+ zxSignalsState
+ zxSMCParameters
+ zxSMCResult
+ zxWaitItem
+ zxRights
+ zxVAddr
+ zxPAddr
+ zxProcessInfo
+ zxExceptionStatus
+ zxExceptionBehaviour
+ zxFunctionPtr
+ zxRRec
+ zxChannelCallArgs
+ zxFIFOState
+ zxVMOption
+)
+
+var sysTypeNames = map[string]SysTypeName{
+ "any": zxAny,
+ "void": zxVoid,
+ "bool": zxBool,
+ "unsigned int": zxUint,
+ "int": zxInt,
+ "char": zxChar,
+ "uint8_t": zxUint8,
+ "int16_t": zxInt16,
+ "int32_t": zxInt32,
+ "int64_t": zxInt64,
+ "uint16_t": zxUint16,
+ "uint32_t": zxUint32,
+ "uint64_t": zxUint64,
+ "uintptr_t": zxUintptr,
+ "size_t": zxSize,
+ "zx_status_t": zxStatus, // int32_t
+ "zx_clock_t": zxUint32,
+ "zx_time_t": zxTime, // uint64_t monotonic time
+ "zx_ticks_t": zxUint64,
+ "zx_duration_t": zxDuration, // uint64_t nanoseconds
+ "zx_koid_t": zxKOID,
+ "zx_handle_t": zxHandle, // int32_t
+ "zx_futex_t": zxInt32,
+ "zx_signals_t": zxSignals,
+ "zx_signals_state_t": zxSignalsState,
+ "zx_wait_item_t": zxWaitItem,
+ "zx_rights_t": zxRights,
+ "zx_vaddr_t": zxVAddr,
+ "zx_paddr_t": zxPAddr,
+ "zx_smc_parameters_t": zxSMCParameters,
+ "zx_smc_result_t": zxSMCResult,
+ "zx_process_info_t": zxProcessInfo,
+ "zx_exception_status_t": zxExceptionStatus,
+ "zx_exception_behaviour_t": zxExceptionBehaviour,
+ "zx_function_pointer": zxFunctionPtr,
+ "zx_rrec_t": zxRRec,
+ "zx_channel_call_args_t": zxChannelCallArgs,
+ "zx_fifo_state_t": zxFIFOState,
+ "zx_vm_option_t": zxVMOption,
+ // TODO(dhobsd): Remove the following temporary types. They could be blacklisted, but this is easier.
+ "zx_cache_policy_t": zxInt,
+ "zx_port_packet_t": zxInt,
+ "zx_pci_init_arg_t": zxInt,
+ "zx_pci_irq_mode_t": zxInt,
+ "zx_pci_resource_t": zxInt,
+ "zx_pcie_device_info_t": zxInt,
+ "zx_pcie_get_nth_info_t": zxInt,
+ "zx_vcpu_create_args_t": zxInt,
+ "zx_system_powerctl_arg_t": zxInt,
+ "zx_handle_info_t": zxInt,
+ "zx_profile_info_t": zxInt,
+ "zx_pci_bar_t": zxInt,
+}
+
+// Size returns the size (in bytes) of the type. Its argument represents the size of the register
+// on the machine for which the type is generated.
+func (t SysType) Size() int {
+ if t.Array {
+ return 8
+ }
+ switch t.Name {
+ case zxFunctionPtr:
+ return 8
+ case zxVoid:
+ return 0
+ case zxAny:
+ return 0
+ case zxBool:
+ return 1
+ case zxInt, zxUint, zxUintptr, zxSize:
+ return 8
+ case zxChar, zxUint8:
+ return 1
+ case zxInt16, zxUint16:
+ return 2
+ case zxInt32, zxUint32:
+ return 4
+ case zxInt64, zxUint64:
+ return 8
+ case zxStatus:
+ return 4
+ case zxClock:
+ return 4
+ case zxTime:
+ return 8
+ case zxDuration:
+ return 8
+ case zxKOID:
+ return 8
+ case zxHandle:
+ return 4
+ case zxSignals:
+ return 4
+ case zxRights:
+ return 4
+ case zxVMOption:
+ return 4
+ case zxVAddr, zxPAddr:
+ return 8
+ case zxProcessInfo:
+ panic("cannot pass zxprocess_info")
+ case zxExceptionStatus, zxExceptionBehaviour:
+ return 4
+ default:
+ panic(fmt.Sprintf("UNKNOWN(%s)", t.Name))
+ }
+}
+
+func (t SysType) goType() string {
+ switch t.Name {
+ case zxVoid:
+ return "BAD(void)"
+ case zxAny:
+ return "BAD(any)"
+ case zxBool:
+ return "bool"
+ case zxUint:
+ return "uint"
+ case zxInt:
+ return "int"
+ case zxChar, zxUint8:
+ return "uint8"
+ case zxInt16:
+ return "int16"
+ case zxUint16:
+ return "uint16"
+ case zxInt32:
+ return "int32"
+ case zxUint32:
+ return "uint32"
+ case zxInt64:
+ return "int64"
+ case zxUint64:
+ return "uint64"
+ case zxUintptr:
+ return "uintptr"
+ case zxStatus:
+ return "Status"
+ case zxClock:
+ return "Clock"
+ case zxTime:
+ return "Time"
+ case zxDuration:
+ return "Duration"
+ case zxKOID:
+ return "uint64"
+ case zxHandle:
+ return "Handle"
+ case zxSignals:
+ return "Signals"
+ case zxWaitItem:
+ return "WaitItem"
+ case zxRights:
+ return "Rights"
+ case zxVAddr:
+ return "Vaddr"
+ case zxPAddr:
+ return "Paddr"
+ case zxSize:
+ return "uint"
+ case zxProcessInfo:
+ return "ProcessInfo"
+ case zxExceptionStatus:
+ return "ExceptionStatus"
+ case zxExceptionBehaviour:
+ return "ExceptionBehaviour"
+ case zxRRec:
+ return "Rrec"
+ case zxChannelCallArgs:
+ return "ChannelCallArgs"
+ case zxFIFOState:
+ return "FIFOState"
+ case zxSMCParameters:
+ return "SMCParameters"
+ case zxSMCResult:
+ return "SMCResult"
+ case zxVMOption:
+ return "VMFlag"
+ default:
+ panic(fmt.Sprintf("UNKNOWN(%s)", t.Name))
+ }
+}
+
+// GoType returns the Go type name for the corresponding SysType.
+func (t SysType) GoType() string {
+ if t.Array {
+ if t.Name == zxAny {
+ return "unsafe.Pointer"
+ }
+ return fmt.Sprintf("*%s", t.goType())
+ }
+
+ return t.goType()
+}
+
+// NativeType returns a size-compatible Go native type for the SysType.
+func (t SysType) NativeType() string {
+ if t.Array {
+ return "unsafe.Pointer"
+ }
+
+ switch t.Name {
+ case zxVoid:
+ return "BAD(void)"
+ case zxAny:
+ return "uintptr"
+ case zxBool:
+ return "bool"
+ case zxUint:
+ return "uint"
+ case zxInt:
+ return "int"
+ case zxChar, zxUint8:
+ return "uint8"
+ case zxInt16:
+ return "int16"
+ case zxUint16:
+ return "uint16"
+ case zxInt32:
+ return "int32"
+ case zxUint32:
+ return "uint32"
+ case zxInt64:
+ return "int64"
+ case zxUint64:
+ return "uint64"
+ case zxUintptr:
+ return "uintptr"
+ case zxStatus:
+ return "int32"
+ case zxClock:
+ return "uint32"
+ case zxTime:
+ return "int64"
+ case zxDuration:
+ return "int64"
+ case zxKOID:
+ return "uint64"
+ case zxHandle:
+ return "uint32"
+ case zxSignals:
+ return "uint32"
+ case zxWaitItem:
+ return "uintptr"
+ case zxRights:
+ return "uint32"
+ case zxVAddr:
+ return "uintptr"
+ case zxPAddr:
+ return "uintptr"
+ case zxSize:
+ return "uint"
+ case zxProcessInfo:
+ return "uintptr"
+ case zxExceptionStatus:
+ return "uintptr"
+ case zxExceptionBehaviour:
+ return "uintptr"
+ case zxRRec:
+ return "uintptr"
+ case zxChannelCallArgs:
+ return "uintptr"
+ case zxFIFOState:
+ return "uintptr"
+ case zxSMCParameters:
+ return "uintptr"
+ case zxSMCResult:
+ return "uintptr"
+ case zxVMOption:
+ return "uint32"
+ default:
+ panic(fmt.Sprintf("UNKNOWN(%s)", t.Name))
+ }
+}
diff --git a/src/internal/poll/fd_fuchsia.go b/src/internal/poll/fd_fuchsia.go
new file mode 100644
index 0000000..89b703d
--- /dev/null
+++ b/src/internal/poll/fd_fuchsia.go
@@ -0,0 +1,341 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package poll
+
+import (
+ "io"
+ "sync/atomic"
+ "syscall"
+ "syscall/zx"
+ "syscall/zx/mxnet"
+ "syscall/zx/zxsocket"
+ "unsafe"
+)
+
+// FD is a file descriptor. The net and os packages embed this type in
+// a larger type representing a network connection or OS file.
+type FD struct {
+ // Lock sysfd and serialize access to Read and Write methods.
+ fdmu fdMutex
+
+ // System file descriptor. Immutable until Close.
+ Sysfd int
+
+ // I/O poller.
+ pd pollDesc
+
+ // Whether this is a streaming descriptor, as opposed to a
+ // packet-based descriptor like a UDP socket.
+ IsStream bool
+
+ // Whether a zero byte read indicates EOF. This is false for a
+ // message based socket connection.
+ ZeroReadIsEOF bool
+
+ // Whether this is a normal file.
+ isFile bool
+
+ // Whether in blocking mode
+ isBlocking uint32
+}
+
+// Init initializes the FD. The Sysfd field should already be set.
+// This can be called multiple times on a single FD.
+// The net argument is a network name from the net package (e.g., "tcp"),
+// or "file".
+// Set pollable to true if fd should be managed by runtime netpoll.
+func (fd *FD) Init(net string, pollable bool) error {
+ // We don't actually care about the various network types.
+ if net == "file" {
+ fd.isFile = true
+ }
+ if !pollable {
+ fd.isBlocking = 1
+ return nil
+ }
+ err := fd.pd.init(fd)
+ if err != nil {
+ fd.isBlocking = 1
+ }
+ return err
+}
+
+// see fd.Close() for reasoning.
+func close(fd *FD) error {
+ sysfd := atomic.SwapInt64((*int64)(unsafe.Pointer(&fd.Sysfd)), -1)
+ if sysfd != -1 {
+ return syscall.Close(int(sysfd))
+ }
+ return nil
+}
+
+// Destroy closes the file descriptor. This is called when there are
+// no remaining references.
+func (fd *FD) destroy() error {
+ // Poller may want to unregister fd in readiness notification mechanism,
+ // so this must be executed before closing the fd.
+ fd.pd.close()
+
+ return close(fd)
+}
+
+// Close closes the FD. The underlying file descriptor is closed by the
+// destroy method when there are no remaining references.
+func (fd *FD) Close() error {
+ if !fd.fdmu.increfAndClose() {
+ return errClosing(fd.isFile)
+ }
+
+ fd.pd.evict()
+ // Note: On other implementations, evict will unblock sibling refs, however,
+ // that can't be done yet here. Instead, we have to forcefully close the
+ // connection, sadly ahead of destroy, in order to unblock others.
+ err := close(fd)
+
+ fd.decref()
+
+ return err
+}
+
+// Shutdown wraps the shutdown network call.
+func (fd *FD) Shutdown(how int) error {
+ if err := fd.incref(); err != nil {
+ return err
+ }
+ defer fd.decref()
+ panic("TODO shutdown")
+ //return syscall.Shutdown(fd.Sysfd, how) // TODO
+}
+
+func (fd *FD) Read(p []byte) (int, error) {
+ if err := fd.readLock(); err != nil {
+ return 0, err
+ }
+ defer fd.readUnlock()
+ if len(p) == 0 {
+ // If the caller wanted a zero byte read, return immediately
+ // without trying (but after acquiring the readLock).
+ return 0, nil
+ }
+ if err := fd.pd.prepareRead(fd.isFile); err != nil {
+ return 0, err
+ }
+ // TODO: pollable() read
+ n, err := syscall.Read(fd.Sysfd, p)
+ err = fd.eofError(n, err)
+ return n, err
+}
+
+// Pread wraps the pread system call.
+func (fd *FD) Pread(p []byte, off int64) (int, error) {
+ // Call incref, not readLock, because since pread specifies the
+ // offset it is independent from other reads.
+ // Similarly, using the poller doesn't make sense for pread.
+ if err := fd.incref(); err != nil {
+ return 0, err
+ }
+ n, err := syscall.Pread(fd.Sysfd, p, off)
+ if err != nil {
+ n = 0
+ }
+ fd.decref()
+ err = fd.eofError(n, err)
+ return n, err
+}
+
+// Write implements io.Writer.
+func (fd *FD) Write(p []byte) (int, error) {
+ if err := fd.writeLock(); err != nil {
+ return 0, err
+ }
+ defer fd.writeUnlock()
+ if err := fd.pd.prepareWrite(fd.isFile); err != nil {
+ return 0, err
+ }
+ var nn int
+ for {
+ n, err := syscall.Write(fd.Sysfd, p[nn:])
+ if n > 0 {
+ nn += n
+ }
+ if nn == len(p) {
+ return nn, err
+ }
+ if err != nil {
+ return nn, err
+ }
+ if n == 0 {
+ return nn, io.ErrUnexpectedEOF
+ }
+ }
+}
+
+// Pwrite wraps the pwrite system call.
+func (fd *FD) Pwrite(p []byte, off int64) (int, error) {
+ // Call incref, not writeLock, because since pwrite specifies the
+ // offset it is independent from other writes.
+ // Similarly, using the poller doesn't make sense for pwrite.
+ if err := fd.incref(); err != nil {
+ return 0, err
+ }
+ defer fd.decref()
+ var nn int
+ for {
+ n, err := syscall.Pwrite(fd.Sysfd, p[nn:], off+int64(nn))
+ if n > 0 {
+ nn += n
+ }
+ if nn == len(p) {
+ return nn, err
+ }
+ if err != nil {
+ return nn, err
+ }
+ if n == 0 {
+ return nn, io.ErrUnexpectedEOF
+ }
+ }
+}
+
+// Accept wraps the accept network call.
+func (fd *FD) Accept() (*zxsocket.Socket, error) {
+ if err := fd.readLock(); err != nil {
+ return nil, err
+ }
+ defer fd.readUnlock()
+
+ if err := fd.pd.prepareRead(fd.isFile); err != nil {
+ return nil, err
+ }
+
+ if s, ok := syscall.FDIOForFD(fd.Sysfd).(*zxsocket.Socket); ok {
+ code, err := s.Accept(0)
+ if code == syscall.EAGAIN {
+ // TODO: non-blocking support, pass this to the poller
+ if obs, err := s.Wait(mxnet.MXSIO_SIGNAL_INCOMING|zx.SignalSocketPeerClosed, zx.TimensecInfinite); err != nil {
+ return nil, err
+ } else if obs&zx.SignalSocketPeerClosed != 0 {
+ return nil, &zx.Error{Status: zx.ErrPeerClosed, Text: "zxsocket"}
+ } else if obs&mxnet.MXSIO_SIGNAL_INCOMING != 0 {
+ // fallthrough
+ } else {
+ panic("unreachable")
+ }
+ code, err = s.Accept(0)
+ }
+ if err != nil {
+ return nil, err
+ }
+ if code != 0 {
+ return nil, syscall.Errno(code)
+ }
+ var h zx.Handle
+ if err := s.Socket.Accept(&h); err != nil {
+ return nil, err
+ }
+ return zxsocket.NewSocket(zx.Socket(h)), nil
+ }
+ return nil, syscall.EBADF
+}
+
+// Seek wraps syscall.Seek.
+func (fd *FD) Seek(offset int64, whence int) (int64, error) {
+ if err := fd.incref(); err != nil {
+ return 0, err
+ }
+ defer fd.decref()
+ return syscall.Seek(fd.Sysfd, offset, whence)
+}
+
+// ReadDirent wraps syscall.ReadDirent.
+// We treat this like an ordinary system call rather than a call
+// that tries to fill the buffer.
+func (fd *FD) ReadDirent(buf []byte) (int, error) {
+ if err := fd.incref(); err != nil {
+ return 0, err
+ }
+ defer fd.decref()
+ return syscall.ReadDirent(fd.Sysfd, buf)
+}
+
+// Fstat wraps syscall.Fstat
+func (fd *FD) Fstat(s *syscall.Stat_t) error {
+ if err := fd.incref(); err != nil {
+ return err
+ }
+ defer fd.decref()
+ return syscall.Fstat(fd.Sysfd, s)
+}
+
+// eofError returns io.EOF when fd is available for reading end of
+// file.
+func (fd *FD) eofError(n int, err error) error {
+ if n == 0 && err == nil && fd.ZeroReadIsEOF {
+ return io.EOF
+ }
+ return err
+}
+
+// RawControl invokes the user-defined function f for a non-IO
+// operation.
+func (fd *FD) RawControl(f func(uintptr)) error {
+ if err := fd.incref(); err != nil {
+ return err
+ }
+ defer fd.decref()
+ f(uintptr(fd.Sysfd))
+ return nil
+}
+
+// RawRead invokes the user-defined function f for a read operation.
+func (fd *FD) RawRead(f func(uintptr) bool) error {
+ if err := fd.readLock(); err != nil {
+ return err
+ }
+ defer fd.readUnlock()
+ if err := fd.pd.prepareRead(fd.isFile); err != nil {
+ return err
+ }
+ for {
+ if f(uintptr(fd.Sysfd)) {
+ return nil
+ }
+ if err := fd.pd.waitRead(fd.isFile); err != nil {
+ return err
+ }
+ }
+}
+
+// RawWrite invokes the user-defined function f for a write operation.
+func (fd *FD) RawWrite(f func(uintptr) bool) error {
+ if err := fd.writeLock(); err != nil {
+ return err
+ }
+ defer fd.writeUnlock()
+ if err := fd.pd.prepareWrite(fd.isFile); err != nil {
+ return err
+ }
+ for {
+ if f(uintptr(fd.Sysfd)) {
+ return nil
+ }
+ if err := fd.pd.waitWrite(fd.isFile); err != nil {
+ return err
+ }
+ }
+}
+
+// SetBlocking puts the file into blocking mode.
+func (fd *FD) SetBlocking() error {
+ if err := fd.incref(); err != nil {
+ return err
+ }
+ defer fd.decref()
+ // Atomic store so that concurrent calls to SetBlocking
+ // do not cause a race condition. isBlocking only ever goes
+ // from 0 to 1 so there is no real race here.
+ atomic.StoreUint32(&fd.isBlocking, 1)
+ return syscall.SetNonblock(fd.Sysfd, false)
+}
diff --git a/src/internal/poll/fd_poll_fuchsia.go b/src/internal/poll/fd_poll_fuchsia.go
new file mode 100644
index 0000000..fd87b03
--- /dev/null
+++ b/src/internal/poll/fd_poll_fuchsia.go
@@ -0,0 +1,75 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// TODO: use fd_poll_runtime.go for fuchsia
+
+package poll
+
+import (
+ "time"
+)
+
+type pollDesc struct {
+ fd *FD
+ closing bool
+}
+
+func (pd *pollDesc) init(fd *FD) error { pd.fd = fd; return nil }
+
+func (pd *pollDesc) close() {}
+
+func (pd *pollDesc) evict() {
+ pd.closing = true
+}
+
+func (pd *pollDesc) prepare(mode int, isFile bool) error {
+ if pd.closing {
+ return errClosing(isFile)
+ }
+ return nil
+}
+
+func (pd *pollDesc) prepareRead(isFile bool) error { return pd.prepare('r', isFile) }
+
+func (pd *pollDesc) prepareWrite(isFile bool) error { return pd.prepare('w', isFile) }
+
+func (pd *pollDesc) wait(mode int, isFile bool) error {
+ if pd.closing {
+ return errClosing(isFile)
+ }
+ return ErrTimeout
+}
+
+func (pd *pollDesc) waitRead(isFile bool) error { return pd.wait('r', isFile) }
+
+func (pd *pollDesc) waitWrite(isFile bool) error { return pd.wait('w', isFile) }
+
+func (pd *pollDesc) waitCanceled(mode int) {}
+
+func (pd *pollDesc) pollable() bool { return true }
+
+// SetDeadline sets the read and write deadlines associated with fd.
+func (fd *FD) SetDeadline(t time.Time) error {
+ return setDeadlineImpl(fd, t, 'r'+'w')
+}
+
+// SetReadDeadline sets the read deadline associated with fd.
+func (fd *FD) SetReadDeadline(t time.Time) error {
+ return setDeadlineImpl(fd, t, 'r')
+}
+
+// SetWriteDeadline sets the write deadline associated with fd.
+func (fd *FD) SetWriteDeadline(t time.Time) error {
+ return setDeadlineImpl(fd, t, 'w')
+}
+
+func setDeadlineImpl(fd *FD, t time.Time, mode int) error {
+ return ErrNoDeadline // TODO set deadline
+}
+
+// PollDescriptor returns the descriptor being used by the poller,
+// or ^uintptr(0) if there isn't one. This is only used for testing.
+func PollDescriptor() uintptr {
+ return ^uintptr(0)
+}
diff --git a/src/internal/syscall/unix/nonblocking_fuchsia.go b/src/internal/syscall/unix/nonblocking_fuchsia.go
new file mode 100644
index 0000000..ff67c75
--- /dev/null
+++ b/src/internal/syscall/unix/nonblocking_fuchsia.go
@@ -0,0 +1,9 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package unix
+
+func IsNonblock(fd int) (nonblocking bool, err error) {
+ return false, nil
+}
diff --git a/src/internal/testenv/testenv.go b/src/internal/testenv/testenv.go
index 8f69fe0..c0b6243 100644
--- a/src/internal/testenv/testenv.go
+++ b/src/internal/testenv/testenv.go
@@ -41,7 +41,7 @@
return false
}
switch runtime.GOOS {
- case "android", "nacl", "js":
+ case "android", "fuchsia", "nacl", "js":
return false
case "darwin":
if strings.HasPrefix(runtime.GOARCH, "arm") {
@@ -149,7 +149,7 @@
// HasExternalNetwork reports whether the current system can use
// external (non-localhost) networks.
func HasExternalNetwork() bool {
- return !testing.Short() && runtime.GOOS != "nacl" && runtime.GOOS != "js"
+ return !testing.Short() && runtime.GOOS != "nacl" && runtime.GOOS != "js" && runtime.GOOS != "fuchsia"
}
// MustHaveExternalNetwork checks that the current system can use
@@ -162,6 +162,10 @@
if testing.Short() {
t.Skipf("skipping test: no external network in -short mode")
}
+
+ if runtime.GOOS == "fuchsia" {
+ t.Skipf("external network tests disabled on fuchsia; not all builders have one.")
+ }
}
var haveCGO bool
@@ -209,6 +213,11 @@
}
}
+// HasChmod reports whether the current system can use os.Chmod.
+func HasChmod() bool {
+ return runtime.GOOS != "fuchsia"
+}
+
var flaky = flag.Bool("flaky", false, "run known-flaky tests too")
func SkipFlaky(t testing.TB, issue int) {
diff --git a/src/internal/testenv/testenv_notwin.go b/src/internal/testenv/testenv_notwin.go
index d8ce6cd..e587e6a 100644
--- a/src/internal/testenv/testenv_notwin.go
+++ b/src/internal/testenv/testenv_notwin.go
@@ -12,7 +12,7 @@
func hasSymlink() (ok bool, reason string) {
switch runtime.GOOS {
- case "android", "nacl", "plan9":
+ case "android", "nacl", "plan9", "fuchsia":
return false, ""
}
diff --git a/src/internal/x/net/internal/nettest/helper_stub.go b/src/internal/x/net/internal/nettest/helper_stub.go
index d89cf29..b06e5cc 100644
--- a/src/internal/x/net/internal/nettest/helper_stub.go
+++ b/src/internal/x/net/internal/nettest/helper_stub.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build js nacl plan9
+// +build fuchsia js nacl plan9
package nettest
diff --git a/src/io/io_fuchsia.go b/src/io/io_fuchsia.go
new file mode 100644
index 0000000..ac81e67
--- /dev/null
+++ b/src/io/io_fuchsia.go
@@ -0,0 +1,15 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build fuchsia
+
+package io
+
+import (
+ "syscall/zx"
+)
+
+func init() {
+ zx.EOF = EOF
+}
diff --git a/src/mime/type_fuchsia.go b/src/mime/type_fuchsia.go
new file mode 100644
index 0000000..986c0bb
--- /dev/null
+++ b/src/mime/type_fuchsia.go
@@ -0,0 +1,15 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build fuchsia
+
+package mime
+
+func init() {
+ osInitMime = initMimeFuchsia
+}
+
+func initMimeFuchsia() {
+ // TODO: find an equivalent to /etc/mime.types.
+}
diff --git a/src/net/addrselect.go b/src/net/addrselect.go
index 7c0dfe2..3e7091e 100644
--- a/src/net/addrselect.go
+++ b/src/net/addrselect.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris
+// +build aix darwin dragonfly freebsd fuchsia linux netbsd openbsd solaris
// Minimal RFC 6724 address selection.
diff --git a/src/net/cgo_stub.go b/src/net/cgo_stub.go
index 041f8af..5f19ef4 100644
--- a/src/net/cgo_stub.go
+++ b/src/net/cgo_stub.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build !cgo netgo
+// +build !cgo netgo fuchsia
package net
diff --git a/src/net/conf.go b/src/net/conf.go
index 971b1a3..e4c2c8e 100644
--- a/src/net/conf.go
+++ b/src/net/conf.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris
+// +build aix darwin dragonfly freebsd fuchsia linux netbsd openbsd solaris
package net
diff --git a/src/net/dial_test.go b/src/net/dial_test.go
index 3a2c59a..c79aa1d 100644
--- a/src/net/dial_test.go
+++ b/src/net/dial_test.go
@@ -77,7 +77,7 @@
func TestDialerDualStackFDLeak(t *testing.T) {
switch runtime.GOOS {
- case "plan9":
+ case "plan9", "fuchsia":
t.Skipf("%s does not have full support of socktest", runtime.GOOS)
case "windows":
t.Skipf("not implemented a way to cancel dial racers in TCP SYN-SENT state on %s", runtime.GOOS)
@@ -431,6 +431,10 @@
if !supportsIPv4() || !supportsIPv6() {
t.Skip("both IPv4 and IPv6 are required")
}
+ // TODO(TC-149): disabled without further triage. Needs work.
+ if runtime.GOOS == "fuchsia" {
+ t.Skip("network test disabled for GOOS=fuchsia")
+ }
var wg sync.WaitGroup
wg.Add(2)
@@ -541,6 +545,10 @@
if !supportsIPv4() || !supportsIPv6() {
t.Skip("both IPv4 and IPv6 are required")
}
+ // TODO(TC-149): disabled without further triage. Needs work.
+ if runtime.GOOS == "fuchsia" {
+ t.Skip("network test disabled for GOOS=fuchsia")
+ }
type test struct {
network, raddr string
@@ -712,6 +720,11 @@
}
func TestDialerKeepAlive(t *testing.T) {
+ // TODO(TC-149): disabled without further triage. Needs work.
+ if runtime.GOOS == "fuchsia" {
+ t.Skip("network test disabled for GOOS=fuchsia")
+ }
+
handler := func(ls *localServer, ln Listener) {
for {
c, err := ln.Accept()
@@ -822,6 +835,10 @@
}
func TestCancelAfterDial(t *testing.T) {
+ // TODO(TC-149): disabled without further triage. Needs work.
+ if runtime.GOOS == "fuchsia" {
+ t.Skip("network test disabled for GOOS=fuchsia")
+ }
if testing.Short() {
t.Skip("avoiding time.Sleep")
}
@@ -923,7 +940,7 @@
func TestDialerControl(t *testing.T) {
switch runtime.GOOS {
- case "nacl", "plan9":
+ case "fuchsia", "nacl", "plan9":
t.Skipf("not supported on %s", runtime.GOOS)
}
diff --git a/src/net/dnsclient_unix.go b/src/net/dnsclient_unix.go
index 86ce92d..b87df78 100644
--- a/src/net/dnsclient_unix.go
+++ b/src/net/dnsclient_unix.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris
+// +build aix darwin dragonfly freebsd fuchsia linux netbsd openbsd solaris
// DNS client: see RFC 1035.
// Has to be linked into package net for Dial.
diff --git a/src/net/dnsconfig_fuchsia.go b/src/net/dnsconfig_fuchsia.go
new file mode 100644
index 0000000..c13658b
--- /dev/null
+++ b/src/net/dnsconfig_fuchsia.go
@@ -0,0 +1,44 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build fuchsia
+
+// TODO: use dnsconfig_unix when 127.0.0.1:53 is a valid DNS server.
+
+package net
+
+import (
+ "os"
+ "time"
+)
+
+var (
+ defaultNS = []string{"8.8.8.8:53"}
+ getHostname = os.Hostname // variable for testing
+)
+
+type dnsConfig struct {
+ servers []string
+ attempts int
+ timeout time.Duration
+ search []string
+ ndots int
+ rotate bool
+ unknownOpt bool
+ lookup []string
+ err error
+ mtime time.Time
+ soffset uint32
+}
+
+func dnsReadConfig(filename string) *dnsConfig {
+ return &dnsConfig{
+ ndots: 1,
+ timeout: 5 * time.Second,
+ attempts: 2,
+ servers: defaultNS,
+ }
+}
+
+func (c *dnsConfig) serverOffset() uint32 { return 0 }
diff --git a/src/net/dnsconfig_unix.go b/src/net/dnsconfig_unix.go
index 842d408..bfdeab7 100644
--- a/src/net/dnsconfig_unix.go
+++ b/src/net/dnsconfig_unix.go
@@ -16,7 +16,7 @@
)
var (
- defaultNS = []string{"127.0.0.1:53", "[::1]:53"}
+ defaultNS = []string{"8.8.8.8:53"}
getHostname = os.Hostname // variable for testing
)
diff --git a/src/net/error_fuchsia.go b/src/net/error_fuchsia.go
new file mode 100644
index 0000000..caad133
--- /dev/null
+++ b/src/net/error_fuchsia.go
@@ -0,0 +1,9 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package net
+
+func isConnError(err error) bool {
+ return false
+}
diff --git a/src/net/error_fuchsia_test.go b/src/net/error_fuchsia_test.go
new file mode 100644
index 0000000..2ab6ff6
--- /dev/null
+++ b/src/net/error_fuchsia_test.go
@@ -0,0 +1,35 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build fuchsia !plan9,!windows,!unix
+
+package net
+
+import (
+ "os"
+ "syscall"
+ "syscall/zx"
+)
+
+var (
+ errTimedout = syscall.ETIMEDOUT
+ errOpNotSupported = syscall.EOPNOTSUPP
+
+ abortedConnRequestErrors = []error{syscall.ECONNABORTED} // see accept in fd_unix.go
+)
+
+func isPlatformError(err error) bool {
+ _, ok := err.(*zx.Error)
+ return ok
+}
+
+func samePlatformError(err, want error) bool {
+ if op, ok := err.(*OpError); ok {
+ err = op.Err
+ }
+ if sys, ok := err.(*os.SyscallError); ok {
+ err = sys.Err
+ }
+ return err == want
+}
diff --git a/src/net/error_posix_test.go b/src/net/error_posix_test.go
index b411a37..ab44e70 100644
--- a/src/net/error_posix_test.go
+++ b/src/net/error_posix_test.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build !plan9
+// +build !plan9,!fuchsia
package net
diff --git a/src/net/error_test.go b/src/net/error_test.go
index 2819986..26f6922 100644
--- a/src/net/error_test.go
+++ b/src/net/error_test.go
@@ -137,8 +137,9 @@
}
func TestDialError(t *testing.T) {
+ // TODO(TC-149): disabled without further triage. Needs work.
switch runtime.GOOS {
- case "plan9":
+ case "plan9", "fuchsia":
t.Skipf("%s does not have full support of socktest", runtime.GOOS)
}
@@ -184,6 +185,10 @@
}
func TestProtocolDialError(t *testing.T) {
+ // TODO(TC-149): disabled without further triage. Needs work.
+ if runtime.GOOS == "fuchsia" {
+ t.Skip("network test disabled for GOOS=fuchsia")
+ }
switch runtime.GOOS {
case "nacl", "solaris":
t.Skipf("not supported on %s", runtime.GOOS)
@@ -286,6 +291,10 @@
}
func TestListenError(t *testing.T) {
+ // TODO(TC-149): disabled without further triage. Needs work.
+ if runtime.GOOS == "fuchsia" {
+ t.Skip("network test disabled for GOOS=fuchsia")
+ }
switch runtime.GOOS {
case "plan9":
t.Skipf("%s does not have full support of socktest", runtime.GOOS)
@@ -346,6 +355,10 @@
}
func TestListenPacketError(t *testing.T) {
+ // TODO(TC-149): disabled without further triage. Needs work.
+ if runtime.GOOS == "fuchsia" {
+ t.Skip("network test disabled for GOOS=fuchsia")
+ }
switch runtime.GOOS {
case "plan9":
t.Skipf("%s does not have full support of socktest", runtime.GOOS)
@@ -375,6 +388,10 @@
}
func TestProtocolListenError(t *testing.T) {
+ // TODO(TC-149): disabled without further triage. Needs work.
+ if runtime.GOOS == "fuchsia" {
+ t.Skip("network test disabled for GOOS=fuchsia")
+ }
switch runtime.GOOS {
case "nacl", "plan9":
t.Skipf("not supported on %s", runtime.GOOS)
@@ -548,6 +565,10 @@
}
func TestCloseError(t *testing.T) {
+ // TODO(TC-149): disabled without further triage. Needs work.
+ if runtime.GOOS == "fuchsia" {
+ t.Skip("network test disabled for GOOS=fuchsia")
+ }
ln, err := newLocalListener("tcp")
if err != nil {
t.Fatal(err)
@@ -582,6 +603,11 @@
}
}
+ // TODO(TC-149): disabled without further triage. Needs work.
+ if runtime.GOOS == "fuchsia" {
+ t.Skip("network test disabled for GOOS=fuchsia")
+ }
+
pc, err := ListenPacket("udp", "127.0.0.1:0")
if err != nil {
t.Fatal(err)
@@ -640,6 +666,11 @@
}
func TestAcceptError(t *testing.T) {
+ // TODO(TC-149): disabled without further triage. Needs work.
+ if runtime.GOOS == "fuchsia" {
+ t.Skip("network test disabled for GOOS=fuchsia")
+ }
+
handler := func(ls *localServer, ln Listener) {
for {
ln.(*TCPListener).SetDeadline(time.Now().Add(5 * time.Millisecond))
@@ -719,6 +750,10 @@
}
func TestFileError(t *testing.T) {
+ // TODO(TC-149): disabled without further triage. Needs work.
+ if runtime.GOOS == "fuchsia" {
+ t.Skip("network test disabled for GOOS=fuchsia")
+ }
switch runtime.GOOS {
case "windows":
t.Skipf("not supported on %s", runtime.GOOS)
diff --git a/src/net/error_unix_test.go b/src/net/error_unix_test.go
index 9ce9e12..441ca49 100644
--- a/src/net/error_unix_test.go
+++ b/src/net/error_unix_test.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build !plan9,!windows
+// +build !plan9,!windows,!fuchsia
package net
diff --git a/src/net/fd_fuchsia.go b/src/net/fd_fuchsia.go
new file mode 100644
index 0000000..3e71d3f
--- /dev/null
+++ b/src/net/fd_fuchsia.go
@@ -0,0 +1,156 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// TODO: move to using fd_unix for fuchsia?
+
+package net
+
+import (
+ "errors"
+ "internal/poll"
+ "os"
+ "runtime"
+ "syscall"
+ "syscall/zx/mxnet"
+ "syscall/zx/zxsocket"
+ "time"
+)
+
+// Network file descriptor.
+type netFD struct {
+ pfd poll.FD
+
+ // immutable until Close
+ sock *zxsocket.Socket
+ net string
+ family int
+ sotype int
+ isStream bool
+ isConnected bool
+ laddr Addr
+ raddr Addr
+}
+
+func newFD(sock *zxsocket.Socket, family, sotype int, net string) *netFD {
+ netfd := &netFD{
+ pfd: poll.FD{
+ Sysfd: syscall.OpenFDIO(sock),
+ },
+ sock: sock,
+ family: family,
+ sotype: sotype,
+ net: net,
+ }
+ return netfd
+}
+
+func (fd *netFD) init() error {
+ // TODO: flip to true after implementing netpoller for real
+ return fd.pfd.Init(fd.net, false)
+}
+
+func (fd *netFD) isTCP() bool {
+ return len(fd.net) >= 3 && fd.net[:3] == "tcp"
+}
+
+func (fd *netFD) Read(b []byte) (n int, err error) {
+ n, err = fd.pfd.Read(b)
+ runtime.KeepAlive(fd)
+ return n, err
+}
+
+func (fd *netFD) Write(b []byte) (n int, err error) {
+ n, err = fd.pfd.Write(b)
+ runtime.KeepAlive(fd)
+ return n, err
+}
+
+func (fd *netFD) readMsg(b []byte) (n, flags int, addr string, port uint16, err error) {
+ // TODO: move call to pfd
+ data, flags, addr, port, err := fd.sock.RecvMsg(len(b))
+ runtime.KeepAlive(fd)
+ n = copy(b, data)
+ return n, flags, addr, port, err
+}
+
+func (fd *netFD) sendMsg(b []byte, addr string, port uint16) (n int, err error) {
+ // TODO: move call to pfd
+ n, err = fd.sock.SendMsg(b, addr, port)
+ runtime.KeepAlive(fd)
+ return n, err
+}
+
+func (fd *netFD) closeRead() error {
+ return errors.New("net: closeRead not implemented on fuchsia")
+}
+
+func (fd *netFD) closeWrite() error {
+ return errors.New("net: closeWrite not implemented on fuchsia")
+}
+
+func (fd *netFD) Close() error {
+ return fd.pfd.Close()
+}
+
+func (fd *netFD) dup() (*os.File, error) {
+ // TODO(mknyszek): fd.sock is an FDIO so one can make an FD from it to
+ // implement this.
+ return nil, errors.New("net: dup not implemented on fuchsia")
+}
+
+func (fd *netFD) accept() (*netFD, error) {
+ newm, err := fd.pfd.Accept()
+ if err != nil {
+ return nil, err
+ }
+ netfd := newFD(newm, fd.family, fd.sotype, fd.net)
+ if err := netfd.init(); err != nil {
+ fd.Close()
+ return nil, err
+ }
+ netfd.setAddr()
+ return netfd, nil
+}
+
+func (fd *netFD) asAddr(code int16, b []byte, err error) sockaddr {
+ if err != nil {
+ return nil
+ }
+ if code != 0 {
+ return nil
+ }
+ addr, port, err := mxnet.DecodeSockaddr(b)
+ if err != nil {
+ return nil
+ }
+ ip := IP(addr)
+ if isZeros(ip) && port == 0 {
+ return nil
+ }
+ switch fd.sotype {
+ case syscall.SOCK_STREAM:
+ return &TCPAddr{IP: ip, Port: int(port)}
+ case syscall.SOCK_DGRAM:
+ return &UDPAddr{IP: ip, Port: int(port)}
+ }
+ return nil
+}
+
+func (fd *netFD) setAddr() {
+ fd.laddr = fd.asAddr(fd.sock.GetSockName())
+ fd.raddr = fd.asAddr(fd.sock.GetPeerName())
+ runtime.SetFinalizer(fd, (*netFD).Close)
+}
+
+func (fd *netFD) SetDeadline(t time.Time) error {
+ return fd.pfd.SetDeadline(t)
+}
+
+func (fd *netFD) SetReadDeadline(t time.Time) error {
+ return fd.pfd.SetReadDeadline(t)
+}
+
+func (fd *netFD) SetWriteDeadline(t time.Time) error {
+ return fd.pfd.SetWriteDeadline(t)
+}
diff --git a/src/net/file_stub.go b/src/net/file_stub.go
index 2256608..dce5470 100644
--- a/src/net/file_stub.go
+++ b/src/net/file_stub.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build nacl js,wasm
+// +build nacl js,wasm fuchsia
package net
diff --git a/src/net/file_test.go b/src/net/file_test.go
index cd71774..87aeaf6 100644
--- a/src/net/file_test.go
+++ b/src/net/file_test.go
@@ -30,8 +30,9 @@
}
func TestFileConn(t *testing.T) {
+ // TODO(TC-149): disabled without further triage. Needs work.
switch runtime.GOOS {
- case "nacl", "plan9", "windows":
+ case "nacl", "plan9", "windows", "fuchsia":
t.Skipf("not supported on %s", runtime.GOOS)
}
@@ -137,8 +138,9 @@
}
func TestFileListener(t *testing.T) {
+ // TODO(TC-149): disabled without further triage. Needs work.
switch runtime.GOOS {
- case "nacl", "plan9", "windows":
+ case "nacl", "plan9", "windows", "fuchsia":
t.Skipf("not supported on %s", runtime.GOOS)
}
@@ -229,8 +231,9 @@
}
func TestFilePacketConn(t *testing.T) {
+ // TODO(TC-149): disabled without further triage. Needs work.
switch runtime.GOOS {
- case "nacl", "plan9", "windows":
+ case "nacl", "plan9", "windows", "fuchsia":
t.Skipf("not supported on %s", runtime.GOOS)
}
@@ -297,7 +300,7 @@
// Issue 24483.
func TestFileCloseRace(t *testing.T) {
switch runtime.GOOS {
- case "nacl", "plan9", "windows":
+ case "fuchsia", "nacl", "plan9", "windows":
t.Skipf("not supported on %s", runtime.GOOS)
}
if !testableNetwork("tcp") {
diff --git a/src/net/hook_fuchsia.go b/src/net/hook_fuchsia.go
new file mode 100644
index 0000000..e445c1a
--- /dev/null
+++ b/src/net/hook_fuchsia.go
@@ -0,0 +1,17 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build fuchsia
+
+package net
+
+import "syscall"
+
+var (
+ testHookDialChannel = func() {} // for golang.org/issue/5349
+ testHookCanceledDial = func() {} // for golang.org/issue/16523
+
+ // Placeholders for socket system calls.
+ closeFunc func(int) error = syscall.Close
+)
diff --git a/src/net/hosts_test.go b/src/net/hosts_test.go
index f850e2f..3169866 100644
--- a/src/net/hosts_test.go
+++ b/src/net/hosts_test.go
@@ -6,6 +6,7 @@
import (
"reflect"
+ "runtime"
"strings"
"testing"
)
@@ -59,6 +60,11 @@
}
func TestLookupStaticHost(t *testing.T) {
+ // TODO(TC-149): disabled without further triage. Needs work.
+ if runtime.GOOS == "fuchsia" {
+ t.Skip("network test disabled for GOOS=fuchsia")
+ }
+
defer func(orig string) { testHookHostsPath = orig }(testHookHostsPath)
for _, tt := range lookupStaticHostTests {
@@ -128,6 +134,10 @@
}
func TestLookupStaticAddr(t *testing.T) {
+ // TODO(TC-149): disabled without further triage. Needs work.
+ if runtime.GOOS == "fuchsia" {
+ t.Skip("network test disabled for GOOS=fuchsia")
+ }
defer func(orig string) { testHookHostsPath = orig }(testHookHostsPath)
for _, tt := range lookupStaticAddrTests {
@@ -149,6 +159,10 @@
}
func TestHostCacheModification(t *testing.T) {
+ // TODO(TC-149): disabled without further triage. Needs work.
+ if runtime.GOOS == "fuchsia" {
+ t.Skip("network test disabled for GOOS=fuchsia")
+ }
// Ensure that programs can't modify the internals of the host cache.
// See https://golang.org/issues/14212.
defer func(orig string) { testHookHostsPath = orig }(testHookHostsPath)
diff --git a/src/net/interface_stub.go b/src/net/interface_stub.go
index 0afaa80..426ac46 100644
--- a/src/net/interface_stub.go
+++ b/src/net/interface_stub.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build nacl js,wasm
+// +build nacl js,wasm fuchsia
package net
diff --git a/src/net/internal/socktest/switch_posix.go b/src/net/internal/socktest/switch_posix.go
index 863edef..0ead109 100644
--- a/src/net/internal/socktest/switch_posix.go
+++ b/src/net/internal/socktest/switch_posix.go
@@ -3,6 +3,7 @@
// license that can be found in the LICENSE file.
// +build !plan9
+// +build !fuchsia
package socktest
diff --git a/src/net/internal/socktest/switch_stub.go b/src/net/internal/socktest/switch_stub.go
index 28ce72c..9ba7d73 100644
--- a/src/net/internal/socktest/switch_stub.go
+++ b/src/net/internal/socktest/switch_stub.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build plan9
+// +build plan9 fuchsia
package socktest
diff --git a/src/net/ip_test.go b/src/net/ip_test.go
index a5fc5e6..cde5eca 100644
--- a/src/net/ip_test.go
+++ b/src/net/ip_test.go
@@ -61,6 +61,7 @@
}
func TestLookupWithIP(t *testing.T) {
+ mustHaveExternalNetwork(t)
_, err := LookupIP("")
if err == nil {
t.Errorf(`LookupIP("") succeeded, should fail`)
diff --git a/src/net/iprawsock_fuchsia.go b/src/net/iprawsock_fuchsia.go
new file mode 100644
index 0000000..0bfd133
--- /dev/null
+++ b/src/net/iprawsock_fuchsia.go
@@ -0,0 +1,34 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package net
+
+import (
+ "context"
+ "syscall"
+)
+
+func (c *IPConn) readFrom(b []byte) (int, *IPAddr, error) {
+ return 0, nil, syscall.EFUCHSIA
+}
+
+func (c *IPConn) readMsg(b, oob []byte) (n, oobn, flags int, addr *IPAddr, err error) {
+ return 0, 0, 0, nil, syscall.EFUCHSIA
+}
+
+func (c *IPConn) writeTo(b []byte, addr *IPAddr) (int, error) {
+ return 0, syscall.EFUCHSIA
+}
+
+func (c *IPConn) writeMsg(b, oob []byte, addr *IPAddr) (n, oobn int, err error) {
+ return 0, 0, syscall.EFUCHSIA
+}
+
+func (sd *sysDialer) dialIP(ctx context.Context, laddr, raddr *IPAddr) (*IPConn, error) {
+ return nil, syscall.EFUCHSIA
+}
+
+func (sl *sysListener) listenIP(ctx context.Context, laddr *IPAddr) (*IPConn, error) {
+ return nil, syscall.EFUCHSIA
+}
diff --git a/src/net/iprawsock_test.go b/src/net/iprawsock_test.go
index 8e3543d..4985e88 100644
--- a/src/net/iprawsock_test.go
+++ b/src/net/iprawsock_test.go
@@ -8,6 +8,7 @@
import (
"reflect"
+ "runtime"
"testing"
)
@@ -88,6 +89,10 @@
}
func TestIPConnLocalName(t *testing.T) {
+ // TODO(TC-149): disabled without further triage. Needs work.
+ if runtime.GOOS == "fuchsia" {
+ t.Skip("network test disabled for GOOS=fuchsia")
+ }
for _, tt := range ipConnLocalNameTests {
if !testableNetwork(tt.net) {
t.Logf("skipping %s test", tt.net)
@@ -105,6 +110,10 @@
}
func TestIPConnRemoteName(t *testing.T) {
+ // TODO(TC-149): disabled without further triage. Needs work.
+ if runtime.GOOS == "fuchsia" {
+ t.Skip("network test disabled for GOOS=fuchsia")
+ }
if !testableNetwork("ip:tcp") {
t.Skip("ip:tcp test")
}
diff --git a/src/net/ipsock_fuchsia.go b/src/net/ipsock_fuchsia.go
new file mode 100644
index 0000000..2fd6775
--- /dev/null
+++ b/src/net/ipsock_fuchsia.go
@@ -0,0 +1,204 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package net
+
+import (
+ "context"
+ "errors"
+ "sync"
+ "syscall"
+ "syscall/zx"
+ "syscall/zx/fdio"
+ "syscall/zx/fidl"
+ "syscall/zx/mxnet"
+ zxnet "syscall/zx/net"
+ "syscall/zx/zxsocket"
+ "time"
+)
+
+func (p *ipStackCapabilities) probe() {
+ p.ipv4Enabled = true
+ p.ipv6Enabled = true
+ p.ipv4MappedIPv6Enabled = true
+}
+
+// A sockaddr represents a TCP, UDP, IP or Unix network endpoint
+// address that can be converted into an fdio sockaddr message.
+type sockaddr interface {
+ Addr
+
+ family() int
+ isWildcard() bool
+ sockaddr(family int) (addr mxnet.Addr, port uint16, zone uint32, err error)
+}
+
+func favoriteAddrFamily(net string, laddr, raddr sockaddr, mode string) (family int, ipv6only bool) {
+ switch net[len(net)-1] {
+ case '4':
+ return syscall.AF_INET, false
+ case '6':
+ return syscall.AF_INET6, true
+ }
+
+ if mode == "listen" && (laddr == nil || laddr.isWildcard()) {
+ if supportsIPv4map() || !supportsIPv4() {
+ return syscall.AF_INET6, false
+ }
+ if laddr == nil {
+ return syscall.AF_INET, false
+ }
+ return laddr.family(), false
+ }
+
+ if (laddr == nil || laddr.family() == syscall.AF_INET) &&
+ (raddr == nil || raddr.family() == syscall.AF_INET) {
+ return syscall.AF_INET, false
+ }
+ return syscall.AF_INET6, false
+}
+
+var socketProvider struct {
+ mu sync.Mutex
+ h zx.Handle
+}
+
+func getSocketProvider() zx.Handle {
+ socketProvider.mu.Lock()
+ defer socketProvider.mu.Unlock()
+ if socketProvider.h == zx.HandleInvalid {
+ if c0, c1, err := zx.NewChannel(0); err == nil {
+ if err := fdio.ServiceConnect("/svc/"+zxnet.SocketProviderName, zx.Handle(c0)); err == nil {
+ socketProvider.h = zx.Handle(c1)
+ }
+ }
+ }
+ return socketProvider.h
+}
+
+func dialFuchsia(ctx context.Context, net string, laddr, raddr sockaddr) (fd *netFD, err error) {
+ family, _ := favoriteAddrFamily(net, laddr, raddr, "dial")
+
+ sotype := syscall.SOCK_STREAM
+ if stringsHasPrefix(net, "udp") {
+ sotype = syscall.SOCK_DGRAM
+ }
+
+ var sp zxnet.SocketProviderInterface
+ // Wait for the network stack to publish the socket device.
+ // See similar logic in zircon/system/ulib/fdio/bsdsocket.c.
+ for i := 0; i < 40; i++ {
+ if h := getSocketProvider(); h.IsValid() {
+ sp = zxnet.SocketProviderInterface(fidl.ChannelProxy{Channel: zx.Channel(h)})
+ break
+ }
+ time.Sleep(250 * time.Millisecond)
+ }
+ code, s, err := sp.Socket(int16(family), int16(sotype), syscall.IPPROTO_IP)
+ if err != nil {
+ return nil, err
+ }
+ if code != 0 {
+ return nil, syscall.Errno(code)
+ }
+ sock := zxsocket.NewSocket(s)
+ if sotype == syscall.SOCK_DGRAM {
+ sock.SetDgram()
+ }
+
+ fd = newFD(sock, family, sotype, net)
+ if laddr != nil {
+ addr, port, zone, err := laddr.sockaddr(family)
+ if err != nil {
+ return nil, err
+ }
+ if addr != "" || port != 0 {
+ b := make([]byte, mxnet.SockaddrLen)
+ addrlen, err := mxnet.EncodeSockaddr(b, addr, port, zone)
+ if err != nil {
+ return nil, err
+ }
+ b = b[:addrlen]
+ if code, err := fd.sock.Bind(b); err != nil {
+ return nil, err
+ } else if code != 0 {
+ return nil, syscall.Errno(code)
+ }
+ }
+ if raddr == nil {
+ switch sotype {
+ case syscall.SOCK_STREAM:
+ code, err := fd.sock.Listen(int16(listenerBacklog()))
+ if err != nil {
+ return nil, err
+ }
+ if code != 0 {
+ return nil, syscall.Errno(code)
+ }
+ case syscall.SOCK_DGRAM:
+ return nil, errors.New("net: TODO listen datagram")
+ }
+ }
+ }
+ if raddr != nil {
+ addr, port, zone, err := raddr.sockaddr(family)
+ if err != nil {
+ return nil, err
+ }
+ b := make([]byte, mxnet.SockaddrLen)
+ addrlen, err := mxnet.EncodeSockaddr(b, addr, port, zone)
+ if err != nil {
+ return nil, err
+ }
+ b = b[:addrlen]
+ code, err := fd.sock.Connect(b)
+ if code == syscall.EINPROGRESS {
+ if obs, err := fd.sock.Wait(mxnet.MXSIO_SIGNAL_OUTGOING|zx.SignalSocketPeerClosed, zx.TimensecInfinite); err != nil {
+ return nil, err
+ } else if obs&zx.SignalSocketPeerClosed != 0 {
+ return nil, &zx.Error{Status: zx.ErrPeerClosed, Text: "zxsocket"}
+ } else if obs&mxnet.MXSIO_SIGNAL_OUTGOING != 0 {
+ // fallthrough
+ } else {
+ panic("unreachable")
+ }
+ // Call connect again to learn the result.
+ code, err = fd.sock.Connect(b)
+ }
+ if err != nil {
+ return nil, err
+ }
+ if code != 0 {
+ return nil, syscall.Errno(code)
+ }
+ fd.isConnected = true
+ }
+ fd.setAddr()
+
+ return fd, nil
+}
+
+func ipToSockaddr(family int, ip IP, port int, zone_str string) (addr mxnet.Addr, portres uint16, zone uint32, err error) {
+ switch family {
+ case syscall.AF_INET:
+ if len(ip) == 0 {
+ ip = IPv4zero
+ }
+ ip4 := ip.To4()
+ if ip4 == nil {
+ return "", 0, 0, &AddrError{Err: "non-IPv4 address", Addr: ip.String()}
+ }
+ return mxnet.Addr(ip4)[:4], uint16(port), 0, nil
+ case syscall.AF_INET6:
+ if len(ip) == 0 || ip.Equal(IPv4zero) {
+ ip = IPv6zero
+ }
+ ip6 := ip.To16()
+ if ip6 == nil {
+ return "", 0, 0, &AddrError{Err: "non-IPv6 address", Addr: ip.String()}
+ }
+ return mxnet.Addr(ip6), uint16(port), uint32(zoneCache.index(zone_str)), nil
+ }
+ return "", 0, 0, &AddrError{Err: "invalid address family", Addr: ip.String()}
+}
diff --git a/src/net/ipsock_fuchsia_test.go b/src/net/ipsock_fuchsia_test.go
new file mode 100644
index 0000000..76a666e
--- /dev/null
+++ b/src/net/ipsock_fuchsia_test.go
@@ -0,0 +1,90 @@
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build fuchsia
+
+package net
+
+import (
+ "bytes"
+ "syscall"
+ "syscall/zx/mxnet"
+ "testing"
+)
+
+func TestIPToSockaddr(t *testing.T) {
+ type inArgs struct {
+ family int
+ ip IP
+ port int
+ zone string
+ }
+
+ type want struct {
+ addr mxnet.Addr
+ portres uint16
+ zone uint32
+ err bool
+ }
+
+ tests := []struct {
+ name string
+ in inArgs
+ want want
+ }{
+ {
+ "v4 non-numeric string zone ignored",
+ inArgs{syscall.AF_INET, ParseIP("1.2.3.4"), 6667, "zone"},
+ want{mxnet.Addr([]byte{1, 2, 3, 4}), 6667, 0, false},
+ },
+ {
+ "v4 numeric string zone ignored",
+ inArgs{syscall.AF_INET, ParseIP("1.2.3.4"), 6697, "17"},
+ want{mxnet.Addr([]byte{1, 2, 3, 4}), 6697, 0, false},
+ },
+ {
+ "v4 invalid IP returns error",
+ inArgs{syscall.AF_INET, IP([]byte{1}), 6697, ""},
+ want{"", 0, 0, true},
+ },
+ {
+ "v6 with non-numeric zone ignored",
+ inArgs{syscall.AF_INET6, ParseIP("fe80::1"), 443, "zone"},
+ want{mxnet.Addr([]byte{0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}), 443, 0, false},
+ },
+ {
+ "v6 with numeric zone handled properly",
+ inArgs{syscall.AF_INET6, ParseIP("fe80::1"), 80, "42"},
+ want{mxnet.Addr([]byte{0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}), 80, 42, false},
+ },
+ {
+ "v6 invalid IP returns error",
+ inArgs{syscall.AF_INET6, IP([]byte{1}), 1, ""},
+ want{"", 0, 0, true},
+ },
+ }
+
+ for _, test := range tests {
+ addr, portres, zone, err := ipToSockaddr(test.in.family, test.in.ip, test.in.port, test.in.zone)
+ if test.want.err && err == nil {
+ t.Errorf("test %q returned no error, but an error was expected", test.name)
+ continue
+ } else if !test.want.err && err != nil {
+ t.Errorf("test %q got error %v; no error was expected", test.name, err)
+ continue
+ }
+
+ if !bytes.Equal([]byte(addr), []byte(test.want.addr)) {
+ t.Errorf("test %q got addr %v, wanted %v", test.name, []byte(addr), []byte(test.want.addr))
+ }
+
+ if portres != test.want.portres {
+ t.Errorf("test %q got portres %d, wanted %d", test.name, portres, test.want.portres)
+ }
+
+ if zone != test.want.zone {
+ t.Errorf("test %q got zone %d, wanted %d", test.name, zone, test.want.zone)
+ }
+ }
+}
diff --git a/src/net/listen_test.go b/src/net/listen_test.go
index 6c3f70c..731ff7c 100644
--- a/src/net/listen_test.go
+++ b/src/net/listen_test.go
@@ -63,6 +63,10 @@
// listener with same address family, same listening address and
// same port.
func TestTCPListener(t *testing.T) {
+ // TODO(TC-149): disabled without further triage. Needs work.
+ if runtime.GOOS == "fuchsia" {
+ t.Skip("network test disabled for GOOS=fuchsia")
+ }
switch runtime.GOOS {
case "plan9":
t.Skipf("not supported on %s", runtime.GOOS)
@@ -124,8 +128,9 @@
// listener with same address family, same listening address and
// same port.
func TestUDPListener(t *testing.T) {
+ // TODO(TC-149): disabled without further triage. Needs work.
switch runtime.GOOS {
- case "plan9":
+ case "plan9", "fuchsia":
t.Skipf("not supported on %s", runtime.GOOS)
}
@@ -223,6 +228,10 @@
// On DragonFly BSD, we expect the kernel version of node under test
// to be greater than or equal to 4.4.
func TestDualStackTCPListener(t *testing.T) {
+ // TODO(TC-149): disabled without further triage. Needs work.
+ if runtime.GOOS == "fuchsia" {
+ t.Skip("network test disabled for GOOS=fuchsia")
+ }
switch runtime.GOOS {
case "nacl", "plan9":
t.Skipf("not supported on %s", runtime.GOOS)
@@ -313,8 +322,9 @@
// On DragonFly BSD, we expect the kernel version of node under test
// to be greater than or equal to 4.4.
func TestDualStackUDPListener(t *testing.T) {
+ // TODO(TC-149): disabled without further triage. Needs work.
switch runtime.GOOS {
- case "nacl", "plan9":
+ case "nacl", "plan9", "fuchsia":
t.Skipf("not supported on %s", runtime.GOOS)
}
if !supportsIPv4() || !supportsIPv6() {
@@ -488,8 +498,9 @@
func TestWildWildcardListener(t *testing.T) {
testenv.MustHaveExternalNetwork(t)
+ // TODO(TC-149): disabled without further triage. Needs work.
switch runtime.GOOS {
- case "plan9":
+ case "plan9", "fuchsia":
t.Skipf("not supported on %s", runtime.GOOS)
}
@@ -531,8 +542,9 @@
func TestIPv4MulticastListener(t *testing.T) {
testenv.MustHaveExternalNetwork(t)
+ // TODO(TC-149): disabled without further triage. Needs work.
switch runtime.GOOS {
- case "android", "nacl", "plan9":
+ case "android", "nacl", "plan9", "fuchsia":
t.Skipf("not supported on %s", runtime.GOOS)
case "solaris":
t.Skipf("not supported on solaris, see golang.org/issue/7399")
@@ -606,8 +618,9 @@
func TestIPv6MulticastListener(t *testing.T) {
testenv.MustHaveExternalNetwork(t)
+ // TODO(TC-149): disabled without further triage. Needs work.
switch runtime.GOOS {
- case "plan9":
+ case "plan9", "fuchsia":
t.Skipf("not supported on %s", runtime.GOOS)
case "solaris":
t.Skipf("not supported on solaris, see issue 7399")
@@ -701,6 +714,11 @@
// Issue 21856.
func TestClosingListener(t *testing.T) {
+ // TODO(TC-149): disabled without further triage. Needs work.
+ if runtime.GOOS == "fuchsia" {
+ t.Skip("network test disabled for GOOS=fuchsia")
+ }
+
ln, err := newLocalListener("tcp")
if err != nil {
t.Fatal(err)
@@ -733,7 +751,7 @@
func TestListenConfigControl(t *testing.T) {
switch runtime.GOOS {
- case "nacl", "plan9":
+ case "fuchsia", "nacl", "plan9":
t.Skipf("not supported on %s", runtime.GOOS)
}
diff --git a/src/net/lookup_fuchsia.go b/src/net/lookup_fuchsia.go
new file mode 100644
index 0000000..0968082
--- /dev/null
+++ b/src/net/lookup_fuchsia.go
@@ -0,0 +1,324 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build darwin dragonfly freebsd fuchsia linux netbsd openbsd solaris
+
+package net
+
+import (
+ "context"
+ "internal/bytealg"
+ "sync"
+
+ "internal/x/net/dns/dnsmessage"
+)
+
+var onceReadProtocols sync.Once
+
+// readProtocols loads contents of /etc/protocols into protocols map
+// for quick access.
+func readProtocols() {
+ file, err := open("/etc/protocols")
+ if err != nil {
+ return
+ }
+ defer file.close()
+
+ for line, ok := file.readLine(); ok; line, ok = file.readLine() {
+ // tcp 6 TCP # transmission control protocol
+ if i := bytealg.IndexByteString(line, '#'); i >= 0 {
+ line = line[0:i]
+ }
+ f := getFields(line)
+ if len(f) < 2 {
+ continue
+ }
+ if proto, _, ok := dtoi(f[1]); ok {
+ if _, ok := protocols[f[0]]; !ok {
+ protocols[f[0]] = proto
+ }
+ for _, alias := range f[2:] {
+ if _, ok := protocols[alias]; !ok {
+ protocols[alias] = proto
+ }
+ }
+ }
+ }
+}
+
+// lookupProtocol looks up IP protocol name in /etc/protocols and
+// returns correspondent protocol number.
+func lookupProtocol(_ context.Context, name string) (int, error) {
+ onceReadProtocols.Do(readProtocols)
+ return lookupProtocolMap(name)
+}
+
+func (r *Resolver) dial(ctx context.Context, network, server string) (Conn, error) {
+ // Calling Dial here is scary -- we have to be sure not to
+ // dial a name that will require a DNS lookup, or Dial will
+ // call back here to translate it. The DNS config parser has
+ // already checked that all the cfg.servers are IP
+ // addresses, which Dial will use without a DNS lookup.
+ var c Conn
+ var err error
+ if r != nil && r.Dial != nil {
+ c, err = r.Dial(ctx, network, server)
+ } else {
+ var d Dialer
+ c, err = d.DialContext(ctx, network, server)
+ }
+ if err != nil {
+ return nil, mapErr(err)
+ }
+ return c, nil
+}
+
+func (r *Resolver) lookupHost(ctx context.Context, host string) (addrs []string, err error) {
+ order := systemConf().hostLookupOrder(r, host)
+ if !r.preferGo() && order == hostLookupCgo {
+ if addrs, err, ok := cgoLookupHost(ctx, host); ok {
+ return addrs, err
+ }
+ // cgo not available (or netgo); fall back to Go's DNS resolver
+ order = hostLookupFilesDNS
+ }
+ return r.goLookupHostOrder(ctx, host, order)
+}
+
+func (r *Resolver) lookupIP(ctx context.Context, network, host string) (addrs []IPAddr, err error) {
+ if r.preferGo() {
+ return r.goLookupIP(ctx, host)
+ }
+ order := systemConf().hostLookupOrder(r, host)
+ if order == hostLookupCgo {
+ if addrs, err, ok := cgoLookupIP(ctx, network, host); ok {
+ return addrs, err
+ }
+ // cgo not available (or netgo); fall back to Go's DNS resolver
+ order = hostLookupFilesDNS
+ }
+ ips, _, err := r.goLookupIPCNAMEOrder(ctx, host, order)
+ return ips, err
+}
+
+func (r *Resolver) lookupPort(ctx context.Context, network, service string) (int, error) {
+ if !r.preferGo() && systemConf().canUseCgo() {
+ if port, err, ok := cgoLookupPort(ctx, network, service); ok {
+ if err != nil {
+ // Issue 18213: if cgo fails, first check to see whether we
+ // have the answer baked-in to the net package.
+ if port, err := goLookupPort(network, service); err == nil {
+ return port, nil
+ }
+ }
+ return port, err
+ }
+ }
+ return goLookupPort(network, service)
+}
+
+func (r *Resolver) lookupCNAME(ctx context.Context, name string) (string, error) {
+ if !r.preferGo() && systemConf().canUseCgo() {
+ if cname, err, ok := cgoLookupCNAME(ctx, name); ok {
+ return cname, err
+ }
+ }
+ return r.goLookupCNAME(ctx, name)
+}
+
+func (r *Resolver) lookupSRV(ctx context.Context, service, proto, name string) (string, []*SRV, error) {
+ var target string
+ if service == "" && proto == "" {
+ target = name
+ } else {
+ target = "_" + service + "._" + proto + "." + name
+ }
+ p, server, err := r.lookup(ctx, target, dnsmessage.TypeSRV)
+ if err != nil {
+ return "", nil, err
+ }
+ var srvs []*SRV
+ var cname dnsmessage.Name
+ for {
+ h, err := p.AnswerHeader()
+ if err == dnsmessage.ErrSectionDone {
+ break
+ }
+ if err != nil {
+ return "", nil, &DNSError{
+ Err: "cannot unmarshal DNS message",
+ Name: name,
+ Server: server,
+ }
+ }
+ if h.Type != dnsmessage.TypeSRV {
+ if err := p.SkipAnswer(); err != nil {
+ return "", nil, &DNSError{
+ Err: "cannot unmarshal DNS message",
+ Name: name,
+ Server: server,
+ }
+ }
+ continue
+ }
+ if cname.Length == 0 && h.Name.Length != 0 {
+ cname = h.Name
+ }
+ srv, err := p.SRVResource()
+ if err != nil {
+ return "", nil, &DNSError{
+ Err: "cannot unmarshal DNS message",
+ Name: name,
+ Server: server,
+ }
+ }
+ srvs = append(srvs, &SRV{Target: srv.Target.String(), Port: srv.Port, Priority: srv.Priority, Weight: srv.Weight})
+ }
+ byPriorityWeight(srvs).sort()
+ return cname.String(), srvs, nil
+}
+
+func (r *Resolver) lookupMX(ctx context.Context, name string) ([]*MX, error) {
+ p, server, err := r.lookup(ctx, name, dnsmessage.TypeMX)
+ if err != nil {
+ return nil, err
+ }
+ var mxs []*MX
+ for {
+ h, err := p.AnswerHeader()
+ if err == dnsmessage.ErrSectionDone {
+ break
+ }
+ if err != nil {
+ return nil, &DNSError{
+ Err: "cannot unmarshal DNS message",
+ Name: name,
+ Server: server,
+ }
+ }
+ if h.Type != dnsmessage.TypeMX {
+ if err := p.SkipAnswer(); err != nil {
+ return nil, &DNSError{
+ Err: "cannot unmarshal DNS message",
+ Name: name,
+ Server: server,
+ }
+ }
+ continue
+ }
+ mx, err := p.MXResource()
+ if err != nil {
+ return nil, &DNSError{
+ Err: "cannot unmarshal DNS message",
+ Name: name,
+ Server: server,
+ }
+ }
+ mxs = append(mxs, &MX{Host: mx.MX.String(), Pref: mx.Pref})
+
+ }
+ byPref(mxs).sort()
+ return mxs, nil
+}
+
+func (r *Resolver) lookupNS(ctx context.Context, name string) ([]*NS, error) {
+ p, server, err := r.lookup(ctx, name, dnsmessage.TypeNS)
+ if err != nil {
+ return nil, err
+ }
+ var nss []*NS
+ for {
+ h, err := p.AnswerHeader()
+ if err == dnsmessage.ErrSectionDone {
+ break
+ }
+ if err != nil {
+ return nil, &DNSError{
+ Err: "cannot unmarshal DNS message",
+ Name: name,
+ Server: server,
+ }
+ }
+ if h.Type != dnsmessage.TypeNS {
+ if err := p.SkipAnswer(); err != nil {
+ return nil, &DNSError{
+ Err: "cannot unmarshal DNS message",
+ Name: name,
+ Server: server,
+ }
+ }
+ continue
+ }
+ ns, err := p.NSResource()
+ if err != nil {
+ return nil, &DNSError{
+ Err: "cannot unmarshal DNS message",
+ Name: name,
+ Server: server,
+ }
+ }
+ nss = append(nss, &NS{Host: ns.NS.String()})
+ }
+ return nss, nil
+}
+
+func (r *Resolver) lookupTXT(ctx context.Context, name string) ([]string, error) {
+ p, server, err := r.lookup(ctx, name, dnsmessage.TypeTXT)
+ if err != nil {
+ return nil, err
+ }
+ var txts []string
+ for {
+ h, err := p.AnswerHeader()
+ if err == dnsmessage.ErrSectionDone {
+ break
+ }
+ if err != nil {
+ return nil, &DNSError{
+ Err: "cannot unmarshal DNS message",
+ Name: name,
+ Server: server,
+ }
+ }
+ if h.Type != dnsmessage.TypeTXT {
+ if err := p.SkipAnswer(); err != nil {
+ return nil, &DNSError{
+ Err: "cannot unmarshal DNS message",
+ Name: name,
+ Server: server,
+ }
+ }
+ continue
+ }
+ txt, err := p.TXTResource()
+ if err != nil {
+ return nil, &DNSError{
+ Err: "cannot unmarshal DNS message",
+ Name: name,
+ Server: server,
+ }
+ }
+ if len(txts) == 0 {
+ txts = txt.TXT
+ } else {
+ txts = append(txts, txt.TXT...)
+ }
+ }
+ return txts, nil
+}
+
+func (r *Resolver) lookupAddr(ctx context.Context, addr string) ([]string, error) {
+ if !r.preferGo() && systemConf().canUseCgo() {
+ if ptrs, err, ok := cgoLookupPTR(ctx, addr); ok {
+ return ptrs, err
+ }
+ }
+ return r.goLookupPTR(ctx, addr)
+}
+
+// concurrentThreadsLimit returns the number of threads we permit to
+// run concurrently doing DNS lookups via cgo.
+func concurrentThreadsLimit() int {
+ return 500
+}
diff --git a/src/net/lookup_test.go b/src/net/lookup_test.go
index 28a895e..871e17a 100644
--- a/src/net/lookup_test.go
+++ b/src/net/lookup_test.go
@@ -751,6 +751,11 @@
}
func TestLookupPort(t *testing.T) {
+ // TODO(TC-149): disabled without further triage. Needs work.
+ if runtime.GOOS == "fuchsia" {
+ t.Skip("network test disabled for GOOS=fuchsia")
+ }
+
// See https://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.xhtml
//
// Please be careful about adding new test cases.
@@ -809,6 +814,10 @@
// Like TestLookupPort but with minimal tests that should always pass
// because the answers are baked-in to the net package.
func TestLookupPort_Minimal(t *testing.T) {
+ // TODO(TC-149): disabled without further triage. Needs work.
+ if runtime.GOOS == "fuchsia" {
+ t.Skip("network test disabled for GOOS=fuchsia")
+ }
type test struct {
network string
name string
diff --git a/src/net/main_fuchsia_test.go b/src/net/main_fuchsia_test.go
new file mode 100644
index 0000000..b266361
--- /dev/null
+++ b/src/net/main_fuchsia_test.go
@@ -0,0 +1,20 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build fuchsia
+
+package net
+
+func installTestHooks() {
+}
+
+func uninstallTestHooks() {
+}
+
+// forceCloseSockets must be called only from TestMain.
+func forceCloseSockets() {
+ for s := range sw.Sockets() {
+ closeFunc(s)
+ }
+}
diff --git a/src/net/main_test.go b/src/net/main_test.go
index 85a269d..0be80c4 100644
--- a/src/net/main_test.go
+++ b/src/net/main_test.go
@@ -46,6 +46,10 @@
)
func TestMain(m *testing.M) {
+ if runtime.GOOS == "fuchsia" {
+ flag.CommandLine.Set("test.v", "true")
+ }
+
setupTestData()
installTestHooks()
diff --git a/src/net/net_test.go b/src/net/net_test.go
index 2b5845b..715db51 100644
--- a/src/net/net_test.go
+++ b/src/net/net_test.go
@@ -19,6 +19,10 @@
)
func TestCloseRead(t *testing.T) {
+ // TODO(TC-149): disabled without further triage. Needs work.
+ if runtime.GOOS == "fuchsia" {
+ t.Skip("network test disabled for GOOS=fuchsia")
+ }
switch runtime.GOOS {
case "plan9":
t.Skipf("not supported on %s", runtime.GOOS)
@@ -71,8 +75,9 @@
}
func TestCloseWrite(t *testing.T) {
+ // TODO(TC-149): disabled without further triage. Needs work.
switch runtime.GOOS {
- case "nacl", "plan9":
+ case "nacl", "plan9", "fuchsia":
t.Skipf("not supported on %s", runtime.GOOS)
}
@@ -201,6 +206,10 @@
}
func TestListenerClose(t *testing.T) {
+ if runtime.GOOS == "fuchsia" {
+ t.Skip("Time based test is unstable on Fuchsia CI")
+ }
+
for _, network := range []string{"tcp", "unix", "unixpacket"} {
if !testableNetwork(network) {
t.Logf("skipping %s test", network)
@@ -255,6 +264,10 @@
}
func TestPacketConnClose(t *testing.T) {
+ // TODO(TC-149): disabled without further triage. Needs work.
+ if runtime.GOOS == "fuchsia" {
+ t.Skip("network test disabled for GOOS=fuchsia")
+ }
for _, network := range []string{"udp", "unixgram"} {
if !testableNetwork(network) {
t.Logf("skipping %s test", network)
@@ -313,6 +326,10 @@
// See golang.org/issue/6163, golang.org/issue/6987.
func TestAcceptIgnoreAbortedConnRequest(t *testing.T) {
+ // TODO(TC-149): disabled without further triage. Needs work.
+ if runtime.GOOS == "fuchsia" {
+ t.Skip("network test disabled for GOOS=fuchsia")
+ }
switch runtime.GOOS {
case "plan9":
t.Skipf("%s does not have full support of socktest", runtime.GOOS)
@@ -460,6 +477,10 @@
// See golang.org/cl/30164 which documented this. The net/http package
// depends on this.
func TestReadTimeoutUnblocksRead(t *testing.T) {
+ // TODO(TC-149): disabled without further triage. Needs work.
+ if runtime.GOOS == "fuchsia" {
+ t.Skip("network test disabled for GOOS=fuchsia")
+ }
serverDone := make(chan struct{})
server := func(cs *TCPConn) error {
defer close(serverDone)
@@ -503,6 +524,10 @@
// Issue 17695: verify that a blocked Read is woken up by a Close.
func TestCloseUnblocksRead(t *testing.T) {
+ // TODO(TC-149): disabled without further triage. Needs work.
+ if runtime.GOOS == "fuchsia" {
+ t.Skip("network test disabled for GOOS=fuchsia")
+ }
t.Parallel()
server := func(cs *TCPConn) error {
// Give the client time to get stuck in a Read:
@@ -522,6 +547,10 @@
// Issue 24808: verify that ECONNRESET is not temporary for read.
func TestNotTemporaryRead(t *testing.T) {
+ // TODO(TC-149): disabled without further triage. Needs work.
+ if runtime.GOOS == "fuchsia" {
+ t.Skip("network test disabled for GOOS=fuchsia")
+ }
if runtime.GOOS == "freebsd" {
testenv.SkipFlaky(t, 25289)
}
diff --git a/src/net/nss.go b/src/net/nss.go
index 96b9cdd..29caa46 100644
--- a/src/net/nss.go
+++ b/src/net/nss.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris
+// +build aix darwin dragonfly freebsd fuchsia linux netbsd openbsd solaris
package net
diff --git a/src/net/packetconn_test.go b/src/net/packetconn_test.go
index a377d33..eafad0a 100644
--- a/src/net/packetconn_test.go
+++ b/src/net/packetconn_test.go
@@ -11,6 +11,7 @@
import (
"os"
+ "runtime"
"testing"
"time"
)
@@ -38,6 +39,10 @@
}
func TestPacketConn(t *testing.T) {
+ // TODO(TC-149): disabled without further triage. Needs work.
+ if runtime.GOOS == "fuchsia" {
+ t.Skip("network test disabled for GOOS=fuchsia")
+ }
closer := func(c PacketConn, net, addr1, addr2 string) {
c.Close()
switch net {
@@ -92,6 +97,10 @@
}
func TestConnAndPacketConn(t *testing.T) {
+ // TODO(TC-149): disabled without further triage. Needs work.
+ if runtime.GOOS == "fuchsia" {
+ t.Skip("network test disabled for GOOS=fuchsia")
+ }
closer := func(c PacketConn, net, addr1, addr2 string) {
c.Close()
switch net {
diff --git a/src/net/parse_test.go b/src/net/parse_test.go
index c5f8bfd..ffe4d12 100644
--- a/src/net/parse_test.go
+++ b/src/net/parse_test.go
@@ -14,7 +14,7 @@
func TestReadLine(t *testing.T) {
// /etc/services file does not exist on android, plan9, windows.
switch runtime.GOOS {
- case "android", "plan9", "windows":
+ case "android", "plan9", "windows", "fuchsia":
t.Skipf("not supported on %s", runtime.GOOS)
}
filename := "/etc/services" // a nice big file
diff --git a/src/net/platform_test.go b/src/net/platform_test.go
index 7e9ad70..9cdcc0c 100644
--- a/src/net/platform_test.go
+++ b/src/net/platform_test.go
@@ -35,7 +35,7 @@
}
case "unix", "unixgram":
switch runtime.GOOS {
- case "android", "nacl", "plan9", "windows":
+ case "android", "fuchsia", "nacl", "plan9", "windows":
return false
case "aix":
// Unix network isn't properly working on AIX 7.2 with Technical Level < 2
@@ -54,7 +54,7 @@
}
case "unixpacket":
switch runtime.GOOS {
- case "aix", "android", "darwin", "nacl", "plan9", "windows":
+ case "aix", "android", "darwin", "fuchsia", "nacl", "plan9", "windows":
return false
case "netbsd":
// It passes on amd64 at least. 386 fails (Issue 22927). arm is unknown.
diff --git a/src/net/port_fuchsia.go b/src/net/port_fuchsia.go
new file mode 100644
index 0000000..c8438b1
--- /dev/null
+++ b/src/net/port_fuchsia.go
@@ -0,0 +1,11 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package net
+
+import "errors"
+
+func goLookupPort(network, service string) (port int, err error) {
+ return -1, errors.New("net: port lookup not supported yet on fuchsia")
+}
diff --git a/src/net/protoconn_test.go b/src/net/protoconn_test.go
index 9f6772c..266657f 100644
--- a/src/net/protoconn_test.go
+++ b/src/net/protoconn_test.go
@@ -23,6 +23,10 @@
// golang.org/x/net/icmp
func TestTCPListenerSpecificMethods(t *testing.T) {
+ // TODO(TC-149): disabled without further triage. Needs work.
+ if runtime.GOOS == "fuchsia" {
+ t.Skip("network test disabled for GOOS=fuchsia")
+ }
switch runtime.GOOS {
case "plan9":
t.Skipf("not supported on %s", runtime.GOOS)
@@ -115,6 +119,10 @@
}
func TestUDPConnSpecificMethods(t *testing.T) {
+ // TODO(TC-149): disabled without further triage. Needs work.
+ if runtime.GOOS == "fuchsia" {
+ t.Skip("network test disabled for GOOS=fuchsia")
+ }
la, err := ResolveUDPAddr("udp4", "127.0.0.1:0")
if err != nil {
t.Fatal(err)
@@ -164,6 +172,10 @@
}
func TestIPConnSpecificMethods(t *testing.T) {
+ // TODO(TC-149): disabled without further triage. Needs work.
+ if runtime.GOOS == "fuchsia" {
+ t.Skip("network test disabled for GOOS=fuchsia")
+ }
if os.Getuid() != 0 {
t.Skip("must be root")
}
@@ -203,6 +215,10 @@
}
func TestUnixListenerSpecificMethods(t *testing.T) {
+ // TODO(TC-149): disabled without further triage. Needs work.
+ if runtime.GOOS == "fuchsia" {
+ t.Skip("network test disabled for GOOS=fuchsia")
+ }
if !testableNetwork("unix") {
t.Skip("unix test")
}
@@ -244,6 +260,10 @@
}
func TestUnixConnSpecificMethods(t *testing.T) {
+ // TODO(TC-149): disabled without further triage. Needs work.
+ if runtime.GOOS == "fuchsia" {
+ t.Skip("network test disabled for GOOS=fuchsia")
+ }
if !testableNetwork("unixgram") {
t.Skip("unixgram test")
}
diff --git a/src/net/rawconn_stub_test.go b/src/net/rawconn_stub_test.go
index 0a033c1..9c18a62 100644
--- a/src/net/rawconn_stub_test.go
+++ b/src/net/rawconn_stub_test.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build js,wasm nacl plan9
+// +build fuchsia js,wasm nacl plan9
package net
diff --git a/src/net/rawconn_test.go b/src/net/rawconn_test.go
index 11900df..e01318d 100644
--- a/src/net/rawconn_test.go
+++ b/src/net/rawconn_test.go
@@ -15,7 +15,7 @@
func TestRawConnReadWrite(t *testing.T) {
switch runtime.GOOS {
- case "nacl", "plan9":
+ case "fuchsia", "nacl", "plan9":
t.Skipf("not supported on %s", runtime.GOOS)
}
@@ -175,7 +175,7 @@
func TestRawConnControl(t *testing.T) {
switch runtime.GOOS {
- case "nacl", "plan9":
+ case "fuchsia", "nacl", "plan9":
t.Skipf("not supported on %s", runtime.GOOS)
}
diff --git a/src/net/sendfile_test.go b/src/net/sendfile_test.go
index 911e613..f856b8c 100644
--- a/src/net/sendfile_test.go
+++ b/src/net/sendfile_test.go
@@ -27,6 +27,10 @@
)
func TestSendfile(t *testing.T) {
+ // TODO(TC-149): disabled without further triage. Needs work.
+ if runtime.GOOS == "fuchsia" {
+ t.Skip("network test disabled for GOOS=fuchsia")
+ }
ln, err := newLocalListener("tcp")
if err != nil {
t.Fatal(err)
@@ -97,6 +101,11 @@
}
func TestSendfileParts(t *testing.T) {
+ // TODO(TC-149): disabled without further triage. Needs work.
+ if runtime.GOOS == "fuchsia" {
+ t.Skip("network test disabled for GOOS=fuchsia")
+ }
+
ln, err := newLocalListener("tcp")
if err != nil {
t.Fatal(err)
@@ -155,6 +164,11 @@
}
func TestSendfileSeeked(t *testing.T) {
+ // TODO(TC-149): disabled without further triage. Needs work.
+ if runtime.GOOS == "fuchsia" {
+ t.Skip("network test disabled for GOOS=fuchsia")
+ }
+
ln, err := newLocalListener("tcp")
if err != nil {
t.Fatal(err)
@@ -218,7 +232,7 @@
// Test that sendfile doesn't put a pipe into blocking mode.
func TestSendfilePipe(t *testing.T) {
switch runtime.GOOS {
- case "nacl", "plan9", "windows":
+ case "fuchsia", "nacl", "plan9", "windows":
// These systems don't support deadlines on pipes.
t.Skipf("skipping on %s", runtime.GOOS)
}
diff --git a/src/net/server_test.go b/src/net/server_test.go
index 1608beb..4bec5ae 100644
--- a/src/net/server_test.go
+++ b/src/net/server_test.go
@@ -8,6 +8,7 @@
import (
"os"
+ "runtime"
"testing"
)
@@ -53,6 +54,10 @@
// TestTCPServer tests concurrent accept-read-write servers.
func TestTCPServer(t *testing.T) {
+ // TODO(TC-149): disabled without further triage. Needs work.
+ if runtime.GOOS == "fuchsia" {
+ t.Skip("network test disabled for GOOS=fuchsia")
+ }
const N = 3
for i, tt := range tcpServerTests {
@@ -137,6 +142,10 @@
// TestUnixAndUnixpacketServer tests concurrent accept-read-write
// servers
func TestUnixAndUnixpacketServer(t *testing.T) {
+ // TODO(TC-149): disabled without further triage. Needs work.
+ if runtime.GOOS == "fuchsia" {
+ t.Skip("network test disabled for GOOS=fuchsia")
+ }
const N = 3
for i, tt := range unixAndUnixpacketServerTests {
@@ -251,6 +260,10 @@
}
func TestUDPServer(t *testing.T) {
+ // TODO(TC-149): disabled without further triage. Needs work.
+ if runtime.GOOS == "fuchsia" {
+ t.Skip("network test disabled for GOOS=fuchsia")
+ }
for i, tt := range udpServerTests {
if !testableListenArgs(tt.snet, tt.saddr, tt.taddr) {
t.Logf("skipping %s test", tt.snet+" "+tt.saddr+"<-"+tt.taddr)
@@ -329,6 +342,10 @@
}
func TestUnixgramServer(t *testing.T) {
+ // TODO(TC-149): disabled without further triage. Needs work.
+ if runtime.GOOS == "fuchsia" {
+ t.Skip("network test disabled for GOOS=fuchsia")
+ }
for i, tt := range unixgramServerTests {
if !testableListenArgs("unixgram", tt.saddr, "") {
t.Logf("skipping %s test", "unixgram "+tt.saddr+"<-"+tt.caddr)
diff --git a/src/net/sock_stub.go b/src/net/sock_stub.go
index bbce61b..e91285e 100644
--- a/src/net/sock_stub.go
+++ b/src/net/sock_stub.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build aix nacl js,wasm solaris
+// +build aix nacl js,wasm solaris fuchsia
package net
diff --git a/src/net/sockopt_stub.go b/src/net/sockopt_stub.go
index bc06675..7240cac 100644
--- a/src/net/sockopt_stub.go
+++ b/src/net/sockopt_stub.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build nacl js,wasm
+// +build nacl js,wasm fuchsia
package net
diff --git a/src/net/tcpsock_fuchsia.go b/src/net/tcpsock_fuchsia.go
new file mode 100644
index 0000000..1fd7497
--- /dev/null
+++ b/src/net/tcpsock_fuchsia.go
@@ -0,0 +1,85 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package net
+
+import (
+ "context"
+ "io"
+ "os"
+ "syscall"
+ "syscall/zx/mxnet"
+)
+
+func (a *TCPAddr) encode() ([]byte, error) { // TODO remove
+ b := make([]byte, mxnet.SockaddrLen)
+ _, err := mxnet.EncodeSockaddr(b, mxnet.Addr(a.IP), uint16(a.Port), uint32(zoneCache.index(a.Zone)))
+ return b, err
+}
+
+func (a *TCPAddr) family() int {
+ if a == nil || len(a.IP) <= IPv4len {
+ return syscall.AF_INET
+ }
+ if a.IP.To4() != nil {
+ return syscall.AF_INET
+ }
+ return syscall.AF_INET6
+}
+
+func (a *TCPAddr) sockaddr(family int) (addr mxnet.Addr, port uint16, zone uint32, err error) {
+ if a == nil {
+ return "", 0, 0, nil
+ }
+ return ipToSockaddr(family, a.IP, a.Port, a.Zone)
+}
+
+func (c *TCPConn) readFrom(r io.Reader) (int64, error) {
+ return genericReadFrom(c, r)
+}
+
+func (sd *sysDialer) dialTCP(ctx context.Context, laddr, raddr *TCPAddr) (*TCPConn, error) {
+ if testHookDialTCP != nil {
+ return testHookDialTCP(ctx, sd.network, laddr, raddr)
+ }
+ return sd.doDialTCP(ctx, laddr, raddr)
+}
+
+func (sd *sysDialer) doDialTCP(ctx context.Context, laddr, raddr *TCPAddr) (*TCPConn, error) {
+ switch sd.network {
+ case "tcp", "tcp4", "tcp6":
+ default:
+ return nil, UnknownNetworkError(sd.network)
+ }
+ if raddr == nil {
+ return nil, errMissingAddress
+ }
+ fd, err := dialFuchsia(ctx, sd.network, laddr, raddr)
+ if err != nil {
+ return nil, err
+ }
+ return newTCPConn(fd), nil
+}
+
+func (ln *TCPListener) ok() bool { return ln != nil && ln.fd != nil }
+
+func (ln *TCPListener) accept() (*TCPConn, error) {
+ fd, err := ln.fd.accept()
+ if err != nil {
+ return nil, err
+ }
+ return newTCPConn(fd), nil
+}
+
+func (ln *TCPListener) close() error { return ln.fd.Close() }
+
+func (ln *TCPListener) file() (*os.File, error) { return ln.fd.dup() }
+
+func (sl *sysListener) listenTCP(ctx context.Context, laddr *TCPAddr) (*TCPListener, error) {
+ fd, err := dialFuchsia(ctx, sl.network, laddr, nil)
+ if err != nil {
+ return nil, err
+ }
+ return &TCPListener{fd}, nil
+}
diff --git a/src/net/tcpsock_test.go b/src/net/tcpsock_test.go
index 36d2ccb..4a520d9 100644
--- a/src/net/tcpsock_test.go
+++ b/src/net/tcpsock_test.go
@@ -328,6 +328,10 @@
}
func TestResolveTCPAddr(t *testing.T) {
+ // TODO(TC-149): disabled without further triage. Needs work.
+ if runtime.GOOS == "fuchsia" {
+ t.Skip("network test disabled for GOOS=fuchsia")
+ }
origTestHookLookupIP := testHookLookupIP
defer func() { testHookLookupIP = origTestHookLookupIP }()
testHookLookupIP = lookupLocalhost
@@ -428,6 +432,11 @@
}
func TestTCPConcurrentAccept(t *testing.T) {
+ // TODO(TC-149): disabled without further triage. Needs work.
+ if runtime.GOOS == "fuchsia" {
+ t.Skip("network test disabled for GOOS=fuchsia")
+ }
+
defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(4))
ln, err := Listen("tcp", "127.0.0.1:0")
if err != nil {
@@ -470,6 +479,10 @@
}
func TestTCPReadWriteAllocs(t *testing.T) {
+ // TODO(TC-149): disabled without further triage. Needs work.
+ if runtime.GOOS == "fuchsia" {
+ t.Skip("network test disabled for GOOS=fuchsia")
+ }
switch runtime.GOOS {
case "plan9":
// The implementation of asynchronous cancelable
@@ -543,6 +556,10 @@
}
func TestTCPStress(t *testing.T) {
+ // TODO(TC-149): disabled without further triage. Needs work.
+ if runtime.GOOS == "fuchsia" {
+ t.Skip("network test disabled for GOOS=fuchsia")
+ }
const conns = 2
const msgLen = 512
msgs := int(1e4)
@@ -625,6 +642,10 @@
}
func TestTCPSelfConnect(t *testing.T) {
+ // TODO(TC-149): disabled without further triage. Needs work.
+ if runtime.GOOS == "fuchsia" {
+ t.Skip("network test disabled for GOOS=fuchsia")
+ }
if runtime.GOOS == "windows" {
// TODO(brainman): do not know why it hangs.
t.Skip("known-broken test on windows")
@@ -674,6 +695,10 @@
// Test that >32-bit reads work on 64-bit systems.
// On 32-bit systems this tests that maxint reads work.
func TestTCPBig(t *testing.T) {
+ // TODO(TC-149): disabled without further triage. Needs work.
+ if runtime.GOOS == "fuchsia" {
+ t.Skip("network test disabled for GOOS=fuchsia")
+ }
if !*testTCPBig {
t.Skip("test disabled; use -tcpbig to enable")
}
@@ -727,6 +752,11 @@
}
func TestCopyPipeIntoTCP(t *testing.T) {
+ // TODO(TC-149): disabled without further triage. Needs work.
+ if runtime.GOOS == "fuchsia" {
+ t.Skip("network test disabled for GOOS=fuchsia")
+ }
+
ln, err := newLocalListener("tcp")
if err != nil {
t.Fatal(err)
diff --git a/src/net/tcpsock_unix_test.go b/src/net/tcpsock_unix_test.go
index 2bd591b..65d0a96 100644
--- a/src/net/tcpsock_unix_test.go
+++ b/src/net/tcpsock_unix_test.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build !js,!plan9,!windows
+// +build !fuchsia,!js,!plan9,!windows
package net
diff --git a/src/net/tcpsockopt_stub.go b/src/net/tcpsockopt_stub.go
index fd7f579..7e23c1f 100644
--- a/src/net/tcpsockopt_stub.go
+++ b/src/net/tcpsockopt_stub.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build nacl js,wasm
+// +build nacl js,wasm fuchsia
package net
diff --git a/src/net/timeout_test.go b/src/net/timeout_test.go
index 9599fa1..7e735b2 100644
--- a/src/net/timeout_test.go
+++ b/src/net/timeout_test.go
@@ -39,6 +39,10 @@
}
func TestDialTimeout(t *testing.T) {
+ // TODO(TC-149): disabled without further triage. Needs work.
+ if runtime.GOOS == "fuchsia" {
+ t.Skip("network test disabled for GOOS=fuchsia")
+ }
// Cannot use t.Parallel - modifies global hooks.
origTestHookDialChannel := testHookDialChannel
defer func() { testHookDialChannel = origTestHookDialChannel }()
@@ -46,7 +50,7 @@
for i, tt := range dialTimeoutTests {
switch runtime.GOOS {
- case "plan9", "windows":
+ case "plan9", "windows", "fuchsia":
testHookDialChannel = func() { time.Sleep(tt.guard) }
if runtime.GOOS == "plan9" {
break
@@ -102,9 +106,17 @@
}
func TestDialTimeoutMaxDuration(t *testing.T) {
+ // TODO(TC-149): disabled without further triage. Needs work.
+ if runtime.GOOS == "fuchsia" {
+ t.Skip("network test disabled for GOOS=fuchsia")
+ }
if runtime.GOOS == "openbsd" {
testenv.SkipFlaky(t, 15157)
}
+ // TODO(TC-149): disabled without further triage. Needs work.
+ if runtime.GOOS == "fuchsia" {
+ t.Skip("network test disabled for GOOS=fuchsia")
+ }
ln, err := newLocalListener("tcp")
if err != nil {
@@ -154,6 +166,10 @@
}
func TestAcceptTimeout(t *testing.T) {
+ // TODO(TC-149): disabled without further triage. Needs work.
+ if runtime.GOOS == "fuchsia" {
+ t.Skip("network test disabled for GOOS=fuchsia")
+ }
testenv.SkipFlaky(t, 17948)
t.Parallel()
@@ -211,6 +227,10 @@
}
func TestAcceptTimeoutMustReturn(t *testing.T) {
+ // TODO(TC-149): disabled without further triage. Needs work.
+ if runtime.GOOS == "fuchsia" {
+ t.Skip("network test disabled for GOOS=fuchsia")
+ }
t.Parallel()
switch runtime.GOOS {
@@ -257,6 +277,10 @@
}
func TestAcceptTimeoutMustNotReturn(t *testing.T) {
+ // TODO(TC-149): disabled without further triage. Needs work.
+ if runtime.GOOS == "fuchsia" {
+ t.Skip("network test disabled for GOOS=fuchsia")
+ }
t.Parallel()
switch runtime.GOOS {
@@ -308,6 +332,10 @@
}
func TestReadTimeout(t *testing.T) {
+ // TODO(TC-149): disabled without further triage. Needs work.
+ if runtime.GOOS == "fuchsia" {
+ t.Skip("network test disabled for GOOS=fuchsia")
+ }
handler := func(ls *localServer, ln Listener) {
c, err := ln.Accept()
if err != nil {
@@ -362,6 +390,10 @@
}
func TestReadTimeoutMustNotReturn(t *testing.T) {
+ // TODO(TC-149): disabled without further triage. Needs work.
+ if runtime.GOOS == "fuchsia" {
+ t.Skip("network test disabled for GOOS=fuchsia")
+ }
t.Parallel()
switch runtime.GOOS {
@@ -432,6 +464,10 @@
}
func TestReadFromTimeout(t *testing.T) {
+ // TODO(TC-149): disabled without further triage. Needs work.
+ if runtime.GOOS == "fuchsia" {
+ t.Skip("network test disabled for GOOS=fuchsia")
+ }
switch runtime.GOOS {
case "nacl":
t.Skipf("not supported on %s", runtime.GOOS) // see golang.org/issue/8916
@@ -505,6 +541,10 @@
}
func TestWriteTimeout(t *testing.T) {
+ // TODO(TC-149): disabled without further triage. Needs work.
+ if runtime.GOOS == "fuchsia" {
+ t.Skip("network test disabled for GOOS=fuchsia")
+ }
t.Parallel()
ln, err := newLocalListener("tcp")
@@ -548,6 +588,10 @@
}
func TestWriteTimeoutMustNotReturn(t *testing.T) {
+ // TODO(TC-149): disabled without further triage. Needs work.
+ if runtime.GOOS == "fuchsia" {
+ t.Skip("network test disabled for GOOS=fuchsia")
+ }
t.Parallel()
switch runtime.GOOS {
@@ -619,6 +663,10 @@
}
func TestWriteToTimeout(t *testing.T) {
+ // TODO(TC-149): disabled without further triage. Needs work.
+ if runtime.GOOS == "fuchsia" {
+ t.Skip("network test disabled for GOOS=fuchsia")
+ }
t.Parallel()
switch runtime.GOOS {
@@ -672,6 +720,10 @@
}
func TestReadTimeoutFluctuation(t *testing.T) {
+ // TODO(TC-149): disabled without further triage. Needs work.
+ if runtime.GOOS == "fuchsia" {
+ t.Skip("network test disabled for GOOS=fuchsia")
+ }
t.Parallel()
ln, err := newLocalListener("tcp")
@@ -705,6 +757,10 @@
}
func TestReadFromTimeoutFluctuation(t *testing.T) {
+ // TODO(TC-149): disabled without further triage. Needs work.
+ if runtime.GOOS == "fuchsia" {
+ t.Skip("network test disabled for GOOS=fuchsia")
+ }
t.Parallel()
c1, err := newLocalPacketListener("udp")
@@ -738,6 +794,10 @@
}
func TestWriteTimeoutFluctuation(t *testing.T) {
+ // TODO(TC-149): disabled without further triage. Needs work.
+ if runtime.GOOS == "fuchsia" {
+ t.Skip("network test disabled for GOOS=fuchsia")
+ }
t.Parallel()
switch runtime.GOOS {
@@ -780,11 +840,19 @@
}
func TestVariousDeadlines(t *testing.T) {
+ // TODO(TC-149): disabled without further triage. Needs work.
+ if runtime.GOOS == "fuchsia" {
+ t.Skip("network test disabled for GOOS=fuchsia")
+ }
t.Parallel()
testVariousDeadlines(t)
}
func TestVariousDeadlines1Proc(t *testing.T) {
+ // TODO(TC-149): disabled without further triage. Needs work.
+ if runtime.GOOS == "fuchsia" {
+ t.Skip("network test disabled for GOOS=fuchsia")
+ }
// Cannot use t.Parallel - modifies global GOMAXPROCS.
if testing.Short() {
t.Skip("skipping in short mode")
@@ -794,6 +862,10 @@
}
func TestVariousDeadlines4Proc(t *testing.T) {
+ // TODO(TC-149): disabled without further triage. Needs work.
+ if runtime.GOOS == "fuchsia" {
+ t.Skip("network test disabled for GOOS=fuchsia")
+ }
// Cannot use t.Parallel - modifies global GOMAXPROCS.
if testing.Short() {
t.Skip("skipping in short mode")
@@ -928,6 +1000,10 @@
// TestReadWriteProlongedTimeout tests concurrent deadline
// modification. Known to cause data races in the past.
func TestReadWriteProlongedTimeout(t *testing.T) {
+ // TODO(TC-149): disabled without further triage. Needs work.
+ if runtime.GOOS == "fuchsia" {
+ t.Skip("network test disabled for GOOS=fuchsia")
+ }
t.Parallel()
switch runtime.GOOS {
@@ -1008,6 +1084,10 @@
}
func TestReadWriteDeadlineRace(t *testing.T) {
+ // TODO(TC-149): disabled without further triage. Needs work.
+ if runtime.GOOS == "fuchsia" {
+ t.Skip("network test disabled for GOOS=fuchsia")
+ }
t.Parallel()
switch runtime.GOOS {
diff --git a/src/net/udpsock_fuchsia.go b/src/net/udpsock_fuchsia.go
new file mode 100644
index 0000000..a0f0fb4
--- /dev/null
+++ b/src/net/udpsock_fuchsia.go
@@ -0,0 +1,92 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package net
+
+import (
+ "context"
+ "syscall"
+ "syscall/zx/mxnet"
+)
+
+func (a *UDPAddr) encode() ([]byte, error) {
+ b := make([]byte, mxnet.SockaddrLen)
+ _, err := mxnet.EncodeSockaddr(b, mxnet.Addr(a.IP), uint16(a.Port), uint32(zoneCache.index(a.Zone)))
+ return b, err
+}
+
+func (a *UDPAddr) family() int {
+ if a == nil || len(a.IP) <= IPv4len {
+ return syscall.AF_INET
+ }
+ if a.IP.To4() != nil {
+ return syscall.AF_INET
+ }
+ return syscall.AF_INET6
+}
+
+func (a *UDPAddr) sockaddr(family int) (addr mxnet.Addr, port uint16, zone uint32, err error) {
+ if a == nil {
+ return "", 0, 0, nil
+ }
+ return ipToSockaddr(family, a.IP, a.Port, a.Zone)
+}
+
+func (c *UDPConn) readFrom(b []byte) (n int, addr *UDPAddr, err error) {
+ panic("TODO readFrom")
+}
+
+func (c *UDPConn) readMsg(b, oob []byte) (n, oobn, flags int, addr *UDPAddr, err error) {
+ n, flags, addrstr, port, err := c.fd.readMsg(b)
+ if err != nil {
+ return 0, 0, 0, nil, err
+ }
+ addr = &UDPAddr{
+ IP: IP(addrstr),
+ Port: int(port),
+ }
+ return n, 0, flags, addr, nil
+}
+
+func (c *UDPConn) writeTo(b []byte, addr *UDPAddr) (int, error) {
+ panic("TODO writeTo")
+}
+
+func (c *UDPConn) writeMsg(b, oob []byte, addr *UDPAddr) (n, oobn int, err error) {
+ if len(oob) > 0 {
+ return 0, 0, syscall.EFUCHSIA
+ }
+ n, err = c.fd.sendMsg(b, string(addr.IP), uint16(addr.Port))
+ return n, 0, err
+}
+
+func (sd *sysDialer) dialUDP(ctx context.Context, laddr, raddr *UDPAddr) (*UDPConn, error) {
+ switch sd.network {
+ case "udp", "udp4", "udp6":
+ default:
+ return nil, UnknownNetworkError(sd.network)
+ }
+ if raddr == nil {
+ return nil, errMissingAddress
+ }
+ var laddrif sockaddr
+ if laddr != nil {
+ laddrif = laddr
+ }
+ fd, err := dialFuchsia(ctx, sd.network, laddrif, raddr)
+ if err != nil {
+ return nil, err
+ }
+ return newUDPConn(fd), nil
+}
+
+const udpHeaderSize = 16*3 + 2*2
+
+func (sl *sysListener) listenUDP(ctx context.Context, laddr *UDPAddr) (*UDPConn, error) {
+ panic("TODO listenUDP")
+}
+
+func (sl *sysListener) listenMulticastUDP(ctx context.Context, ifi *Interface, gaddr *UDPAddr) (*UDPConn, error) {
+ return nil, syscall.EFUCHSIA
+}
diff --git a/src/net/udpsock_test.go b/src/net/udpsock_test.go
index 397b664..f4706e5 100644
--- a/src/net/udpsock_test.go
+++ b/src/net/udpsock_test.go
@@ -15,6 +15,10 @@
)
func BenchmarkUDP6LinkLocalUnicast(b *testing.B) {
+ if runtime.GOOS == "fuchsia" {
+ b.Skip("Fuchsia doesn't implement UDP")
+ }
+
testHookUninstaller.Do(uninstallTestHooks)
if !supportsIPv6() {
@@ -88,6 +92,10 @@
}
func TestResolveUDPAddr(t *testing.T) {
+ // TODO(TC-149): disabled without further triage. Needs work.
+ if runtime.GOOS == "fuchsia" {
+ t.Skip("network test disabled for GOOS=fuchsia")
+ }
origTestHookLookupIP := testHookLookupIP
defer func() { testHookLookupIP = origTestHookLookupIP }()
testHookLookupIP = lookupLocalhost
@@ -108,6 +116,10 @@
}
func TestWriteToUDP(t *testing.T) {
+ // TODO(TC-149): disabled without further triage. Needs work.
+ if runtime.GOOS == "fuchsia" {
+ t.Skip("network test disabled for GOOS=fuchsia")
+ }
switch runtime.GOOS {
case "plan9":
t.Skipf("not supported on %s", runtime.GOOS)
@@ -124,6 +136,10 @@
}
func testWriteToConn(t *testing.T, raddr string) {
+ if runtime.GOOS == "fuchsia" {
+ t.Skip("Fuchsia doesn't implement UDP")
+ }
+
c, err := Dial("udp", raddr)
if err != nil {
t.Fatal(err)
@@ -173,6 +189,10 @@
}
func testWriteToPacketConn(t *testing.T, raddr string) {
+ if runtime.GOOS == "fuchsia" {
+ t.Skip("Fuchsia doesn't implement UDP")
+ }
+
c, err := ListenPacket("udp", "127.0.0.1:0")
if err != nil {
t.Fatal(err)
@@ -241,6 +261,10 @@
}
func TestUDPConnLocalAndRemoteNames(t *testing.T) {
+ // TODO(TC-149): disabled without further triage. Needs work.
+ if runtime.GOOS == "fuchsia" {
+ t.Skip("network test disabled for GOOS=fuchsia")
+ }
for _, laddr := range []string{"", "127.0.0.1:0"} {
c1, err := ListenPacket("udp", "127.0.0.1:0")
if err != nil {
@@ -334,6 +358,10 @@
}
func TestUDPZeroBytePayload(t *testing.T) {
+ // TODO(TC-149): disabled without further triage. Needs work.
+ if runtime.GOOS == "fuchsia" {
+ t.Skip("network test disabled for GOOS=fuchsia")
+ }
switch runtime.GOOS {
case "nacl", "plan9":
t.Skipf("not supported on %s", runtime.GOOS)
@@ -372,6 +400,10 @@
}
func TestUDPZeroByteBuffer(t *testing.T) {
+ // TODO(TC-149): disabled without further triage. Needs work.
+ if runtime.GOOS == "fuchsia" {
+ t.Skip("network test disabled for GOOS=fuchsia")
+ }
switch runtime.GOOS {
case "nacl", "plan9":
t.Skipf("not supported on %s", runtime.GOOS)
@@ -410,7 +442,7 @@
func TestUDPReadSizeError(t *testing.T) {
switch runtime.GOOS {
- case "nacl", "plan9":
+ case "fuchsia", "nacl", "plan9":
t.Skipf("not supported on %s", runtime.GOOS)
}
diff --git a/src/net/unixsock_fuchsia.go b/src/net/unixsock_fuchsia.go
new file mode 100644
index 0000000..1ed9304
--- /dev/null
+++ b/src/net/unixsock_fuchsia.go
@@ -0,0 +1,51 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package net
+
+import (
+ "context"
+ "os"
+ "syscall"
+)
+
+func (c *UnixConn) readFrom(b []byte) (int, *UnixAddr, error) {
+ return 0, nil, syscall.EFUCHSIA
+}
+
+func (c *UnixConn) readMsg(b, oob []byte) (n, oobn, flags int, addr *UnixAddr, err error) {
+ return 0, 0, 0, nil, syscall.EFUCHSIA
+}
+
+func (c *UnixConn) writeTo(b []byte, addr *UnixAddr) (int, error) {
+ return 0, syscall.EFUCHSIA
+}
+
+func (c *UnixConn) writeMsg(b, oob []byte, addr *UnixAddr) (n, oobn int, err error) {
+ return 0, 0, syscall.EFUCHSIA
+}
+
+func (sd *sysDialer) dialUnix(ctx context.Context, laddr, raddr *UnixAddr) (*UnixConn, error) {
+ return nil, syscall.EFUCHSIA
+}
+
+func (ln *UnixListener) accept() (*UnixConn, error) {
+ return nil, syscall.EFUCHSIA
+}
+
+func (ln *UnixListener) close() error {
+ return syscall.EFUCHSIA
+}
+
+func (ln *UnixListener) file() (*os.File, error) {
+ return nil, syscall.EFUCHSIA
+}
+
+func (sl *sysListener) listenUnix(ctx context.Context, laddr *UnixAddr) (*UnixListener, error) {
+ return nil, syscall.EFUCHSIA
+}
+
+func (sl *sysListener) listenUnixgram(ctx context.Context, laddr *UnixAddr) (*UnixConn, error) {
+ return nil, syscall.EFUCHSIA
+}
diff --git a/src/net/unixsock_test.go b/src/net/unixsock_test.go
index 4828990..b725be5 100644
--- a/src/net/unixsock_test.go
+++ b/src/net/unixsock_test.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build !js,!nacl,!plan9,!windows
+// +build !js,!nacl,!plan9,!windows,!fuchsia
package net
diff --git a/src/net/writev_test.go b/src/net/writev_test.go
index c43be84..933c826 100644
--- a/src/net/writev_test.go
+++ b/src/net/writev_test.go
@@ -19,6 +19,10 @@
)
func TestBuffers_read(t *testing.T) {
+ // TODO(TC-149): disabled without further triage. Needs work.
+ if runtime.GOOS == "fuchsia" {
+ t.Skip("network test disabled for GOOS=fuchsia")
+ }
const story = "once upon a time in Gopherland ... "
buffers := Buffers{
[]byte("once "),
@@ -41,6 +45,10 @@
}
func TestBuffers_consume(t *testing.T) {
+ // TODO(TC-149): disabled without further triage. Needs work.
+ if runtime.GOOS == "fuchsia" {
+ t.Skip("network test disabled for GOOS=fuchsia")
+ }
tests := []struct {
in Buffers
consume int64
@@ -92,6 +100,10 @@
}
func TestBuffers_WriteTo(t *testing.T) {
+ // TODO(TC-149): disabled without further triage. Needs work.
+ if runtime.GOOS == "fuchsia" {
+ t.Skip("network test disabled for GOOS=fuchsia")
+ }
for _, name := range []string{"WriteTo", "Copy"} {
for _, size := range []int{0, 10, 1023, 1024, 1025} {
t.Run(fmt.Sprintf("%s/%d", name, size), func(t *testing.T) {
@@ -183,6 +195,10 @@
}
func TestWritevError(t *testing.T) {
+ // TODO(TC-149): disabled without further triage. Needs work.
+ if runtime.GOOS == "fuchsia" {
+ t.Skip("network test disabled for GOOS=fuchsia")
+ }
if runtime.GOOS == "windows" {
t.Skipf("skipping the test: windows does not have problem sending large chunks of data")
}
diff --git a/src/os/dir_unix.go b/src/os/dir_unix.go
index bd99ef4..45c5568 100644
--- a/src/os/dir_unix.go
+++ b/src/os/dir_unix.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build aix darwin,!arm,!arm64 dragonfly freebsd js,wasm linux nacl netbsd openbsd solaris
+// +build aix darwin,!arm,!arm64 dragonfly freebsd fuchsia js,wasm linux nacl netbsd openbsd solaris
package os
diff --git a/src/os/error_fuchsia.go b/src/os/error_fuchsia.go
new file mode 100644
index 0000000..e3a655a
--- /dev/null
+++ b/src/os/error_fuchsia.go
@@ -0,0 +1,47 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build fuchsia
+
+package os
+
+import (
+ "syscall"
+ "syscall/zx"
+)
+
+func isExist(err error) bool {
+ err = underlyingError(err)
+ if err, ok := err.(*zx.Error); ok {
+ return err.Status == zx.ErrAlreadyExists
+ }
+ return err == syscall.EEXIST || err == syscall.ENOTEMPTY || err == ErrExist
+}
+
+func isNotExist(err error) bool {
+ err = underlyingError(err)
+ if err, ok := err.(*zx.Error); ok {
+ return err.Status == zx.ErrNotFound
+ }
+ return err == syscall.ENOENT || err == ErrNotExist
+}
+
+func isPermission(err error) bool {
+ err = underlyingError(err)
+ if err, ok := err.(*zx.Error); ok {
+ return err.Status == zx.ErrAccessDenied
+ }
+ return err == syscall.EACCES || err == syscall.EPERM || err == ErrPermission
+}
+
+func wrapSyscallError(name string, err error) error {
+ if err, ok := err.(*zx.Error); ok {
+ text := name
+ if err.Text != "" {
+ text += ": " + err.Text
+ }
+ return &zx.Error{Status: err.Status, Text: text}
+ }
+ return err
+}
diff --git a/src/os/exec/exec_test.go b/src/os/exec/exec_test.go
index 3e6b7bb..26881e2 100644
--- a/src/os/exec/exec_test.go
+++ b/src/os/exec/exec_test.go
@@ -589,7 +589,7 @@
func TestExtraFiles(t *testing.T) {
testenv.MustHaveExec(t)
- if runtime.GOOS == "windows" {
+ if runtime.GOOS == "windows" || runtime.GOOS == "fuchsia" {
t.Skipf("skipping test on %q", runtime.GOOS)
}
@@ -664,7 +664,7 @@
}
func TestExtraFilesRace(t *testing.T) {
- if runtime.GOOS == "windows" {
+ if runtime.GOOS == "windows" || runtime.GOOS == "fuchsia" {
t.Skip("no operating system support; skipping")
}
listen := func() net.Listener {
diff --git a/src/os/exec/lp_unix.go b/src/os/exec/lp_unix.go
index 799e0b4..1c590a5 100644
--- a/src/os/exec/lp_unix.go
+++ b/src/os/exec/lp_unix.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build aix darwin dragonfly freebsd linux nacl netbsd openbsd solaris
+// +build aix darwin dragonfly freebsd fuchsia linux nacl netbsd openbsd solaris
package exec
diff --git a/src/os/exec_fuchsia.go b/src/os/exec_fuchsia.go
new file mode 100644
index 0000000..f5fb417
--- /dev/null
+++ b/src/os/exec_fuchsia.go
@@ -0,0 +1,91 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package os
+
+import (
+ "errors"
+ "runtime"
+ "sync/atomic"
+ "syscall/zx"
+ "time"
+)
+
+type ProcessState struct {
+ retCode int
+}
+
+func (p *ProcessState) exited() bool {
+ panic("TODO os.Exited")
+}
+
+func (p *ProcessState) Pid() int {
+ panic("TODO os.Pid")
+}
+
+func (p *ProcessState) String() string {
+ if p == nil {
+ return "<nil>"
+ }
+ return "exit status " + itoa(p.retCode)
+}
+
+func (p *ProcessState) success() bool {
+ return p.retCode == 0
+}
+
+func (p *ProcessState) sys() interface{} {
+ panic("TODO os.sys")
+}
+
+func (p *ProcessState) sysUsage() interface{} {
+ panic("TODO os.sysUsage")
+}
+
+func (p *ProcessState) systemTime() time.Duration {
+ panic("TODO os.systemTime")
+}
+
+func (p *ProcessState) userTime() time.Duration {
+ panic("TODO os.userTime")
+}
+
+func (p *Process) release() error {
+ h := atomic.SwapUintptr(&p.handle, uintptr(zx.HandleInvalid))
+ procHandle := zx.Handle(h)
+ if err := procHandle.Close(); err != nil {
+ return err
+ }
+ // no need for a finalizer anymore
+ runtime.SetFinalizer(p, nil)
+ return nil
+}
+
+func (p *Process) signal(sig Signal) error {
+ panic("TODO os.Process.signal")
+}
+
+func findProcess(pid int) (p *Process, err error) {
+ panic("TODO os.findProcess")
+}
+
+func startProcess(name string, argv []string, attr *ProcAttr) (p *Process, err error) {
+ h, err := fdioStartProcess(name, argv, attr)
+ if err != nil {
+ return nil, err
+ }
+ pid := 1 // TODO: what does this even mean for us?
+ return newProcess(pid, uintptr(h)), nil
+}
+
+func hostname() (name string, err error) {
+ return "", errors.New("os.hostname unimplemented")
+}
+
+type signal string
+
+func (s signal) String() string { return string(s) }
+func (s signal) Signal() {}
+
+var Interrupt = signal("signal_interrupt")
diff --git a/src/os/exec_fuchsia_cgo.go b/src/os/exec_fuchsia_cgo.go
new file mode 100644
index 0000000..7c8c40c
--- /dev/null
+++ b/src/os/exec_fuchsia_cgo.go
@@ -0,0 +1,188 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build fuchsia
+
+package os
+
+// #cgo fuchsia CFLAGS: -I${SRCDIR}/../../../../../zircon/system/ulib/fdio/include
+// #cgo fuchsia LDFLAGS: -lfdio
+//
+// #include <lib/fdio/fd.h>
+// #include <lib/fdio/spawn.h>
+// #include <stdlib.h>
+// #include <unistd.h>
+// #include <zircon/syscalls/object.h>
+// #include <zircon/types.h>
+//
+// static int fsa_get_local_fd(fdio_spawn_action_t *fsa) { return fsa->fd.local_fd; }
+// static int fsa_get_target_fd(fdio_spawn_action_t *fsa) { return fsa->fd.target_fd; }
+//
+// static void fsa_set_local_fd(fdio_spawn_action_t *fsa, int fd) { fsa->fd.local_fd = fd; }
+// static void fsa_set_target_fd(fdio_spawn_action_t *fsa, int fd) { fsa->fd.target_fd = fd; }
+import "C"
+
+import (
+ "errors"
+ "syscall"
+ "syscall/zx"
+ "syscall/zx/zxwait"
+ "unsafe"
+)
+
+func makeCStringArray(s []string) []*C.char {
+ ret := make([]*C.char, len(s)+1)
+ for i, s := range s {
+ ret[i] = (*C.char)(C.CString(s))
+ }
+ ret[len(ret)-1] = nil
+ return ret
+}
+
+func freeCStringArray(a []*C.char) {
+ for i := range a {
+ if a[i] != nil {
+ C.free(unsafe.Pointer(a[i]))
+ }
+ }
+}
+
+// asLibfdioFD returns a File as a libfdio file descriptor.
+func asLibfdioFD(f *File) (int, error) {
+ m := syscall.FDIOForFD(int(f.Fd()))
+ if m == nil {
+ return -1, ErrInvalid
+ }
+
+ mCopy, err := m.Clone()
+ if err != nil {
+ return -1, err
+ }
+ handles := mCopy.Handles()
+
+ var fd C.int
+ status := zx.Status(C.fdio_fd_create(C.zx_handle_t(handles[0]), &fd))
+ if status != zx.ErrOk {
+ return -1, errors.New("fdio_fd_create failed")
+ }
+ return int(fd), nil
+}
+
+func fdioSpawnActions(attr *ProcAttr) (actions []C.fdio_spawn_action_t, err error) {
+ defer func() {
+ if err != nil {
+ for _, action := range actions {
+ C.close(C.fsa_get_local_fd(&action))
+ }
+ }
+ }()
+
+ for i, f := range attr.Files {
+ if f == nil {
+ continue
+ }
+ fd, err := asLibfdioFD(f)
+ if err != nil {
+ return nil, err
+ }
+ action := C.fdio_spawn_action_t{action: C.FDIO_SPAWN_ACTION_TRANSFER_FD}
+ C.fsa_set_local_fd(&action, C.int(fd))
+ C.fsa_set_target_fd(&action, C.int(i))
+ actions = append(actions, action)
+ }
+
+ return actions, nil
+}
+
+func fdioStartProcess(name string, argv []string, attr *ProcAttr) (zx.Handle, error) {
+ env := attr.Env
+ if env == nil {
+ env = Environ()
+ }
+ if attr.Dir != "" {
+ found := false
+ for i, s := range env {
+ const prefix = "PWD="
+ // strings.HasPrefix
+ if len(s) >= len(prefix) && s[:len(prefix)] == prefix {
+ found = true
+ env[i] = "PWD=" + attr.Dir
+ break
+ }
+ }
+ if !found {
+ env = append(env, "PWD="+attr.Dir)
+ }
+ }
+
+ nameC := C.CString(name)
+ defer C.free(unsafe.Pointer(nameC))
+ argvC := makeCStringArray(argv)
+ defer freeCStringArray(argvC)
+ envC := makeCStringArray(env)
+ defer freeCStringArray(envC)
+
+ actions, err := fdioSpawnActions(attr)
+ if err != nil {
+ return 0, err
+ }
+
+ var actions0 *C.fdio_spawn_action_t
+ if len(actions) > 0 {
+ actions0 = &actions[0]
+ }
+
+ var h C.zx_handle_t
+ var errmsg [C.FDIO_SPAWN_ERR_MSG_MAX_LENGTH]C.char
+ status := zx.Status(C.fdio_spawn_etc(
+ C.ZX_HANDLE_INVALID,
+ C.FDIO_SPAWN_CLONE_JOB|C.FDIO_SPAWN_DEFAULT_LDSVC|C.FDIO_SPAWN_CLONE_NAMESPACE, // TODO(mdempsky): Flags.
+ nameC,
+ &argvC[0],
+ &envC[0],
+ C.size_t(len(actions)),
+ actions0,
+ &h,
+ &errmsg[0],
+ ))
+ if status != zx.ErrOk {
+ return 0, errors.New("fdio_spawn_etc: " + itoa(int(status)) + ": " + charsAsString(errmsg[:]))
+ }
+ return zx.Handle(h), nil
+}
+
+func charsAsString(s []C.char) string {
+ var x []byte
+ for _, c := range s {
+ if c == 0 {
+ break
+ }
+ x = append(x, byte(c))
+ }
+ return string(x)
+}
+
+func (p *Process) kill() error {
+ procHandle := zx.Handle(p.handle)
+ status := zx.Sys_task_kill(procHandle)
+ if status != zx.ErrOk {
+ return errors.New("kill error: " + itoa(int(status)))
+ }
+ return nil
+}
+
+func (p *Process) wait() (ps *ProcessState, err error) {
+ procHandle := zx.Handle(p.handle)
+ _, err = zxwait.Wait(procHandle, zx.SignalTaskTerminated, zx.TimensecInfinite)
+ if err != nil {
+ return nil, err
+ }
+ procInfo := C.zx_info_process_t{}
+ status := zx.Sys_object_get_info(procHandle, zx.ObjectInfoProcess, unsafe.Pointer(&procInfo), C.sizeof_zx_info_process_t, nil, nil)
+ if status != zx.ErrOk {
+ return nil, errors.New("error retrieving process info: " + itoa(int(status)))
+ }
+ defer p.Release()
+ return &ProcessState{int(procInfo.return_code)}, nil
+}
diff --git a/src/os/exec_fuchsia_stubs.go b/src/os/exec_fuchsia_stubs.go
new file mode 100644
index 0000000..83aa953
--- /dev/null
+++ b/src/os/exec_fuchsia_stubs.go
@@ -0,0 +1,22 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build fuchsia
+// +build !cgo
+
+package os
+
+import "syscall/zx"
+
+func fdioStartProcess(name string, argv []string, attr *ProcAttr) (zx.Handle, error) {
+ panic("os.fdioStartProcess unimplemented")
+}
+
+func (p *Process) kill() error {
+ panic("os.Process.kill unimplemented")
+}
+
+func (p *Process) wait() (*ProcessState, error) {
+ panic("os.Process.wait unimplemented")
+}
diff --git a/src/os/executable_procfs.go b/src/os/executable_procfs.go
index 5bb63b9..3c35f23 100644
--- a/src/os/executable_procfs.go
+++ b/src/os/executable_procfs.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build linux netbsd dragonfly nacl js,wasm
+// +build linux netbsd dragonfly nacl js,wasm fuchsia
package os
diff --git a/src/os/executable_test.go b/src/os/executable_test.go
index d513c87..a8006c8 100644
--- a/src/os/executable_test.go
+++ b/src/os/executable_test.go
@@ -20,6 +20,9 @@
testenv.MustHaveExec(t) // will also exclude nacl, which doesn't support Executable anyway
ep, err := os.Executable()
if err != nil {
+ if runtime.GOOS == "fuchsia" {
+ t.Skipf("Executable failed on %s: %v, expected", runtime.GOOS, err) // TODO(dhobsd): rebase
+ }
t.Fatalf("Executable failed: %v", err)
}
// we want fn to be of the form "dir/prog"
diff --git a/src/os/file_fuchsia.go b/src/os/file_fuchsia.go
new file mode 100644
index 0000000..62a7981
--- /dev/null
+++ b/src/os/file_fuchsia.go
@@ -0,0 +1,159 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package os
+
+import (
+ "errors"
+ "internal/poll"
+ "syscall"
+ "syscall/zx/fdio"
+ "time"
+)
+
+func (f *File) Truncate(size int64) error {
+ if err := f.checkValid("truncate"); err != nil {
+ return err
+ }
+ return syscall.Ftruncate(f.pfd.Sysfd, size)
+}
+
+func (f *File) Sync() error {
+ if f == nil {
+ return ErrInvalid
+ }
+ return syscall.Fsync(f.pfd.Sysfd)
+}
+
+func syscallMode(i FileMode) (o uint32) {
+ o |= uint32(i.Perm())
+ // TODO i&ModeSetuid != 0
+ // TODO i&ModeSetgid != 0
+ // TODO i&ModeSticky != 0
+ return o
+}
+
+func (f *File) chmod(mode FileMode) error {
+ if err := f.checkValid("chmod"); err != nil {
+ return err
+ }
+ return chmod(f.Name(), mode)
+}
+
+func (f *File) Chown(uid, gid int) error {
+ return errors.New("os: Chown unimplemented on fuchsia")
+}
+
+func chmod(name string, mode FileMode) error {
+ if _, err := Stat(name); err != nil {
+ return err
+ }
+
+ return nil
+}
+
+func Chown(name string, uid, gid int) error {
+ return errors.New("os: Chown unimplemented on fuchsia")
+}
+
+func Chtimes(name string, atime time.Time, mtime time.Time) error {
+ var utimes [2]syscall.Timespec
+ utimes[0] = syscall.NsecToTimespec(atime.UnixNano())
+ utimes[1] = syscall.NsecToTimespec(mtime.UnixNano())
+ if e := syscall.UtimesNano(fixLongPath(name), utimes[0:]); e != nil {
+ return &PathError{"chtimes", name, e}
+ }
+ return nil
+}
+
+func Readlink(name string) (string, error) {
+ return "", errors.New("Readlink unimplemented")
+}
+
+func Pipe() (r *File, w *File, err error) {
+ p0, p1, err := fdio.NewPipes()
+ if err != nil {
+ return nil, nil, err
+ }
+ r = NewFile(uintptr(syscall.OpenFDIO(p0)), "|0")
+ w = NewFile(uintptr(syscall.OpenFDIO(p1)), "|1")
+ // TODO CloseOnExec equivalent
+ return r, w, nil
+}
+
+// Chdir changes the current working directory to the file,
+// which must be a directory.
+// If there is an error, it will be of type *PathError.
+func (f *File) Chdir() error {
+ if err := f.checkValid("chdir"); err != nil {
+ return err
+ }
+ if e := syscall.Fchdir(f.pfd.Sysfd); e != nil {
+ return &PathError{"chdir", f.name, e}
+ }
+ return nil
+}
+
+func sigpipe() // implemented in package runtime
+
+var supportsCloseOnExec = true
+
+func fillFileStatFromSys(fs *fileStat, name string) {
+ fs.name = basename(name)
+ fs.size = int64(fs.sys.Size)
+ // For now, pretend files have all bits. This should really be:
+ // fs.mode = FileMode(fs.sys.Dev & 0777)
+ // but we don't really set file modes properly and testing for executables
+ // in $PATH fails without the x bit set.
+ fs.mode = FileMode(0766)
+
+ switch fs.sys.Dev & 0xf000 {
+ case 0x4000:
+ fs.mode = fs.mode | ModeDir
+ case 0x2000:
+ fs.mode = fs.mode | ModeCharDevice
+ case 0xa000:
+ fs.mode = fs.mode | ModeSymlink
+ case 0xc000:
+ fs.mode = fs.mode | ModeSocket
+ }
+ fs.modTime = time.Unix(int64(fs.sys.ModifyTime), 0)
+}
+
+func atime(fi FileInfo) time.Time {
+ // TODO: fdio doesn't have atime yet
+ return time.Time{}
+}
+
+// setDeadline sets the read and write deadline.
+func (f *File) setDeadline(time.Time) error {
+ if err := f.checkValid("SetDeadline"); err != nil {
+ return err
+ }
+ return poll.ErrNoDeadline
+}
+
+// setReadDeadline sets the read deadline.
+func (f *File) setReadDeadline(time.Time) error {
+ if err := f.checkValid("SetReadDeadline"); err != nil {
+ return err
+ }
+ return poll.ErrNoDeadline
+}
+
+// setWriteDeadline sets the write deadline.
+func (f *File) setWriteDeadline(time.Time) error {
+ if err := f.checkValid("SetWriteDeadline"); err != nil {
+ return err
+ }
+ return poll.ErrNoDeadline
+}
+
+// checkValid checks whether f is valid for use.
+func (f *File) checkValid(op string) error {
+ if f == nil {
+ return ErrInvalid
+ }
+ return nil
+}
diff --git a/src/os/file_unix.go b/src/os/file_unix.go
index 2615df9..257cee9 100644
--- a/src/os/file_unix.go
+++ b/src/os/file_unix.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build aix darwin dragonfly freebsd js,wasm linux nacl netbsd openbsd solaris
+// +build aix darwin dragonfly freebsd fuchsia js,wasm linux nacl netbsd openbsd solaris
package os
diff --git a/src/os/getwd.go b/src/os/getwd.go
index 6d25466..39a4fd2 100644
--- a/src/os/getwd.go
+++ b/src/os/getwd.go
@@ -24,7 +24,7 @@
// reached via multiple paths (due to symbolic links),
// Getwd may return any one of them.
func Getwd() (dir string, err error) {
- if runtime.GOOS == "windows" || runtime.GOOS == "plan9" {
+ if runtime.GOOS == "windows" || runtime.GOOS == "plan9" || runtime.GOOS == "fuchsia" {
return syscall.Getwd()
}
diff --git a/src/os/os_test.go b/src/os/os_test.go
index 9c4d5da..aa4fe8f 100644
--- a/src/os/os_test.go
+++ b/src/os/os_test.go
@@ -26,15 +26,49 @@
"time"
)
-var dot = []string{
- "dir_unix.go",
- "env.go",
- "error.go",
- "file.go",
- "os_test.go",
- "types.go",
- "stat_darwin.go",
- "stat_linux.go",
+var dot = func() []string {
+ switch runtime.GOOS {
+ case "fuchsia":
+ return []string{
+ "go_os_test_foo",
+ "go_os_test_bar",
+ "go_os_test_baz",
+ }
+ default:
+ return []string{
+ "dir_unix.go",
+ "env.go",
+ "error.go",
+ "file.go",
+ "os_test.go",
+ "types.go",
+ "stat_darwin.go",
+ "stat_linux.go",
+ }
+ }
+}()
+
+func init() {
+ if runtime.GOOS == "fuchsia" {
+ flag.CommandLine.Set("test.v", "true")
+ }
+}
+
+func tmpInit(t *testing.T) {
+ if runtime.GOOS == "fuchsia" {
+ dir, err := ioutil.TempDir("", "")
+ if err != nil {
+ t.Fatalf("tempdir: %v", err)
+ }
+ for _, fname := range dot {
+ if err := MkdirAll(filepath.Join(dir, fname), ModePerm); err != nil {
+ t.Fatalf("Initializing tmp: %v", err)
+ }
+ }
+ if err := Chdir(dir); err != nil {
+ t.Fatalf("chdir: %v", err)
+ }
+ }
}
type sysDir struct {
@@ -44,6 +78,14 @@
var sysdir = func() *sysDir {
switch runtime.GOOS {
+ case "fuchsia":
+ return &sysDir{
+ "/boot/lib",
+ []string{
+ "libfdio.so",
+ "ld.so.1",
+ },
+ }
case "android":
return &sysDir{
"/system/lib",
@@ -175,6 +217,9 @@
}
func TestStatError(t *testing.T) {
+ if runtime.GOOS == "fuchsia" {
+ t.Skip("TODO(dhobsd): fix")
+ }
defer chtmpdir(t)()
path := "no-such-file"
@@ -344,11 +389,13 @@
}
func TestReaddirnames(t *testing.T) {
+ tmpInit(t)
testReaddirnames(".", dot, t)
testReaddirnames(sysdir.name, sysdir.files, t)
}
func TestReaddir(t *testing.T) {
+ tmpInit(t)
testReaddir(".", dot, t)
testReaddir(sysdir.name, sysdir.files, t)
}
@@ -466,6 +513,8 @@
// big directory that doesn't change often.
dir := "/usr/bin"
switch runtime.GOOS {
+ case "fuchsia":
+ dir = "/boot/bin"
case "android":
dir = "/system/bin"
case "darwin":
@@ -994,6 +1043,8 @@
switch runtime.GOOS {
case "android":
t.Skip("android doesn't have /bin/pwd")
+ case "fuchsia":
+ t.Skip("fuchsia doesn't have /bin/pwd")
case "windows":
cmd = Getenv("COMSPEC")
dir = Getenv("SystemRoot")
@@ -1027,8 +1078,8 @@
}
func TestChmod(t *testing.T) {
- // Chmod is not supported under windows.
- if runtime.GOOS == "windows" {
+ // Chmod is not supported under windows or Fuchsia
+ if runtime.GOOS == "windows" || runtime.GOOS == "fuchsia" {
return
}
f := newFile("TestChmod", t)
@@ -1101,6 +1152,11 @@
// On NFS, timings can be off due to caching of meta-data on
// NFS servers (Issue 848).
func TestChtimes(t *testing.T) {
+ if runtime.GOOS == "fuchsia" {
+ // It passes sometimes, but seems to be flakey
+ t.Skipf("TODO(smklein): Implement")
+ }
+
f := newFile("TestChtimes", t)
defer Remove(f.Name())
@@ -1115,6 +1171,11 @@
// On NFS, timings can be off due to caching of meta-data on
// NFS servers (Issue 848).
func TestChtimesDir(t *testing.T) {
+ if runtime.GOOS == "fuchsia" {
+ // It passes sometimes, but seems to be flakey
+ t.Skipf("TODO(smklein): Implement")
+ }
+
name := newDir("TestChtimes", t)
defer RemoveAll(name)
@@ -1146,7 +1207,7 @@
pmt := postStat.ModTime()
if !pat.Before(at) {
switch runtime.GOOS {
- case "plan9", "nacl":
+ case "plan9", "nacl", "fuchsia":
// Ignore.
// Plan 9, NaCl:
// Mtime is the time of the last change of
@@ -1172,7 +1233,7 @@
func TestChdirAndGetwd(t *testing.T) {
// TODO(brainman): file.Chdir() is not implemented on windows.
- if runtime.GOOS == "windows" {
+ if runtime.GOOS == "windows" || runtime.GOOS == "fuchsia" {
return
}
fd, err := Open(".")
@@ -1403,6 +1464,10 @@
}
func TestOpenError(t *testing.T) {
+ if runtime.GOOS == "fuchsia" {
+ t.Skipf("TODO(smklein): Implement")
+ }
+
for _, tt := range openErrorTests {
f, err := OpenFile(tt.path, tt.mode, 0)
if err == nil {
@@ -1504,6 +1569,10 @@
}
func TestHostname(t *testing.T) {
+ if runtime.GOOS == "fuchsia" {
+ t.Skipf("TODO(dho): Implement")
+ }
+
hostname, err := Hostname()
if err != nil {
t.Fatal(err)
@@ -1727,6 +1796,10 @@
}
func TestSameFile(t *testing.T) {
+ if runtime.GOOS == "fuchsia" {
+ t.Skipf("TODO(smklein): Implement")
+ }
+
defer chtmpdir(t)()
fa, err := Create("a")
if err != nil {
@@ -1775,13 +1848,13 @@
if fi.Size() != 0 {
t.Errorf(pre+"wrong file size have %d want 0", fi.Size())
}
- if fi.Mode()&ModeDevice == 0 {
+ if fi.Mode()&ModeDevice == 0 && runtime.GOOS != "fuchsia" {
t.Errorf(pre+"wrong file mode %q: ModeDevice is not set", fi.Mode())
}
if fi.Mode()&ModeCharDevice == 0 {
t.Errorf(pre+"wrong file mode %q: ModeCharDevice is not set", fi.Mode())
}
- if fi.Mode().IsRegular() {
+ if fi.Mode().IsRegular() && runtime.GOOS != "fuchsia" {
t.Errorf(pre+"wrong file mode %q: IsRegular returns true", fi.Mode())
}
}
@@ -1838,6 +1911,10 @@
}
func TestStatDirModeExec(t *testing.T) {
+ if runtime.GOOS == "fuchsia" {
+ t.Skipf("TODO(smklein): Implement")
+ }
+
const mode = 0111
path, err := ioutil.TempDir("", "go-build")
@@ -1861,7 +1938,8 @@
func TestStatStdin(t *testing.T) {
switch runtime.GOOS {
- case "android", "plan9":
+ case "android", "plan9", "fuchsia":
+ // TODO(smklein): Implement on Fuchsia
t.Skipf("%s doesn't have /bin/sh", runtime.GOOS)
}
@@ -1977,6 +2055,10 @@
}
func TestLongPath(t *testing.T) {
+ if runtime.GOOS == "fuchsia" {
+ t.Skipf("no chmod support on fuchsia")
+ }
+
tmpdir := newDir("TestLongPath", t)
defer func(d string) {
if err := RemoveAll(d); err != nil {
@@ -2033,9 +2115,11 @@
if dir.Size() != filesize || filesize != wantSize {
t.Errorf("Size(%q) is %d, len(ReadFile()) is %d, want %d", path, dir.Size(), filesize, wantSize)
}
- err = Chmod(path, dir.Mode())
- if err != nil {
- t.Fatalf("Chmod(%q) failed: %v", path, err)
+ if testenv.HasChmod() {
+ err = Chmod(path, dir.Mode())
+ if err != nil {
+ t.Fatalf("Chmod(%q) failed: %v", path, err)
+ }
}
}
if err := Truncate(sizedTempDir+"/bar.txt", 0); err != nil {
@@ -2088,6 +2172,9 @@
// TODO: golang.org/issue/8206
t.Skipf("skipping test on plan9; see issue 8206")
}
+ if runtime.GOOS == "fuchsia" {
+ t.Skipf("TODO(smklein): Implement")
+ }
testenv.MustHaveExec(t)
@@ -2113,6 +2200,10 @@
}
func TestKillFindProcess(t *testing.T) {
+ if runtime.GOOS == "fuchsia" {
+ t.Skipf("TODO(smklein): Implement")
+ }
+
testKillProcess(t, func(p *Process) {
p2, err := FindProcess(p.Pid)
if err != nil {
@@ -2148,6 +2239,10 @@
// Test that all File methods give ErrInvalid if the receiver is nil.
func TestNilFileMethods(t *testing.T) {
+ if runtime.GOOS == "fuchsia" {
+ t.Skipf("TODO(smklein): Implement")
+ }
+
for _, tt := range nilFileMethodTests {
var file *File
got := tt.f(file)
@@ -2219,6 +2314,8 @@
t.Skip("skipping on Plan 9; does not support runtime poller")
case "js":
t.Skip("skipping on js; no support for os.Pipe")
+ case "fuchsia":
+ t.Skip("skipping on fuchsia; TODO")
}
threads := 100
diff --git a/src/os/path_test.go b/src/os/path_test.go
index 6cb25bc..7ee8a38 100644
--- a/src/os/path_test.go
+++ b/src/os/path_test.go
@@ -105,7 +105,7 @@
func TestMkdirAllAtSlash(t *testing.T) {
switch runtime.GOOS {
- case "android", "plan9", "windows":
+ case "android", "fuchsia", "plan9", "windows":
t.Skipf("skipping on %s", runtime.GOOS)
case "darwin":
switch runtime.GOARCH {
diff --git a/src/os/path_unix.go b/src/os/path_unix.go
index df423d2..da990b8 100644
--- a/src/os/path_unix.go
+++ b/src/os/path_unix.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build aix darwin dragonfly freebsd js,wasm linux nacl netbsd openbsd solaris
+// +build aix darwin dragonfly freebsd fuchsia js,wasm linux nacl netbsd openbsd solaris
package os
diff --git a/src/os/pipe_test.go b/src/os/pipe_test.go
index 779b2bd..319db29 100644
--- a/src/os/pipe_test.go
+++ b/src/os/pipe_test.go
@@ -3,7 +3,7 @@
// license that can be found in the LICENSE file.
// Test broken pipes on Unix systems.
-// +build !windows,!plan9,!nacl,!js
+// +build !windows,!plan9,!nacl,!js,!fuchsia
package os_test
@@ -397,6 +397,10 @@
}
func TestFdReadRace(t *testing.T) {
+ if runtime.GOOS == "fuchsia" {
+ t.Skip("deadlines are TODO on fuchsia")
+ }
+
t.Parallel()
r, w, err := os.Pipe()
diff --git a/src/os/rawconn_test.go b/src/os/rawconn_test.go
index 820150d..ab1696b 100644
--- a/src/os/rawconn_test.go
+++ b/src/os/rawconn_test.go
@@ -3,7 +3,7 @@
// license that can be found in the LICENSE file.
// Test use of raw connections.
-// +build !plan9,!nacl,!js
+// +build !fuchsia,!plan9,!nacl,!js
package os_test
diff --git a/src/os/signal/signal_fuchsia.go b/src/os/signal/signal_fuchsia.go
new file mode 100644
index 0000000..0d4e736
--- /dev/null
+++ b/src/os/signal/signal_fuchsia.go
@@ -0,0 +1,29 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package signal
+
+import "os"
+
+const numSig = 65
+
+func signum(sig os.Signal) int {
+ panic("TODO")
+}
+
+func enableSignal(sig int) {
+ panic("TODO")
+}
+
+func disableSignal(sig int) {
+ panic("TODO")
+}
+
+func ignoreSignal(sig int) {
+ panic("TODO")
+}
+
+func signalIgnored(sig int) bool {
+ panic("TODO")
+}
diff --git a/src/os/stat_unix.go b/src/os/stat_unix.go
index 4f85dce..804e625 100644
--- a/src/os/stat_unix.go
+++ b/src/os/stat_unix.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build aix darwin dragonfly freebsd js,wasm linux nacl netbsd openbsd solaris
+// +build aix darwin dragonfly freebsd fuchsia js,wasm linux nacl netbsd openbsd solaris
package os
diff --git a/src/os/timeout_test.go b/src/os/timeout_test.go
index 4720738..8fd7956 100644
--- a/src/os/timeout_test.go
+++ b/src/os/timeout_test.go
@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+// +build !fuchsia
// +build !nacl
// +build !js
// +build !plan9
@@ -64,6 +65,10 @@
}
func TestReadTimeout(t *testing.T) {
+ if runtime.GOOS == "fuchsia" {
+ t.Skip("deadlines are TODO on fuchsia")
+ }
+
t.Parallel()
r, w, err := os.Pipe()
@@ -104,6 +109,9 @@
}
func TestReadTimeoutMustNotReturn(t *testing.T) {
+ if runtime.GOOS == "fuchsia" {
+ t.Skip("file read timeouts are TODO on fuchsia")
+ }
t.Parallel()
r, w, err := os.Pipe()
@@ -155,6 +163,10 @@
}
func TestWriteTimeout(t *testing.T) {
+ if runtime.GOOS == "fuchsia" {
+ t.Skip("deadlines are TODO on fuchsia")
+ }
+
t.Parallel()
for i, tt := range writeTimeoutTests {
@@ -192,6 +204,10 @@
}
func TestWriteTimeoutMustNotReturn(t *testing.T) {
+ if runtime.GOOS == "fuchsia" {
+ t.Skip("deadlines are TODO on fuchsia")
+ }
+
t.Parallel()
r, w, err := os.Pipe()
@@ -258,6 +274,10 @@
}
func TestReadTimeoutFluctuation(t *testing.T) {
+ if runtime.GOOS == "fuchsia" {
+ t.Skip("deadlines are TODO on fuchsia")
+ }
+
t.Parallel()
r, w, err := os.Pipe()
@@ -309,6 +329,10 @@
}
func TestWriteTimeoutFluctuation(t *testing.T) {
+ if runtime.GOOS == "fuchsia" {
+ t.Skip("deadlines are TODO on fuchsia")
+ }
+
t.Parallel()
r, w, err := os.Pipe()
@@ -367,6 +391,10 @@
}
func testVariousDeadlines(t *testing.T) {
+ if runtime.GOOS == "fuchsia" {
+ t.Skip("deadlines are TODO on fuchsia")
+ }
+
type result struct {
n int64
err error
@@ -460,6 +488,10 @@
}
func TestReadWriteDeadlineRace(t *testing.T) {
+ if runtime.GOOS == "fuchsia" {
+ t.Skip("deadlines are TODO on fuchsia")
+ }
+
t.Parallel()
N := 1000
@@ -516,6 +548,10 @@
// TestRacyRead tests that it is safe to mutate the input Read buffer
// immediately after cancelation has occurred.
func TestRacyRead(t *testing.T) {
+ if runtime.GOOS == "fuchsia" {
+ t.Skip("deadlines are TODO on fuchsia")
+ }
+
t.Parallel()
r, w, err := os.Pipe()
@@ -555,6 +591,10 @@
// TestRacyWrite tests that it is safe to mutate the input Write buffer
// immediately after cancelation has occurred.
func TestRacyWrite(t *testing.T) {
+ if runtime.GOOS == "fuchsia" {
+ t.Skip("deadlines are TODO on fuchsia")
+ }
+
t.Parallel()
r, w, err := os.Pipe()
diff --git a/src/os/user/lookup_fuchsia.go b/src/os/user/lookup_fuchsia.go
new file mode 100644
index 0000000..80fa82c
--- /dev/null
+++ b/src/os/user/lookup_fuchsia.go
@@ -0,0 +1,38 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build fuchsia
+
+package user
+
+import "errors"
+
+func init() {
+ userImplemented = false
+ groupImplemented = false
+}
+
+func current() (*User, error) {
+ return nil, errors.New("user: Current not implemented on fuchsia")
+}
+
+func lookupUser(string) (*User, error) {
+ return nil, errors.New("user: Lookup not implemented on fuchsia")
+}
+
+func lookupUserId(string) (*User, error) {
+ return nil, errors.New("user: LookupId not implemented on fuchsia")
+}
+
+func lookupGroup(string) (*Group, error) {
+ return nil, errors.New("user: LookupGroup not implemented on fuchsia")
+}
+
+func lookupGroupId(string) (*Group, error) {
+ return nil, errors.New("user: LookupGroupId not implemented on fuchsia")
+}
+
+func listGroups(*User) ([]string, error) {
+ return nil, errors.New("user: GroupIds not implemented on fuchsia")
+}
diff --git a/src/os/user/lookup_stubs.go b/src/os/user/lookup_stubs.go
index 61bf1dc..1666db4 100644
--- a/src/os/user/lookup_stubs.go
+++ b/src/os/user/lookup_stubs.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build !cgo,!windows,!plan9 android osusergo,!windows,!plan9
+// +build !cgo,!windows,!plan9 android osusergo,!windows,!plan9,!fuchsia
package user
diff --git a/src/path/filepath/path_unix.go b/src/path/filepath/path_unix.go
index c10b328..275dc6c 100644
--- a/src/path/filepath/path_unix.go
+++ b/src/path/filepath/path_unix.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build aix darwin dragonfly freebsd js,wasm linux nacl netbsd openbsd solaris
+// +build aix darwin dragonfly freebsd fuchsia js,wasm linux nacl netbsd openbsd solaris
package filepath
diff --git a/src/runtime/asm_amd64.s b/src/runtime/asm_amd64.s
index 6339dc0..a422ace 100644
--- a/src/runtime/asm_amd64.s
+++ b/src/runtime/asm_amd64.s
@@ -160,9 +160,12 @@
// skip TLS setup on Darwin
JMP ok
#endif
+#ifdef GOOS_fuchsia
+ // TODO(dhobsd): Fuchsia needs thread handle.
+#endif
- LEAQ runtime·m0+m_tls(SB), DI
- CALL runtime·settls(SB)
+ LEAQ runtime·m0+m_tls(SB), DI
+ CALL runtime·settls(SB)
// store through it, to make sure it works
get_tls(BX)
diff --git a/src/runtime/cgo/cgo.go b/src/runtime/cgo/cgo.go
index 241a821..11d9238 100644
--- a/src/runtime/cgo/cgo.go
+++ b/src/runtime/cgo/cgo.go
@@ -16,14 +16,18 @@
#cgo darwin,arm64 LDFLAGS: -framework CoreFoundation
#cgo dragonfly LDFLAGS: -lpthread
#cgo freebsd LDFLAGS: -lpthread
+#cgo fuchsia LDFLAGS: -lpthread -lfdio
#cgo android LDFLAGS: -llog
#cgo !android,linux LDFLAGS: -lpthread
#cgo netbsd LDFLAGS: -lpthread
#cgo openbsd LDFLAGS: -lpthread
-#cgo CFLAGS: -Wall -Werror
+#cgo !darwin CFLAGS: -Wall -Werror
+#cgo darwin CFLAGS: -Wall -Wno-unused-command-line-argument -Werror
#cgo solaris CPPFLAGS: -D_POSIX_PTHREAD_SEMANTICS
*/
import "C"
+
+// TODO(INTK-705): Remove darwin CFLAGS hack when we figure out the cause of these failures on Mac
diff --git a/src/runtime/cgo/fuchsia.go b/src/runtime/cgo/fuchsia.go
new file mode 100644
index 0000000..42fc3b9
--- /dev/null
+++ b/src/runtime/cgo/fuchsia.go
@@ -0,0 +1,21 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build fuchsia
+
+package cgo
+
+import _ "unsafe" // for go:linkname
+
+//go:cgo_import_static x_cgo_get_initial_handles
+//go:linkname x_cgo_get_initial_handles x_cgo_get_initial_handles
+//go:linkname _cgo_get_initial_handles runtime._cgo_get_initial_handles
+var x_cgo_get_initial_handles byte
+var _cgo_get_initial_handles = &x_cgo_get_initial_handles
+
+//go:cgo_import_static x_cgo_get_thread_self_handle
+//go:linkname x_cgo_get_thread_self_handle x_cgo_get_thread_self_handle
+//go:linkname _cgo_get_thread_self_handle runtime._cgo_get_thread_self_handle
+var x_cgo_get_thread_self_handle byte
+var _cgo_get_thread_self_handle = &x_cgo_get_thread_self_handle
diff --git a/src/runtime/cgo/gcc_fatalf.c b/src/runtime/cgo/gcc_fatalf.c
index fdcf6f5..1f416b5 100644
--- a/src/runtime/cgo/gcc_fatalf.c
+++ b/src/runtime/cgo/gcc_fatalf.c
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build !android,linux freebsd
+// +build !android,linux freebsd fuchsia
#include <stdarg.h>
#include <stdio.h>
diff --git a/src/runtime/cgo/gcc_fuchsia.c b/src/runtime/cgo/gcc_fuchsia.c
new file mode 100644
index 0000000..4cb998d
--- /dev/null
+++ b/src/runtime/cgo/gcc_fuchsia.c
@@ -0,0 +1,89 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build cgo
+// +build fuchsia
+
+#include "libcgo.h"
+
+#include <stdlib.h>
+#include <pthread.h>
+
+#include <lib/fdio/fd.h>
+#include <lib/fdio/namespace.h>
+#include <zircon/process.h>
+#include <zircon/processargs.h>
+#include <zircon/threads.h>
+#include <zircon/types.h>
+
+extern char **environ;
+
+// fdio_init matches a Go struct of the same name in os_fuchsia.go.
+struct fdio_init {
+ zx_handle_t stdioClones[3];
+ uint32_t stdioCloneNumHandles[3];
+ uint32_t stdioCloneTypes[3];
+ zx_handle_t processSelf;
+ zx_handle_t vmarRootSelf;
+ int32_t envlen;
+ char** environ;
+ uint8_t padding[4];
+ int32_t rootNSNumHandles;
+ zx_handle_t *rootNSHandles;
+ char** rootNSPaths;
+};
+
+void
+x_cgo_get_initial_handles(struct fdio_init *handles)
+{
+ // When running with cgo support, there are two FDIO libraries in the
+ // same process. We let the C FDIO start first, then clone its namespace
+ // and use that for Go.
+ // TODO: there is some small amount of fdio library state we
+ // have to share between Go and C, in particular, cwd.
+ // Work out how.
+
+ // fdio may have initialized std{in,out,err} with a single fd if the FDIO_FLAG_USE_FOR_STDIO
+ // flag was set, or have separate in/out/err fds. We clone fds {0,1,2} to separate fds for use
+ // in the Go runtime. The cloned fds aren't installed into fdio's fd table so they are only
+ // usable from Go's table.
+ for (int i = 0; i < 3; ++i) {
+ zx_status_t status = fdio_fd_clone(i, &handles->stdioClones[i]);
+ if (status != ZX_OK) {
+ printf("runtime/cgo: fdio_fd_clone of stdio[%d] failed: %d\n", i, status);
+ handles->stdioCloneNumHandles[i] = 0;
+ } else {
+ handles->stdioCloneNumHandles[i] = 1;
+ handles->stdioCloneTypes[i] = PA_FD;
+ }
+ }
+
+ handles->processSelf = zx_process_self();
+ handles->vmarRootSelf = zx_vmar_root_self();
+
+ for (char** env = environ; *env; env++) {
+ handles->envlen++;
+ }
+ handles->environ = environ;
+
+ fdio_flat_namespace_t* root_ns = NULL;
+ zx_status_t status = fdio_ns_export_root(&root_ns);
+ if (status != ZX_OK) {
+ handles->rootNSNumHandles = 0;
+ handles->rootNSHandles = NULL;
+ handles->rootNSPaths = NULL;
+ } else {
+ handles->rootNSNumHandles = (int32_t)root_ns->count;
+ handles->rootNSHandles = root_ns->handle;
+ handles->rootNSPaths = (char**)root_ns->path;
+ }
+}
+
+void
+x_cgo_get_thread_self_handle(zx_handle_t *h)
+{
+ // N.B.: libc currently (and probably always will) share the same type for
+ // C11 threads and pthreads.
+ *h = thrd_get_zx_handle(pthread_self());
+}
diff --git a/src/runtime/cgo/gcc_fuchsia_amd64.c b/src/runtime/cgo/gcc_fuchsia_amd64.c
new file mode 100644
index 0000000..ae65662
--- /dev/null
+++ b/src/runtime/cgo/gcc_fuchsia_amd64.c
@@ -0,0 +1,52 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#include <pthread.h>
+#include <errno.h>
+#include <string.h> // strerror
+#include <signal.h>
+#include <stdlib.h>
+#include "libcgo.h"
+
+static void* threadentry(void*);
+static void (*setg_gcc)(void*);
+
+void
+x_cgo_init(G* g, void (*setg)(void*))
+{
+ setg_gcc = setg;
+}
+
+void
+_cgo_sys_thread_start(ThreadStart *ts)
+{
+ // TODO: switch to threads.h.
+ pthread_attr_t attr;
+ pthread_t p;
+ size_t size;
+ int err;
+
+ pthread_attr_init(&attr);
+ pthread_attr_getstacksize(&attr, &size);
+ // leave stacklo=0 and set stackhi=size; mstack will do the rest.
+ ts->g->stackhi = size;
+ err = pthread_create(&p, &attr, threadentry, ts);
+
+ if (err != 0) {
+ fatalf("pthread_create failed: %s", strerror(err));
+ }
+}
+
+static void*
+threadentry(void *v)
+{
+ ThreadStart ts;
+
+ ts = *(ThreadStart*)v;
+ free(v);
+ setg_gcc((void*)ts.g);
+
+ crosscall_amd64(ts.fn);
+ return 0;
+}
diff --git a/src/runtime/cgo/gcc_fuchsia_arm64.c b/src/runtime/cgo/gcc_fuchsia_arm64.c
new file mode 100644
index 0000000..e79d192
--- /dev/null
+++ b/src/runtime/cgo/gcc_fuchsia_arm64.c
@@ -0,0 +1,53 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#include <pthread.h>
+#include <errno.h>
+#include <string.h> // strerror
+#include <signal.h>
+#include <stdlib.h>
+#include "libcgo.h"
+
+#include <stdio.h>
+
+static void* threadentry(void*);
+static void (*setg_gcc)(void*);
+
+void
+x_cgo_init(G* g, void (*setg)(void*))
+{
+ setg_gcc = setg;
+}
+
+void
+_cgo_sys_thread_start(ThreadStart *ts)
+{
+ pthread_attr_t attr;
+ pthread_t p;
+ size_t size;
+ int err;
+
+ pthread_attr_init(&attr);
+ pthread_attr_getstacksize(&attr, &size);
+ // leave stacklo=0 and set stackhi=size; mstack will do the rest.
+ ts->g->stackhi = size;
+ err = pthread_create(&p, &attr, threadentry, ts);
+
+ if (err != 0) {
+ fatalf("pthread_create failed: %s", strerror(err));
+ }
+}
+
+extern void crosscall1(void (*fn)(void), void (*setg_gcc)(void*), void *g);
+static void*
+threadentry(void *v)
+{
+ ThreadStart ts;
+
+ ts = *(ThreadStart*)v;
+ free(v);
+
+ crosscall1(ts.fn, setg_gcc, (void*)ts.g);
+ return 0;
+}
diff --git a/src/runtime/cgo/gcc_libinit.c b/src/runtime/cgo/gcc_libinit.c
index 3dafd10..298ffc0 100644
--- a/src/runtime/cgo/gcc_libinit.c
+++ b/src/runtime/cgo/gcc_libinit.c
@@ -3,7 +3,7 @@
// license that can be found in the LICENSE file.
// +build cgo
-// +build darwin dragonfly freebsd linux netbsd openbsd solaris
+// +build darwin dragonfly freebsd fuchsia linux netbsd openbsd solaris
#include <pthread.h>
#include <errno.h>
diff --git a/src/runtime/cgo/gcc_setenv.c b/src/runtime/cgo/gcc_setenv.c
index ed5d203..2f2581d 100644
--- a/src/runtime/cgo/gcc_setenv.c
+++ b/src/runtime/cgo/gcc_setenv.c
@@ -3,7 +3,7 @@
// license that can be found in the LICENSE file.
// +build cgo
-// +build darwin dragonfly freebsd linux netbsd openbsd solaris
+// +build darwin dragonfly freebsd fuchsia linux netbsd openbsd solaris
#include "libcgo.h"
diff --git a/src/runtime/cgo/setenv.go b/src/runtime/cgo/setenv.go
index fab4339..7fe251a 100644
--- a/src/runtime/cgo/setenv.go
+++ b/src/runtime/cgo/setenv.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build darwin dragonfly freebsd linux netbsd openbsd solaris
+// +build darwin dragonfly freebsd fuchsia linux netbsd openbsd solaris
package cgo
diff --git a/src/runtime/defs_fuchsia_amd64.go b/src/runtime/defs_fuchsia_amd64.go
new file mode 100644
index 0000000..7c5b9ac
--- /dev/null
+++ b/src/runtime/defs_fuchsia_amd64.go
@@ -0,0 +1,32 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package runtime
+
+type generalRegs struct {
+ rax uint64
+ rbx uint64
+ rcx uint64
+ rdx uint64
+ rsi uint64
+ rdi uint64
+ rbp uint64
+ rsp uint64
+ r8 uint64
+ r9 uint64
+ r10 uint64
+ r11 uint64
+ r12 uint64
+ r13 uint64
+ r14 uint64
+ r15 uint64
+ rip uint64
+ rflags uint64
+ fs_base uint64
+ gs_base uint64
+}
+
+func (r *generalRegs) rPC() uintptr { return uintptr(r.rip) }
+func (r *generalRegs) rSP() uintptr { return uintptr(r.rsp) }
+func (r *generalRegs) rLR() uintptr { return 0 }
diff --git a/src/runtime/defs_fuchsia_arm64.go b/src/runtime/defs_fuchsia_arm64.go
new file mode 100644
index 0000000..0daffac
--- /dev/null
+++ b/src/runtime/defs_fuchsia_arm64.go
@@ -0,0 +1,18 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package runtime
+
+type generalRegs struct {
+ r [30]uint64
+ lr uint64
+ sp uint64
+ pc uint64
+ cpsr uint64
+ tpidr uint64
+}
+
+func (r *generalRegs) rPC() uintptr { return uintptr(r.pc) }
+func (r *generalRegs) rSP() uintptr { return uintptr(r.sp) }
+func (r *generalRegs) rLR() uintptr { return uintptr(r.lr) }
diff --git a/src/runtime/env_posix.go b/src/runtime/env_posix.go
index 03208c7..d38a419 100644
--- a/src/runtime/env_posix.go
+++ b/src/runtime/env_posix.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build aix darwin dragonfly freebsd js,wasm linux nacl netbsd openbsd solaris windows
+// +build aix darwin dragonfly freebsd fuchsia js,wasm linux nacl netbsd openbsd solaris windows
package runtime
diff --git a/src/runtime/internal/sys/zgoos_aix.go b/src/runtime/internal/sys/zgoos_aix.go
index 909bfc5..e8ce26c 100644
--- a/src/runtime/internal/sys/zgoos_aix.go
+++ b/src/runtime/internal/sys/zgoos_aix.go
@@ -11,6 +11,7 @@
const GoosDarwin = 0
const GoosDragonfly = 0
const GoosFreebsd = 0
+const GoosFuchsia = 0
const GoosHurd = 0
const GoosJs = 0
const GoosLinux = 0
diff --git a/src/runtime/internal/sys/zgoos_android.go b/src/runtime/internal/sys/zgoos_android.go
index 434ce46..76bbf6b 100644
--- a/src/runtime/internal/sys/zgoos_android.go
+++ b/src/runtime/internal/sys/zgoos_android.go
@@ -11,6 +11,7 @@
const GoosDarwin = 0
const GoosDragonfly = 0
const GoosFreebsd = 0
+const GoosFuchsia = 0
const GoosHurd = 0
const GoosJs = 0
const GoosLinux = 0
diff --git a/src/runtime/internal/sys/zgoos_darwin.go b/src/runtime/internal/sys/zgoos_darwin.go
index b645d1cf..0d65588 100644
--- a/src/runtime/internal/sys/zgoos_darwin.go
+++ b/src/runtime/internal/sys/zgoos_darwin.go
@@ -11,6 +11,7 @@
const GoosDarwin = 1
const GoosDragonfly = 0
const GoosFreebsd = 0
+const GoosFuchsia = 0
const GoosHurd = 0
const GoosJs = 0
const GoosLinux = 0
diff --git a/src/runtime/internal/sys/zgoos_dragonfly.go b/src/runtime/internal/sys/zgoos_dragonfly.go
index 154cec3..6056501 100644
--- a/src/runtime/internal/sys/zgoos_dragonfly.go
+++ b/src/runtime/internal/sys/zgoos_dragonfly.go
@@ -11,6 +11,7 @@
const GoosDarwin = 0
const GoosDragonfly = 1
const GoosFreebsd = 0
+const GoosFuchsia = 0
const GoosHurd = 0
const GoosJs = 0
const GoosLinux = 0
diff --git a/src/runtime/internal/sys/zgoos_freebsd.go b/src/runtime/internal/sys/zgoos_freebsd.go
index 5f41c03..1e3e476 100644
--- a/src/runtime/internal/sys/zgoos_freebsd.go
+++ b/src/runtime/internal/sys/zgoos_freebsd.go
@@ -11,6 +11,7 @@
const GoosDarwin = 0
const GoosDragonfly = 0
const GoosFreebsd = 1
+const GoosFuchsia = 0
const GoosHurd = 0
const GoosJs = 0
const GoosLinux = 0
diff --git a/src/runtime/internal/sys/zgoos_fuchsia.go b/src/runtime/internal/sys/zgoos_fuchsia.go
new file mode 100644
index 0000000..ad679c7
--- /dev/null
+++ b/src/runtime/internal/sys/zgoos_fuchsia.go
@@ -0,0 +1,24 @@
+// Code generated by gengoos.go using 'go generate'. DO NOT EDIT.
+
+// +build fuchsia
+
+package sys
+
+const GOOS = `fuchsia`
+
+const GoosAix = 0
+const GoosAndroid = 0
+const GoosDarwin = 0
+const GoosDragonfly = 0
+const GoosFreebsd = 0
+const GoosFuchsia = 1
+const GoosHurd = 0
+const GoosJs = 0
+const GoosLinux = 0
+const GoosNacl = 0
+const GoosNetbsd = 0
+const GoosOpenbsd = 0
+const GoosPlan9 = 0
+const GoosSolaris = 0
+const GoosWindows = 0
+const GoosZos = 0
diff --git a/src/runtime/internal/sys/zgoos_hurd.go b/src/runtime/internal/sys/zgoos_hurd.go
index 53f7fc3..48a8586 100644
--- a/src/runtime/internal/sys/zgoos_hurd.go
+++ b/src/runtime/internal/sys/zgoos_hurd.go
@@ -11,6 +11,7 @@
const GoosDarwin = 0
const GoosDragonfly = 0
const GoosFreebsd = 0
+const GoosFuchsia = 0
const GoosHurd = 1
const GoosJs = 0
const GoosLinux = 0
diff --git a/src/runtime/internal/sys/zgoos_js.go b/src/runtime/internal/sys/zgoos_js.go
index c6cca49..a8b6c89 100644
--- a/src/runtime/internal/sys/zgoos_js.go
+++ b/src/runtime/internal/sys/zgoos_js.go
@@ -11,6 +11,7 @@
const GoosDarwin = 0
const GoosDragonfly = 0
const GoosFreebsd = 0
+const GoosFuchsia = 0
const GoosHurd = 0
const GoosJs = 1
const GoosLinux = 0
diff --git a/src/runtime/internal/sys/zgoos_linux.go b/src/runtime/internal/sys/zgoos_linux.go
index 088dbc1..5b34da8 100644
--- a/src/runtime/internal/sys/zgoos_linux.go
+++ b/src/runtime/internal/sys/zgoos_linux.go
@@ -12,6 +12,7 @@
const GoosDarwin = 0
const GoosDragonfly = 0
const GoosFreebsd = 0
+const GoosFuchsia = 0
const GoosHurd = 0
const GoosJs = 0
const GoosLinux = 1
diff --git a/src/runtime/internal/sys/zgoos_nacl.go b/src/runtime/internal/sys/zgoos_nacl.go
index 65bec4a..b91e2f2 100644
--- a/src/runtime/internal/sys/zgoos_nacl.go
+++ b/src/runtime/internal/sys/zgoos_nacl.go
@@ -11,6 +11,7 @@
const GoosDarwin = 0
const GoosDragonfly = 0
const GoosFreebsd = 0
+const GoosFuchsia = 0
const GoosHurd = 0
const GoosJs = 0
const GoosLinux = 0
diff --git a/src/runtime/internal/sys/zgoos_netbsd.go b/src/runtime/internal/sys/zgoos_netbsd.go
index 93d0fa7..da52c6f 100644
--- a/src/runtime/internal/sys/zgoos_netbsd.go
+++ b/src/runtime/internal/sys/zgoos_netbsd.go
@@ -11,6 +11,7 @@
const GoosDarwin = 0
const GoosDragonfly = 0
const GoosFreebsd = 0
+const GoosFuchsia = 0
const GoosHurd = 0
const GoosJs = 0
const GoosLinux = 0
diff --git a/src/runtime/internal/sys/zgoos_openbsd.go b/src/runtime/internal/sys/zgoos_openbsd.go
index 7919359..2681abf 100644
--- a/src/runtime/internal/sys/zgoos_openbsd.go
+++ b/src/runtime/internal/sys/zgoos_openbsd.go
@@ -11,6 +11,7 @@
const GoosDarwin = 0
const GoosDragonfly = 0
const GoosFreebsd = 0
+const GoosFuchsia = 0
const GoosHurd = 0
const GoosJs = 0
const GoosLinux = 0
diff --git a/src/runtime/internal/sys/zgoos_plan9.go b/src/runtime/internal/sys/zgoos_plan9.go
index 2b95e08..d474f2b 100644
--- a/src/runtime/internal/sys/zgoos_plan9.go
+++ b/src/runtime/internal/sys/zgoos_plan9.go
@@ -11,6 +11,7 @@
const GoosDarwin = 0
const GoosDragonfly = 0
const GoosFreebsd = 0
+const GoosFuchsia = 0
const GoosHurd = 0
const GoosJs = 0
const GoosLinux = 0
diff --git a/src/runtime/internal/sys/zgoos_solaris.go b/src/runtime/internal/sys/zgoos_solaris.go
index 6e3988a..904204c 100644
--- a/src/runtime/internal/sys/zgoos_solaris.go
+++ b/src/runtime/internal/sys/zgoos_solaris.go
@@ -11,6 +11,7 @@
const GoosDarwin = 0
const GoosDragonfly = 0
const GoosFreebsd = 0
+const GoosFuchsia = 0
const GoosHurd = 0
const GoosJs = 0
const GoosLinux = 0
diff --git a/src/runtime/internal/sys/zgoos_windows.go b/src/runtime/internal/sys/zgoos_windows.go
index a56e125..75b74db 100644
--- a/src/runtime/internal/sys/zgoos_windows.go
+++ b/src/runtime/internal/sys/zgoos_windows.go
@@ -11,6 +11,7 @@
const GoosDarwin = 0
const GoosDragonfly = 0
const GoosFreebsd = 0
+const GoosFuchsia = 0
const GoosHurd = 0
const GoosJs = 0
const GoosLinux = 0
diff --git a/src/runtime/internal/sys/zgoos_zos.go b/src/runtime/internal/sys/zgoos_zos.go
index 0f56e46..48f81bc 100644
--- a/src/runtime/internal/sys/zgoos_zos.go
+++ b/src/runtime/internal/sys/zgoos_zos.go
@@ -11,6 +11,7 @@
const GoosDarwin = 0
const GoosDragonfly = 0
const GoosFreebsd = 0
+const GoosFuchsia = 0
const GoosHurd = 0
const GoosJs = 0
const GoosLinux = 0
diff --git a/src/runtime/lock_futex.go b/src/runtime/lock_futex.go
index d2828b1..3cc206a 100644
--- a/src/runtime/lock_futex.go
+++ b/src/runtime/lock_futex.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build dragonfly freebsd linux
+// +build dragonfly freebsd fuchsia linux
package runtime
diff --git a/src/runtime/mem_fuchsia.go b/src/runtime/mem_fuchsia.go
new file mode 100644
index 0000000..eee26bc
--- /dev/null
+++ b/src/runtime/mem_fuchsia.go
@@ -0,0 +1,81 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package runtime
+
+import (
+ "syscall/zx"
+ "unsafe"
+)
+
+//go:nosplit
+func sysAlloc(n uintptr, sysStat *uint64) unsafe.Pointer {
+ var p unsafe.Pointer
+ sysMmap(unsafe.Pointer(&p), n, zx.VMFlagPermRead|zx.VMFlagPermWrite)
+ if uintptr(p) < 4096 {
+ println("runtime: sysMmap failed n=", n)
+ exit(2)
+ }
+ mSysStatInc(sysStat, n)
+ return p
+}
+
+func sysUnused(v unsafe.Pointer, n uintptr) {
+ // TODO(dho): Implement this based on ZX_VMO_OP_DECOMMIT
+}
+
+func sysUsed(v unsafe.Pointer, n uintptr) {
+ // TODO(dho): Maybe implement this based on ZX_VMO_OP_COMMIT
+}
+
+//go:nosplit
+func sysFree(v unsafe.Pointer, n uintptr, sysStat *uint64) {
+ mSysStatDec(sysStat, n)
+ if status := zx.Sys_vmar_unmap(zx.Handle(zx.VMARRoot), zx.Vaddr(v), uint64(n)); status != zx.ErrOk {
+ println("runtime: zx.Sys_vmar_unmap failed: ", status.String())
+ }
+}
+
+func sysMmap(ptr unsafe.Pointer, sz uintptr, flags zx.VMFlag) {
+ var h zx.Handle
+ if status := zx.Sys_vmo_create(uint64(sz), 0, &h); status != zx.ErrOk {
+ println("runtime: zx.Sys_vmo_create failed: ", status.String())
+ exit(2)
+ }
+
+ prop := []byte("go-sys-mmap")
+ if status := zx.Sys_object_set_property(h, zx.PropName, unsafe.Pointer(&prop[0]), uint(len(prop))); status != zx.ErrOk {
+ println("runtime: zx.Sys_object_set_property failed: ", status.String())
+ exit(2)
+ }
+
+ if status := zx.Sys_vmar_map(zx.Handle(zx.VMARRoot), flags, 0, h, 0, uint64(sz), (*zx.Vaddr)(ptr)); status != zx.ErrOk {
+ println("runtime: zx.Sys_vmar_map failed: ", status.String())
+ exit(2)
+ }
+
+ if status := zx.Sys_handle_close(h); status != zx.ErrOk {
+ println("runtime: zx.Sys_handle_close failed: ", status.String())
+ exit(2)
+ }
+}
+
+func sysReserve(v unsafe.Pointer, n uintptr) unsafe.Pointer {
+ p := v
+ sysMmap(unsafe.Pointer(&p), n, 0)
+ return p
+}
+
+func sysFault(v unsafe.Pointer, n uintptr) {
+ println("TODO sysFault")
+}
+
+func sysMap(v unsafe.Pointer, n uintptr, sysStat *uint64) {
+ mSysStatInc(sysStat, n)
+
+ if status := zx.Sys_vmar_protect(zx.Handle(zx.VMARRoot), zx.VMFlagPermRead|zx.VMFlagPermWrite, zx.Vaddr(v), uint64(n)); status != zx.ErrOk {
+ println("runtime: zx.Sys_vmar_protect failed: ", status.String())
+ exit(2)
+ }
+}
diff --git a/src/runtime/mkfuchsiavdso.go b/src/runtime/mkfuchsiavdso.go
new file mode 100644
index 0000000..102095b
--- /dev/null
+++ b/src/runtime/mkfuchsiavdso.go
@@ -0,0 +1,328 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build ignore
+
+// Uses the output of the internal/fuchsia/abigen parser to produce Go assembly
+// stubs to assign values to the vDSO entry points for syscalls.
+//
+// Regenerate with:
+//
+// go run mkfuchsiavdso.go -keys > vdso_keys_fuchsia.go
+// go run mkfuchsiavdso.go -calls -arch=amd64 > vdsocalls_fuchsia_amd64.s
+// go run mkfuchsiavdso.go -calls -arch=arm64 > vdsocalls_fuchsia_arm64.s
+package main
+
+import (
+ "bytes"
+ "flag"
+ "fmt"
+ "io/ioutil"
+ "log"
+ "os"
+ "path/filepath"
+
+ "internal/fuchsia/abigen"
+)
+
+var (
+ keys = flag.Bool("keys", false, "generate VDSO symbol keys and call stubs")
+ calls = flag.Bool("calls", false, "generate ASM call implementation")
+ arch = flag.String("arch", "amd64", "architecture to generate calls for")
+ fuchsiaRoot = flag.String("fuchsia_root", filepath.Join(os.Getenv("HOME"), "fuchsia"), "path to fuchsia root")
+)
+
+func elfHashGNU(s string) uint32 {
+ h := uint32(5381)
+ for i := 0; i < len(s); i++ {
+ h = h<<5 + h + uint32(s[i])
+ }
+ return h
+}
+
+func main() {
+ flag.Parse()
+
+ switch *arch {
+ case "amd64":
+ case "arm64":
+ default:
+ log.Fatalf("GOARCH=%s not supported", *arch)
+ }
+
+ syscallsFile := filepath.Join(*fuchsiaRoot, "/zircon/system/public/zircon/syscalls.abigen")
+ if args := flag.Args(); len(args) != 0 {
+ syscallsFile = args[0]
+ }
+
+ b, err := ioutil.ReadFile(syscallsFile)
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ p := abigen.NewParser(b, syscallsFile)
+ defs, err := p.Parse()
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ buf := new(bytes.Buffer)
+
+ if *keys {
+ writeKeys(buf, defs)
+ } else if *calls {
+ writeCalls(buf, defs)
+ }
+
+ buf.WriteTo(os.Stdout)
+}
+
+func writeKeys(buf *bytes.Buffer, defs []abigen.SysDef) {
+ fmt.Fprint(buf, keyHeader[1:])
+
+ fmt.Fprint(buf, "var vdsoSymbolKeys = []vdsoSymbolKey{\n")
+ for _, def := range defs {
+ sym := "_zx_" + def.Name
+ fmt.Fprintf(buf, "\t{\"%s\", 0x%x, &vdso_zx_%s},\n", sym, elfHashGNU(sym), def.Name)
+ }
+ fmt.Fprint(buf, "}\n")
+
+ fmt.Fprint(buf, "\n")
+ for _, def := range defs {
+ fmt.Fprintf(buf, "//go:cgo_import_dynamic vdso_zx_%s _zx_%s\n", def.Name, def.Name)
+ }
+
+ fmt.Fprint(buf, "\n")
+ for _, def := range defs {
+ fmt.Fprintf(buf, "//go:linkname vdso_zx_%s vdso_zx_%s\n", def.Name, def.Name)
+ }
+
+ fmt.Fprint(buf, "\n")
+ for _, def := range defs {
+ fmt.Fprint(buf, "//go:noescape\n")
+ fmt.Fprint(buf, "//go:nosplit\n")
+ printStub(buf, def)
+ fmt.Fprint(buf, "\n")
+ }
+
+ fmt.Fprint(buf, "var (\n")
+ for _, def := range defs {
+ fmt.Fprintf(buf, "\tvdso_zx_%s uintptr\n", def.Name)
+ }
+ fmt.Fprint(buf, ")\n")
+}
+
+func writeCalls(buf *bytes.Buffer, defs []abigen.SysDef) {
+ fmt.Fprint(buf, callHeader[1:])
+ for _, def := range defs {
+ fmt.Fprint(buf, "// ")
+ printStub(buf, def)
+ printAsm(buf, def)
+ fmt.Fprint(buf, "\n")
+ }
+}
+
+const keyHeader = `
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Keys for vDSO symbols.
+// Generated by mkfuchsiavdso.go, do not edit.
+
+package runtime
+
+import "unsafe"
+
+const (
+ // vdsoArrayMax is the byte-size of a maximally sized array on this architecture.
+ // See cmd/compile/internal/amd64/galign.go arch.MAXWIDTH initialization.
+ vdsoArrayMax = 1<<50 - 1
+)
+`
+
+const callHeader = `
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Zircon system calls for the Fuchsia OS.
+// Generated by mkfuchsia.go, do not edit.
+
+#include "go_asm.h"
+#include "go_tls.h"
+#include "textflag.h"
+#include "funcdata.h"
+
+`
+
+func printStub(buf *bytes.Buffer, def abigen.SysDef) {
+ fmt.Fprintf(buf, "func vdsoCall_zx_%s(", def.Name)
+ for i, arg := range def.Args {
+ if arg.Type == (abigen.SysType{}) {
+ continue
+ }
+ if i > 0 {
+ fmt.Fprint(buf, ", ")
+ }
+ fmt.Fprintf(buf, "%s ", arg.Name)
+ fmt.Fprintf(buf, "%s", arg.Type.NativeType())
+ }
+ fmt.Fprint(buf, ")")
+ if def.Ret != (abigen.SysType{}) {
+ fmt.Fprint(buf, " ")
+ fmt.Fprintf(buf, "%s", def.Ret.NativeType())
+ }
+ fmt.Fprint(buf, "\n")
+}
+
+// amd64RegArgs is the amd64 registers in function argument calling convention order.
+var amd64RegArgs = []string{"DI", "SI", "DX", "CX", "R8", "R9", "R12", "R13"}
+
+// arm64RegArgs is the arm64 registers in function argument calling convention order.
+var arm64RegArgs = []string{"R0", "R1", "R2", "R3", "R4", "R5", "R6", "R7"}
+
+// blockingSyscalls is a map of known syscalls which may block.
+// TODO(dhobsd): Is this list accurate? Potentially add nanosleep or others.
+var blockingSyscalls = map[string]bool{
+ "channel_call": true,
+ "object_wait_many": true,
+ "object_wait_one": true,
+ "port_wait": true,
+}
+
+func printAsm(buf *bytes.Buffer, def abigen.SysDef) {
+ // The summed size of all arguments.
+ argSize := 0
+ for _, arg := range def.Args {
+ sz := arg.Type.Size()
+ if *arch == "arm64" && sz == 1 {
+ sz = 8
+ }
+ for argSize%sz != 0 {
+ // Add padding until the 'argSize' is aligned to the type we are adding.
+ argSize++
+ }
+ argSize += sz
+ }
+ if argSize%8 == 4 {
+ // Force the return argument on the stack to be 8-byte aligned, not 4-byte aligned
+ argSize += 4
+ }
+ retSize := def.Ret.Size()
+
+ var frameSize int
+ var regArgs []string
+ var callIns, retReg, suffix4, suffix8 string
+ switch *arch {
+ case "amd64":
+ regArgs = amd64RegArgs
+ callIns = "CALL"
+ retReg = "AX"
+ suffix8 = "Q"
+ suffix4 = "L"
+ frameSize = 8
+ switch len(def.Args) {
+ case 7:
+ frameSize += 16 + 8
+ case 8:
+ frameSize += 16 + 2*8
+ }
+ case "arm64":
+ regArgs = arm64RegArgs
+ callIns = "BL"
+ retReg = "R0"
+ suffix8 = "D"
+ suffix4 = "W"
+ default:
+ panic(fmt.Sprintf("arch=%s not supported", *arch))
+ }
+
+ fmt.Fprintf(buf, "TEXT runtime·vdsoCall_zx_%s(SB),NOSPLIT,$%d-%d\n", def.Name, frameSize, argSize+retSize)
+ fmt.Fprint(buf, "\tGO_ARGS\n")
+ fmt.Fprint(buf, "\tNO_LOCAL_POINTERS\n")
+
+ // Set vdso{PC,SP} so that pprof tracebacks work for VDSO calls.
+ switch *arch {
+ case "amd64":
+ fmt.Fprint(buf, "\tget_tls(CX)\n")
+ fmt.Fprint(buf, "\tMOVQ g(CX), AX\n")
+ fmt.Fprint(buf, "\tMOVQ g_m(AX), R14\n")
+ fmt.Fprint(buf, "\tPUSHQ R14\n")
+ fmt.Fprintf(buf, "\tMOVQ %d(SP), DX\n", frameSize+16)
+ fmt.Fprint(buf, "\tMOVQ DX, m_vdsoPC(R14)\n")
+ fmt.Fprintf(buf, "\tLEAQ %d(SP), DX\n", frameSize+16)
+ fmt.Fprint(buf, "\tMOVQ DX, m_vdsoSP(R14)\n")
+ case "arm64":
+ fmt.Fprint(buf, "\tMOVD g_m(g), R21\n")
+ fmt.Fprint(buf, "\tMOVD LR, m_vdsoPC(R21)\n")
+ fmt.Fprint(buf, "\tMOVD RSP, R20\n")
+ fmt.Fprint(buf, "\tMOVD R20, m_vdsoSP(R21)\n")
+ }
+
+ if _, ok := blockingSyscalls[def.Name]; ok {
+ fmt.Fprintf(buf, "\tCALL runtime·entersyscall(SB)\n")
+ }
+ off := 0
+ for i, arg := range def.Args {
+ name := arg.Name
+ suffix := suffix8
+ t := arg.Type
+ sz := t.Size()
+ if sz == 4 {
+ suffix = suffix4
+ } else if *arch == "arm64" && sz == 1 {
+ sz = 8
+ }
+ for off%sz != 0 {
+ // Add padding until the offset is aligned to the type we are accessing
+ off++
+ }
+
+ fmt.Fprintf(buf, "\tMOV%s %s+%d(FP), %s\n", suffix, name, off, regArgs[i])
+ off += sz
+ }
+ switch *arch {
+ case "amd64":
+ if len(def.Args) >= 7 {
+ fmt.Fprintf(buf, "\tMOVQ SP, BP // BP is preserved across vsdo call by the x86-64 ABI\n")
+ fmt.Fprintf(buf, "\tANDQ $~15, SP // stack alignment for x86-64 ABI\n")
+ if len(def.Args) == 8 {
+ fmt.Fprintf(buf, "\tPUSHQ R13\n")
+ }
+ fmt.Fprintf(buf, "\tPUSHQ R12\n")
+ }
+ fmt.Fprintf(buf, "\tMOVQ vdso_zx_%s(SB), AX\n", def.Name)
+ fmt.Fprintf(buf, "\tCALL AX\n")
+ if len(def.Args) >= 7 {
+ fmt.Fprintf(buf, "\tPOPQ R12\n")
+ if len(def.Args) == 8 {
+ fmt.Fprintf(buf, "\tPOPQ R13\n")
+ }
+ fmt.Fprintf(buf, "\tMOVQ BP, SP\n")
+ }
+ case "arm64":
+ fmt.Fprintf(buf, "\tBL vdso_zx_%s(SB)\n", def.Name)
+ }
+ if retSize := def.Ret.Size(); retSize > 0 {
+ suffix := suffix8
+ if retSize == 4 {
+ suffix = suffix4
+ }
+ fmt.Fprintf(buf, "\tMOV%s %s, ret+%d(FP)\n", suffix, retReg, argSize)
+ }
+ if _, ok := blockingSyscalls[def.Name]; ok {
+ fmt.Fprintf(buf, "\t%s runtime·exitsyscall(SB)\n", callIns)
+ }
+ // Clear vdsoSP. sigprof only checks vdsoSP for generating tracebacks, so we can leave vdsoPC alone.
+ switch *arch {
+ case "amd64":
+ fmt.Fprintf(buf, "\tPOPQ R14\n")
+ fmt.Fprintf(buf, "\tMOVQ $0, m_vdsoSP(R14)\n")
+ case "arm64":
+ fmt.Fprint(buf, "\tMOVD g_m(g), R21\n")
+ fmt.Fprintf(buf, "\tMOVD $0, m_vdsoSP(R21)\n")
+ }
+ fmt.Fprintf(buf, "\tRET\n")
+}
diff --git a/src/runtime/netpoll_stub.go b/src/runtime/netpoll_stub.go
index f585333..4eb8f6a 100644
--- a/src/runtime/netpoll_stub.go
+++ b/src/runtime/netpoll_stub.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build plan9
+// +build fuchsia plan9
package runtime
diff --git a/src/runtime/os_fuchsia.go b/src/runtime/os_fuchsia.go
new file mode 100644
index 0000000..4cf764e
--- /dev/null
+++ b/src/runtime/os_fuchsia.go
@@ -0,0 +1,498 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package runtime
+
+import (
+ "runtime/internal/atomic"
+ "syscall/zx"
+ "unsafe"
+)
+
+type mOS struct{}
+
+type sigset struct{}
+
+//go:nosplit
+func getRandomData(r []byte) {
+ zx.RandRead(r)
+}
+
+//go:nosplit
+func futexsleep(addr *uint32, val uint32, ns int64) {
+ deadline := zx.Sys_deadline_after(zx.Duration(ns))
+ if ns < 0 {
+ deadline = zx.Time(zx.TimensecInfinite)
+ }
+ zx.Sys_futex_wait((*int32)(unsafe.Pointer(addr)), int32(val), zx.HandleInvalid, deadline)
+}
+
+//go:nosplit
+func futexwakeup(addr *uint32, cnt uint32) {
+ zx.Sys_futex_wake((*int32)(unsafe.Pointer(addr)), cnt)
+}
+
+//go:nosplit
+func osyield() {
+ zx.Sys_nanosleep(0)
+}
+
+// cgocallm0 calls a C function on the current stack.
+//
+// It is intended for use inside functions like osinit that run
+// before mstart directly on an OS thread stack.
+//
+// If in doubt, do not use.
+func cgocallm0(fn, arg unsafe.Pointer)
+
+func osinit() {
+ if _cgo_get_initial_handles != nil {
+ cgocallm0(_cgo_get_initial_handles, unsafe.Pointer(&fdioHandles))
+ for i := 0; i < 3; i = i + 1 {
+ zx.StdioHandles[i] = fdioHandles.stdioClones[i]
+ zx.StdioHandleTypes[i] = int(fdioHandles.stdioCloneTypes[i])
+ }
+ zx.ProcHandle = zx.Handle(fdioHandles.processSelf)
+ zx.VMARRoot = zx.VMAR(fdioHandles.vmarRootSelf)
+ } else {
+ // TODO: implement cgo-less init
+ println("runtime: no fuchsia process handle without cgo yet")
+ exit(2)
+ }
+
+ ncpu = int32(zx.Sys_system_get_num_cpus())
+ physPageSize = 4096
+}
+
+func parseRootNS() {
+ if fdioHandles.rootNSNumHandles > 0 {
+ const maxHandleCount = 1 << 20 // arbitrary
+ paths := (*(*[maxHandleCount]*byte)(unsafe.Pointer(fdioHandles.rootNSPaths)))[:fdioHandles.rootNSNumHandles]
+ handles := (*(*[maxHandleCount]zx.Handle)(unsafe.Pointer(fdioHandles.rootNSHandles)))[:fdioHandles.rootNSNumHandles]
+ zx.RootNSMap = make(map[string]zx.Handle)
+ for i, p := range paths {
+ zx.RootNSMap[gostring(p)] = handles[i]
+ }
+ }
+}
+
+// Filled in by runtime/cgo when linked into binary.
+
+var (
+ _cgo_get_initial_handles unsafe.Pointer
+ _cgo_get_thread_self_handle unsafe.Pointer
+)
+
+//go:nosplit
+func minit() {
+ var h zx.Handle
+ asmcgocall(_cgo_get_thread_self_handle, unsafe.Pointer(&h))
+ atomic.Storeuintptr(&getg().m.thread, uintptr(h))
+}
+
+//go:nosplit
+func unminit() {
+ // TODO
+}
+
+func sigpanic() {
+ // TODO
+}
+
+func mpreinit(mp *m) {
+ // TODO
+}
+
+//go:nosplit
+func msigsave(mp *m) {
+ // TODO
+}
+
+//go:nosplit
+func msigrestore(sigmask sigset) {
+ // TODO
+}
+
+func initsig(preinit bool) {
+ // TODO
+}
+
+//go:nosplit
+func sigblock() {
+ // TODO
+}
+
+func sigenable(sig uint32) {
+ // TODO
+}
+
+func sigdisable(sig uint32) {
+ // TODO
+}
+
+func sigignore(sig uint32) {
+ // TODO
+}
+
+func crash() {
+ *(*int32)(nil) = 0
+}
+
+func threadinit(mp *m)
+
+var gothreadname = []byte("gothread")
+
+//go:nowritebarrier
+func newosproc(mp *m) {
+ stk := unsafe.Pointer(mp.g0.stack.hi)
+ p := zx.Handle(0) // TODO: only works due to temporary hack in zircon
+ var h zx.Handle
+ status := zx.Sys_thread_create(p, &gothreadname[0], uint(len(gothreadname)), 0, &h)
+ if status < 0 {
+ println("runtime: newosproc zx.Sys_thread_create failed:", h)
+ exit(2)
+ }
+
+ mp.thread = uintptr(h)
+
+ status = zx.Sys_thread_start(h, zx.Vaddr(funcPC(threadinit)), zx.Vaddr(stk), uintptr(unsafe.Pointer(mp)), 0)
+ if status < 0 {
+ println("runtime: newosproc zx.Sys_thread_start failed:", h)
+ exit(2)
+ }
+}
+
+type zx_proc_args struct {
+ protocol uint32
+ version uint32
+ handle_info_off uint32
+ args_off uint32
+ args_num uint32
+}
+
+type zx_proc_info struct {
+ magic uint32
+ version uint32
+ next_tls_slot uint32
+ proc_args *zx_proc_args
+ handle *zx.Handle
+ handle_info *uint32
+ handle_count int32
+ argv **byte
+ argc int32
+}
+
+type zx_tls_root struct {
+ self *zx_tls_root
+ proc *zx_proc_info
+ magic uint32
+ flags uint16
+ maxslots uint16
+ slots [8]uintptr // has length maxslots
+}
+
+func resetcpuprofiler(hz int32) {
+ // TODO
+}
+
+// fdio_init matches a Go struct of the same name in gcc_fdio.c.
+type fdio_init struct {
+ stdioClones [3]zx.Handle
+ stdioCloneNumHandles [3]uint32
+ stdioCloneTypes [3]uint32
+ processSelf zx.Handle
+ vmarRootSelf zx.Handle
+ envlen int32
+ environ **byte
+ _ [4]byte
+ rootNSNumHandles int32
+ rootNSHandles *zx.Handle
+ rootNSPaths **byte
+}
+
+var fdioHandles fdio_init
+
+func goenvs() {
+ if _cgo_get_initial_handles != nil {
+ const maxEnvSize = 1 << 20 // arbitrary
+ envp := (*(*[maxEnvSize]*byte)(unsafe.Pointer(fdioHandles.environ)))[:fdioHandles.envlen]
+ envs = make([]string, len(envp))
+ for i, e := range envp {
+ envs[i] = gostring(e)
+ }
+ // TODO: find a better place to call this
+ parseRootNS()
+ } else {
+ // TODO: implement cgo-less init
+ println("runtime: no fuchsia process handle without cgo yet")
+ exit(2)
+ }
+}
+
+const _NSIG = 65 // TODO
+
+const (
+ ZX_CLOCK_MONOTONIC = 0
+ ZX_HANDLE_INVALID = 0
+ ZX_INFO_THREAD = uint32(10)
+ ZX_OK = int32(0)
+ ZX_THREAD_STATE_GENERAL_REGS = uint32(0)
+ ZX_THREAD_STATE_NEW = uint32(0)
+ ZX_THREAD_SUSPENDED = uint32(1 << 5)
+ ZX_THREAD_TERMINATED = uint32(1 << 3)
+ ZX_TIME_INFINITE = int64(^uint64(1 << 63))
+ ZX_TIMER_SIGNALED = uint32(1 << 3)
+ ZX_TIMER_SLACK_EARLY = 1
+)
+
+//go:nosplit
+func nanotime() int64 {
+ return int64(zx.Sys_clock_get(ZX_CLOCK_MONOTONIC))
+}
+
+//go:linkname time_now time.now
+//go:nosplit
+func time_now() (sec int64, nsec int32, mono int64) {
+ const ZX_CLOCK_UTC = 1
+ x := int64(zx.Sys_clock_get(ZX_CLOCK_UTC))
+ return int64(x / 1e9), int32(x % 1e9), nanotime()
+}
+
+func unixnanotime() int64 {
+ return nanotime()
+}
+
+// #define LOGBUF_MAX (ZX_LOG_RECORD_MAX - sizeof(zx_log_record_t))
+const logBufMax = 224
+
+var logger zx.Handle
+var logBufferArray [logBufMax]byte
+var logBufferN int
+
+//go:nosplit
+func write(fd uintptr, buf unsafe.Pointer, n int32) int32 {
+ if fd != 1 && fd != 2 {
+ panic("runtime.write(): can not write to non-log fd")
+ }
+
+ // This initialization mechanism is not thread-safe, but if the only calls to 'write' with
+ // these file descriptors come from print, they will already be serialized by a lock in
+ // print's implementation.
+ if logger <= 0 {
+ zx.Sys_debuglog_create(0, 0, &logger)
+ logBufferN = 0
+ }
+ // Ideally this should panic, but that would go down "blind", which is arguably worse.
+ if logger <= 0 {
+ return -1
+ }
+
+ for i := int32(0); i < n; i++ {
+ c := *(*byte)(unsafe.Pointer(uintptr(buf) + uintptr(i)))
+
+ if c == '\n' {
+ zx.Sys_debuglog_write(logger, 0, unsafe.Pointer(&logBufferArray[0]), uint(logBufferN))
+ logBufferN = 0
+ continue
+ }
+
+ if c < ' ' {
+ continue
+ }
+
+ logBufferArray[logBufferN] = c
+ logBufferN++
+
+ if logBufferN == len(logBufferArray) {
+ zx.Sys_debuglog_write(logger, 0, unsafe.Pointer(&logBufferArray[0]), uint(logBufferN))
+ logBufferN = 0
+ }
+ }
+
+ return n
+}
+
+//go:nosplit
+func exit(code int32) {
+ zx.Sys_process_exit(int64(code))
+}
+
+//go:nosplit
+func usleep(usec uint32) {
+ zx.Sys_nanosleep(zx.Sys_deadline_after(zx.Duration(usec * 1000)))
+}
+
+func signame(sig uint32) string {
+ return "unknown_sig" // TODO
+}
+
+// zircon_mktls
+//go:nosplit
+func zircon_mktls() {
+ // TODO
+}
+
+//go:nosplit
+func zircon_settls(val uintptr) {
+ // TODO: should call zx_set_object_property with property ZX_PROP_REGISTER_FS in amd64 or
+ // ZX_PROP_REGISTER_CP15 on arm.
+}
+
+//go:linkname os_sigpipe os.sigpipe
+func os_sigpipe() {
+ // TODO
+}
+
+// gsignalStack is unused on fuchsia
+type gsignalStack struct{}
+
+const (
+ profStkSize = uintptr(1 << 16)
+)
+
+var (
+ profTimer uint32 // timer handle
+ profThread uint32 // thread handle
+ profHz = ZX_TIME_INFINITE
+ profName = []byte("profiler")
+ profStk unsafe.Pointer
+ profStkFail = []byte("runtime: failed to allocate stack for the new OS thread\n")
+)
+
+type zxInfoThread struct {
+ state uint32
+ waitExceptionPortType uint32
+}
+
+//go:noescape
+//go:nosplit
+func profiler_object_wait_one(handle uint32, signals uint32, deadline int64, observed *uint32) int32
+
+func profilem(mp *m, thread uint32) {
+ // Ignore nascent threads.
+ var observed uint32
+ var info zxInfoThread
+ var actualSize uint64
+ var availSize uint64
+ if status := vdsoCall_zx_object_get_info(thread, ZX_INFO_THREAD, unsafe.Pointer(&info), uint(unsafe.Sizeof(info)), unsafe.Pointer(&actualSize), unsafe.Pointer(&availSize)); status != ZX_OK {
+ return
+ }
+ if info.state == ZX_THREAD_STATE_NEW {
+ return
+ }
+
+ // Wait for the thread to be suspended.
+ if status := profiler_object_wait_one(thread, ZX_THREAD_SUSPENDED|ZX_THREAD_TERMINATED, ZX_TIME_INFINITE, &observed); status != ZX_OK {
+ return
+ }
+
+ // Ignore threads that were terminated as a result of suspension.
+ if observed&ZX_THREAD_TERMINATED == ZX_THREAD_TERMINATED {
+ return
+ }
+
+ var r generalRegs
+ if status := vdsoCall_zx_thread_read_state(thread, ZX_THREAD_STATE_GENERAL_REGS, unsafe.Pointer(&r), uint(unsafe.Sizeof(r))); status != ZX_OK {
+ return
+ }
+
+ if mp.curg != nil {
+ sigprof(r.rPC(), r.rSP(), r.rLR(), mp.curg, mp)
+ } else {
+ sigprofNonGoPC(r.rPC())
+ }
+}
+
+// profileLoop is called when pprof CPU tracing is enabled. It runs without a p, hence nowritebarrierrec.
+//
+//go:nosplit
+//go:nowritebarrierrec
+func profileLoop() {
+ me := getg().m
+ for {
+ var observed uint32
+ if status := profiler_object_wait_one(profTimer, ZX_TIMER_SIGNALED, ZX_TIME_INFINITE, &observed); status != ZX_OK {
+ continue
+ }
+
+ // Scan over all threads and suspend them, then trace. Ideally, we'd scan over
+ // all of them and give them a chance to suspend before this, but I don't want
+ // to deal with allocation here.
+ first := (*m)(atomic.Loadp(unsafe.Pointer(&allm)))
+ for mp := first; mp != nil; mp = mp.alllink {
+ thread := uint32(atomic.Loaduintptr(&mp.thread))
+ // Do not profile threads blocked on Notes (this includes idle worker threads, idle timer thread,
+ // idle heap scavenger, etc.). Do not profile this thread.
+ if thread == ZX_HANDLE_INVALID || mp.profilehz == 0 || mp.blocked || mp == me {
+ continue
+ }
+
+ var token uint32
+ if status := vdsoCall_zx_task_suspend_token(thread, unsafe.Pointer(&token)); status == ZX_OK {
+ profilem(mp, thread)
+ }
+ vdsoCall_zx_handle_close(token)
+
+ }
+
+ due := vdsoCall_zx_deadline_after(profHz)
+ if status := vdsoCall_zx_timer_set(profTimer, due, ZX_TIMER_SLACK_EARLY); status != ZX_OK {
+ // TODO: what do?
+ return
+ }
+ }
+}
+
+// profileloop is defined in sys_fuchsia_{amd,arm}64.s
+func profileloop()
+
+func setProcessCPUProfiler(hz int32) {
+ // This function is entered in the critical section guarded by
+ // prof.signalLock in proc.go and is thus safe to assume the profiler's
+ // timer is created atomically.
+ if profTimer == ZX_HANDLE_INVALID {
+ if status := vdsoCall_zx_timer_create(ZX_TIMER_SLACK_EARLY, ZX_CLOCK_MONOTONIC, unsafe.Pointer(&profTimer)); status != ZX_OK {
+ // TODO: what do?
+ return
+ }
+
+ newm(profileLoop, nil)
+ }
+}
+
+func setThreadCPUProfiler(hz int32) {
+ // Don't do anything if we don't have a timer yet.
+ if profTimer == ZX_HANDLE_INVALID {
+ return
+ }
+
+ atomic.Store((*uint32)(unsafe.Pointer(&getg().m.profilehz)), uint32(hz))
+
+ if hz > 0 {
+ ns := int64(int64(1000000000) / int64(hz))
+ // Bound tracing frequency to microseconds. This is likely
+ // already well above the granularity traces can actually
+ // provide.
+ if ns < 1000 {
+ ns = 1000
+ }
+
+ profHz = ns
+ due := vdsoCall_zx_deadline_after(ns)
+ if status := vdsoCall_zx_timer_set(profTimer, due, ZX_TIMER_SLACK_EARLY); status != ZX_OK {
+ // TODO: what do?
+ return
+ }
+ } else {
+ if status := vdsoCall_zx_timer_cancel(profTimer); status != ZX_OK {
+ return
+ }
+ }
+}
+
+func exitThread(wait *uint32) {}
+
+//go:nosplit
+//go:nowritebarrierrec
+func clearSignalHandlers() {}
diff --git a/src/runtime/os_fuchsia_arm64.go b/src/runtime/os_fuchsia_arm64.go
new file mode 100644
index 0000000..143fe39
--- /dev/null
+++ b/src/runtime/os_fuchsia_arm64.go
@@ -0,0 +1,12 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package runtime
+
+import "syscall/zx"
+
+//go:nosplit
+func cputicks() int64 {
+ return int64(zx.Sys_ticks_get())
+}
diff --git a/src/runtime/pprof/pprof_test.go b/src/runtime/pprof/pprof_test.go
index 7c6043f..2865c85 100644
--- a/src/runtime/pprof/pprof_test.go
+++ b/src/runtime/pprof/pprof_test.go
@@ -325,6 +325,10 @@
// Use smaller size for Android to avoid crash.
heap = 100 << 20
}
+ if runtime.GOOS == "fuchsia" {
+ // Use smaller heap for Fuchsia to avoid crash.
+ heap = 100 << 20
+ }
if runtime.GOOS == "windows" && runtime.GOARCH == "arm" {
// Use smaller heap for Windows/ARM to avoid crash.
heap = 100 << 20
@@ -450,6 +454,10 @@
}
func TestMorestack(t *testing.T) {
+ if runtime.GOOS == "fuchsia" {
+ t.Skip("skipping on fuchsia")
+ }
+
testCPUProfile(t, stackContainsAll, []string{"runtime.newstack,runtime/pprof.growstack"}, avoidFunctions(), func(duration time.Duration) {
t := time.After(duration)
c := make(chan bool)
diff --git a/src/runtime/rt0_fuchsia_amd64.s b/src/runtime/rt0_fuchsia_amd64.s
new file mode 100644
index 0000000..40c92a3
--- /dev/null
+++ b/src/runtime/rt0_fuchsia_amd64.s
@@ -0,0 +1,8 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#include "textflag.h"
+
+TEXT _rt0_amd64_fuchsia(SB),NOSPLIT,$-8
+ JMP _rt0_amd64(SB)
diff --git a/src/runtime/rt0_fuchsia_arm64.s b/src/runtime/rt0_fuchsia_arm64.s
new file mode 100644
index 0000000..f28e28d
--- /dev/null
+++ b/src/runtime/rt0_fuchsia_arm64.s
@@ -0,0 +1,14 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#include "textflag.h"
+
+TEXT _rt0_arm64_fuchsia(SB),NOSPLIT,$-8
+ MOVD 0(RSP), R0 // argc
+ ADD $8, RSP, R1 // argv
+ BL main(SB)
+
+TEXT main(SB),NOSPLIT,$-8
+ MOVD $runtime·rt0_go(SB), R2
+ BL R2
diff --git a/src/runtime/runtime2.go b/src/runtime/runtime2.go
index df9cbae..17de639 100644
--- a/src/runtime/runtime2.go
+++ b/src/runtime/runtime2.go
@@ -814,6 +814,7 @@
waitReasonTraceReaderBlocked // "trace reader (blocked)"
waitReasonWaitForGCCycle // "wait for GC cycle"
waitReasonGCWorkerIdle // "GC worker (idle)"
+ waitReasonZXWait // "ZX wait"
)
var waitReasonStrings = [...]string{
@@ -841,6 +842,7 @@
waitReasonTraceReaderBlocked: "trace reader (blocked)",
waitReasonWaitForGCCycle: "wait for GC cycle",
waitReasonGCWorkerIdle: "GC worker (idle)",
+ waitReasonZXWait: "ZX wait",
}
func (w waitReason) String() string {
diff --git a/src/runtime/stubs2.go b/src/runtime/stubs2.go
index 57134f7..9a135af 100644
--- a/src/runtime/stubs2.go
+++ b/src/runtime/stubs2.go
@@ -8,6 +8,7 @@
// +build !nacl
// +build !js
// +build !darwin
+// +build !fuchsia
// +build !aix
package runtime
diff --git a/src/runtime/stubs3.go b/src/runtime/stubs3.go
index a9ff689..91aae78 100644
--- a/src/runtime/stubs3.go
+++ b/src/runtime/stubs3.go
@@ -8,6 +8,7 @@
// +build !nacl
// +build !freebsd
// +build !darwin
+// +build !fuchsia
// +build !aix
package runtime
diff --git a/src/runtime/sys_fuchsia_amd64.s b/src/runtime/sys_fuchsia_amd64.s
new file mode 100644
index 0000000..e909874
--- /dev/null
+++ b/src/runtime/sys_fuchsia_amd64.s
@@ -0,0 +1,87 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#include "go_asm.h"
+#include "go_tls.h"
+#include "textflag.h"
+
+TEXT runtime·threadinit(SB),NOSPLIT,$0
+ MOVQ DI, R8
+
+ MOVQ m_g0(R8), DX // g
+ MOVQ R8, g_m(DX)
+
+ // Layout new m scheduler stack on os stack.
+ // TODO: which os stack? do we need to make a new vmo?
+ LEAQ (-8*1024+104)(SP), BX
+ MOVQ BX, g_stackguard0(DX)
+ MOVQ BX, g_stackguard1(DX)
+ MOVQ BX, (g_stack+stack_lo)(DX)
+ MOVQ SP, (g_stack+stack_hi)(DX)
+
+ PUSHQ R8
+
+ // Set up tls.
+ LEAQ m_tls(R8), DI
+ CALL runtime·settls(SB)
+
+ get_tls(CX)
+
+ POPQ R8
+ MOVQ m_g0(R8), DX
+ MOVQ DX, g(CX)
+
+ CLD // convention is D is always left cleared
+ CALL runtime·stackcheck(SB) // clobbers AX,CX
+ CALL runtime·mstart(SB)
+ // TODO CALL syscall/zx·Sys_zircon_thread_exit(SB)
+ RET
+
+// Set TLS base to DI for the thread handle supplied in SI.
+TEXT runtime·settls(SB),NOSPLIT,$0
+ ADDQ $8, DI // ELF wants to use -8(FS)
+ PUSHQ DI
+ LEAQ 0(SP), DX // object_set_property takes a pointer to the base
+
+ SUBQ $28, SP
+
+ MOVL SI, 0(SP) // thread handle
+ MOVL $4, 4(SP) // ZX_PROP_REGISTER_FS
+ MOVQ DX, 8(SP) // pointer to fs base
+ MOVQ $8, 16(SP) // size
+ CALL runtime·vdsoCall_zx_object_set_property(SB)
+
+ // Stash return and restore SP
+ MOVL 24(SP), AX
+ ADDQ $28, SP
+ TESTL $0, AX
+ JZ 2(PC)
+ MOVL $0xf1, 0xf1 // crash
+ POPQ DI
+ RET
+
+TEXT ·cgocallm0(SB),NOSPLIT,$0-20
+ MOVQ fn+0(FP), AX
+ MOVQ arg+8(FP), DI
+
+ MOVQ SP, BP // BP is callee-save in the x86-64 ABI
+
+ ANDQ $~15, SP
+ CALL AX
+
+ MOVQ BP, SP
+ get_tls(CX)
+ RET
+
+// This implementation lives separately because the m/g for the profiler
+// are faked, and this causes issues with runtime.exitsyscall not returning.
+TEXT runtime·profiler_object_wait_one(SB),NOSPLIT,$0-28
+ MOVL handle+0(FP), DI
+ MOVL signals+4(FP), SI
+ MOVQ deadline+8(FP), DX
+ MOVQ observed+16(FP), CX
+ MOVQ vdso_zx_object_wait_one(SB), AX
+ CALL AX
+ MOVL AX, ret+24(FP)
+ RET
diff --git a/src/runtime/sys_fuchsia_arm64.s b/src/runtime/sys_fuchsia_arm64.s
new file mode 100644
index 0000000..a391e7d
--- /dev/null
+++ b/src/runtime/sys_fuchsia_arm64.s
@@ -0,0 +1,53 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#include "go_asm.h"
+#include "funcdata.h"
+#include "textflag.h"
+
+TEXT runtime·threadinit(SB),NOSPLIT,$0
+ // Layout new m scheduler stack on os stack.
+ // TODO: which os stack? do we need to make a new vmo?
+
+ MOVD m_g0(R0), g
+ MOVD R0, g_m(g)
+
+ MOVD RSP, R7
+ MOVD $(-64*1024)(R7), R0
+ MOVD R0, g_stackguard0(g)
+ MOVD R0, g_stackguard1(g)
+ MOVD R0, (g_stack+stack_lo)(g)
+ MOVD R7, (g_stack+stack_hi)(g)
+
+ BL runtime·mstart(SB)
+ MOVD $0, R0
+ MOVD R0, (R0) // boom
+ UNDEF
+
+TEXT ·cgocallm0(SB),NOSPLIT,$0-20
+ MOVD fn+0(FP), R1
+ MOVD arg+8(FP), R0
+
+ MOVD RSP, R19 // R19 is callee-save by C
+ MOVD g, R21 // R21 is callee-save by C
+ MOVD RSP, R7
+ ADD $-32, R7, R7
+ AND $~15, R7
+ MOVD R7, RSP // align stack for C
+ BL R1
+
+ MOVD R19, RSP // restore SP
+ MOVD R21, g // restore g
+ RET
+
+// This implementation lives separately because the m/g for the profiler
+// are faked, and this causes issues with runtime.exitsyscall not returning.
+TEXT runtime·profiler_object_wait_one(SB),NOSPLIT,$0-28
+ MOVW handle+0(FP), R0
+ MOVW signals+4(FP), R1
+ MOVD deadline+8(FP), R2
+ MOVD observed+16(FP), R3
+ BL vdso_zx_object_wait_one(SB)
+ MOVW R0, ret+24(FP)
+ RET
diff --git a/src/runtime/timestub.go b/src/runtime/timestub.go
index 459bf8e..c7a2bc4 100644
--- a/src/runtime/timestub.go
+++ b/src/runtime/timestub.go
@@ -6,6 +6,7 @@
// indirectly, in terms of walltime and nanotime assembly.
// +build !windows
+// +build !fuchsia
package runtime
diff --git a/src/runtime/tls_arm64.h b/src/runtime/tls_arm64.h
index c29fa7f..c2480d7 100644
--- a/src/runtime/tls_arm64.h
+++ b/src/runtime/tls_arm64.h
@@ -9,6 +9,9 @@
#ifdef GOOS_linux
#define TLS_linux
#endif
+#ifdef GOOS_fuchsia
+#define TLS_linux
+#endif
#ifdef TLS_linux
#define TPIDR TPIDR_EL0
#define MRS_TPIDR_R0 WORD $0xd53bd040 // MRS TPIDR_EL0, R0
diff --git a/src/runtime/vdso_elf.go b/src/runtime/vdso_elf.go
new file mode 100644
index 0000000..d3cefdb
--- /dev/null
+++ b/src/runtime/vdso_elf.go
@@ -0,0 +1,58 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+//
+// +build linux fuchsia
+// +build 386 amd64 arm arm64 ppc64 ppc64le
+
+package runtime
+
+import "unsafe"
+
+const (
+ _AT_SYSINFO_EHDR = 33
+
+ _PT_LOAD = 1 /* Loadable program segment */
+ _PT_DYNAMIC = 2 /* Dynamic linking information */
+
+ _PF_X = 1 /* Executable PH segment */
+
+ _DT_NULL = 0 /* Marks end of dynamic section */
+ _DT_HASH = 4 /* Dynamic symbol hash table */
+ _DT_STRTAB = 5 /* Address of string table */
+ _DT_SYMTAB = 6 /* Address of symbol table */
+ _DT_GNU_HASH = 0x6ffffef5 /* GNU-style dynamic symbol hash table */
+ _DT_VERSYM = 0x6ffffff0
+ _DT_VERDEF = 0x6ffffffc
+
+ _VER_FLG_BASE = 0x1 /* Version definition of file itself */
+
+ _SHN_UNDEF = 0 /* Undefined section */
+
+ _SHT_DYNSYM = 11 /* Dynamic linker symbol table */
+
+ _STT_FUNC = 2 /* Symbol is a code object */
+
+ _STT_NOTYPE = 0 /* Symbol type is not specified */
+
+ _STB_GLOBAL = 1 /* Global symbol */
+ _STB_WEAK = 2 /* Weak symbol */
+
+ _EI_NIDENT = 16
+
+ // Maximum indices for the array types used when traversing the vDSO ELF structures.
+ // Computed from architecture-specific max provided by vdso_linux_*.go
+ vdsoSymTabSize = vdsoArrayMax / unsafe.Sizeof(elfSym{})
+ vdsoDynSize = vdsoArrayMax / unsafe.Sizeof(elfDyn{})
+ vdsoSymStringsSize = vdsoArrayMax // byte
+ vdsoVerSymSize = vdsoArrayMax / 2 // uint16
+ vdsoHashSize = vdsoArrayMax / 4 // uint32
+
+ // vdsoBloomSizeScale is a scaling factor for gnuhash tables which are uint32 indexed,
+ // but contain uintptrs
+ vdsoBloomSizeScale = unsafe.Sizeof(uintptr(0)) / 4 // uint32
+)
+
+/* How to extract and insert information held in the st_info field. */
+func _ELF_ST_BIND(val byte) byte { return val >> 4 }
+func _ELF_ST_TYPE(val byte) byte { return val & 0xf }
diff --git a/src/runtime/vdso_elf64.go b/src/runtime/vdso_elf64.go
index 7c9bd96..90a3c9e 100644
--- a/src/runtime/vdso_elf64.go
+++ b/src/runtime/vdso_elf64.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build linux
+// +build linux fuchsia
// +build amd64 arm64 ppc64 ppc64le
package runtime
diff --git a/src/runtime/vdso_fuchsia.go b/src/runtime/vdso_fuchsia.go
new file mode 100644
index 0000000..9e4c7f3
--- /dev/null
+++ b/src/runtime/vdso_fuchsia.go
@@ -0,0 +1,160 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package runtime
+
+import "unsafe"
+
+// Look up symbols in the Fuchsia vDSO.
+//
+// When processes are spawned in Fuchsia, they are provided with a handle to a channel
+// and a pointer to where the vDSO is loaded. Syscalls may never be called directly;
+// on syscall entry, the kernel checks to see that the syscall was entered from the
+// vDSO. Because reading from the channel requires performing a syscall, we must
+// resolve symbols from the vDSO first.
+//
+// This is only performed when not using cgo. When a Go binary is built with cgo, libc
+// handles all of this.
+
+type vdsoSymbolKey struct {
+ name string
+ gnuHash uint32
+ ptr *uintptr
+}
+
+type vdsoInfo struct {
+ /* Load information */
+ loadAddr uintptr
+ loadBase uintptr /* loadAddr + p_vaddr */
+
+ /* Symbol table */
+ symtab *[vdsoSymTabSize]elfSym
+ symstrings *[vdsoSymStringsSize]byte
+ chain []uint32
+ bucket []uint32
+ symOff uint32
+ nBuckets uint32
+}
+
+var (
+ vdsoLoadBase uintptr
+ vdsoMemSize uintptr
+)
+
+// see vdso_keys_fuchsia.go for vdsoSymbolKeys[] and vdso*Sym vars
+
+func vdsoInit(info *vdsoInfo, hdr *elfEhdr) {
+ info.loadAddr = uintptr(unsafe.Pointer(hdr))
+
+ pt := unsafe.Pointer(info.loadAddr + uintptr(hdr.e_phoff))
+
+ // We need two things from the segment table: the load offset
+ // and the dynamic table.
+ var foundVaddr bool
+ var dyn *[vdsoDynSize]elfDyn
+ for i := uint16(0); i < hdr.e_phnum; i++ {
+ pt := (*elfPhdr)(add(pt, uintptr(i)*unsafe.Sizeof(elfPhdr{})))
+ switch pt.p_type {
+ case _PT_LOAD:
+ if !foundVaddr && pt.p_flags&_PF_X == _PF_X {
+ foundVaddr = true
+ info.loadBase = info.loadAddr + uintptr(pt.p_vaddr)
+ vdsoLoadBase = info.loadBase
+ vdsoMemSize = uintptr(pt.p_memsz)
+ }
+
+ case _PT_DYNAMIC:
+ dyn = (*[vdsoDynSize]elfDyn)(unsafe.Pointer(info.loadAddr + uintptr(pt.p_vaddr)))
+ }
+ }
+
+ if !foundVaddr || dyn == nil {
+ crash()
+ }
+
+ // Fish out the useful bits of the dynamic table.
+ var gnuhash *[vdsoHashSize]uint32
+ info.symstrings = nil
+ info.symtab = nil
+ for i := 0; dyn[i].d_tag != _DT_NULL; i++ {
+ dt := &dyn[i]
+ p := info.loadAddr + uintptr(dt.d_val)
+ switch dt.d_tag {
+ case _DT_STRTAB:
+ info.symstrings = (*[vdsoSymStringsSize]byte)(unsafe.Pointer(p))
+ case _DT_SYMTAB:
+ info.symtab = (*[vdsoSymTabSize]elfSym)(unsafe.Pointer(p))
+ case _DT_GNU_HASH:
+ gnuhash = (*[vdsoHashSize]uint32)(unsafe.Pointer(p))
+ }
+ }
+
+ if info.symstrings == nil || info.symtab == nil || gnuhash == nil {
+ crash()
+ }
+
+ // Parse the GNU hash table header.
+ info.nBuckets = gnuhash[0]
+ info.symOff = gnuhash[1]
+ bloomSize := gnuhash[2]
+ info.bucket = gnuhash[4+bloomSize*uint32(vdsoBloomSizeScale):][:info.nBuckets]
+ info.chain = gnuhash[4+bloomSize*uint32(vdsoBloomSizeScale)+info.nBuckets:]
+}
+
+func vdsoResolveSymbols(info *vdsoInfo) {
+ // Loop over the keys we wish to resolve and assign the symbol's offset to the
+ // pointer in the key table. We assume that all symbols we want to resolve
+ // exist, and crash if we are unable to resolve any of them.
+ for _, k := range vdsoSymbolKeys {
+ symIndex := info.bucket[k.gnuHash%info.nBuckets]
+
+ // Anything less than info.symOff is e.g. STN_UNDEF and will not be
+ // resolvable. Since that means we wouldn't be able to resolve this
+ // symbol we definitely need, crash.
+ if symIndex < info.symOff {
+ crash()
+ }
+
+ // For each symbol in this bucket, compare hashes and the name. If the
+ // symbol is not found, crash.
+ for ; ; symIndex++ {
+ hash := info.chain[symIndex-info.symOff]
+ sym := &info.symtab[symIndex]
+ if hash|1 == k.gnuHash|1 && k.name == gostringnocopy(&info.symstrings[sym.st_name]) {
+ typ := _ELF_ST_TYPE(sym.st_info)
+ bind := _ELF_ST_BIND(sym.st_info)
+ // If this isn't a function, doesn't have the appropriate binding, or
+ // has an undefined index, crash.
+ if typ != _STT_FUNC || (bind != _STB_GLOBAL && bind != _STB_WEAK) || sym.st_shndx == _SHN_UNDEF {
+ crash()
+ }
+
+ // We've found our symbol, assign its address and continue on to the
+ // next symbol.
+ *k.ptr = info.loadAddr + uintptr(sym.st_value)
+ break
+ }
+
+ if hash&1 != 0 {
+ // We made it to the end of this chain without finding
+ // our symbol. We won't find it. Crash.
+ crash()
+ }
+ }
+ }
+}
+
+func loadVDSO(val uintptr) {
+ var info vdsoInfo
+ // TODO(dhobsd): rsc says in vdso_linux.go that the compiler thinks info
+ // escapes. Remove/fix/investigate this comment at some point.
+ info1 := (*vdsoInfo)(noescape(unsafe.Pointer(&info)))
+ vdsoInit(info1, (*elfEhdr)(unsafe.Pointer(val)))
+ vdsoResolveSymbols(info1)
+}
+
+// inVDSOPage returns whether an observed PC falls within the VDSO mapping.
+func inVDSOPage(pc uintptr) bool {
+ return pc >= vdsoLoadBase && pc < vdsoLoadBase+vdsoMemSize
+}
diff --git a/src/runtime/vdso_in_none.go b/src/runtime/vdso_in_none.go
index f2d6bb5..fa388ba 100644
--- a/src/runtime/vdso_in_none.go
+++ b/src/runtime/vdso_in_none.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build linux,!386,!amd64,!arm,!arm64,!ppc64,!ppc64le !linux
+// +build linux,!386,!amd64,!arm,!arm64,!ppc64,!ppc64le !linux,!fuchsia
package runtime
diff --git a/src/runtime/vdso_keys_fuchsia.go b/src/runtime/vdso_keys_fuchsia.go
new file mode 100644
index 0000000..04cf6a5
--- /dev/null
+++ b/src/runtime/vdso_keys_fuchsia.go
@@ -0,0 +1,1088 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Keys for vDSO symbols.
+// Generated by mkfuchsiavdso.go, do not edit.
+
+package runtime
+
+import "unsafe"
+
+const (
+ // vdsoArrayMax is the byte-size of a maximally sized array on this architecture.
+ // See cmd/compile/internal/amd64/galign.go arch.MAXWIDTH initialization.
+ vdsoArrayMax = 1<<50 - 1
+)
+
+var vdsoSymbolKeys = []vdsoSymbolKey{
+ {"_zx_clock_get", 0x3fb5d7c0, &vdso_zx_clock_get},
+ {"_zx_clock_get_new", 0x5291b129, &vdso_zx_clock_get_new},
+ {"_zx_clock_get_monotonic", 0xb00e6115, &vdso_zx_clock_get_monotonic},
+ {"_zx_nanosleep", 0xe9d6145a, &vdso_zx_nanosleep},
+ {"_zx_ticks_get", 0xaeb30a32, &vdso_zx_ticks_get},
+ {"_zx_ticks_per_second", 0x6ed47574, &vdso_zx_ticks_per_second},
+ {"_zx_deadline_after", 0x6253eb5c, &vdso_zx_deadline_after},
+ {"_zx_clock_adjust", 0x87cf38ab, &vdso_zx_clock_adjust},
+ {"_zx_system_get_dcache_line_size", 0x2d6d6511, &vdso_zx_system_get_dcache_line_size},
+ {"_zx_system_get_num_cpus", 0x8e92a0c2, &vdso_zx_system_get_num_cpus},
+ {"_zx_system_get_version", 0x206d39de, &vdso_zx_system_get_version},
+ {"_zx_system_get_physmem", 0x5a0e027b, &vdso_zx_system_get_physmem},
+ {"_zx_system_get_features", 0x42682df7, &vdso_zx_system_get_features},
+ {"_zx_cache_flush", 0x319eccca, &vdso_zx_cache_flush},
+ {"_zx_handle_close", 0xe769f876, &vdso_zx_handle_close},
+ {"_zx_handle_close_many", 0x8a9a3aaa, &vdso_zx_handle_close_many},
+ {"_zx_handle_duplicate", 0x3f0a83b, &vdso_zx_handle_duplicate},
+ {"_zx_handle_replace", 0xdc2d9edc, &vdso_zx_handle_replace},
+ {"_zx_object_wait_one", 0xed850621, &vdso_zx_object_wait_one},
+ {"_zx_object_wait_many", 0x9e247bd4, &vdso_zx_object_wait_many},
+ {"_zx_object_wait_async", 0x61e4dcdd, &vdso_zx_object_wait_async},
+ {"_zx_object_signal", 0x460ab89, &vdso_zx_object_signal},
+ {"_zx_object_signal_peer", 0xe90c8694, &vdso_zx_object_signal_peer},
+ {"_zx_object_get_property", 0xd60c8aef, &vdso_zx_object_get_property},
+ {"_zx_object_set_property", 0x2174eb7b, &vdso_zx_object_set_property},
+ {"_zx_object_get_info", 0x7582ddf6, &vdso_zx_object_get_info},
+ {"_zx_object_get_child", 0x256ecc2e, &vdso_zx_object_get_child},
+ {"_zx_object_set_profile", 0x7d1d2727, &vdso_zx_object_set_profile},
+ {"_zx_channel_create", 0xe5199281, &vdso_zx_channel_create},
+ {"_zx_channel_read", 0xe7169b09, &vdso_zx_channel_read},
+ {"_zx_channel_read_etc", 0x77c4cc84, &vdso_zx_channel_read_etc},
+ {"_zx_channel_write", 0xca4bbc18, &vdso_zx_channel_write},
+ {"_zx_channel_call_noretry", 0xb5ad0b5b, &vdso_zx_channel_call_noretry},
+ {"_zx_channel_call_finish", 0x85ce3de9, &vdso_zx_channel_call_finish},
+ {"_zx_channel_call", 0xe70e51c9, &vdso_zx_channel_call},
+ {"_zx_socket_create", 0xf536e851, &vdso_zx_socket_create},
+ {"_zx_socket_write", 0x5e2d97e8, &vdso_zx_socket_write},
+ {"_zx_socket_read", 0xb5443cd9, &vdso_zx_socket_read},
+ {"_zx_socket_share", 0x5ddf97d0, &vdso_zx_socket_share},
+ {"_zx_socket_accept", 0xef7c1f4d, &vdso_zx_socket_accept},
+ {"_zx_socket_shutdown", 0x78afef9, &vdso_zx_socket_shutdown},
+ {"_zx_thread_exit", 0xed44fe6, &vdso_zx_thread_exit},
+ {"_zx_thread_create", 0x100e8a20, &vdso_zx_thread_create},
+ {"_zx_thread_start", 0xea59505a, &vdso_zx_thread_start},
+ {"_zx_thread_read_state", 0x82fd0a88, &vdso_zx_thread_read_state},
+ {"_zx_thread_write_state", 0xb9265eb7, &vdso_zx_thread_write_state},
+ {"_zx_process_exit", 0xc7f8a64d, &vdso_zx_process_exit},
+ {"_zx_process_create", 0xa3a21647, &vdso_zx_process_create},
+ {"_zx_process_start", 0xc80873a1, &vdso_zx_process_start},
+ {"_zx_process_read_memory", 0x883ab627, &vdso_zx_process_read_memory},
+ {"_zx_process_write_memory", 0x18162116, &vdso_zx_process_write_memory},
+ {"_zx_job_create", 0x6b9cbb63, &vdso_zx_job_create},
+ {"_zx_job_set_policy", 0xa45d60ea, &vdso_zx_job_set_policy},
+ {"_zx_task_bind_exception_port", 0xbf7013d6, &vdso_zx_task_bind_exception_port},
+ {"_zx_task_suspend", 0xe13ad509, &vdso_zx_task_suspend},
+ {"_zx_task_suspend_token", 0x341e98a9, &vdso_zx_task_suspend_token},
+ {"_zx_task_resume_from_exception", 0x185b8e99, &vdso_zx_task_resume_from_exception},
+ {"_zx_task_kill", 0x1ae4e313, &vdso_zx_task_kill},
+ {"_zx_event_create", 0x4c39490a, &vdso_zx_event_create},
+ {"_zx_eventpair_create", 0xe3fd9c16, &vdso_zx_eventpair_create},
+ {"_zx_futex_wait", 0xb089e255, &vdso_zx_futex_wait},
+ {"_zx_futex_wake", 0xb089e288, &vdso_zx_futex_wake},
+ {"_zx_futex_requeue", 0xd509be7c, &vdso_zx_futex_requeue},
+ {"_zx_futex_wake_single_owner", 0x63970173, &vdso_zx_futex_wake_single_owner},
+ {"_zx_futex_requeue_single_owner", 0x8f9a9e7, &vdso_zx_futex_requeue_single_owner},
+ {"_zx_futex_get_owner", 0xf16dec6a, &vdso_zx_futex_get_owner},
+ {"_zx_port_create", 0x5294baed, &vdso_zx_port_create},
+ {"_zx_port_queue", 0x8f22883e, &vdso_zx_port_queue},
+ {"_zx_port_wait", 0xfc97666e, &vdso_zx_port_wait},
+ {"_zx_port_cancel", 0x5166105f, &vdso_zx_port_cancel},
+ {"_zx_timer_create", 0x943773a9, &vdso_zx_timer_create},
+ {"_zx_timer_set", 0xa2689081, &vdso_zx_timer_set},
+ {"_zx_timer_cancel", 0x9308c91b, &vdso_zx_timer_cancel},
+ {"_zx_vmo_create", 0xb27a765a, &vdso_zx_vmo_create},
+ {"_zx_vmo_read", 0xe70ab4a2, &vdso_zx_vmo_read},
+ {"_zx_vmo_write", 0xc8c308d1, &vdso_zx_vmo_write},
+ {"_zx_vmo_get_size", 0x261c77c0, &vdso_zx_vmo_get_size},
+ {"_zx_vmo_set_size", 0x3932724c, &vdso_zx_vmo_set_size},
+ {"_zx_vmo_op_range", 0xa73d6b71, &vdso_zx_vmo_op_range},
+ {"_zx_vmo_create_child", 0xc755ed37, &vdso_zx_vmo_create_child},
+ {"_zx_vmo_set_cache_policy", 0xe509bad4, &vdso_zx_vmo_set_cache_policy},
+ {"_zx_vmo_replace_as_executable", 0xbd38e576, &vdso_zx_vmo_replace_as_executable},
+ {"_zx_vmar_allocate", 0x4cac85ef, &vdso_zx_vmar_allocate},
+ {"_zx_vmar_destroy", 0xc2294134, &vdso_zx_vmar_destroy},
+ {"_zx_vmar_map", 0xc7b00448, &vdso_zx_vmar_map},
+ {"_zx_vmar_unmap", 0x745a1b6b, &vdso_zx_vmar_unmap},
+ {"_zx_vmar_protect", 0x7bee8f8b, &vdso_zx_vmar_protect},
+ {"_zx_cprng_draw_once", 0x40248ce0, &vdso_zx_cprng_draw_once},
+ {"_zx_cprng_draw", 0x12929c5c, &vdso_zx_cprng_draw},
+ {"_zx_cprng_add_entropy", 0x1617dd47, &vdso_zx_cprng_add_entropy},
+ {"_zx_fifo_create", 0xf197cb2c, &vdso_zx_fifo_create},
+ {"_zx_fifo_read", 0x3ec8acf4, &vdso_zx_fifo_read},
+ {"_zx_fifo_write", 0x18400b63, &vdso_zx_fifo_write},
+ {"_zx_profile_create", 0x28e1bf39, &vdso_zx_profile_create},
+ {"_zx_vmar_unmap_handle_close_thread_exit", 0x5a372afb, &vdso_zx_vmar_unmap_handle_close_thread_exit},
+ {"_zx_futex_wake_handle_close_thread_exit", 0x49731cb8, &vdso_zx_futex_wake_handle_close_thread_exit},
+ {"_zx_debuglog_create", 0x2504f1, &vdso_zx_debuglog_create},
+ {"_zx_debuglog_write", 0x3f7aa088, &vdso_zx_debuglog_write},
+ {"_zx_debuglog_read", 0x66c2b179, &vdso_zx_debuglog_read},
+ {"_zx_ktrace_read", 0x7a59dbca, &vdso_zx_ktrace_read},
+ {"_zx_ktrace_control", 0x15debecf, &vdso_zx_ktrace_control},
+ {"_zx_ktrace_write", 0xc5f714f9, &vdso_zx_ktrace_write},
+ {"_zx_mtrace_control", 0x8c5f3211, &vdso_zx_mtrace_control},
+ {"_zx_debug_read", 0x6c062397, &vdso_zx_debug_read},
+ {"_zx_debug_write", 0xed2c5666, &vdso_zx_debug_write},
+ {"_zx_debug_send_command", 0xac6e8203, &vdso_zx_debug_send_command},
+ {"_zx_interrupt_create", 0xaa939795, &vdso_zx_interrupt_create},
+ {"_zx_interrupt_bind", 0xa25b97be, &vdso_zx_interrupt_bind},
+ {"_zx_interrupt_wait", 0xa266f916, &vdso_zx_interrupt_wait},
+ {"_zx_interrupt_destroy", 0x2cb5724b, &vdso_zx_interrupt_destroy},
+ {"_zx_interrupt_ack", 0x3b390f10, &vdso_zx_interrupt_ack},
+ {"_zx_interrupt_trigger", 0x19f00875, &vdso_zx_interrupt_trigger},
+ {"_zx_interrupt_bind_vcpu", 0x505f9f1b, &vdso_zx_interrupt_bind_vcpu},
+ {"_zx_ioports_request", 0xb8f1c0ad, &vdso_zx_ioports_request},
+ {"_zx_vmo_create_contiguous", 0x466a8289, &vdso_zx_vmo_create_contiguous},
+ {"_zx_vmo_create_physical", 0x659677b6, &vdso_zx_vmo_create_physical},
+ {"_zx_iommu_create", 0x297b6af, &vdso_zx_iommu_create},
+ {"_zx_bti_create", 0x7833987, &vdso_zx_bti_create},
+ {"_zx_bti_pin", 0x2aa0e6da, &vdso_zx_bti_pin},
+ {"_zx_bti_release_quarantine", 0x441c1c6b, &vdso_zx_bti_release_quarantine},
+ {"_zx_pmt_unpin", 0x8e954c6f, &vdso_zx_pmt_unpin},
+ {"_zx_framebuffer_get_info", 0xe6c88924, &vdso_zx_framebuffer_get_info},
+ {"_zx_framebuffer_set_range", 0x364ad6b1, &vdso_zx_framebuffer_set_range},
+ {"_zx_pc_firmware_tables", 0x1a05d1fe, &vdso_zx_pc_firmware_tables},
+ {"_zx_smc_call", 0x63f0533, &vdso_zx_smc_call},
+ {"_zx_resource_create", 0x22a0d150, &vdso_zx_resource_create},
+ {"_zx_system_mexec", 0xd142362b, &vdso_zx_system_mexec},
+ {"_zx_system_mexec_payload_get", 0x34bd22b3, &vdso_zx_system_mexec_payload_get},
+ {"_zx_system_powerctl", 0x43f6ae09, &vdso_zx_system_powerctl},
+ {"_zx_pager_create", 0x8d44ed57, &vdso_zx_pager_create},
+ {"_zx_pager_create_vmo", 0x564fdd48, &vdso_zx_pager_create_vmo},
+ {"_zx_pager_detach_vmo", 0x2072c15d, &vdso_zx_pager_detach_vmo},
+ {"_zx_pager_supply_pages", 0x69d1fc7f, &vdso_zx_pager_supply_pages},
+}
+
+//go:cgo_import_dynamic vdso_zx_clock_get _zx_clock_get
+//go:cgo_import_dynamic vdso_zx_clock_get_new _zx_clock_get_new
+//go:cgo_import_dynamic vdso_zx_clock_get_monotonic _zx_clock_get_monotonic
+//go:cgo_import_dynamic vdso_zx_nanosleep _zx_nanosleep
+//go:cgo_import_dynamic vdso_zx_ticks_get _zx_ticks_get
+//go:cgo_import_dynamic vdso_zx_ticks_per_second _zx_ticks_per_second
+//go:cgo_import_dynamic vdso_zx_deadline_after _zx_deadline_after
+//go:cgo_import_dynamic vdso_zx_clock_adjust _zx_clock_adjust
+//go:cgo_import_dynamic vdso_zx_system_get_dcache_line_size _zx_system_get_dcache_line_size
+//go:cgo_import_dynamic vdso_zx_system_get_num_cpus _zx_system_get_num_cpus
+//go:cgo_import_dynamic vdso_zx_system_get_version _zx_system_get_version
+//go:cgo_import_dynamic vdso_zx_system_get_physmem _zx_system_get_physmem
+//go:cgo_import_dynamic vdso_zx_system_get_features _zx_system_get_features
+//go:cgo_import_dynamic vdso_zx_cache_flush _zx_cache_flush
+//go:cgo_import_dynamic vdso_zx_handle_close _zx_handle_close
+//go:cgo_import_dynamic vdso_zx_handle_close_many _zx_handle_close_many
+//go:cgo_import_dynamic vdso_zx_handle_duplicate _zx_handle_duplicate
+//go:cgo_import_dynamic vdso_zx_handle_replace _zx_handle_replace
+//go:cgo_import_dynamic vdso_zx_object_wait_one _zx_object_wait_one
+//go:cgo_import_dynamic vdso_zx_object_wait_many _zx_object_wait_many
+//go:cgo_import_dynamic vdso_zx_object_wait_async _zx_object_wait_async
+//go:cgo_import_dynamic vdso_zx_object_signal _zx_object_signal
+//go:cgo_import_dynamic vdso_zx_object_signal_peer _zx_object_signal_peer
+//go:cgo_import_dynamic vdso_zx_object_get_property _zx_object_get_property
+//go:cgo_import_dynamic vdso_zx_object_set_property _zx_object_set_property
+//go:cgo_import_dynamic vdso_zx_object_get_info _zx_object_get_info
+//go:cgo_import_dynamic vdso_zx_object_get_child _zx_object_get_child
+//go:cgo_import_dynamic vdso_zx_object_set_profile _zx_object_set_profile
+//go:cgo_import_dynamic vdso_zx_channel_create _zx_channel_create
+//go:cgo_import_dynamic vdso_zx_channel_read _zx_channel_read
+//go:cgo_import_dynamic vdso_zx_channel_read_etc _zx_channel_read_etc
+//go:cgo_import_dynamic vdso_zx_channel_write _zx_channel_write
+//go:cgo_import_dynamic vdso_zx_channel_call_noretry _zx_channel_call_noretry
+//go:cgo_import_dynamic vdso_zx_channel_call_finish _zx_channel_call_finish
+//go:cgo_import_dynamic vdso_zx_channel_call _zx_channel_call
+//go:cgo_import_dynamic vdso_zx_socket_create _zx_socket_create
+//go:cgo_import_dynamic vdso_zx_socket_write _zx_socket_write
+//go:cgo_import_dynamic vdso_zx_socket_read _zx_socket_read
+//go:cgo_import_dynamic vdso_zx_socket_share _zx_socket_share
+//go:cgo_import_dynamic vdso_zx_socket_accept _zx_socket_accept
+//go:cgo_import_dynamic vdso_zx_socket_shutdown _zx_socket_shutdown
+//go:cgo_import_dynamic vdso_zx_thread_exit _zx_thread_exit
+//go:cgo_import_dynamic vdso_zx_thread_create _zx_thread_create
+//go:cgo_import_dynamic vdso_zx_thread_start _zx_thread_start
+//go:cgo_import_dynamic vdso_zx_thread_read_state _zx_thread_read_state
+//go:cgo_import_dynamic vdso_zx_thread_write_state _zx_thread_write_state
+//go:cgo_import_dynamic vdso_zx_process_exit _zx_process_exit
+//go:cgo_import_dynamic vdso_zx_process_create _zx_process_create
+//go:cgo_import_dynamic vdso_zx_process_start _zx_process_start
+//go:cgo_import_dynamic vdso_zx_process_read_memory _zx_process_read_memory
+//go:cgo_import_dynamic vdso_zx_process_write_memory _zx_process_write_memory
+//go:cgo_import_dynamic vdso_zx_job_create _zx_job_create
+//go:cgo_import_dynamic vdso_zx_job_set_policy _zx_job_set_policy
+//go:cgo_import_dynamic vdso_zx_task_bind_exception_port _zx_task_bind_exception_port
+//go:cgo_import_dynamic vdso_zx_task_suspend _zx_task_suspend
+//go:cgo_import_dynamic vdso_zx_task_suspend_token _zx_task_suspend_token
+//go:cgo_import_dynamic vdso_zx_task_resume_from_exception _zx_task_resume_from_exception
+//go:cgo_import_dynamic vdso_zx_task_kill _zx_task_kill
+//go:cgo_import_dynamic vdso_zx_event_create _zx_event_create
+//go:cgo_import_dynamic vdso_zx_eventpair_create _zx_eventpair_create
+//go:cgo_import_dynamic vdso_zx_futex_wait _zx_futex_wait
+//go:cgo_import_dynamic vdso_zx_futex_wake _zx_futex_wake
+//go:cgo_import_dynamic vdso_zx_futex_requeue _zx_futex_requeue
+//go:cgo_import_dynamic vdso_zx_futex_wake_single_owner _zx_futex_wake_single_owner
+//go:cgo_import_dynamic vdso_zx_futex_requeue_single_owner _zx_futex_requeue_single_owner
+//go:cgo_import_dynamic vdso_zx_futex_get_owner _zx_futex_get_owner
+//go:cgo_import_dynamic vdso_zx_port_create _zx_port_create
+//go:cgo_import_dynamic vdso_zx_port_queue _zx_port_queue
+//go:cgo_import_dynamic vdso_zx_port_wait _zx_port_wait
+//go:cgo_import_dynamic vdso_zx_port_cancel _zx_port_cancel
+//go:cgo_import_dynamic vdso_zx_timer_create _zx_timer_create
+//go:cgo_import_dynamic vdso_zx_timer_set _zx_timer_set
+//go:cgo_import_dynamic vdso_zx_timer_cancel _zx_timer_cancel
+//go:cgo_import_dynamic vdso_zx_vmo_create _zx_vmo_create
+//go:cgo_import_dynamic vdso_zx_vmo_read _zx_vmo_read
+//go:cgo_import_dynamic vdso_zx_vmo_write _zx_vmo_write
+//go:cgo_import_dynamic vdso_zx_vmo_get_size _zx_vmo_get_size
+//go:cgo_import_dynamic vdso_zx_vmo_set_size _zx_vmo_set_size
+//go:cgo_import_dynamic vdso_zx_vmo_op_range _zx_vmo_op_range
+//go:cgo_import_dynamic vdso_zx_vmo_create_child _zx_vmo_create_child
+//go:cgo_import_dynamic vdso_zx_vmo_set_cache_policy _zx_vmo_set_cache_policy
+//go:cgo_import_dynamic vdso_zx_vmo_replace_as_executable _zx_vmo_replace_as_executable
+//go:cgo_import_dynamic vdso_zx_vmar_allocate _zx_vmar_allocate
+//go:cgo_import_dynamic vdso_zx_vmar_destroy _zx_vmar_destroy
+//go:cgo_import_dynamic vdso_zx_vmar_map _zx_vmar_map
+//go:cgo_import_dynamic vdso_zx_vmar_unmap _zx_vmar_unmap
+//go:cgo_import_dynamic vdso_zx_vmar_protect _zx_vmar_protect
+//go:cgo_import_dynamic vdso_zx_cprng_draw_once _zx_cprng_draw_once
+//go:cgo_import_dynamic vdso_zx_cprng_draw _zx_cprng_draw
+//go:cgo_import_dynamic vdso_zx_cprng_add_entropy _zx_cprng_add_entropy
+//go:cgo_import_dynamic vdso_zx_fifo_create _zx_fifo_create
+//go:cgo_import_dynamic vdso_zx_fifo_read _zx_fifo_read
+//go:cgo_import_dynamic vdso_zx_fifo_write _zx_fifo_write
+//go:cgo_import_dynamic vdso_zx_profile_create _zx_profile_create
+//go:cgo_import_dynamic vdso_zx_vmar_unmap_handle_close_thread_exit _zx_vmar_unmap_handle_close_thread_exit
+//go:cgo_import_dynamic vdso_zx_futex_wake_handle_close_thread_exit _zx_futex_wake_handle_close_thread_exit
+//go:cgo_import_dynamic vdso_zx_debuglog_create _zx_debuglog_create
+//go:cgo_import_dynamic vdso_zx_debuglog_write _zx_debuglog_write
+//go:cgo_import_dynamic vdso_zx_debuglog_read _zx_debuglog_read
+//go:cgo_import_dynamic vdso_zx_ktrace_read _zx_ktrace_read
+//go:cgo_import_dynamic vdso_zx_ktrace_control _zx_ktrace_control
+//go:cgo_import_dynamic vdso_zx_ktrace_write _zx_ktrace_write
+//go:cgo_import_dynamic vdso_zx_mtrace_control _zx_mtrace_control
+//go:cgo_import_dynamic vdso_zx_debug_read _zx_debug_read
+//go:cgo_import_dynamic vdso_zx_debug_write _zx_debug_write
+//go:cgo_import_dynamic vdso_zx_debug_send_command _zx_debug_send_command
+//go:cgo_import_dynamic vdso_zx_interrupt_create _zx_interrupt_create
+//go:cgo_import_dynamic vdso_zx_interrupt_bind _zx_interrupt_bind
+//go:cgo_import_dynamic vdso_zx_interrupt_wait _zx_interrupt_wait
+//go:cgo_import_dynamic vdso_zx_interrupt_destroy _zx_interrupt_destroy
+//go:cgo_import_dynamic vdso_zx_interrupt_ack _zx_interrupt_ack
+//go:cgo_import_dynamic vdso_zx_interrupt_trigger _zx_interrupt_trigger
+//go:cgo_import_dynamic vdso_zx_interrupt_bind_vcpu _zx_interrupt_bind_vcpu
+//go:cgo_import_dynamic vdso_zx_ioports_request _zx_ioports_request
+//go:cgo_import_dynamic vdso_zx_vmo_create_contiguous _zx_vmo_create_contiguous
+//go:cgo_import_dynamic vdso_zx_vmo_create_physical _zx_vmo_create_physical
+//go:cgo_import_dynamic vdso_zx_iommu_create _zx_iommu_create
+//go:cgo_import_dynamic vdso_zx_bti_create _zx_bti_create
+//go:cgo_import_dynamic vdso_zx_bti_pin _zx_bti_pin
+//go:cgo_import_dynamic vdso_zx_bti_release_quarantine _zx_bti_release_quarantine
+//go:cgo_import_dynamic vdso_zx_pmt_unpin _zx_pmt_unpin
+//go:cgo_import_dynamic vdso_zx_framebuffer_get_info _zx_framebuffer_get_info
+//go:cgo_import_dynamic vdso_zx_framebuffer_set_range _zx_framebuffer_set_range
+//go:cgo_import_dynamic vdso_zx_pc_firmware_tables _zx_pc_firmware_tables
+//go:cgo_import_dynamic vdso_zx_smc_call _zx_smc_call
+//go:cgo_import_dynamic vdso_zx_resource_create _zx_resource_create
+//go:cgo_import_dynamic vdso_zx_system_mexec _zx_system_mexec
+//go:cgo_import_dynamic vdso_zx_system_mexec_payload_get _zx_system_mexec_payload_get
+//go:cgo_import_dynamic vdso_zx_system_powerctl _zx_system_powerctl
+//go:cgo_import_dynamic vdso_zx_pager_create _zx_pager_create
+//go:cgo_import_dynamic vdso_zx_pager_create_vmo _zx_pager_create_vmo
+//go:cgo_import_dynamic vdso_zx_pager_detach_vmo _zx_pager_detach_vmo
+//go:cgo_import_dynamic vdso_zx_pager_supply_pages _zx_pager_supply_pages
+
+//go:linkname vdso_zx_clock_get vdso_zx_clock_get
+//go:linkname vdso_zx_clock_get_new vdso_zx_clock_get_new
+//go:linkname vdso_zx_clock_get_monotonic vdso_zx_clock_get_monotonic
+//go:linkname vdso_zx_nanosleep vdso_zx_nanosleep
+//go:linkname vdso_zx_ticks_get vdso_zx_ticks_get
+//go:linkname vdso_zx_ticks_per_second vdso_zx_ticks_per_second
+//go:linkname vdso_zx_deadline_after vdso_zx_deadline_after
+//go:linkname vdso_zx_clock_adjust vdso_zx_clock_adjust
+//go:linkname vdso_zx_system_get_dcache_line_size vdso_zx_system_get_dcache_line_size
+//go:linkname vdso_zx_system_get_num_cpus vdso_zx_system_get_num_cpus
+//go:linkname vdso_zx_system_get_version vdso_zx_system_get_version
+//go:linkname vdso_zx_system_get_physmem vdso_zx_system_get_physmem
+//go:linkname vdso_zx_system_get_features vdso_zx_system_get_features
+//go:linkname vdso_zx_cache_flush vdso_zx_cache_flush
+//go:linkname vdso_zx_handle_close vdso_zx_handle_close
+//go:linkname vdso_zx_handle_close_many vdso_zx_handle_close_many
+//go:linkname vdso_zx_handle_duplicate vdso_zx_handle_duplicate
+//go:linkname vdso_zx_handle_replace vdso_zx_handle_replace
+//go:linkname vdso_zx_object_wait_one vdso_zx_object_wait_one
+//go:linkname vdso_zx_object_wait_many vdso_zx_object_wait_many
+//go:linkname vdso_zx_object_wait_async vdso_zx_object_wait_async
+//go:linkname vdso_zx_object_signal vdso_zx_object_signal
+//go:linkname vdso_zx_object_signal_peer vdso_zx_object_signal_peer
+//go:linkname vdso_zx_object_get_property vdso_zx_object_get_property
+//go:linkname vdso_zx_object_set_property vdso_zx_object_set_property
+//go:linkname vdso_zx_object_get_info vdso_zx_object_get_info
+//go:linkname vdso_zx_object_get_child vdso_zx_object_get_child
+//go:linkname vdso_zx_object_set_profile vdso_zx_object_set_profile
+//go:linkname vdso_zx_channel_create vdso_zx_channel_create
+//go:linkname vdso_zx_channel_read vdso_zx_channel_read
+//go:linkname vdso_zx_channel_read_etc vdso_zx_channel_read_etc
+//go:linkname vdso_zx_channel_write vdso_zx_channel_write
+//go:linkname vdso_zx_channel_call_noretry vdso_zx_channel_call_noretry
+//go:linkname vdso_zx_channel_call_finish vdso_zx_channel_call_finish
+//go:linkname vdso_zx_channel_call vdso_zx_channel_call
+//go:linkname vdso_zx_socket_create vdso_zx_socket_create
+//go:linkname vdso_zx_socket_write vdso_zx_socket_write
+//go:linkname vdso_zx_socket_read vdso_zx_socket_read
+//go:linkname vdso_zx_socket_share vdso_zx_socket_share
+//go:linkname vdso_zx_socket_accept vdso_zx_socket_accept
+//go:linkname vdso_zx_socket_shutdown vdso_zx_socket_shutdown
+//go:linkname vdso_zx_thread_exit vdso_zx_thread_exit
+//go:linkname vdso_zx_thread_create vdso_zx_thread_create
+//go:linkname vdso_zx_thread_start vdso_zx_thread_start
+//go:linkname vdso_zx_thread_read_state vdso_zx_thread_read_state
+//go:linkname vdso_zx_thread_write_state vdso_zx_thread_write_state
+//go:linkname vdso_zx_process_exit vdso_zx_process_exit
+//go:linkname vdso_zx_process_create vdso_zx_process_create
+//go:linkname vdso_zx_process_start vdso_zx_process_start
+//go:linkname vdso_zx_process_read_memory vdso_zx_process_read_memory
+//go:linkname vdso_zx_process_write_memory vdso_zx_process_write_memory
+//go:linkname vdso_zx_job_create vdso_zx_job_create
+//go:linkname vdso_zx_job_set_policy vdso_zx_job_set_policy
+//go:linkname vdso_zx_task_bind_exception_port vdso_zx_task_bind_exception_port
+//go:linkname vdso_zx_task_suspend vdso_zx_task_suspend
+//go:linkname vdso_zx_task_suspend_token vdso_zx_task_suspend_token
+//go:linkname vdso_zx_task_resume_from_exception vdso_zx_task_resume_from_exception
+//go:linkname vdso_zx_task_kill vdso_zx_task_kill
+//go:linkname vdso_zx_event_create vdso_zx_event_create
+//go:linkname vdso_zx_eventpair_create vdso_zx_eventpair_create
+//go:linkname vdso_zx_futex_wait vdso_zx_futex_wait
+//go:linkname vdso_zx_futex_wake vdso_zx_futex_wake
+//go:linkname vdso_zx_futex_requeue vdso_zx_futex_requeue
+//go:linkname vdso_zx_futex_wake_single_owner vdso_zx_futex_wake_single_owner
+//go:linkname vdso_zx_futex_requeue_single_owner vdso_zx_futex_requeue_single_owner
+//go:linkname vdso_zx_futex_get_owner vdso_zx_futex_get_owner
+//go:linkname vdso_zx_port_create vdso_zx_port_create
+//go:linkname vdso_zx_port_queue vdso_zx_port_queue
+//go:linkname vdso_zx_port_wait vdso_zx_port_wait
+//go:linkname vdso_zx_port_cancel vdso_zx_port_cancel
+//go:linkname vdso_zx_timer_create vdso_zx_timer_create
+//go:linkname vdso_zx_timer_set vdso_zx_timer_set
+//go:linkname vdso_zx_timer_cancel vdso_zx_timer_cancel
+//go:linkname vdso_zx_vmo_create vdso_zx_vmo_create
+//go:linkname vdso_zx_vmo_read vdso_zx_vmo_read
+//go:linkname vdso_zx_vmo_write vdso_zx_vmo_write
+//go:linkname vdso_zx_vmo_get_size vdso_zx_vmo_get_size
+//go:linkname vdso_zx_vmo_set_size vdso_zx_vmo_set_size
+//go:linkname vdso_zx_vmo_op_range vdso_zx_vmo_op_range
+//go:linkname vdso_zx_vmo_create_child vdso_zx_vmo_create_child
+//go:linkname vdso_zx_vmo_set_cache_policy vdso_zx_vmo_set_cache_policy
+//go:linkname vdso_zx_vmo_replace_as_executable vdso_zx_vmo_replace_as_executable
+//go:linkname vdso_zx_vmar_allocate vdso_zx_vmar_allocate
+//go:linkname vdso_zx_vmar_destroy vdso_zx_vmar_destroy
+//go:linkname vdso_zx_vmar_map vdso_zx_vmar_map
+//go:linkname vdso_zx_vmar_unmap vdso_zx_vmar_unmap
+//go:linkname vdso_zx_vmar_protect vdso_zx_vmar_protect
+//go:linkname vdso_zx_cprng_draw_once vdso_zx_cprng_draw_once
+//go:linkname vdso_zx_cprng_draw vdso_zx_cprng_draw
+//go:linkname vdso_zx_cprng_add_entropy vdso_zx_cprng_add_entropy
+//go:linkname vdso_zx_fifo_create vdso_zx_fifo_create
+//go:linkname vdso_zx_fifo_read vdso_zx_fifo_read
+//go:linkname vdso_zx_fifo_write vdso_zx_fifo_write
+//go:linkname vdso_zx_profile_create vdso_zx_profile_create
+//go:linkname vdso_zx_vmar_unmap_handle_close_thread_exit vdso_zx_vmar_unmap_handle_close_thread_exit
+//go:linkname vdso_zx_futex_wake_handle_close_thread_exit vdso_zx_futex_wake_handle_close_thread_exit
+//go:linkname vdso_zx_debuglog_create vdso_zx_debuglog_create
+//go:linkname vdso_zx_debuglog_write vdso_zx_debuglog_write
+//go:linkname vdso_zx_debuglog_read vdso_zx_debuglog_read
+//go:linkname vdso_zx_ktrace_read vdso_zx_ktrace_read
+//go:linkname vdso_zx_ktrace_control vdso_zx_ktrace_control
+//go:linkname vdso_zx_ktrace_write vdso_zx_ktrace_write
+//go:linkname vdso_zx_mtrace_control vdso_zx_mtrace_control
+//go:linkname vdso_zx_debug_read vdso_zx_debug_read
+//go:linkname vdso_zx_debug_write vdso_zx_debug_write
+//go:linkname vdso_zx_debug_send_command vdso_zx_debug_send_command
+//go:linkname vdso_zx_interrupt_create vdso_zx_interrupt_create
+//go:linkname vdso_zx_interrupt_bind vdso_zx_interrupt_bind
+//go:linkname vdso_zx_interrupt_wait vdso_zx_interrupt_wait
+//go:linkname vdso_zx_interrupt_destroy vdso_zx_interrupt_destroy
+//go:linkname vdso_zx_interrupt_ack vdso_zx_interrupt_ack
+//go:linkname vdso_zx_interrupt_trigger vdso_zx_interrupt_trigger
+//go:linkname vdso_zx_interrupt_bind_vcpu vdso_zx_interrupt_bind_vcpu
+//go:linkname vdso_zx_ioports_request vdso_zx_ioports_request
+//go:linkname vdso_zx_vmo_create_contiguous vdso_zx_vmo_create_contiguous
+//go:linkname vdso_zx_vmo_create_physical vdso_zx_vmo_create_physical
+//go:linkname vdso_zx_iommu_create vdso_zx_iommu_create
+//go:linkname vdso_zx_bti_create vdso_zx_bti_create
+//go:linkname vdso_zx_bti_pin vdso_zx_bti_pin
+//go:linkname vdso_zx_bti_release_quarantine vdso_zx_bti_release_quarantine
+//go:linkname vdso_zx_pmt_unpin vdso_zx_pmt_unpin
+//go:linkname vdso_zx_framebuffer_get_info vdso_zx_framebuffer_get_info
+//go:linkname vdso_zx_framebuffer_set_range vdso_zx_framebuffer_set_range
+//go:linkname vdso_zx_pc_firmware_tables vdso_zx_pc_firmware_tables
+//go:linkname vdso_zx_smc_call vdso_zx_smc_call
+//go:linkname vdso_zx_resource_create vdso_zx_resource_create
+//go:linkname vdso_zx_system_mexec vdso_zx_system_mexec
+//go:linkname vdso_zx_system_mexec_payload_get vdso_zx_system_mexec_payload_get
+//go:linkname vdso_zx_system_powerctl vdso_zx_system_powerctl
+//go:linkname vdso_zx_pager_create vdso_zx_pager_create
+//go:linkname vdso_zx_pager_create_vmo vdso_zx_pager_create_vmo
+//go:linkname vdso_zx_pager_detach_vmo vdso_zx_pager_detach_vmo
+//go:linkname vdso_zx_pager_supply_pages vdso_zx_pager_supply_pages
+
+//go:noescape
+//go:nosplit
+func vdsoCall_zx_clock_get(clock_id uint32) int64
+
+//go:noescape
+//go:nosplit
+func vdsoCall_zx_clock_get_new(clock_id uint32, out unsafe.Pointer) int32
+
+//go:noescape
+//go:nosplit
+func vdsoCall_zx_clock_get_monotonic() int64
+
+//go:noescape
+//go:nosplit
+func vdsoCall_zx_nanosleep(deadline int64) int32
+
+//go:noescape
+//go:nosplit
+func vdsoCall_zx_ticks_get() uint64
+
+//go:noescape
+//go:nosplit
+func vdsoCall_zx_ticks_per_second() uint64
+
+//go:noescape
+//go:nosplit
+func vdsoCall_zx_deadline_after(nanoseconds int64) int64
+
+//go:noescape
+//go:nosplit
+func vdsoCall_zx_clock_adjust(handle uint32, clock_id uint32, offset int64) int32
+
+//go:noescape
+//go:nosplit
+func vdsoCall_zx_system_get_dcache_line_size() uint32
+
+//go:noescape
+//go:nosplit
+func vdsoCall_zx_system_get_num_cpus() uint32
+
+//go:noescape
+//go:nosplit
+func vdsoCall_zx_system_get_version(version unsafe.Pointer, version_size uint) int32
+
+//go:noescape
+//go:nosplit
+func vdsoCall_zx_system_get_physmem() uint64
+
+//go:noescape
+//go:nosplit
+func vdsoCall_zx_system_get_features(kind uint32, features unsafe.Pointer) int32
+
+//go:noescape
+//go:nosplit
+func vdsoCall_zx_cache_flush(addr unsafe.Pointer, size uint, options uint32) int32
+
+//go:noescape
+//go:nosplit
+func vdsoCall_zx_handle_close(handle uint32) int32
+
+//go:noescape
+//go:nosplit
+func vdsoCall_zx_handle_close_many(handles unsafe.Pointer, num_handles uint) int32
+
+//go:noescape
+//go:nosplit
+func vdsoCall_zx_handle_duplicate(handle uint32, rights uint32, out unsafe.Pointer) int32
+
+//go:noescape
+//go:nosplit
+func vdsoCall_zx_handle_replace(handle uint32, rights uint32, out unsafe.Pointer) int32
+
+//go:noescape
+//go:nosplit
+func vdsoCall_zx_object_wait_one(handle uint32, signals uint32, deadline int64, observed unsafe.Pointer) int32
+
+//go:noescape
+//go:nosplit
+func vdsoCall_zx_object_wait_many(items unsafe.Pointer, count uint, deadline int64) int32
+
+//go:noescape
+//go:nosplit
+func vdsoCall_zx_object_wait_async(handle uint32, port uint32, key uint64, signals uint32, options uint32) int32
+
+//go:noescape
+//go:nosplit
+func vdsoCall_zx_object_signal(handle uint32, clear_mask uint32, set_mask uint32) int32
+
+//go:noescape
+//go:nosplit
+func vdsoCall_zx_object_signal_peer(handle uint32, clear_mask uint32, set_mask uint32) int32
+
+//go:noescape
+//go:nosplit
+func vdsoCall_zx_object_get_property(handle uint32, property uint32, value unsafe.Pointer, value_size uint) int32
+
+//go:noescape
+//go:nosplit
+func vdsoCall_zx_object_set_property(handle uint32, property uint32, value unsafe.Pointer, value_size uint) int32
+
+//go:noescape
+//go:nosplit
+func vdsoCall_zx_object_get_info(handle uint32, topic uint32, buffer unsafe.Pointer, buffer_size uint, actual unsafe.Pointer, avail unsafe.Pointer) int32
+
+//go:noescape
+//go:nosplit
+func vdsoCall_zx_object_get_child(handle uint32, koid uint64, rights uint32, out unsafe.Pointer) int32
+
+//go:noescape
+//go:nosplit
+func vdsoCall_zx_object_set_profile(handle uint32, profile uint32, options uint32) int32
+
+//go:noescape
+//go:nosplit
+func vdsoCall_zx_channel_create(options uint32, out0 unsafe.Pointer, out1 unsafe.Pointer) int32
+
+//go:noescape
+//go:nosplit
+func vdsoCall_zx_channel_read(handle uint32, options uint32, bytes unsafe.Pointer, handles unsafe.Pointer, num_bytes uint32, num_handles uint32, actual_bytes unsafe.Pointer, actual_handles unsafe.Pointer) int32
+
+//go:noescape
+//go:nosplit
+func vdsoCall_zx_channel_read_etc(handle uint32, options uint32, bytes unsafe.Pointer, handles unsafe.Pointer, num_bytes uint32, num_handles uint32, actual_bytes unsafe.Pointer, actual_handles unsafe.Pointer) int32
+
+//go:noescape
+//go:nosplit
+func vdsoCall_zx_channel_write(handle uint32, options uint32, bytes unsafe.Pointer, num_bytes uint32, handles unsafe.Pointer, num_handles uint32) int32
+
+//go:noescape
+//go:nosplit
+func vdsoCall_zx_channel_call_noretry(handle uint32, options uint32, deadline int64, args unsafe.Pointer, actual_bytes unsafe.Pointer, actual_handles unsafe.Pointer) int32
+
+//go:noescape
+//go:nosplit
+func vdsoCall_zx_channel_call_finish(deadline int64, args unsafe.Pointer, actual_bytes unsafe.Pointer, actual_handles unsafe.Pointer) int32
+
+//go:noescape
+//go:nosplit
+func vdsoCall_zx_channel_call(handle uint32, options uint32, deadline int64, args unsafe.Pointer, actual_bytes unsafe.Pointer, actual_handles unsafe.Pointer) int32
+
+//go:noescape
+//go:nosplit
+func vdsoCall_zx_socket_create(options uint32, out0 unsafe.Pointer, out1 unsafe.Pointer) int32
+
+//go:noescape
+//go:nosplit
+func vdsoCall_zx_socket_write(handle uint32, options uint32, buffer unsafe.Pointer, buffer_size uint, actual unsafe.Pointer) int32
+
+//go:noescape
+//go:nosplit
+func vdsoCall_zx_socket_read(handle uint32, options uint32, buffer unsafe.Pointer, buffer_size uint, actual unsafe.Pointer) int32
+
+//go:noescape
+//go:nosplit
+func vdsoCall_zx_socket_share(handle uint32, socket_to_share uint32) int32
+
+//go:noescape
+//go:nosplit
+func vdsoCall_zx_socket_accept(handle uint32, out_socket unsafe.Pointer) int32
+
+//go:noescape
+//go:nosplit
+func vdsoCall_zx_socket_shutdown(handle uint32, options uint32) int32
+
+//go:noescape
+//go:nosplit
+func vdsoCall_zx_thread_exit()
+
+//go:noescape
+//go:nosplit
+func vdsoCall_zx_thread_create(process uint32, name unsafe.Pointer, name_size uint, options uint32, out unsafe.Pointer) int32
+
+//go:noescape
+//go:nosplit
+func vdsoCall_zx_thread_start(handle uint32, thread_entry uintptr, stack uintptr, arg1 uintptr, arg2 uintptr) int32
+
+//go:noescape
+//go:nosplit
+func vdsoCall_zx_thread_read_state(handle uint32, kind uint32, buffer unsafe.Pointer, buffer_size uint) int32
+
+//go:noescape
+//go:nosplit
+func vdsoCall_zx_thread_write_state(handle uint32, kind uint32, buffer unsafe.Pointer, buffer_size uint) int32
+
+//go:noescape
+//go:nosplit
+func vdsoCall_zx_process_exit(retcode int64)
+
+//go:noescape
+//go:nosplit
+func vdsoCall_zx_process_create(job uint32, name unsafe.Pointer, name_size uint, options uint32, proc_handle unsafe.Pointer, vmar_handle unsafe.Pointer) int32
+
+//go:noescape
+//go:nosplit
+func vdsoCall_zx_process_start(handle uint32, thread uint32, entry uintptr, stack uintptr, arg1 uint32, arg2 uintptr) int32
+
+//go:noescape
+//go:nosplit
+func vdsoCall_zx_process_read_memory(handle uint32, vaddr uintptr, buffer unsafe.Pointer, buffer_size uint, actual unsafe.Pointer) int32
+
+//go:noescape
+//go:nosplit
+func vdsoCall_zx_process_write_memory(handle uint32, vaddr uintptr, buffer unsafe.Pointer, buffer_size uint, actual unsafe.Pointer) int32
+
+//go:noescape
+//go:nosplit
+func vdsoCall_zx_job_create(parent_job uint32, options uint32, out unsafe.Pointer) int32
+
+//go:noescape
+//go:nosplit
+func vdsoCall_zx_job_set_policy(handle uint32, options uint32, topic uint32, policy unsafe.Pointer, count uint32) int32
+
+//go:noescape
+//go:nosplit
+func vdsoCall_zx_task_bind_exception_port(handle uint32, port uint32, key uint64, options uint32) int32
+
+//go:noescape
+//go:nosplit
+func vdsoCall_zx_task_suspend(handle uint32, token unsafe.Pointer) int32
+
+//go:noescape
+//go:nosplit
+func vdsoCall_zx_task_suspend_token(handle uint32, token unsafe.Pointer) int32
+
+//go:noescape
+//go:nosplit
+func vdsoCall_zx_task_resume_from_exception(handle uint32, port uint32, options uint32) int32
+
+//go:noescape
+//go:nosplit
+func vdsoCall_zx_task_kill(handle uint32) int32
+
+//go:noescape
+//go:nosplit
+func vdsoCall_zx_event_create(options uint32, out unsafe.Pointer) int32
+
+//go:noescape
+//go:nosplit
+func vdsoCall_zx_eventpair_create(options uint32, out0 unsafe.Pointer, out1 unsafe.Pointer) int32
+
+//go:noescape
+//go:nosplit
+func vdsoCall_zx_futex_wait(value_ptr unsafe.Pointer, current_value int32, new_futex_owner uint32, deadline int64) int32
+
+//go:noescape
+//go:nosplit
+func vdsoCall_zx_futex_wake(value_ptr unsafe.Pointer, wake_count uint32) int32
+
+//go:noescape
+//go:nosplit
+func vdsoCall_zx_futex_requeue(value_ptr unsafe.Pointer, wake_count uint32, current_value int32, requeue_ptr unsafe.Pointer, requeue_count uint32, new_requeue_owner uint32) int32
+
+//go:noescape
+//go:nosplit
+func vdsoCall_zx_futex_wake_single_owner(value_ptr unsafe.Pointer) int32
+
+//go:noescape
+//go:nosplit
+func vdsoCall_zx_futex_requeue_single_owner(value_ptr unsafe.Pointer, current_value int32, requeue_ptr unsafe.Pointer, requeue_count uint32, new_requeue_owner uint32) int32
+
+//go:noescape
+//go:nosplit
+func vdsoCall_zx_futex_get_owner(value_ptr unsafe.Pointer, koid unsafe.Pointer) int32
+
+//go:noescape
+//go:nosplit
+func vdsoCall_zx_port_create(options uint32, out unsafe.Pointer) int32
+
+//go:noescape
+//go:nosplit
+func vdsoCall_zx_port_queue(handle uint32, packet unsafe.Pointer) int32
+
+//go:noescape
+//go:nosplit
+func vdsoCall_zx_port_wait(handle uint32, deadline int64, packet unsafe.Pointer) int32
+
+//go:noescape
+//go:nosplit
+func vdsoCall_zx_port_cancel(handle uint32, source uint32, key uint64) int32
+
+//go:noescape
+//go:nosplit
+func vdsoCall_zx_timer_create(options uint32, clock_id uint32, out unsafe.Pointer) int32
+
+//go:noescape
+//go:nosplit
+func vdsoCall_zx_timer_set(handle uint32, deadline int64, slack int64) int32
+
+//go:noescape
+//go:nosplit
+func vdsoCall_zx_timer_cancel(handle uint32) int32
+
+//go:noescape
+//go:nosplit
+func vdsoCall_zx_vmo_create(size uint64, options uint32, out unsafe.Pointer) int32
+
+//go:noescape
+//go:nosplit
+func vdsoCall_zx_vmo_read(handle uint32, buffer unsafe.Pointer, offset uint64, buffer_size uint) int32
+
+//go:noescape
+//go:nosplit
+func vdsoCall_zx_vmo_write(handle uint32, buffer unsafe.Pointer, offset uint64, buffer_size uint) int32
+
+//go:noescape
+//go:nosplit
+func vdsoCall_zx_vmo_get_size(handle uint32, size unsafe.Pointer) int32
+
+//go:noescape
+//go:nosplit
+func vdsoCall_zx_vmo_set_size(handle uint32, size uint64) int32
+
+//go:noescape
+//go:nosplit
+func vdsoCall_zx_vmo_op_range(handle uint32, op uint32, offset uint64, size uint64, buffer unsafe.Pointer, buffer_size uint) int32
+
+//go:noescape
+//go:nosplit
+func vdsoCall_zx_vmo_create_child(handle uint32, options uint32, offset uint64, size uint64, out unsafe.Pointer) int32
+
+//go:noescape
+//go:nosplit
+func vdsoCall_zx_vmo_set_cache_policy(handle uint32, cache_policy uint32) int32
+
+//go:noescape
+//go:nosplit
+func vdsoCall_zx_vmo_replace_as_executable(handle uint32, vmex uint32, out unsafe.Pointer) int32
+
+//go:noescape
+//go:nosplit
+func vdsoCall_zx_vmar_allocate(parent_vmar uint32, options uint32, offset uint64, size uint64, child_vmar unsafe.Pointer, child_addr unsafe.Pointer) int32
+
+//go:noescape
+//go:nosplit
+func vdsoCall_zx_vmar_destroy(handle uint32) int32
+
+//go:noescape
+//go:nosplit
+func vdsoCall_zx_vmar_map(handle uint32, options uint32, vmar_offset uint64, vmo uint32, vmo_offset uint64, len uint64, mapped_addr unsafe.Pointer) int32
+
+//go:noescape
+//go:nosplit
+func vdsoCall_zx_vmar_unmap(handle uint32, addr uintptr, len uint64) int32
+
+//go:noescape
+//go:nosplit
+func vdsoCall_zx_vmar_protect(handle uint32, options uint32, addr uintptr, len uint64) int32
+
+//go:noescape
+//go:nosplit
+func vdsoCall_zx_cprng_draw_once(buffer unsafe.Pointer, buffer_size uint) int32
+
+//go:noescape
+//go:nosplit
+func vdsoCall_zx_cprng_draw(buffer unsafe.Pointer, buffer_size uint)
+
+//go:noescape
+//go:nosplit
+func vdsoCall_zx_cprng_add_entropy(buffer unsafe.Pointer, buffer_size uint) int32
+
+//go:noescape
+//go:nosplit
+func vdsoCall_zx_fifo_create(elem_count uint, elem_size uint, options uint32, out0 unsafe.Pointer, out1 unsafe.Pointer) int32
+
+//go:noescape
+//go:nosplit
+func vdsoCall_zx_fifo_read(handle uint32, elem_size uint, data unsafe.Pointer, count uint, actual_count unsafe.Pointer) int32
+
+//go:noescape
+//go:nosplit
+func vdsoCall_zx_fifo_write(handle uint32, elem_size uint, data unsafe.Pointer, count uint, actual_count unsafe.Pointer) int32
+
+//go:noescape
+//go:nosplit
+func vdsoCall_zx_profile_create(root_job uint32, profile unsafe.Pointer, out unsafe.Pointer) int32
+
+//go:noescape
+//go:nosplit
+func vdsoCall_zx_vmar_unmap_handle_close_thread_exit(vmar_handle uint32, addr uintptr, size uint, close_handle uint32) int32
+
+//go:noescape
+//go:nosplit
+func vdsoCall_zx_futex_wake_handle_close_thread_exit(value_ptr unsafe.Pointer, wake_count uint32, new_value int32, close_handle uint32)
+
+//go:noescape
+//go:nosplit
+func vdsoCall_zx_debuglog_create(resource uint32, options uint32, out unsafe.Pointer) int32
+
+//go:noescape
+//go:nosplit
+func vdsoCall_zx_debuglog_write(handle uint32, options uint32, buffer unsafe.Pointer, buffer_size uint) int32
+
+//go:noescape
+//go:nosplit
+func vdsoCall_zx_debuglog_read(handle uint32, options uint32, buffer unsafe.Pointer, buffer_size uint) int32
+
+//go:noescape
+//go:nosplit
+func vdsoCall_zx_ktrace_read(handle uint32, data unsafe.Pointer, offset uint32, data_size uint, actual unsafe.Pointer) int32
+
+//go:noescape
+//go:nosplit
+func vdsoCall_zx_ktrace_control(handle uint32, action uint32, options uint32, ptr unsafe.Pointer) int32
+
+//go:noescape
+//go:nosplit
+func vdsoCall_zx_ktrace_write(handle uint32, id uint32, arg0 uint32, arg1 uint32) int32
+
+//go:noescape
+//go:nosplit
+func vdsoCall_zx_mtrace_control(handle uint32, kind uint32, action uint32, options uint32, ptr unsafe.Pointer, ptr_size uint) int32
+
+//go:noescape
+//go:nosplit
+func vdsoCall_zx_debug_read(handle uint32, buffer unsafe.Pointer, buffer_size unsafe.Pointer) int32
+
+//go:noescape
+//go:nosplit
+func vdsoCall_zx_debug_write(buffer unsafe.Pointer, buffer_size uint) int32
+
+//go:noescape
+//go:nosplit
+func vdsoCall_zx_debug_send_command(resource uint32, buffer unsafe.Pointer, buffer_size uint) int32
+
+//go:noescape
+//go:nosplit
+func vdsoCall_zx_interrupt_create(src_obj uint32, src_num uint32, options uint32, out_handle unsafe.Pointer) int32
+
+//go:noescape
+//go:nosplit
+func vdsoCall_zx_interrupt_bind(handle uint32, port_handle uint32, key uint64, options uint32) int32
+
+//go:noescape
+//go:nosplit
+func vdsoCall_zx_interrupt_wait(handle uint32, out_timestamp unsafe.Pointer) int32
+
+//go:noescape
+//go:nosplit
+func vdsoCall_zx_interrupt_destroy(handle uint32) int32
+
+//go:noescape
+//go:nosplit
+func vdsoCall_zx_interrupt_ack(handle uint32) int32
+
+//go:noescape
+//go:nosplit
+func vdsoCall_zx_interrupt_trigger(handle uint32, options uint32, timestamp int64) int32
+
+//go:noescape
+//go:nosplit
+func vdsoCall_zx_interrupt_bind_vcpu(handle uint32, vcpu uint32, options uint32) int32
+
+//go:noescape
+//go:nosplit
+func vdsoCall_zx_ioports_request(resource uint32, io_addr uint16, len uint32) int32
+
+//go:noescape
+//go:nosplit
+func vdsoCall_zx_vmo_create_contiguous(bti uint32, size uint, alignment_log2 uint32, out unsafe.Pointer) int32
+
+//go:noescape
+//go:nosplit
+func vdsoCall_zx_vmo_create_physical(resource uint32, paddr uintptr, size uint, out unsafe.Pointer) int32
+
+//go:noescape
+//go:nosplit
+func vdsoCall_zx_iommu_create(resource uint32, typ uint32, desc unsafe.Pointer, desc_size uint, out unsafe.Pointer) int32
+
+//go:noescape
+//go:nosplit
+func vdsoCall_zx_bti_create(iommu uint32, options uint32, bti_id uint64, out unsafe.Pointer) int32
+
+//go:noescape
+//go:nosplit
+func vdsoCall_zx_bti_pin(handle uint32, options uint32, vmo uint32, offset uint64, size uint64, addrs unsafe.Pointer, addrs_count uint, pmt unsafe.Pointer) int32
+
+//go:noescape
+//go:nosplit
+func vdsoCall_zx_bti_release_quarantine(handle uint32) int32
+
+//go:noescape
+//go:nosplit
+func vdsoCall_zx_pmt_unpin(handle uint32) int32
+
+//go:noescape
+//go:nosplit
+func vdsoCall_zx_framebuffer_get_info(resource uint32, format unsafe.Pointer, width unsafe.Pointer, height unsafe.Pointer, stride unsafe.Pointer) int32
+
+//go:noescape
+//go:nosplit
+func vdsoCall_zx_framebuffer_set_range(resource uint32, vmo uint32, len uint32, format uint32, width uint32, height uint32, stride uint32) int32
+
+//go:noescape
+//go:nosplit
+func vdsoCall_zx_pc_firmware_tables(handle uint32, acpi_rsdp unsafe.Pointer, smbios unsafe.Pointer) int32
+
+//go:noescape
+//go:nosplit
+func vdsoCall_zx_smc_call(handle uint32, parameters unsafe.Pointer, out_smc_result unsafe.Pointer) int32
+
+//go:noescape
+//go:nosplit
+func vdsoCall_zx_resource_create(parent_rsrc uint32, options uint32, base uint64, size uint, name unsafe.Pointer, name_size uint, resource_out unsafe.Pointer) int32
+
+//go:noescape
+//go:nosplit
+func vdsoCall_zx_system_mexec(resource uint32, kernel_vmo uint32, bootimage_vmo uint32) int32
+
+//go:noescape
+//go:nosplit
+func vdsoCall_zx_system_mexec_payload_get(resource uint32, buffer unsafe.Pointer, buffer_size uint) int32
+
+//go:noescape
+//go:nosplit
+func vdsoCall_zx_system_powerctl(resource uint32, cmd uint32, arg unsafe.Pointer) int32
+
+//go:noescape
+//go:nosplit
+func vdsoCall_zx_pager_create(options uint32, out unsafe.Pointer) int32
+
+//go:noescape
+//go:nosplit
+func vdsoCall_zx_pager_create_vmo(pager uint32, options uint32, port uint32, key uint64, size uint64, out unsafe.Pointer) int32
+
+//go:noescape
+//go:nosplit
+func vdsoCall_zx_pager_detach_vmo(pager uint32, vmo uint32) int32
+
+//go:noescape
+//go:nosplit
+func vdsoCall_zx_pager_supply_pages(pager uint32, pager_vmo uint32, offset uint64, length uint64, aux_vmo uint32, aux_offset uint64) int32
+
+var (
+ vdso_zx_clock_get uintptr
+ vdso_zx_clock_get_new uintptr
+ vdso_zx_clock_get_monotonic uintptr
+ vdso_zx_nanosleep uintptr
+ vdso_zx_ticks_get uintptr
+ vdso_zx_ticks_per_second uintptr
+ vdso_zx_deadline_after uintptr
+ vdso_zx_clock_adjust uintptr
+ vdso_zx_system_get_dcache_line_size uintptr
+ vdso_zx_system_get_num_cpus uintptr
+ vdso_zx_system_get_version uintptr
+ vdso_zx_system_get_physmem uintptr
+ vdso_zx_system_get_features uintptr
+ vdso_zx_cache_flush uintptr
+ vdso_zx_handle_close uintptr
+ vdso_zx_handle_close_many uintptr
+ vdso_zx_handle_duplicate uintptr
+ vdso_zx_handle_replace uintptr
+ vdso_zx_object_wait_one uintptr
+ vdso_zx_object_wait_many uintptr
+ vdso_zx_object_wait_async uintptr
+ vdso_zx_object_signal uintptr
+ vdso_zx_object_signal_peer uintptr
+ vdso_zx_object_get_property uintptr
+ vdso_zx_object_set_property uintptr
+ vdso_zx_object_get_info uintptr
+ vdso_zx_object_get_child uintptr
+ vdso_zx_object_set_profile uintptr
+ vdso_zx_channel_create uintptr
+ vdso_zx_channel_read uintptr
+ vdso_zx_channel_read_etc uintptr
+ vdso_zx_channel_write uintptr
+ vdso_zx_channel_call_noretry uintptr
+ vdso_zx_channel_call_finish uintptr
+ vdso_zx_channel_call uintptr
+ vdso_zx_socket_create uintptr
+ vdso_zx_socket_write uintptr
+ vdso_zx_socket_read uintptr
+ vdso_zx_socket_share uintptr
+ vdso_zx_socket_accept uintptr
+ vdso_zx_socket_shutdown uintptr
+ vdso_zx_thread_exit uintptr
+ vdso_zx_thread_create uintptr
+ vdso_zx_thread_start uintptr
+ vdso_zx_thread_read_state uintptr
+ vdso_zx_thread_write_state uintptr
+ vdso_zx_process_exit uintptr
+ vdso_zx_process_create uintptr
+ vdso_zx_process_start uintptr
+ vdso_zx_process_read_memory uintptr
+ vdso_zx_process_write_memory uintptr
+ vdso_zx_job_create uintptr
+ vdso_zx_job_set_policy uintptr
+ vdso_zx_task_bind_exception_port uintptr
+ vdso_zx_task_suspend uintptr
+ vdso_zx_task_suspend_token uintptr
+ vdso_zx_task_resume_from_exception uintptr
+ vdso_zx_task_kill uintptr
+ vdso_zx_event_create uintptr
+ vdso_zx_eventpair_create uintptr
+ vdso_zx_futex_wait uintptr
+ vdso_zx_futex_wake uintptr
+ vdso_zx_futex_requeue uintptr
+ vdso_zx_futex_wake_single_owner uintptr
+ vdso_zx_futex_requeue_single_owner uintptr
+ vdso_zx_futex_get_owner uintptr
+ vdso_zx_port_create uintptr
+ vdso_zx_port_queue uintptr
+ vdso_zx_port_wait uintptr
+ vdso_zx_port_cancel uintptr
+ vdso_zx_timer_create uintptr
+ vdso_zx_timer_set uintptr
+ vdso_zx_timer_cancel uintptr
+ vdso_zx_vmo_create uintptr
+ vdso_zx_vmo_read uintptr
+ vdso_zx_vmo_write uintptr
+ vdso_zx_vmo_get_size uintptr
+ vdso_zx_vmo_set_size uintptr
+ vdso_zx_vmo_op_range uintptr
+ vdso_zx_vmo_create_child uintptr
+ vdso_zx_vmo_set_cache_policy uintptr
+ vdso_zx_vmo_replace_as_executable uintptr
+ vdso_zx_vmar_allocate uintptr
+ vdso_zx_vmar_destroy uintptr
+ vdso_zx_vmar_map uintptr
+ vdso_zx_vmar_unmap uintptr
+ vdso_zx_vmar_protect uintptr
+ vdso_zx_cprng_draw_once uintptr
+ vdso_zx_cprng_draw uintptr
+ vdso_zx_cprng_add_entropy uintptr
+ vdso_zx_fifo_create uintptr
+ vdso_zx_fifo_read uintptr
+ vdso_zx_fifo_write uintptr
+ vdso_zx_profile_create uintptr
+ vdso_zx_vmar_unmap_handle_close_thread_exit uintptr
+ vdso_zx_futex_wake_handle_close_thread_exit uintptr
+ vdso_zx_debuglog_create uintptr
+ vdso_zx_debuglog_write uintptr
+ vdso_zx_debuglog_read uintptr
+ vdso_zx_ktrace_read uintptr
+ vdso_zx_ktrace_control uintptr
+ vdso_zx_ktrace_write uintptr
+ vdso_zx_mtrace_control uintptr
+ vdso_zx_debug_read uintptr
+ vdso_zx_debug_write uintptr
+ vdso_zx_debug_send_command uintptr
+ vdso_zx_interrupt_create uintptr
+ vdso_zx_interrupt_bind uintptr
+ vdso_zx_interrupt_wait uintptr
+ vdso_zx_interrupt_destroy uintptr
+ vdso_zx_interrupt_ack uintptr
+ vdso_zx_interrupt_trigger uintptr
+ vdso_zx_interrupt_bind_vcpu uintptr
+ vdso_zx_ioports_request uintptr
+ vdso_zx_vmo_create_contiguous uintptr
+ vdso_zx_vmo_create_physical uintptr
+ vdso_zx_iommu_create uintptr
+ vdso_zx_bti_create uintptr
+ vdso_zx_bti_pin uintptr
+ vdso_zx_bti_release_quarantine uintptr
+ vdso_zx_pmt_unpin uintptr
+ vdso_zx_framebuffer_get_info uintptr
+ vdso_zx_framebuffer_set_range uintptr
+ vdso_zx_pc_firmware_tables uintptr
+ vdso_zx_smc_call uintptr
+ vdso_zx_resource_create uintptr
+ vdso_zx_system_mexec uintptr
+ vdso_zx_system_mexec_payload_get uintptr
+ vdso_zx_system_powerctl uintptr
+ vdso_zx_pager_create uintptr
+ vdso_zx_pager_create_vmo uintptr
+ vdso_zx_pager_detach_vmo uintptr
+ vdso_zx_pager_supply_pages uintptr
+)
diff --git a/src/runtime/vdso_linux.go b/src/runtime/vdso_linux.go
index 71ba4ce..ed09b4c 100644
--- a/src/runtime/vdso_linux.go
+++ b/src/runtime/vdso_linux.go
@@ -20,52 +20,6 @@
// The version section is documented at
// https://refspecs.linuxfoundation.org/LSB_3.2.0/LSB-Core-generic/LSB-Core-generic/symversion.html
-const (
- _AT_SYSINFO_EHDR = 33
-
- _PT_LOAD = 1 /* Loadable program segment */
- _PT_DYNAMIC = 2 /* Dynamic linking information */
-
- _DT_NULL = 0 /* Marks end of dynamic section */
- _DT_HASH = 4 /* Dynamic symbol hash table */
- _DT_STRTAB = 5 /* Address of string table */
- _DT_SYMTAB = 6 /* Address of symbol table */
- _DT_GNU_HASH = 0x6ffffef5 /* GNU-style dynamic symbol hash table */
- _DT_VERSYM = 0x6ffffff0
- _DT_VERDEF = 0x6ffffffc
-
- _VER_FLG_BASE = 0x1 /* Version definition of file itself */
-
- _SHN_UNDEF = 0 /* Undefined section */
-
- _SHT_DYNSYM = 11 /* Dynamic linker symbol table */
-
- _STT_FUNC = 2 /* Symbol is a code object */
-
- _STT_NOTYPE = 0 /* Symbol type is not specified */
-
- _STB_GLOBAL = 1 /* Global symbol */
- _STB_WEAK = 2 /* Weak symbol */
-
- _EI_NIDENT = 16
-
- // Maximum indices for the array types used when traversing the vDSO ELF structures.
- // Computed from architecture-specific max provided by vdso_linux_*.go
- vdsoSymTabSize = vdsoArrayMax / unsafe.Sizeof(elfSym{})
- vdsoDynSize = vdsoArrayMax / unsafe.Sizeof(elfDyn{})
- vdsoSymStringsSize = vdsoArrayMax // byte
- vdsoVerSymSize = vdsoArrayMax / 2 // uint16
- vdsoHashSize = vdsoArrayMax / 4 // uint32
-
- // vdsoBloomSizeScale is a scaling factor for gnuhash tables which are uint32 indexed,
- // but contain uintptrs
- vdsoBloomSizeScale = unsafe.Sizeof(uintptr(0)) / 4 // uint32
-)
-
-/* How to extract and insert information held in the st_info field. */
-func _ELF_ST_BIND(val byte) byte { return val >> 4 }
-func _ELF_ST_TYPE(val byte) byte { return val & 0xf }
-
type vdsoSymbolKey struct {
name string
symHash uint32
diff --git a/src/runtime/vdsocalls_fuchsia_amd64.s b/src/runtime/vdsocalls_fuchsia_amd64.s
new file mode 100644
index 0000000..6f99a4a
--- /dev/null
+++ b/src/runtime/vdsocalls_fuchsia_amd64.s
@@ -0,0 +1,3025 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Zircon system calls for the Fuchsia OS.
+// Generated by mkfuchsia.go, do not edit.
+
+#include "go_asm.h"
+#include "go_tls.h"
+#include "textflag.h"
+#include "funcdata.h"
+
+// func vdsoCall_zx_clock_get(clock_id uint32) int64
+TEXT runtime·vdsoCall_zx_clock_get(SB),NOSPLIT,$8-16
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), R14
+ PUSHQ R14
+ MOVQ 24(SP), DX
+ MOVQ DX, m_vdsoPC(R14)
+ LEAQ 24(SP), DX
+ MOVQ DX, m_vdsoSP(R14)
+ MOVL clock_id+0(FP), DI
+ MOVQ vdso_zx_clock_get(SB), AX
+ CALL AX
+ MOVQ AX, ret+8(FP)
+ POPQ R14
+ MOVQ $0, m_vdsoSP(R14)
+ RET
+
+// func vdsoCall_zx_clock_get_new(clock_id uint32, out unsafe.Pointer) int32
+TEXT runtime·vdsoCall_zx_clock_get_new(SB),NOSPLIT,$8-20
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), R14
+ PUSHQ R14
+ MOVQ 24(SP), DX
+ MOVQ DX, m_vdsoPC(R14)
+ LEAQ 24(SP), DX
+ MOVQ DX, m_vdsoSP(R14)
+ MOVL clock_id+0(FP), DI
+ MOVQ out+8(FP), SI
+ MOVQ vdso_zx_clock_get_new(SB), AX
+ CALL AX
+ MOVL AX, ret+16(FP)
+ POPQ R14
+ MOVQ $0, m_vdsoSP(R14)
+ RET
+
+// func vdsoCall_zx_clock_get_monotonic() int64
+TEXT runtime·vdsoCall_zx_clock_get_monotonic(SB),NOSPLIT,$8-8
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), R14
+ PUSHQ R14
+ MOVQ 24(SP), DX
+ MOVQ DX, m_vdsoPC(R14)
+ LEAQ 24(SP), DX
+ MOVQ DX, m_vdsoSP(R14)
+ MOVQ vdso_zx_clock_get_monotonic(SB), AX
+ CALL AX
+ MOVQ AX, ret+0(FP)
+ POPQ R14
+ MOVQ $0, m_vdsoSP(R14)
+ RET
+
+// func vdsoCall_zx_nanosleep(deadline int64) int32
+TEXT runtime·vdsoCall_zx_nanosleep(SB),NOSPLIT,$8-12
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), R14
+ PUSHQ R14
+ MOVQ 24(SP), DX
+ MOVQ DX, m_vdsoPC(R14)
+ LEAQ 24(SP), DX
+ MOVQ DX, m_vdsoSP(R14)
+ MOVQ deadline+0(FP), DI
+ MOVQ vdso_zx_nanosleep(SB), AX
+ CALL AX
+ MOVL AX, ret+8(FP)
+ POPQ R14
+ MOVQ $0, m_vdsoSP(R14)
+ RET
+
+// func vdsoCall_zx_ticks_get() uint64
+TEXT runtime·vdsoCall_zx_ticks_get(SB),NOSPLIT,$8-8
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), R14
+ PUSHQ R14
+ MOVQ 24(SP), DX
+ MOVQ DX, m_vdsoPC(R14)
+ LEAQ 24(SP), DX
+ MOVQ DX, m_vdsoSP(R14)
+ MOVQ vdso_zx_ticks_get(SB), AX
+ CALL AX
+ MOVQ AX, ret+0(FP)
+ POPQ R14
+ MOVQ $0, m_vdsoSP(R14)
+ RET
+
+// func vdsoCall_zx_ticks_per_second() uint64
+TEXT runtime·vdsoCall_zx_ticks_per_second(SB),NOSPLIT,$8-8
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), R14
+ PUSHQ R14
+ MOVQ 24(SP), DX
+ MOVQ DX, m_vdsoPC(R14)
+ LEAQ 24(SP), DX
+ MOVQ DX, m_vdsoSP(R14)
+ MOVQ vdso_zx_ticks_per_second(SB), AX
+ CALL AX
+ MOVQ AX, ret+0(FP)
+ POPQ R14
+ MOVQ $0, m_vdsoSP(R14)
+ RET
+
+// func vdsoCall_zx_deadline_after(nanoseconds int64) int64
+TEXT runtime·vdsoCall_zx_deadline_after(SB),NOSPLIT,$8-16
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), R14
+ PUSHQ R14
+ MOVQ 24(SP), DX
+ MOVQ DX, m_vdsoPC(R14)
+ LEAQ 24(SP), DX
+ MOVQ DX, m_vdsoSP(R14)
+ MOVQ nanoseconds+0(FP), DI
+ MOVQ vdso_zx_deadline_after(SB), AX
+ CALL AX
+ MOVQ AX, ret+8(FP)
+ POPQ R14
+ MOVQ $0, m_vdsoSP(R14)
+ RET
+
+// func vdsoCall_zx_clock_adjust(handle uint32, clock_id uint32, offset int64) int32
+TEXT runtime·vdsoCall_zx_clock_adjust(SB),NOSPLIT,$8-20
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), R14
+ PUSHQ R14
+ MOVQ 24(SP), DX
+ MOVQ DX, m_vdsoPC(R14)
+ LEAQ 24(SP), DX
+ MOVQ DX, m_vdsoSP(R14)
+ MOVL handle+0(FP), DI
+ MOVL clock_id+4(FP), SI
+ MOVQ offset+8(FP), DX
+ MOVQ vdso_zx_clock_adjust(SB), AX
+ CALL AX
+ MOVL AX, ret+16(FP)
+ POPQ R14
+ MOVQ $0, m_vdsoSP(R14)
+ RET
+
+// func vdsoCall_zx_system_get_dcache_line_size() uint32
+TEXT runtime·vdsoCall_zx_system_get_dcache_line_size(SB),NOSPLIT,$8-4
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), R14
+ PUSHQ R14
+ MOVQ 24(SP), DX
+ MOVQ DX, m_vdsoPC(R14)
+ LEAQ 24(SP), DX
+ MOVQ DX, m_vdsoSP(R14)
+ MOVQ vdso_zx_system_get_dcache_line_size(SB), AX
+ CALL AX
+ MOVL AX, ret+0(FP)
+ POPQ R14
+ MOVQ $0, m_vdsoSP(R14)
+ RET
+
+// func vdsoCall_zx_system_get_num_cpus() uint32
+TEXT runtime·vdsoCall_zx_system_get_num_cpus(SB),NOSPLIT,$8-4
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), R14
+ PUSHQ R14
+ MOVQ 24(SP), DX
+ MOVQ DX, m_vdsoPC(R14)
+ LEAQ 24(SP), DX
+ MOVQ DX, m_vdsoSP(R14)
+ MOVQ vdso_zx_system_get_num_cpus(SB), AX
+ CALL AX
+ MOVL AX, ret+0(FP)
+ POPQ R14
+ MOVQ $0, m_vdsoSP(R14)
+ RET
+
+// func vdsoCall_zx_system_get_version(version unsafe.Pointer, version_size uint) int32
+TEXT runtime·vdsoCall_zx_system_get_version(SB),NOSPLIT,$8-20
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), R14
+ PUSHQ R14
+ MOVQ 24(SP), DX
+ MOVQ DX, m_vdsoPC(R14)
+ LEAQ 24(SP), DX
+ MOVQ DX, m_vdsoSP(R14)
+ MOVQ version+0(FP), DI
+ MOVQ version_size+8(FP), SI
+ MOVQ vdso_zx_system_get_version(SB), AX
+ CALL AX
+ MOVL AX, ret+16(FP)
+ POPQ R14
+ MOVQ $0, m_vdsoSP(R14)
+ RET
+
+// func vdsoCall_zx_system_get_physmem() uint64
+TEXT runtime·vdsoCall_zx_system_get_physmem(SB),NOSPLIT,$8-8
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), R14
+ PUSHQ R14
+ MOVQ 24(SP), DX
+ MOVQ DX, m_vdsoPC(R14)
+ LEAQ 24(SP), DX
+ MOVQ DX, m_vdsoSP(R14)
+ MOVQ vdso_zx_system_get_physmem(SB), AX
+ CALL AX
+ MOVQ AX, ret+0(FP)
+ POPQ R14
+ MOVQ $0, m_vdsoSP(R14)
+ RET
+
+// func vdsoCall_zx_system_get_features(kind uint32, features unsafe.Pointer) int32
+TEXT runtime·vdsoCall_zx_system_get_features(SB),NOSPLIT,$8-20
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), R14
+ PUSHQ R14
+ MOVQ 24(SP), DX
+ MOVQ DX, m_vdsoPC(R14)
+ LEAQ 24(SP), DX
+ MOVQ DX, m_vdsoSP(R14)
+ MOVL kind+0(FP), DI
+ MOVQ features+8(FP), SI
+ MOVQ vdso_zx_system_get_features(SB), AX
+ CALL AX
+ MOVL AX, ret+16(FP)
+ POPQ R14
+ MOVQ $0, m_vdsoSP(R14)
+ RET
+
+// func vdsoCall_zx_cache_flush(addr unsafe.Pointer, size uint, options uint32) int32
+TEXT runtime·vdsoCall_zx_cache_flush(SB),NOSPLIT,$8-28
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), R14
+ PUSHQ R14
+ MOVQ 24(SP), DX
+ MOVQ DX, m_vdsoPC(R14)
+ LEAQ 24(SP), DX
+ MOVQ DX, m_vdsoSP(R14)
+ MOVQ addr+0(FP), DI
+ MOVQ size+8(FP), SI
+ MOVL options+16(FP), DX
+ MOVQ vdso_zx_cache_flush(SB), AX
+ CALL AX
+ MOVL AX, ret+24(FP)
+ POPQ R14
+ MOVQ $0, m_vdsoSP(R14)
+ RET
+
+// func vdsoCall_zx_handle_close(handle uint32) int32
+TEXT runtime·vdsoCall_zx_handle_close(SB),NOSPLIT,$8-12
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), R14
+ PUSHQ R14
+ MOVQ 24(SP), DX
+ MOVQ DX, m_vdsoPC(R14)
+ LEAQ 24(SP), DX
+ MOVQ DX, m_vdsoSP(R14)
+ MOVL handle+0(FP), DI
+ MOVQ vdso_zx_handle_close(SB), AX
+ CALL AX
+ MOVL AX, ret+8(FP)
+ POPQ R14
+ MOVQ $0, m_vdsoSP(R14)
+ RET
+
+// func vdsoCall_zx_handle_close_many(handles unsafe.Pointer, num_handles uint) int32
+TEXT runtime·vdsoCall_zx_handle_close_many(SB),NOSPLIT,$8-20
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), R14
+ PUSHQ R14
+ MOVQ 24(SP), DX
+ MOVQ DX, m_vdsoPC(R14)
+ LEAQ 24(SP), DX
+ MOVQ DX, m_vdsoSP(R14)
+ MOVQ handles+0(FP), DI
+ MOVQ num_handles+8(FP), SI
+ MOVQ vdso_zx_handle_close_many(SB), AX
+ CALL AX
+ MOVL AX, ret+16(FP)
+ POPQ R14
+ MOVQ $0, m_vdsoSP(R14)
+ RET
+
+// func vdsoCall_zx_handle_duplicate(handle uint32, rights uint32, out unsafe.Pointer) int32
+TEXT runtime·vdsoCall_zx_handle_duplicate(SB),NOSPLIT,$8-20
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), R14
+ PUSHQ R14
+ MOVQ 24(SP), DX
+ MOVQ DX, m_vdsoPC(R14)
+ LEAQ 24(SP), DX
+ MOVQ DX, m_vdsoSP(R14)
+ MOVL handle+0(FP), DI
+ MOVL rights+4(FP), SI
+ MOVQ out+8(FP), DX
+ MOVQ vdso_zx_handle_duplicate(SB), AX
+ CALL AX
+ MOVL AX, ret+16(FP)
+ POPQ R14
+ MOVQ $0, m_vdsoSP(R14)
+ RET
+
+// func vdsoCall_zx_handle_replace(handle uint32, rights uint32, out unsafe.Pointer) int32
+TEXT runtime·vdsoCall_zx_handle_replace(SB),NOSPLIT,$8-20
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), R14
+ PUSHQ R14
+ MOVQ 24(SP), DX
+ MOVQ DX, m_vdsoPC(R14)
+ LEAQ 24(SP), DX
+ MOVQ DX, m_vdsoSP(R14)
+ MOVL handle+0(FP), DI
+ MOVL rights+4(FP), SI
+ MOVQ out+8(FP), DX
+ MOVQ vdso_zx_handle_replace(SB), AX
+ CALL AX
+ MOVL AX, ret+16(FP)
+ POPQ R14
+ MOVQ $0, m_vdsoSP(R14)
+ RET
+
+// func vdsoCall_zx_object_wait_one(handle uint32, signals uint32, deadline int64, observed unsafe.Pointer) int32
+TEXT runtime·vdsoCall_zx_object_wait_one(SB),NOSPLIT,$8-28
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), R14
+ PUSHQ R14
+ MOVQ 24(SP), DX
+ MOVQ DX, m_vdsoPC(R14)
+ LEAQ 24(SP), DX
+ MOVQ DX, m_vdsoSP(R14)
+ CALL runtime·entersyscall(SB)
+ MOVL handle+0(FP), DI
+ MOVL signals+4(FP), SI
+ MOVQ deadline+8(FP), DX
+ MOVQ observed+16(FP), CX
+ MOVQ vdso_zx_object_wait_one(SB), AX
+ CALL AX
+ MOVL AX, ret+24(FP)
+ CALL runtime·exitsyscall(SB)
+ POPQ R14
+ MOVQ $0, m_vdsoSP(R14)
+ RET
+
+// func vdsoCall_zx_object_wait_many(items unsafe.Pointer, count uint, deadline int64) int32
+TEXT runtime·vdsoCall_zx_object_wait_many(SB),NOSPLIT,$8-28
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), R14
+ PUSHQ R14
+ MOVQ 24(SP), DX
+ MOVQ DX, m_vdsoPC(R14)
+ LEAQ 24(SP), DX
+ MOVQ DX, m_vdsoSP(R14)
+ CALL runtime·entersyscall(SB)
+ MOVQ items+0(FP), DI
+ MOVQ count+8(FP), SI
+ MOVQ deadline+16(FP), DX
+ MOVQ vdso_zx_object_wait_many(SB), AX
+ CALL AX
+ MOVL AX, ret+24(FP)
+ CALL runtime·exitsyscall(SB)
+ POPQ R14
+ MOVQ $0, m_vdsoSP(R14)
+ RET
+
+// func vdsoCall_zx_object_wait_async(handle uint32, port uint32, key uint64, signals uint32, options uint32) int32
+TEXT runtime·vdsoCall_zx_object_wait_async(SB),NOSPLIT,$8-28
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), R14
+ PUSHQ R14
+ MOVQ 24(SP), DX
+ MOVQ DX, m_vdsoPC(R14)
+ LEAQ 24(SP), DX
+ MOVQ DX, m_vdsoSP(R14)
+ MOVL handle+0(FP), DI
+ MOVL port+4(FP), SI
+ MOVQ key+8(FP), DX
+ MOVL signals+16(FP), CX
+ MOVL options+20(FP), R8
+ MOVQ vdso_zx_object_wait_async(SB), AX
+ CALL AX
+ MOVL AX, ret+24(FP)
+ POPQ R14
+ MOVQ $0, m_vdsoSP(R14)
+ RET
+
+// func vdsoCall_zx_object_signal(handle uint32, clear_mask uint32, set_mask uint32) int32
+TEXT runtime·vdsoCall_zx_object_signal(SB),NOSPLIT,$8-20
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), R14
+ PUSHQ R14
+ MOVQ 24(SP), DX
+ MOVQ DX, m_vdsoPC(R14)
+ LEAQ 24(SP), DX
+ MOVQ DX, m_vdsoSP(R14)
+ MOVL handle+0(FP), DI
+ MOVL clear_mask+4(FP), SI
+ MOVL set_mask+8(FP), DX
+ MOVQ vdso_zx_object_signal(SB), AX
+ CALL AX
+ MOVL AX, ret+16(FP)
+ POPQ R14
+ MOVQ $0, m_vdsoSP(R14)
+ RET
+
+// func vdsoCall_zx_object_signal_peer(handle uint32, clear_mask uint32, set_mask uint32) int32
+TEXT runtime·vdsoCall_zx_object_signal_peer(SB),NOSPLIT,$8-20
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), R14
+ PUSHQ R14
+ MOVQ 24(SP), DX
+ MOVQ DX, m_vdsoPC(R14)
+ LEAQ 24(SP), DX
+ MOVQ DX, m_vdsoSP(R14)
+ MOVL handle+0(FP), DI
+ MOVL clear_mask+4(FP), SI
+ MOVL set_mask+8(FP), DX
+ MOVQ vdso_zx_object_signal_peer(SB), AX
+ CALL AX
+ MOVL AX, ret+16(FP)
+ POPQ R14
+ MOVQ $0, m_vdsoSP(R14)
+ RET
+
+// func vdsoCall_zx_object_get_property(handle uint32, property uint32, value unsafe.Pointer, value_size uint) int32
+TEXT runtime·vdsoCall_zx_object_get_property(SB),NOSPLIT,$8-28
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), R14
+ PUSHQ R14
+ MOVQ 24(SP), DX
+ MOVQ DX, m_vdsoPC(R14)
+ LEAQ 24(SP), DX
+ MOVQ DX, m_vdsoSP(R14)
+ MOVL handle+0(FP), DI
+ MOVL property+4(FP), SI
+ MOVQ value+8(FP), DX
+ MOVQ value_size+16(FP), CX
+ MOVQ vdso_zx_object_get_property(SB), AX
+ CALL AX
+ MOVL AX, ret+24(FP)
+ POPQ R14
+ MOVQ $0, m_vdsoSP(R14)
+ RET
+
+// func vdsoCall_zx_object_set_property(handle uint32, property uint32, value unsafe.Pointer, value_size uint) int32
+TEXT runtime·vdsoCall_zx_object_set_property(SB),NOSPLIT,$8-28
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), R14
+ PUSHQ R14
+ MOVQ 24(SP), DX
+ MOVQ DX, m_vdsoPC(R14)
+ LEAQ 24(SP), DX
+ MOVQ DX, m_vdsoSP(R14)
+ MOVL handle+0(FP), DI
+ MOVL property+4(FP), SI
+ MOVQ value+8(FP), DX
+ MOVQ value_size+16(FP), CX
+ MOVQ vdso_zx_object_set_property(SB), AX
+ CALL AX
+ MOVL AX, ret+24(FP)
+ POPQ R14
+ MOVQ $0, m_vdsoSP(R14)
+ RET
+
+// func vdsoCall_zx_object_get_info(handle uint32, topic uint32, buffer unsafe.Pointer, buffer_size uint, actual unsafe.Pointer, avail unsafe.Pointer) int32
+TEXT runtime·vdsoCall_zx_object_get_info(SB),NOSPLIT,$8-44
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), R14
+ PUSHQ R14
+ MOVQ 24(SP), DX
+ MOVQ DX, m_vdsoPC(R14)
+ LEAQ 24(SP), DX
+ MOVQ DX, m_vdsoSP(R14)
+ MOVL handle+0(FP), DI
+ MOVL topic+4(FP), SI
+ MOVQ buffer+8(FP), DX
+ MOVQ buffer_size+16(FP), CX
+ MOVQ actual+24(FP), R8
+ MOVQ avail+32(FP), R9
+ MOVQ vdso_zx_object_get_info(SB), AX
+ CALL AX
+ MOVL AX, ret+40(FP)
+ POPQ R14
+ MOVQ $0, m_vdsoSP(R14)
+ RET
+
+// func vdsoCall_zx_object_get_child(handle uint32, koid uint64, rights uint32, out unsafe.Pointer) int32
+TEXT runtime·vdsoCall_zx_object_get_child(SB),NOSPLIT,$8-36
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), R14
+ PUSHQ R14
+ MOVQ 24(SP), DX
+ MOVQ DX, m_vdsoPC(R14)
+ LEAQ 24(SP), DX
+ MOVQ DX, m_vdsoSP(R14)
+ MOVL handle+0(FP), DI
+ MOVQ koid+8(FP), SI
+ MOVL rights+16(FP), DX
+ MOVQ out+24(FP), CX
+ MOVQ vdso_zx_object_get_child(SB), AX
+ CALL AX
+ MOVL AX, ret+32(FP)
+ POPQ R14
+ MOVQ $0, m_vdsoSP(R14)
+ RET
+
+// func vdsoCall_zx_object_set_profile(handle uint32, profile uint32, options uint32) int32
+TEXT runtime·vdsoCall_zx_object_set_profile(SB),NOSPLIT,$8-20
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), R14
+ PUSHQ R14
+ MOVQ 24(SP), DX
+ MOVQ DX, m_vdsoPC(R14)
+ LEAQ 24(SP), DX
+ MOVQ DX, m_vdsoSP(R14)
+ MOVL handle+0(FP), DI
+ MOVL profile+4(FP), SI
+ MOVL options+8(FP), DX
+ MOVQ vdso_zx_object_set_profile(SB), AX
+ CALL AX
+ MOVL AX, ret+16(FP)
+ POPQ R14
+ MOVQ $0, m_vdsoSP(R14)
+ RET
+
+// func vdsoCall_zx_channel_create(options uint32, out0 unsafe.Pointer, out1 unsafe.Pointer) int32
+TEXT runtime·vdsoCall_zx_channel_create(SB),NOSPLIT,$8-28
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), R14
+ PUSHQ R14
+ MOVQ 24(SP), DX
+ MOVQ DX, m_vdsoPC(R14)
+ LEAQ 24(SP), DX
+ MOVQ DX, m_vdsoSP(R14)
+ MOVL options+0(FP), DI
+ MOVQ out0+8(FP), SI
+ MOVQ out1+16(FP), DX
+ MOVQ vdso_zx_channel_create(SB), AX
+ CALL AX
+ MOVL AX, ret+24(FP)
+ POPQ R14
+ MOVQ $0, m_vdsoSP(R14)
+ RET
+
+// func vdsoCall_zx_channel_read(handle uint32, options uint32, bytes unsafe.Pointer, handles unsafe.Pointer, num_bytes uint32, num_handles uint32, actual_bytes unsafe.Pointer, actual_handles unsafe.Pointer) int32
+TEXT runtime·vdsoCall_zx_channel_read(SB),NOSPLIT,$40-52
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), R14
+ PUSHQ R14
+ MOVQ 56(SP), DX
+ MOVQ DX, m_vdsoPC(R14)
+ LEAQ 56(SP), DX
+ MOVQ DX, m_vdsoSP(R14)
+ MOVL handle+0(FP), DI
+ MOVL options+4(FP), SI
+ MOVQ bytes+8(FP), DX
+ MOVQ handles+16(FP), CX
+ MOVL num_bytes+24(FP), R8
+ MOVL num_handles+28(FP), R9
+ MOVQ actual_bytes+32(FP), R12
+ MOVQ actual_handles+40(FP), R13
+ MOVQ SP, BP // BP is preserved across vsdo call by the x86-64 ABI
+ ANDQ $~15, SP // stack alignment for x86-64 ABI
+ PUSHQ R13
+ PUSHQ R12
+ MOVQ vdso_zx_channel_read(SB), AX
+ CALL AX
+ POPQ R12
+ POPQ R13
+ MOVQ BP, SP
+ MOVL AX, ret+48(FP)
+ POPQ R14
+ MOVQ $0, m_vdsoSP(R14)
+ RET
+
+// func vdsoCall_zx_channel_read_etc(handle uint32, options uint32, bytes unsafe.Pointer, handles unsafe.Pointer, num_bytes uint32, num_handles uint32, actual_bytes unsafe.Pointer, actual_handles unsafe.Pointer) int32
+TEXT runtime·vdsoCall_zx_channel_read_etc(SB),NOSPLIT,$40-52
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), R14
+ PUSHQ R14
+ MOVQ 56(SP), DX
+ MOVQ DX, m_vdsoPC(R14)
+ LEAQ 56(SP), DX
+ MOVQ DX, m_vdsoSP(R14)
+ MOVL handle+0(FP), DI
+ MOVL options+4(FP), SI
+ MOVQ bytes+8(FP), DX
+ MOVQ handles+16(FP), CX
+ MOVL num_bytes+24(FP), R8
+ MOVL num_handles+28(FP), R9
+ MOVQ actual_bytes+32(FP), R12
+ MOVQ actual_handles+40(FP), R13
+ MOVQ SP, BP // BP is preserved across vsdo call by the x86-64 ABI
+ ANDQ $~15, SP // stack alignment for x86-64 ABI
+ PUSHQ R13
+ PUSHQ R12
+ MOVQ vdso_zx_channel_read_etc(SB), AX
+ CALL AX
+ POPQ R12
+ POPQ R13
+ MOVQ BP, SP
+ MOVL AX, ret+48(FP)
+ POPQ R14
+ MOVQ $0, m_vdsoSP(R14)
+ RET
+
+// func vdsoCall_zx_channel_write(handle uint32, options uint32, bytes unsafe.Pointer, num_bytes uint32, handles unsafe.Pointer, num_handles uint32) int32
+TEXT runtime·vdsoCall_zx_channel_write(SB),NOSPLIT,$8-44
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), R14
+ PUSHQ R14
+ MOVQ 24(SP), DX
+ MOVQ DX, m_vdsoPC(R14)
+ LEAQ 24(SP), DX
+ MOVQ DX, m_vdsoSP(R14)
+ MOVL handle+0(FP), DI
+ MOVL options+4(FP), SI
+ MOVQ bytes+8(FP), DX
+ MOVL num_bytes+16(FP), CX
+ MOVQ handles+24(FP), R8
+ MOVL num_handles+32(FP), R9
+ MOVQ vdso_zx_channel_write(SB), AX
+ CALL AX
+ MOVL AX, ret+40(FP)
+ POPQ R14
+ MOVQ $0, m_vdsoSP(R14)
+ RET
+
+// func vdsoCall_zx_channel_call_noretry(handle uint32, options uint32, deadline int64, args unsafe.Pointer, actual_bytes unsafe.Pointer, actual_handles unsafe.Pointer) int32
+TEXT runtime·vdsoCall_zx_channel_call_noretry(SB),NOSPLIT,$8-44
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), R14
+ PUSHQ R14
+ MOVQ 24(SP), DX
+ MOVQ DX, m_vdsoPC(R14)
+ LEAQ 24(SP), DX
+ MOVQ DX, m_vdsoSP(R14)
+ MOVL handle+0(FP), DI
+ MOVL options+4(FP), SI
+ MOVQ deadline+8(FP), DX
+ MOVQ args+16(FP), CX
+ MOVQ actual_bytes+24(FP), R8
+ MOVQ actual_handles+32(FP), R9
+ MOVQ vdso_zx_channel_call_noretry(SB), AX
+ CALL AX
+ MOVL AX, ret+40(FP)
+ POPQ R14
+ MOVQ $0, m_vdsoSP(R14)
+ RET
+
+// func vdsoCall_zx_channel_call_finish(deadline int64, args unsafe.Pointer, actual_bytes unsafe.Pointer, actual_handles unsafe.Pointer) int32
+TEXT runtime·vdsoCall_zx_channel_call_finish(SB),NOSPLIT,$8-36
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), R14
+ PUSHQ R14
+ MOVQ 24(SP), DX
+ MOVQ DX, m_vdsoPC(R14)
+ LEAQ 24(SP), DX
+ MOVQ DX, m_vdsoSP(R14)
+ MOVQ deadline+0(FP), DI
+ MOVQ args+8(FP), SI
+ MOVQ actual_bytes+16(FP), DX
+ MOVQ actual_handles+24(FP), CX
+ MOVQ vdso_zx_channel_call_finish(SB), AX
+ CALL AX
+ MOVL AX, ret+32(FP)
+ POPQ R14
+ MOVQ $0, m_vdsoSP(R14)
+ RET
+
+// func vdsoCall_zx_channel_call(handle uint32, options uint32, deadline int64, args unsafe.Pointer, actual_bytes unsafe.Pointer, actual_handles unsafe.Pointer) int32
+TEXT runtime·vdsoCall_zx_channel_call(SB),NOSPLIT,$8-44
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), R14
+ PUSHQ R14
+ MOVQ 24(SP), DX
+ MOVQ DX, m_vdsoPC(R14)
+ LEAQ 24(SP), DX
+ MOVQ DX, m_vdsoSP(R14)
+ CALL runtime·entersyscall(SB)
+ MOVL handle+0(FP), DI
+ MOVL options+4(FP), SI
+ MOVQ deadline+8(FP), DX
+ MOVQ args+16(FP), CX
+ MOVQ actual_bytes+24(FP), R8
+ MOVQ actual_handles+32(FP), R9
+ MOVQ vdso_zx_channel_call(SB), AX
+ CALL AX
+ MOVL AX, ret+40(FP)
+ CALL runtime·exitsyscall(SB)
+ POPQ R14
+ MOVQ $0, m_vdsoSP(R14)
+ RET
+
+// func vdsoCall_zx_socket_create(options uint32, out0 unsafe.Pointer, out1 unsafe.Pointer) int32
+TEXT runtime·vdsoCall_zx_socket_create(SB),NOSPLIT,$8-28
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), R14
+ PUSHQ R14
+ MOVQ 24(SP), DX
+ MOVQ DX, m_vdsoPC(R14)
+ LEAQ 24(SP), DX
+ MOVQ DX, m_vdsoSP(R14)
+ MOVL options+0(FP), DI
+ MOVQ out0+8(FP), SI
+ MOVQ out1+16(FP), DX
+ MOVQ vdso_zx_socket_create(SB), AX
+ CALL AX
+ MOVL AX, ret+24(FP)
+ POPQ R14
+ MOVQ $0, m_vdsoSP(R14)
+ RET
+
+// func vdsoCall_zx_socket_write(handle uint32, options uint32, buffer unsafe.Pointer, buffer_size uint, actual unsafe.Pointer) int32
+TEXT runtime·vdsoCall_zx_socket_write(SB),NOSPLIT,$8-36
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), R14
+ PUSHQ R14
+ MOVQ 24(SP), DX
+ MOVQ DX, m_vdsoPC(R14)
+ LEAQ 24(SP), DX
+ MOVQ DX, m_vdsoSP(R14)
+ MOVL handle+0(FP), DI
+ MOVL options+4(FP), SI
+ MOVQ buffer+8(FP), DX
+ MOVQ buffer_size+16(FP), CX
+ MOVQ actual+24(FP), R8
+ MOVQ vdso_zx_socket_write(SB), AX
+ CALL AX
+ MOVL AX, ret+32(FP)
+ POPQ R14
+ MOVQ $0, m_vdsoSP(R14)
+ RET
+
+// func vdsoCall_zx_socket_read(handle uint32, options uint32, buffer unsafe.Pointer, buffer_size uint, actual unsafe.Pointer) int32
+TEXT runtime·vdsoCall_zx_socket_read(SB),NOSPLIT,$8-36
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), R14
+ PUSHQ R14
+ MOVQ 24(SP), DX
+ MOVQ DX, m_vdsoPC(R14)
+ LEAQ 24(SP), DX
+ MOVQ DX, m_vdsoSP(R14)
+ MOVL handle+0(FP), DI
+ MOVL options+4(FP), SI
+ MOVQ buffer+8(FP), DX
+ MOVQ buffer_size+16(FP), CX
+ MOVQ actual+24(FP), R8
+ MOVQ vdso_zx_socket_read(SB), AX
+ CALL AX
+ MOVL AX, ret+32(FP)
+ POPQ R14
+ MOVQ $0, m_vdsoSP(R14)
+ RET
+
+// func vdsoCall_zx_socket_share(handle uint32, socket_to_share uint32) int32
+TEXT runtime·vdsoCall_zx_socket_share(SB),NOSPLIT,$8-12
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), R14
+ PUSHQ R14
+ MOVQ 24(SP), DX
+ MOVQ DX, m_vdsoPC(R14)
+ LEAQ 24(SP), DX
+ MOVQ DX, m_vdsoSP(R14)
+ MOVL handle+0(FP), DI
+ MOVL socket_to_share+4(FP), SI
+ MOVQ vdso_zx_socket_share(SB), AX
+ CALL AX
+ MOVL AX, ret+8(FP)
+ POPQ R14
+ MOVQ $0, m_vdsoSP(R14)
+ RET
+
+// func vdsoCall_zx_socket_accept(handle uint32, out_socket unsafe.Pointer) int32
+TEXT runtime·vdsoCall_zx_socket_accept(SB),NOSPLIT,$8-20
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), R14
+ PUSHQ R14
+ MOVQ 24(SP), DX
+ MOVQ DX, m_vdsoPC(R14)
+ LEAQ 24(SP), DX
+ MOVQ DX, m_vdsoSP(R14)
+ MOVL handle+0(FP), DI
+ MOVQ out_socket+8(FP), SI
+ MOVQ vdso_zx_socket_accept(SB), AX
+ CALL AX
+ MOVL AX, ret+16(FP)
+ POPQ R14
+ MOVQ $0, m_vdsoSP(R14)
+ RET
+
+// func vdsoCall_zx_socket_shutdown(handle uint32, options uint32) int32
+TEXT runtime·vdsoCall_zx_socket_shutdown(SB),NOSPLIT,$8-12
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), R14
+ PUSHQ R14
+ MOVQ 24(SP), DX
+ MOVQ DX, m_vdsoPC(R14)
+ LEAQ 24(SP), DX
+ MOVQ DX, m_vdsoSP(R14)
+ MOVL handle+0(FP), DI
+ MOVL options+4(FP), SI
+ MOVQ vdso_zx_socket_shutdown(SB), AX
+ CALL AX
+ MOVL AX, ret+8(FP)
+ POPQ R14
+ MOVQ $0, m_vdsoSP(R14)
+ RET
+
+// func vdsoCall_zx_thread_exit()
+TEXT runtime·vdsoCall_zx_thread_exit(SB),NOSPLIT,$8-0
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), R14
+ PUSHQ R14
+ MOVQ 24(SP), DX
+ MOVQ DX, m_vdsoPC(R14)
+ LEAQ 24(SP), DX
+ MOVQ DX, m_vdsoSP(R14)
+ MOVQ vdso_zx_thread_exit(SB), AX
+ CALL AX
+ POPQ R14
+ MOVQ $0, m_vdsoSP(R14)
+ RET
+
+// func vdsoCall_zx_thread_create(process uint32, name unsafe.Pointer, name_size uint, options uint32, out unsafe.Pointer) int32
+TEXT runtime·vdsoCall_zx_thread_create(SB),NOSPLIT,$8-44
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), R14
+ PUSHQ R14
+ MOVQ 24(SP), DX
+ MOVQ DX, m_vdsoPC(R14)
+ LEAQ 24(SP), DX
+ MOVQ DX, m_vdsoSP(R14)
+ MOVL process+0(FP), DI
+ MOVQ name+8(FP), SI
+ MOVQ name_size+16(FP), DX
+ MOVL options+24(FP), CX
+ MOVQ out+32(FP), R8
+ MOVQ vdso_zx_thread_create(SB), AX
+ CALL AX
+ MOVL AX, ret+40(FP)
+ POPQ R14
+ MOVQ $0, m_vdsoSP(R14)
+ RET
+
+// func vdsoCall_zx_thread_start(handle uint32, thread_entry uintptr, stack uintptr, arg1 uintptr, arg2 uintptr) int32
+TEXT runtime·vdsoCall_zx_thread_start(SB),NOSPLIT,$8-44
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), R14
+ PUSHQ R14
+ MOVQ 24(SP), DX
+ MOVQ DX, m_vdsoPC(R14)
+ LEAQ 24(SP), DX
+ MOVQ DX, m_vdsoSP(R14)
+ MOVL handle+0(FP), DI
+ MOVQ thread_entry+8(FP), SI
+ MOVQ stack+16(FP), DX
+ MOVQ arg1+24(FP), CX
+ MOVQ arg2+32(FP), R8
+ MOVQ vdso_zx_thread_start(SB), AX
+ CALL AX
+ MOVL AX, ret+40(FP)
+ POPQ R14
+ MOVQ $0, m_vdsoSP(R14)
+ RET
+
+// func vdsoCall_zx_thread_read_state(handle uint32, kind uint32, buffer unsafe.Pointer, buffer_size uint) int32
+TEXT runtime·vdsoCall_zx_thread_read_state(SB),NOSPLIT,$8-28
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), R14
+ PUSHQ R14
+ MOVQ 24(SP), DX
+ MOVQ DX, m_vdsoPC(R14)
+ LEAQ 24(SP), DX
+ MOVQ DX, m_vdsoSP(R14)
+ MOVL handle+0(FP), DI
+ MOVL kind+4(FP), SI
+ MOVQ buffer+8(FP), DX
+ MOVQ buffer_size+16(FP), CX
+ MOVQ vdso_zx_thread_read_state(SB), AX
+ CALL AX
+ MOVL AX, ret+24(FP)
+ POPQ R14
+ MOVQ $0, m_vdsoSP(R14)
+ RET
+
+// func vdsoCall_zx_thread_write_state(handle uint32, kind uint32, buffer unsafe.Pointer, buffer_size uint) int32
+TEXT runtime·vdsoCall_zx_thread_write_state(SB),NOSPLIT,$8-28
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), R14
+ PUSHQ R14
+ MOVQ 24(SP), DX
+ MOVQ DX, m_vdsoPC(R14)
+ LEAQ 24(SP), DX
+ MOVQ DX, m_vdsoSP(R14)
+ MOVL handle+0(FP), DI
+ MOVL kind+4(FP), SI
+ MOVQ buffer+8(FP), DX
+ MOVQ buffer_size+16(FP), CX
+ MOVQ vdso_zx_thread_write_state(SB), AX
+ CALL AX
+ MOVL AX, ret+24(FP)
+ POPQ R14
+ MOVQ $0, m_vdsoSP(R14)
+ RET
+
+// func vdsoCall_zx_process_exit(retcode int64)
+TEXT runtime·vdsoCall_zx_process_exit(SB),NOSPLIT,$8-8
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), R14
+ PUSHQ R14
+ MOVQ 24(SP), DX
+ MOVQ DX, m_vdsoPC(R14)
+ LEAQ 24(SP), DX
+ MOVQ DX, m_vdsoSP(R14)
+ MOVQ retcode+0(FP), DI
+ MOVQ vdso_zx_process_exit(SB), AX
+ CALL AX
+ POPQ R14
+ MOVQ $0, m_vdsoSP(R14)
+ RET
+
+// func vdsoCall_zx_process_create(job uint32, name unsafe.Pointer, name_size uint, options uint32, proc_handle unsafe.Pointer, vmar_handle unsafe.Pointer) int32
+TEXT runtime·vdsoCall_zx_process_create(SB),NOSPLIT,$8-52
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), R14
+ PUSHQ R14
+ MOVQ 24(SP), DX
+ MOVQ DX, m_vdsoPC(R14)
+ LEAQ 24(SP), DX
+ MOVQ DX, m_vdsoSP(R14)
+ MOVL job+0(FP), DI
+ MOVQ name+8(FP), SI
+ MOVQ name_size+16(FP), DX
+ MOVL options+24(FP), CX
+ MOVQ proc_handle+32(FP), R8
+ MOVQ vmar_handle+40(FP), R9
+ MOVQ vdso_zx_process_create(SB), AX
+ CALL AX
+ MOVL AX, ret+48(FP)
+ POPQ R14
+ MOVQ $0, m_vdsoSP(R14)
+ RET
+
+// func vdsoCall_zx_process_start(handle uint32, thread uint32, entry uintptr, stack uintptr, arg1 uint32, arg2 uintptr) int32
+TEXT runtime·vdsoCall_zx_process_start(SB),NOSPLIT,$8-44
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), R14
+ PUSHQ R14
+ MOVQ 24(SP), DX
+ MOVQ DX, m_vdsoPC(R14)
+ LEAQ 24(SP), DX
+ MOVQ DX, m_vdsoSP(R14)
+ MOVL handle+0(FP), DI
+ MOVL thread+4(FP), SI
+ MOVQ entry+8(FP), DX
+ MOVQ stack+16(FP), CX
+ MOVL arg1+24(FP), R8
+ MOVQ arg2+32(FP), R9
+ MOVQ vdso_zx_process_start(SB), AX
+ CALL AX
+ MOVL AX, ret+40(FP)
+ POPQ R14
+ MOVQ $0, m_vdsoSP(R14)
+ RET
+
+// func vdsoCall_zx_process_read_memory(handle uint32, vaddr uintptr, buffer unsafe.Pointer, buffer_size uint, actual unsafe.Pointer) int32
+TEXT runtime·vdsoCall_zx_process_read_memory(SB),NOSPLIT,$8-44
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), R14
+ PUSHQ R14
+ MOVQ 24(SP), DX
+ MOVQ DX, m_vdsoPC(R14)
+ LEAQ 24(SP), DX
+ MOVQ DX, m_vdsoSP(R14)
+ MOVL handle+0(FP), DI
+ MOVQ vaddr+8(FP), SI
+ MOVQ buffer+16(FP), DX
+ MOVQ buffer_size+24(FP), CX
+ MOVQ actual+32(FP), R8
+ MOVQ vdso_zx_process_read_memory(SB), AX
+ CALL AX
+ MOVL AX, ret+40(FP)
+ POPQ R14
+ MOVQ $0, m_vdsoSP(R14)
+ RET
+
+// func vdsoCall_zx_process_write_memory(handle uint32, vaddr uintptr, buffer unsafe.Pointer, buffer_size uint, actual unsafe.Pointer) int32
+TEXT runtime·vdsoCall_zx_process_write_memory(SB),NOSPLIT,$8-44
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), R14
+ PUSHQ R14
+ MOVQ 24(SP), DX
+ MOVQ DX, m_vdsoPC(R14)
+ LEAQ 24(SP), DX
+ MOVQ DX, m_vdsoSP(R14)
+ MOVL handle+0(FP), DI
+ MOVQ vaddr+8(FP), SI
+ MOVQ buffer+16(FP), DX
+ MOVQ buffer_size+24(FP), CX
+ MOVQ actual+32(FP), R8
+ MOVQ vdso_zx_process_write_memory(SB), AX
+ CALL AX
+ MOVL AX, ret+40(FP)
+ POPQ R14
+ MOVQ $0, m_vdsoSP(R14)
+ RET
+
+// func vdsoCall_zx_job_create(parent_job uint32, options uint32, out unsafe.Pointer) int32
+TEXT runtime·vdsoCall_zx_job_create(SB),NOSPLIT,$8-20
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), R14
+ PUSHQ R14
+ MOVQ 24(SP), DX
+ MOVQ DX, m_vdsoPC(R14)
+ LEAQ 24(SP), DX
+ MOVQ DX, m_vdsoSP(R14)
+ MOVL parent_job+0(FP), DI
+ MOVL options+4(FP), SI
+ MOVQ out+8(FP), DX
+ MOVQ vdso_zx_job_create(SB), AX
+ CALL AX
+ MOVL AX, ret+16(FP)
+ POPQ R14
+ MOVQ $0, m_vdsoSP(R14)
+ RET
+
+// func vdsoCall_zx_job_set_policy(handle uint32, options uint32, topic uint32, policy unsafe.Pointer, count uint32) int32
+TEXT runtime·vdsoCall_zx_job_set_policy(SB),NOSPLIT,$8-36
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), R14
+ PUSHQ R14
+ MOVQ 24(SP), DX
+ MOVQ DX, m_vdsoPC(R14)
+ LEAQ 24(SP), DX
+ MOVQ DX, m_vdsoSP(R14)
+ MOVL handle+0(FP), DI
+ MOVL options+4(FP), SI
+ MOVL topic+8(FP), DX
+ MOVQ policy+16(FP), CX
+ MOVL count+24(FP), R8
+ MOVQ vdso_zx_job_set_policy(SB), AX
+ CALL AX
+ MOVL AX, ret+32(FP)
+ POPQ R14
+ MOVQ $0, m_vdsoSP(R14)
+ RET
+
+// func vdsoCall_zx_task_bind_exception_port(handle uint32, port uint32, key uint64, options uint32) int32
+TEXT runtime·vdsoCall_zx_task_bind_exception_port(SB),NOSPLIT,$8-28
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), R14
+ PUSHQ R14
+ MOVQ 24(SP), DX
+ MOVQ DX, m_vdsoPC(R14)
+ LEAQ 24(SP), DX
+ MOVQ DX, m_vdsoSP(R14)
+ MOVL handle+0(FP), DI
+ MOVL port+4(FP), SI
+ MOVQ key+8(FP), DX
+ MOVL options+16(FP), CX
+ MOVQ vdso_zx_task_bind_exception_port(SB), AX
+ CALL AX
+ MOVL AX, ret+24(FP)
+ POPQ R14
+ MOVQ $0, m_vdsoSP(R14)
+ RET
+
+// func vdsoCall_zx_task_suspend(handle uint32, token unsafe.Pointer) int32
+TEXT runtime·vdsoCall_zx_task_suspend(SB),NOSPLIT,$8-20
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), R14
+ PUSHQ R14
+ MOVQ 24(SP), DX
+ MOVQ DX, m_vdsoPC(R14)
+ LEAQ 24(SP), DX
+ MOVQ DX, m_vdsoSP(R14)
+ MOVL handle+0(FP), DI
+ MOVQ token+8(FP), SI
+ MOVQ vdso_zx_task_suspend(SB), AX
+ CALL AX
+ MOVL AX, ret+16(FP)
+ POPQ R14
+ MOVQ $0, m_vdsoSP(R14)
+ RET
+
+// func vdsoCall_zx_task_suspend_token(handle uint32, token unsafe.Pointer) int32
+TEXT runtime·vdsoCall_zx_task_suspend_token(SB),NOSPLIT,$8-20
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), R14
+ PUSHQ R14
+ MOVQ 24(SP), DX
+ MOVQ DX, m_vdsoPC(R14)
+ LEAQ 24(SP), DX
+ MOVQ DX, m_vdsoSP(R14)
+ MOVL handle+0(FP), DI
+ MOVQ token+8(FP), SI
+ MOVQ vdso_zx_task_suspend_token(SB), AX
+ CALL AX
+ MOVL AX, ret+16(FP)
+ POPQ R14
+ MOVQ $0, m_vdsoSP(R14)
+ RET
+
+// func vdsoCall_zx_task_resume_from_exception(handle uint32, port uint32, options uint32) int32
+TEXT runtime·vdsoCall_zx_task_resume_from_exception(SB),NOSPLIT,$8-20
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), R14
+ PUSHQ R14
+ MOVQ 24(SP), DX
+ MOVQ DX, m_vdsoPC(R14)
+ LEAQ 24(SP), DX
+ MOVQ DX, m_vdsoSP(R14)
+ MOVL handle+0(FP), DI
+ MOVL port+4(FP), SI
+ MOVL options+8(FP), DX
+ MOVQ vdso_zx_task_resume_from_exception(SB), AX
+ CALL AX
+ MOVL AX, ret+16(FP)
+ POPQ R14
+ MOVQ $0, m_vdsoSP(R14)
+ RET
+
+// func vdsoCall_zx_task_kill(handle uint32) int32
+TEXT runtime·vdsoCall_zx_task_kill(SB),NOSPLIT,$8-12
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), R14
+ PUSHQ R14
+ MOVQ 24(SP), DX
+ MOVQ DX, m_vdsoPC(R14)
+ LEAQ 24(SP), DX
+ MOVQ DX, m_vdsoSP(R14)
+ MOVL handle+0(FP), DI
+ MOVQ vdso_zx_task_kill(SB), AX
+ CALL AX
+ MOVL AX, ret+8(FP)
+ POPQ R14
+ MOVQ $0, m_vdsoSP(R14)
+ RET
+
+// func vdsoCall_zx_event_create(options uint32, out unsafe.Pointer) int32
+TEXT runtime·vdsoCall_zx_event_create(SB),NOSPLIT,$8-20
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), R14
+ PUSHQ R14
+ MOVQ 24(SP), DX
+ MOVQ DX, m_vdsoPC(R14)
+ LEAQ 24(SP), DX
+ MOVQ DX, m_vdsoSP(R14)
+ MOVL options+0(FP), DI
+ MOVQ out+8(FP), SI
+ MOVQ vdso_zx_event_create(SB), AX
+ CALL AX
+ MOVL AX, ret+16(FP)
+ POPQ R14
+ MOVQ $0, m_vdsoSP(R14)
+ RET
+
+// func vdsoCall_zx_eventpair_create(options uint32, out0 unsafe.Pointer, out1 unsafe.Pointer) int32
+TEXT runtime·vdsoCall_zx_eventpair_create(SB),NOSPLIT,$8-28
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), R14
+ PUSHQ R14
+ MOVQ 24(SP), DX
+ MOVQ DX, m_vdsoPC(R14)
+ LEAQ 24(SP), DX
+ MOVQ DX, m_vdsoSP(R14)
+ MOVL options+0(FP), DI
+ MOVQ out0+8(FP), SI
+ MOVQ out1+16(FP), DX
+ MOVQ vdso_zx_eventpair_create(SB), AX
+ CALL AX
+ MOVL AX, ret+24(FP)
+ POPQ R14
+ MOVQ $0, m_vdsoSP(R14)
+ RET
+
+// func vdsoCall_zx_futex_wait(value_ptr unsafe.Pointer, current_value int32, new_futex_owner uint32, deadline int64) int32
+TEXT runtime·vdsoCall_zx_futex_wait(SB),NOSPLIT,$8-28
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), R14
+ PUSHQ R14
+ MOVQ 24(SP), DX
+ MOVQ DX, m_vdsoPC(R14)
+ LEAQ 24(SP), DX
+ MOVQ DX, m_vdsoSP(R14)
+ MOVQ value_ptr+0(FP), DI
+ MOVL current_value+8(FP), SI
+ MOVL new_futex_owner+12(FP), DX
+ MOVQ deadline+16(FP), CX
+ MOVQ vdso_zx_futex_wait(SB), AX
+ CALL AX
+ MOVL AX, ret+24(FP)
+ POPQ R14
+ MOVQ $0, m_vdsoSP(R14)
+ RET
+
+// func vdsoCall_zx_futex_wake(value_ptr unsafe.Pointer, wake_count uint32) int32
+TEXT runtime·vdsoCall_zx_futex_wake(SB),NOSPLIT,$8-20
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), R14
+ PUSHQ R14
+ MOVQ 24(SP), DX
+ MOVQ DX, m_vdsoPC(R14)
+ LEAQ 24(SP), DX
+ MOVQ DX, m_vdsoSP(R14)
+ MOVQ value_ptr+0(FP), DI
+ MOVL wake_count+8(FP), SI
+ MOVQ vdso_zx_futex_wake(SB), AX
+ CALL AX
+ MOVL AX, ret+16(FP)
+ POPQ R14
+ MOVQ $0, m_vdsoSP(R14)
+ RET
+
+// func vdsoCall_zx_futex_requeue(value_ptr unsafe.Pointer, wake_count uint32, current_value int32, requeue_ptr unsafe.Pointer, requeue_count uint32, new_requeue_owner uint32) int32
+TEXT runtime·vdsoCall_zx_futex_requeue(SB),NOSPLIT,$8-36
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), R14
+ PUSHQ R14
+ MOVQ 24(SP), DX
+ MOVQ DX, m_vdsoPC(R14)
+ LEAQ 24(SP), DX
+ MOVQ DX, m_vdsoSP(R14)
+ MOVQ value_ptr+0(FP), DI
+ MOVL wake_count+8(FP), SI
+ MOVL current_value+12(FP), DX
+ MOVQ requeue_ptr+16(FP), CX
+ MOVL requeue_count+24(FP), R8
+ MOVL new_requeue_owner+28(FP), R9
+ MOVQ vdso_zx_futex_requeue(SB), AX
+ CALL AX
+ MOVL AX, ret+32(FP)
+ POPQ R14
+ MOVQ $0, m_vdsoSP(R14)
+ RET
+
+// func vdsoCall_zx_futex_wake_single_owner(value_ptr unsafe.Pointer) int32
+TEXT runtime·vdsoCall_zx_futex_wake_single_owner(SB),NOSPLIT,$8-12
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), R14
+ PUSHQ R14
+ MOVQ 24(SP), DX
+ MOVQ DX, m_vdsoPC(R14)
+ LEAQ 24(SP), DX
+ MOVQ DX, m_vdsoSP(R14)
+ MOVQ value_ptr+0(FP), DI
+ MOVQ vdso_zx_futex_wake_single_owner(SB), AX
+ CALL AX
+ MOVL AX, ret+8(FP)
+ POPQ R14
+ MOVQ $0, m_vdsoSP(R14)
+ RET
+
+// func vdsoCall_zx_futex_requeue_single_owner(value_ptr unsafe.Pointer, current_value int32, requeue_ptr unsafe.Pointer, requeue_count uint32, new_requeue_owner uint32) int32
+TEXT runtime·vdsoCall_zx_futex_requeue_single_owner(SB),NOSPLIT,$8-36
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), R14
+ PUSHQ R14
+ MOVQ 24(SP), DX
+ MOVQ DX, m_vdsoPC(R14)
+ LEAQ 24(SP), DX
+ MOVQ DX, m_vdsoSP(R14)
+ MOVQ value_ptr+0(FP), DI
+ MOVL current_value+8(FP), SI
+ MOVQ requeue_ptr+16(FP), DX
+ MOVL requeue_count+24(FP), CX
+ MOVL new_requeue_owner+28(FP), R8
+ MOVQ vdso_zx_futex_requeue_single_owner(SB), AX
+ CALL AX
+ MOVL AX, ret+32(FP)
+ POPQ R14
+ MOVQ $0, m_vdsoSP(R14)
+ RET
+
+// func vdsoCall_zx_futex_get_owner(value_ptr unsafe.Pointer, koid unsafe.Pointer) int32
+TEXT runtime·vdsoCall_zx_futex_get_owner(SB),NOSPLIT,$8-20
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), R14
+ PUSHQ R14
+ MOVQ 24(SP), DX
+ MOVQ DX, m_vdsoPC(R14)
+ LEAQ 24(SP), DX
+ MOVQ DX, m_vdsoSP(R14)
+ MOVQ value_ptr+0(FP), DI
+ MOVQ koid+8(FP), SI
+ MOVQ vdso_zx_futex_get_owner(SB), AX
+ CALL AX
+ MOVL AX, ret+16(FP)
+ POPQ R14
+ MOVQ $0, m_vdsoSP(R14)
+ RET
+
+// func vdsoCall_zx_port_create(options uint32, out unsafe.Pointer) int32
+TEXT runtime·vdsoCall_zx_port_create(SB),NOSPLIT,$8-20
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), R14
+ PUSHQ R14
+ MOVQ 24(SP), DX
+ MOVQ DX, m_vdsoPC(R14)
+ LEAQ 24(SP), DX
+ MOVQ DX, m_vdsoSP(R14)
+ MOVL options+0(FP), DI
+ MOVQ out+8(FP), SI
+ MOVQ vdso_zx_port_create(SB), AX
+ CALL AX
+ MOVL AX, ret+16(FP)
+ POPQ R14
+ MOVQ $0, m_vdsoSP(R14)
+ RET
+
+// func vdsoCall_zx_port_queue(handle uint32, packet unsafe.Pointer) int32
+TEXT runtime·vdsoCall_zx_port_queue(SB),NOSPLIT,$8-20
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), R14
+ PUSHQ R14
+ MOVQ 24(SP), DX
+ MOVQ DX, m_vdsoPC(R14)
+ LEAQ 24(SP), DX
+ MOVQ DX, m_vdsoSP(R14)
+ MOVL handle+0(FP), DI
+ MOVQ packet+8(FP), SI
+ MOVQ vdso_zx_port_queue(SB), AX
+ CALL AX
+ MOVL AX, ret+16(FP)
+ POPQ R14
+ MOVQ $0, m_vdsoSP(R14)
+ RET
+
+// func vdsoCall_zx_port_wait(handle uint32, deadline int64, packet unsafe.Pointer) int32
+TEXT runtime·vdsoCall_zx_port_wait(SB),NOSPLIT,$8-28
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), R14
+ PUSHQ R14
+ MOVQ 24(SP), DX
+ MOVQ DX, m_vdsoPC(R14)
+ LEAQ 24(SP), DX
+ MOVQ DX, m_vdsoSP(R14)
+ CALL runtime·entersyscall(SB)
+ MOVL handle+0(FP), DI
+ MOVQ deadline+8(FP), SI
+ MOVQ packet+16(FP), DX
+ MOVQ vdso_zx_port_wait(SB), AX
+ CALL AX
+ MOVL AX, ret+24(FP)
+ CALL runtime·exitsyscall(SB)
+ POPQ R14
+ MOVQ $0, m_vdsoSP(R14)
+ RET
+
+// func vdsoCall_zx_port_cancel(handle uint32, source uint32, key uint64) int32
+TEXT runtime·vdsoCall_zx_port_cancel(SB),NOSPLIT,$8-20
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), R14
+ PUSHQ R14
+ MOVQ 24(SP), DX
+ MOVQ DX, m_vdsoPC(R14)
+ LEAQ 24(SP), DX
+ MOVQ DX, m_vdsoSP(R14)
+ MOVL handle+0(FP), DI
+ MOVL source+4(FP), SI
+ MOVQ key+8(FP), DX
+ MOVQ vdso_zx_port_cancel(SB), AX
+ CALL AX
+ MOVL AX, ret+16(FP)
+ POPQ R14
+ MOVQ $0, m_vdsoSP(R14)
+ RET
+
+// func vdsoCall_zx_timer_create(options uint32, clock_id uint32, out unsafe.Pointer) int32
+TEXT runtime·vdsoCall_zx_timer_create(SB),NOSPLIT,$8-20
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), R14
+ PUSHQ R14
+ MOVQ 24(SP), DX
+ MOVQ DX, m_vdsoPC(R14)
+ LEAQ 24(SP), DX
+ MOVQ DX, m_vdsoSP(R14)
+ MOVL options+0(FP), DI
+ MOVL clock_id+4(FP), SI
+ MOVQ out+8(FP), DX
+ MOVQ vdso_zx_timer_create(SB), AX
+ CALL AX
+ MOVL AX, ret+16(FP)
+ POPQ R14
+ MOVQ $0, m_vdsoSP(R14)
+ RET
+
+// func vdsoCall_zx_timer_set(handle uint32, deadline int64, slack int64) int32
+TEXT runtime·vdsoCall_zx_timer_set(SB),NOSPLIT,$8-28
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), R14
+ PUSHQ R14
+ MOVQ 24(SP), DX
+ MOVQ DX, m_vdsoPC(R14)
+ LEAQ 24(SP), DX
+ MOVQ DX, m_vdsoSP(R14)
+ MOVL handle+0(FP), DI
+ MOVQ deadline+8(FP), SI
+ MOVQ slack+16(FP), DX
+ MOVQ vdso_zx_timer_set(SB), AX
+ CALL AX
+ MOVL AX, ret+24(FP)
+ POPQ R14
+ MOVQ $0, m_vdsoSP(R14)
+ RET
+
+// func vdsoCall_zx_timer_cancel(handle uint32) int32
+TEXT runtime·vdsoCall_zx_timer_cancel(SB),NOSPLIT,$8-12
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), R14
+ PUSHQ R14
+ MOVQ 24(SP), DX
+ MOVQ DX, m_vdsoPC(R14)
+ LEAQ 24(SP), DX
+ MOVQ DX, m_vdsoSP(R14)
+ MOVL handle+0(FP), DI
+ MOVQ vdso_zx_timer_cancel(SB), AX
+ CALL AX
+ MOVL AX, ret+8(FP)
+ POPQ R14
+ MOVQ $0, m_vdsoSP(R14)
+ RET
+
+// func vdsoCall_zx_vmo_create(size uint64, options uint32, out unsafe.Pointer) int32
+TEXT runtime·vdsoCall_zx_vmo_create(SB),NOSPLIT,$8-28
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), R14
+ PUSHQ R14
+ MOVQ 24(SP), DX
+ MOVQ DX, m_vdsoPC(R14)
+ LEAQ 24(SP), DX
+ MOVQ DX, m_vdsoSP(R14)
+ MOVQ size+0(FP), DI
+ MOVL options+8(FP), SI
+ MOVQ out+16(FP), DX
+ MOVQ vdso_zx_vmo_create(SB), AX
+ CALL AX
+ MOVL AX, ret+24(FP)
+ POPQ R14
+ MOVQ $0, m_vdsoSP(R14)
+ RET
+
+// func vdsoCall_zx_vmo_read(handle uint32, buffer unsafe.Pointer, offset uint64, buffer_size uint) int32
+TEXT runtime·vdsoCall_zx_vmo_read(SB),NOSPLIT,$8-36
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), R14
+ PUSHQ R14
+ MOVQ 24(SP), DX
+ MOVQ DX, m_vdsoPC(R14)
+ LEAQ 24(SP), DX
+ MOVQ DX, m_vdsoSP(R14)
+ MOVL handle+0(FP), DI
+ MOVQ buffer+8(FP), SI
+ MOVQ offset+16(FP), DX
+ MOVQ buffer_size+24(FP), CX
+ MOVQ vdso_zx_vmo_read(SB), AX
+ CALL AX
+ MOVL AX, ret+32(FP)
+ POPQ R14
+ MOVQ $0, m_vdsoSP(R14)
+ RET
+
+// func vdsoCall_zx_vmo_write(handle uint32, buffer unsafe.Pointer, offset uint64, buffer_size uint) int32
+TEXT runtime·vdsoCall_zx_vmo_write(SB),NOSPLIT,$8-36
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), R14
+ PUSHQ R14
+ MOVQ 24(SP), DX
+ MOVQ DX, m_vdsoPC(R14)
+ LEAQ 24(SP), DX
+ MOVQ DX, m_vdsoSP(R14)
+ MOVL handle+0(FP), DI
+ MOVQ buffer+8(FP), SI
+ MOVQ offset+16(FP), DX
+ MOVQ buffer_size+24(FP), CX
+ MOVQ vdso_zx_vmo_write(SB), AX
+ CALL AX
+ MOVL AX, ret+32(FP)
+ POPQ R14
+ MOVQ $0, m_vdsoSP(R14)
+ RET
+
+// func vdsoCall_zx_vmo_get_size(handle uint32, size unsafe.Pointer) int32
+TEXT runtime·vdsoCall_zx_vmo_get_size(SB),NOSPLIT,$8-20
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), R14
+ PUSHQ R14
+ MOVQ 24(SP), DX
+ MOVQ DX, m_vdsoPC(R14)
+ LEAQ 24(SP), DX
+ MOVQ DX, m_vdsoSP(R14)
+ MOVL handle+0(FP), DI
+ MOVQ size+8(FP), SI
+ MOVQ vdso_zx_vmo_get_size(SB), AX
+ CALL AX
+ MOVL AX, ret+16(FP)
+ POPQ R14
+ MOVQ $0, m_vdsoSP(R14)
+ RET
+
+// func vdsoCall_zx_vmo_set_size(handle uint32, size uint64) int32
+TEXT runtime·vdsoCall_zx_vmo_set_size(SB),NOSPLIT,$8-20
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), R14
+ PUSHQ R14
+ MOVQ 24(SP), DX
+ MOVQ DX, m_vdsoPC(R14)
+ LEAQ 24(SP), DX
+ MOVQ DX, m_vdsoSP(R14)
+ MOVL handle+0(FP), DI
+ MOVQ size+8(FP), SI
+ MOVQ vdso_zx_vmo_set_size(SB), AX
+ CALL AX
+ MOVL AX, ret+16(FP)
+ POPQ R14
+ MOVQ $0, m_vdsoSP(R14)
+ RET
+
+// func vdsoCall_zx_vmo_op_range(handle uint32, op uint32, offset uint64, size uint64, buffer unsafe.Pointer, buffer_size uint) int32
+TEXT runtime·vdsoCall_zx_vmo_op_range(SB),NOSPLIT,$8-44
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), R14
+ PUSHQ R14
+ MOVQ 24(SP), DX
+ MOVQ DX, m_vdsoPC(R14)
+ LEAQ 24(SP), DX
+ MOVQ DX, m_vdsoSP(R14)
+ MOVL handle+0(FP), DI
+ MOVL op+4(FP), SI
+ MOVQ offset+8(FP), DX
+ MOVQ size+16(FP), CX
+ MOVQ buffer+24(FP), R8
+ MOVQ buffer_size+32(FP), R9
+ MOVQ vdso_zx_vmo_op_range(SB), AX
+ CALL AX
+ MOVL AX, ret+40(FP)
+ POPQ R14
+ MOVQ $0, m_vdsoSP(R14)
+ RET
+
+// func vdsoCall_zx_vmo_create_child(handle uint32, options uint32, offset uint64, size uint64, out unsafe.Pointer) int32
+TEXT runtime·vdsoCall_zx_vmo_create_child(SB),NOSPLIT,$8-36
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), R14
+ PUSHQ R14
+ MOVQ 24(SP), DX
+ MOVQ DX, m_vdsoPC(R14)
+ LEAQ 24(SP), DX
+ MOVQ DX, m_vdsoSP(R14)
+ MOVL handle+0(FP), DI
+ MOVL options+4(FP), SI
+ MOVQ offset+8(FP), DX
+ MOVQ size+16(FP), CX
+ MOVQ out+24(FP), R8
+ MOVQ vdso_zx_vmo_create_child(SB), AX
+ CALL AX
+ MOVL AX, ret+32(FP)
+ POPQ R14
+ MOVQ $0, m_vdsoSP(R14)
+ RET
+
+// func vdsoCall_zx_vmo_set_cache_policy(handle uint32, cache_policy uint32) int32
+TEXT runtime·vdsoCall_zx_vmo_set_cache_policy(SB),NOSPLIT,$8-12
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), R14
+ PUSHQ R14
+ MOVQ 24(SP), DX
+ MOVQ DX, m_vdsoPC(R14)
+ LEAQ 24(SP), DX
+ MOVQ DX, m_vdsoSP(R14)
+ MOVL handle+0(FP), DI
+ MOVL cache_policy+4(FP), SI
+ MOVQ vdso_zx_vmo_set_cache_policy(SB), AX
+ CALL AX
+ MOVL AX, ret+8(FP)
+ POPQ R14
+ MOVQ $0, m_vdsoSP(R14)
+ RET
+
+// func vdsoCall_zx_vmo_replace_as_executable(handle uint32, vmex uint32, out unsafe.Pointer) int32
+TEXT runtime·vdsoCall_zx_vmo_replace_as_executable(SB),NOSPLIT,$8-20
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), R14
+ PUSHQ R14
+ MOVQ 24(SP), DX
+ MOVQ DX, m_vdsoPC(R14)
+ LEAQ 24(SP), DX
+ MOVQ DX, m_vdsoSP(R14)
+ MOVL handle+0(FP), DI
+ MOVL vmex+4(FP), SI
+ MOVQ out+8(FP), DX
+ MOVQ vdso_zx_vmo_replace_as_executable(SB), AX
+ CALL AX
+ MOVL AX, ret+16(FP)
+ POPQ R14
+ MOVQ $0, m_vdsoSP(R14)
+ RET
+
+// func vdsoCall_zx_vmar_allocate(parent_vmar uint32, options uint32, offset uint64, size uint64, child_vmar unsafe.Pointer, child_addr unsafe.Pointer) int32
+TEXT runtime·vdsoCall_zx_vmar_allocate(SB),NOSPLIT,$8-44
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), R14
+ PUSHQ R14
+ MOVQ 24(SP), DX
+ MOVQ DX, m_vdsoPC(R14)
+ LEAQ 24(SP), DX
+ MOVQ DX, m_vdsoSP(R14)
+ MOVL parent_vmar+0(FP), DI
+ MOVL options+4(FP), SI
+ MOVQ offset+8(FP), DX
+ MOVQ size+16(FP), CX
+ MOVQ child_vmar+24(FP), R8
+ MOVQ child_addr+32(FP), R9
+ MOVQ vdso_zx_vmar_allocate(SB), AX
+ CALL AX
+ MOVL AX, ret+40(FP)
+ POPQ R14
+ MOVQ $0, m_vdsoSP(R14)
+ RET
+
+// func vdsoCall_zx_vmar_destroy(handle uint32) int32
+TEXT runtime·vdsoCall_zx_vmar_destroy(SB),NOSPLIT,$8-12
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), R14
+ PUSHQ R14
+ MOVQ 24(SP), DX
+ MOVQ DX, m_vdsoPC(R14)
+ LEAQ 24(SP), DX
+ MOVQ DX, m_vdsoSP(R14)
+ MOVL handle+0(FP), DI
+ MOVQ vdso_zx_vmar_destroy(SB), AX
+ CALL AX
+ MOVL AX, ret+8(FP)
+ POPQ R14
+ MOVQ $0, m_vdsoSP(R14)
+ RET
+
+// func vdsoCall_zx_vmar_map(handle uint32, options uint32, vmar_offset uint64, vmo uint32, vmo_offset uint64, len uint64, mapped_addr unsafe.Pointer) int32
+TEXT runtime·vdsoCall_zx_vmar_map(SB),NOSPLIT,$32-52
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), R14
+ PUSHQ R14
+ MOVQ 48(SP), DX
+ MOVQ DX, m_vdsoPC(R14)
+ LEAQ 48(SP), DX
+ MOVQ DX, m_vdsoSP(R14)
+ MOVL handle+0(FP), DI
+ MOVL options+4(FP), SI
+ MOVQ vmar_offset+8(FP), DX
+ MOVL vmo+16(FP), CX
+ MOVQ vmo_offset+24(FP), R8
+ MOVQ len+32(FP), R9
+ MOVQ mapped_addr+40(FP), R12
+ MOVQ SP, BP // BP is preserved across vsdo call by the x86-64 ABI
+ ANDQ $~15, SP // stack alignment for x86-64 ABI
+ PUSHQ R12
+ MOVQ vdso_zx_vmar_map(SB), AX
+ CALL AX
+ POPQ R12
+ MOVQ BP, SP
+ MOVL AX, ret+48(FP)
+ POPQ R14
+ MOVQ $0, m_vdsoSP(R14)
+ RET
+
+// func vdsoCall_zx_vmar_unmap(handle uint32, addr uintptr, len uint64) int32
+TEXT runtime·vdsoCall_zx_vmar_unmap(SB),NOSPLIT,$8-28
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), R14
+ PUSHQ R14
+ MOVQ 24(SP), DX
+ MOVQ DX, m_vdsoPC(R14)
+ LEAQ 24(SP), DX
+ MOVQ DX, m_vdsoSP(R14)
+ MOVL handle+0(FP), DI
+ MOVQ addr+8(FP), SI
+ MOVQ len+16(FP), DX
+ MOVQ vdso_zx_vmar_unmap(SB), AX
+ CALL AX
+ MOVL AX, ret+24(FP)
+ POPQ R14
+ MOVQ $0, m_vdsoSP(R14)
+ RET
+
+// func vdsoCall_zx_vmar_protect(handle uint32, options uint32, addr uintptr, len uint64) int32
+TEXT runtime·vdsoCall_zx_vmar_protect(SB),NOSPLIT,$8-28
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), R14
+ PUSHQ R14
+ MOVQ 24(SP), DX
+ MOVQ DX, m_vdsoPC(R14)
+ LEAQ 24(SP), DX
+ MOVQ DX, m_vdsoSP(R14)
+ MOVL handle+0(FP), DI
+ MOVL options+4(FP), SI
+ MOVQ addr+8(FP), DX
+ MOVQ len+16(FP), CX
+ MOVQ vdso_zx_vmar_protect(SB), AX
+ CALL AX
+ MOVL AX, ret+24(FP)
+ POPQ R14
+ MOVQ $0, m_vdsoSP(R14)
+ RET
+
+// func vdsoCall_zx_cprng_draw_once(buffer unsafe.Pointer, buffer_size uint) int32
+TEXT runtime·vdsoCall_zx_cprng_draw_once(SB),NOSPLIT,$8-20
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), R14
+ PUSHQ R14
+ MOVQ 24(SP), DX
+ MOVQ DX, m_vdsoPC(R14)
+ LEAQ 24(SP), DX
+ MOVQ DX, m_vdsoSP(R14)
+ MOVQ buffer+0(FP), DI
+ MOVQ buffer_size+8(FP), SI
+ MOVQ vdso_zx_cprng_draw_once(SB), AX
+ CALL AX
+ MOVL AX, ret+16(FP)
+ POPQ R14
+ MOVQ $0, m_vdsoSP(R14)
+ RET
+
+// func vdsoCall_zx_cprng_draw(buffer unsafe.Pointer, buffer_size uint)
+TEXT runtime·vdsoCall_zx_cprng_draw(SB),NOSPLIT,$8-16
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), R14
+ PUSHQ R14
+ MOVQ 24(SP), DX
+ MOVQ DX, m_vdsoPC(R14)
+ LEAQ 24(SP), DX
+ MOVQ DX, m_vdsoSP(R14)
+ MOVQ buffer+0(FP), DI
+ MOVQ buffer_size+8(FP), SI
+ MOVQ vdso_zx_cprng_draw(SB), AX
+ CALL AX
+ POPQ R14
+ MOVQ $0, m_vdsoSP(R14)
+ RET
+
+// func vdsoCall_zx_cprng_add_entropy(buffer unsafe.Pointer, buffer_size uint) int32
+TEXT runtime·vdsoCall_zx_cprng_add_entropy(SB),NOSPLIT,$8-20
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), R14
+ PUSHQ R14
+ MOVQ 24(SP), DX
+ MOVQ DX, m_vdsoPC(R14)
+ LEAQ 24(SP), DX
+ MOVQ DX, m_vdsoSP(R14)
+ MOVQ buffer+0(FP), DI
+ MOVQ buffer_size+8(FP), SI
+ MOVQ vdso_zx_cprng_add_entropy(SB), AX
+ CALL AX
+ MOVL AX, ret+16(FP)
+ POPQ R14
+ MOVQ $0, m_vdsoSP(R14)
+ RET
+
+// func vdsoCall_zx_fifo_create(elem_count uint, elem_size uint, options uint32, out0 unsafe.Pointer, out1 unsafe.Pointer) int32
+TEXT runtime·vdsoCall_zx_fifo_create(SB),NOSPLIT,$8-44
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), R14
+ PUSHQ R14
+ MOVQ 24(SP), DX
+ MOVQ DX, m_vdsoPC(R14)
+ LEAQ 24(SP), DX
+ MOVQ DX, m_vdsoSP(R14)
+ MOVQ elem_count+0(FP), DI
+ MOVQ elem_size+8(FP), SI
+ MOVL options+16(FP), DX
+ MOVQ out0+24(FP), CX
+ MOVQ out1+32(FP), R8
+ MOVQ vdso_zx_fifo_create(SB), AX
+ CALL AX
+ MOVL AX, ret+40(FP)
+ POPQ R14
+ MOVQ $0, m_vdsoSP(R14)
+ RET
+
+// func vdsoCall_zx_fifo_read(handle uint32, elem_size uint, data unsafe.Pointer, count uint, actual_count unsafe.Pointer) int32
+TEXT runtime·vdsoCall_zx_fifo_read(SB),NOSPLIT,$8-44
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), R14
+ PUSHQ R14
+ MOVQ 24(SP), DX
+ MOVQ DX, m_vdsoPC(R14)
+ LEAQ 24(SP), DX
+ MOVQ DX, m_vdsoSP(R14)
+ MOVL handle+0(FP), DI
+ MOVQ elem_size+8(FP), SI
+ MOVQ data+16(FP), DX
+ MOVQ count+24(FP), CX
+ MOVQ actual_count+32(FP), R8
+ MOVQ vdso_zx_fifo_read(SB), AX
+ CALL AX
+ MOVL AX, ret+40(FP)
+ POPQ R14
+ MOVQ $0, m_vdsoSP(R14)
+ RET
+
+// func vdsoCall_zx_fifo_write(handle uint32, elem_size uint, data unsafe.Pointer, count uint, actual_count unsafe.Pointer) int32
+TEXT runtime·vdsoCall_zx_fifo_write(SB),NOSPLIT,$8-44
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), R14
+ PUSHQ R14
+ MOVQ 24(SP), DX
+ MOVQ DX, m_vdsoPC(R14)
+ LEAQ 24(SP), DX
+ MOVQ DX, m_vdsoSP(R14)
+ MOVL handle+0(FP), DI
+ MOVQ elem_size+8(FP), SI
+ MOVQ data+16(FP), DX
+ MOVQ count+24(FP), CX
+ MOVQ actual_count+32(FP), R8
+ MOVQ vdso_zx_fifo_write(SB), AX
+ CALL AX
+ MOVL AX, ret+40(FP)
+ POPQ R14
+ MOVQ $0, m_vdsoSP(R14)
+ RET
+
+// func vdsoCall_zx_profile_create(root_job uint32, profile unsafe.Pointer, out unsafe.Pointer) int32
+TEXT runtime·vdsoCall_zx_profile_create(SB),NOSPLIT,$8-28
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), R14
+ PUSHQ R14
+ MOVQ 24(SP), DX
+ MOVQ DX, m_vdsoPC(R14)
+ LEAQ 24(SP), DX
+ MOVQ DX, m_vdsoSP(R14)
+ MOVL root_job+0(FP), DI
+ MOVQ profile+8(FP), SI
+ MOVQ out+16(FP), DX
+ MOVQ vdso_zx_profile_create(SB), AX
+ CALL AX
+ MOVL AX, ret+24(FP)
+ POPQ R14
+ MOVQ $0, m_vdsoSP(R14)
+ RET
+
+// func vdsoCall_zx_vmar_unmap_handle_close_thread_exit(vmar_handle uint32, addr uintptr, size uint, close_handle uint32) int32
+TEXT runtime·vdsoCall_zx_vmar_unmap_handle_close_thread_exit(SB),NOSPLIT,$8-36
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), R14
+ PUSHQ R14
+ MOVQ 24(SP), DX
+ MOVQ DX, m_vdsoPC(R14)
+ LEAQ 24(SP), DX
+ MOVQ DX, m_vdsoSP(R14)
+ MOVL vmar_handle+0(FP), DI
+ MOVQ addr+8(FP), SI
+ MOVQ size+16(FP), DX
+ MOVL close_handle+24(FP), CX
+ MOVQ vdso_zx_vmar_unmap_handle_close_thread_exit(SB), AX
+ CALL AX
+ MOVL AX, ret+32(FP)
+ POPQ R14
+ MOVQ $0, m_vdsoSP(R14)
+ RET
+
+// func vdsoCall_zx_futex_wake_handle_close_thread_exit(value_ptr unsafe.Pointer, wake_count uint32, new_value int32, close_handle uint32)
+TEXT runtime·vdsoCall_zx_futex_wake_handle_close_thread_exit(SB),NOSPLIT,$8-24
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), R14
+ PUSHQ R14
+ MOVQ 24(SP), DX
+ MOVQ DX, m_vdsoPC(R14)
+ LEAQ 24(SP), DX
+ MOVQ DX, m_vdsoSP(R14)
+ MOVQ value_ptr+0(FP), DI
+ MOVL wake_count+8(FP), SI
+ MOVL new_value+12(FP), DX
+ MOVL close_handle+16(FP), CX
+ MOVQ vdso_zx_futex_wake_handle_close_thread_exit(SB), AX
+ CALL AX
+ POPQ R14
+ MOVQ $0, m_vdsoSP(R14)
+ RET
+
+// func vdsoCall_zx_debuglog_create(resource uint32, options uint32, out unsafe.Pointer) int32
+TEXT runtime·vdsoCall_zx_debuglog_create(SB),NOSPLIT,$8-20
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), R14
+ PUSHQ R14
+ MOVQ 24(SP), DX
+ MOVQ DX, m_vdsoPC(R14)
+ LEAQ 24(SP), DX
+ MOVQ DX, m_vdsoSP(R14)
+ MOVL resource+0(FP), DI
+ MOVL options+4(FP), SI
+ MOVQ out+8(FP), DX
+ MOVQ vdso_zx_debuglog_create(SB), AX
+ CALL AX
+ MOVL AX, ret+16(FP)
+ POPQ R14
+ MOVQ $0, m_vdsoSP(R14)
+ RET
+
+// func vdsoCall_zx_debuglog_write(handle uint32, options uint32, buffer unsafe.Pointer, buffer_size uint) int32
+TEXT runtime·vdsoCall_zx_debuglog_write(SB),NOSPLIT,$8-28
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), R14
+ PUSHQ R14
+ MOVQ 24(SP), DX
+ MOVQ DX, m_vdsoPC(R14)
+ LEAQ 24(SP), DX
+ MOVQ DX, m_vdsoSP(R14)
+ MOVL handle+0(FP), DI
+ MOVL options+4(FP), SI
+ MOVQ buffer+8(FP), DX
+ MOVQ buffer_size+16(FP), CX
+ MOVQ vdso_zx_debuglog_write(SB), AX
+ CALL AX
+ MOVL AX, ret+24(FP)
+ POPQ R14
+ MOVQ $0, m_vdsoSP(R14)
+ RET
+
+// func vdsoCall_zx_debuglog_read(handle uint32, options uint32, buffer unsafe.Pointer, buffer_size uint) int32
+TEXT runtime·vdsoCall_zx_debuglog_read(SB),NOSPLIT,$8-28
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), R14
+ PUSHQ R14
+ MOVQ 24(SP), DX
+ MOVQ DX, m_vdsoPC(R14)
+ LEAQ 24(SP), DX
+ MOVQ DX, m_vdsoSP(R14)
+ MOVL handle+0(FP), DI
+ MOVL options+4(FP), SI
+ MOVQ buffer+8(FP), DX
+ MOVQ buffer_size+16(FP), CX
+ MOVQ vdso_zx_debuglog_read(SB), AX
+ CALL AX
+ MOVL AX, ret+24(FP)
+ POPQ R14
+ MOVQ $0, m_vdsoSP(R14)
+ RET
+
+// func vdsoCall_zx_ktrace_read(handle uint32, data unsafe.Pointer, offset uint32, data_size uint, actual unsafe.Pointer) int32
+TEXT runtime·vdsoCall_zx_ktrace_read(SB),NOSPLIT,$8-44
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), R14
+ PUSHQ R14
+ MOVQ 24(SP), DX
+ MOVQ DX, m_vdsoPC(R14)
+ LEAQ 24(SP), DX
+ MOVQ DX, m_vdsoSP(R14)
+ MOVL handle+0(FP), DI
+ MOVQ data+8(FP), SI
+ MOVL offset+16(FP), DX
+ MOVQ data_size+24(FP), CX
+ MOVQ actual+32(FP), R8
+ MOVQ vdso_zx_ktrace_read(SB), AX
+ CALL AX
+ MOVL AX, ret+40(FP)
+ POPQ R14
+ MOVQ $0, m_vdsoSP(R14)
+ RET
+
+// func vdsoCall_zx_ktrace_control(handle uint32, action uint32, options uint32, ptr unsafe.Pointer) int32
+TEXT runtime·vdsoCall_zx_ktrace_control(SB),NOSPLIT,$8-28
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), R14
+ PUSHQ R14
+ MOVQ 24(SP), DX
+ MOVQ DX, m_vdsoPC(R14)
+ LEAQ 24(SP), DX
+ MOVQ DX, m_vdsoSP(R14)
+ MOVL handle+0(FP), DI
+ MOVL action+4(FP), SI
+ MOVL options+8(FP), DX
+ MOVQ ptr+16(FP), CX
+ MOVQ vdso_zx_ktrace_control(SB), AX
+ CALL AX
+ MOVL AX, ret+24(FP)
+ POPQ R14
+ MOVQ $0, m_vdsoSP(R14)
+ RET
+
+// func vdsoCall_zx_ktrace_write(handle uint32, id uint32, arg0 uint32, arg1 uint32) int32
+TEXT runtime·vdsoCall_zx_ktrace_write(SB),NOSPLIT,$8-20
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), R14
+ PUSHQ R14
+ MOVQ 24(SP), DX
+ MOVQ DX, m_vdsoPC(R14)
+ LEAQ 24(SP), DX
+ MOVQ DX, m_vdsoSP(R14)
+ MOVL handle+0(FP), DI
+ MOVL id+4(FP), SI
+ MOVL arg0+8(FP), DX
+ MOVL arg1+12(FP), CX
+ MOVQ vdso_zx_ktrace_write(SB), AX
+ CALL AX
+ MOVL AX, ret+16(FP)
+ POPQ R14
+ MOVQ $0, m_vdsoSP(R14)
+ RET
+
+// func vdsoCall_zx_mtrace_control(handle uint32, kind uint32, action uint32, options uint32, ptr unsafe.Pointer, ptr_size uint) int32
+TEXT runtime·vdsoCall_zx_mtrace_control(SB),NOSPLIT,$8-36
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), R14
+ PUSHQ R14
+ MOVQ 24(SP), DX
+ MOVQ DX, m_vdsoPC(R14)
+ LEAQ 24(SP), DX
+ MOVQ DX, m_vdsoSP(R14)
+ MOVL handle+0(FP), DI
+ MOVL kind+4(FP), SI
+ MOVL action+8(FP), DX
+ MOVL options+12(FP), CX
+ MOVQ ptr+16(FP), R8
+ MOVQ ptr_size+24(FP), R9
+ MOVQ vdso_zx_mtrace_control(SB), AX
+ CALL AX
+ MOVL AX, ret+32(FP)
+ POPQ R14
+ MOVQ $0, m_vdsoSP(R14)
+ RET
+
+// func vdsoCall_zx_debug_read(handle uint32, buffer unsafe.Pointer, buffer_size unsafe.Pointer) int32
+TEXT runtime·vdsoCall_zx_debug_read(SB),NOSPLIT,$8-28
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), R14
+ PUSHQ R14
+ MOVQ 24(SP), DX
+ MOVQ DX, m_vdsoPC(R14)
+ LEAQ 24(SP), DX
+ MOVQ DX, m_vdsoSP(R14)
+ MOVL handle+0(FP), DI
+ MOVQ buffer+8(FP), SI
+ MOVQ buffer_size+16(FP), DX
+ MOVQ vdso_zx_debug_read(SB), AX
+ CALL AX
+ MOVL AX, ret+24(FP)
+ POPQ R14
+ MOVQ $0, m_vdsoSP(R14)
+ RET
+
+// func vdsoCall_zx_debug_write(buffer unsafe.Pointer, buffer_size uint) int32
+TEXT runtime·vdsoCall_zx_debug_write(SB),NOSPLIT,$8-20
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), R14
+ PUSHQ R14
+ MOVQ 24(SP), DX
+ MOVQ DX, m_vdsoPC(R14)
+ LEAQ 24(SP), DX
+ MOVQ DX, m_vdsoSP(R14)
+ MOVQ buffer+0(FP), DI
+ MOVQ buffer_size+8(FP), SI
+ MOVQ vdso_zx_debug_write(SB), AX
+ CALL AX
+ MOVL AX, ret+16(FP)
+ POPQ R14
+ MOVQ $0, m_vdsoSP(R14)
+ RET
+
+// func vdsoCall_zx_debug_send_command(resource uint32, buffer unsafe.Pointer, buffer_size uint) int32
+TEXT runtime·vdsoCall_zx_debug_send_command(SB),NOSPLIT,$8-28
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), R14
+ PUSHQ R14
+ MOVQ 24(SP), DX
+ MOVQ DX, m_vdsoPC(R14)
+ LEAQ 24(SP), DX
+ MOVQ DX, m_vdsoSP(R14)
+ MOVL resource+0(FP), DI
+ MOVQ buffer+8(FP), SI
+ MOVQ buffer_size+16(FP), DX
+ MOVQ vdso_zx_debug_send_command(SB), AX
+ CALL AX
+ MOVL AX, ret+24(FP)
+ POPQ R14
+ MOVQ $0, m_vdsoSP(R14)
+ RET
+
+// func vdsoCall_zx_interrupt_create(src_obj uint32, src_num uint32, options uint32, out_handle unsafe.Pointer) int32
+TEXT runtime·vdsoCall_zx_interrupt_create(SB),NOSPLIT,$8-28
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), R14
+ PUSHQ R14
+ MOVQ 24(SP), DX
+ MOVQ DX, m_vdsoPC(R14)
+ LEAQ 24(SP), DX
+ MOVQ DX, m_vdsoSP(R14)
+ MOVL src_obj+0(FP), DI
+ MOVL src_num+4(FP), SI
+ MOVL options+8(FP), DX
+ MOVQ out_handle+16(FP), CX
+ MOVQ vdso_zx_interrupt_create(SB), AX
+ CALL AX
+ MOVL AX, ret+24(FP)
+ POPQ R14
+ MOVQ $0, m_vdsoSP(R14)
+ RET
+
+// func vdsoCall_zx_interrupt_bind(handle uint32, port_handle uint32, key uint64, options uint32) int32
+TEXT runtime·vdsoCall_zx_interrupt_bind(SB),NOSPLIT,$8-28
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), R14
+ PUSHQ R14
+ MOVQ 24(SP), DX
+ MOVQ DX, m_vdsoPC(R14)
+ LEAQ 24(SP), DX
+ MOVQ DX, m_vdsoSP(R14)
+ MOVL handle+0(FP), DI
+ MOVL port_handle+4(FP), SI
+ MOVQ key+8(FP), DX
+ MOVL options+16(FP), CX
+ MOVQ vdso_zx_interrupt_bind(SB), AX
+ CALL AX
+ MOVL AX, ret+24(FP)
+ POPQ R14
+ MOVQ $0, m_vdsoSP(R14)
+ RET
+
+// func vdsoCall_zx_interrupt_wait(handle uint32, out_timestamp unsafe.Pointer) int32
+TEXT runtime·vdsoCall_zx_interrupt_wait(SB),NOSPLIT,$8-20
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), R14
+ PUSHQ R14
+ MOVQ 24(SP), DX
+ MOVQ DX, m_vdsoPC(R14)
+ LEAQ 24(SP), DX
+ MOVQ DX, m_vdsoSP(R14)
+ MOVL handle+0(FP), DI
+ MOVQ out_timestamp+8(FP), SI
+ MOVQ vdso_zx_interrupt_wait(SB), AX
+ CALL AX
+ MOVL AX, ret+16(FP)
+ POPQ R14
+ MOVQ $0, m_vdsoSP(R14)
+ RET
+
+// func vdsoCall_zx_interrupt_destroy(handle uint32) int32
+TEXT runtime·vdsoCall_zx_interrupt_destroy(SB),NOSPLIT,$8-12
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), R14
+ PUSHQ R14
+ MOVQ 24(SP), DX
+ MOVQ DX, m_vdsoPC(R14)
+ LEAQ 24(SP), DX
+ MOVQ DX, m_vdsoSP(R14)
+ MOVL handle+0(FP), DI
+ MOVQ vdso_zx_interrupt_destroy(SB), AX
+ CALL AX
+ MOVL AX, ret+8(FP)
+ POPQ R14
+ MOVQ $0, m_vdsoSP(R14)
+ RET
+
+// func vdsoCall_zx_interrupt_ack(handle uint32) int32
+TEXT runtime·vdsoCall_zx_interrupt_ack(SB),NOSPLIT,$8-12
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), R14
+ PUSHQ R14
+ MOVQ 24(SP), DX
+ MOVQ DX, m_vdsoPC(R14)
+ LEAQ 24(SP), DX
+ MOVQ DX, m_vdsoSP(R14)
+ MOVL handle+0(FP), DI
+ MOVQ vdso_zx_interrupt_ack(SB), AX
+ CALL AX
+ MOVL AX, ret+8(FP)
+ POPQ R14
+ MOVQ $0, m_vdsoSP(R14)
+ RET
+
+// func vdsoCall_zx_interrupt_trigger(handle uint32, options uint32, timestamp int64) int32
+TEXT runtime·vdsoCall_zx_interrupt_trigger(SB),NOSPLIT,$8-20
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), R14
+ PUSHQ R14
+ MOVQ 24(SP), DX
+ MOVQ DX, m_vdsoPC(R14)
+ LEAQ 24(SP), DX
+ MOVQ DX, m_vdsoSP(R14)
+ MOVL handle+0(FP), DI
+ MOVL options+4(FP), SI
+ MOVQ timestamp+8(FP), DX
+ MOVQ vdso_zx_interrupt_trigger(SB), AX
+ CALL AX
+ MOVL AX, ret+16(FP)
+ POPQ R14
+ MOVQ $0, m_vdsoSP(R14)
+ RET
+
+// func vdsoCall_zx_interrupt_bind_vcpu(handle uint32, vcpu uint32, options uint32) int32
+TEXT runtime·vdsoCall_zx_interrupt_bind_vcpu(SB),NOSPLIT,$8-20
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), R14
+ PUSHQ R14
+ MOVQ 24(SP), DX
+ MOVQ DX, m_vdsoPC(R14)
+ LEAQ 24(SP), DX
+ MOVQ DX, m_vdsoSP(R14)
+ MOVL handle+0(FP), DI
+ MOVL vcpu+4(FP), SI
+ MOVL options+8(FP), DX
+ MOVQ vdso_zx_interrupt_bind_vcpu(SB), AX
+ CALL AX
+ MOVL AX, ret+16(FP)
+ POPQ R14
+ MOVQ $0, m_vdsoSP(R14)
+ RET
+
+// func vdsoCall_zx_ioports_request(resource uint32, io_addr uint16, len uint32) int32
+TEXT runtime·vdsoCall_zx_ioports_request(SB),NOSPLIT,$8-20
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), R14
+ PUSHQ R14
+ MOVQ 24(SP), DX
+ MOVQ DX, m_vdsoPC(R14)
+ LEAQ 24(SP), DX
+ MOVQ DX, m_vdsoSP(R14)
+ MOVL resource+0(FP), DI
+ MOVQ io_addr+4(FP), SI
+ MOVL len+8(FP), DX
+ MOVQ vdso_zx_ioports_request(SB), AX
+ CALL AX
+ MOVL AX, ret+16(FP)
+ POPQ R14
+ MOVQ $0, m_vdsoSP(R14)
+ RET
+
+// func vdsoCall_zx_vmo_create_contiguous(bti uint32, size uint, alignment_log2 uint32, out unsafe.Pointer) int32
+TEXT runtime·vdsoCall_zx_vmo_create_contiguous(SB),NOSPLIT,$8-36
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), R14
+ PUSHQ R14
+ MOVQ 24(SP), DX
+ MOVQ DX, m_vdsoPC(R14)
+ LEAQ 24(SP), DX
+ MOVQ DX, m_vdsoSP(R14)
+ MOVL bti+0(FP), DI
+ MOVQ size+8(FP), SI
+ MOVL alignment_log2+16(FP), DX
+ MOVQ out+24(FP), CX
+ MOVQ vdso_zx_vmo_create_contiguous(SB), AX
+ CALL AX
+ MOVL AX, ret+32(FP)
+ POPQ R14
+ MOVQ $0, m_vdsoSP(R14)
+ RET
+
+// func vdsoCall_zx_vmo_create_physical(resource uint32, paddr uintptr, size uint, out unsafe.Pointer) int32
+TEXT runtime·vdsoCall_zx_vmo_create_physical(SB),NOSPLIT,$8-36
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), R14
+ PUSHQ R14
+ MOVQ 24(SP), DX
+ MOVQ DX, m_vdsoPC(R14)
+ LEAQ 24(SP), DX
+ MOVQ DX, m_vdsoSP(R14)
+ MOVL resource+0(FP), DI
+ MOVQ paddr+8(FP), SI
+ MOVQ size+16(FP), DX
+ MOVQ out+24(FP), CX
+ MOVQ vdso_zx_vmo_create_physical(SB), AX
+ CALL AX
+ MOVL AX, ret+32(FP)
+ POPQ R14
+ MOVQ $0, m_vdsoSP(R14)
+ RET
+
+// func vdsoCall_zx_iommu_create(resource uint32, typ uint32, desc unsafe.Pointer, desc_size uint, out unsafe.Pointer) int32
+TEXT runtime·vdsoCall_zx_iommu_create(SB),NOSPLIT,$8-36
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), R14
+ PUSHQ R14
+ MOVQ 24(SP), DX
+ MOVQ DX, m_vdsoPC(R14)
+ LEAQ 24(SP), DX
+ MOVQ DX, m_vdsoSP(R14)
+ MOVL resource+0(FP), DI
+ MOVL typ+4(FP), SI
+ MOVQ desc+8(FP), DX
+ MOVQ desc_size+16(FP), CX
+ MOVQ out+24(FP), R8
+ MOVQ vdso_zx_iommu_create(SB), AX
+ CALL AX
+ MOVL AX, ret+32(FP)
+ POPQ R14
+ MOVQ $0, m_vdsoSP(R14)
+ RET
+
+// func vdsoCall_zx_bti_create(iommu uint32, options uint32, bti_id uint64, out unsafe.Pointer) int32
+TEXT runtime·vdsoCall_zx_bti_create(SB),NOSPLIT,$8-28
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), R14
+ PUSHQ R14
+ MOVQ 24(SP), DX
+ MOVQ DX, m_vdsoPC(R14)
+ LEAQ 24(SP), DX
+ MOVQ DX, m_vdsoSP(R14)
+ MOVL iommu+0(FP), DI
+ MOVL options+4(FP), SI
+ MOVQ bti_id+8(FP), DX
+ MOVQ out+16(FP), CX
+ MOVQ vdso_zx_bti_create(SB), AX
+ CALL AX
+ MOVL AX, ret+24(FP)
+ POPQ R14
+ MOVQ $0, m_vdsoSP(R14)
+ RET
+
+// func vdsoCall_zx_bti_pin(handle uint32, options uint32, vmo uint32, offset uint64, size uint64, addrs unsafe.Pointer, addrs_count uint, pmt unsafe.Pointer) int32
+TEXT runtime·vdsoCall_zx_bti_pin(SB),NOSPLIT,$40-60
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), R14
+ PUSHQ R14
+ MOVQ 56(SP), DX
+ MOVQ DX, m_vdsoPC(R14)
+ LEAQ 56(SP), DX
+ MOVQ DX, m_vdsoSP(R14)
+ MOVL handle+0(FP), DI
+ MOVL options+4(FP), SI
+ MOVL vmo+8(FP), DX
+ MOVQ offset+16(FP), CX
+ MOVQ size+24(FP), R8
+ MOVQ addrs+32(FP), R9
+ MOVQ addrs_count+40(FP), R12
+ MOVQ pmt+48(FP), R13
+ MOVQ SP, BP // BP is preserved across vsdo call by the x86-64 ABI
+ ANDQ $~15, SP // stack alignment for x86-64 ABI
+ PUSHQ R13
+ PUSHQ R12
+ MOVQ vdso_zx_bti_pin(SB), AX
+ CALL AX
+ POPQ R12
+ POPQ R13
+ MOVQ BP, SP
+ MOVL AX, ret+56(FP)
+ POPQ R14
+ MOVQ $0, m_vdsoSP(R14)
+ RET
+
+// func vdsoCall_zx_bti_release_quarantine(handle uint32) int32
+TEXT runtime·vdsoCall_zx_bti_release_quarantine(SB),NOSPLIT,$8-12
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), R14
+ PUSHQ R14
+ MOVQ 24(SP), DX
+ MOVQ DX, m_vdsoPC(R14)
+ LEAQ 24(SP), DX
+ MOVQ DX, m_vdsoSP(R14)
+ MOVL handle+0(FP), DI
+ MOVQ vdso_zx_bti_release_quarantine(SB), AX
+ CALL AX
+ MOVL AX, ret+8(FP)
+ POPQ R14
+ MOVQ $0, m_vdsoSP(R14)
+ RET
+
+// func vdsoCall_zx_pmt_unpin(handle uint32) int32
+TEXT runtime·vdsoCall_zx_pmt_unpin(SB),NOSPLIT,$8-12
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), R14
+ PUSHQ R14
+ MOVQ 24(SP), DX
+ MOVQ DX, m_vdsoPC(R14)
+ LEAQ 24(SP), DX
+ MOVQ DX, m_vdsoSP(R14)
+ MOVL handle+0(FP), DI
+ MOVQ vdso_zx_pmt_unpin(SB), AX
+ CALL AX
+ MOVL AX, ret+8(FP)
+ POPQ R14
+ MOVQ $0, m_vdsoSP(R14)
+ RET
+
+// func vdsoCall_zx_framebuffer_get_info(resource uint32, format unsafe.Pointer, width unsafe.Pointer, height unsafe.Pointer, stride unsafe.Pointer) int32
+TEXT runtime·vdsoCall_zx_framebuffer_get_info(SB),NOSPLIT,$8-44
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), R14
+ PUSHQ R14
+ MOVQ 24(SP), DX
+ MOVQ DX, m_vdsoPC(R14)
+ LEAQ 24(SP), DX
+ MOVQ DX, m_vdsoSP(R14)
+ MOVL resource+0(FP), DI
+ MOVQ format+8(FP), SI
+ MOVQ width+16(FP), DX
+ MOVQ height+24(FP), CX
+ MOVQ stride+32(FP), R8
+ MOVQ vdso_zx_framebuffer_get_info(SB), AX
+ CALL AX
+ MOVL AX, ret+40(FP)
+ POPQ R14
+ MOVQ $0, m_vdsoSP(R14)
+ RET
+
+// func vdsoCall_zx_framebuffer_set_range(resource uint32, vmo uint32, len uint32, format uint32, width uint32, height uint32, stride uint32) int32
+TEXT runtime·vdsoCall_zx_framebuffer_set_range(SB),NOSPLIT,$32-36
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), R14
+ PUSHQ R14
+ MOVQ 48(SP), DX
+ MOVQ DX, m_vdsoPC(R14)
+ LEAQ 48(SP), DX
+ MOVQ DX, m_vdsoSP(R14)
+ MOVL resource+0(FP), DI
+ MOVL vmo+4(FP), SI
+ MOVL len+8(FP), DX
+ MOVL format+12(FP), CX
+ MOVL width+16(FP), R8
+ MOVL height+20(FP), R9
+ MOVL stride+24(FP), R12
+ MOVQ SP, BP // BP is preserved across vsdo call by the x86-64 ABI
+ ANDQ $~15, SP // stack alignment for x86-64 ABI
+ PUSHQ R12
+ MOVQ vdso_zx_framebuffer_set_range(SB), AX
+ CALL AX
+ POPQ R12
+ MOVQ BP, SP
+ MOVL AX, ret+32(FP)
+ POPQ R14
+ MOVQ $0, m_vdsoSP(R14)
+ RET
+
+// func vdsoCall_zx_pc_firmware_tables(handle uint32, acpi_rsdp unsafe.Pointer, smbios unsafe.Pointer) int32
+TEXT runtime·vdsoCall_zx_pc_firmware_tables(SB),NOSPLIT,$8-28
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), R14
+ PUSHQ R14
+ MOVQ 24(SP), DX
+ MOVQ DX, m_vdsoPC(R14)
+ LEAQ 24(SP), DX
+ MOVQ DX, m_vdsoSP(R14)
+ MOVL handle+0(FP), DI
+ MOVQ acpi_rsdp+8(FP), SI
+ MOVQ smbios+16(FP), DX
+ MOVQ vdso_zx_pc_firmware_tables(SB), AX
+ CALL AX
+ MOVL AX, ret+24(FP)
+ POPQ R14
+ MOVQ $0, m_vdsoSP(R14)
+ RET
+
+// func vdsoCall_zx_smc_call(handle uint32, parameters unsafe.Pointer, out_smc_result unsafe.Pointer) int32
+TEXT runtime·vdsoCall_zx_smc_call(SB),NOSPLIT,$8-28
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), R14
+ PUSHQ R14
+ MOVQ 24(SP), DX
+ MOVQ DX, m_vdsoPC(R14)
+ LEAQ 24(SP), DX
+ MOVQ DX, m_vdsoSP(R14)
+ MOVL handle+0(FP), DI
+ MOVQ parameters+8(FP), SI
+ MOVQ out_smc_result+16(FP), DX
+ MOVQ vdso_zx_smc_call(SB), AX
+ CALL AX
+ MOVL AX, ret+24(FP)
+ POPQ R14
+ MOVQ $0, m_vdsoSP(R14)
+ RET
+
+// func vdsoCall_zx_resource_create(parent_rsrc uint32, options uint32, base uint64, size uint, name unsafe.Pointer, name_size uint, resource_out unsafe.Pointer) int32
+TEXT runtime·vdsoCall_zx_resource_create(SB),NOSPLIT,$32-52
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), R14
+ PUSHQ R14
+ MOVQ 48(SP), DX
+ MOVQ DX, m_vdsoPC(R14)
+ LEAQ 48(SP), DX
+ MOVQ DX, m_vdsoSP(R14)
+ MOVL parent_rsrc+0(FP), DI
+ MOVL options+4(FP), SI
+ MOVQ base+8(FP), DX
+ MOVQ size+16(FP), CX
+ MOVQ name+24(FP), R8
+ MOVQ name_size+32(FP), R9
+ MOVQ resource_out+40(FP), R12
+ MOVQ SP, BP // BP is preserved across vsdo call by the x86-64 ABI
+ ANDQ $~15, SP // stack alignment for x86-64 ABI
+ PUSHQ R12
+ MOVQ vdso_zx_resource_create(SB), AX
+ CALL AX
+ POPQ R12
+ MOVQ BP, SP
+ MOVL AX, ret+48(FP)
+ POPQ R14
+ MOVQ $0, m_vdsoSP(R14)
+ RET
+
+// func vdsoCall_zx_system_mexec(resource uint32, kernel_vmo uint32, bootimage_vmo uint32) int32
+TEXT runtime·vdsoCall_zx_system_mexec(SB),NOSPLIT,$8-20
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), R14
+ PUSHQ R14
+ MOVQ 24(SP), DX
+ MOVQ DX, m_vdsoPC(R14)
+ LEAQ 24(SP), DX
+ MOVQ DX, m_vdsoSP(R14)
+ MOVL resource+0(FP), DI
+ MOVL kernel_vmo+4(FP), SI
+ MOVL bootimage_vmo+8(FP), DX
+ MOVQ vdso_zx_system_mexec(SB), AX
+ CALL AX
+ MOVL AX, ret+16(FP)
+ POPQ R14
+ MOVQ $0, m_vdsoSP(R14)
+ RET
+
+// func vdsoCall_zx_system_mexec_payload_get(resource uint32, buffer unsafe.Pointer, buffer_size uint) int32
+TEXT runtime·vdsoCall_zx_system_mexec_payload_get(SB),NOSPLIT,$8-28
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), R14
+ PUSHQ R14
+ MOVQ 24(SP), DX
+ MOVQ DX, m_vdsoPC(R14)
+ LEAQ 24(SP), DX
+ MOVQ DX, m_vdsoSP(R14)
+ MOVL resource+0(FP), DI
+ MOVQ buffer+8(FP), SI
+ MOVQ buffer_size+16(FP), DX
+ MOVQ vdso_zx_system_mexec_payload_get(SB), AX
+ CALL AX
+ MOVL AX, ret+24(FP)
+ POPQ R14
+ MOVQ $0, m_vdsoSP(R14)
+ RET
+
+// func vdsoCall_zx_system_powerctl(resource uint32, cmd uint32, arg unsafe.Pointer) int32
+TEXT runtime·vdsoCall_zx_system_powerctl(SB),NOSPLIT,$8-20
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), R14
+ PUSHQ R14
+ MOVQ 24(SP), DX
+ MOVQ DX, m_vdsoPC(R14)
+ LEAQ 24(SP), DX
+ MOVQ DX, m_vdsoSP(R14)
+ MOVL resource+0(FP), DI
+ MOVL cmd+4(FP), SI
+ MOVQ arg+8(FP), DX
+ MOVQ vdso_zx_system_powerctl(SB), AX
+ CALL AX
+ MOVL AX, ret+16(FP)
+ POPQ R14
+ MOVQ $0, m_vdsoSP(R14)
+ RET
+
+// func vdsoCall_zx_pager_create(options uint32, out unsafe.Pointer) int32
+TEXT runtime·vdsoCall_zx_pager_create(SB),NOSPLIT,$8-20
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), R14
+ PUSHQ R14
+ MOVQ 24(SP), DX
+ MOVQ DX, m_vdsoPC(R14)
+ LEAQ 24(SP), DX
+ MOVQ DX, m_vdsoSP(R14)
+ MOVL options+0(FP), DI
+ MOVQ out+8(FP), SI
+ MOVQ vdso_zx_pager_create(SB), AX
+ CALL AX
+ MOVL AX, ret+16(FP)
+ POPQ R14
+ MOVQ $0, m_vdsoSP(R14)
+ RET
+
+// func vdsoCall_zx_pager_create_vmo(pager uint32, options uint32, port uint32, key uint64, size uint64, out unsafe.Pointer) int32
+TEXT runtime·vdsoCall_zx_pager_create_vmo(SB),NOSPLIT,$8-44
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), R14
+ PUSHQ R14
+ MOVQ 24(SP), DX
+ MOVQ DX, m_vdsoPC(R14)
+ LEAQ 24(SP), DX
+ MOVQ DX, m_vdsoSP(R14)
+ MOVL pager+0(FP), DI
+ MOVL options+4(FP), SI
+ MOVL port+8(FP), DX
+ MOVQ key+16(FP), CX
+ MOVQ size+24(FP), R8
+ MOVQ out+32(FP), R9
+ MOVQ vdso_zx_pager_create_vmo(SB), AX
+ CALL AX
+ MOVL AX, ret+40(FP)
+ POPQ R14
+ MOVQ $0, m_vdsoSP(R14)
+ RET
+
+// func vdsoCall_zx_pager_detach_vmo(pager uint32, vmo uint32) int32
+TEXT runtime·vdsoCall_zx_pager_detach_vmo(SB),NOSPLIT,$8-12
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), R14
+ PUSHQ R14
+ MOVQ 24(SP), DX
+ MOVQ DX, m_vdsoPC(R14)
+ LEAQ 24(SP), DX
+ MOVQ DX, m_vdsoSP(R14)
+ MOVL pager+0(FP), DI
+ MOVL vmo+4(FP), SI
+ MOVQ vdso_zx_pager_detach_vmo(SB), AX
+ CALL AX
+ MOVL AX, ret+8(FP)
+ POPQ R14
+ MOVQ $0, m_vdsoSP(R14)
+ RET
+
+// func vdsoCall_zx_pager_supply_pages(pager uint32, pager_vmo uint32, offset uint64, length uint64, aux_vmo uint32, aux_offset uint64) int32
+TEXT runtime·vdsoCall_zx_pager_supply_pages(SB),NOSPLIT,$8-44
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ get_tls(CX)
+ MOVQ g(CX), AX
+ MOVQ g_m(AX), R14
+ PUSHQ R14
+ MOVQ 24(SP), DX
+ MOVQ DX, m_vdsoPC(R14)
+ LEAQ 24(SP), DX
+ MOVQ DX, m_vdsoSP(R14)
+ MOVL pager+0(FP), DI
+ MOVL pager_vmo+4(FP), SI
+ MOVQ offset+8(FP), DX
+ MOVQ length+16(FP), CX
+ MOVL aux_vmo+24(FP), R8
+ MOVQ aux_offset+32(FP), R9
+ MOVQ vdso_zx_pager_supply_pages(SB), AX
+ CALL AX
+ MOVL AX, ret+40(FP)
+ POPQ R14
+ MOVQ $0, m_vdsoSP(R14)
+ RET
+
diff --git a/src/runtime/vdsocalls_fuchsia_arm64.s b/src/runtime/vdsocalls_fuchsia_arm64.s
new file mode 100644
index 0000000..2b8cd5e
--- /dev/null
+++ b/src/runtime/vdsocalls_fuchsia_arm64.s
@@ -0,0 +1,2324 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Zircon system calls for the Fuchsia OS.
+// Generated by mkfuchsia.go, do not edit.
+
+#include "go_asm.h"
+#include "go_tls.h"
+#include "textflag.h"
+#include "funcdata.h"
+
+// func vdsoCall_zx_clock_get(clock_id uint32) int64
+TEXT runtime·vdsoCall_zx_clock_get(SB),NOSPLIT,$0-16
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ MOVD g_m(g), R21
+ MOVD LR, m_vdsoPC(R21)
+ MOVD RSP, R20
+ MOVD R20, m_vdsoSP(R21)
+ MOVW clock_id+0(FP), R0
+ BL vdso_zx_clock_get(SB)
+ MOVD R0, ret+8(FP)
+ MOVD g_m(g), R21
+ MOVD $0, m_vdsoSP(R21)
+ RET
+
+// func vdsoCall_zx_clock_get_new(clock_id uint32, out unsafe.Pointer) int32
+TEXT runtime·vdsoCall_zx_clock_get_new(SB),NOSPLIT,$0-20
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ MOVD g_m(g), R21
+ MOVD LR, m_vdsoPC(R21)
+ MOVD RSP, R20
+ MOVD R20, m_vdsoSP(R21)
+ MOVW clock_id+0(FP), R0
+ MOVD out+8(FP), R1
+ BL vdso_zx_clock_get_new(SB)
+ MOVW R0, ret+16(FP)
+ MOVD g_m(g), R21
+ MOVD $0, m_vdsoSP(R21)
+ RET
+
+// func vdsoCall_zx_clock_get_monotonic() int64
+TEXT runtime·vdsoCall_zx_clock_get_monotonic(SB),NOSPLIT,$0-8
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ MOVD g_m(g), R21
+ MOVD LR, m_vdsoPC(R21)
+ MOVD RSP, R20
+ MOVD R20, m_vdsoSP(R21)
+ BL vdso_zx_clock_get_monotonic(SB)
+ MOVD R0, ret+0(FP)
+ MOVD g_m(g), R21
+ MOVD $0, m_vdsoSP(R21)
+ RET
+
+// func vdsoCall_zx_nanosleep(deadline int64) int32
+TEXT runtime·vdsoCall_zx_nanosleep(SB),NOSPLIT,$0-12
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ MOVD g_m(g), R21
+ MOVD LR, m_vdsoPC(R21)
+ MOVD RSP, R20
+ MOVD R20, m_vdsoSP(R21)
+ MOVD deadline+0(FP), R0
+ BL vdso_zx_nanosleep(SB)
+ MOVW R0, ret+8(FP)
+ MOVD g_m(g), R21
+ MOVD $0, m_vdsoSP(R21)
+ RET
+
+// func vdsoCall_zx_ticks_get() uint64
+TEXT runtime·vdsoCall_zx_ticks_get(SB),NOSPLIT,$0-8
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ MOVD g_m(g), R21
+ MOVD LR, m_vdsoPC(R21)
+ MOVD RSP, R20
+ MOVD R20, m_vdsoSP(R21)
+ BL vdso_zx_ticks_get(SB)
+ MOVD R0, ret+0(FP)
+ MOVD g_m(g), R21
+ MOVD $0, m_vdsoSP(R21)
+ RET
+
+// func vdsoCall_zx_ticks_per_second() uint64
+TEXT runtime·vdsoCall_zx_ticks_per_second(SB),NOSPLIT,$0-8
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ MOVD g_m(g), R21
+ MOVD LR, m_vdsoPC(R21)
+ MOVD RSP, R20
+ MOVD R20, m_vdsoSP(R21)
+ BL vdso_zx_ticks_per_second(SB)
+ MOVD R0, ret+0(FP)
+ MOVD g_m(g), R21
+ MOVD $0, m_vdsoSP(R21)
+ RET
+
+// func vdsoCall_zx_deadline_after(nanoseconds int64) int64
+TEXT runtime·vdsoCall_zx_deadline_after(SB),NOSPLIT,$0-16
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ MOVD g_m(g), R21
+ MOVD LR, m_vdsoPC(R21)
+ MOVD RSP, R20
+ MOVD R20, m_vdsoSP(R21)
+ MOVD nanoseconds+0(FP), R0
+ BL vdso_zx_deadline_after(SB)
+ MOVD R0, ret+8(FP)
+ MOVD g_m(g), R21
+ MOVD $0, m_vdsoSP(R21)
+ RET
+
+// func vdsoCall_zx_clock_adjust(handle uint32, clock_id uint32, offset int64) int32
+TEXT runtime·vdsoCall_zx_clock_adjust(SB),NOSPLIT,$0-20
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ MOVD g_m(g), R21
+ MOVD LR, m_vdsoPC(R21)
+ MOVD RSP, R20
+ MOVD R20, m_vdsoSP(R21)
+ MOVW handle+0(FP), R0
+ MOVW clock_id+4(FP), R1
+ MOVD offset+8(FP), R2
+ BL vdso_zx_clock_adjust(SB)
+ MOVW R0, ret+16(FP)
+ MOVD g_m(g), R21
+ MOVD $0, m_vdsoSP(R21)
+ RET
+
+// func vdsoCall_zx_system_get_dcache_line_size() uint32
+TEXT runtime·vdsoCall_zx_system_get_dcache_line_size(SB),NOSPLIT,$0-4
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ MOVD g_m(g), R21
+ MOVD LR, m_vdsoPC(R21)
+ MOVD RSP, R20
+ MOVD R20, m_vdsoSP(R21)
+ BL vdso_zx_system_get_dcache_line_size(SB)
+ MOVW R0, ret+0(FP)
+ MOVD g_m(g), R21
+ MOVD $0, m_vdsoSP(R21)
+ RET
+
+// func vdsoCall_zx_system_get_num_cpus() uint32
+TEXT runtime·vdsoCall_zx_system_get_num_cpus(SB),NOSPLIT,$0-4
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ MOVD g_m(g), R21
+ MOVD LR, m_vdsoPC(R21)
+ MOVD RSP, R20
+ MOVD R20, m_vdsoSP(R21)
+ BL vdso_zx_system_get_num_cpus(SB)
+ MOVW R0, ret+0(FP)
+ MOVD g_m(g), R21
+ MOVD $0, m_vdsoSP(R21)
+ RET
+
+// func vdsoCall_zx_system_get_version(version unsafe.Pointer, version_size uint) int32
+TEXT runtime·vdsoCall_zx_system_get_version(SB),NOSPLIT,$0-20
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ MOVD g_m(g), R21
+ MOVD LR, m_vdsoPC(R21)
+ MOVD RSP, R20
+ MOVD R20, m_vdsoSP(R21)
+ MOVD version+0(FP), R0
+ MOVD version_size+8(FP), R1
+ BL vdso_zx_system_get_version(SB)
+ MOVW R0, ret+16(FP)
+ MOVD g_m(g), R21
+ MOVD $0, m_vdsoSP(R21)
+ RET
+
+// func vdsoCall_zx_system_get_physmem() uint64
+TEXT runtime·vdsoCall_zx_system_get_physmem(SB),NOSPLIT,$0-8
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ MOVD g_m(g), R21
+ MOVD LR, m_vdsoPC(R21)
+ MOVD RSP, R20
+ MOVD R20, m_vdsoSP(R21)
+ BL vdso_zx_system_get_physmem(SB)
+ MOVD R0, ret+0(FP)
+ MOVD g_m(g), R21
+ MOVD $0, m_vdsoSP(R21)
+ RET
+
+// func vdsoCall_zx_system_get_features(kind uint32, features unsafe.Pointer) int32
+TEXT runtime·vdsoCall_zx_system_get_features(SB),NOSPLIT,$0-20
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ MOVD g_m(g), R21
+ MOVD LR, m_vdsoPC(R21)
+ MOVD RSP, R20
+ MOVD R20, m_vdsoSP(R21)
+ MOVW kind+0(FP), R0
+ MOVD features+8(FP), R1
+ BL vdso_zx_system_get_features(SB)
+ MOVW R0, ret+16(FP)
+ MOVD g_m(g), R21
+ MOVD $0, m_vdsoSP(R21)
+ RET
+
+// func vdsoCall_zx_cache_flush(addr unsafe.Pointer, size uint, options uint32) int32
+TEXT runtime·vdsoCall_zx_cache_flush(SB),NOSPLIT,$0-28
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ MOVD g_m(g), R21
+ MOVD LR, m_vdsoPC(R21)
+ MOVD RSP, R20
+ MOVD R20, m_vdsoSP(R21)
+ MOVD addr+0(FP), R0
+ MOVD size+8(FP), R1
+ MOVW options+16(FP), R2
+ BL vdso_zx_cache_flush(SB)
+ MOVW R0, ret+24(FP)
+ MOVD g_m(g), R21
+ MOVD $0, m_vdsoSP(R21)
+ RET
+
+// func vdsoCall_zx_handle_close(handle uint32) int32
+TEXT runtime·vdsoCall_zx_handle_close(SB),NOSPLIT,$0-12
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ MOVD g_m(g), R21
+ MOVD LR, m_vdsoPC(R21)
+ MOVD RSP, R20
+ MOVD R20, m_vdsoSP(R21)
+ MOVW handle+0(FP), R0
+ BL vdso_zx_handle_close(SB)
+ MOVW R0, ret+8(FP)
+ MOVD g_m(g), R21
+ MOVD $0, m_vdsoSP(R21)
+ RET
+
+// func vdsoCall_zx_handle_close_many(handles unsafe.Pointer, num_handles uint) int32
+TEXT runtime·vdsoCall_zx_handle_close_many(SB),NOSPLIT,$0-20
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ MOVD g_m(g), R21
+ MOVD LR, m_vdsoPC(R21)
+ MOVD RSP, R20
+ MOVD R20, m_vdsoSP(R21)
+ MOVD handles+0(FP), R0
+ MOVD num_handles+8(FP), R1
+ BL vdso_zx_handle_close_many(SB)
+ MOVW R0, ret+16(FP)
+ MOVD g_m(g), R21
+ MOVD $0, m_vdsoSP(R21)
+ RET
+
+// func vdsoCall_zx_handle_duplicate(handle uint32, rights uint32, out unsafe.Pointer) int32
+TEXT runtime·vdsoCall_zx_handle_duplicate(SB),NOSPLIT,$0-20
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ MOVD g_m(g), R21
+ MOVD LR, m_vdsoPC(R21)
+ MOVD RSP, R20
+ MOVD R20, m_vdsoSP(R21)
+ MOVW handle+0(FP), R0
+ MOVW rights+4(FP), R1
+ MOVD out+8(FP), R2
+ BL vdso_zx_handle_duplicate(SB)
+ MOVW R0, ret+16(FP)
+ MOVD g_m(g), R21
+ MOVD $0, m_vdsoSP(R21)
+ RET
+
+// func vdsoCall_zx_handle_replace(handle uint32, rights uint32, out unsafe.Pointer) int32
+TEXT runtime·vdsoCall_zx_handle_replace(SB),NOSPLIT,$0-20
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ MOVD g_m(g), R21
+ MOVD LR, m_vdsoPC(R21)
+ MOVD RSP, R20
+ MOVD R20, m_vdsoSP(R21)
+ MOVW handle+0(FP), R0
+ MOVW rights+4(FP), R1
+ MOVD out+8(FP), R2
+ BL vdso_zx_handle_replace(SB)
+ MOVW R0, ret+16(FP)
+ MOVD g_m(g), R21
+ MOVD $0, m_vdsoSP(R21)
+ RET
+
+// func vdsoCall_zx_object_wait_one(handle uint32, signals uint32, deadline int64, observed unsafe.Pointer) int32
+TEXT runtime·vdsoCall_zx_object_wait_one(SB),NOSPLIT,$0-28
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ MOVD g_m(g), R21
+ MOVD LR, m_vdsoPC(R21)
+ MOVD RSP, R20
+ MOVD R20, m_vdsoSP(R21)
+ CALL runtime·entersyscall(SB)
+ MOVW handle+0(FP), R0
+ MOVW signals+4(FP), R1
+ MOVD deadline+8(FP), R2
+ MOVD observed+16(FP), R3
+ BL vdso_zx_object_wait_one(SB)
+ MOVW R0, ret+24(FP)
+ BL runtime·exitsyscall(SB)
+ MOVD g_m(g), R21
+ MOVD $0, m_vdsoSP(R21)
+ RET
+
+// func vdsoCall_zx_object_wait_many(items unsafe.Pointer, count uint, deadline int64) int32
+TEXT runtime·vdsoCall_zx_object_wait_many(SB),NOSPLIT,$0-28
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ MOVD g_m(g), R21
+ MOVD LR, m_vdsoPC(R21)
+ MOVD RSP, R20
+ MOVD R20, m_vdsoSP(R21)
+ CALL runtime·entersyscall(SB)
+ MOVD items+0(FP), R0
+ MOVD count+8(FP), R1
+ MOVD deadline+16(FP), R2
+ BL vdso_zx_object_wait_many(SB)
+ MOVW R0, ret+24(FP)
+ BL runtime·exitsyscall(SB)
+ MOVD g_m(g), R21
+ MOVD $0, m_vdsoSP(R21)
+ RET
+
+// func vdsoCall_zx_object_wait_async(handle uint32, port uint32, key uint64, signals uint32, options uint32) int32
+TEXT runtime·vdsoCall_zx_object_wait_async(SB),NOSPLIT,$0-28
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ MOVD g_m(g), R21
+ MOVD LR, m_vdsoPC(R21)
+ MOVD RSP, R20
+ MOVD R20, m_vdsoSP(R21)
+ MOVW handle+0(FP), R0
+ MOVW port+4(FP), R1
+ MOVD key+8(FP), R2
+ MOVW signals+16(FP), R3
+ MOVW options+20(FP), R4
+ BL vdso_zx_object_wait_async(SB)
+ MOVW R0, ret+24(FP)
+ MOVD g_m(g), R21
+ MOVD $0, m_vdsoSP(R21)
+ RET
+
+// func vdsoCall_zx_object_signal(handle uint32, clear_mask uint32, set_mask uint32) int32
+TEXT runtime·vdsoCall_zx_object_signal(SB),NOSPLIT,$0-20
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ MOVD g_m(g), R21
+ MOVD LR, m_vdsoPC(R21)
+ MOVD RSP, R20
+ MOVD R20, m_vdsoSP(R21)
+ MOVW handle+0(FP), R0
+ MOVW clear_mask+4(FP), R1
+ MOVW set_mask+8(FP), R2
+ BL vdso_zx_object_signal(SB)
+ MOVW R0, ret+16(FP)
+ MOVD g_m(g), R21
+ MOVD $0, m_vdsoSP(R21)
+ RET
+
+// func vdsoCall_zx_object_signal_peer(handle uint32, clear_mask uint32, set_mask uint32) int32
+TEXT runtime·vdsoCall_zx_object_signal_peer(SB),NOSPLIT,$0-20
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ MOVD g_m(g), R21
+ MOVD LR, m_vdsoPC(R21)
+ MOVD RSP, R20
+ MOVD R20, m_vdsoSP(R21)
+ MOVW handle+0(FP), R0
+ MOVW clear_mask+4(FP), R1
+ MOVW set_mask+8(FP), R2
+ BL vdso_zx_object_signal_peer(SB)
+ MOVW R0, ret+16(FP)
+ MOVD g_m(g), R21
+ MOVD $0, m_vdsoSP(R21)
+ RET
+
+// func vdsoCall_zx_object_get_property(handle uint32, property uint32, value unsafe.Pointer, value_size uint) int32
+TEXT runtime·vdsoCall_zx_object_get_property(SB),NOSPLIT,$0-28
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ MOVD g_m(g), R21
+ MOVD LR, m_vdsoPC(R21)
+ MOVD RSP, R20
+ MOVD R20, m_vdsoSP(R21)
+ MOVW handle+0(FP), R0
+ MOVW property+4(FP), R1
+ MOVD value+8(FP), R2
+ MOVD value_size+16(FP), R3
+ BL vdso_zx_object_get_property(SB)
+ MOVW R0, ret+24(FP)
+ MOVD g_m(g), R21
+ MOVD $0, m_vdsoSP(R21)
+ RET
+
+// func vdsoCall_zx_object_set_property(handle uint32, property uint32, value unsafe.Pointer, value_size uint) int32
+TEXT runtime·vdsoCall_zx_object_set_property(SB),NOSPLIT,$0-28
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ MOVD g_m(g), R21
+ MOVD LR, m_vdsoPC(R21)
+ MOVD RSP, R20
+ MOVD R20, m_vdsoSP(R21)
+ MOVW handle+0(FP), R0
+ MOVW property+4(FP), R1
+ MOVD value+8(FP), R2
+ MOVD value_size+16(FP), R3
+ BL vdso_zx_object_set_property(SB)
+ MOVW R0, ret+24(FP)
+ MOVD g_m(g), R21
+ MOVD $0, m_vdsoSP(R21)
+ RET
+
+// func vdsoCall_zx_object_get_info(handle uint32, topic uint32, buffer unsafe.Pointer, buffer_size uint, actual unsafe.Pointer, avail unsafe.Pointer) int32
+TEXT runtime·vdsoCall_zx_object_get_info(SB),NOSPLIT,$0-44
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ MOVD g_m(g), R21
+ MOVD LR, m_vdsoPC(R21)
+ MOVD RSP, R20
+ MOVD R20, m_vdsoSP(R21)
+ MOVW handle+0(FP), R0
+ MOVW topic+4(FP), R1
+ MOVD buffer+8(FP), R2
+ MOVD buffer_size+16(FP), R3
+ MOVD actual+24(FP), R4
+ MOVD avail+32(FP), R5
+ BL vdso_zx_object_get_info(SB)
+ MOVW R0, ret+40(FP)
+ MOVD g_m(g), R21
+ MOVD $0, m_vdsoSP(R21)
+ RET
+
+// func vdsoCall_zx_object_get_child(handle uint32, koid uint64, rights uint32, out unsafe.Pointer) int32
+TEXT runtime·vdsoCall_zx_object_get_child(SB),NOSPLIT,$0-36
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ MOVD g_m(g), R21
+ MOVD LR, m_vdsoPC(R21)
+ MOVD RSP, R20
+ MOVD R20, m_vdsoSP(R21)
+ MOVW handle+0(FP), R0
+ MOVD koid+8(FP), R1
+ MOVW rights+16(FP), R2
+ MOVD out+24(FP), R3
+ BL vdso_zx_object_get_child(SB)
+ MOVW R0, ret+32(FP)
+ MOVD g_m(g), R21
+ MOVD $0, m_vdsoSP(R21)
+ RET
+
+// func vdsoCall_zx_object_set_profile(handle uint32, profile uint32, options uint32) int32
+TEXT runtime·vdsoCall_zx_object_set_profile(SB),NOSPLIT,$0-20
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ MOVD g_m(g), R21
+ MOVD LR, m_vdsoPC(R21)
+ MOVD RSP, R20
+ MOVD R20, m_vdsoSP(R21)
+ MOVW handle+0(FP), R0
+ MOVW profile+4(FP), R1
+ MOVW options+8(FP), R2
+ BL vdso_zx_object_set_profile(SB)
+ MOVW R0, ret+16(FP)
+ MOVD g_m(g), R21
+ MOVD $0, m_vdsoSP(R21)
+ RET
+
+// func vdsoCall_zx_channel_create(options uint32, out0 unsafe.Pointer, out1 unsafe.Pointer) int32
+TEXT runtime·vdsoCall_zx_channel_create(SB),NOSPLIT,$0-28
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ MOVD g_m(g), R21
+ MOVD LR, m_vdsoPC(R21)
+ MOVD RSP, R20
+ MOVD R20, m_vdsoSP(R21)
+ MOVW options+0(FP), R0
+ MOVD out0+8(FP), R1
+ MOVD out1+16(FP), R2
+ BL vdso_zx_channel_create(SB)
+ MOVW R0, ret+24(FP)
+ MOVD g_m(g), R21
+ MOVD $0, m_vdsoSP(R21)
+ RET
+
+// func vdsoCall_zx_channel_read(handle uint32, options uint32, bytes unsafe.Pointer, handles unsafe.Pointer, num_bytes uint32, num_handles uint32, actual_bytes unsafe.Pointer, actual_handles unsafe.Pointer) int32
+TEXT runtime·vdsoCall_zx_channel_read(SB),NOSPLIT,$0-52
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ MOVD g_m(g), R21
+ MOVD LR, m_vdsoPC(R21)
+ MOVD RSP, R20
+ MOVD R20, m_vdsoSP(R21)
+ MOVW handle+0(FP), R0
+ MOVW options+4(FP), R1
+ MOVD bytes+8(FP), R2
+ MOVD handles+16(FP), R3
+ MOVW num_bytes+24(FP), R4
+ MOVW num_handles+28(FP), R5
+ MOVD actual_bytes+32(FP), R6
+ MOVD actual_handles+40(FP), R7
+ BL vdso_zx_channel_read(SB)
+ MOVW R0, ret+48(FP)
+ MOVD g_m(g), R21
+ MOVD $0, m_vdsoSP(R21)
+ RET
+
+// func vdsoCall_zx_channel_read_etc(handle uint32, options uint32, bytes unsafe.Pointer, handles unsafe.Pointer, num_bytes uint32, num_handles uint32, actual_bytes unsafe.Pointer, actual_handles unsafe.Pointer) int32
+TEXT runtime·vdsoCall_zx_channel_read_etc(SB),NOSPLIT,$0-52
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ MOVD g_m(g), R21
+ MOVD LR, m_vdsoPC(R21)
+ MOVD RSP, R20
+ MOVD R20, m_vdsoSP(R21)
+ MOVW handle+0(FP), R0
+ MOVW options+4(FP), R1
+ MOVD bytes+8(FP), R2
+ MOVD handles+16(FP), R3
+ MOVW num_bytes+24(FP), R4
+ MOVW num_handles+28(FP), R5
+ MOVD actual_bytes+32(FP), R6
+ MOVD actual_handles+40(FP), R7
+ BL vdso_zx_channel_read_etc(SB)
+ MOVW R0, ret+48(FP)
+ MOVD g_m(g), R21
+ MOVD $0, m_vdsoSP(R21)
+ RET
+
+// func vdsoCall_zx_channel_write(handle uint32, options uint32, bytes unsafe.Pointer, num_bytes uint32, handles unsafe.Pointer, num_handles uint32) int32
+TEXT runtime·vdsoCall_zx_channel_write(SB),NOSPLIT,$0-44
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ MOVD g_m(g), R21
+ MOVD LR, m_vdsoPC(R21)
+ MOVD RSP, R20
+ MOVD R20, m_vdsoSP(R21)
+ MOVW handle+0(FP), R0
+ MOVW options+4(FP), R1
+ MOVD bytes+8(FP), R2
+ MOVW num_bytes+16(FP), R3
+ MOVD handles+24(FP), R4
+ MOVW num_handles+32(FP), R5
+ BL vdso_zx_channel_write(SB)
+ MOVW R0, ret+40(FP)
+ MOVD g_m(g), R21
+ MOVD $0, m_vdsoSP(R21)
+ RET
+
+// func vdsoCall_zx_channel_call_noretry(handle uint32, options uint32, deadline int64, args unsafe.Pointer, actual_bytes unsafe.Pointer, actual_handles unsafe.Pointer) int32
+TEXT runtime·vdsoCall_zx_channel_call_noretry(SB),NOSPLIT,$0-44
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ MOVD g_m(g), R21
+ MOVD LR, m_vdsoPC(R21)
+ MOVD RSP, R20
+ MOVD R20, m_vdsoSP(R21)
+ MOVW handle+0(FP), R0
+ MOVW options+4(FP), R1
+ MOVD deadline+8(FP), R2
+ MOVD args+16(FP), R3
+ MOVD actual_bytes+24(FP), R4
+ MOVD actual_handles+32(FP), R5
+ BL vdso_zx_channel_call_noretry(SB)
+ MOVW R0, ret+40(FP)
+ MOVD g_m(g), R21
+ MOVD $0, m_vdsoSP(R21)
+ RET
+
+// func vdsoCall_zx_channel_call_finish(deadline int64, args unsafe.Pointer, actual_bytes unsafe.Pointer, actual_handles unsafe.Pointer) int32
+TEXT runtime·vdsoCall_zx_channel_call_finish(SB),NOSPLIT,$0-36
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ MOVD g_m(g), R21
+ MOVD LR, m_vdsoPC(R21)
+ MOVD RSP, R20
+ MOVD R20, m_vdsoSP(R21)
+ MOVD deadline+0(FP), R0
+ MOVD args+8(FP), R1
+ MOVD actual_bytes+16(FP), R2
+ MOVD actual_handles+24(FP), R3
+ BL vdso_zx_channel_call_finish(SB)
+ MOVW R0, ret+32(FP)
+ MOVD g_m(g), R21
+ MOVD $0, m_vdsoSP(R21)
+ RET
+
+// func vdsoCall_zx_channel_call(handle uint32, options uint32, deadline int64, args unsafe.Pointer, actual_bytes unsafe.Pointer, actual_handles unsafe.Pointer) int32
+TEXT runtime·vdsoCall_zx_channel_call(SB),NOSPLIT,$0-44
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ MOVD g_m(g), R21
+ MOVD LR, m_vdsoPC(R21)
+ MOVD RSP, R20
+ MOVD R20, m_vdsoSP(R21)
+ CALL runtime·entersyscall(SB)
+ MOVW handle+0(FP), R0
+ MOVW options+4(FP), R1
+ MOVD deadline+8(FP), R2
+ MOVD args+16(FP), R3
+ MOVD actual_bytes+24(FP), R4
+ MOVD actual_handles+32(FP), R5
+ BL vdso_zx_channel_call(SB)
+ MOVW R0, ret+40(FP)
+ BL runtime·exitsyscall(SB)
+ MOVD g_m(g), R21
+ MOVD $0, m_vdsoSP(R21)
+ RET
+
+// func vdsoCall_zx_socket_create(options uint32, out0 unsafe.Pointer, out1 unsafe.Pointer) int32
+TEXT runtime·vdsoCall_zx_socket_create(SB),NOSPLIT,$0-28
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ MOVD g_m(g), R21
+ MOVD LR, m_vdsoPC(R21)
+ MOVD RSP, R20
+ MOVD R20, m_vdsoSP(R21)
+ MOVW options+0(FP), R0
+ MOVD out0+8(FP), R1
+ MOVD out1+16(FP), R2
+ BL vdso_zx_socket_create(SB)
+ MOVW R0, ret+24(FP)
+ MOVD g_m(g), R21
+ MOVD $0, m_vdsoSP(R21)
+ RET
+
+// func vdsoCall_zx_socket_write(handle uint32, options uint32, buffer unsafe.Pointer, buffer_size uint, actual unsafe.Pointer) int32
+TEXT runtime·vdsoCall_zx_socket_write(SB),NOSPLIT,$0-36
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ MOVD g_m(g), R21
+ MOVD LR, m_vdsoPC(R21)
+ MOVD RSP, R20
+ MOVD R20, m_vdsoSP(R21)
+ MOVW handle+0(FP), R0
+ MOVW options+4(FP), R1
+ MOVD buffer+8(FP), R2
+ MOVD buffer_size+16(FP), R3
+ MOVD actual+24(FP), R4
+ BL vdso_zx_socket_write(SB)
+ MOVW R0, ret+32(FP)
+ MOVD g_m(g), R21
+ MOVD $0, m_vdsoSP(R21)
+ RET
+
+// func vdsoCall_zx_socket_read(handle uint32, options uint32, buffer unsafe.Pointer, buffer_size uint, actual unsafe.Pointer) int32
+TEXT runtime·vdsoCall_zx_socket_read(SB),NOSPLIT,$0-36
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ MOVD g_m(g), R21
+ MOVD LR, m_vdsoPC(R21)
+ MOVD RSP, R20
+ MOVD R20, m_vdsoSP(R21)
+ MOVW handle+0(FP), R0
+ MOVW options+4(FP), R1
+ MOVD buffer+8(FP), R2
+ MOVD buffer_size+16(FP), R3
+ MOVD actual+24(FP), R4
+ BL vdso_zx_socket_read(SB)
+ MOVW R0, ret+32(FP)
+ MOVD g_m(g), R21
+ MOVD $0, m_vdsoSP(R21)
+ RET
+
+// func vdsoCall_zx_socket_share(handle uint32, socket_to_share uint32) int32
+TEXT runtime·vdsoCall_zx_socket_share(SB),NOSPLIT,$0-12
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ MOVD g_m(g), R21
+ MOVD LR, m_vdsoPC(R21)
+ MOVD RSP, R20
+ MOVD R20, m_vdsoSP(R21)
+ MOVW handle+0(FP), R0
+ MOVW socket_to_share+4(FP), R1
+ BL vdso_zx_socket_share(SB)
+ MOVW R0, ret+8(FP)
+ MOVD g_m(g), R21
+ MOVD $0, m_vdsoSP(R21)
+ RET
+
+// func vdsoCall_zx_socket_accept(handle uint32, out_socket unsafe.Pointer) int32
+TEXT runtime·vdsoCall_zx_socket_accept(SB),NOSPLIT,$0-20
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ MOVD g_m(g), R21
+ MOVD LR, m_vdsoPC(R21)
+ MOVD RSP, R20
+ MOVD R20, m_vdsoSP(R21)
+ MOVW handle+0(FP), R0
+ MOVD out_socket+8(FP), R1
+ BL vdso_zx_socket_accept(SB)
+ MOVW R0, ret+16(FP)
+ MOVD g_m(g), R21
+ MOVD $0, m_vdsoSP(R21)
+ RET
+
+// func vdsoCall_zx_socket_shutdown(handle uint32, options uint32) int32
+TEXT runtime·vdsoCall_zx_socket_shutdown(SB),NOSPLIT,$0-12
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ MOVD g_m(g), R21
+ MOVD LR, m_vdsoPC(R21)
+ MOVD RSP, R20
+ MOVD R20, m_vdsoSP(R21)
+ MOVW handle+0(FP), R0
+ MOVW options+4(FP), R1
+ BL vdso_zx_socket_shutdown(SB)
+ MOVW R0, ret+8(FP)
+ MOVD g_m(g), R21
+ MOVD $0, m_vdsoSP(R21)
+ RET
+
+// func vdsoCall_zx_thread_exit()
+TEXT runtime·vdsoCall_zx_thread_exit(SB),NOSPLIT,$0-0
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ MOVD g_m(g), R21
+ MOVD LR, m_vdsoPC(R21)
+ MOVD RSP, R20
+ MOVD R20, m_vdsoSP(R21)
+ BL vdso_zx_thread_exit(SB)
+ MOVD g_m(g), R21
+ MOVD $0, m_vdsoSP(R21)
+ RET
+
+// func vdsoCall_zx_thread_create(process uint32, name unsafe.Pointer, name_size uint, options uint32, out unsafe.Pointer) int32
+TEXT runtime·vdsoCall_zx_thread_create(SB),NOSPLIT,$0-44
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ MOVD g_m(g), R21
+ MOVD LR, m_vdsoPC(R21)
+ MOVD RSP, R20
+ MOVD R20, m_vdsoSP(R21)
+ MOVW process+0(FP), R0
+ MOVD name+8(FP), R1
+ MOVD name_size+16(FP), R2
+ MOVW options+24(FP), R3
+ MOVD out+32(FP), R4
+ BL vdso_zx_thread_create(SB)
+ MOVW R0, ret+40(FP)
+ MOVD g_m(g), R21
+ MOVD $0, m_vdsoSP(R21)
+ RET
+
+// func vdsoCall_zx_thread_start(handle uint32, thread_entry uintptr, stack uintptr, arg1 uintptr, arg2 uintptr) int32
+TEXT runtime·vdsoCall_zx_thread_start(SB),NOSPLIT,$0-44
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ MOVD g_m(g), R21
+ MOVD LR, m_vdsoPC(R21)
+ MOVD RSP, R20
+ MOVD R20, m_vdsoSP(R21)
+ MOVW handle+0(FP), R0
+ MOVD thread_entry+8(FP), R1
+ MOVD stack+16(FP), R2
+ MOVD arg1+24(FP), R3
+ MOVD arg2+32(FP), R4
+ BL vdso_zx_thread_start(SB)
+ MOVW R0, ret+40(FP)
+ MOVD g_m(g), R21
+ MOVD $0, m_vdsoSP(R21)
+ RET
+
+// func vdsoCall_zx_thread_read_state(handle uint32, kind uint32, buffer unsafe.Pointer, buffer_size uint) int32
+TEXT runtime·vdsoCall_zx_thread_read_state(SB),NOSPLIT,$0-28
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ MOVD g_m(g), R21
+ MOVD LR, m_vdsoPC(R21)
+ MOVD RSP, R20
+ MOVD R20, m_vdsoSP(R21)
+ MOVW handle+0(FP), R0
+ MOVW kind+4(FP), R1
+ MOVD buffer+8(FP), R2
+ MOVD buffer_size+16(FP), R3
+ BL vdso_zx_thread_read_state(SB)
+ MOVW R0, ret+24(FP)
+ MOVD g_m(g), R21
+ MOVD $0, m_vdsoSP(R21)
+ RET
+
+// func vdsoCall_zx_thread_write_state(handle uint32, kind uint32, buffer unsafe.Pointer, buffer_size uint) int32
+TEXT runtime·vdsoCall_zx_thread_write_state(SB),NOSPLIT,$0-28
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ MOVD g_m(g), R21
+ MOVD LR, m_vdsoPC(R21)
+ MOVD RSP, R20
+ MOVD R20, m_vdsoSP(R21)
+ MOVW handle+0(FP), R0
+ MOVW kind+4(FP), R1
+ MOVD buffer+8(FP), R2
+ MOVD buffer_size+16(FP), R3
+ BL vdso_zx_thread_write_state(SB)
+ MOVW R0, ret+24(FP)
+ MOVD g_m(g), R21
+ MOVD $0, m_vdsoSP(R21)
+ RET
+
+// func vdsoCall_zx_process_exit(retcode int64)
+TEXT runtime·vdsoCall_zx_process_exit(SB),NOSPLIT,$0-8
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ MOVD g_m(g), R21
+ MOVD LR, m_vdsoPC(R21)
+ MOVD RSP, R20
+ MOVD R20, m_vdsoSP(R21)
+ MOVD retcode+0(FP), R0
+ BL vdso_zx_process_exit(SB)
+ MOVD g_m(g), R21
+ MOVD $0, m_vdsoSP(R21)
+ RET
+
+// func vdsoCall_zx_process_create(job uint32, name unsafe.Pointer, name_size uint, options uint32, proc_handle unsafe.Pointer, vmar_handle unsafe.Pointer) int32
+TEXT runtime·vdsoCall_zx_process_create(SB),NOSPLIT,$0-52
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ MOVD g_m(g), R21
+ MOVD LR, m_vdsoPC(R21)
+ MOVD RSP, R20
+ MOVD R20, m_vdsoSP(R21)
+ MOVW job+0(FP), R0
+ MOVD name+8(FP), R1
+ MOVD name_size+16(FP), R2
+ MOVW options+24(FP), R3
+ MOVD proc_handle+32(FP), R4
+ MOVD vmar_handle+40(FP), R5
+ BL vdso_zx_process_create(SB)
+ MOVW R0, ret+48(FP)
+ MOVD g_m(g), R21
+ MOVD $0, m_vdsoSP(R21)
+ RET
+
+// func vdsoCall_zx_process_start(handle uint32, thread uint32, entry uintptr, stack uintptr, arg1 uint32, arg2 uintptr) int32
+TEXT runtime·vdsoCall_zx_process_start(SB),NOSPLIT,$0-44
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ MOVD g_m(g), R21
+ MOVD LR, m_vdsoPC(R21)
+ MOVD RSP, R20
+ MOVD R20, m_vdsoSP(R21)
+ MOVW handle+0(FP), R0
+ MOVW thread+4(FP), R1
+ MOVD entry+8(FP), R2
+ MOVD stack+16(FP), R3
+ MOVW arg1+24(FP), R4
+ MOVD arg2+32(FP), R5
+ BL vdso_zx_process_start(SB)
+ MOVW R0, ret+40(FP)
+ MOVD g_m(g), R21
+ MOVD $0, m_vdsoSP(R21)
+ RET
+
+// func vdsoCall_zx_process_read_memory(handle uint32, vaddr uintptr, buffer unsafe.Pointer, buffer_size uint, actual unsafe.Pointer) int32
+TEXT runtime·vdsoCall_zx_process_read_memory(SB),NOSPLIT,$0-44
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ MOVD g_m(g), R21
+ MOVD LR, m_vdsoPC(R21)
+ MOVD RSP, R20
+ MOVD R20, m_vdsoSP(R21)
+ MOVW handle+0(FP), R0
+ MOVD vaddr+8(FP), R1
+ MOVD buffer+16(FP), R2
+ MOVD buffer_size+24(FP), R3
+ MOVD actual+32(FP), R4
+ BL vdso_zx_process_read_memory(SB)
+ MOVW R0, ret+40(FP)
+ MOVD g_m(g), R21
+ MOVD $0, m_vdsoSP(R21)
+ RET
+
+// func vdsoCall_zx_process_write_memory(handle uint32, vaddr uintptr, buffer unsafe.Pointer, buffer_size uint, actual unsafe.Pointer) int32
+TEXT runtime·vdsoCall_zx_process_write_memory(SB),NOSPLIT,$0-44
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ MOVD g_m(g), R21
+ MOVD LR, m_vdsoPC(R21)
+ MOVD RSP, R20
+ MOVD R20, m_vdsoSP(R21)
+ MOVW handle+0(FP), R0
+ MOVD vaddr+8(FP), R1
+ MOVD buffer+16(FP), R2
+ MOVD buffer_size+24(FP), R3
+ MOVD actual+32(FP), R4
+ BL vdso_zx_process_write_memory(SB)
+ MOVW R0, ret+40(FP)
+ MOVD g_m(g), R21
+ MOVD $0, m_vdsoSP(R21)
+ RET
+
+// func vdsoCall_zx_job_create(parent_job uint32, options uint32, out unsafe.Pointer) int32
+TEXT runtime·vdsoCall_zx_job_create(SB),NOSPLIT,$0-20
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ MOVD g_m(g), R21
+ MOVD LR, m_vdsoPC(R21)
+ MOVD RSP, R20
+ MOVD R20, m_vdsoSP(R21)
+ MOVW parent_job+0(FP), R0
+ MOVW options+4(FP), R1
+ MOVD out+8(FP), R2
+ BL vdso_zx_job_create(SB)
+ MOVW R0, ret+16(FP)
+ MOVD g_m(g), R21
+ MOVD $0, m_vdsoSP(R21)
+ RET
+
+// func vdsoCall_zx_job_set_policy(handle uint32, options uint32, topic uint32, policy unsafe.Pointer, count uint32) int32
+TEXT runtime·vdsoCall_zx_job_set_policy(SB),NOSPLIT,$0-36
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ MOVD g_m(g), R21
+ MOVD LR, m_vdsoPC(R21)
+ MOVD RSP, R20
+ MOVD R20, m_vdsoSP(R21)
+ MOVW handle+0(FP), R0
+ MOVW options+4(FP), R1
+ MOVW topic+8(FP), R2
+ MOVD policy+16(FP), R3
+ MOVW count+24(FP), R4
+ BL vdso_zx_job_set_policy(SB)
+ MOVW R0, ret+32(FP)
+ MOVD g_m(g), R21
+ MOVD $0, m_vdsoSP(R21)
+ RET
+
+// func vdsoCall_zx_task_bind_exception_port(handle uint32, port uint32, key uint64, options uint32) int32
+TEXT runtime·vdsoCall_zx_task_bind_exception_port(SB),NOSPLIT,$0-28
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ MOVD g_m(g), R21
+ MOVD LR, m_vdsoPC(R21)
+ MOVD RSP, R20
+ MOVD R20, m_vdsoSP(R21)
+ MOVW handle+0(FP), R0
+ MOVW port+4(FP), R1
+ MOVD key+8(FP), R2
+ MOVW options+16(FP), R3
+ BL vdso_zx_task_bind_exception_port(SB)
+ MOVW R0, ret+24(FP)
+ MOVD g_m(g), R21
+ MOVD $0, m_vdsoSP(R21)
+ RET
+
+// func vdsoCall_zx_task_suspend(handle uint32, token unsafe.Pointer) int32
+TEXT runtime·vdsoCall_zx_task_suspend(SB),NOSPLIT,$0-20
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ MOVD g_m(g), R21
+ MOVD LR, m_vdsoPC(R21)
+ MOVD RSP, R20
+ MOVD R20, m_vdsoSP(R21)
+ MOVW handle+0(FP), R0
+ MOVD token+8(FP), R1
+ BL vdso_zx_task_suspend(SB)
+ MOVW R0, ret+16(FP)
+ MOVD g_m(g), R21
+ MOVD $0, m_vdsoSP(R21)
+ RET
+
+// func vdsoCall_zx_task_suspend_token(handle uint32, token unsafe.Pointer) int32
+TEXT runtime·vdsoCall_zx_task_suspend_token(SB),NOSPLIT,$0-20
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ MOVD g_m(g), R21
+ MOVD LR, m_vdsoPC(R21)
+ MOVD RSP, R20
+ MOVD R20, m_vdsoSP(R21)
+ MOVW handle+0(FP), R0
+ MOVD token+8(FP), R1
+ BL vdso_zx_task_suspend_token(SB)
+ MOVW R0, ret+16(FP)
+ MOVD g_m(g), R21
+ MOVD $0, m_vdsoSP(R21)
+ RET
+
+// func vdsoCall_zx_task_resume_from_exception(handle uint32, port uint32, options uint32) int32
+TEXT runtime·vdsoCall_zx_task_resume_from_exception(SB),NOSPLIT,$0-20
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ MOVD g_m(g), R21
+ MOVD LR, m_vdsoPC(R21)
+ MOVD RSP, R20
+ MOVD R20, m_vdsoSP(R21)
+ MOVW handle+0(FP), R0
+ MOVW port+4(FP), R1
+ MOVW options+8(FP), R2
+ BL vdso_zx_task_resume_from_exception(SB)
+ MOVW R0, ret+16(FP)
+ MOVD g_m(g), R21
+ MOVD $0, m_vdsoSP(R21)
+ RET
+
+// func vdsoCall_zx_task_kill(handle uint32) int32
+TEXT runtime·vdsoCall_zx_task_kill(SB),NOSPLIT,$0-12
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ MOVD g_m(g), R21
+ MOVD LR, m_vdsoPC(R21)
+ MOVD RSP, R20
+ MOVD R20, m_vdsoSP(R21)
+ MOVW handle+0(FP), R0
+ BL vdso_zx_task_kill(SB)
+ MOVW R0, ret+8(FP)
+ MOVD g_m(g), R21
+ MOVD $0, m_vdsoSP(R21)
+ RET
+
+// func vdsoCall_zx_event_create(options uint32, out unsafe.Pointer) int32
+TEXT runtime·vdsoCall_zx_event_create(SB),NOSPLIT,$0-20
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ MOVD g_m(g), R21
+ MOVD LR, m_vdsoPC(R21)
+ MOVD RSP, R20
+ MOVD R20, m_vdsoSP(R21)
+ MOVW options+0(FP), R0
+ MOVD out+8(FP), R1
+ BL vdso_zx_event_create(SB)
+ MOVW R0, ret+16(FP)
+ MOVD g_m(g), R21
+ MOVD $0, m_vdsoSP(R21)
+ RET
+
+// func vdsoCall_zx_eventpair_create(options uint32, out0 unsafe.Pointer, out1 unsafe.Pointer) int32
+TEXT runtime·vdsoCall_zx_eventpair_create(SB),NOSPLIT,$0-28
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ MOVD g_m(g), R21
+ MOVD LR, m_vdsoPC(R21)
+ MOVD RSP, R20
+ MOVD R20, m_vdsoSP(R21)
+ MOVW options+0(FP), R0
+ MOVD out0+8(FP), R1
+ MOVD out1+16(FP), R2
+ BL vdso_zx_eventpair_create(SB)
+ MOVW R0, ret+24(FP)
+ MOVD g_m(g), R21
+ MOVD $0, m_vdsoSP(R21)
+ RET
+
+// func vdsoCall_zx_futex_wait(value_ptr unsafe.Pointer, current_value int32, new_futex_owner uint32, deadline int64) int32
+TEXT runtime·vdsoCall_zx_futex_wait(SB),NOSPLIT,$0-28
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ MOVD g_m(g), R21
+ MOVD LR, m_vdsoPC(R21)
+ MOVD RSP, R20
+ MOVD R20, m_vdsoSP(R21)
+ MOVD value_ptr+0(FP), R0
+ MOVW current_value+8(FP), R1
+ MOVW new_futex_owner+12(FP), R2
+ MOVD deadline+16(FP), R3
+ BL vdso_zx_futex_wait(SB)
+ MOVW R0, ret+24(FP)
+ MOVD g_m(g), R21
+ MOVD $0, m_vdsoSP(R21)
+ RET
+
+// func vdsoCall_zx_futex_wake(value_ptr unsafe.Pointer, wake_count uint32) int32
+TEXT runtime·vdsoCall_zx_futex_wake(SB),NOSPLIT,$0-20
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ MOVD g_m(g), R21
+ MOVD LR, m_vdsoPC(R21)
+ MOVD RSP, R20
+ MOVD R20, m_vdsoSP(R21)
+ MOVD value_ptr+0(FP), R0
+ MOVW wake_count+8(FP), R1
+ BL vdso_zx_futex_wake(SB)
+ MOVW R0, ret+16(FP)
+ MOVD g_m(g), R21
+ MOVD $0, m_vdsoSP(R21)
+ RET
+
+// func vdsoCall_zx_futex_requeue(value_ptr unsafe.Pointer, wake_count uint32, current_value int32, requeue_ptr unsafe.Pointer, requeue_count uint32, new_requeue_owner uint32) int32
+TEXT runtime·vdsoCall_zx_futex_requeue(SB),NOSPLIT,$0-36
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ MOVD g_m(g), R21
+ MOVD LR, m_vdsoPC(R21)
+ MOVD RSP, R20
+ MOVD R20, m_vdsoSP(R21)
+ MOVD value_ptr+0(FP), R0
+ MOVW wake_count+8(FP), R1
+ MOVW current_value+12(FP), R2
+ MOVD requeue_ptr+16(FP), R3
+ MOVW requeue_count+24(FP), R4
+ MOVW new_requeue_owner+28(FP), R5
+ BL vdso_zx_futex_requeue(SB)
+ MOVW R0, ret+32(FP)
+ MOVD g_m(g), R21
+ MOVD $0, m_vdsoSP(R21)
+ RET
+
+// func vdsoCall_zx_futex_wake_single_owner(value_ptr unsafe.Pointer) int32
+TEXT runtime·vdsoCall_zx_futex_wake_single_owner(SB),NOSPLIT,$0-12
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ MOVD g_m(g), R21
+ MOVD LR, m_vdsoPC(R21)
+ MOVD RSP, R20
+ MOVD R20, m_vdsoSP(R21)
+ MOVD value_ptr+0(FP), R0
+ BL vdso_zx_futex_wake_single_owner(SB)
+ MOVW R0, ret+8(FP)
+ MOVD g_m(g), R21
+ MOVD $0, m_vdsoSP(R21)
+ RET
+
+// func vdsoCall_zx_futex_requeue_single_owner(value_ptr unsafe.Pointer, current_value int32, requeue_ptr unsafe.Pointer, requeue_count uint32, new_requeue_owner uint32) int32
+TEXT runtime·vdsoCall_zx_futex_requeue_single_owner(SB),NOSPLIT,$0-36
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ MOVD g_m(g), R21
+ MOVD LR, m_vdsoPC(R21)
+ MOVD RSP, R20
+ MOVD R20, m_vdsoSP(R21)
+ MOVD value_ptr+0(FP), R0
+ MOVW current_value+8(FP), R1
+ MOVD requeue_ptr+16(FP), R2
+ MOVW requeue_count+24(FP), R3
+ MOVW new_requeue_owner+28(FP), R4
+ BL vdso_zx_futex_requeue_single_owner(SB)
+ MOVW R0, ret+32(FP)
+ MOVD g_m(g), R21
+ MOVD $0, m_vdsoSP(R21)
+ RET
+
+// func vdsoCall_zx_futex_get_owner(value_ptr unsafe.Pointer, koid unsafe.Pointer) int32
+TEXT runtime·vdsoCall_zx_futex_get_owner(SB),NOSPLIT,$0-20
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ MOVD g_m(g), R21
+ MOVD LR, m_vdsoPC(R21)
+ MOVD RSP, R20
+ MOVD R20, m_vdsoSP(R21)
+ MOVD value_ptr+0(FP), R0
+ MOVD koid+8(FP), R1
+ BL vdso_zx_futex_get_owner(SB)
+ MOVW R0, ret+16(FP)
+ MOVD g_m(g), R21
+ MOVD $0, m_vdsoSP(R21)
+ RET
+
+// func vdsoCall_zx_port_create(options uint32, out unsafe.Pointer) int32
+TEXT runtime·vdsoCall_zx_port_create(SB),NOSPLIT,$0-20
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ MOVD g_m(g), R21
+ MOVD LR, m_vdsoPC(R21)
+ MOVD RSP, R20
+ MOVD R20, m_vdsoSP(R21)
+ MOVW options+0(FP), R0
+ MOVD out+8(FP), R1
+ BL vdso_zx_port_create(SB)
+ MOVW R0, ret+16(FP)
+ MOVD g_m(g), R21
+ MOVD $0, m_vdsoSP(R21)
+ RET
+
+// func vdsoCall_zx_port_queue(handle uint32, packet unsafe.Pointer) int32
+TEXT runtime·vdsoCall_zx_port_queue(SB),NOSPLIT,$0-20
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ MOVD g_m(g), R21
+ MOVD LR, m_vdsoPC(R21)
+ MOVD RSP, R20
+ MOVD R20, m_vdsoSP(R21)
+ MOVW handle+0(FP), R0
+ MOVD packet+8(FP), R1
+ BL vdso_zx_port_queue(SB)
+ MOVW R0, ret+16(FP)
+ MOVD g_m(g), R21
+ MOVD $0, m_vdsoSP(R21)
+ RET
+
+// func vdsoCall_zx_port_wait(handle uint32, deadline int64, packet unsafe.Pointer) int32
+TEXT runtime·vdsoCall_zx_port_wait(SB),NOSPLIT,$0-28
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ MOVD g_m(g), R21
+ MOVD LR, m_vdsoPC(R21)
+ MOVD RSP, R20
+ MOVD R20, m_vdsoSP(R21)
+ CALL runtime·entersyscall(SB)
+ MOVW handle+0(FP), R0
+ MOVD deadline+8(FP), R1
+ MOVD packet+16(FP), R2
+ BL vdso_zx_port_wait(SB)
+ MOVW R0, ret+24(FP)
+ BL runtime·exitsyscall(SB)
+ MOVD g_m(g), R21
+ MOVD $0, m_vdsoSP(R21)
+ RET
+
+// func vdsoCall_zx_port_cancel(handle uint32, source uint32, key uint64) int32
+TEXT runtime·vdsoCall_zx_port_cancel(SB),NOSPLIT,$0-20
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ MOVD g_m(g), R21
+ MOVD LR, m_vdsoPC(R21)
+ MOVD RSP, R20
+ MOVD R20, m_vdsoSP(R21)
+ MOVW handle+0(FP), R0
+ MOVW source+4(FP), R1
+ MOVD key+8(FP), R2
+ BL vdso_zx_port_cancel(SB)
+ MOVW R0, ret+16(FP)
+ MOVD g_m(g), R21
+ MOVD $0, m_vdsoSP(R21)
+ RET
+
+// func vdsoCall_zx_timer_create(options uint32, clock_id uint32, out unsafe.Pointer) int32
+TEXT runtime·vdsoCall_zx_timer_create(SB),NOSPLIT,$0-20
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ MOVD g_m(g), R21
+ MOVD LR, m_vdsoPC(R21)
+ MOVD RSP, R20
+ MOVD R20, m_vdsoSP(R21)
+ MOVW options+0(FP), R0
+ MOVW clock_id+4(FP), R1
+ MOVD out+8(FP), R2
+ BL vdso_zx_timer_create(SB)
+ MOVW R0, ret+16(FP)
+ MOVD g_m(g), R21
+ MOVD $0, m_vdsoSP(R21)
+ RET
+
+// func vdsoCall_zx_timer_set(handle uint32, deadline int64, slack int64) int32
+TEXT runtime·vdsoCall_zx_timer_set(SB),NOSPLIT,$0-28
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ MOVD g_m(g), R21
+ MOVD LR, m_vdsoPC(R21)
+ MOVD RSP, R20
+ MOVD R20, m_vdsoSP(R21)
+ MOVW handle+0(FP), R0
+ MOVD deadline+8(FP), R1
+ MOVD slack+16(FP), R2
+ BL vdso_zx_timer_set(SB)
+ MOVW R0, ret+24(FP)
+ MOVD g_m(g), R21
+ MOVD $0, m_vdsoSP(R21)
+ RET
+
+// func vdsoCall_zx_timer_cancel(handle uint32) int32
+TEXT runtime·vdsoCall_zx_timer_cancel(SB),NOSPLIT,$0-12
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ MOVD g_m(g), R21
+ MOVD LR, m_vdsoPC(R21)
+ MOVD RSP, R20
+ MOVD R20, m_vdsoSP(R21)
+ MOVW handle+0(FP), R0
+ BL vdso_zx_timer_cancel(SB)
+ MOVW R0, ret+8(FP)
+ MOVD g_m(g), R21
+ MOVD $0, m_vdsoSP(R21)
+ RET
+
+// func vdsoCall_zx_vmo_create(size uint64, options uint32, out unsafe.Pointer) int32
+TEXT runtime·vdsoCall_zx_vmo_create(SB),NOSPLIT,$0-28
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ MOVD g_m(g), R21
+ MOVD LR, m_vdsoPC(R21)
+ MOVD RSP, R20
+ MOVD R20, m_vdsoSP(R21)
+ MOVD size+0(FP), R0
+ MOVW options+8(FP), R1
+ MOVD out+16(FP), R2
+ BL vdso_zx_vmo_create(SB)
+ MOVW R0, ret+24(FP)
+ MOVD g_m(g), R21
+ MOVD $0, m_vdsoSP(R21)
+ RET
+
+// func vdsoCall_zx_vmo_read(handle uint32, buffer unsafe.Pointer, offset uint64, buffer_size uint) int32
+TEXT runtime·vdsoCall_zx_vmo_read(SB),NOSPLIT,$0-36
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ MOVD g_m(g), R21
+ MOVD LR, m_vdsoPC(R21)
+ MOVD RSP, R20
+ MOVD R20, m_vdsoSP(R21)
+ MOVW handle+0(FP), R0
+ MOVD buffer+8(FP), R1
+ MOVD offset+16(FP), R2
+ MOVD buffer_size+24(FP), R3
+ BL vdso_zx_vmo_read(SB)
+ MOVW R0, ret+32(FP)
+ MOVD g_m(g), R21
+ MOVD $0, m_vdsoSP(R21)
+ RET
+
+// func vdsoCall_zx_vmo_write(handle uint32, buffer unsafe.Pointer, offset uint64, buffer_size uint) int32
+TEXT runtime·vdsoCall_zx_vmo_write(SB),NOSPLIT,$0-36
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ MOVD g_m(g), R21
+ MOVD LR, m_vdsoPC(R21)
+ MOVD RSP, R20
+ MOVD R20, m_vdsoSP(R21)
+ MOVW handle+0(FP), R0
+ MOVD buffer+8(FP), R1
+ MOVD offset+16(FP), R2
+ MOVD buffer_size+24(FP), R3
+ BL vdso_zx_vmo_write(SB)
+ MOVW R0, ret+32(FP)
+ MOVD g_m(g), R21
+ MOVD $0, m_vdsoSP(R21)
+ RET
+
+// func vdsoCall_zx_vmo_get_size(handle uint32, size unsafe.Pointer) int32
+TEXT runtime·vdsoCall_zx_vmo_get_size(SB),NOSPLIT,$0-20
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ MOVD g_m(g), R21
+ MOVD LR, m_vdsoPC(R21)
+ MOVD RSP, R20
+ MOVD R20, m_vdsoSP(R21)
+ MOVW handle+0(FP), R0
+ MOVD size+8(FP), R1
+ BL vdso_zx_vmo_get_size(SB)
+ MOVW R0, ret+16(FP)
+ MOVD g_m(g), R21
+ MOVD $0, m_vdsoSP(R21)
+ RET
+
+// func vdsoCall_zx_vmo_set_size(handle uint32, size uint64) int32
+TEXT runtime·vdsoCall_zx_vmo_set_size(SB),NOSPLIT,$0-20
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ MOVD g_m(g), R21
+ MOVD LR, m_vdsoPC(R21)
+ MOVD RSP, R20
+ MOVD R20, m_vdsoSP(R21)
+ MOVW handle+0(FP), R0
+ MOVD size+8(FP), R1
+ BL vdso_zx_vmo_set_size(SB)
+ MOVW R0, ret+16(FP)
+ MOVD g_m(g), R21
+ MOVD $0, m_vdsoSP(R21)
+ RET
+
+// func vdsoCall_zx_vmo_op_range(handle uint32, op uint32, offset uint64, size uint64, buffer unsafe.Pointer, buffer_size uint) int32
+TEXT runtime·vdsoCall_zx_vmo_op_range(SB),NOSPLIT,$0-44
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ MOVD g_m(g), R21
+ MOVD LR, m_vdsoPC(R21)
+ MOVD RSP, R20
+ MOVD R20, m_vdsoSP(R21)
+ MOVW handle+0(FP), R0
+ MOVW op+4(FP), R1
+ MOVD offset+8(FP), R2
+ MOVD size+16(FP), R3
+ MOVD buffer+24(FP), R4
+ MOVD buffer_size+32(FP), R5
+ BL vdso_zx_vmo_op_range(SB)
+ MOVW R0, ret+40(FP)
+ MOVD g_m(g), R21
+ MOVD $0, m_vdsoSP(R21)
+ RET
+
+// func vdsoCall_zx_vmo_create_child(handle uint32, options uint32, offset uint64, size uint64, out unsafe.Pointer) int32
+TEXT runtime·vdsoCall_zx_vmo_create_child(SB),NOSPLIT,$0-36
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ MOVD g_m(g), R21
+ MOVD LR, m_vdsoPC(R21)
+ MOVD RSP, R20
+ MOVD R20, m_vdsoSP(R21)
+ MOVW handle+0(FP), R0
+ MOVW options+4(FP), R1
+ MOVD offset+8(FP), R2
+ MOVD size+16(FP), R3
+ MOVD out+24(FP), R4
+ BL vdso_zx_vmo_create_child(SB)
+ MOVW R0, ret+32(FP)
+ MOVD g_m(g), R21
+ MOVD $0, m_vdsoSP(R21)
+ RET
+
+// func vdsoCall_zx_vmo_set_cache_policy(handle uint32, cache_policy uint32) int32
+TEXT runtime·vdsoCall_zx_vmo_set_cache_policy(SB),NOSPLIT,$0-12
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ MOVD g_m(g), R21
+ MOVD LR, m_vdsoPC(R21)
+ MOVD RSP, R20
+ MOVD R20, m_vdsoSP(R21)
+ MOVW handle+0(FP), R0
+ MOVW cache_policy+4(FP), R1
+ BL vdso_zx_vmo_set_cache_policy(SB)
+ MOVW R0, ret+8(FP)
+ MOVD g_m(g), R21
+ MOVD $0, m_vdsoSP(R21)
+ RET
+
+// func vdsoCall_zx_vmo_replace_as_executable(handle uint32, vmex uint32, out unsafe.Pointer) int32
+TEXT runtime·vdsoCall_zx_vmo_replace_as_executable(SB),NOSPLIT,$0-20
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ MOVD g_m(g), R21
+ MOVD LR, m_vdsoPC(R21)
+ MOVD RSP, R20
+ MOVD R20, m_vdsoSP(R21)
+ MOVW handle+0(FP), R0
+ MOVW vmex+4(FP), R1
+ MOVD out+8(FP), R2
+ BL vdso_zx_vmo_replace_as_executable(SB)
+ MOVW R0, ret+16(FP)
+ MOVD g_m(g), R21
+ MOVD $0, m_vdsoSP(R21)
+ RET
+
+// func vdsoCall_zx_vmar_allocate(parent_vmar uint32, options uint32, offset uint64, size uint64, child_vmar unsafe.Pointer, child_addr unsafe.Pointer) int32
+TEXT runtime·vdsoCall_zx_vmar_allocate(SB),NOSPLIT,$0-44
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ MOVD g_m(g), R21
+ MOVD LR, m_vdsoPC(R21)
+ MOVD RSP, R20
+ MOVD R20, m_vdsoSP(R21)
+ MOVW parent_vmar+0(FP), R0
+ MOVW options+4(FP), R1
+ MOVD offset+8(FP), R2
+ MOVD size+16(FP), R3
+ MOVD child_vmar+24(FP), R4
+ MOVD child_addr+32(FP), R5
+ BL vdso_zx_vmar_allocate(SB)
+ MOVW R0, ret+40(FP)
+ MOVD g_m(g), R21
+ MOVD $0, m_vdsoSP(R21)
+ RET
+
+// func vdsoCall_zx_vmar_destroy(handle uint32) int32
+TEXT runtime·vdsoCall_zx_vmar_destroy(SB),NOSPLIT,$0-12
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ MOVD g_m(g), R21
+ MOVD LR, m_vdsoPC(R21)
+ MOVD RSP, R20
+ MOVD R20, m_vdsoSP(R21)
+ MOVW handle+0(FP), R0
+ BL vdso_zx_vmar_destroy(SB)
+ MOVW R0, ret+8(FP)
+ MOVD g_m(g), R21
+ MOVD $0, m_vdsoSP(R21)
+ RET
+
+// func vdsoCall_zx_vmar_map(handle uint32, options uint32, vmar_offset uint64, vmo uint32, vmo_offset uint64, len uint64, mapped_addr unsafe.Pointer) int32
+TEXT runtime·vdsoCall_zx_vmar_map(SB),NOSPLIT,$0-52
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ MOVD g_m(g), R21
+ MOVD LR, m_vdsoPC(R21)
+ MOVD RSP, R20
+ MOVD R20, m_vdsoSP(R21)
+ MOVW handle+0(FP), R0
+ MOVW options+4(FP), R1
+ MOVD vmar_offset+8(FP), R2
+ MOVW vmo+16(FP), R3
+ MOVD vmo_offset+24(FP), R4
+ MOVD len+32(FP), R5
+ MOVD mapped_addr+40(FP), R6
+ BL vdso_zx_vmar_map(SB)
+ MOVW R0, ret+48(FP)
+ MOVD g_m(g), R21
+ MOVD $0, m_vdsoSP(R21)
+ RET
+
+// func vdsoCall_zx_vmar_unmap(handle uint32, addr uintptr, len uint64) int32
+TEXT runtime·vdsoCall_zx_vmar_unmap(SB),NOSPLIT,$0-28
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ MOVD g_m(g), R21
+ MOVD LR, m_vdsoPC(R21)
+ MOVD RSP, R20
+ MOVD R20, m_vdsoSP(R21)
+ MOVW handle+0(FP), R0
+ MOVD addr+8(FP), R1
+ MOVD len+16(FP), R2
+ BL vdso_zx_vmar_unmap(SB)
+ MOVW R0, ret+24(FP)
+ MOVD g_m(g), R21
+ MOVD $0, m_vdsoSP(R21)
+ RET
+
+// func vdsoCall_zx_vmar_protect(handle uint32, options uint32, addr uintptr, len uint64) int32
+TEXT runtime·vdsoCall_zx_vmar_protect(SB),NOSPLIT,$0-28
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ MOVD g_m(g), R21
+ MOVD LR, m_vdsoPC(R21)
+ MOVD RSP, R20
+ MOVD R20, m_vdsoSP(R21)
+ MOVW handle+0(FP), R0
+ MOVW options+4(FP), R1
+ MOVD addr+8(FP), R2
+ MOVD len+16(FP), R3
+ BL vdso_zx_vmar_protect(SB)
+ MOVW R0, ret+24(FP)
+ MOVD g_m(g), R21
+ MOVD $0, m_vdsoSP(R21)
+ RET
+
+// func vdsoCall_zx_cprng_draw_once(buffer unsafe.Pointer, buffer_size uint) int32
+TEXT runtime·vdsoCall_zx_cprng_draw_once(SB),NOSPLIT,$0-20
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ MOVD g_m(g), R21
+ MOVD LR, m_vdsoPC(R21)
+ MOVD RSP, R20
+ MOVD R20, m_vdsoSP(R21)
+ MOVD buffer+0(FP), R0
+ MOVD buffer_size+8(FP), R1
+ BL vdso_zx_cprng_draw_once(SB)
+ MOVW R0, ret+16(FP)
+ MOVD g_m(g), R21
+ MOVD $0, m_vdsoSP(R21)
+ RET
+
+// func vdsoCall_zx_cprng_draw(buffer unsafe.Pointer, buffer_size uint)
+TEXT runtime·vdsoCall_zx_cprng_draw(SB),NOSPLIT,$0-16
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ MOVD g_m(g), R21
+ MOVD LR, m_vdsoPC(R21)
+ MOVD RSP, R20
+ MOVD R20, m_vdsoSP(R21)
+ MOVD buffer+0(FP), R0
+ MOVD buffer_size+8(FP), R1
+ BL vdso_zx_cprng_draw(SB)
+ MOVD g_m(g), R21
+ MOVD $0, m_vdsoSP(R21)
+ RET
+
+// func vdsoCall_zx_cprng_add_entropy(buffer unsafe.Pointer, buffer_size uint) int32
+TEXT runtime·vdsoCall_zx_cprng_add_entropy(SB),NOSPLIT,$0-20
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ MOVD g_m(g), R21
+ MOVD LR, m_vdsoPC(R21)
+ MOVD RSP, R20
+ MOVD R20, m_vdsoSP(R21)
+ MOVD buffer+0(FP), R0
+ MOVD buffer_size+8(FP), R1
+ BL vdso_zx_cprng_add_entropy(SB)
+ MOVW R0, ret+16(FP)
+ MOVD g_m(g), R21
+ MOVD $0, m_vdsoSP(R21)
+ RET
+
+// func vdsoCall_zx_fifo_create(elem_count uint, elem_size uint, options uint32, out0 unsafe.Pointer, out1 unsafe.Pointer) int32
+TEXT runtime·vdsoCall_zx_fifo_create(SB),NOSPLIT,$0-44
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ MOVD g_m(g), R21
+ MOVD LR, m_vdsoPC(R21)
+ MOVD RSP, R20
+ MOVD R20, m_vdsoSP(R21)
+ MOVD elem_count+0(FP), R0
+ MOVD elem_size+8(FP), R1
+ MOVW options+16(FP), R2
+ MOVD out0+24(FP), R3
+ MOVD out1+32(FP), R4
+ BL vdso_zx_fifo_create(SB)
+ MOVW R0, ret+40(FP)
+ MOVD g_m(g), R21
+ MOVD $0, m_vdsoSP(R21)
+ RET
+
+// func vdsoCall_zx_fifo_read(handle uint32, elem_size uint, data unsafe.Pointer, count uint, actual_count unsafe.Pointer) int32
+TEXT runtime·vdsoCall_zx_fifo_read(SB),NOSPLIT,$0-44
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ MOVD g_m(g), R21
+ MOVD LR, m_vdsoPC(R21)
+ MOVD RSP, R20
+ MOVD R20, m_vdsoSP(R21)
+ MOVW handle+0(FP), R0
+ MOVD elem_size+8(FP), R1
+ MOVD data+16(FP), R2
+ MOVD count+24(FP), R3
+ MOVD actual_count+32(FP), R4
+ BL vdso_zx_fifo_read(SB)
+ MOVW R0, ret+40(FP)
+ MOVD g_m(g), R21
+ MOVD $0, m_vdsoSP(R21)
+ RET
+
+// func vdsoCall_zx_fifo_write(handle uint32, elem_size uint, data unsafe.Pointer, count uint, actual_count unsafe.Pointer) int32
+TEXT runtime·vdsoCall_zx_fifo_write(SB),NOSPLIT,$0-44
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ MOVD g_m(g), R21
+ MOVD LR, m_vdsoPC(R21)
+ MOVD RSP, R20
+ MOVD R20, m_vdsoSP(R21)
+ MOVW handle+0(FP), R0
+ MOVD elem_size+8(FP), R1
+ MOVD data+16(FP), R2
+ MOVD count+24(FP), R3
+ MOVD actual_count+32(FP), R4
+ BL vdso_zx_fifo_write(SB)
+ MOVW R0, ret+40(FP)
+ MOVD g_m(g), R21
+ MOVD $0, m_vdsoSP(R21)
+ RET
+
+// func vdsoCall_zx_profile_create(root_job uint32, profile unsafe.Pointer, out unsafe.Pointer) int32
+TEXT runtime·vdsoCall_zx_profile_create(SB),NOSPLIT,$0-28
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ MOVD g_m(g), R21
+ MOVD LR, m_vdsoPC(R21)
+ MOVD RSP, R20
+ MOVD R20, m_vdsoSP(R21)
+ MOVW root_job+0(FP), R0
+ MOVD profile+8(FP), R1
+ MOVD out+16(FP), R2
+ BL vdso_zx_profile_create(SB)
+ MOVW R0, ret+24(FP)
+ MOVD g_m(g), R21
+ MOVD $0, m_vdsoSP(R21)
+ RET
+
+// func vdsoCall_zx_vmar_unmap_handle_close_thread_exit(vmar_handle uint32, addr uintptr, size uint, close_handle uint32) int32
+TEXT runtime·vdsoCall_zx_vmar_unmap_handle_close_thread_exit(SB),NOSPLIT,$0-36
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ MOVD g_m(g), R21
+ MOVD LR, m_vdsoPC(R21)
+ MOVD RSP, R20
+ MOVD R20, m_vdsoSP(R21)
+ MOVW vmar_handle+0(FP), R0
+ MOVD addr+8(FP), R1
+ MOVD size+16(FP), R2
+ MOVW close_handle+24(FP), R3
+ BL vdso_zx_vmar_unmap_handle_close_thread_exit(SB)
+ MOVW R0, ret+32(FP)
+ MOVD g_m(g), R21
+ MOVD $0, m_vdsoSP(R21)
+ RET
+
+// func vdsoCall_zx_futex_wake_handle_close_thread_exit(value_ptr unsafe.Pointer, wake_count uint32, new_value int32, close_handle uint32)
+TEXT runtime·vdsoCall_zx_futex_wake_handle_close_thread_exit(SB),NOSPLIT,$0-24
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ MOVD g_m(g), R21
+ MOVD LR, m_vdsoPC(R21)
+ MOVD RSP, R20
+ MOVD R20, m_vdsoSP(R21)
+ MOVD value_ptr+0(FP), R0
+ MOVW wake_count+8(FP), R1
+ MOVW new_value+12(FP), R2
+ MOVW close_handle+16(FP), R3
+ BL vdso_zx_futex_wake_handle_close_thread_exit(SB)
+ MOVD g_m(g), R21
+ MOVD $0, m_vdsoSP(R21)
+ RET
+
+// func vdsoCall_zx_debuglog_create(resource uint32, options uint32, out unsafe.Pointer) int32
+TEXT runtime·vdsoCall_zx_debuglog_create(SB),NOSPLIT,$0-20
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ MOVD g_m(g), R21
+ MOVD LR, m_vdsoPC(R21)
+ MOVD RSP, R20
+ MOVD R20, m_vdsoSP(R21)
+ MOVW resource+0(FP), R0
+ MOVW options+4(FP), R1
+ MOVD out+8(FP), R2
+ BL vdso_zx_debuglog_create(SB)
+ MOVW R0, ret+16(FP)
+ MOVD g_m(g), R21
+ MOVD $0, m_vdsoSP(R21)
+ RET
+
+// func vdsoCall_zx_debuglog_write(handle uint32, options uint32, buffer unsafe.Pointer, buffer_size uint) int32
+TEXT runtime·vdsoCall_zx_debuglog_write(SB),NOSPLIT,$0-28
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ MOVD g_m(g), R21
+ MOVD LR, m_vdsoPC(R21)
+ MOVD RSP, R20
+ MOVD R20, m_vdsoSP(R21)
+ MOVW handle+0(FP), R0
+ MOVW options+4(FP), R1
+ MOVD buffer+8(FP), R2
+ MOVD buffer_size+16(FP), R3
+ BL vdso_zx_debuglog_write(SB)
+ MOVW R0, ret+24(FP)
+ MOVD g_m(g), R21
+ MOVD $0, m_vdsoSP(R21)
+ RET
+
+// func vdsoCall_zx_debuglog_read(handle uint32, options uint32, buffer unsafe.Pointer, buffer_size uint) int32
+TEXT runtime·vdsoCall_zx_debuglog_read(SB),NOSPLIT,$0-28
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ MOVD g_m(g), R21
+ MOVD LR, m_vdsoPC(R21)
+ MOVD RSP, R20
+ MOVD R20, m_vdsoSP(R21)
+ MOVW handle+0(FP), R0
+ MOVW options+4(FP), R1
+ MOVD buffer+8(FP), R2
+ MOVD buffer_size+16(FP), R3
+ BL vdso_zx_debuglog_read(SB)
+ MOVW R0, ret+24(FP)
+ MOVD g_m(g), R21
+ MOVD $0, m_vdsoSP(R21)
+ RET
+
+// func vdsoCall_zx_ktrace_read(handle uint32, data unsafe.Pointer, offset uint32, data_size uint, actual unsafe.Pointer) int32
+TEXT runtime·vdsoCall_zx_ktrace_read(SB),NOSPLIT,$0-44
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ MOVD g_m(g), R21
+ MOVD LR, m_vdsoPC(R21)
+ MOVD RSP, R20
+ MOVD R20, m_vdsoSP(R21)
+ MOVW handle+0(FP), R0
+ MOVD data+8(FP), R1
+ MOVW offset+16(FP), R2
+ MOVD data_size+24(FP), R3
+ MOVD actual+32(FP), R4
+ BL vdso_zx_ktrace_read(SB)
+ MOVW R0, ret+40(FP)
+ MOVD g_m(g), R21
+ MOVD $0, m_vdsoSP(R21)
+ RET
+
+// func vdsoCall_zx_ktrace_control(handle uint32, action uint32, options uint32, ptr unsafe.Pointer) int32
+TEXT runtime·vdsoCall_zx_ktrace_control(SB),NOSPLIT,$0-28
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ MOVD g_m(g), R21
+ MOVD LR, m_vdsoPC(R21)
+ MOVD RSP, R20
+ MOVD R20, m_vdsoSP(R21)
+ MOVW handle+0(FP), R0
+ MOVW action+4(FP), R1
+ MOVW options+8(FP), R2
+ MOVD ptr+16(FP), R3
+ BL vdso_zx_ktrace_control(SB)
+ MOVW R0, ret+24(FP)
+ MOVD g_m(g), R21
+ MOVD $0, m_vdsoSP(R21)
+ RET
+
+// func vdsoCall_zx_ktrace_write(handle uint32, id uint32, arg0 uint32, arg1 uint32) int32
+TEXT runtime·vdsoCall_zx_ktrace_write(SB),NOSPLIT,$0-20
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ MOVD g_m(g), R21
+ MOVD LR, m_vdsoPC(R21)
+ MOVD RSP, R20
+ MOVD R20, m_vdsoSP(R21)
+ MOVW handle+0(FP), R0
+ MOVW id+4(FP), R1
+ MOVW arg0+8(FP), R2
+ MOVW arg1+12(FP), R3
+ BL vdso_zx_ktrace_write(SB)
+ MOVW R0, ret+16(FP)
+ MOVD g_m(g), R21
+ MOVD $0, m_vdsoSP(R21)
+ RET
+
+// func vdsoCall_zx_mtrace_control(handle uint32, kind uint32, action uint32, options uint32, ptr unsafe.Pointer, ptr_size uint) int32
+TEXT runtime·vdsoCall_zx_mtrace_control(SB),NOSPLIT,$0-36
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ MOVD g_m(g), R21
+ MOVD LR, m_vdsoPC(R21)
+ MOVD RSP, R20
+ MOVD R20, m_vdsoSP(R21)
+ MOVW handle+0(FP), R0
+ MOVW kind+4(FP), R1
+ MOVW action+8(FP), R2
+ MOVW options+12(FP), R3
+ MOVD ptr+16(FP), R4
+ MOVD ptr_size+24(FP), R5
+ BL vdso_zx_mtrace_control(SB)
+ MOVW R0, ret+32(FP)
+ MOVD g_m(g), R21
+ MOVD $0, m_vdsoSP(R21)
+ RET
+
+// func vdsoCall_zx_debug_read(handle uint32, buffer unsafe.Pointer, buffer_size unsafe.Pointer) int32
+TEXT runtime·vdsoCall_zx_debug_read(SB),NOSPLIT,$0-28
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ MOVD g_m(g), R21
+ MOVD LR, m_vdsoPC(R21)
+ MOVD RSP, R20
+ MOVD R20, m_vdsoSP(R21)
+ MOVW handle+0(FP), R0
+ MOVD buffer+8(FP), R1
+ MOVD buffer_size+16(FP), R2
+ BL vdso_zx_debug_read(SB)
+ MOVW R0, ret+24(FP)
+ MOVD g_m(g), R21
+ MOVD $0, m_vdsoSP(R21)
+ RET
+
+// func vdsoCall_zx_debug_write(buffer unsafe.Pointer, buffer_size uint) int32
+TEXT runtime·vdsoCall_zx_debug_write(SB),NOSPLIT,$0-20
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ MOVD g_m(g), R21
+ MOVD LR, m_vdsoPC(R21)
+ MOVD RSP, R20
+ MOVD R20, m_vdsoSP(R21)
+ MOVD buffer+0(FP), R0
+ MOVD buffer_size+8(FP), R1
+ BL vdso_zx_debug_write(SB)
+ MOVW R0, ret+16(FP)
+ MOVD g_m(g), R21
+ MOVD $0, m_vdsoSP(R21)
+ RET
+
+// func vdsoCall_zx_debug_send_command(resource uint32, buffer unsafe.Pointer, buffer_size uint) int32
+TEXT runtime·vdsoCall_zx_debug_send_command(SB),NOSPLIT,$0-28
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ MOVD g_m(g), R21
+ MOVD LR, m_vdsoPC(R21)
+ MOVD RSP, R20
+ MOVD R20, m_vdsoSP(R21)
+ MOVW resource+0(FP), R0
+ MOVD buffer+8(FP), R1
+ MOVD buffer_size+16(FP), R2
+ BL vdso_zx_debug_send_command(SB)
+ MOVW R0, ret+24(FP)
+ MOVD g_m(g), R21
+ MOVD $0, m_vdsoSP(R21)
+ RET
+
+// func vdsoCall_zx_interrupt_create(src_obj uint32, src_num uint32, options uint32, out_handle unsafe.Pointer) int32
+TEXT runtime·vdsoCall_zx_interrupt_create(SB),NOSPLIT,$0-28
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ MOVD g_m(g), R21
+ MOVD LR, m_vdsoPC(R21)
+ MOVD RSP, R20
+ MOVD R20, m_vdsoSP(R21)
+ MOVW src_obj+0(FP), R0
+ MOVW src_num+4(FP), R1
+ MOVW options+8(FP), R2
+ MOVD out_handle+16(FP), R3
+ BL vdso_zx_interrupt_create(SB)
+ MOVW R0, ret+24(FP)
+ MOVD g_m(g), R21
+ MOVD $0, m_vdsoSP(R21)
+ RET
+
+// func vdsoCall_zx_interrupt_bind(handle uint32, port_handle uint32, key uint64, options uint32) int32
+TEXT runtime·vdsoCall_zx_interrupt_bind(SB),NOSPLIT,$0-28
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ MOVD g_m(g), R21
+ MOVD LR, m_vdsoPC(R21)
+ MOVD RSP, R20
+ MOVD R20, m_vdsoSP(R21)
+ MOVW handle+0(FP), R0
+ MOVW port_handle+4(FP), R1
+ MOVD key+8(FP), R2
+ MOVW options+16(FP), R3
+ BL vdso_zx_interrupt_bind(SB)
+ MOVW R0, ret+24(FP)
+ MOVD g_m(g), R21
+ MOVD $0, m_vdsoSP(R21)
+ RET
+
+// func vdsoCall_zx_interrupt_wait(handle uint32, out_timestamp unsafe.Pointer) int32
+TEXT runtime·vdsoCall_zx_interrupt_wait(SB),NOSPLIT,$0-20
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ MOVD g_m(g), R21
+ MOVD LR, m_vdsoPC(R21)
+ MOVD RSP, R20
+ MOVD R20, m_vdsoSP(R21)
+ MOVW handle+0(FP), R0
+ MOVD out_timestamp+8(FP), R1
+ BL vdso_zx_interrupt_wait(SB)
+ MOVW R0, ret+16(FP)
+ MOVD g_m(g), R21
+ MOVD $0, m_vdsoSP(R21)
+ RET
+
+// func vdsoCall_zx_interrupt_destroy(handle uint32) int32
+TEXT runtime·vdsoCall_zx_interrupt_destroy(SB),NOSPLIT,$0-12
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ MOVD g_m(g), R21
+ MOVD LR, m_vdsoPC(R21)
+ MOVD RSP, R20
+ MOVD R20, m_vdsoSP(R21)
+ MOVW handle+0(FP), R0
+ BL vdso_zx_interrupt_destroy(SB)
+ MOVW R0, ret+8(FP)
+ MOVD g_m(g), R21
+ MOVD $0, m_vdsoSP(R21)
+ RET
+
+// func vdsoCall_zx_interrupt_ack(handle uint32) int32
+TEXT runtime·vdsoCall_zx_interrupt_ack(SB),NOSPLIT,$0-12
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ MOVD g_m(g), R21
+ MOVD LR, m_vdsoPC(R21)
+ MOVD RSP, R20
+ MOVD R20, m_vdsoSP(R21)
+ MOVW handle+0(FP), R0
+ BL vdso_zx_interrupt_ack(SB)
+ MOVW R0, ret+8(FP)
+ MOVD g_m(g), R21
+ MOVD $0, m_vdsoSP(R21)
+ RET
+
+// func vdsoCall_zx_interrupt_trigger(handle uint32, options uint32, timestamp int64) int32
+TEXT runtime·vdsoCall_zx_interrupt_trigger(SB),NOSPLIT,$0-20
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ MOVD g_m(g), R21
+ MOVD LR, m_vdsoPC(R21)
+ MOVD RSP, R20
+ MOVD R20, m_vdsoSP(R21)
+ MOVW handle+0(FP), R0
+ MOVW options+4(FP), R1
+ MOVD timestamp+8(FP), R2
+ BL vdso_zx_interrupt_trigger(SB)
+ MOVW R0, ret+16(FP)
+ MOVD g_m(g), R21
+ MOVD $0, m_vdsoSP(R21)
+ RET
+
+// func vdsoCall_zx_interrupt_bind_vcpu(handle uint32, vcpu uint32, options uint32) int32
+TEXT runtime·vdsoCall_zx_interrupt_bind_vcpu(SB),NOSPLIT,$0-20
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ MOVD g_m(g), R21
+ MOVD LR, m_vdsoPC(R21)
+ MOVD RSP, R20
+ MOVD R20, m_vdsoSP(R21)
+ MOVW handle+0(FP), R0
+ MOVW vcpu+4(FP), R1
+ MOVW options+8(FP), R2
+ BL vdso_zx_interrupt_bind_vcpu(SB)
+ MOVW R0, ret+16(FP)
+ MOVD g_m(g), R21
+ MOVD $0, m_vdsoSP(R21)
+ RET
+
+// func vdsoCall_zx_ioports_request(resource uint32, io_addr uint16, len uint32) int32
+TEXT runtime·vdsoCall_zx_ioports_request(SB),NOSPLIT,$0-20
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ MOVD g_m(g), R21
+ MOVD LR, m_vdsoPC(R21)
+ MOVD RSP, R20
+ MOVD R20, m_vdsoSP(R21)
+ MOVW resource+0(FP), R0
+ MOVD io_addr+4(FP), R1
+ MOVW len+8(FP), R2
+ BL vdso_zx_ioports_request(SB)
+ MOVW R0, ret+16(FP)
+ MOVD g_m(g), R21
+ MOVD $0, m_vdsoSP(R21)
+ RET
+
+// func vdsoCall_zx_vmo_create_contiguous(bti uint32, size uint, alignment_log2 uint32, out unsafe.Pointer) int32
+TEXT runtime·vdsoCall_zx_vmo_create_contiguous(SB),NOSPLIT,$0-36
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ MOVD g_m(g), R21
+ MOVD LR, m_vdsoPC(R21)
+ MOVD RSP, R20
+ MOVD R20, m_vdsoSP(R21)
+ MOVW bti+0(FP), R0
+ MOVD size+8(FP), R1
+ MOVW alignment_log2+16(FP), R2
+ MOVD out+24(FP), R3
+ BL vdso_zx_vmo_create_contiguous(SB)
+ MOVW R0, ret+32(FP)
+ MOVD g_m(g), R21
+ MOVD $0, m_vdsoSP(R21)
+ RET
+
+// func vdsoCall_zx_vmo_create_physical(resource uint32, paddr uintptr, size uint, out unsafe.Pointer) int32
+TEXT runtime·vdsoCall_zx_vmo_create_physical(SB),NOSPLIT,$0-36
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ MOVD g_m(g), R21
+ MOVD LR, m_vdsoPC(R21)
+ MOVD RSP, R20
+ MOVD R20, m_vdsoSP(R21)
+ MOVW resource+0(FP), R0
+ MOVD paddr+8(FP), R1
+ MOVD size+16(FP), R2
+ MOVD out+24(FP), R3
+ BL vdso_zx_vmo_create_physical(SB)
+ MOVW R0, ret+32(FP)
+ MOVD g_m(g), R21
+ MOVD $0, m_vdsoSP(R21)
+ RET
+
+// func vdsoCall_zx_iommu_create(resource uint32, typ uint32, desc unsafe.Pointer, desc_size uint, out unsafe.Pointer) int32
+TEXT runtime·vdsoCall_zx_iommu_create(SB),NOSPLIT,$0-36
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ MOVD g_m(g), R21
+ MOVD LR, m_vdsoPC(R21)
+ MOVD RSP, R20
+ MOVD R20, m_vdsoSP(R21)
+ MOVW resource+0(FP), R0
+ MOVW typ+4(FP), R1
+ MOVD desc+8(FP), R2
+ MOVD desc_size+16(FP), R3
+ MOVD out+24(FP), R4
+ BL vdso_zx_iommu_create(SB)
+ MOVW R0, ret+32(FP)
+ MOVD g_m(g), R21
+ MOVD $0, m_vdsoSP(R21)
+ RET
+
+// func vdsoCall_zx_bti_create(iommu uint32, options uint32, bti_id uint64, out unsafe.Pointer) int32
+TEXT runtime·vdsoCall_zx_bti_create(SB),NOSPLIT,$0-28
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ MOVD g_m(g), R21
+ MOVD LR, m_vdsoPC(R21)
+ MOVD RSP, R20
+ MOVD R20, m_vdsoSP(R21)
+ MOVW iommu+0(FP), R0
+ MOVW options+4(FP), R1
+ MOVD bti_id+8(FP), R2
+ MOVD out+16(FP), R3
+ BL vdso_zx_bti_create(SB)
+ MOVW R0, ret+24(FP)
+ MOVD g_m(g), R21
+ MOVD $0, m_vdsoSP(R21)
+ RET
+
+// func vdsoCall_zx_bti_pin(handle uint32, options uint32, vmo uint32, offset uint64, size uint64, addrs unsafe.Pointer, addrs_count uint, pmt unsafe.Pointer) int32
+TEXT runtime·vdsoCall_zx_bti_pin(SB),NOSPLIT,$0-60
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ MOVD g_m(g), R21
+ MOVD LR, m_vdsoPC(R21)
+ MOVD RSP, R20
+ MOVD R20, m_vdsoSP(R21)
+ MOVW handle+0(FP), R0
+ MOVW options+4(FP), R1
+ MOVW vmo+8(FP), R2
+ MOVD offset+16(FP), R3
+ MOVD size+24(FP), R4
+ MOVD addrs+32(FP), R5
+ MOVD addrs_count+40(FP), R6
+ MOVD pmt+48(FP), R7
+ BL vdso_zx_bti_pin(SB)
+ MOVW R0, ret+56(FP)
+ MOVD g_m(g), R21
+ MOVD $0, m_vdsoSP(R21)
+ RET
+
+// func vdsoCall_zx_bti_release_quarantine(handle uint32) int32
+TEXT runtime·vdsoCall_zx_bti_release_quarantine(SB),NOSPLIT,$0-12
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ MOVD g_m(g), R21
+ MOVD LR, m_vdsoPC(R21)
+ MOVD RSP, R20
+ MOVD R20, m_vdsoSP(R21)
+ MOVW handle+0(FP), R0
+ BL vdso_zx_bti_release_quarantine(SB)
+ MOVW R0, ret+8(FP)
+ MOVD g_m(g), R21
+ MOVD $0, m_vdsoSP(R21)
+ RET
+
+// func vdsoCall_zx_pmt_unpin(handle uint32) int32
+TEXT runtime·vdsoCall_zx_pmt_unpin(SB),NOSPLIT,$0-12
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ MOVD g_m(g), R21
+ MOVD LR, m_vdsoPC(R21)
+ MOVD RSP, R20
+ MOVD R20, m_vdsoSP(R21)
+ MOVW handle+0(FP), R0
+ BL vdso_zx_pmt_unpin(SB)
+ MOVW R0, ret+8(FP)
+ MOVD g_m(g), R21
+ MOVD $0, m_vdsoSP(R21)
+ RET
+
+// func vdsoCall_zx_framebuffer_get_info(resource uint32, format unsafe.Pointer, width unsafe.Pointer, height unsafe.Pointer, stride unsafe.Pointer) int32
+TEXT runtime·vdsoCall_zx_framebuffer_get_info(SB),NOSPLIT,$0-44
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ MOVD g_m(g), R21
+ MOVD LR, m_vdsoPC(R21)
+ MOVD RSP, R20
+ MOVD R20, m_vdsoSP(R21)
+ MOVW resource+0(FP), R0
+ MOVD format+8(FP), R1
+ MOVD width+16(FP), R2
+ MOVD height+24(FP), R3
+ MOVD stride+32(FP), R4
+ BL vdso_zx_framebuffer_get_info(SB)
+ MOVW R0, ret+40(FP)
+ MOVD g_m(g), R21
+ MOVD $0, m_vdsoSP(R21)
+ RET
+
+// func vdsoCall_zx_framebuffer_set_range(resource uint32, vmo uint32, len uint32, format uint32, width uint32, height uint32, stride uint32) int32
+TEXT runtime·vdsoCall_zx_framebuffer_set_range(SB),NOSPLIT,$0-36
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ MOVD g_m(g), R21
+ MOVD LR, m_vdsoPC(R21)
+ MOVD RSP, R20
+ MOVD R20, m_vdsoSP(R21)
+ MOVW resource+0(FP), R0
+ MOVW vmo+4(FP), R1
+ MOVW len+8(FP), R2
+ MOVW format+12(FP), R3
+ MOVW width+16(FP), R4
+ MOVW height+20(FP), R5
+ MOVW stride+24(FP), R6
+ BL vdso_zx_framebuffer_set_range(SB)
+ MOVW R0, ret+32(FP)
+ MOVD g_m(g), R21
+ MOVD $0, m_vdsoSP(R21)
+ RET
+
+// func vdsoCall_zx_pc_firmware_tables(handle uint32, acpi_rsdp unsafe.Pointer, smbios unsafe.Pointer) int32
+TEXT runtime·vdsoCall_zx_pc_firmware_tables(SB),NOSPLIT,$0-28
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ MOVD g_m(g), R21
+ MOVD LR, m_vdsoPC(R21)
+ MOVD RSP, R20
+ MOVD R20, m_vdsoSP(R21)
+ MOVW handle+0(FP), R0
+ MOVD acpi_rsdp+8(FP), R1
+ MOVD smbios+16(FP), R2
+ BL vdso_zx_pc_firmware_tables(SB)
+ MOVW R0, ret+24(FP)
+ MOVD g_m(g), R21
+ MOVD $0, m_vdsoSP(R21)
+ RET
+
+// func vdsoCall_zx_smc_call(handle uint32, parameters unsafe.Pointer, out_smc_result unsafe.Pointer) int32
+TEXT runtime·vdsoCall_zx_smc_call(SB),NOSPLIT,$0-28
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ MOVD g_m(g), R21
+ MOVD LR, m_vdsoPC(R21)
+ MOVD RSP, R20
+ MOVD R20, m_vdsoSP(R21)
+ MOVW handle+0(FP), R0
+ MOVD parameters+8(FP), R1
+ MOVD out_smc_result+16(FP), R2
+ BL vdso_zx_smc_call(SB)
+ MOVW R0, ret+24(FP)
+ MOVD g_m(g), R21
+ MOVD $0, m_vdsoSP(R21)
+ RET
+
+// func vdsoCall_zx_resource_create(parent_rsrc uint32, options uint32, base uint64, size uint, name unsafe.Pointer, name_size uint, resource_out unsafe.Pointer) int32
+TEXT runtime·vdsoCall_zx_resource_create(SB),NOSPLIT,$0-52
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ MOVD g_m(g), R21
+ MOVD LR, m_vdsoPC(R21)
+ MOVD RSP, R20
+ MOVD R20, m_vdsoSP(R21)
+ MOVW parent_rsrc+0(FP), R0
+ MOVW options+4(FP), R1
+ MOVD base+8(FP), R2
+ MOVD size+16(FP), R3
+ MOVD name+24(FP), R4
+ MOVD name_size+32(FP), R5
+ MOVD resource_out+40(FP), R6
+ BL vdso_zx_resource_create(SB)
+ MOVW R0, ret+48(FP)
+ MOVD g_m(g), R21
+ MOVD $0, m_vdsoSP(R21)
+ RET
+
+// func vdsoCall_zx_system_mexec(resource uint32, kernel_vmo uint32, bootimage_vmo uint32) int32
+TEXT runtime·vdsoCall_zx_system_mexec(SB),NOSPLIT,$0-20
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ MOVD g_m(g), R21
+ MOVD LR, m_vdsoPC(R21)
+ MOVD RSP, R20
+ MOVD R20, m_vdsoSP(R21)
+ MOVW resource+0(FP), R0
+ MOVW kernel_vmo+4(FP), R1
+ MOVW bootimage_vmo+8(FP), R2
+ BL vdso_zx_system_mexec(SB)
+ MOVW R0, ret+16(FP)
+ MOVD g_m(g), R21
+ MOVD $0, m_vdsoSP(R21)
+ RET
+
+// func vdsoCall_zx_system_mexec_payload_get(resource uint32, buffer unsafe.Pointer, buffer_size uint) int32
+TEXT runtime·vdsoCall_zx_system_mexec_payload_get(SB),NOSPLIT,$0-28
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ MOVD g_m(g), R21
+ MOVD LR, m_vdsoPC(R21)
+ MOVD RSP, R20
+ MOVD R20, m_vdsoSP(R21)
+ MOVW resource+0(FP), R0
+ MOVD buffer+8(FP), R1
+ MOVD buffer_size+16(FP), R2
+ BL vdso_zx_system_mexec_payload_get(SB)
+ MOVW R0, ret+24(FP)
+ MOVD g_m(g), R21
+ MOVD $0, m_vdsoSP(R21)
+ RET
+
+// func vdsoCall_zx_system_powerctl(resource uint32, cmd uint32, arg unsafe.Pointer) int32
+TEXT runtime·vdsoCall_zx_system_powerctl(SB),NOSPLIT,$0-20
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ MOVD g_m(g), R21
+ MOVD LR, m_vdsoPC(R21)
+ MOVD RSP, R20
+ MOVD R20, m_vdsoSP(R21)
+ MOVW resource+0(FP), R0
+ MOVW cmd+4(FP), R1
+ MOVD arg+8(FP), R2
+ BL vdso_zx_system_powerctl(SB)
+ MOVW R0, ret+16(FP)
+ MOVD g_m(g), R21
+ MOVD $0, m_vdsoSP(R21)
+ RET
+
+// func vdsoCall_zx_pager_create(options uint32, out unsafe.Pointer) int32
+TEXT runtime·vdsoCall_zx_pager_create(SB),NOSPLIT,$0-20
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ MOVD g_m(g), R21
+ MOVD LR, m_vdsoPC(R21)
+ MOVD RSP, R20
+ MOVD R20, m_vdsoSP(R21)
+ MOVW options+0(FP), R0
+ MOVD out+8(FP), R1
+ BL vdso_zx_pager_create(SB)
+ MOVW R0, ret+16(FP)
+ MOVD g_m(g), R21
+ MOVD $0, m_vdsoSP(R21)
+ RET
+
+// func vdsoCall_zx_pager_create_vmo(pager uint32, options uint32, port uint32, key uint64, size uint64, out unsafe.Pointer) int32
+TEXT runtime·vdsoCall_zx_pager_create_vmo(SB),NOSPLIT,$0-44
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ MOVD g_m(g), R21
+ MOVD LR, m_vdsoPC(R21)
+ MOVD RSP, R20
+ MOVD R20, m_vdsoSP(R21)
+ MOVW pager+0(FP), R0
+ MOVW options+4(FP), R1
+ MOVW port+8(FP), R2
+ MOVD key+16(FP), R3
+ MOVD size+24(FP), R4
+ MOVD out+32(FP), R5
+ BL vdso_zx_pager_create_vmo(SB)
+ MOVW R0, ret+40(FP)
+ MOVD g_m(g), R21
+ MOVD $0, m_vdsoSP(R21)
+ RET
+
+// func vdsoCall_zx_pager_detach_vmo(pager uint32, vmo uint32) int32
+TEXT runtime·vdsoCall_zx_pager_detach_vmo(SB),NOSPLIT,$0-12
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ MOVD g_m(g), R21
+ MOVD LR, m_vdsoPC(R21)
+ MOVD RSP, R20
+ MOVD R20, m_vdsoSP(R21)
+ MOVW pager+0(FP), R0
+ MOVW vmo+4(FP), R1
+ BL vdso_zx_pager_detach_vmo(SB)
+ MOVW R0, ret+8(FP)
+ MOVD g_m(g), R21
+ MOVD $0, m_vdsoSP(R21)
+ RET
+
+// func vdsoCall_zx_pager_supply_pages(pager uint32, pager_vmo uint32, offset uint64, length uint64, aux_vmo uint32, aux_offset uint64) int32
+TEXT runtime·vdsoCall_zx_pager_supply_pages(SB),NOSPLIT,$0-44
+ GO_ARGS
+ NO_LOCAL_POINTERS
+ MOVD g_m(g), R21
+ MOVD LR, m_vdsoPC(R21)
+ MOVD RSP, R20
+ MOVD R20, m_vdsoSP(R21)
+ MOVW pager+0(FP), R0
+ MOVW pager_vmo+4(FP), R1
+ MOVD offset+8(FP), R2
+ MOVD length+16(FP), R3
+ MOVW aux_vmo+24(FP), R4
+ MOVD aux_offset+32(FP), R5
+ BL vdso_zx_pager_supply_pages(SB)
+ MOVW R0, ret+40(FP)
+ MOVD g_m(g), R21
+ MOVD $0, m_vdsoSP(R21)
+ RET
+
diff --git a/src/syscall/dirent.go b/src/syscall/dirent.go
index 5c7af42..0a22c3c 100644
--- a/src/syscall/dirent.go
+++ b/src/syscall/dirent.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build aix darwin dragonfly freebsd js,wasm linux nacl netbsd openbsd solaris
+// +build aix darwin dragonfly freebsd fuchsia js,wasm linux nacl netbsd openbsd solaris
package syscall
diff --git a/src/syscall/env_unix.go b/src/syscall/env_unix.go
index 0b6b711..31359a0 100644
--- a/src/syscall/env_unix.go
+++ b/src/syscall/env_unix.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build aix darwin dragonfly freebsd js,wasm linux nacl netbsd openbsd solaris
+// +build aix darwin dragonfly freebsd fuchsia js,wasm linux nacl netbsd openbsd solaris
// Unix environment variables.
diff --git a/src/syscall/exec_fuchsia.go b/src/syscall/exec_fuchsia.go
new file mode 100644
index 0000000..3904808
--- /dev/null
+++ b/src/syscall/exec_fuchsia.go
@@ -0,0 +1,10 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package syscall
+
+import ()
+
+type SysProcAttr struct {
+}
diff --git a/src/syscall/syscall_fuchsia.go b/src/syscall/syscall_fuchsia.go
new file mode 100644
index 0000000..7ce9eb7
--- /dev/null
+++ b/src/syscall/syscall_fuchsia.go
@@ -0,0 +1,720 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package syscall
+
+import (
+ "errors"
+ "io"
+ "path"
+ "strings"
+ "sync"
+ "unsafe"
+
+ "syscall/zx"
+ "syscall/zx/fdio"
+ fidlIo "syscall/zx/io"
+)
+
+var (
+ Stdin = 0
+ Stdout = 1
+ Stderr = 2
+)
+
+const (
+ FsRightReadable = 0x00000001
+ FsRightWritable = 0x00000002
+ FsRightAdmin = 0x00000004
+ FsRights = FsRightReadable | FsRightWritable | FsRightAdmin
+ FsRightSpace = 0x0000FFFF
+ FsFlagCreate = 0x00010000
+ FsFlagExclusive = 0x00020000
+ FsFlagTruncate = 0x00040000
+ FsFlagDirectory = 0x00080000
+ FsFlagAppend = 0x00100000
+ FsFlagNoRemote = 0x00200000
+ FsFlagPath = 0x00400000
+ FsFlagDescribe = 0x00800000
+ FsFlagPosix = 0x01000000
+ FsFlagNotDirectory = 0x02000000
+ FsFlagCloneSameRights = 0x04000000
+
+ FsFlagsAllowedWithPath = FsFlagPath | FsFlagDirectory |
+ FsFlagNotDirectory | FsFlagDescribe
+)
+
+const (
+ O_RDONLY = 0x0
+ O_WRONLY = 0x1
+ O_RDWR = 0x2
+
+ // Flags which align with ZXIO_FS_*
+ O_ADMIN = FsRightAdmin
+ O_CREAT = FsFlagCreate
+ O_EXCL = FsFlagExclusive
+ O_TRUNC = FsFlagTruncate
+ O_DIRECTORY = FsFlagDirectory
+ O_APPEND = FsFlagAppend
+ O_NOREMOTE = FsFlagNoRemote
+ O_PATH = FsFlagPath
+
+ FdioAlignedFlags = O_ADMIN | O_CREAT | O_EXCL | O_TRUNC | O_DIRECTORY | O_APPEND |
+ O_NOREMOTE | O_PATH
+
+ // Flags which do not align with ZXIO_FS_*
+ O_NONBLOCK = 0x00000010
+ O_DSYNC = 0x00000020
+ O_SYNC = 0x00000040 | O_DSYNC
+ O_RSYNC = O_SYNC
+ O_NOFOLLOW = 0x00000080
+ O_CLOEXEC = 0x00000100
+ O_NOCTTY = 0x00000200
+ O_ASYNC = 0x00000400
+ O_DIRECT = 0x00000800
+ O_LARGEFILE = 0x00001000
+ O_NOATIME = 0x00002000
+ O_TMPFILE = 0x00004000
+)
+
+func FdioFlagsToZxio(flags uint32) (zflags uint32) {
+ perms := uint32(O_RDONLY | O_WRONLY | O_RDWR)
+ switch flags & perms {
+ case O_RDONLY:
+ zflags |= FsRightReadable
+ case O_WRONLY:
+ zflags |= FsRightWritable
+ case O_RDWR:
+ zflags |= FsRightReadable | FsRightWritable
+ }
+
+ zflags |= FsFlagDescribe
+ zflags |= (flags & FdioAlignedFlags)
+ if (zflags & FsFlagPath) == 0 {
+ zflags |= FsFlagPosix
+ } else {
+ zflags &= FsFlagsAllowedWithPath
+ }
+ return zflags
+}
+
+const (
+ S_IFMT = fdio.S_IFMT
+ S_IFDIR = fdio.S_IFDIR
+ S_IFREG = fdio.S_IFREG
+ S_IFIFO = fdio.S_IFIFO
+)
+
+// TODO(crawshaw): generate a zerrors file once cgo is working
+const (
+ EPERM = Errno(0x01)
+ ENOENT = Errno(0x02)
+ EINTR = Errno(0x04)
+ EIO = Errno(0x05)
+ EBADF = Errno(0x09)
+ EACCES = Errno(0x0d)
+ EEXIST = Errno(0x11)
+ ENOTDIR = Errno(0x14)
+ EISDIR = Errno(0x15)
+ EINVAL = Errno(0x16)
+ EMFILE = Errno(0x18)
+ ESPIPE = Errno(0x1d)
+ ENAMETOOLONG = Errno(0x24)
+ ENOTEMPTY = Errno(0x27)
+ ENOPROTOOPT = Errno(0x5c)
+ EOPNOTSUPP = Errno(0x5f)
+ ENOTSUP = EOPNOTSUPP
+ EADDRINUSE = Errno(0x62)
+ EADDRNOTAVAIL = Errno(0x63)
+ ETIMEDOUT = Errno(0x6e)
+ ECONNABORTED = Errno(0x67)
+ EHOSTUNREACH = Errno(0x71)
+ EFUCHSIA = Errno(0xfa)
+)
+
+var EPIPE error = Errno(0x20)
+
+const (
+ SOMAXCONN = 0x80
+)
+
+const (
+ PathMax = 4096
+)
+
+type Stat_t struct {
+ Dev uint64
+ Ino uint64
+ Size uint64
+ CreateTime uint64
+ ModifyTime uint64
+ Mode uint64
+}
+
+func Getpid() (pid int) {
+ // TODO: is ProcHandle process-wide or OS-wide?
+ return int(zx.ProcHandle)
+}
+
+func Getppid() (ppid int) {
+ return 0
+}
+
+func Getuid() (uid int) {
+ return 0
+}
+
+func Geteuid() (uid int) {
+ return 0
+}
+
+func Getgid() (uid int) {
+ return 0
+}
+
+func Getegid() (uid int) {
+ return 0
+}
+
+func Getgroups() (gids []int, err error) {
+ return nil, errors.New("Getgroups unimplemented")
+}
+
+//func Exit(code int) {
+//zx.Sys_process_exit(int64(code))
+//}
+
+const ImplementsGetwd = true
+
+func Getwd() (wd string, err error) {
+ cwdMu.Lock()
+ wd = cwdStr
+ cwdMu.Unlock()
+ return wd, nil
+}
+
+func Chdir(dir string) (err error) {
+ // TODO: if cgo enabled, change the working directory there too.
+ f, err := OpenPath(dir, 0, 0)
+ if err != nil {
+ return err
+ }
+ cwdMu.Lock()
+ var old fdio.FDIO
+ old, cwd = cwd, f
+ // cwd starts as a reference to root, which should remain open.
+ if old != nil && old != root {
+ defer old.Close()
+ }
+ if path.IsAbs(dir) {
+ cwdStr = path.Clean(dir)
+ } else {
+ cwdStr = path.Join(cwdStr, dir)
+ }
+ cwdMu.Unlock()
+ return nil
+}
+
+func Mkdir(path string, mode uint32) (err error) {
+ f, err := OpenPath(path, O_CREAT|O_EXCL|O_RDWR, mode&0777|S_IFDIR)
+ if err != nil {
+ return err
+ }
+ f.Close()
+ return nil
+}
+
+func Rmdir(path string) error {
+ return Unlink(path)
+}
+
+func Unlink(p string) error {
+ dir, relp := fdioPath(path.Clean(p))
+ return dir.Unlink(relp)
+}
+
+func makeAbs(paths ...string) []string {
+ cwdMu.Lock()
+ dir := cwdStr
+ cwdMu.Unlock()
+ for i := range paths {
+ if !path.IsAbs(paths[i]) {
+ paths[i] = path.Join(dir, paths[i])
+ }
+ }
+ return paths
+}
+
+func Rename(oldpath, newpath string) error {
+ abs := makeAbs(oldpath, newpath)
+ rootMu.Lock()
+ r := root
+ rootMu.Unlock()
+ return r.Rename(abs[0][1:], abs[1][1:])
+}
+
+func Link(oldpath, newpath string) error {
+ abs := makeAbs(oldpath, newpath)
+ rootMu.Lock()
+ r := root
+ rootMu.Unlock()
+ return r.Link(abs[0][1:], abs[1][1:])
+}
+
+func Fsync(fd int) error {
+ fdsMu.Lock()
+ f := fds[fd-fdsOff]
+ fdsMu.Unlock()
+ return f.Sync()
+}
+
+func Fchdir(fd int) (err error) {
+ return errors.New("Fchdir unimplemented")
+}
+
+func CloseOnExec(r int) {
+ panic("syscall.CloseOnExec TODO")
+}
+
+func SetNonblock(fd int, nonblocking bool) (err error) {
+ if nonblocking {
+ return errors.New("syscall.SetNonblock: non-blocking not supported on fuchsia")
+ }
+ return nil
+}
+
+var (
+ rootMu sync.Mutex
+ root fdio.FDIO
+)
+
+var (
+ cwdMu sync.Mutex
+ cwd fdio.FDIO
+ cwdStr string
+)
+
+var (
+ nsMu sync.Mutex
+ ns *fdio.NS
+)
+
+var (
+ stdioMu sync.Mutex
+ stdin fdio.FDIO
+ stdout fdio.FDIO
+ stderr fdio.FDIO
+)
+
+const fdsOff = 1e6 // move outside the fd range of unistd.c FDIO
+
+var (
+ fdsMu sync.Mutex
+ fds []fdio.FDIO
+)
+
+func Read(fd int, p []byte) (n int, err error) {
+ if fd == Stdin {
+ stdioMu.Lock()
+ n, err = stdin.Read(p)
+ stdioMu.Unlock()
+ } else {
+ if fd < fdsOff {
+ return 0, EINVAL
+ }
+ fdsMu.Lock()
+ f := fds[fd-fdsOff]
+ fdsMu.Unlock()
+
+ n, err = f.Read(p)
+ }
+ // An io.Reader can return n < len(p) and io.EOF.
+ // But this is the POSIX syscall read(3), which
+ // returns nil on eof.
+ if err == io.EOF {
+ err = nil
+ }
+ return n, err
+}
+
+func init() {
+ EPIPE = zx.EPIPE
+
+ var err error
+
+ nsMu.Lock()
+ ns, err = fdio.NewNSFromMap(zx.RootNSMap)
+ nsMu.Unlock()
+ if err != nil {
+ println("syscall: failed to create namespace: ", err.Error())
+ }
+
+ rootMu.Lock()
+ root, err = ns.OpenRoot()
+ rootMu.Unlock()
+ if err != nil {
+ println("syscall: failed to create root directory from namespace: ", err.Error())
+ }
+
+ cwdMu.Lock()
+ var found bool
+ cwdStr, found = Getenv("PWD")
+ if !found {
+ cwdStr = "/"
+ } else {
+ // Ensure the incoming cwd is absolute and cleaned
+ cwdStr = path.Join("/", cwdStr)
+ }
+ cwd = root
+ if cwdStr != "/" {
+ cwd, err = OpenPath(cwdStr, 0, 0)
+ }
+ cwdMu.Unlock()
+ if err != nil {
+ println("syscall: failed to create fdio cwd: ", err.Error())
+ }
+
+ initStdio := func(i int) (fdio.FDIO, error) {
+ switch zx.StdioHandleTypes[i] {
+ case 0:
+ return nil, EINVAL
+ case fdio.HandleTypeRemote, fdio.HandleTypeSocket, fdio.HandleTypeLogger, fdio.HandleTypeFileDescriptor:
+ info, err := zx.StdioHandles[i].GetInfoHandleBasic()
+ if err != nil {
+ println("syscall: GetInfoHandleBasic failed", err)
+ return nil, EINVAL
+ }
+ switch info.Type {
+ case zx.ObjectTypeChannel:
+ return &fdio.File{
+ Node: fdio.Node{
+ NodeInterface: &fidlIo.NodeInterface{
+ Channel: zx.Channel(zx.StdioHandles[i]),
+ },
+ },
+ }, nil
+ case zx.ObjectTypeSocket:
+ return fdio.NewPipe(zx.Socket(zx.StdioHandles[i])), nil
+ case zx.ObjectTypeLog:
+ return fdio.NewLogger(zx.Log(zx.StdioHandles[i])), nil
+ default:
+ println("syscall: unknown object type for stdio: ", info.Type)
+ return nil, EINVAL
+ }
+ default:
+ println("syscall: unknown handle type for stdio: " + itoa(zx.StdioHandleTypes[i]))
+ return nil, EINVAL
+ }
+ }
+ stdioMu.Lock()
+ stdin, err = initStdio(0)
+ if err != nil {
+ println("syscall: failed to create fdio stdin: ", err.Error())
+ }
+ stdout, err = initStdio(1)
+ if err != nil {
+ println("syscall: failed to create fdio stdout: ", err.Error())
+ }
+ stderr, err = initStdio(2)
+ if err != nil {
+ println("syscall: failed to create fdio stderr: ", err.Error())
+ }
+ stdioMu.Unlock()
+}
+
+func Write(fd int, p []byte) (n int, err error) {
+ switch fd {
+ case Stdout:
+ stdioMu.Lock()
+ n, err := stdout.Write(p)
+ stdioMu.Unlock()
+ return n, err
+ case Stderr:
+ stdioMu.Lock()
+ n, err := stderr.Write(p)
+ stdioMu.Unlock()
+ return n, err
+ default:
+ fdsMu.Lock()
+ f := fds[fd-fdsOff]
+ fdsMu.Unlock()
+ return f.Write(p)
+ }
+}
+
+func Seek(fd int, offset int64, whence int) (int64, error) {
+ fdsMu.Lock()
+ f := fds[fd-fdsOff]
+ fdsMu.Unlock()
+ off, err := f.Seek(offset, whence)
+ if err, ok := err.(*zx.Error); ok && err.Status == zx.ErrNotSupported {
+ if _, ok := f.(*fdio.Pipe); ok {
+ return off, ESPIPE
+ }
+ }
+ return off, err
+}
+
+func Close(fd int) (err error) {
+ if fd < fdsOff {
+ return EINVAL
+ }
+ fdsMu.Lock()
+ if fd-fdsOff > len(fds) {
+ fdsMu.Unlock()
+ return EINVAL
+ }
+ f := fds[fd-fdsOff]
+ fds[fd-fdsOff] = nil
+ fdsMu.Unlock()
+ return f.Close()
+}
+
+func fdioPath(p string) (fdio.FDIO, string) {
+ if path.IsAbs(p) {
+ rootMu.Lock()
+ r := root
+ rootMu.Unlock()
+ return r, p[1:]
+ }
+ cwdMu.Lock()
+ c := cwd
+ cwdMu.Unlock()
+ return c, p
+}
+
+func OpenPath(p string, flags int, mode uint32) (f fdio.FDIO, err error) {
+ if strings.Contains(p, "\x00") {
+ return nil, EINVAL
+ }
+ dir, relp := fdioPath(path.Clean(p))
+ zflags := preprocessFlags(FdioFlagsToZxio(uint32(flags)), mode)
+ return dir.Open(relp, zflags, mode)
+}
+
+func preprocessFlags(flags uint32, mode uint32) uint32 {
+ flagsIncompatibleWithDirectory := (flags&FsRightWritable != 0) || (flags&FsFlagCreate != 0)
+ // Special allowance for Mkdir
+ if (flags == FsFlagCreate|FsFlagExclusive|FsRightReadable|FsRightWritable) &&
+ (mode&S_IFDIR != 0) {
+ flagsIncompatibleWithDirectory = false
+ }
+ if (flags&FsFlagDirectory) == 0 && flagsIncompatibleWithDirectory {
+ flags |= FsFlagNotDirectory
+ }
+ return flags
+}
+
+func Open(path string, flags int, mode uint32) (fd int, err error) {
+ if path == "" {
+ return -1, EINVAL
+ }
+ f, err := OpenPath(path, flags, mode)
+ if err != nil {
+ return -1, err
+ }
+ return OpenFDIO(f), nil
+}
+
+func OpenAt(fdParent int, path string, flags int, mode uint32) (fd int, err error) {
+ parent := FDIOForFD(fdParent)
+ if parent == nil {
+ return -1, EBADF
+ }
+ zflags := preprocessFlags(FdioFlagsToZxio(uint32(flags)), mode)
+ f, err := parent.Open(path, zflags, mode)
+ if err != nil {
+ return -1, err
+ }
+ return OpenFDIO(f), nil
+}
+
+func FDIOForFD(fd int) fdio.FDIO {
+ switch fd {
+ case Stdin:
+ return stdin
+ case Stdout:
+ return stdout
+ case Stderr:
+ return stderr
+ }
+ if fd < fdsOff {
+ return nil
+ }
+ fdsMu.Lock()
+ if fd-fdsOff > len(fds) {
+ fdsMu.Unlock()
+ return nil
+ }
+ f := fds[fd-fdsOff]
+ fdsMu.Unlock()
+ return f
+}
+
+func OpenFDIO(f fdio.FDIO) (fd int) {
+ fdsMu.Lock()
+ i := -1
+ for i = 0; i < len(fds); i++ {
+ if fds[i] == nil {
+ fds[i] = f
+ break
+ }
+ }
+ if i == len(fds) {
+ fds = append(fds, f)
+ }
+ fdsMu.Unlock()
+
+ return i + fdsOff
+}
+
+func Ioctl(fd int, op uint32, max uint64, in []byte, handles []zx.Handle) ([]byte, []zx.Handle, error) {
+ fdsMu.Lock()
+ f := fds[fd-fdsOff]
+ fdsMu.Unlock()
+ return f.Ioctl(op, max, in, handles)
+}
+
+func Fstat(fd int, stat *Stat_t) (err error) {
+ fdsMu.Lock()
+ f := fds[fd-fdsOff]
+ fdsMu.Unlock()
+
+ attr, err := f.GetAttr()
+ if err != nil {
+ return err
+ }
+ stat.Dev = uint64(attr.Mode)
+ stat.Ino = attr.Id
+ stat.Size = attr.ContentSize
+ stat.CreateTime = attr.CreationTime
+ stat.ModifyTime = attr.ModificationTime
+ return nil
+}
+
+func Stat(path string, stat *Stat_t) (err error) {
+ fd, err := Open(path, O_RDONLY|O_PATH, 0)
+ if err != nil {
+ return err
+ }
+ err = Fstat(fd, stat)
+ if err2 := Close(fd); err == nil {
+ err = err2
+ }
+ return err
+}
+
+func Lstat(path string, stat *Stat_t) (err error) {
+ // TODO: adjust when there are symlinks
+ return Stat(path, stat)
+}
+
+func Pread(fd int, p []byte, offset int64) (n int, err error) {
+ if fd == Stdout || fd == Stderr {
+ return 0, ESPIPE
+ }
+
+ fdsMu.Lock()
+ f := fds[fd-fdsOff]
+ fdsMu.Unlock()
+
+ // An io.Reader can return n < len(p) and io.EOF.
+ // But this is the POSIX syscall read(3), which
+ // returns nil on eof.
+ n, err = f.ReadAt(p, offset)
+ if err == io.EOF {
+ err = nil
+ }
+ return n, err
+}
+
+func Pwrite(fd int, p []byte, offset int64) (n int, err error) {
+ if fd == Stdout || fd == Stderr {
+ return 0, ESPIPE
+ }
+
+ fdsMu.Lock()
+ f := fds[fd-fdsOff]
+ fdsMu.Unlock()
+ return f.WriteAt(p, offset)
+}
+
+func Ftruncate(fd int, length int64) (err error) {
+ fdsMu.Lock()
+ f := fds[fd-fdsOff]
+ fdsMu.Unlock()
+ return f.Truncate(uint64(length))
+}
+
+func Truncate(path string, length int64) (err error) {
+ fd, err := Open(path, O_WRONLY, 0)
+ if err != nil {
+ return err
+ }
+ err = Ftruncate(fd, length)
+ if err2 := Close(fd); err == nil {
+ err = err2
+ }
+ return err
+}
+
+func Symlink(oldpath string, newpath string) (err error) {
+ return EOPNOTSUPP // no fuchsia support yet
+}
+
+func UtimesNano(path string, ts []Timespec) (err error) {
+ f, err := OpenPath(path, 0, 0)
+ if err != nil {
+ return err
+ }
+ defer f.Close()
+ return f.SetAttr(fidlIo.NodeAttributeFlagModificationTime, fidlIo.NodeAttributes{
+ ModificationTime: uint64(TimespecToNsec(ts[1])),
+ })
+}
+
+func clen(n []byte) int {
+ for i := 0; i < len(n); i++ {
+ if n[i] == 0 {
+ return i
+ }
+ }
+ return len(n)
+}
+
+func ReadDirent(fd int, buf []byte) (n int, err error) {
+ fdsMu.Lock()
+ f := fds[fd-fdsOff]
+ fdsMu.Unlock()
+ dirent, err := f.ReadDirents(uint64(len(buf)))
+ if err != nil {
+ return 0, err
+ }
+ return copy(buf, dirent), nil
+}
+
+func direntIno(buf []byte) (uint64, bool) {
+ return readInt(buf, unsafe.Offsetof(Dirent{}.Ino), unsafe.Sizeof(Dirent{}.Ino))
+}
+
+func direntReclen(buf []byte) (uint64, bool) {
+ if namelen, ok := direntNamlen(buf); ok {
+ return namelen + uint64(direntSize), true
+ } else {
+ return 0, false
+ }
+}
+
+func direntNamlen(buf []byte) (uint64, bool) {
+ return readInt(buf, unsafe.Offsetof(Dirent{}.Size), unsafe.Sizeof(Dirent{}.Size))
+}
+
+type Dirent struct {
+ Ino uint64
+ Size uint8
+ Type uint8
+ Name [1]byte
+}
+
+const direntSize = int(unsafe.Offsetof(Dirent{}.Name))
diff --git a/src/syscall/timestruct.go b/src/syscall/timestruct.go
index d17811c..89f4061 100644
--- a/src/syscall/timestruct.go
+++ b/src/syscall/timestruct.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build aix darwin dragonfly freebsd js,wasm linux nacl netbsd openbsd solaris
+// +build aix darwin dragonfly freebsd fuchsia js,wasm linux nacl netbsd openbsd solaris
package syscall
diff --git a/src/syscall/types_fuchsia.go b/src/syscall/types_fuchsia.go
new file mode 100644
index 0000000..9098a4a
--- /dev/null
+++ b/src/syscall/types_fuchsia.go
@@ -0,0 +1,29 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package syscall
+
+type Errno uintptr
+
+func (e Errno) Error() string {
+ return "errno(" + itoa(int(e)) + ")"
+}
+
+type Timespec struct {
+ Sec int64
+ Nsec int64
+}
+
+type Timeval struct {
+ Sec int64
+ Usec int64
+}
+
+func setTimespec(sec, nsec int64) Timespec {
+ return Timespec{Sec: sec, Nsec: nsec}
+}
+
+func setTimeval(sec, usec int64) Timeval {
+ return Timeval{Sec: sec, Usec: usec}
+}
diff --git a/src/syscall/zerrors_fuchsia.go b/src/syscall/zerrors_fuchsia.go
new file mode 100644
index 0000000..9f5e96b
--- /dev/null
+++ b/src/syscall/zerrors_fuchsia.go
@@ -0,0 +1,77 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package syscall
+
+const (
+ EAGAIN = 11
+ EINPROGRESS = 115
+)
+
+const (
+ SOCK_STREAM = 1
+ SOCK_DGRAM = 2
+ SOCK_RAW = 3
+)
+
+const (
+ IPPROTO_IP = 0
+ IPPROTO_ICMP = 1
+ IPPROTO_TCP = 6
+ IPPROTO_UDP = 17
+ IPPROTO_ICMPV6 = 58
+)
+
+const (
+ AF_INET = 0x2
+ AF_INET6 = 0xa
+)
+
+const (
+ SOL_SOCKET = 0x1
+ SOL_TCP = 0x6
+)
+
+const (
+ SO_ACCEPTCONN = 0x1e
+ SO_BROADCAST = 0x6
+ SO_BSDCOMPAT = 0xe
+ SO_DEBUG = 0x1
+ SO_DOMAIN = 0x27
+ SO_DONTROUTE = 0x5
+ SO_ERROR = 0x4
+ SO_KEEPALIVE = 0x9
+ SO_LINGER = 0xd
+ SO_NO_CHECK = 0xb
+ SO_PASSCRED = 0x10
+ SO_PEERCRED = 0x11
+ SO_PRIORITY = 0xc
+ SO_PROTOCOL = 0x26
+ SO_RCVBUF = 0x8
+ SO_RCVBUFFORCE = 0x21
+ SO_RCVLOWAT = 0x12
+ SO_RCVTIMEO = 0x14
+ SO_REUSEADDR = 0x2
+ SO_REUSEPORT = 0xf
+ SO_SNDBUF = 0x7
+ SO_SNDBUFFORCE = 0x20
+ SO_SNDLOWAT = 0x13
+ SO_SNDTIMEO = 0x15
+ SO_TYPE = 0x3
+)
+
+const (
+ TCP_NODELAY = 1
+ TCP_MAXSEG = 2
+ TCP_CORK = 3
+ TCP_KEEPIDLE = 4
+ TCP_KEEPINTVL = 5
+ TCP_KEEPCNT = 6
+ TCP_SYNCNT = 7
+ TCP_LINGER2 = 8
+ TCP_DEFER_ACCEPT = 9
+ TCP_WINDOW_CLAMP = 10
+ TCP_INFO = 11
+ TCP_QUICKACK = 12
+)
diff --git a/src/syscall/ztypes_fuchsia_amd64.go b/src/syscall/ztypes_fuchsia_amd64.go
new file mode 100644
index 0000000..6621a4f
--- /dev/null
+++ b/src/syscall/ztypes_fuchsia_amd64.go
@@ -0,0 +1,28 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build amd64,fuchsia
+
+package syscall
+
+type RawSockaddrInet4 struct {
+ Family uint16
+ Port uint16
+ Addr [4]byte /* in_addr */
+ Zero [8]uint8
+}
+
+type RawSockaddrInet6 struct {
+ Family uint16
+ Port uint16
+ Flowinfo uint32
+ Addr [16]byte /* in6_addr */
+ Scope_id uint32
+}
+
+const (
+ SizeofSockaddrInet4 = 0x10
+ SizeofSockaddrInet6 = 0x1c
+ SizeofSockaddrAny = 0x70
+)
diff --git a/src/syscall/ztypes_fuchsia_arm64.go b/src/syscall/ztypes_fuchsia_arm64.go
new file mode 100644
index 0000000..0cca414
--- /dev/null
+++ b/src/syscall/ztypes_fuchsia_arm64.go
@@ -0,0 +1,28 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package syscall
+
+// +build arm64,fuchsia
+
+type RawSockaddrInet4 struct {
+ Family uint16
+ Port uint16
+ Addr [4]byte /* in_addr */
+ Zero [8]uint8
+}
+
+type RawSockaddrInet6 struct {
+ Family uint16
+ Port uint16
+ Flowinfo uint32
+ Addr [16]byte /* in6_addr */
+ Scope_id uint32
+}
+
+const (
+ SizeofSockaddrInet4 = 0x10
+ SizeofSockaddrInet6 = 0x1c
+ SizeofSockaddrAny = 0x70
+)
diff --git a/src/syscall/zx/dispatch/dispatcher.go b/src/syscall/zx/dispatch/dispatcher.go
new file mode 100644
index 0000000..0652a08
--- /dev/null
+++ b/src/syscall/zx/dispatch/dispatcher.go
@@ -0,0 +1,225 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build fuchsia
+
+package dispatch
+
+import (
+ "strconv"
+ "sync"
+ "syscall/zx"
+)
+
+// WaitResult represents a wait result that is returned by the callback.
+// WaitResult determines whether the wait should be re-queued.
+type WaitResult int
+
+const (
+ WaitFinished WaitResult = iota
+ WaitAgain
+)
+
+// WaitID is a monotonically increasing ID which corresponds to a particular
+// call to BeginWait. Note that it may become invalidated if a wait is dequeued.
+type WaitID uint64
+
+// WaitFlags represents the collection of certain options for waiting.
+type WaitFlags uint32
+
+const (
+ HandleShutdown WaitFlags = 1 << 0 // Calls the callback on shutdown.
+)
+
+// Handler is the callback that will be called when the wait is complete.
+type Handler func(*Dispatcher, zx.Status, *zx.PacketSignal) WaitResult
+
+// waitContext is a bookkeeping structure for in-progress waits.
+type waitContext struct {
+ object zx.Handle
+ callback Handler
+ trigger zx.Signals
+ flags WaitFlags
+}
+
+// Dispatcher can read messages from a handle and assign them to a callback.
+type Dispatcher struct {
+ // port is the underlying port used to wait on signals and dispatch.
+ port zx.Port
+
+ // objects is a map that manages wait contexts.
+ mu sync.RWMutex
+ objects map[WaitID]*waitContext
+ nextWaitID WaitID
+
+ // handling is a map that manages which wait IDs that are current being
+ // handled. It is also protected by mu.
+ handling map[WaitID]struct{}
+
+ // shutdown is whether the dispatcher has shut down.
+ shutdown bool
+}
+
+// New creates a new dispatcher.
+func NewDispatcher() (*Dispatcher, error) {
+ port, err := zx.NewPort(0)
+ if err != nil {
+ return nil, err
+ }
+ return &Dispatcher{
+ port: port,
+ objects: make(map[WaitID]*waitContext),
+ handling: make(map[WaitID]struct{}),
+ }, nil
+}
+
+func assertWaitResult(result WaitResult, status zx.Status) {
+ if !(result == WaitFinished || (result == WaitAgain && status == zx.ErrOk)) {
+ panic("expected " + strconv.Itoa(int(result)) + " for status " + strconv.Itoa(int(status)))
+ }
+}
+
+// Closes a dispatcher, shutting down all handles added to the dispatcher.
+func (d *Dispatcher) Close() {
+ d.mu.Lock()
+ defer d.mu.Unlock()
+ d.port.Close()
+ for _, obj := range d.objects {
+ if obj != nil && (obj.flags&HandleShutdown) != 0 {
+ // Ignore the result; we won't be waiting again.
+ result := obj.callback(d, zx.ErrCanceled, nil)
+ assertWaitResult(result, zx.ErrCanceled)
+ }
+ }
+ d.objects = make(map[WaitID]*waitContext)
+ d.shutdown = true
+}
+
+func (d *Dispatcher) getWaitID() WaitID {
+ _, ok := d.objects[d.nextWaitID]
+ for ok {
+ d.nextWaitID++
+ _, ok = d.objects[d.nextWaitID]
+ }
+ return d.nextWaitID
+}
+
+// BeginWait creates a new wait on the handle h for signals t. The new wait
+// will respect the flags f, and call the handler c on wait completion.
+func (d *Dispatcher) BeginWait(h zx.Handle, t zx.Signals, f WaitFlags, c Handler) (WaitID, error) {
+ d.mu.Lock()
+ defer d.mu.Unlock()
+
+ // If we've shut down, just notify that we're in a bad state.
+ if d.shutdown {
+ return 0, &zx.Error{Status: zx.ErrBadState}
+ }
+
+ // Register the wait.
+ id := d.getWaitID()
+ d.objects[id] = &waitContext{
+ object: h,
+ callback: c,
+ trigger: t,
+ flags: f,
+ }
+
+ // Schedule the wait on the port.
+ err := d.port.WaitAsync(h, uint64(id), t, zx.PortWaitAsyncOnce)
+
+ // If we fail, make sure to de-register the wait.
+ if err != nil {
+ delete(d.objects, id)
+ }
+ return id, err
+}
+
+// CancelWait cancels the wait with the given WaitID.
+func (d *Dispatcher) CancelWait(id WaitID) error {
+ d.mu.Lock()
+ defer d.mu.Unlock()
+
+ // Look up the wait context.
+ wc := d.objects[id]
+ if wc == nil {
+ return &zx.Error{Status: zx.ErrNotFound}
+ }
+
+ // If we're currently handling it, it's not being waited on, so there's nothing
+ // to cancel.
+ _, ok := d.handling[id]
+ if ok {
+ return &zx.Error{Status: zx.ErrNotFound}
+ }
+
+ // Deregister no matter what here. Due to stack semantics of defer, this will always
+ // execute before the lock is released.
+ defer delete(d.objects, id)
+
+ // Cancel the actual wait.
+ return d.port.Cancel(wc.object, uint64(id))
+}
+
+func (d *Dispatcher) dispatch(id WaitID, wc *waitContext, signals *zx.PacketSignal) {
+ // Deregister the handler before invoking it.
+ d.mu.Lock()
+ d.handling[id] = struct{}{}
+ d.mu.Unlock()
+
+ // Call the handler.
+ result := wc.callback(d, zx.ErrOk, signals)
+ assertWaitResult(result, zx.ErrOk)
+ switch result {
+ case WaitAgain:
+ // Re-arm the handler, as the handler requested. Use a fresh ID since there's a
+ // chance the old ID has already been re-used.
+ d.mu.Lock()
+ delete(d.handling, id)
+ err := d.port.WaitAsync(wc.object, uint64(id), wc.trigger, zx.PortWaitAsyncOnce)
+ d.mu.Unlock()
+
+ // If we fail to re-arm, notify the handler of what happened.
+ if err != nil {
+ status := err.(*zx.Error).Status
+ result = wc.callback(d, status, nil)
+ assertWaitResult(result, status)
+ }
+ case WaitFinished:
+ d.mu.Lock()
+ delete(d.handling, id)
+ delete(d.objects, id)
+ d.mu.Unlock()
+ }
+}
+
+// Serve runs indefinitely, waiting for the port to return a packet and dispatches
+// the relevant handlers.
+func (d *Dispatcher) Serve() {
+ for {
+ // Wait for any handler to be ready
+ var packet zx.Packet
+ err := d.port.Wait(&packet, zx.TimensecInfinite)
+ if err != nil {
+ d.Close()
+ return
+ }
+ id := WaitID(packet.Hdr.Key)
+
+ // Get the object for dispatching.
+ d.mu.RLock()
+ wc := d.objects[id]
+ d.mu.RUnlock()
+
+ // If handler was removed while this packet was in the queue,
+ // just go back to waiting.
+ if wc == nil {
+ continue
+ }
+
+ // Dispatch to the appropriate handler.
+ if packet.Hdr.Type == zx.PortPacketTypeSignalOne {
+ d.dispatch(id, wc, packet.Signal())
+ }
+ }
+}
diff --git a/src/syscall/zx/dispatch/dispatcher_test.go b/src/syscall/zx/dispatch/dispatcher_test.go
new file mode 100644
index 0000000..9c1975b
--- /dev/null
+++ b/src/syscall/zx/dispatch/dispatcher_test.go
@@ -0,0 +1,231 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build fuchsia
+
+package dispatch_test
+
+import (
+ "sync/atomic"
+ "syscall/zx"
+ . "syscall/zx/dispatch"
+ "testing"
+ "time"
+)
+
+func dispatcherTest(t *testing.T, name string, f func(d *Dispatcher) error) {
+ t.Run(name, func(t *testing.T) {
+ d, err := NewDispatcher()
+ if err != nil {
+ t.Fatal("creating dispatcher: ", err)
+ }
+ go d.Serve()
+ if err := f(d); err != nil {
+ t.Fatal("executing test: ", err)
+ }
+ d.Close()
+ })
+}
+
+func TestWait(t *testing.T) {
+ t.Parallel()
+ dispatcherTest(t, "WaitOnce", func(d *Dispatcher) error {
+ h0, h1, err := zx.NewChannel(0)
+ if err != nil {
+ return err
+ }
+ defer h0.Close()
+
+ done := make(chan struct{}, 1)
+ defer close(done)
+
+ handler := func(d *Dispatcher, s zx.Status, p *zx.PacketSignal) WaitResult {
+ done <- struct{}{}
+ return WaitFinished
+ }
+
+ _, err = d.BeginWait(zx.Handle(h0), zx.SignalChannelPeerClosed, 0, handler)
+ if err != nil {
+ return err
+ }
+
+ h1.Close()
+
+ select {
+ case <-done:
+ return nil
+ case <-time.After(5 * time.Second):
+ t.Fatal("timed out, handler never executed")
+ }
+ return nil
+ })
+ dispatcherTest(t, "WaitMultipleTimes", func(d *Dispatcher) error {
+ h0, h1, err := zx.NewChannel(0)
+ if err != nil {
+ return err
+ }
+ defer h0.Close()
+ defer h1.Close()
+
+ done := make(chan struct{}, 1)
+ defer close(done)
+
+ handler := func(d *Dispatcher, s zx.Status, p *zx.PacketSignal) WaitResult {
+ var b [zx.ChannelMaxMessageBytes]byte
+ var h [zx.ChannelMaxMessageHandles]zx.Handle
+ bn, hn, err := h0.Read(b[:], h[:], 0)
+ if err != nil {
+ t.Fatal("error reading: ", err)
+ }
+ if bn != 1 || hn != 0 {
+ t.Fatalf("unexpected read %d bytes %d handles", bn, hn)
+ }
+ if b[0] == 1 {
+ return WaitAgain
+ }
+ done <- struct{}{}
+ return WaitFinished
+ }
+
+ _, err = d.BeginWait(zx.Handle(h0), zx.SignalChannelReadable, 0, handler)
+ if err != nil {
+ return err
+ }
+
+ for i := 0; i < 5; i++ {
+ if err := h1.Write([]byte{1}, nil, 0); err != nil {
+ return err
+ }
+ }
+ if err := h1.Write([]byte{0}, nil, 0); err != nil {
+ return err
+ }
+
+ select {
+ case <-done:
+ return nil
+ case <-time.After(5 * time.Second):
+ t.Fatal("timed out, handler never executed")
+ }
+ return nil
+ })
+ dispatcherTest(t, "CancelWaitHandleShutdown", func(d *Dispatcher) error {
+ h0, h1, err := zx.NewChannel(0)
+ if err != nil {
+ return err
+ }
+ defer h0.Close()
+ defer h1.Close()
+
+ var i uint32
+ handler := func(d *Dispatcher, s zx.Status, p *zx.PacketSignal) WaitResult {
+ atomic.AddUint32(&i, 1)
+ return WaitFinished
+ }
+
+ id, err := d.BeginWait(zx.Handle(h0), zx.SignalChannelPeerClosed, HandleShutdown, handler)
+ if err != nil {
+ return err
+ }
+
+ if err := d.CancelWait(id); err != nil {
+ return err
+ }
+ d.Close()
+ if i != 0 {
+ t.Fatal("handler ran unexpectedly")
+ }
+ return nil
+ })
+ dispatcherTest(t, "Shutdown", func(d *Dispatcher) error {
+ h0, h1, err := zx.NewChannel(0)
+ if err != nil {
+ return err
+ }
+ defer h0.Close()
+ defer h1.Close()
+
+ handler := func(d *Dispatcher, s zx.Status, p *zx.PacketSignal) WaitResult {
+ return WaitFinished
+ }
+ d.Close()
+
+ _, err = d.BeginWait(zx.Handle(h0), zx.SignalChannelPeerClosed, 0, handler)
+ if err == nil {
+ t.Fatal("unexpected success for BeginWait on shut down dispatcher")
+ }
+ return nil
+ })
+ dispatcherTest(t, "HandleShutdown", func(d *Dispatcher) error {
+ h0, h1, err := zx.NewChannel(0)
+ if err != nil {
+ return err
+ }
+ defer h0.Close()
+ defer h1.Close()
+
+ done := make(chan struct{}, 1)
+ defer close(done)
+
+ handler := func(d *Dispatcher, s zx.Status, p *zx.PacketSignal) WaitResult {
+ done <- struct{}{}
+ return WaitFinished
+ }
+
+ _, err = d.BeginWait(zx.Handle(h0), zx.SignalChannelPeerClosed, HandleShutdown, handler)
+ if err != nil {
+ return err
+ }
+ d.Close()
+
+ select {
+ case <-done:
+ return nil
+ case <-time.After(5 * time.Second):
+ t.Fatal("timed out, handler never executed")
+ }
+ return nil
+ })
+ dispatcherTest(t, "MultipleGoroutines", func(d *Dispatcher) error {
+ // Spin up 5 goroutines all serving the dispatcher.
+ for i := 0; i < 5; i++ {
+ go d.Serve()
+ }
+
+ done := make(chan struct{}, 20)
+ defer close(done)
+
+ var ends []zx.Channel
+ for i := 0; i < 20; i++ {
+ h0, h1, err := zx.NewChannel(0)
+ if err != nil {
+ return err
+ }
+ defer h0.Close()
+
+ handler := func(d *Dispatcher, s zx.Status, p *zx.PacketSignal) WaitResult {
+ done <- struct{}{}
+ return WaitFinished
+ }
+
+ _, err = d.BeginWait(zx.Handle(h0), zx.SignalChannelPeerClosed, 0, handler)
+ if err != nil {
+ return err
+ }
+ ends = append(ends, h1)
+ }
+ for _, e := range ends {
+ e.Close()
+ }
+ for i := 0; i < 20; i++ {
+ select {
+ case <-done:
+ continue
+ case <-time.After(3 * time.Second):
+ t.Fatal("timed out, some handler never executed")
+ }
+ }
+ return nil
+ })
+}
diff --git a/src/syscall/zx/fdio/client.go b/src/syscall/zx/fdio/client.go
new file mode 100644
index 0000000..2efd265
--- /dev/null
+++ b/src/syscall/zx/fdio/client.go
@@ -0,0 +1,34 @@
+// +build fuchsia
+
+package fdio
+
+import (
+ "syscall/zx"
+ "syscall/zx/fidl"
+ "syscall/zx/io"
+)
+
+func ServiceConnect(svcpath string, h zx.Handle) error {
+ // Otherwise attempt to connect through the root namespace.
+ ns, err := NewNSFromMap(zx.RootNSMap)
+ if err == nil {
+ return ns.Connect(svcpath, h)
+ }
+ h.Close()
+ return &zx.Error{Status: zx.ErrNotFound, Text: "fdio.ServiceConnect"}
+}
+
+func ServiceConnectAt(dir zx.Handle, path string, h zx.Handle) error {
+ if !dir.IsValid() || !h.IsValid() {
+ return &zx.Error{Status: zx.ErrInvalidArgs, Text: "fdio.ServiceConnectAt"}
+ }
+ // Open the path on the remote.
+ iface := (*io.DirectoryInterface)(&fidl.ChannelProxy{Channel: zx.Channel(dir)})
+ req := io.NodeInterfaceRequest(fidl.InterfaceRequest{Channel: zx.Channel(h)})
+ err := iface.Open(io.OpenRightReadable|io.OpenRightWritable, 0755, path, req)
+ if err != nil {
+ h.Close()
+ return err
+ }
+ return nil
+}
diff --git a/src/syscall/zx/fdio/directory.go b/src/syscall/zx/fdio/directory.go
new file mode 100644
index 0000000..8373a9b
--- /dev/null
+++ b/src/syscall/zx/fdio/directory.go
@@ -0,0 +1,189 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build fuchsia
+
+package fdio
+
+import (
+ "syscall/zx"
+ "syscall/zx/fidl"
+ "syscall/zx/io"
+)
+
+// Directory is a wrapper around a DirectoryAdminInterface which implements FDIO.
+type Directory struct {
+ Node
+}
+
+func (d *Directory) getToken() (zx.Handle, error) {
+ status, token, err := d.DirectoryInterface().GetToken()
+ if err != nil {
+ return zx.HandleInvalid, err
+ } else if zx.Status(status) != zx.ErrOk {
+ return zx.HandleInvalid, &zx.Error{Status: zx.Status(status), Text: "io.directory.getToken"}
+ }
+ return token, nil
+}
+
+// DirectoryInterface returns the underlying Directory FIDL interface.
+// It lies a little, in the sense that it always returns a "DirectoryAdminInterface"
+// for convenience.
+func (d *Directory) DirectoryInterface() *io.DirectoryAdminInterface {
+ return (*io.DirectoryAdminInterface)(d.Node.NodeInterface)
+}
+
+// Close closes the Directory object.
+func (d *Directory) Close() error {
+ defer ((*fidl.ChannelProxy)(d.Node.NodeInterface)).Close()
+ if status, err := d.Node.NodeInterface.Close(); err != nil {
+ return err
+ } else if zx.Status(status) != zx.ErrOk {
+ return &zx.Error{Status: zx.Status(status), Text: "io.directory.Close"}
+ }
+ return nil
+}
+
+// Open opens an FDIO at path with the given flags and mode relative to this
+// Directory.
+func (d *Directory) Open(pathname string, flags uint32, mode uint32) (FDIO, error) {
+ req, obj, err := io.NewNodeInterfaceRequest()
+ if err != nil {
+ return nil, err
+ }
+ err = d.DirectoryInterface().Open(flags|io.OpenFlagDescribe, mode, pathname, req)
+ if err != nil {
+ ((*fidl.ChannelProxy)(obj)).Close()
+ return nil, err
+ }
+ status, info, err := obj.ExpectOnOpen()
+ if err != nil {
+ ((*fidl.ChannelProxy)(obj)).Close()
+ return nil, err
+ } else if zx.Status(status) != zx.ErrOk {
+ ((*fidl.ChannelProxy)(obj)).Close()
+ return nil, &zx.Error{Status: zx.Status(status), Text: "io.directory.Open"}
+ }
+ return nodeFromInfo(info, obj)
+}
+
+func (d *Directory) openParent(pathname string) (FDIO, string, error) {
+ dirpath, name := pathSplit(pathname)
+ parent, err := d.Open(
+ pathDir(dirpath),
+ io.OpenRightReadable|io.OpenFlagDirectory|io.OpenFlagPosix,
+ S_IFDIR)
+ if err != nil {
+ return nil, "", err
+ }
+ return parent, name, err
+}
+
+// Link creates a link between two paths under this Directory.
+func (d *Directory) Link(oldpath, newpath string) error {
+ oldparent, oldname, err := d.openParent(oldpath)
+ if err != nil {
+ return err
+ }
+ defer oldparent.Close()
+ newparent, newname, err := d.openParent(newpath)
+ if err != nil {
+ return err
+ }
+ defer newparent.Close()
+ olddir, ok := oldparent.(*Directory)
+ if !ok {
+ return &zx.Error{Status: zx.ErrNotSupported, Text: "io.directory.Link"}
+ }
+ newdir, ok := newparent.(*Directory)
+ if !ok {
+ return &zx.Error{Status: zx.ErrNotSupported, Text: "io.directory.Link"}
+ }
+ token, err := newdir.getToken()
+ if err != nil {
+ return err
+ }
+ status, err := olddir.DirectoryInterface().Link(oldname, token, newname)
+ if err != nil {
+ return err
+ } else if zx.Status(status) != zx.ErrOk {
+ return &zx.Error{Status: zx.Status(status), Text: "io.directory.Link"}
+ }
+ return nil
+}
+
+// Rename renames an object at one path to another under this Directory.
+func (d *Directory) Rename(oldpath, newpath string) error {
+ oldf, oldname, err := d.openParent(oldpath)
+ if err != nil {
+ return err
+ }
+ defer oldf.Close()
+ newf, newname, err := d.openParent(newpath)
+ if err != nil {
+ return err
+ }
+ defer newf.Close()
+ olddir, ok := oldf.(*Directory)
+ if !ok {
+ return &zx.Error{Status: zx.ErrNotSupported, Text: "io.directory.Rename"}
+ }
+ newdir, ok := newf.(*Directory)
+ if !ok {
+ return &zx.Error{Status: zx.ErrNotSupported, Text: "io.directory.Rename"}
+ }
+ token, err := newdir.getToken()
+ if err != nil {
+ return err
+ }
+ status, err := olddir.DirectoryInterface().Rename(oldname, token, newname)
+ if err != nil {
+ return err
+ } else if zx.Status(status) != zx.ErrOk {
+ return &zx.Error{Status: zx.Status(status), Text: "io.directory.Rename"}
+ }
+ return nil
+}
+
+// Unlink unlinks an object at a pauth under this Directory.
+func (d *Directory) Unlink(pathname string) error {
+ parent, name, err := d.openParent(pathname)
+ if err != nil {
+ return err
+ }
+ defer parent.Close()
+ parentdir, ok := parent.(*Directory)
+ if !ok {
+ return &zx.Error{Status: zx.ErrNotSupported, Text: "io.directory.Unlink"}
+ }
+ if status, err := parentdir.DirectoryInterface().Unlink(name); err != nil {
+ return err
+ } else if zx.Status(status) != zx.ErrOk {
+ return &zx.Error{Status: zx.Status(status), Text: "io.directory.Unlink"}
+ }
+ return nil
+}
+
+// ReadDirents returns up to max-worth bytes of byte-encoded dirents which represent
+// objects under this Directory. Repeated calls to ReadDirents continues giving back
+// objects.
+func (d *Directory) ReadDirents(max uint64) ([]byte, error) {
+ status, dirents, err := d.DirectoryInterface().ReadDirents(max)
+ if err != nil {
+ return nil, err
+ } else if zx.Status(status) != zx.ErrOk {
+ return nil, &zx.Error{Status: zx.Status(status), Text: "io.file"}
+ }
+ return dirents, nil
+}
+
+// Rewind resets the ReadDirents' counter.
+func (d *Directory) Rewind() error {
+ if status, err := d.DirectoryInterface().Rewind(); err != nil {
+ return err
+ } else if zx.Status(status) != zx.ErrOk {
+ return &zx.Error{Status: zx.Status(status), Text: "io.directory.Unlink"}
+ }
+ return nil
+}
diff --git a/src/syscall/zx/fdio/fdio.go b/src/syscall/zx/fdio/fdio.go
new file mode 100644
index 0000000..8935d15
--- /dev/null
+++ b/src/syscall/zx/fdio/fdio.go
@@ -0,0 +1,84 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build fuchsia
+
+// Package fdio provides unix-style IO, implementing Zircon's "system/ulib/fdio"
+package fdio
+
+import (
+ "syscall/zx"
+ "syscall/zx/io"
+)
+
+// FDIO provides classic unix-style IO over various transports
+type FDIO interface {
+ Handles() []zx.Handle
+
+ Clone() (FDIO, error)
+ Close() error
+
+ Sync() error
+ GetAttr() (io.NodeAttributes, error)
+ SetAttr(flags uint32, attr io.NodeAttributes) error
+ Ioctl(op uint32, max uint64, in []byte, handles []zx.Handle) ([]byte, []zx.Handle, error)
+
+ Read(data []byte) (int, error)
+ ReadAt(data []byte, off int64) (int, error)
+ Write(data []byte) (int, error)
+ WriteAt(data []byte, off int64) (int, error)
+ Seek(offset int64, whence int) (int64, error)
+ Truncate(length uint64) error
+
+ Open(path string, flags uint32, mode uint32) (FDIO, error)
+ Link(oldpath, newpath string) error
+ Rename(oldpath, newpath string) error
+ Unlink(path string) error
+ ReadDirents(max uint64) ([]byte, error)
+ Rewind() error
+}
+
+type Vtype uint32
+
+// bit-compatible with POSIX stat
+const (
+ VtypeMask Vtype = 0170000
+ VtypeSock Vtype = 0140000
+ VtypeLink Vtype = 0120000
+ VtypeFile Vtype = 0100000
+ VtypeBdev Vtype = 0060000
+ VtypeDir Vtype = 0040000
+ VtypeCdev Vtype = 0020000
+ VtypePipe Vtype = 0010000
+
+ VtypeISUID Vtype = 0004000
+ VtypeISGID Vtype = 0002000
+ VtypeISVTX Vtype = 0001000
+ VtypeIRWXU Vtype = 0000700
+ VtypeIRUSR Vtype = 0000400
+ VtypeIWUSR Vtype = 0000200
+ VtypeIXUSR Vtype = 0000100
+ VtypeIRWXG Vtype = 0000070
+ VtypeIRGRP Vtype = 0000040
+ VtypeIWGRP Vtype = 0000020
+ VtypeIXGRP Vtype = 0000010
+ VtypeIRWXO Vtype = 0000007
+ VtypeIROTH Vtype = 0000004
+ VtypeIWOTH Vtype = 0000002
+ VtypeIXOTH Vtype = 0000001
+)
+
+const (
+ HandleTypeFileDescriptor = 0x30
+ HandleTypeRemote = 0x32
+ HandleTypeLogger = 0x35
+ HandleTypeSocket = 0x36
+)
+
+const (
+ S_IFMT = 0000170000
+ S_IFDIR = 0000040000
+ S_IFREG = 0000100000
+ S_IFIFO = 0000010000
+)
diff --git a/src/syscall/zx/fdio/file.go b/src/syscall/zx/fdio/file.go
new file mode 100644
index 0000000..acf4886
--- /dev/null
+++ b/src/syscall/zx/fdio/file.go
@@ -0,0 +1,152 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build fuchsia
+
+package fdio
+
+import (
+ "syscall/zx"
+ "syscall/zx/io"
+)
+
+// File is a wrapper around a FileInterface which implements FDIO.
+type File struct {
+ Node
+ Event zx.Event
+}
+
+// FileInterface returns the underlying File FIDL interface.
+func (f *File) FileInterface() *io.FileInterface {
+ return (*io.FileInterface)(f.Node.NodeInterface)
+}
+
+// Handles returns all the underlying handles for this file,
+// which is the control channel and an event.
+func (f *File) Handles() []zx.Handle {
+ return append(f.Node.Handles(), zx.Handle(f.Event))
+}
+
+// Close closes all the control channel and event associated with the file
+// object.
+func (f *File) Close() error {
+ defer f.Event.Close()
+ return f.Node.Close()
+}
+
+// read reads data from a File. If off == -1 then it does a read
+// from whatever the seek offset is.
+func (f *File) read(data []byte, off int64) (int, error) {
+ ptr := 0
+ for ptr < len(data) {
+ bytesToRead := int(io.MaxBuf)
+ if len(data)-ptr < int(io.MaxBuf) {
+ bytesToRead = len(data) - ptr
+ }
+ var status int32
+ var out []byte
+ var err error
+ if off == -1 {
+ status, out, err = f.FileInterface().Read(uint64(bytesToRead))
+ } else {
+ status, out, err = f.FileInterface().ReadAt(
+ uint64(bytesToRead),
+ uint64(int64(ptr)+off),
+ )
+ }
+ if err != nil {
+ return ptr, err
+ } else if zx.Status(status) != zx.ErrOk {
+ return ptr, &zx.Error{Status: zx.Status(status), Text: "io.file"}
+ }
+ if len(out) == 0 {
+ return ptr, nil
+ }
+ copy(data[ptr:ptr+len(out)], out)
+ ptr += len(out)
+ // Stop at short read.
+ if len(out) < bytesToRead {
+ return ptr, nil
+ }
+ }
+ return ptr, nil
+}
+
+// Read reads data from the internally held offset in the File.
+func (f *File) Read(data []byte) (int, error) {
+ return f.read(data, -1)
+}
+
+// ReadAt reads data at an offset in a File.
+func (f *File) ReadAt(data []byte, off int64) (int, error) {
+ return f.read(data, off)
+}
+
+// write writes data to a file. If off == -1 then the write occurs at
+// whatever the seek offset is.
+func (f *File) write(data []byte, off int64) (int, error) {
+ ptr := 0
+ for ptr < len(data) {
+ bytesToWrite := int(io.MaxBuf)
+ if len(data)-ptr < int(io.MaxBuf) {
+ bytesToWrite = len(data) - ptr
+ }
+ var status int32
+ var written uint64
+ var err error
+ if off == -1 {
+ status, written, err = f.FileInterface().Write(
+ data[ptr : ptr+bytesToWrite],
+ )
+ } else {
+ status, written, err = f.FileInterface().WriteAt(
+ data[ptr:ptr+bytesToWrite],
+ uint64(int64(ptr)+off),
+ )
+ }
+ if err != nil {
+ return ptr, err
+ } else if zx.Status(status) != zx.ErrOk {
+ return ptr, &zx.Error{Status: zx.Status(status), Text: "io.file"}
+ }
+ ptr += int(written)
+ // Error on a short write.
+ if int(written) < bytesToWrite {
+ return ptr, &zx.Error{Status: zx.ErrIO, Text: "io.file"}
+ }
+ }
+ return ptr, nil
+}
+
+// Write writes data at the internally held offset in the File.
+func (f *File) Write(data []byte) (int, error) {
+ return f.write(data, -1)
+}
+
+// WriteAt writes data at an offset in a File.
+func (f *File) WriteAt(data []byte, off int64) (int, error) {
+ return f.write(data, off)
+}
+
+// Seek moves the read/write head offset of the File.
+func (f *File) Seek(offset int64, whence int) (int64, error) {
+ status, off, err := f.FileInterface().Seek(offset, io.SeekOrigin(whence))
+ if err != nil {
+ return -1, err
+ } else if zx.Status(status) != zx.ErrOk {
+ return -1, &zx.Error{Status: zx.Status(status), Text: "io.file"}
+ }
+ return int64(off), nil
+}
+
+// Truncate truncates a File.
+func (f *File) Truncate(length uint64) error {
+ status, err := f.FileInterface().Truncate(length)
+ if err != nil {
+ return err
+ } else if zx.Status(status) != zx.ErrOk {
+ return &zx.Error{Status: zx.Status(status), Text: "io.file"}
+ }
+ return nil
+}
diff --git a/src/syscall/zx/fdio/logger.go b/src/syscall/zx/fdio/logger.go
new file mode 100644
index 0000000..bd54aa9
--- /dev/null
+++ b/src/syscall/zx/fdio/logger.go
@@ -0,0 +1,156 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build fuchsia
+
+package fdio
+
+import (
+ "syscall/zx"
+ "syscall/zx/io"
+)
+
+// #define LOGBUF_MAX (ZX_LOG_RECORD_MAX - sizeof(zx_log_record_t))
+const logBufMax = 224
+
+type Logger struct {
+ log zx.Log
+ logBufferArray [logBufMax]byte
+ logBufferN int
+}
+
+func NewLogger(log zx.Log) *Logger {
+ return &Logger{log: log}
+}
+
+// Clone makes a clone of the object.
+func (f *Logger) Clone() (FDIO, error) {
+ logHandle := zx.Handle(f.log)
+ h, err := logHandle.Duplicate(zx.RightSameRights)
+ if err != nil {
+ return nil, err
+ }
+ return NewLogger(zx.Log(h)), nil
+}
+
+// Handle returns the underlying log handle as an untyped handle.
+func (f *Logger) Handles() []zx.Handle {
+ return []zx.Handle{zx.Handle(f.log)}
+}
+
+// Close closes the object.
+func (f *Logger) Close() error {
+ return f.log.Close()
+}
+
+// Sync implements FDIO for Logger.
+func (f *Logger) Sync() error {
+ return &zx.Error{Status: zx.ErrNotSupported, Text: "fdio.logger"}
+}
+
+// GetAttr implements FDIO for Logger.
+func (f *Logger) GetAttr() (io.NodeAttributes, error) {
+ return io.NodeAttributes{}, &zx.Error{Status: zx.ErrNotSupported, Text: "fdio.logger"}
+}
+
+// SetAttr implements FDIO for Logger.
+func (f *Logger) SetAttr(flags uint32, attr io.NodeAttributes) error {
+ return &zx.Error{Status: zx.ErrNotSupported, Text: "fdio.logger"}
+}
+
+// Ioctl implements FDIO for Logger.
+func (f *Logger) Ioctl(op uint32, max uint64, in []byte, handles []zx.Handle) ([]byte, []zx.Handle, error) {
+ return nil, nil, &zx.Error{Status: zx.ErrNotSupported, Text: "fdio.logger"}
+}
+
+// Read implements FDIO for Logger.
+func (f *Logger) Read(data []byte) (int, error) {
+ return 0, &zx.Error{Status: zx.ErrNotSupported, Text: "fdio.logger"}
+}
+
+// ReadAt implements FDIO for Logger.
+func (f *Logger) ReadAt(data []byte, off int64) (int, error) {
+ return 0, &zx.Error{Status: zx.ErrNotSupported, Text: "fdio.logger"}
+}
+
+// Write implements FDIO for Logger.
+func (f *Logger) Write(data []byte) (int, error) {
+ written := 0
+
+ for i := 0; i < len(data); i++ {
+ c := data[i]
+ written++
+
+ if c == '\n' {
+ _, err := f.log.Write(f.logBufferArray[:f.logBufferN])
+ f.logBufferN = 0
+ if err != nil {
+ return written, err
+ }
+ continue
+ }
+
+ if c < ' ' {
+ continue
+ }
+
+ f.logBufferArray[f.logBufferN] = c
+ f.logBufferN++
+
+ if f.logBufferN == len(f.logBufferArray) {
+ _, err := f.log.Write(f.logBufferArray[:f.logBufferN])
+ f.logBufferN = 0
+ if err != nil {
+ return written, err
+ }
+ }
+ }
+
+ return written, nil
+}
+
+// WriteAt implements FDIO for Logger.
+func (f *Logger) WriteAt(data []byte, off int64) (int, error) {
+ return 0, &zx.Error{Status: zx.ErrNotSupported, Text: "fdio.logger"}
+}
+
+// Seek implements FDIO for Logger.
+func (f *Logger) Seek(offset int64, whence int) (int64, error) {
+ return 0, &zx.Error{Status: zx.ErrNotSupported, Text: "fdio.logger"}
+}
+
+// Truncate implements FDIO for Logger.
+func (f *Logger) Truncate(length uint64) error {
+ return &zx.Error{Status: zx.ErrNotSupported, Text: "fdio.logger"}
+}
+
+// Open implements FDIO for Logger.
+func (f *Logger) Open(path string, flags uint32, mode uint32) (FDIO, error) {
+ return nil, &zx.Error{Status: zx.ErrNotSupported, Text: "fdio.logger"}
+}
+
+// Link implements FDIO for Logger.
+func (f *Logger) Link(oldpath, newpath string) error {
+ return &zx.Error{Status: zx.ErrNotSupported, Text: "fdio.logger"}
+}
+
+// Rename implements FDIO for Logger.
+func (f *Logger) Rename(oldpath, newpath string) error {
+ return &zx.Error{Status: zx.ErrNotSupported, Text: "fdio.logger"}
+}
+
+// Unlink implements FDIO for Logger.
+func (f *Logger) Unlink(path string) error {
+ return &zx.Error{Status: zx.ErrNotSupported, Text: "fdio.logger"}
+}
+
+// ReadDirents implements FDIO for Logger.
+func (f *Logger) ReadDirents(max uint64) ([]byte, error) {
+ return nil, &zx.Error{Status: zx.ErrNotSupported, Text: "fdio.logger"}
+}
+
+// Rewind implements FDIO for Logger.
+func (f *Logger) Rewind() error {
+ return &zx.Error{Status: zx.ErrNotSupported, Text: "fdio.logger"}
+}
diff --git a/src/syscall/zx/fdio/namespace.go b/src/syscall/zx/fdio/namespace.go
new file mode 100644
index 0000000..bbed032
--- /dev/null
+++ b/src/syscall/zx/fdio/namespace.go
@@ -0,0 +1,384 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build fuchsia
+
+package fdio
+
+import (
+ "sync"
+ "syscall/zx"
+ "syscall/zx/fidl"
+ "syscall/zx/io"
+)
+
+type NS struct {
+ mu sync.Mutex
+ m map[string]zx.Handle
+}
+
+func NewNS() *NS {
+ return &NS{m: make(map[string]zx.Handle)}
+}
+
+func NewNSFromMap(m map[string]zx.Handle) (*NS, error) {
+ if m == nil {
+ return nil, &zx.Error{Status: zx.ErrInvalidArgs, Text: "namespace.NewFromNSMAP"}
+ }
+ ns := &NS{m: make(map[string]zx.Handle)}
+ for k, v := range m {
+ ns.m[k] = v
+ }
+ return ns, nil
+}
+
+func (ns *NS) Bind(p string, h zx.Handle) {
+ ns.mu.Lock()
+ ns.m[p] = h
+ ns.mu.Unlock()
+}
+
+func (ns *NS) Connect(p string, h zx.Handle) error {
+ if p[0] != '/' {
+ h.Close()
+ return &zx.Error{Status: zx.ErrNotFound, Text: "namespace.Connect"}
+ }
+ node := p
+ for {
+ ns.mu.Lock()
+ svcHandle := ns.m[node]
+ ns.mu.Unlock()
+ if svcHandle.IsValid() {
+ rest := trimPrefix(p, node)
+ rest = trimPrefix(rest, "/")
+ return ServiceConnectAt(svcHandle, rest, h)
+ }
+ if node == "/" {
+ break
+ }
+ node = pathDir(node)
+ }
+ h.Close()
+ return &zx.Error{Status: zx.ErrNotFound, Text: "namespace.Connect"}
+}
+
+func (ns *NS) OpenRoot() (FDIO, error) {
+ root := &vnode{}
+ ns.mu.Lock()
+ defer ns.mu.Unlock()
+ for path, h := range ns.m {
+ if path == "" || path[0] != '/' {
+ return nil, &zx.Error{Status: zx.ErrBadPath, Text: "fdio.OpenRoot"}
+ }
+ vn := root
+ path = path[1:]
+ for path != "" {
+ name, remaining := pathSplitForward(path)
+ vn = vn.getOrAddChild(name)
+ path = remaining
+ }
+ if vn.remote.IsValid() {
+ return nil, &zx.Error{Status: zx.ErrAlreadyExists, Text: "fdio.OpenRoot"}
+ }
+ obj := (*io.NodeInterface)(&fidl.ChannelProxy{Channel: zx.Channel(h)})
+ vn.remote = Directory{Node: Node{obj}}
+ }
+ return &dir{root}, nil
+}
+
+// vnode is a virtual node in the namespace "filesystem".
+type vnode struct {
+ child *vnode
+ parent *vnode
+ next *vnode
+ remote Directory
+ name string
+}
+
+func (vn *vnode) getOrAddChild(name string) *vnode {
+ child := vn.getChild(name)
+ if child == nil {
+ child = &vnode{
+ parent: vn,
+ next: vn.child,
+ name: name,
+ }
+ vn.child = child
+ }
+ return child
+}
+
+func (vn *vnode) getChild(name string) *vnode {
+ for vn = vn.child; vn != nil; vn = vn.next {
+ if vn.name == name {
+ return vn
+ }
+ }
+ return nil
+}
+
+// dir represents a directory in the namespace.
+type dir struct {
+ vn *vnode
+}
+
+// Handle returns the underlying handle as an untyped handle.
+func (d *dir) Handles() []zx.Handle {
+ return d.vn.remote.Handles()
+}
+
+// Clone makes a clone of the dir, if possible.
+func (d *dir) Clone() (FDIO, error) {
+ if !d.vn.remote.IsValid() {
+ return nil, &zx.Error{Status: zx.ErrNotSupported, Text: "fdio.ns.dir"}
+ }
+ return d.vn.remote.Clone()
+}
+
+// Close closes the dir.
+func (d *dir) Close() error {
+ if !d.vn.remote.IsValid() {
+ return nil
+ }
+ return d.vn.remote.Close()
+}
+
+// Sync implements FDIO for dir.
+func (d *dir) Sync() error {
+ return &zx.Error{Status: zx.ErrNotSupported, Text: "fdio.ns.dir"}
+}
+
+// GetAttr implements FDIO for dir.
+func (d *dir) GetAttr() (io.NodeAttributes, error) {
+ return io.NodeAttributes{
+ Mode: uint32(io.ModeTypeDirectory) | uint32(VtypeIRUSR),
+ Id: 1,
+ LinkCount: 1,
+ }, nil
+}
+
+// SetAttr implements FDIO for dir.
+func (d *dir) SetAttr(flags uint32, attr io.NodeAttributes) error {
+ return &zx.Error{Status: zx.ErrNotSupported, Text: "fdio.ns.dir"}
+}
+
+// Ioctl implements FDIO for dir.
+func (d *dir) Ioctl(op uint32, max uint64, in []byte, handles []zx.Handle) ([]byte, []zx.Handle, error) {
+ return nil, nil, &zx.Error{Status: zx.ErrNotSupported, Text: "fdio.ns.dir"}
+}
+
+func (d *dir) Read(data []byte) (int, error) {
+ return 0, &zx.Error{Status: zx.ErrNotSupported, Text: "fdio.dir"}
+}
+
+func (d *dir) ReadAt(data []byte, off int64) (int, error) {
+ return 0, &zx.Error{Status: zx.ErrNotSupported, Text: "fdio.dir"}
+}
+
+func (d *dir) Write(data []byte) (n int, err error) {
+ return 0, &zx.Error{Status: zx.ErrNotSupported, Text: "fdio.dir"}
+}
+
+func (d *dir) WriteAt(data []byte, off int64) (int, error) {
+ return 0, &zx.Error{Status: zx.ErrNotSupported, Text: "fdio.dir"}
+}
+
+func (d *dir) Seek(offset int64, whence int) (int64, error) {
+ return 0, &zx.Error{Status: zx.ErrNotSupported, Text: "fdio.dir"}
+}
+
+// Truncate implements FDIO for dir.
+func (d *dir) Truncate(length uint64) error {
+ return &zx.Error{Status: zx.ErrNotSupported, Text: "fdio.ns.dir"}
+}
+
+func (d *dir) getVnode(path string) (vn *vnode, rpath string, isRemote bool, err error) {
+ vn = d.vn
+
+ if path == "." || path == "" {
+ if vn.remote.IsValid() {
+ return vn, ".", true, nil
+ }
+ return vn, "", false, nil
+ }
+
+ originalPath := path
+
+ var savedVn *vnode
+ var savedPath string
+
+ for {
+ name, remaining := pathSplitForward(path)
+
+ if name == "" {
+ return nil, "", false, &zx.Error{Status: zx.ErrBadPath, Text: path}
+ }
+
+ child := vn.getChild(name)
+
+ if child != nil {
+ if remaining == "" {
+ // We've resolved all the path segments and found the vnode we're
+ // looking for.
+ if child.remote.IsValid() {
+ return child, ".", true, nil
+ } else {
+ return child, "", false, nil
+ }
+ } else {
+ // We've got more path to resolve.
+ vn = child
+ path = remaining
+
+ // If this child has a remote file system, we might hand off to
+ // this remote if we don't find anything more specific below
+ // this vnode.
+ if child.remote.IsValid() {
+ savedVn = vn
+ savedPath = path
+ }
+
+ continue
+ }
+ }
+
+ // We've reached the end of our local vnode structure with more
+ // path to resolve.
+
+ if vn.remote.IsValid() {
+ // We've got a remote file system at this vnode. We can hand off
+ // directly to that file system.
+ return vn, path, true, nil
+ }
+
+ // We saw a remote file system earlier in our walk that might have this
+ // path. Let's hand off to it.
+ if savedVn != nil {
+ return savedVn, savedPath, true, nil
+ }
+
+ // There is no remote file system to resolve the path against,
+ // which means we failed to find what we were looking for.
+ return nil, "", false, &zx.Error{Status: zx.ErrNotFound, Text: originalPath}
+ }
+}
+
+// Open implements FDIO for dir.
+func (d *dir) Open(pathname string, flags uint32, mode uint32) (FDIO, error) {
+ vn, relp, isRemote, err := d.getVnode(pathname)
+ if err != nil {
+ return nil, err
+ }
+ if isRemote {
+ return vn.remote.Open(relp, flags, mode)
+ }
+ return &dir{vn}, nil
+}
+
+func (d *dir) openParent(pathname string) (FDIO, string, error) {
+ dirpath, name := pathSplit(pathname)
+ parent, err := d.Open(
+ pathDir(dirpath),
+ io.OpenRightReadable|io.OpenFlagDirectory|io.OpenFlagPosix,
+ S_IFDIR)
+ if err != nil {
+ return nil, "", err
+ }
+ return parent, name, err
+}
+
+// Link implements FDIO for dir.
+func (d *dir) Link(oldpath, newpath string) error {
+ oldparent, oldname, err := d.openParent(oldpath)
+ if err != nil {
+ return err
+ }
+ defer oldparent.Close()
+ newparent, newname, err := d.openParent(newpath)
+ if err != nil {
+ return err
+ }
+ defer newparent.Close()
+ olddir, ok := oldparent.(*Directory)
+ if !ok {
+ return &zx.Error{Status: zx.ErrNotSupported, Text: "fdio.ns.dir"}
+ }
+ newdir, ok := newparent.(*Directory)
+ if !ok {
+ return &zx.Error{Status: zx.ErrNotSupported, Text: "fdio.ns.dir"}
+ }
+ token, err := newdir.getToken()
+ if err != nil {
+ return err
+ }
+ status, err := olddir.DirectoryInterface().Link(oldname, token, newname)
+ if err != nil {
+ return err
+ } else if zx.Status(status) != zx.ErrOk {
+ return &zx.Error{Status: zx.Status(status), Text: "fdio.ns.dir"}
+ }
+ return nil
+}
+
+// Rename implements FDIO for dir.
+func (d *dir) Rename(oldpath, newpath string) error {
+ oldf, oldname, err := d.openParent(oldpath)
+ if err != nil {
+ return err
+ }
+ defer oldf.Close()
+ newf, newname, err := d.openParent(newpath)
+ if err != nil {
+ return err
+ }
+ defer newf.Close()
+ olddir, ok := oldf.(*Directory)
+ if !ok {
+ return &zx.Error{Status: zx.ErrNotSupported, Text: "fdio.ns.dir"}
+ }
+ newdir, ok := newf.(*Directory)
+ if !ok {
+ return &zx.Error{Status: zx.ErrNotSupported, Text: "fdio.ns.dir"}
+ }
+ token, err := newdir.getToken()
+ if err != nil {
+ return err
+ }
+ status, err := olddir.DirectoryInterface().Rename(oldname, token, newname)
+ if err != nil {
+ return err
+ } else if zx.Status(status) != zx.ErrOk {
+ return &zx.Error{Status: zx.Status(status), Text: "fdio.ns.dir"}
+ }
+ return nil
+}
+
+// Unlink implements FDIO for dir.
+func (d *dir) Unlink(pathname string) error {
+ parent, name, err := d.openParent(pathname)
+ if err != nil {
+ return err
+ }
+ defer parent.Close()
+ parentdir, ok := parent.(*Directory)
+ if !ok {
+ return &zx.Error{Status: zx.ErrNotSupported, Text: "fdio.ns.dir"}
+ }
+ if status, err := parentdir.DirectoryInterface().Unlink(name); err != nil {
+ return err
+ } else if zx.Status(status) != zx.ErrOk {
+ return &zx.Error{Status: zx.Status(status), Text: "fdio.ns.dir"}
+ }
+ return nil
+}
+
+// ReadDirents implements FDIO for dir.
+func (d *dir) ReadDirents(max uint64) ([]byte, error) {
+ return nil, &zx.Error{Status: zx.ErrNotSupported, Text: "fdio.ns.dir"}
+}
+
+// Rewind implements FDIO for dir.
+func (d *dir) Rewind() error {
+ return &zx.Error{Status: zx.ErrNotSupported, Text: "fdio.ns.dir"}
+}
diff --git a/src/syscall/zx/fdio/node.go b/src/syscall/zx/fdio/node.go
new file mode 100644
index 0000000..68beb56
--- /dev/null
+++ b/src/syscall/zx/fdio/node.go
@@ -0,0 +1,214 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build fuchsia
+
+package fdio
+
+import (
+ "syscall/zx"
+ "syscall/zx/fidl"
+ "syscall/zx/io"
+)
+
+func nodeFromInfo(info *io.NodeInfo, node *io.NodeInterface) (result FDIO, err error) {
+ if info == nil {
+ if err = ((*fidl.ChannelProxy)(node)).Channel.Close(); err != nil {
+ return nil, err
+ }
+ return nil, &zx.Error{Status: zx.ErrNotSupported, Text: "io.node"}
+ }
+ switch info.NodeInfoTag {
+ case io.NodeInfoService:
+ // TODO(mknyszek): Figure out the correct type to return here.
+ result = &Node{NodeInterface: node}
+ case io.NodeInfoFile:
+ result = &File{
+ Node: Node{NodeInterface: node},
+ Event: info.File.Event,
+ }
+ case io.NodeInfoDevice:
+ result = &File{
+ Node: Node{NodeInterface: node},
+ Event: info.Device.Event,
+ }
+ case io.NodeInfoDirectory:
+ result = &Directory{Node: Node{NodeInterface: node}}
+ case io.NodeInfoPipe:
+ if err = ((*fidl.ChannelProxy)(node)).Channel.Close(); err != nil {
+ return nil, err
+ }
+ result = NewPipe(info.Pipe.Socket)
+ case io.NodeInfoVmofile:
+ if err = ((*fidl.ChannelProxy)(node)).Channel.Close(); err != nil {
+ return nil, err
+ }
+ result, err = NewVMOFile(info.Vmofile.Vmo, info.Vmofile.Offset, info.Vmofile.Length)
+ if err != nil {
+ return nil, err
+ }
+ default:
+ if err = ((*fidl.ChannelProxy)(node)).Channel.Close(); err != nil {
+ return nil, err
+ }
+ return nil, &zx.Error{Status: zx.ErrNotSupported, Text: "io.node"}
+ }
+ return result, nil
+}
+
+// Node is a wrapper around an NodeInterface which implements FDIO.
+type Node struct {
+ *io.NodeInterface
+}
+
+// IsValid returns true if the Node is valid.
+func (n *Node) IsValid() bool {
+ if n.NodeInterface == nil {
+ return false
+ }
+ return ((*fidl.ChannelProxy)(n.NodeInterface)).IsValid()
+}
+
+// Handles returns a slice of untyped zx handles containing the underlying
+// channel of the Node.
+func (n *Node) Handles() []zx.Handle {
+ return []zx.Handle{
+ zx.Handle(((*fidl.ChannelProxy)(n.NodeInterface)).Channel),
+ }
+}
+
+// Clone makes a clone of the node.
+func (n *Node) Clone() (FDIO, error) {
+ req, newNode, err := io.NewNodeInterfaceRequest()
+ if err != nil {
+ return nil, err
+ }
+ cloneFlag := io.CloneFlagSameRights | io.OpenFlagDescribe
+ if err := n.NodeInterface.Clone(cloneFlag, req); err != nil {
+ ((*fidl.ChannelProxy)(newNode)).Close()
+ return nil, err
+ }
+ status, info, err := newNode.ExpectOnOpen()
+ if err != nil {
+ ((*fidl.ChannelProxy)(newNode)).Close()
+ return nil, err
+ } else if zx.Status(status) != zx.ErrOk {
+ ((*fidl.ChannelProxy)(newNode)).Close()
+ return nil, &zx.Error{Status: zx.Status(status), Text: "io.node"}
+ }
+ return nodeFromInfo(info, newNode)
+}
+
+// Close closes the node.
+func (n *Node) Close() error {
+ defer ((*fidl.ChannelProxy)(n.NodeInterface)).Close()
+ if status, err := n.NodeInterface.Close(); err != nil {
+ return err
+ } else if zx.Status(status) != zx.ErrOk {
+ return &zx.Error{Status: zx.Status(status), Text: "io.node"}
+ }
+ return nil
+}
+
+// Sync performs a sync operation on a Node.
+func (n *Node) Sync() error {
+ if status, err := n.NodeInterface.Sync(); err != nil {
+ return err
+ } else if zx.Status(status) != zx.ErrOk {
+ return &zx.Error{Status: zx.Status(status), Text: "io.node"}
+ }
+ return nil
+}
+
+// GetAttr returns the attributes for the Node.
+func (n *Node) GetAttr() (io.NodeAttributes, error) {
+ status, attrs, err := n.NodeInterface.GetAttr()
+ if err != nil {
+ return io.NodeAttributes{}, err
+ } else if zx.Status(status) != zx.ErrOk {
+ return io.NodeAttributes{}, &zx.Error{Status: zx.Status(status), Text: "io.node"}
+ }
+ return attrs, nil
+}
+
+// SetAttr sets the attributes for Node as defined by flags.
+func (n *Node) SetAttr(flags uint32, attr io.NodeAttributes) error {
+ if status, err := n.NodeInterface.SetAttr(flags, attr); err != nil {
+ return err
+ } else if zx.Status(status) != zx.ErrOk {
+ return &zx.Error{Status: zx.Status(status), Text: "io.node"}
+ }
+ return nil
+}
+
+// Ioctl calls an ioctl on Node.
+func (n *Node) Ioctl(op uint32, max uint64, in []byte, handles []zx.Handle) ([]byte, []zx.Handle, error) {
+ status, h, b, err := n.NodeInterface.Ioctl(op, max, handles, in)
+ if err != nil {
+ return nil, nil, err
+ } else if zx.Status(status) != zx.ErrOk {
+ return nil, nil, &zx.Error{Status: zx.Status(status), Text: "io.node"}
+ }
+ return b, h, nil
+}
+
+// Read implements FDIO for Node.
+func (n *Node) Read(data []byte) (int, error) {
+ return 0, &zx.Error{Status: zx.ErrNotSupported, Text: "io.node"}
+}
+
+// ReadAt implements FDIO for Node.
+func (n *Node) ReadAt(data []byte, off int64) (int, error) {
+ return 0, &zx.Error{Status: zx.ErrNotSupported, Text: "io.node"}
+}
+
+// Write implements FDIO for Node.
+func (n *Node) Write(data []byte) (int, error) {
+ return 0, &zx.Error{Status: zx.ErrNotSupported, Text: "io.node"}
+}
+
+// WriteAt implements FDIO for Node.
+func (n *Node) WriteAt(data []byte, off int64) (int, error) {
+ return 0, &zx.Error{Status: zx.ErrNotSupported, Text: "io.node"}
+}
+
+// Seek implements FDIO for Node.
+func (n *Node) Seek(offset int64, whence int) (int64, error) {
+ return 0, &zx.Error{Status: zx.ErrNotSupported, Text: "io.node"}
+}
+
+// Truncate implements FDIO for Node.
+func (n *Node) Truncate(length uint64) error {
+ return &zx.Error{Status: zx.ErrNotSupported, Text: "io.node"}
+}
+
+// Open implements FDIO for Node.
+func (n *Node) Open(path string, flags uint32, mode uint32) (FDIO, error) {
+ return nil, &zx.Error{Status: zx.ErrNotSupported, Text: "io.node"}
+}
+
+// Link implements FDIO for Node.
+func (n *Node) Link(oldpath, newpath string) error {
+ return &zx.Error{Status: zx.ErrNotSupported, Text: "io.node"}
+}
+
+// Rename implements FDIO for Node.
+func (n *Node) Rename(oldpath, newpath string) error {
+ return &zx.Error{Status: zx.ErrNotSupported, Text: "io.node"}
+}
+
+// Unlink implements FDIO for Node.
+func (n *Node) Unlink(path string) error {
+ return &zx.Error{Status: zx.ErrNotSupported, Text: "io.node"}
+}
+
+// ReadDirents implements FDIO for Node.
+func (n *Node) ReadDirents(max uint64) ([]byte, error) {
+ return nil, &zx.Error{Status: zx.ErrNotSupported, Text: "io.node"}
+}
+
+// Rewind implements FDIO for Node.
+func (n *Node) Rewind() error {
+ return &zx.Error{Status: zx.ErrNotSupported, Text: "io.node"}
+}
diff --git a/src/syscall/zx/fdio/path.go b/src/syscall/zx/fdio/path.go
new file mode 100644
index 0000000..d4a7da0
--- /dev/null
+++ b/src/syscall/zx/fdio/path.go
@@ -0,0 +1,169 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+//
+// This file contains implementations of various path functions we need to support
+// without importing the path or strings packages.
+//
+// +build fuchsia
+
+package fdio
+
+import "internal/bytealg"
+
+// pathSplitForward has special path splitting semantics for vnode / service connect.
+// It differs from path.Split primarily in that it begins searching for path
+// separators from the front of the path, as opposed to from the back. The
+// semantics for various other path types also differ:
+// * Rooted paths, or paths not containing a file name (i.e. slash is the last
+// character in the path) results in empty strings returned for directory and
+// file.
+// * Paths containing no slash return the whole path as the directory.
+func pathSplitForward(path string) (dir, file string) {
+ slash := bytealg.IndexByte([]byte(path), '/')
+ if slash == 0 || slash == len(path)-1 {
+ return "", ""
+ } else if slash == -1 {
+ return path, ""
+ } else {
+ return path[:slash], path[slash+1:]
+ }
+}
+
+// pathSplit is an implementation of path.Split that additionally implements
+// strings.LastIndex to avoid a dependency on both the path and strings
+// package.
+func pathSplit(path string) (dir, file string) {
+ var i int
+ for i = len(path) - 1; i >= 0; i-- {
+ if path[i] == '/' {
+ break
+ }
+ }
+
+ return path[:i+1], path[i+1:]
+}
+
+// pathDir is an implementation of path.Dir.
+func pathDir(path string) string {
+ dir, _ := pathSplit(path)
+ return pathClean(dir)
+}
+
+// trimPrefix is an implementation of strings.TrimPrefix.
+func trimPrefix(path, prefix string) string {
+ if path[:len(prefix)] == prefix {
+ return path[len(prefix):]
+ }
+ return path
+}
+
+// The following is copied verbatim from the path package to implement
+// path.Clean. This is done to avoid a dependency on the path package,
+// though it is unfortunate to have the code duplicated.
+
+// A lazybuf is a lazily constructed path buffer.
+// It supports append, reading previously appended bytes,
+// and retrieving the final string. It does not allocate a buffer
+// to hold the output until that output diverges from s.
+type lazybuf struct {
+ s string
+ buf []byte
+ w int
+}
+
+func (b *lazybuf) index(i int) byte {
+ if b.buf != nil {
+ return b.buf[i]
+ }
+ return b.s[i]
+}
+
+func (b *lazybuf) append(c byte) {
+ if b.buf == nil {
+ if b.w < len(b.s) && b.s[b.w] == c {
+ b.w++
+ return
+ }
+ b.buf = make([]byte, len(b.s))
+ copy(b.buf, b.s[:b.w])
+ }
+ b.buf[b.w] = c
+ b.w++
+}
+
+func (b *lazybuf) string() string {
+ if b.buf == nil {
+ return b.s[:b.w]
+ }
+ return string(b.buf[:b.w])
+}
+
+// pathClean is copied verbatim from path.Clean.
+func pathClean(path string) string {
+ if path == "" {
+ return "."
+ }
+
+ rooted := path[0] == '/'
+ n := len(path)
+
+ // Invariants:
+ // reading from path; r is index of next byte to process.
+ // writing to buf; w is index of next byte to write.
+ // dotdot is index in buf where .. must stop, either because
+ // it is the leading slash or it is a leading ../../.. prefix.
+ out := lazybuf{s: path}
+ r, dotdot := 0, 0
+ if rooted {
+ out.append('/')
+ r, dotdot = 1, 1
+ }
+
+ for r < n {
+ switch {
+ case path[r] == '/':
+ // empty path element
+ r++
+ case path[r] == '.' && (r+1 == n || path[r+1] == '/'):
+ // . element
+ r++
+ case path[r] == '.' && path[r+1] == '.' && (r+2 == n || path[r+2] == '/'):
+ // .. element: remove to last /
+ r += 2
+ switch {
+ case out.w > dotdot:
+ // can backtrack
+ out.w--
+ for out.w > dotdot && out.index(out.w) != '/' {
+ out.w--
+ }
+ case !rooted:
+ // cannot backtrack, but not rooted, so append .. element.
+ if out.w > 0 {
+ out.append('/')
+ }
+ out.append('.')
+ out.append('.')
+ dotdot = out.w
+ }
+ default:
+ // real path element.
+ // add slash if needed
+ if rooted && out.w != 1 || !rooted && out.w != 0 {
+ out.append('/')
+ }
+ // copy element
+ for ; r < n && path[r] != '/'; r++ {
+ out.append(path[r])
+ }
+ }
+ }
+
+ // Turn empty string into "."
+ if out.w == 0 {
+ return "."
+ }
+
+ return out.string()
+}
diff --git a/src/syscall/zx/fdio/pipe.go b/src/syscall/zx/fdio/pipe.go
new file mode 100644
index 0000000..d8468198
--- /dev/null
+++ b/src/syscall/zx/fdio/pipe.go
@@ -0,0 +1,167 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build fuchsia
+
+package fdio
+
+import (
+ "syscall/zx"
+ "syscall/zx/io"
+ "syscall/zx/zxwait"
+)
+
+type Pipe struct {
+ s zx.Socket
+}
+
+func NewPipes() (*Pipe, *Pipe, error) {
+ s0, s1, err := zx.NewSocket(0)
+ if err != nil {
+ return nil, nil, err
+ }
+ return &Pipe{s0}, &Pipe{s1}, nil
+}
+
+func NewPipe(s zx.Socket) *Pipe {
+ return &Pipe{s}
+}
+
+func (f *Pipe) Wait(signals zx.Signals, timeout zx.Time) (observed zx.Signals, err error) {
+ return zxwait.Wait(zx.Handle(f.s), signals, timeout)
+}
+
+func (f *Pipe) Handles() []zx.Handle {
+ return []zx.Handle{zx.Handle(f.s)}
+}
+
+func (f *Pipe) Clone() (FDIO, error) {
+ h, err := f.s.Handle().Duplicate(zx.RightSameRights)
+ if err != nil {
+ return nil, err
+ }
+ return NewPipe(zx.Socket(h)), nil
+}
+
+func (f *Pipe) Close() error {
+ if err := f.s.Close(); err != nil {
+ return err
+ }
+ f.s = zx.Socket(zx.HandleInvalid)
+ return nil
+}
+
+func (f *Pipe) Sync() error {
+ return &zx.Error{Status: zx.ErrNotSupported, Text: "fdio.Pipe"}
+}
+
+func (f *Pipe) GetAttr() (io.NodeAttributes, error) {
+ return io.NodeAttributes{}, &zx.Error{Status: zx.ErrNotSupported, Text: "fdio.Pipe"}
+}
+
+func (f *Pipe) SetAttr(flags uint32, attr io.NodeAttributes) error {
+ return &zx.Error{Status: zx.ErrNotSupported, Text: "fdio.Pipe"}
+}
+
+func (f *Pipe) Ioctl(op uint32, max uint64, in []byte, handles []zx.Handle) ([]byte, []zx.Handle, error) {
+ return nil, nil, &zx.Error{Status: zx.ErrNotSupported, Text: "fdio.Pipe"}
+}
+
+func (f *Pipe) Read(data []byte) (int, error) {
+ for {
+ n, err := f.s.Read(data, 0)
+ if err != nil {
+ if err, ok := err.(*zx.Error); ok {
+ switch err.Status {
+ case zx.ErrPeerClosed:
+ return 0, zx.EOF
+ case zx.ErrShouldWait:
+ pending, err := f.Wait(zx.SignalSocketReadable|zx.SignalSocketPeerClosed, zx.TimensecInfinite)
+ if err != nil {
+ return 0, err
+ }
+ if pending&zx.SignalSocketReadable != 0 {
+ continue
+ }
+ if pending&zx.SignalSocketPeerClosed != 0 {
+ return 0, zx.EOF
+ }
+ // impossible
+ return 0, &zx.Error{Status: zx.ErrInternal, Text: "fdio.Pipe"}
+ }
+ }
+ return 0, err
+ }
+ return n, nil
+ }
+}
+
+func (f *Pipe) ReadAt(data []byte, off int64) (int, error) {
+ return 0, &zx.Error{Status: zx.ErrNotSupported, Text: "fdio.Pipe"}
+}
+
+func (f *Pipe) Write(data []byte) (int, error) {
+ for {
+ n, err := f.s.Write(data, 0)
+ if err != nil {
+ if err, ok := err.(*zx.Error); ok {
+ switch err.Status {
+ case zx.ErrPeerClosed:
+ return 0, zx.EPIPE
+ case zx.ErrShouldWait:
+ pending, err := f.Wait(zx.SignalSocketWritable|zx.SignalSocketPeerClosed, zx.TimensecInfinite)
+ if err != nil {
+ return 0, err
+ }
+ if pending&zx.SignalSocketWritable != 0 {
+ continue
+ }
+ if pending&zx.SignalSocketPeerClosed != 0 {
+ return 0, zx.EPIPE
+ }
+ // impossible
+ return 0, &zx.Error{Status: zx.ErrInternal, Text: "fdio.Pipe"}
+ }
+ }
+ return 0, err
+ }
+ return n, nil
+ }
+}
+
+func (f *Pipe) WriteAt(data []byte, off int64) (int, error) {
+ return 0, &zx.Error{Status: zx.ErrNotSupported, Text: "fdio.Pipe"}
+}
+
+func (f *Pipe) Seek(offset int64, whence int) (int64, error) {
+ return 0, &zx.Error{Status: zx.ErrNotSupported, Text: "fdio.Pipe"}
+}
+
+func (f *Pipe) Truncate(length uint64) error {
+ return &zx.Error{Status: zx.ErrNotSupported, Text: "fdio.Pipe"}
+}
+
+func (f *Pipe) Open(path string, flags uint32, mode uint32) (FDIO, error) {
+ return nil, &zx.Error{Status: zx.ErrNotSupported, Text: "fdio.Pipe"}
+}
+
+func (f *Pipe) Link(oldpath, newpath string) error {
+ return &zx.Error{Status: zx.ErrNotSupported, Text: "fdio.Pipe"}
+}
+
+func (f *Pipe) Rename(oldpath, newpath string) error {
+ return &zx.Error{Status: zx.ErrNotSupported, Text: "fdio.Pipe"}
+}
+
+func (f *Pipe) Unlink(path string) error {
+ return &zx.Error{Status: zx.ErrNotSupported, Text: "fdio.Pipe"}
+}
+
+func (f *Pipe) ReadDirents(max uint64) ([]byte, error) {
+ return nil, &zx.Error{Status: zx.ErrNotSupported, Text: "fdio.Pipe"}
+}
+
+func (f *Pipe) Rewind() error {
+ return &zx.Error{Status: zx.ErrNotSupported, Text: "fdio.Pipe"}
+}
diff --git a/src/syscall/zx/fdio/stub.go b/src/syscall/zx/fdio/stub.go
new file mode 100644
index 0000000..07623ab
--- /dev/null
+++ b/src/syscall/zx/fdio/stub.go
@@ -0,0 +1,3 @@
+//+build !fuchsia
+
+package fdio
diff --git a/src/syscall/zx/fdio/vmo.go b/src/syscall/zx/fdio/vmo.go
new file mode 100644
index 0000000..b3c2a6a
--- /dev/null
+++ b/src/syscall/zx/fdio/vmo.go
@@ -0,0 +1,161 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build fuchsia
+
+package fdio
+
+import (
+ "syscall/zx"
+ "syscall/zx/io"
+)
+
+type VMOFile struct {
+ h zx.VMO
+ off int64
+ len int64
+ end int64
+ at int64
+}
+
+func NewVMOFile(handle zx.VMO, offset uint64, length uint64) (*VMOFile, error) {
+ // fdio_vmofile_create
+ f := &VMOFile{
+ h: handle,
+ off: int64(offset),
+ len: int64(length),
+ }
+ f.end = f.off + f.len
+ f.at = f.off
+ return f, nil
+}
+
+func (f *VMOFile) Handles() []zx.Handle {
+ return []zx.Handle{zx.Handle(f.h)}
+}
+
+func (f *VMOFile) Clone() (FDIO, error) {
+ return nil, &zx.Error{Status: zx.ErrNotSupported, Text: "fdio.VMOFile"}
+}
+
+func (f *VMOFile) Close() error {
+ if err := f.h.Close(); err != nil {
+ return err
+ }
+ f.h = 0
+ return nil
+}
+
+func (f *VMOFile) Sync() error {
+ return &zx.Error{Status: zx.ErrNotSupported, Text: "fdio.VMOFile"}
+}
+
+func (f *VMOFile) GetAttr() (io.NodeAttributes, error) {
+ return io.NodeAttributes{
+ ContentSize: uint64(f.len),
+ StorageSize: uint64(f.len),
+ Mode: uint32(io.ModeTypeFile) | uint32(VtypeIRUSR),
+ }, nil
+}
+
+func (f *VMOFile) SetAttr(flags uint32, attr io.NodeAttributes) error {
+ return &zx.Error{Status: zx.ErrNotSupported, Text: "fdio.VMOFile"}
+}
+
+func (f *VMOFile) Ioctl(op uint32, max uint64, in []byte, handles []zx.Handle) ([]byte, []zx.Handle, error) {
+ return nil, nil, &zx.Error{Status: zx.ErrNotSupported, Text: "fdio.VMOFile"}
+}
+
+func (f *VMOFile) Read(data []byte) (n int, err error) {
+ if int64(len(data)) > f.end-f.at {
+ data = data[:f.end-f.at]
+ err = zx.EOF
+ }
+ if len(data) == 0 {
+ return 0, err
+ }
+ if err2 := f.h.Read(data, uint64(f.at)); err2 != nil {
+ return 0, err2
+ }
+ n = len(data)
+ f.at += int64(n)
+ return
+}
+
+func (f *VMOFile) ReadAt(data []byte, off int64) (n int, err error) {
+ if off < 0 {
+ return 0, &zx.Error{Status: zx.ErrInvalidArgs, Text: "fdio.VMOFile.ReadAt"}
+ }
+ if off >= f.end {
+ return 0, zx.EOF
+ }
+ if len(data) == 0 {
+ return 0, zx.EOF
+ }
+ n = len(data)
+ max := int(f.end - off)
+ if max < n {
+ n = max
+ err = zx.EOF
+ }
+ data = data[:n]
+ if err2 := f.h.Read(data, uint64(off)); err2 != nil {
+ return 0, err2
+ }
+ return
+}
+
+func (f *VMOFile) Write(data []byte) (int, error) {
+ return 0, &zx.Error{Status: zx.ErrNotSupported, Text: "fdio.VMOFile"}
+}
+
+func (f *VMOFile) WriteAt(data []byte, off int64) (int, error) {
+ return 0, &zx.Error{Status: zx.ErrNotSupported, Text: "fdio.VMOFile"}
+}
+
+func (f *VMOFile) Seek(offset int64, whence int) (int64, error) {
+ var at int64
+ switch whence {
+ case 0: // SEEK_SET
+ at = offset
+ case 1: // SEEK_CUR
+ at = f.at - f.off + offset
+ case 2: // SEEK_END
+ at = f.end - f.off + offset
+ }
+
+ if at > f.end-f.off {
+ return 0, &zx.Error{Status: zx.ErrOutOfRange, Text: "fdio.VMOFile"}
+ }
+ f.at = f.off + at
+ return at, nil
+}
+
+func (f *VMOFile) Truncate(length uint64) error {
+ return &zx.Error{Status: zx.ErrNotSupported, Text: "fdio.VMOFile"}
+}
+
+func (f *VMOFile) Open(path string, flags uint32, mode uint32) (FDIO, error) {
+ return nil, &zx.Error{Status: zx.ErrNotSupported, Text: "fdio.VMOFile"}
+}
+
+func (f *VMOFile) Link(oldpath, newpath string) error {
+ return &zx.Error{Status: zx.ErrNotSupported, Text: "fdio.VMOFile"}
+}
+
+func (f *VMOFile) Rename(oldpath, newpath string) error {
+ return &zx.Error{Status: zx.ErrNotSupported, Text: "fdio.VMOFile"}
+}
+
+func (f *VMOFile) Unlink(path string) error {
+ return &zx.Error{Status: zx.ErrNotSupported, Text: "fdio.VMOFile"}
+}
+
+func (f *VMOFile) ReadDirents(max uint64) ([]byte, error) {
+ return nil, &zx.Error{Status: zx.ErrNotSupported, Text: "fdio.VMOFile"}
+}
+
+func (f *VMOFile) Rewind() error {
+ return &zx.Error{Status: zx.ErrNotSupported, Text: "fdio.VMOFile"}
+}
diff --git a/src/syscall/zx/fidl/bindings.go b/src/syscall/zx/fidl/bindings.go
new file mode 100644
index 0000000..2e8e8fd
--- /dev/null
+++ b/src/syscall/zx/fidl/bindings.go
@@ -0,0 +1,315 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build fuchsia
+
+package fidl
+
+import (
+ "sync"
+ "syscall/zx"
+ "syscall/zx/dispatch"
+)
+
+const prefix = "zx/fidl: "
+
+// d is a process-local dispatcher.
+var d *dispatch.Dispatcher
+
+func init() {
+ disp, err := dispatch.NewDispatcher()
+ if err != nil {
+ panic(prefix + "failed to create dispatcher: " + err.Error())
+ }
+ d = disp
+}
+
+// Serve is a blocking call to the process-local dispatcher's serve method.
+func Serve() {
+ d.Serve()
+}
+
+type bindingState int32
+
+const (
+ idle bindingState = iota
+ handling
+ cleanup
+)
+
+// Binding binds the implementation of a Stub to a Channel.
+//
+// A Binding listens for incoming messages on the Channel, decodes them, and
+// asks the Stub to dispatch to the appropriate implementation of the interface.
+// If the message expects a reply, the Binding will also encode the reply and
+// send it back over the Channel.
+type Binding struct {
+ // Stub is a wrapper around an implementation of a FIDL interface which
+ // knows how to dispatch to a method by ordinal.
+ Stub Stub
+
+ // Channel is the Channel primitive to which the Stub is bound.
+ Channel zx.Channel
+
+ // id is an identifier for this waiter in the process-local dispatcher.
+ id *dispatch.WaitID
+
+ // errHandler is called with connection errors, when encountered.
+ errHandler func(error)
+
+ // handling is an atomically-updated signal which represents the state of the
+ // binding.
+ stateMu sync.Mutex
+ state bindingState
+}
+
+// Init initializes a Binding.
+func (b *Binding) Init(errHandler func(error)) error {
+ // Declare the wait handler as a closure.
+ h := func(d *dispatch.Dispatcher, s zx.Status, sigs *zx.PacketSignal) (result dispatch.WaitResult) {
+ b.stateMu.Lock()
+ if b.state == cleanup {
+ b.close()
+ b.stateMu.Unlock()
+ return dispatch.WaitFinished
+ }
+ b.state = handling
+ b.stateMu.Unlock()
+ defer func() {
+ b.stateMu.Lock()
+ defer b.stateMu.Unlock()
+ if b.state == cleanup {
+ b.close()
+ result = dispatch.WaitFinished
+ }
+ b.state = idle
+ }()
+ if s != zx.ErrOk {
+ b.errHandler(&zx.Error{Status: s})
+ return dispatch.WaitFinished
+ }
+ if sigs.Observed&zx.SignalChannelReadable != 0 {
+ for i := uint64(0); i < sigs.Count; i++ {
+ shouldWait, err := b.dispatch()
+ if err != nil {
+ errHandler(err)
+ return dispatch.WaitFinished
+ }
+ if shouldWait {
+ return dispatch.WaitAgain
+ }
+ }
+ return dispatch.WaitAgain
+ }
+ b.errHandler(&zx.Error{Status: zx.ErrPeerClosed})
+ return dispatch.WaitFinished
+ }
+
+ b.stateMu.Lock()
+ b.state = idle
+ b.stateMu.Unlock()
+
+ b.errHandler = errHandler
+
+ // Start the wait on the Channel.
+ id, err := d.BeginWait(
+ zx.Handle(b.Channel),
+ zx.SignalChannelReadable|zx.SignalChannelPeerClosed,
+ 0,
+ h,
+ )
+ if err != nil {
+ return err
+ }
+ b.id = &id
+ return nil
+}
+
+// dispatch reads from the underlying Channel and dispatches into the Stub.
+//
+// Returns true if the channel should be waited, or false if there is more data to be read.
+func (b *Binding) dispatch() (shouldWait bool, err error) {
+ respb := messageBytesPool.Get().([]byte)
+ resph := messageHandlesPool.Get().([]zx.Handle)
+
+ defer messageBytesPool.Put(respb)
+ defer messageHandlesPool.Put(resph)
+
+ nb, nh, err := b.Channel.Read(respb, resph, 0)
+ if err != nil {
+ if err, ok := err.(*zx.Error); ok && err.Status == zx.ErrShouldWait {
+ return true, nil
+ }
+ return false, err
+ }
+ msg := respb[:nb]
+ handles := resph[:nh]
+ var header MessageHeader
+ if _, _, err := UnmarshalNew(msg, nil, &header); err != nil {
+ return false, err
+ }
+ p, err := b.Stub.DispatchNew(header.Ordinal, msg[MessageHeaderSize:], handles)
+ switch {
+ case err == ErrUnknownOrdinal:
+ // If we couldn't determine the ordinal, we still own the
+ // handles, so we should close them all.
+ for _, h := range handles {
+ h.Close()
+ }
+ fallthrough
+ case err != nil:
+ return false, err
+ }
+ // Message has no response.
+ if p == nil {
+ return false, nil
+ }
+ cnb, cnh, err := MarshalHeaderThenMessage(&header, p, respb, resph)
+ if err != nil {
+ return false, err
+ }
+ if err := b.Channel.Write(respb[:cnb], resph[:cnh], 0); err != nil {
+ return false, err
+ }
+ return false, nil
+}
+
+// Close cancels any outstanding waits, resets the Binding's state, and closes
+// the bound Channel once any out-standing requests are finished being handled.
+func (b *Binding) Close() error {
+ b.stateMu.Lock()
+ defer b.stateMu.Unlock()
+ if zx.Handle(b.Channel) == zx.HandleInvalid || b.state == cleanup {
+ panic(prefix + "double binding close")
+ }
+ switch b.state {
+ case idle:
+ return b.close()
+ case handling:
+ b.state = cleanup
+ }
+ return nil
+}
+
+// close cancels any outstanding waits, resets the Binding's state, and
+// closes the bound Channel. This method is not thread-safe, and should be
+// called with the binding's mutex set.
+func (b *Binding) close() error {
+ if err := d.CancelWait(*b.id); err != nil {
+ // If it just says that the ID isn't found, there are cases where this is
+ // a reasonable error (particularly when we're in the middle of handling
+ // a signal from the dispatcher).
+ if err, ok := err.(*zx.Error); !ok || err.Status != zx.ErrNotFound {
+ // Attempt to close the channel if we hit a more serious error.
+ b.Channel.Close()
+ return err
+ }
+ }
+ b.id = nil
+ b.state = idle
+ return b.Channel.Close()
+}
+
+// BindingKey is a key which maps to a specific binding.
+//
+// It is only valid for the BindingSet that produced it.
+type BindingKey uint64
+
+// BindingSet is a managed set of Bindings which know how to unbind and
+// remove themselves in the event of a connection error.
+type BindingSet struct {
+ mu sync.Mutex
+ nextKey BindingKey
+ bindings map[BindingKey]*Binding
+}
+
+// Add creates a new Binding, initializes it, and adds it to the set.
+//
+// onError is an optional handler than may be passed which will be called after
+// the binding between the Stub and the Channel is successfully closed.
+func (b *BindingSet) Add(s Stub, c zx.Channel, onError func(error)) (BindingKey, error) {
+ b.mu.Lock()
+ defer b.mu.Unlock()
+ binding := &Binding{
+ Stub: s,
+ Channel: c,
+ }
+ if b.bindings == nil {
+ b.bindings = make(map[BindingKey]*Binding)
+ }
+ key := b.nextKey
+ err := binding.Init(func(err error) {
+ if b.Remove(key) && onError != nil {
+ onError(err)
+ }
+ })
+ if err != nil {
+ return 0, err
+ }
+ b.bindings[key] = binding
+ b.nextKey += 1
+ return key, nil
+}
+
+// BindingKeys returns a copy slice of all the BindingKeys in the BindingSet.
+func (b *BindingSet) BindingKeys() []BindingKey {
+ b.mu.Lock()
+ defer b.mu.Unlock()
+ r := make([]BindingKey, 0, len(b.bindings))
+ for key := range b.bindings {
+ r = append(r, key)
+ }
+ return r
+}
+
+// ProxyFor returns an event proxy created from the channel of the binding referred
+// to by key.
+func (b *BindingSet) ProxyFor(key BindingKey) (*ChannelProxy, bool) {
+ b.mu.Lock()
+ defer b.mu.Unlock()
+ if binding, ok := b.bindings[key]; ok {
+ return &ChannelProxy{Channel: binding.Channel}, true
+ }
+ return nil, false
+}
+
+// Remove removes a Binding from the set when it is next idle.
+//
+// Note that this method invalidates the key, and it will never remove a Binding
+// while it is actively being handled.
+//
+// Returns true if a Binding was found and removed.
+func (b *BindingSet) Remove(key BindingKey) bool {
+ b.mu.Lock()
+ defer b.mu.Unlock()
+ if binding, ok := b.bindings[key]; ok {
+ delete(b.bindings, key)
+
+ // Close the binding before calling the callback.
+ if err := binding.Close(); err != nil {
+ // Just panic. The only reason this can fail is if the handle
+ // is bad, which it shouldn't be if we're tracking things. If
+ // it does fail, better to fail fast.
+ panic(prefix + err.Error())
+ }
+ return true
+ }
+ return false
+}
+
+// Close removes all the bindings from the set.
+func (b *BindingSet) Close() {
+ // Lock, close all the bindings, and clear the map.
+ b.mu.Lock()
+ defer b.mu.Unlock()
+ for _, binding := range b.bindings {
+ if err := binding.Close(); err != nil {
+ // Just panic. The only reason this can fail is if the handle
+ // is bad, which it shouldn't be if we're tracking things. If
+ // it does fail, better to fail fast.
+ panic(prefix + err.Error())
+ }
+ }
+ b.bindings = nil
+}
diff --git a/src/syscall/zx/fidl/bindingstest/BUILD.gn b/src/syscall/zx/fidl/bindingstest/BUILD.gn
new file mode 100644
index 0000000..aff4065
--- /dev/null
+++ b/src/syscall/zx/fidl/bindingstest/BUILD.gn
@@ -0,0 +1,11 @@
+# Copyright 2018 The Fuchsia Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//build/fidl/fidl.gni")
+
+fidl("bindingstest") {
+ sources = [
+ "test.fidl",
+ ]
+}
diff --git a/src/syscall/zx/fidl/bindingstest/impl.go b/src/syscall/zx/fidl/bindingstest/impl.go
new file mode 100644
index 0000000..06edb5e
--- /dev/null
+++ b/src/syscall/zx/fidl/bindingstest/impl.go
@@ -0,0 +1,883 @@
+// Copyright 2018 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// GENERATED FILE: Do not edit!
+//
+// To rebuild this file, invoke third_party/go/regen-fidl.
+
+// +build fuchsia
+
+package bindingstest
+
+import (
+ _zx "syscall/zx"
+ _bindings "syscall/zx/fidl"
+)
+
+const (
+ KMaxBuf uint64 = 8192
+)
+
+type TestSimple struct {
+ _ struct{} `fidl2:"s,8,8"`
+ X int64
+}
+
+var _mTestSimple = _bindings.CreateLazyMarshaler(TestSimple{})
+
+func (msg *TestSimple) Marshaler() _bindings.Marshaler {
+ return _mTestSimple
+}
+
+type TestSimpleBool struct {
+ _ struct{} `fidl2:"s,1,1"`
+ X bool
+}
+
+var _mTestSimpleBool = _bindings.CreateLazyMarshaler(TestSimpleBool{})
+
+func (msg *TestSimpleBool) Marshaler() _bindings.Marshaler {
+ return _mTestSimpleBool
+}
+
+type TestAlignment1 struct {
+ _ struct{} `fidl2:"s,8,4"`
+ X int8
+ Y int8
+ Z uint32
+}
+
+var _mTestAlignment1 = _bindings.CreateLazyMarshaler(TestAlignment1{})
+
+func (msg *TestAlignment1) Marshaler() _bindings.Marshaler {
+ return _mTestAlignment1
+}
+
+type TestAlignment2 struct {
+ _ struct{} `fidl2:"s,20,4"`
+ A uint32
+ B uint32
+ C int8
+ D int8
+ E int8
+ F uint8
+ G uint32
+ H uint16
+ I uint16
+}
+
+var _mTestAlignment2 = _bindings.CreateLazyMarshaler(TestAlignment2{})
+
+func (msg *TestAlignment2) Marshaler() _bindings.Marshaler {
+ return _mTestAlignment2
+}
+
+type TestFloat1 struct {
+ _ struct{} `fidl2:"s,4,4"`
+ A float32
+}
+
+var _mTestFloat1 = _bindings.CreateLazyMarshaler(TestFloat1{})
+
+func (msg *TestFloat1) Marshaler() _bindings.Marshaler {
+ return _mTestFloat1
+}
+
+type TestFloat2 struct {
+ _ struct{} `fidl2:"s,8,8"`
+ A float64
+}
+
+var _mTestFloat2 = _bindings.CreateLazyMarshaler(TestFloat2{})
+
+func (msg *TestFloat2) Marshaler() _bindings.Marshaler {
+ return _mTestFloat2
+}
+
+type TestFloat3 struct {
+ _ struct{} `fidl2:"s,32,8"`
+ A float32
+ B float64
+ C uint64
+ D float32
+}
+
+var _mTestFloat3 = _bindings.CreateLazyMarshaler(TestFloat3{})
+
+func (msg *TestFloat3) Marshaler() _bindings.Marshaler {
+ return _mTestFloat3
+}
+
+type TestArray1 struct {
+ _ struct{} `fidl2:"s,5,1"`
+ A [5]int8
+}
+
+var _mTestArray1 = _bindings.CreateLazyMarshaler(TestArray1{})
+
+func (msg *TestArray1) Marshaler() _bindings.Marshaler {
+ return _mTestArray1
+}
+
+type TestArray2 struct {
+ _ struct{} `fidl2:"s,16,8"`
+ A float64
+ B [1]float32
+}
+
+var _mTestArray2 = _bindings.CreateLazyMarshaler(TestArray2{})
+
+func (msg *TestArray2) Marshaler() _bindings.Marshaler {
+ return _mTestArray2
+}
+
+type TestArray3 struct {
+ _ struct{} `fidl2:"s,24,8"`
+ A int32
+ B [3]uint16
+ C uint64
+}
+
+var _mTestArray3 = _bindings.CreateLazyMarshaler(TestArray3{})
+
+func (msg *TestArray3) Marshaler() _bindings.Marshaler {
+ return _mTestArray3
+}
+
+type TestArray4 struct {
+ _ struct{} `fidl2:"s,9,1"`
+ A [9]bool
+}
+
+var _mTestArray4 = _bindings.CreateLazyMarshaler(TestArray4{})
+
+func (msg *TestArray4) Marshaler() _bindings.Marshaler {
+ return _mTestArray4
+}
+
+type TestString1 struct {
+ _ struct{} `fidl2:"s,32,8"`
+ A string
+ B *string
+}
+
+var _mTestString1 = _bindings.CreateLazyMarshaler(TestString1{})
+
+func (msg *TestString1) Marshaler() _bindings.Marshaler {
+ return _mTestString1
+}
+
+type TestString2 struct {
+ _ struct{} `fidl2:"s,32,8"`
+ A [2]string
+}
+
+var _mTestString2 = _bindings.CreateLazyMarshaler(TestString2{})
+
+func (msg *TestString2) Marshaler() _bindings.Marshaler {
+ return _mTestString2
+}
+
+type TestString3 struct {
+ _ struct{} `fidl2:"s,64,8"`
+ A [2]string `fidl:"4" fidl2:"4"`
+ B [2]*string `fidl:"4" fidl2:"4"`
+}
+
+var _mTestString3 = _bindings.CreateLazyMarshaler(TestString3{})
+
+func (msg *TestString3) Marshaler() _bindings.Marshaler {
+ return _mTestString3
+}
+
+type TestStringWithBound struct {
+ _ struct{} `fidl2:"s,16,8"`
+ A string `fidl:"8" fidl2:"8"`
+}
+
+var _mTestStringWithBound = _bindings.CreateLazyMarshaler(TestStringWithBound{})
+
+func (msg *TestStringWithBound) Marshaler() _bindings.Marshaler {
+ return _mTestStringWithBound
+}
+
+type TestOptStringWithBound struct {
+ _ struct{} `fidl2:"s,16,8"`
+ A *string `fidl:"8" fidl2:"8"`
+}
+
+var _mTestOptStringWithBound = _bindings.CreateLazyMarshaler(TestOptStringWithBound{})
+
+func (msg *TestOptStringWithBound) Marshaler() _bindings.Marshaler {
+ return _mTestOptStringWithBound
+}
+
+type TestVector1 struct {
+ _ struct{} `fidl2:"s,64,8"`
+ A []int8
+ B *[]int16
+ C []int32 `fidl:"2" fidl2:"2"`
+ D *[]int64 `fidl:"2" fidl2:"2"`
+}
+
+var _mTestVector1 = _bindings.CreateLazyMarshaler(TestVector1{})
+
+func (msg *TestVector1) Marshaler() _bindings.Marshaler {
+ return _mTestVector1
+}
+
+type TestVector2 struct {
+ _ struct{} `fidl2:"s,64,8"`
+ A [2][]int8
+ B [][]int8 `fidl:",2" fidl2:"2,"`
+ C []*[]string `fidl:"5,2,2" fidl2:"2,2,5"`
+}
+
+var _mTestVector2 = _bindings.CreateLazyMarshaler(TestVector2{})
+
+func (msg *TestVector2) Marshaler() _bindings.Marshaler {
+ return _mTestVector2
+}
+
+type TestStruct1 struct {
+ _ struct{} `fidl2:"s,16,8"`
+ A TestSimple
+ B *TestSimple
+}
+
+var _mTestStruct1 = _bindings.CreateLazyMarshaler(TestStruct1{})
+
+func (msg *TestStruct1) Marshaler() _bindings.Marshaler {
+ return _mTestStruct1
+}
+
+type TestStruct2 struct {
+ _ struct{} `fidl2:"s,88,8"`
+ A TestArray1
+ B TestFloat1
+ C TestVector1
+ D *TestString1
+}
+
+var _mTestStruct2 = _bindings.CreateLazyMarshaler(TestStruct2{})
+
+func (msg *TestStruct2) Marshaler() _bindings.Marshaler {
+ return _mTestStruct2
+}
+
+type EmptyStruct struct {
+ _ struct{} `fidl2:"s,1,1"`
+}
+
+var _mEmptyStruct = _bindings.CreateLazyMarshaler(EmptyStruct{})
+
+func (msg *EmptyStruct) Marshaler() _bindings.Marshaler {
+ return _mEmptyStruct
+}
+
+type TestUnion1 struct {
+ _ struct{} `fidl2:"s,24,8"`
+ A Union1
+ B *Union1
+}
+
+var _mTestUnion1 = _bindings.CreateLazyMarshaler(TestUnion1{})
+
+func (msg *TestUnion1) Marshaler() _bindings.Marshaler {
+ return _mTestUnion1
+}
+
+type TestUnion2 struct {
+ _ struct{} `fidl2:"s,32,8"`
+ A []Union1
+ B []*Union1
+}
+
+var _mTestUnion2 = _bindings.CreateLazyMarshaler(TestUnion2{})
+
+func (msg *TestUnion2) Marshaler() _bindings.Marshaler {
+ return _mTestUnion2
+}
+
+type TestHandle1 struct {
+ _ struct{} `fidl2:"s,16,4"`
+ A _zx.Handle `fidl2:"0"`
+ B _zx.Handle `fidl:"*" fidl2:"1"`
+ C _zx.VMO `fidl2:"0"`
+ D _zx.VMO `fidl:"*" fidl2:"1"`
+}
+
+var _mTestHandle1 = _bindings.CreateLazyMarshaler(TestHandle1{})
+
+func (msg *TestHandle1) Marshaler() _bindings.Marshaler {
+ return _mTestHandle1
+}
+
+type TestHandle2 struct {
+ _ struct{} `fidl2:"s,32,8"`
+ A []_zx.Handle `fidl:"1" fidl2:"1,0"`
+ B []_zx.VMO `fidl:"*,1" fidl2:"1,1"`
+}
+
+var _mTestHandle2 = _bindings.CreateLazyMarshaler(TestHandle2{})
+
+func (msg *TestHandle2) Marshaler() _bindings.Marshaler {
+ return _mTestHandle2
+}
+
+type TestInterface1 struct {
+ _ struct{} `fidl2:"s,16,4"`
+ A Test1Interface
+ B Test1Interface `fidl:"*"`
+ C Test1InterfaceRequest `fidl2:"0"`
+ D Test1InterfaceRequest `fidl:"*" fidl2:"1"`
+}
+
+var _mTestInterface1 = _bindings.CreateLazyMarshaler(TestInterface1{})
+
+func (msg *TestInterface1) Marshaler() _bindings.Marshaler {
+ return _mTestInterface1
+}
+
+type TestSimpleTable struct {
+ _ struct{} `fidl2:"s,16,8"`
+ Table SimpleTable
+}
+
+var _mTestSimpleTable = _bindings.CreateLazyMarshaler(TestSimpleTable{})
+
+func (msg *TestSimpleTable) Marshaler() _bindings.Marshaler {
+ return _mTestSimpleTable
+}
+
+type TestOlderSimpleTable struct {
+ _ struct{} `fidl2:"s,16,8"`
+ Table OlderSimpleTable
+}
+
+var _mTestOlderSimpleTable = _bindings.CreateLazyMarshaler(TestOlderSimpleTable{})
+
+func (msg *TestOlderSimpleTable) Marshaler() _bindings.Marshaler {
+ return _mTestOlderSimpleTable
+}
+
+type TestNewerSimpleTable struct {
+ _ struct{} `fidl2:"s,16,8"`
+ Table NewerSimpleTable
+}
+
+var _mTestNewerSimpleTable = _bindings.CreateLazyMarshaler(TestNewerSimpleTable{})
+
+func (msg *TestNewerSimpleTable) Marshaler() _bindings.Marshaler {
+ return _mTestNewerSimpleTable
+}
+
+type TestWithTableAndInt struct {
+ _ struct{} `fidl2:"s,24,8"`
+ Table SimpleTable
+ Foo uint64
+}
+
+var _mTestWithTableAndInt = _bindings.CreateLazyMarshaler(TestWithTableAndInt{})
+
+func (msg *TestWithTableAndInt) Marshaler() _bindings.Marshaler {
+ return _mTestWithTableAndInt
+}
+
+type Int64Struct struct {
+ _ struct{} `fidl2:"s,8,8"`
+ X int64
+}
+
+var _mInt64Struct = _bindings.CreateLazyMarshaler(Int64Struct{})
+
+func (msg *Int64Struct) Marshaler() _bindings.Marshaler {
+ return _mInt64Struct
+}
+
+type TestFuchsiaIoReadAtResponse struct {
+ _ struct{} `fidl2:"s,24,8"`
+ S int32
+ Data []uint8 `fidl:"8192" fidl2:"8192"`
+}
+
+var _mTestFuchsiaIoReadAtResponse = _bindings.CreateLazyMarshaler(TestFuchsiaIoReadAtResponse{})
+
+func (msg *TestFuchsiaIoReadAtResponse) Marshaler() _bindings.Marshaler {
+ return _mTestFuchsiaIoReadAtResponse
+}
+
+type TestFuchsiaIoWriteAtRequest struct {
+ _ struct{} `fidl2:"s,24,8"`
+ Data []uint8 `fidl:"8192" fidl2:"8192"`
+ Offset uint64
+}
+
+var _mTestFuchsiaIoWriteAtRequest = _bindings.CreateLazyMarshaler(TestFuchsiaIoWriteAtRequest{})
+
+func (msg *TestFuchsiaIoWriteAtRequest) Marshaler() _bindings.Marshaler {
+ return _mTestFuchsiaIoWriteAtRequest
+}
+
+type InterfaceConfig struct {
+ _ struct{} `fidl2:"s,48,8"`
+ Name string
+ IpAddressConfig IpAddressConfig
+}
+
+var _mInterfaceConfig = _bindings.CreateLazyMarshaler(InterfaceConfig{})
+
+func (msg *InterfaceConfig) Marshaler() _bindings.Marshaler {
+ return _mInterfaceConfig
+}
+
+type TestAddEthernetDeviceRequest struct {
+ _ struct{} `fidl2:"s,72,8"`
+ TopologicalPath string
+ Config InterfaceConfig
+ Device EthernetDeviceInterface
+}
+
+var _mTestAddEthernetDeviceRequest = _bindings.CreateLazyMarshaler(TestAddEthernetDeviceRequest{})
+
+func (msg *TestAddEthernetDeviceRequest) Marshaler() _bindings.Marshaler {
+ return _mTestAddEthernetDeviceRequest
+}
+
+type Union1Tag uint32
+
+const (
+ _ Union1Tag = iota
+ Union1A
+ Union1B
+ Union1C
+ Union1D
+)
+
+type Union1 struct {
+ Union1Tag `fidl:"tag" fidl2:"u,16,8"`
+ A [3]int8
+ B TestSimple
+ C *TestSimple
+ D float32
+}
+
+func (u *Union1) Which() Union1Tag {
+ return u.Union1Tag
+}
+
+func (u *Union1) SetA(a [3]int8) {
+ u.Union1Tag = Union1A
+ u.A = a
+}
+
+func (u *Union1) SetB(b TestSimple) {
+ u.Union1Tag = Union1B
+ u.B = b
+}
+
+func (u *Union1) SetC(c *TestSimple) {
+ u.Union1Tag = Union1C
+ u.C = c
+}
+
+func (u *Union1) SetD(d float32) {
+ u.Union1Tag = Union1D
+ u.D = d
+}
+
+type SimpleUnionTag uint32
+
+const (
+ _ SimpleUnionTag = iota
+ SimpleUnionI32
+ SimpleUnionI64
+ SimpleUnionS
+ SimpleUnionOs
+ SimpleUnionStr
+)
+
+type SimpleUnion struct {
+ SimpleUnionTag `fidl:"tag" fidl2:"u,24,8"`
+ I32 int32
+ I64 int64
+ S Int64Struct
+ Os *Int64Struct
+ Str string
+}
+
+func (u *SimpleUnion) Which() SimpleUnionTag {
+ return u.SimpleUnionTag
+}
+
+func (u *SimpleUnion) SetI32(i32 int32) {
+ u.SimpleUnionTag = SimpleUnionI32
+ u.I32 = i32
+}
+
+func (u *SimpleUnion) SetI64(i64 int64) {
+ u.SimpleUnionTag = SimpleUnionI64
+ u.I64 = i64
+}
+
+func (u *SimpleUnion) SetS(s Int64Struct) {
+ u.SimpleUnionTag = SimpleUnionS
+ u.S = s
+}
+
+func (u *SimpleUnion) SetOs(os *Int64Struct) {
+ u.SimpleUnionTag = SimpleUnionOs
+ u.Os = os
+}
+
+func (u *SimpleUnion) SetStr(str string) {
+ u.SimpleUnionTag = SimpleUnionStr
+ u.Str = str
+}
+
+type IpAddressConfigTag uint32
+
+const (
+ _ IpAddressConfigTag = iota
+ IpAddressConfigPaddingSize24Align4
+ IpAddressConfigDhcp
+)
+
+type IpAddressConfig struct {
+ IpAddressConfigTag `fidl:"tag" fidl2:"u,28,4"`
+ PaddingSize24Align4 [6]uint32
+ Dhcp bool
+}
+
+func (u *IpAddressConfig) Which() IpAddressConfigTag {
+ return u.IpAddressConfigTag
+}
+
+func (u *IpAddressConfig) SetPaddingSize24Align4(paddingSize24Align4 [6]uint32) {
+ u.IpAddressConfigTag = IpAddressConfigPaddingSize24Align4
+ u.PaddingSize24Align4 = paddingSize24Align4
+}
+
+func (u *IpAddressConfig) SetDhcp(dhcp bool) {
+ u.IpAddressConfigTag = IpAddressConfigDhcp
+ u.Dhcp = dhcp
+}
+
+type SimpleTable struct {
+ _ struct{} `fidl2:"t,16,8"`
+ X int64 `fidl:"1" fidl2:"1"`
+ XPresent bool
+ Y int64 `fidl:"5" fidl2:"5"`
+ YPresent bool
+}
+
+func (u *SimpleTable) SetX(x int64) {
+ u.X = x
+ u.XPresent = true
+}
+
+func (u *SimpleTable) GetX() int64 {
+ return u.X
+}
+
+func (u *SimpleTable) GetXWithDefault(_default int64) int64 {
+ if !u.HasX() {
+ return _default
+ }
+ return u.X
+}
+
+func (u *SimpleTable) HasX() bool {
+ return u.XPresent
+}
+
+func (u *SimpleTable) ClearX() {
+ u.XPresent = false
+}
+
+func (u *SimpleTable) SetY(y int64) {
+ u.Y = y
+ u.YPresent = true
+}
+
+func (u *SimpleTable) GetY() int64 {
+ return u.Y
+}
+
+func (u *SimpleTable) GetYWithDefault(_default int64) int64 {
+ if !u.HasY() {
+ return _default
+ }
+ return u.Y
+}
+
+func (u *SimpleTable) HasY() bool {
+ return u.YPresent
+}
+
+func (u *SimpleTable) ClearY() {
+ u.YPresent = false
+}
+
+type OlderSimpleTable struct {
+ _ struct{} `fidl2:"t,16,8"`
+ X int64 `fidl:"1" fidl2:"1"`
+ XPresent bool
+}
+
+func (u *OlderSimpleTable) SetX(x int64) {
+ u.X = x
+ u.XPresent = true
+}
+
+func (u *OlderSimpleTable) GetX() int64 {
+ return u.X
+}
+
+func (u *OlderSimpleTable) GetXWithDefault(_default int64) int64 {
+ if !u.HasX() {
+ return _default
+ }
+ return u.X
+}
+
+func (u *OlderSimpleTable) HasX() bool {
+ return u.XPresent
+}
+
+func (u *OlderSimpleTable) ClearX() {
+ u.XPresent = false
+}
+
+type NewerSimpleTable struct {
+ _ struct{} `fidl2:"t,16,8"`
+ X int64 `fidl:"1" fidl2:"1"`
+ XPresent bool
+ Y int64 `fidl:"5" fidl2:"5"`
+ YPresent bool
+ Z int64 `fidl:"6" fidl2:"6"`
+ ZPresent bool
+}
+
+func (u *NewerSimpleTable) SetX(x int64) {
+ u.X = x
+ u.XPresent = true
+}
+
+func (u *NewerSimpleTable) GetX() int64 {
+ return u.X
+}
+
+func (u *NewerSimpleTable) GetXWithDefault(_default int64) int64 {
+ if !u.HasX() {
+ return _default
+ }
+ return u.X
+}
+
+func (u *NewerSimpleTable) HasX() bool {
+ return u.XPresent
+}
+
+func (u *NewerSimpleTable) ClearX() {
+ u.XPresent = false
+}
+
+func (u *NewerSimpleTable) SetY(y int64) {
+ u.Y = y
+ u.YPresent = true
+}
+
+func (u *NewerSimpleTable) GetY() int64 {
+ return u.Y
+}
+
+func (u *NewerSimpleTable) GetYWithDefault(_default int64) int64 {
+ if !u.HasY() {
+ return _default
+ }
+ return u.Y
+}
+
+func (u *NewerSimpleTable) HasY() bool {
+ return u.YPresent
+}
+
+func (u *NewerSimpleTable) ClearY() {
+ u.YPresent = false
+}
+
+func (u *NewerSimpleTable) SetZ(z int64) {
+ u.Z = z
+ u.ZPresent = true
+}
+
+func (u *NewerSimpleTable) GetZ() int64 {
+ return u.Z
+}
+
+func (u *NewerSimpleTable) GetZWithDefault(_default int64) int64 {
+ if !u.HasZ() {
+ return _default
+ }
+ return u.Z
+}
+
+func (u *NewerSimpleTable) HasZ() bool {
+ return u.ZPresent
+}
+
+func (u *NewerSimpleTable) ClearZ() {
+ u.ZPresent = false
+}
+
+const (
+ Test1EchoOrdinal uint32 = 1246312959
+ Test1EchoGenOrdinal uint32 = 1246312959
+ Test1SurpriseOrdinal uint32 = 1272344178
+ Test1SurpriseGenOrdinal uint32 = 1272344178
+)
+
+type test1EchoRequest struct {
+ _ struct{} `fidl2:"s,16,0"`
+ In *string
+}
+
+var _mtest1EchoRequest = _bindings.CreateLazyMarshaler(test1EchoRequest{})
+
+func (msg *test1EchoRequest) Marshaler() _bindings.Marshaler {
+ return _mtest1EchoRequest
+}
+
+type test1EchoResponse struct {
+ _ struct{} `fidl2:"s,16,0"`
+ Out *string
+}
+
+var _mtest1EchoResponse = _bindings.CreateLazyMarshaler(test1EchoResponse{})
+
+func (msg *test1EchoResponse) Marshaler() _bindings.Marshaler {
+ return _mtest1EchoResponse
+}
+
+type test1SurpriseResponse struct {
+ _ struct{} `fidl2:"s,16,0"`
+ Foo string
+}
+
+var _mtest1SurpriseResponse = _bindings.CreateLazyMarshaler(test1SurpriseResponse{})
+
+func (msg *test1SurpriseResponse) Marshaler() _bindings.Marshaler {
+ return _mtest1SurpriseResponse
+}
+
+type Test1Interface _bindings.ChannelProxy
+
+func (p *Test1Interface) Echo(in *string) (*string, error) {
+ req_ := &test1EchoRequest{
+ In: in,
+ }
+ resp_ := &test1EchoResponse{}
+ err := ((*_bindings.ChannelProxy)(p)).CallNew(Test1EchoOrdinal, req_, resp_)
+ return resp_.Out, err
+}
+
+func (p *Test1Interface) ExpectSurprise() (string, error) {
+ resp_ := &test1SurpriseResponse{}
+ err := ((*_bindings.ChannelProxy)(p)).RecvNew(Test1SurpriseOrdinal, resp_)
+ return resp_.Foo, err
+}
+
+type Test1 interface {
+ Echo(in *string) (*string, error)
+}
+
+type Test1TransitionalBase struct{}
+
+type Test1InterfaceRequest _bindings.InterfaceRequest
+
+func NewTest1InterfaceRequest() (Test1InterfaceRequest, *Test1Interface, error) {
+ req, cli, err := _bindings.NewInterfaceRequest()
+ return Test1InterfaceRequest(req), (*Test1Interface)(cli), err
+}
+
+type Test1Stub struct {
+ Impl Test1
+}
+
+func (s *Test1Stub) DispatchNew(ord uint32, b_ []byte, h_ []_zx.Handle) (_bindings.Message, error) {
+ switch ord {
+ case Test1EchoOrdinal:
+ in_ := test1EchoRequest{}
+ if _, _, err_ := _bindings.UnmarshalNew(b_, h_, &in_); err_ != nil {
+ return nil, err_
+ }
+ out, err_ := s.Impl.Echo(in_.In)
+ out_ := test1EchoResponse{}
+ out_.Out = out
+ return &out_, err_
+ }
+ return nil, _bindings.ErrUnknownOrdinal
+}
+
+type Test1Service struct {
+ _bindings.BindingSet
+}
+
+func (s *Test1Service) Add(impl Test1, c _zx.Channel, onError func(error)) (_bindings.BindingKey, error) {
+ return s.BindingSet.Add(&Test1Stub{Impl: impl}, c, onError)
+}
+
+func (s *Test1Service) EventProxyFor(key _bindings.BindingKey) (*Test1EventProxy, bool) {
+ pxy, err := s.BindingSet.ProxyFor(key)
+ return (*Test1EventProxy)(pxy), err
+}
+
+type Test1EventProxy _bindings.ChannelProxy
+
+func (p *Test1EventProxy) Surprise(foo string) error {
+ event_ := &test1SurpriseResponse{
+ Foo: foo,
+ }
+ return ((*_bindings.ChannelProxy)(p)).SendNew(Test1SurpriseOrdinal, event_)
+}
+
+type EthernetDeviceInterface _bindings.ChannelProxy
+
+type EthernetDevice interface {
+}
+
+type EthernetDeviceTransitionalBase struct{}
+
+type EthernetDeviceInterfaceRequest _bindings.InterfaceRequest
+
+func NewEthernetDeviceInterfaceRequest() (EthernetDeviceInterfaceRequest, *EthernetDeviceInterface, error) {
+ req, cli, err := _bindings.NewInterfaceRequest()
+ return EthernetDeviceInterfaceRequest(req), (*EthernetDeviceInterface)(cli), err
+}
+
+type EthernetDeviceStub struct {
+ Impl EthernetDevice
+}
+
+func (s *EthernetDeviceStub) DispatchNew(ord uint32, b_ []byte, h_ []_zx.Handle) (_bindings.Message, error) {
+ switch ord {
+ }
+ return nil, _bindings.ErrUnknownOrdinal
+}
+
+type EthernetDeviceService struct {
+ _bindings.BindingSet
+}
+
+func (s *EthernetDeviceService) Add(impl EthernetDevice, c _zx.Channel, onError func(error)) (_bindings.BindingKey, error) {
+ return s.BindingSet.Add(&EthernetDeviceStub{Impl: impl}, c, onError)
+}
+
+func (s *EthernetDeviceService) EventProxyFor(key _bindings.BindingKey) (*EthernetDeviceEventProxy, bool) {
+ pxy, err := s.BindingSet.ProxyFor(key)
+ return (*EthernetDeviceEventProxy)(pxy), err
+}
+
+type EthernetDeviceEventProxy _bindings.ChannelProxy
diff --git a/src/syscall/zx/fidl/bindingstest/test.test.fidl b/src/syscall/zx/fidl/bindingstest/test.test.fidl
new file mode 100644
index 0000000..2cbae65
--- /dev/null
+++ b/src/syscall/zx/fidl/bindingstest/test.test.fidl
@@ -0,0 +1,246 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+library bindingstest;
+
+using zx;
+
+struct TestSimple {
+ int64 x;
+};
+
+struct TestSimpleBool {
+ bool x;
+};
+
+struct TestAlignment1 {
+ int8 x;
+ int8 y;
+ uint32 z;
+};
+
+struct TestAlignment2 {
+ uint32 a;
+ uint32 b;
+ int8 c;
+ int8 d;
+ int8 e;
+ uint8 f;
+ uint32 g;
+ uint16 h;
+ uint16 i;
+};
+
+struct TestFloat1 {
+ float32 a;
+};
+
+struct TestFloat2 {
+ float64 a;
+};
+
+struct TestFloat3 {
+ float32 a;
+ float64 b;
+ uint64 c;
+ float32 d;
+};
+
+struct TestArray1 {
+ array<int8>:5 a;
+};
+
+struct TestArray2 {
+ float64 a;
+ array<float32>:1 b;
+};
+
+struct TestArray3 {
+ int32 a;
+ array<uint16>:3 b;
+ uint64 c;
+};
+
+struct TestArray4 {
+ array<bool>:9 a;
+};
+
+struct TestString1 {
+ string a;
+ string? b;
+};
+
+struct TestString2 {
+ array<string>:2 a;
+};
+
+struct TestString3 {
+ array<string:4>:2 a;
+ array<string:4?>:2 b;
+};
+
+struct TestStringWithBound {
+ string:8 a;
+};
+
+struct TestOptStringWithBound {
+ string:8? a;
+};
+
+struct TestVector1 {
+ vector<int8> a;
+ vector<int16>? b;
+ vector<int32>:2 c;
+ vector<int64>:2? d;
+};
+
+struct TestVector2 {
+ array<vector<int8>>:2 a;
+ vector<vector<int8>>:2 b;
+ vector<vector<string:5>:2?>:2 c;
+};
+
+struct TestStruct1 {
+ TestSimple a;
+ TestSimple? b;
+};
+
+struct TestStruct2 {
+ TestArray1 a;
+ TestFloat1 b;
+ TestVector1 c;
+ TestString1? d;
+};
+
+struct EmptyStruct {
+};
+
+union Union1 {
+ array<int8>:3 a;
+ TestSimple b;
+ TestSimple? c;
+ float32 d;
+};
+
+struct TestUnion1 {
+ Union1 a;
+ Union1? b;
+};
+
+struct TestUnion2 {
+ vector<Union1> a;
+ vector<Union1?> b;
+};
+
+struct TestHandle1 {
+ handle a;
+ handle? b;
+ handle<vmo> c;
+ handle<vmo>? d;
+};
+
+struct TestHandle2 {
+ vector<handle>:1 a;
+ vector<handle<vmo>?>:1 b;
+};
+
+protocol Test1 {
+ Echo(string? in) -> (string? out);
+ -> Surprise(string foo);
+};
+
+struct TestInterface1 {
+ Test1 a;
+ Test1? b;
+ request<Test1> c;
+ request<Test1>? d;
+};
+
+table SimpleTable {
+ 1: int64 x;
+ 2: reserved;
+ 3: reserved;
+ 4: reserved;
+ 5: int64 y;
+};
+
+struct TestSimpleTable {
+ SimpleTable table;
+};
+
+// A variant of SimpleTable that has just the first few fields.
+// Think of this as an older variant of that type!
+table OlderSimpleTable {
+ 1: int64 x;
+ 2: reserved;
+};
+
+struct TestOlderSimpleTable {
+ OlderSimpleTable table;
+};
+
+// A variant of SimpleTable that has some additional new fields.
+// Think of this as an newer variant of that type!
+table NewerSimpleTable {
+ 1: int64 x;
+ 2: reserved;
+ 3: reserved;
+ 4: reserved;
+ 5: int64 y;
+ 6: int64 z;
+ 7: reserved;
+};
+
+struct TestNewerSimpleTable {
+ NewerSimpleTable table;
+};
+
+struct TestWithTableAndInt {
+ SimpleTable table;
+ uint64 foo;
+};
+
+union SimpleUnion {
+ int32 i32;
+ int64 i64;
+ Int64Struct s;
+ Int64Struct? os;
+ string str;
+};
+
+struct Int64Struct {
+ int64 x;
+};
+
+// examples from fuchsia world.
+
+const uint64 kMaxBuf = 8192;
+
+struct TestFuchsiaIoReadAtResponse {
+ zx.status s;
+ vector<uint8>:kMaxBuf data;
+};
+
+struct TestFuchsiaIoWriteAtRequest {
+ vector<uint8>:kMaxBuf data;
+ uint64 offset;
+};
+
+protocol EthernetDevice {};
+
+struct InterfaceConfig {
+ string name;
+ IpAddressConfig ip_address_config;
+};
+
+union IpAddressConfig {
+ array<uint32>:6 padding_size_24_align_4;
+ bool dhcp;
+};
+
+struct TestAddEthernetDeviceRequest {
+ string topological_path;
+ InterfaceConfig config;
+ EthernetDevice device;
+};
diff --git a/src/syscall/zx/fidl/conformance/impl.go b/src/syscall/zx/fidl/conformance/impl.go
new file mode 100644
index 0000000..c95f7fe
--- /dev/null
+++ b/src/syscall/zx/fidl/conformance/impl.go
@@ -0,0 +1,669 @@
+// Copyright 2019 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// Code generated by tools/fidl/gidl-conformance-suite/regen.sh; DO NOT EDIT.
+
+// +build fuchsia
+
+//
+// WARNING: This file is machine generated by fidlgen.
+
+package conformance
+
+import (
+ _zx "syscall/zx"
+ _bindings "syscall/zx/fidl"
+)
+
+type StructOfSimpleTable struct {
+ _ struct{} `fidl2:"s,16,8"`
+ Table SimpleTable
+}
+
+var _mStructOfSimpleTable = _bindings.CreateLazyMarshaler(StructOfSimpleTable{})
+
+func (msg *StructOfSimpleTable) Marshaler() _bindings.Marshaler {
+ return _mStructOfSimpleTable
+}
+
+type SimpleTableThenUint64 struct {
+ _ struct{} `fidl2:"s,24,8"`
+ Table SimpleTable
+ Number uint64
+}
+
+var _mSimpleTableThenUint64 = _bindings.CreateLazyMarshaler(SimpleTableThenUint64{})
+
+func (msg *SimpleTableThenUint64) Marshaler() _bindings.Marshaler {
+ return _mSimpleTableThenUint64
+}
+
+type StructOfTableWithStringAndVector struct {
+ _ struct{} `fidl2:"s,16,8"`
+ Table TableWithStringAndVector
+}
+
+var _mStructOfTableWithStringAndVector = _bindings.CreateLazyMarshaler(StructOfTableWithStringAndVector{})
+
+func (msg *StructOfTableWithStringAndVector) Marshaler() _bindings.Marshaler {
+ return _mStructOfTableWithStringAndVector
+}
+
+type Int64Struct struct {
+ _ struct{} `fidl2:"s,8,8"`
+ X int64
+}
+
+var _mInt64Struct = _bindings.CreateLazyMarshaler(Int64Struct{})
+
+func (msg *Int64Struct) Marshaler() _bindings.Marshaler {
+ return _mInt64Struct
+}
+
+type TestInlineXUnionInStruct struct {
+ _ struct{} `fidl2:"s,56,8"`
+ Before string
+ Xu SampleXUnion
+ After string
+}
+
+var _mTestInlineXUnionInStruct = _bindings.CreateLazyMarshaler(TestInlineXUnionInStruct{})
+
+func (msg *TestInlineXUnionInStruct) Marshaler() _bindings.Marshaler {
+ return _mTestInlineXUnionInStruct
+}
+
+type TestOptionalXUnionInStruct struct {
+ _ struct{} `fidl2:"s,56,8"`
+ Before string
+ Xu *SampleXUnion
+ After string
+}
+
+var _mTestOptionalXUnionInStruct = _bindings.CreateLazyMarshaler(TestOptionalXUnionInStruct{})
+
+func (msg *TestOptionalXUnionInStruct) Marshaler() _bindings.Marshaler {
+ return _mTestOptionalXUnionInStruct
+}
+
+type StructWithOptionals struct {
+ _ struct{} `fidl2:"s,104,8"`
+ S EmptyStruct
+ S2 *EmptyStruct
+ T TableWithEmptyStruct
+ Xu XUnionWithEmptyStruct
+ Xu2 *XUnionWithEmptyStruct
+ U UnionWithEmptyStruct
+ U2 *UnionWithEmptyStruct
+}
+
+var _mStructWithOptionals = _bindings.CreateLazyMarshaler(StructWithOptionals{})
+
+func (msg *StructWithOptionals) Marshaler() _bindings.Marshaler {
+ return _mStructWithOptionals
+}
+
+type EmptyStruct struct {
+ _ struct{} `fidl2:"s,1,1"`
+}
+
+var _mEmptyStruct = _bindings.CreateLazyMarshaler(EmptyStruct{})
+
+func (msg *EmptyStruct) Marshaler() _bindings.Marshaler {
+ return _mEmptyStruct
+}
+
+type EmptyStructSandwich struct {
+ _ struct{} `fidl2:"s,40,8"`
+ Before string
+ Es EmptyStruct
+ After string
+}
+
+var _mEmptyStructSandwich = _bindings.CreateLazyMarshaler(EmptyStructSandwich{})
+
+func (msg *EmptyStructSandwich) Marshaler() _bindings.Marshaler {
+ return _mEmptyStructSandwich
+}
+
+type Uint8Uint16Uint32Uint64 struct {
+ _ struct{} `fidl2:"s,16,8"`
+ F1 uint8
+ F2 uint16
+ F3 uint32
+ F4 uint64
+}
+
+var _mUint8Uint16Uint32Uint64 = _bindings.CreateLazyMarshaler(Uint8Uint16Uint32Uint64{})
+
+func (msg *Uint8Uint16Uint32Uint64) Marshaler() _bindings.Marshaler {
+ return _mUint8Uint16Uint32Uint64
+}
+
+type Uint64Uint32Uint16Uint8 struct {
+ _ struct{} `fidl2:"s,16,8"`
+ F1 uint64
+ F2 uint32
+ F3 uint16
+ F4 uint8
+}
+
+var _mUint64Uint32Uint16Uint8 = _bindings.CreateLazyMarshaler(Uint64Uint32Uint16Uint8{})
+
+func (msg *Uint64Uint32Uint16Uint8) Marshaler() _bindings.Marshaler {
+ return _mUint64Uint32Uint16Uint8
+}
+
+type TestXUnionInTable struct {
+ _ struct{} `fidl2:"s,16,8"`
+ Value XUnionInTable
+}
+
+var _mTestXUnionInTable = _bindings.CreateLazyMarshaler(TestXUnionInTable{})
+
+func (msg *TestXUnionInTable) Marshaler() _bindings.Marshaler {
+ return _mTestXUnionInTable
+}
+
+type InterfaceConfig struct {
+ _ struct{} `fidl2:"s,48,8"`
+ Name string
+ IpAddressConfig IpAddressConfig
+}
+
+var _mInterfaceConfig = _bindings.CreateLazyMarshaler(InterfaceConfig{})
+
+func (msg *InterfaceConfig) Marshaler() _bindings.Marshaler {
+ return _mInterfaceConfig
+}
+
+type TestAddEthernetDeviceRequest struct {
+ _ struct{} `fidl2:"s,72,8"`
+ TopologicalPath string
+ Config InterfaceConfig
+ ThisShouldBeAHandle uint32
+}
+
+var _mTestAddEthernetDeviceRequest = _bindings.CreateLazyMarshaler(TestAddEthernetDeviceRequest{})
+
+func (msg *TestAddEthernetDeviceRequest) Marshaler() _bindings.Marshaler {
+ return _mTestAddEthernetDeviceRequest
+}
+
+type NodeAttributes struct {
+ _ struct{} `fidl2:"s,56,8"`
+ Mode uint32
+ Id uint64
+ ContentSize uint64
+ StorageSize uint64
+ LinkCount uint64
+ CreationTime uint64
+ ModificationTime uint64
+}
+
+var _mNodeAttributes = _bindings.CreateLazyMarshaler(NodeAttributes{})
+
+func (msg *NodeAttributes) Marshaler() _bindings.Marshaler {
+ return _mNodeAttributes
+}
+
+type FileGetAttrResponse struct {
+ _ struct{} `fidl2:"s,64,8"`
+ S int32
+ Attributes NodeAttributes
+}
+
+var _mFileGetAttrResponse = _bindings.CreateLazyMarshaler(FileGetAttrResponse{})
+
+func (msg *FileGetAttrResponse) Marshaler() _bindings.Marshaler {
+ return _mFileGetAttrResponse
+}
+
+type SimpleUnionTag uint32
+
+const (
+ _ SimpleUnionTag = iota
+ SimpleUnionI32
+ SimpleUnionI64
+ SimpleUnionS
+ SimpleUnionOs
+ SimpleUnionStr
+)
+
+type SimpleUnion struct {
+ SimpleUnionTag `fidl:"tag" fidl2:"u,24,8"`
+ I32 int32
+ I64 int64
+ S Int64Struct
+ Os *Int64Struct
+ Str string
+}
+
+func (u *SimpleUnion) Which() SimpleUnionTag {
+ return u.SimpleUnionTag
+}
+
+func (u *SimpleUnion) SetI32(i32 int32) {
+ u.SimpleUnionTag = SimpleUnionI32
+ u.I32 = i32
+}
+
+func (u *SimpleUnion) SetI64(i64 int64) {
+ u.SimpleUnionTag = SimpleUnionI64
+ u.I64 = i64
+}
+
+func (u *SimpleUnion) SetS(s Int64Struct) {
+ u.SimpleUnionTag = SimpleUnionS
+ u.S = s
+}
+
+func (u *SimpleUnion) SetOs(os *Int64Struct) {
+ u.SimpleUnionTag = SimpleUnionOs
+ u.Os = os
+}
+
+func (u *SimpleUnion) SetStr(str string) {
+ u.SimpleUnionTag = SimpleUnionStr
+ u.Str = str
+}
+
+type UnionWithEmptyStructTag uint32
+
+const (
+ _ UnionWithEmptyStructTag = iota
+ UnionWithEmptyStructS
+ UnionWithEmptyStructS2
+)
+
+type UnionWithEmptyStruct struct {
+ UnionWithEmptyStructTag `fidl:"tag" fidl2:"u,16,8"`
+ S EmptyStruct
+ S2 *EmptyStruct
+}
+
+func (u *UnionWithEmptyStruct) Which() UnionWithEmptyStructTag {
+ return u.UnionWithEmptyStructTag
+}
+
+func (u *UnionWithEmptyStruct) SetS(s EmptyStruct) {
+ u.UnionWithEmptyStructTag = UnionWithEmptyStructS
+ u.S = s
+}
+
+func (u *UnionWithEmptyStruct) SetS2(s2 *EmptyStruct) {
+ u.UnionWithEmptyStructTag = UnionWithEmptyStructS2
+ u.S2 = s2
+}
+
+type IpAddressConfigTag uint32
+
+const (
+ _ IpAddressConfigTag = iota
+ IpAddressConfigPaddingSize24Align4
+ IpAddressConfigDhcp
+)
+
+type IpAddressConfig struct {
+ IpAddressConfigTag `fidl:"tag" fidl2:"u,28,4"`
+ PaddingSize24Align4 [6]uint32
+ Dhcp bool
+}
+
+func (u *IpAddressConfig) Which() IpAddressConfigTag {
+ return u.IpAddressConfigTag
+}
+
+func (u *IpAddressConfig) SetPaddingSize24Align4(paddingSize24Align4 [6]uint32) {
+ u.IpAddressConfigTag = IpAddressConfigPaddingSize24Align4
+ u.PaddingSize24Align4 = paddingSize24Align4
+}
+
+func (u *IpAddressConfig) SetDhcp(dhcp bool) {
+ u.IpAddressConfigTag = IpAddressConfigDhcp
+ u.Dhcp = dhcp
+}
+
+type SampleXUnionTag uint32
+
+const (
+ SampleXUnionU = 949769906 // 0x389c56b2
+ SampleXUnionSu = 2033143581 // 0x792f4f1d
+ SampleXUnionSt = 35514581 // 0x21de8d5
+)
+
+type SampleXUnion struct {
+ SampleXUnionTag `fidl2:"x,24,8"`
+ U uint32 `fidl:"949769906" fidl2:"949769906"`
+ Su SimpleUnion `fidl:"2033143581" fidl2:"2033143581"`
+ St SimpleTable `fidl:"35514581" fidl2:"35514581"`
+}
+
+func (_m *SampleXUnion) Which() SampleXUnionTag {
+ return _m.SampleXUnionTag
+}
+
+func (_m *SampleXUnion) SetU(u uint32) {
+ _m.SampleXUnionTag = SampleXUnionU
+ _m.U = u
+}
+
+func (_m *SampleXUnion) SetSu(su SimpleUnion) {
+ _m.SampleXUnionTag = SampleXUnionSu
+ _m.Su = su
+}
+
+func (_m *SampleXUnion) SetSt(st SimpleTable) {
+ _m.SampleXUnionTag = SampleXUnionSt
+ _m.St = st
+}
+
+type XUnionWithEmptyStructTag uint32
+
+const (
+ XUnionWithEmptyStructS = 1956241662 // 0x7499e0fe
+)
+
+type XUnionWithEmptyStruct struct {
+ XUnionWithEmptyStructTag `fidl2:"x,24,8"`
+ S EmptyStruct `fidl:"1956241662" fidl2:"1956241662"`
+}
+
+func (_m *XUnionWithEmptyStruct) Which() XUnionWithEmptyStructTag {
+ return _m.XUnionWithEmptyStructTag
+}
+
+func (_m *XUnionWithEmptyStruct) SetS(s EmptyStruct) {
+ _m.XUnionWithEmptyStructTag = XUnionWithEmptyStructS
+ _m.S = s
+}
+
+type SimpleTable struct {
+ _ struct{} `fidl2:"t,16,8"`
+ X int64 `fidl:"1" fidl2:"1"`
+ XPresent bool
+ Y int64 `fidl:"5" fidl2:"5"`
+ YPresent bool
+}
+
+func (u *SimpleTable) SetX(x int64) {
+ u.X = x
+ u.XPresent = true
+}
+
+func (u *SimpleTable) GetX() int64 {
+ return u.X
+}
+
+func (u *SimpleTable) GetXWithDefault(_default int64) int64 {
+ if !u.HasX() {
+ return _default
+ }
+ return u.X
+}
+
+func (u *SimpleTable) HasX() bool {
+ return u.XPresent
+}
+
+func (u *SimpleTable) ClearX() {
+ u.XPresent = false
+}
+
+func (u *SimpleTable) SetY(y int64) {
+ u.Y = y
+ u.YPresent = true
+}
+
+func (u *SimpleTable) GetY() int64 {
+ return u.Y
+}
+
+func (u *SimpleTable) GetYWithDefault(_default int64) int64 {
+ if !u.HasY() {
+ return _default
+ }
+ return u.Y
+}
+
+func (u *SimpleTable) HasY() bool {
+ return u.YPresent
+}
+
+func (u *SimpleTable) ClearY() {
+ u.YPresent = false
+}
+
+type TableWithStringAndVector struct {
+ _ struct{} `fidl2:"t,16,8"`
+ Foo string `fidl:",1" fidl2:"1,"`
+ FooPresent bool
+ Bar int32 `fidl:"2" fidl2:"2"`
+ BarPresent bool
+ Baz []uint8 `fidl:",3" fidl2:"3,"`
+ BazPresent bool
+}
+
+func (u *TableWithStringAndVector) SetFoo(foo string) {
+ u.Foo = foo
+ u.FooPresent = true
+}
+
+func (u *TableWithStringAndVector) GetFoo() string {
+ return u.Foo
+}
+
+func (u *TableWithStringAndVector) GetFooWithDefault(_default string) string {
+ if !u.HasFoo() {
+ return _default
+ }
+ return u.Foo
+}
+
+func (u *TableWithStringAndVector) HasFoo() bool {
+ return u.FooPresent
+}
+
+func (u *TableWithStringAndVector) ClearFoo() {
+ u.FooPresent = false
+}
+
+func (u *TableWithStringAndVector) SetBar(bar int32) {
+ u.Bar = bar
+ u.BarPresent = true
+}
+
+func (u *TableWithStringAndVector) GetBar() int32 {
+ return u.Bar
+}
+
+func (u *TableWithStringAndVector) GetBarWithDefault(_default int32) int32 {
+ if !u.HasBar() {
+ return _default
+ }
+ return u.Bar
+}
+
+func (u *TableWithStringAndVector) HasBar() bool {
+ return u.BarPresent
+}
+
+func (u *TableWithStringAndVector) ClearBar() {
+ u.BarPresent = false
+}
+
+func (u *TableWithStringAndVector) SetBaz(baz []uint8) {
+ u.Baz = baz
+ u.BazPresent = true
+}
+
+func (u *TableWithStringAndVector) GetBaz() []uint8 {
+ return u.Baz
+}
+
+func (u *TableWithStringAndVector) GetBazWithDefault(_default []uint8) []uint8 {
+ if !u.HasBaz() {
+ return _default
+ }
+ return u.Baz
+}
+
+func (u *TableWithStringAndVector) HasBaz() bool {
+ return u.BazPresent
+}
+
+func (u *TableWithStringAndVector) ClearBaz() {
+ u.BazPresent = false
+}
+
+type TableWithEmptyStruct struct {
+ _ struct{} `fidl2:"t,16,8"`
+ S EmptyStruct `fidl:"1" fidl2:"1"`
+ SPresent bool
+}
+
+func (u *TableWithEmptyStruct) SetS(s EmptyStruct) {
+ u.S = s
+ u.SPresent = true
+}
+
+func (u *TableWithEmptyStruct) GetS() EmptyStruct {
+ return u.S
+}
+
+func (u *TableWithEmptyStruct) GetSWithDefault(_default EmptyStruct) EmptyStruct {
+ if !u.HasS() {
+ return _default
+ }
+ return u.S
+}
+
+func (u *TableWithEmptyStruct) HasS() bool {
+ return u.SPresent
+}
+
+func (u *TableWithEmptyStruct) ClearS() {
+ u.SPresent = false
+}
+
+type XUnionInTable struct {
+ _ struct{} `fidl2:"t,16,8"`
+ Before string `fidl:",1" fidl2:"1,"`
+ BeforePresent bool
+ Xu SampleXUnion `fidl:"2" fidl2:"2"`
+ XuPresent bool
+ After string `fidl:",3" fidl2:"3,"`
+ AfterPresent bool
+}
+
+func (u *XUnionInTable) SetBefore(before string) {
+ u.Before = before
+ u.BeforePresent = true
+}
+
+func (u *XUnionInTable) GetBefore() string {
+ return u.Before
+}
+
+func (u *XUnionInTable) GetBeforeWithDefault(_default string) string {
+ if !u.HasBefore() {
+ return _default
+ }
+ return u.Before
+}
+
+func (u *XUnionInTable) HasBefore() bool {
+ return u.BeforePresent
+}
+
+func (u *XUnionInTable) ClearBefore() {
+ u.BeforePresent = false
+}
+
+func (u *XUnionInTable) SetXu(xu SampleXUnion) {
+ u.Xu = xu
+ u.XuPresent = true
+}
+
+func (u *XUnionInTable) GetXu() SampleXUnion {
+ return u.Xu
+}
+
+func (u *XUnionInTable) GetXuWithDefault(_default SampleXUnion) SampleXUnion {
+ if !u.HasXu() {
+ return _default
+ }
+ return u.Xu
+}
+
+func (u *XUnionInTable) HasXu() bool {
+ return u.XuPresent
+}
+
+func (u *XUnionInTable) ClearXu() {
+ u.XuPresent = false
+}
+
+func (u *XUnionInTable) SetAfter(after string) {
+ u.After = after
+ u.AfterPresent = true
+}
+
+func (u *XUnionInTable) GetAfter() string {
+ return u.After
+}
+
+func (u *XUnionInTable) GetAfterWithDefault(_default string) string {
+ if !u.HasAfter() {
+ return _default
+ }
+ return u.After
+}
+
+func (u *XUnionInTable) HasAfter() bool {
+ return u.AfterPresent
+}
+
+func (u *XUnionInTable) ClearAfter() {
+ u.AfterPresent = false
+}
+
+type EthernetDeviceInterface _bindings.ChannelProxy
+
+type EthernetDevice interface {
+}
+
+type EthernetDeviceTransitionalBase struct{}
+
+type EthernetDeviceInterfaceRequest _bindings.InterfaceRequest
+
+func NewEthernetDeviceInterfaceRequest() (EthernetDeviceInterfaceRequest, *EthernetDeviceInterface, error) {
+ req, cli, err := _bindings.NewInterfaceRequest()
+ return EthernetDeviceInterfaceRequest(req), (*EthernetDeviceInterface)(cli), err
+}
+
+type EthernetDeviceStub struct {
+ Impl EthernetDevice
+}
+
+func (s *EthernetDeviceStub) DispatchNew(ord uint32, b_ []byte, h_ []_zx.Handle) (_bindings.Message, error) {
+ switch ord {
+ }
+ return nil, _bindings.ErrUnknownOrdinal
+}
+
+type EthernetDeviceService struct {
+ _bindings.BindingSet
+}
+
+func (s *EthernetDeviceService) Add(impl EthernetDevice, c _zx.Channel, onError func(error)) (_bindings.BindingKey, error) {
+ return s.BindingSet.Add(&EthernetDeviceStub{Impl: impl}, c, onError)
+}
+
+func (s *EthernetDeviceService) EventProxyFor(key _bindings.BindingKey) (*EthernetDeviceEventProxy, bool) {
+ pxy, err := s.BindingSet.ProxyFor(key)
+ return (*EthernetDeviceEventProxy)(pxy), err
+}
+
+type EthernetDeviceEventProxy _bindings.ChannelProxy
diff --git a/src/syscall/zx/fidl/deletemepostmigration.go b/src/syscall/zx/fidl/deletemepostmigration.go
new file mode 100644
index 0000000..982212a
--- /dev/null
+++ b/src/syscall/zx/fidl/deletemepostmigration.go
@@ -0,0 +1,22 @@
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build fuchsia
+
+package fidl
+
+import "syscall/zx"
+
+// TODO(pascallouis): Delete all of this post migration, and rename all XyxNew
+// methods to Xyz.
+
+const MessageHeaderSize int = 16
+
+func MarshalNew(message Message, data []byte, handles []zx.Handle) (int, int, error) {
+ return Marshal(message, data, handles)
+}
+
+func UnmarshalNew(data []byte, handles []zx.Handle, message Message) (int, int, error) {
+ return Unmarshal(data, handles, message)
+}
diff --git a/src/syscall/zx/fidl/encoding.go b/src/syscall/zx/fidl/encoding.go
new file mode 100644
index 0000000..7410470
--- /dev/null
+++ b/src/syscall/zx/fidl/encoding.go
@@ -0,0 +1,169 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build fuchsia
+
+package fidl
+
+import (
+ "math"
+ "reflect"
+ "syscall/zx"
+)
+
+const (
+ allocPresent uint64 = math.MaxUint64
+ noAlloc = 0
+)
+
+const (
+ handlePresent uint32 = math.MaxUint32
+ noHandle = 0
+)
+
+var (
+ // TODO(mknyszek): Add support here for process, thread, job, resource,
+ // interrupt, eventpair, fifo, guest, and time once these are actually
+ // supported in the Go runtime.
+ handleType reflect.Type = reflect.TypeOf(zx.Handle(0))
+ channelType = reflect.TypeOf(zx.Channel(0))
+ logType = reflect.TypeOf(zx.Log(0))
+ portType = reflect.TypeOf(zx.Port(0))
+ vmoType = reflect.TypeOf(zx.VMO(0))
+ eventType = reflect.TypeOf(zx.Event(0))
+ socketType = reflect.TypeOf(zx.Socket(0))
+ vmarType = reflect.TypeOf(zx.VMAR(0))
+ interfaceRequestType = reflect.TypeOf(InterfaceRequest{})
+ proxyType = reflect.TypeOf(ChannelProxy{})
+)
+
+// isHandleType returns true if the reflected type is a Fuchsia handle type.
+func isHandleType(t reflect.Type) bool {
+ switch t {
+ case handleType:
+ fallthrough
+ case channelType:
+ fallthrough
+ case logType:
+ fallthrough
+ case portType:
+ fallthrough
+ case vmoType:
+ fallthrough
+ case eventType:
+ fallthrough
+ case socketType:
+ fallthrough
+ case vmarType:
+ return true
+ }
+ return false
+}
+
+// isInterfaceType returns true if the reflected type is a FIDL interface type.
+func isInterfaceType(t reflect.Type) bool {
+ // FIDL interfaces are represented as aliases over Proxy.
+ return t.ConvertibleTo(proxyType)
+}
+
+// isInterfaceRequestType returns true if the reflected type is a FIDL interface
+// request type.
+func isInterfaceRequestType(t reflect.Type) bool {
+ // FIDL interfaces are represented as aliases over InterfaceRequest.
+ return t.ConvertibleTo(interfaceRequestType)
+}
+
+// align increases size such that size is aligned to bytes, and returns the new size.
+//
+// bytes must be a power of 2.
+func align(size, bytes int) int {
+ offset := size & (bytes - 1)
+ // If we're not currently aligned to |bytes| bytes, add padding.
+ if offset != 0 {
+ size += (bytes - offset)
+ }
+ return size
+}
+
+// encoder represents the encoding context that is necessary to maintain across
+// recursive calls within the same FIDL object.
+type encoder struct {
+ // head is the index into buffer at which new data will be written to for the current
+ // object. It must be updated before writing to a new out-of-line object, and then
+ // fixed when that object is finished.
+ head int
+
+ // buffer represents the output buffer that the encoder writes into.
+ buffer []byte
+
+ // handles are the handles discovered when traversing the FIDL data
+ // structure. They are referenced from within the serialized data
+ // structure in buffer.
+ handles []zx.Handle
+}
+
+func (e *encoder) newObject(size int) int {
+ size = align(size, 8)
+ start := len(e.buffer)
+ e.buffer = append(e.buffer, make([]byte, size)...)
+ return start
+}
+
+// writeUint writes an unsigned integer of byte-width size to the buffer.
+//
+// Before writing, it pads the buffer such that the integer is aligned to
+// its own byte-width.
+//
+// size must be a power of 2 <= 8.
+func (e *encoder) writeUint(val uint64, size int) {
+ e.head = align(e.head, size)
+ for i := e.head; i < e.head+size; i++ {
+ e.buffer[i] = byte(val & 0xFF)
+ val >>= 8
+ }
+ e.head += size
+}
+
+// decoder represents the decoding context that is necessary to maintain
+// across recursive calls within the same FIDL object.
+type decoder struct {
+ // head is the index into buffer at which new data will be read from for the current
+ // object. It must be updated before reading from a new out-of-line object, and then
+ // fixed when that object is finished.
+ head int
+
+ // nextObject is the byte index of the next out-of-line object in buffer.
+ nextObject int
+
+ // buffer represents the buffer we're decoding from.
+ buffer []byte
+
+ // handles represents the input untyped handled we're decoding.
+ handles []zx.Handle
+}
+
+// readUint reads an unsigned integer value of byte-width size from the
+// buffer, and protects against reading past the end of the buffer.
+//
+// Before a read, the head is moved forward so as to be naturally aligned with
+// the byte-width of the integer it is reading.
+//
+// Since this is a low-level read, directly off a byte buffer, the only exposed
+// shape is `uint64` with the expectation that callers will do the appropriate
+// conversion.
+//
+// size must be a power of 2 <= 8.
+func (d *decoder) readUint(size int) (uint64, error) {
+ d.head = align(d.head, size)
+ if len(d.buffer) < d.head+size {
+ return 0, ErrPayloadTooSmall
+ }
+ var val uint64
+ for i := d.head + size - 1; i >= d.head; i-- {
+ val <<= 8
+ val |= uint64(d.buffer[i])
+ }
+ d.head += size
+ return val, nil
+}
diff --git a/src/syscall/zx/fidl/encoding_new.go b/src/syscall/zx/fidl/encoding_new.go
new file mode 100644
index 0000000..8b885d6
--- /dev/null
+++ b/src/syscall/zx/fidl/encoding_new.go
@@ -0,0 +1,1390 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build fuchsia
+
+package fidl
+
+import (
+ "errors"
+ "math"
+ "reflect"
+ "strconv"
+ "strings"
+ "sync"
+ "syscall/zx"
+)
+
+// MustCreateMarshaler is like CreateMarshaler but panics if the sample struct
+// cannot be used to create a marshaler. It simplifies safe initialization of
+// global variables holding marshalers.
+func MustCreateMarshaler(sample interface{}) Marshaler {
+ m, err := CreateMarshaler(sample)
+ if err != nil {
+ panic(err)
+ }
+ return m
+}
+
+// CreateMarshaler creates a marshaler from a sample struct.
+func CreateMarshaler(sample interface{}) (Marshaler, error) {
+ typ := reflect.TypeOf(sample)
+ if typ.Kind() == reflect.Ptr {
+ typ = typ.Elem()
+ }
+ if typ.Kind() == reflect.Struct {
+ return createMarshaler(typ)
+ }
+ return nil, errors.New("unable to create marshaler for " + nicefmt(typ))
+}
+
+// CreateMarshaler creates a lazy marshaler from a sample struct. This lazy
+// marshaler initializes its actual delegate marshaler on first use, rather
+// than on creation. As a result, there is no validation on creation, and
+// instead the lazy marshaler will panic on first use if a marshaler
+// cannot be created of the sample provided.
+func CreateLazyMarshaler(sample interface{}) Marshaler {
+ return &lazyMarshaler{
+ sample: sample,
+ }
+}
+
+type lazyMarshaler struct {
+ once sync.Once
+ sample interface{}
+ delegate Marshaler
+}
+
+// Assert that lazyMarshaler implements the Marshaler interface.
+var _ Marshaler = &lazyMarshaler{}
+
+func (m *lazyMarshaler) init() {
+ m.delegate = MustCreateMarshaler(m.sample)
+}
+
+func (m *lazyMarshaler) getSize() int {
+ m.once.Do(m.init)
+ return m.delegate.getSize()
+}
+
+func (m *lazyMarshaler) marshal(v reflect.Value, out *encoder) error {
+ m.once.Do(m.init)
+ return m.delegate.marshal(v, out)
+}
+
+func (m *lazyMarshaler) unmarshal(in *decoder, v reflect.Value) error {
+ m.once.Do(m.init)
+ return m.delegate.unmarshal(in, v)
+}
+
+// Marshal marshals (or encodes) a message into the data and handles slices.
+func Marshal(message Message, data []byte, handles []zx.Handle) (int, int, error) {
+ // By construction, we know that message is a pointer to a struct since
+ // we only generate pointer receiver methods for top-level messages.
+ // Should one implement the interface differently, and call into this
+ // code, it would fail in an obsure way withing relfection. Just don't do
+ // that.
+ var (
+ v = reflect.ValueOf(message).Elem()
+ m = message.Marshaler()
+ )
+
+ // Now, let's get the value of s, marshal the header into a starting
+ // buffer, and then marshal the rest of the payload in s.
+ out := &encoder{buffer: data[:0], handles: handles[:0]}
+ out.head = out.newObject(m.getSize())
+ if err := m.marshal(v, out); err != nil {
+ return 0, 0, err
+ }
+ return len(out.buffer), len(out.handles), nil
+}
+
+// Unmarshal unmarshals (or decodes) into message using the data and handles
+// slices.
+func Unmarshal(data []byte, handles []zx.Handle, message Message) (int, int, error) {
+ // By construction, we know that message is a pointer to a struct since
+ // we only generate pointer receiver methods for top-level messages.
+ // Should one implement the interface differently, and call into this
+ // code, it would fail in an obsure way withing relfection. Just don't do
+ // that.
+ var (
+ v = reflect.ValueOf(message).Elem()
+ m = message.Marshaler()
+ )
+
+ // Get the payload's value and unmarshal it.
+ nextObject := align(m.getSize(), 8)
+ in := &decoder{
+ buffer: data,
+ handles: handles,
+ nextObject: nextObject,
+ }
+ if err := m.unmarshal(in, v); err != nil {
+ return 0, 0, err
+ }
+ return len(in.buffer), len(handles) - len(in.handles), nil
+}
+
+const tagKey = "fidl2"
+
+type tagKind int
+
+const (
+ _ = iota
+ structTag tagKind = iota
+ unionTag
+ xunionTag
+ tableTag
+ boundsTag
+)
+
+type bounds []int
+
+func (b bounds) pop() (int, []int) {
+ if len(b) == 0 {
+ return math.MaxInt32, nil
+ }
+ return b[0], b[1:]
+}
+
+func nicefmt(typ reflect.Type) string {
+ if len(typ.Name()) == 0 {
+ return typ.Kind().String()
+ } else {
+ return typ.Name() + " (" + typ.Kind().String() + ")"
+ }
+}
+
+func createMarshaler(typ reflect.Type) (Marshaler, error) {
+ // field 0 holds the tag
+ marshalerKind, marshalerBounds := readTag(typ.Field(0))
+ var (
+ kind = marshalerKind
+ size = marshalerBounds[0]
+ alignment = marshalerBounds[1]
+ fields []mField
+ ordinals []int
+ )
+ // field 1 and up are the actual data fields
+ // - structs, unions, and xunions have fields one after the other;
+ // - tables have a field, followed by a bool presence indicator, etc.
+ for index := 1; index < typ.NumField(); index++ {
+ field := typ.Field(index)
+ _, fieldBounds := readTag(field)
+ if kind == xunionTag || kind == tableTag {
+ ordinal, actualBounds := fieldBounds.pop()
+ ordinals = append(ordinals, ordinal)
+ fieldBounds = actualBounds
+ }
+ fieldMarshaler, err := createMarshalerForField(field.Type, fieldBounds)
+ if err != nil {
+ return nil, err
+ }
+ fields = append(fields, mField{fieldMarshaler, index})
+ if kind == tableTag {
+ if typ.Field(index+1).Type.Kind() != reflect.Bool {
+ return nil, errors.New("incorrect presence field on " + nicefmt(typ))
+ }
+ index++ // i.e. skip presence field.
+ }
+ }
+
+ switch kind {
+ case structTag:
+ if len(fields) == 0 {
+ return mEmptyStruct{}, nil
+ }
+
+ return mStruct{
+ fields: fields,
+ size: size,
+ alignment: alignment,
+ }, nil
+ case unionTag:
+ return mUnion{
+ fields: fields,
+ size: size,
+ alignment: alignment,
+ }, nil
+ case xunionTag:
+ ordinalTofields := make(map[int]mField)
+ for i := 0; i < len(fields); i++ {
+ ordinalTofields[ordinals[i]] = fields[i]
+ }
+ return mXUnion{
+ fields: ordinalTofields,
+ size: size,
+ alignment: alignment,
+ }, nil
+ case tableTag:
+ return mTable{
+ mStruct: mStruct{
+ fields: fields,
+ size: size,
+ alignment: alignment,
+ },
+ ordinals: ordinals,
+ }, nil
+ default:
+ return nil, errors.New("missing kind marker on " + nicefmt(typ))
+ }
+}
+
+// readTag reads a fidl tag which can be one of
+//
+// s,size,alignement -- marking a struct, with its size, and alignment
+// u,size,alignement -- marking a union, with its size, and alignment
+// x,size,alignement -- marking a xunion, with its size, and alignment
+// t,size,alignement -- marking a table, with its size, and alignment
+// num1, num2, ... -- recording bounds of the types present on the field
+//
+// When handles or interfaces are present, the bounds indicate nullability,
+// with 0 indicating false (not nullable), and any other value true (nullable).
+func readTag(field reflect.StructField) (tagKind, bounds) {
+ content, ok := field.Tag.Lookup(tagKey)
+ if !ok {
+ return boundsTag, nil
+ }
+ elems := strings.Split(content, ",")
+ switch elems[0] {
+ case "s":
+ return structTag, toBounds(elems[1:])
+ case "u":
+ return unionTag, toBounds(elems[1:])
+ case "x":
+ return xunionTag, toBounds(elems[1:])
+ case "t":
+ return tableTag, toBounds(elems[1:])
+ default:
+ return boundsTag, toBounds(elems)
+ }
+}
+
+func toBounds(elems []string) bounds {
+ var nums []int
+ for _, elem := range elems {
+ var (
+ num = math.MaxInt32
+ err error
+ )
+ if len(elem) != 0 {
+ num, err = strconv.Atoi(elem)
+ if err != nil {
+ panic(elem + ": " + err.Error())
+ }
+ }
+ nums = append(nums, num)
+ }
+ return bounds(nums)
+}
+
+func createMarshalerForField(typ reflect.Type, bounds bounds) (Marshaler, error) {
+ if isHandleType(typ) {
+ // TODO(pascallouis): Check that handles' subtype conform?
+ nullable, _ := bounds.pop()
+ return mHandle(nullable != 0), nil
+ }
+
+ if isInterfaceType(typ) || isInterfaceRequestType(typ) {
+ nullable, _ := bounds.pop()
+ return mInterface(nullable != 0), nil
+ }
+
+ switch typ.Kind() {
+ case reflect.Bool:
+ return mBool{}, nil
+ case reflect.Int8:
+ return mInt(1), nil
+ case reflect.Int16:
+ return mInt(2), nil
+ case reflect.Int32:
+ return mInt(4), nil
+ case reflect.Int64:
+ return mInt(8), nil
+ case reflect.Uint8:
+ return mUint(1), nil
+ case reflect.Uint16:
+ return mUint(2), nil
+ case reflect.Uint32:
+ return mUint(4), nil
+ case reflect.Uint64:
+ return mUint(8), nil
+ case reflect.Float32:
+ return mFloat32{}, nil
+ case reflect.Float64:
+ return mFloat64{}, nil
+ case reflect.String:
+ maxSize, _ := bounds.pop()
+ return mString(maxSize), nil
+ case reflect.Array:
+ elemMarshaler, err := createMarshalerForField(typ.Elem(), bounds)
+ if err != nil {
+ return nil, err
+ }
+ return mArray{
+ Marshaler: elemMarshaler,
+ size: typ.Len(),
+ }, nil
+ case reflect.Slice:
+ maxSize, remainder := bounds.pop()
+ elemTyp := typ.Elem()
+ elemMarshaler, err := createMarshalerForField(elemTyp, remainder)
+ if err != nil {
+ return nil, err
+ }
+ return mVector{
+ Marshaler: elemMarshaler,
+ maxSize: maxSize,
+ sliceTyp: reflect.SliceOf(elemTyp),
+ isVectorUint8: elemTyp.Kind() == reflect.Uint8,
+ }, nil
+ case reflect.Struct:
+ return createMarshaler(typ)
+ case reflect.Ptr:
+ return createOptMarshalerForField(typ.Elem(), bounds)
+ default:
+ return nil, errors.New("unable to create field marshaler for " + nicefmt(typ))
+ }
+}
+
+func createOptMarshalerForField(typ reflect.Type, bounds bounds) (Marshaler, error) {
+ m, err := createMarshalerForField(typ, bounds)
+ if err != nil {
+ return nil, err
+ }
+ switch m := m.(type) {
+ case mString:
+ return mOptString(m), nil
+ case mVector:
+ return mOptVector(m), nil
+ case mEmptyStruct:
+ return mOptStructUnionTable{
+ Marshaler: m,
+ elemTyp: typ,
+ }, nil
+ case mStruct:
+ return mOptStructUnionTable{
+ Marshaler: m,
+ elemTyp: typ,
+ }, nil
+ case mUnion:
+ return mOptStructUnionTable{
+ Marshaler: m,
+ elemTyp: typ,
+ }, nil
+ case mXUnion:
+ return mOptXUnion{
+ mXUnion: m,
+ typ: typ,
+ }, nil
+ case mTable:
+ return mOptStructUnionTable{
+ Marshaler: m,
+ elemTyp: typ,
+ }, nil
+ default:
+ return nil, errors.New("unable to create optional field marshaler for " + nicefmt(typ))
+ }
+}
+
+// Message is implemented by any value that represents a FIDL message.
+type Message interface {
+ Marshaler() Marshaler
+}
+
+type Marshaler interface {
+ getSize() int
+ marshal(v reflect.Value, out *encoder) error
+ unmarshal(in *decoder, v reflect.Value) error
+}
+
+// Assert various encoders implement the Marshaler interface.
+var _ = []Marshaler{
+ mStruct{},
+ mEmptyStruct{},
+ mUnion{},
+ mXUnion{},
+ mOptXUnion{},
+ mTable{},
+ mOptStructUnionTable{},
+ mArray{},
+ mVector{},
+ mOptVector{},
+ mBool{},
+ mInt(0),
+ mUint(0),
+ mFloat32{},
+ mFloat64{},
+ mString(0),
+ mOptString(0),
+}
+
+type mField struct {
+ Marshaler
+ index int
+}
+
+type mStruct struct {
+ fields []mField
+ size, alignment int
+}
+
+func (m mStruct) getSize() int {
+ return m.size
+}
+
+func (m mStruct) marshal(v reflect.Value, out *encoder) error {
+ out.head = align(out.head, m.alignment)
+ for _, field := range m.fields {
+ if err := field.Marshaler.marshal(v.Field(field.index), out); err != nil {
+ return err
+ }
+ }
+ out.head = align(out.head, m.alignment)
+ return nil
+}
+
+func (m mStruct) unmarshal(in *decoder, v reflect.Value) error {
+ in.head = align(in.head, m.alignment)
+ for _, field := range m.fields {
+ if err := field.Marshaler.unmarshal(in, v.Field(field.index)); err != nil {
+ return err
+ }
+ }
+ in.head = align(in.head, m.alignment)
+ return nil
+}
+
+type mEmptyStruct struct{}
+
+func (_ mEmptyStruct) getSize() int {
+ return 1
+}
+
+func (_ mEmptyStruct) marshal(v reflect.Value, out *encoder) error {
+ out.writeUint(0, 1)
+ return nil
+}
+
+func (_ mEmptyStruct) unmarshal(in *decoder, v reflect.Value) error {
+ zero, err := in.readUint(1)
+ if err != nil {
+ return err
+ } else if zero != 0 {
+ return newValueError(ErrInvalidEmptyStruct, zero)
+ }
+
+ return nil
+}
+
+type mUnion struct {
+ fields []mField
+ size, alignment int
+}
+
+func (m mUnion) getSize() int {
+ return m.size
+}
+
+func (m mUnion) marshal(v reflect.Value, out *encoder) error {
+ // Kind.
+ kind := int(v.Field(0).Uint()) - 1
+ if kind < 0 || len(m.fields) <= kind {
+ return newValueError(ErrInvalidUnionTag, kind)
+ }
+
+ // Save the head for proper padding.
+ head := out.head
+ out.writeUint(uint64(kind), 4)
+
+ // Re-align to the union's alignment before writing its field.
+ out.head = align(out.head, m.alignment)
+
+ // Marshal field.
+ if err := m.fields[kind].Marshaler.marshal(v.Field(kind+1), out); err != nil {
+ return err
+ }
+
+ // Re-position head.
+ out.head = head + m.size
+
+ return nil
+}
+
+func (m mUnion) unmarshal(in *decoder, v reflect.Value) error {
+ // Save the head for proper padding.
+ head := in.head
+
+ // Kind.
+ kind, err := in.readUint(4)
+ if err != nil {
+ return err
+ }
+ if uint64(len(m.fields)) <= kind {
+ return newValueError(ErrInvalidUnionTag, kind)
+ }
+ v.Field(0).SetUint(kind + 1)
+
+ // Re-align to the union's alignement before writing its field.
+ in.head = align(in.head, m.alignment)
+
+ // Unmarshal field.
+ ikind := int(kind)
+ if err := m.fields[ikind].Marshaler.unmarshal(in, v.Field(ikind+1)); err != nil {
+ return err
+ }
+
+ // Re-position head.
+ in.head = head + m.size
+
+ return nil
+}
+
+type mXUnion struct {
+ fields map[int]mField
+ size, alignment int
+}
+
+func (m mXUnion) getSize() int {
+ return m.size
+}
+
+func (m mXUnion) marshal(v reflect.Value, out *encoder) error {
+ // Ordinal.
+ ordinal := int(v.Field(0).Uint())
+ field, ok := m.fields[ordinal]
+ if !ok {
+ return newValueError(ErrInvalidUnionTag, ordinal)
+ }
+ out.writeUint(uint64(ordinal), 8)
+
+ // Field.
+ if err := marshalEnvelopePresent(field, v.Field(field.index), out); err != nil {
+ return err
+ }
+
+ return nil
+}
+
+func (m mXUnion) unmarshal(in *decoder, v reflect.Value) error {
+ return m.unmarshalWithOptSpecified(in, v, nil)
+}
+
+func (m mXUnion) unmarshalWithOptSpecified(in *decoder, v reflect.Value, typ reflect.Type) error {
+ // Can this envelope be optional? If it can, the type must be provided
+ // in order to reflectively create a pointer container.
+ optAllowed := typ != nil
+
+ // Ordinal.
+ ordinal, err := in.readUint(4)
+ if err != nil {
+ return err
+ }
+ var (
+ fieldMarshaler Marshaler
+ fieldV reflect.Value
+ )
+ if ordinal != 0 {
+ // Regardless of context, envelope must be present if the ordinal is
+ // non-zero.
+ optAllowed = false
+
+ field, ok := m.fields[int(ordinal)]
+ if !ok {
+ return newValueError(ErrInvalidUnionTag, ordinal)
+ }
+ if typ != nil {
+ v.Set(reflect.New(typ))
+ v = v.Elem()
+ }
+ v.Field(0).SetUint(ordinal)
+ fieldMarshaler = field.Marshaler
+ fieldV = v.Field(field.index)
+ } else if !optAllowed {
+ return newValueError(ErrInvalidUnionTag, ordinal)
+ }
+
+ // Field.
+ var mode unmarshalEnvelopeMode
+ if optAllowed {
+ mode = knownMayBeAbsent
+ } else {
+ mode = knowMustBePresent
+ }
+ isPresent, err := unmarshalEnvelope(fieldMarshaler, in, fieldV, mode)
+ if err != nil {
+ return err
+ }
+ if !isPresent {
+ v.Set(reflect.Zero(reflect.PtrTo(typ)))
+ }
+ return nil
+}
+
+type mOptXUnion struct {
+ mXUnion
+ typ reflect.Type
+}
+
+func (m mOptXUnion) getSize() int {
+ return m.size
+}
+
+func (m mOptXUnion) marshal(v reflect.Value, out *encoder) error {
+ if v.IsNil() {
+ out.writeUint(0, 8) // ordinal + padding
+ marshalEnvelopeAbsent(out)
+ return nil
+ } else {
+ return m.mXUnion.marshal(v.Elem(), out)
+ }
+}
+
+func (m mOptXUnion) unmarshal(in *decoder, v reflect.Value) error {
+ return m.unmarshalWithOptSpecified(in, v, m.typ)
+}
+
+type mTable struct {
+ mStruct
+ ordinals []int
+}
+
+const envelopeSize = 16
+
+func marshalEnvelopePresent(m Marshaler, v reflect.Value, out *encoder) error {
+ numHandles := len(out.handles)
+ numBytes := len(out.buffer)
+ head := out.head
+ out.head = out.newObject(m.getSize())
+ if err := m.marshal(v, out); err != nil {
+ return err
+ }
+ numHandles = len(out.handles) - numHandles
+ numBytes = len(out.buffer) - numBytes
+ out.head = head
+ out.writeUint(uint64(numBytes), 4)
+ out.writeUint(uint64(numHandles), 4)
+ out.writeUint(allocPresent, 8)
+ return nil
+}
+
+func marshalEnvelopeAbsent(out *encoder) {
+ out.writeUint(0, 8) // both numBytes, and numHandles
+ out.writeUint(noAlloc, 8)
+}
+
+type unmarshalEnvelopeMode int
+
+const (
+ _ unmarshalEnvelopeMode = iota
+
+ // knownMayBeAbsent indicates that the content of the envelope is known,
+ // and that it may be absent, i.e. encountering an empty envelope is
+ // expected
+ knownMayBeAbsent
+
+ // knowMustBePresent indicates that the content of the envelope is known,
+ // and that it must be present, i.e. encountering an empty envelope
+ // should be considered a failure
+ knowMustBePresent
+
+ // unknown indicates that the content of the envelope is unknown
+ // TODO(FTP-033): we are clarifying whether we should be strict (i.e. fail
+ // on unknown content), extensible (i.e. safely skip content), or allow
+ // both modes as proposed. For now, we choose in this implementation to
+ // be extensible
+ unknown
+)
+
+func unmarshalEnvelope(m Marshaler, in *decoder, v reflect.Value, mode unmarshalEnvelopeMode) (bool, error) {
+ nbu, err := in.readUint(4)
+ if err != nil {
+ return false, err
+ }
+ numBytes := int(nbu)
+
+ nhu, err := in.readUint(4)
+ if err != nil {
+ return false, err
+ }
+ numHandles := int(nhu)
+
+ fieldPresent, err := in.readUint(8)
+ if err != nil {
+ return false, err
+ }
+ switch fieldPresent {
+ case allocPresent:
+ if mode == unknown {
+ for i := 0; i < numHandles; i++ {
+ in.handles[0].Close() // best effort
+ in.handles = in.handles[1:]
+ }
+ return false, nil
+ } else {
+ savedHead := in.head
+ in.head = in.nextObject
+ in.nextObject += align(m.getSize(), 8)
+ if err := m.unmarshal(in, v); err != nil {
+ return false, err
+ }
+ in.head = savedHead
+ return true, nil
+ }
+ case noAlloc:
+ if mode == knowMustBePresent {
+ return false, newValueError(ErrUnexpectedNullRef, v)
+ }
+ if numBytes != 0 {
+ return false, newValueError(ErrUnexpectedNumBytes, numBytes)
+ }
+ if numHandles != 0 {
+ return false, newValueError(ErrUnexpectedNumHandles, numHandles)
+ }
+ return false, nil
+ default:
+ return false, newValueError(ErrBadRefEncoding, v)
+ }
+}
+
+func (m mTable) marshal(v reflect.Value, out *encoder) error {
+ // Determining max ordinal.
+ var (
+ maxOrdinal int
+ numKnown = len(m.ordinals)
+ fieldPresent = make([]bool, numKnown)
+ )
+ for index := 0; index < numKnown; index++ {
+ presenceIndex := index*2 + 2
+ fieldPresent[index] = v.Field(presenceIndex).Bool()
+ if fieldPresent[index] {
+ if fieldOrdinal := m.ordinals[index]; maxOrdinal < fieldOrdinal {
+ maxOrdinal = fieldOrdinal
+ }
+ }
+ }
+
+ // Vector of envelopes header.
+ out.writeUint(uint64(maxOrdinal), 8)
+ out.writeUint(allocPresent, 8)
+
+ // Early exit on empty table.
+ if maxOrdinal == 0 {
+ return nil
+ }
+
+ // Encode in the out-of-line object.
+ oldHead := out.head
+ out.head = out.newObject(maxOrdinal * envelopeSize)
+
+ // Envelopes.
+ var (
+ ordinal = 1
+ index, fieldIndex, presenceIndex = 0, 1, 2
+ )
+ for ordinal <= maxOrdinal {
+ fieldKnown := index < numKnown && ordinal == m.ordinals[index]
+ if fieldKnown && fieldPresent[index] {
+ if err := marshalEnvelopePresent(m.fields[index], v.Field(fieldIndex), out); err != nil {
+ return err
+ }
+ } else {
+ marshalEnvelopeAbsent(out)
+ }
+
+ ordinal++
+ if fieldKnown {
+ index++
+ fieldIndex += 2 // i.e. skip presenece field
+ presenceIndex += 2 // i.e. skip field
+ }
+ }
+
+ // Re-position head.
+ out.head = oldHead
+
+ return nil
+}
+
+func (m mTable) unmarshal(in *decoder, v reflect.Value) error {
+ mou, err := in.readUint(8)
+ if err != nil {
+ return err
+ }
+
+ // uints/ints are only guaranteed to be 32 bit longs.
+ // we use maxOrdinal as an int, so we must make sure that it fits.
+ if mou > uint64(^uint(0)) {
+ return newValueError(ErrUnexpectedOrdinal, v)
+ }
+ maxOrdinal := int(mou)
+
+ allocPtr, err := in.readUint(8)
+ if err != nil {
+ return err
+ }
+ switch allocPtr {
+ case allocPresent:
+ // good
+ case noAlloc:
+ return newValueError(ErrUnexpectedNullRef, v)
+ default:
+ return newValueError(ErrBadRefEncoding, v)
+ }
+
+ // Early exit on empty table.
+ if maxOrdinal == 0 {
+ return nil
+ }
+
+ // Envelopes.
+ var (
+ numKnown = len(m.ordinals)
+ ordinal = 1
+ index, fieldIndex, presenceIndex = 0, 1, 2
+ )
+ tableBodyHead := in.nextObject
+ in.nextObject += maxOrdinal * envelopeSize
+ oldHead := in.head
+ in.head = tableBodyHead
+ for ordinal <= maxOrdinal {
+ fieldKnown := index < numKnown && ordinal == m.ordinals[index]
+ if fieldKnown {
+ if isPresent, err := unmarshalEnvelope(m.fields[index], in, v.Field(fieldIndex), knownMayBeAbsent); err != nil {
+ return err
+ } else if isPresent {
+ v.Field(presenceIndex).SetBool(true)
+ }
+ } else {
+ if _, err := unmarshalEnvelope(nil, in, reflect.Value{}, unknown); err != nil {
+ return err
+ }
+ }
+ ordinal++
+ if fieldKnown {
+ index++
+ fieldIndex += 2 // i.e skip presence field
+ presenceIndex += 2 // i.e skip field
+ }
+ }
+ in.head = oldHead
+
+ return nil
+}
+
+type mOptStructUnionTable struct {
+ Marshaler
+ elemTyp reflect.Type
+}
+
+func (m mOptStructUnionTable) getSize() int {
+ return 8
+}
+
+func (m mOptStructUnionTable) marshal(v reflect.Value, out *encoder) error {
+ // Nil?
+ if v.IsNil() {
+ out.writeUint(noAlloc, 8)
+ return nil
+ }
+
+ // Write out allocation marker.
+ out.writeUint(allocPresent, 8)
+
+ // Set up the out-of-line space and the head.
+ oldHead := out.head
+ out.head = out.newObject(align(m.Marshaler.getSize(), 8))
+
+ // Marshal field.
+ if err := m.Marshaler.marshal(v.Elem(), out); err != nil {
+ return err
+ }
+
+ // Re-position head.
+ out.head = oldHead
+
+ return nil
+}
+
+func (m mOptStructUnionTable) unmarshal(in *decoder, v reflect.Value) error {
+ // Nil?
+ ptr, err := in.readUint(8)
+ if err != nil {
+ return err
+ }
+ switch ptr {
+ case noAlloc:
+ v.Set(reflect.Zero(v.Type()))
+ return nil
+ case allocPresent:
+ // good
+ default:
+ return newValueError(ErrBadRefEncoding, v)
+ }
+
+ // Create the new struct.
+ v.Set(reflect.New(m.elemTyp))
+
+ // Set up the out-of-line space and the head.
+ oldHead := in.head
+ in.head = in.nextObject
+ in.nextObject += align(m.Marshaler.getSize(), 8)
+
+ // Unmarshal field.
+ if err := m.Marshaler.unmarshal(in, v.Elem()); err != nil {
+ return err
+ }
+
+ // Re-position head.
+ in.head = oldHead
+
+ return nil
+}
+
+type mArray struct {
+ Marshaler
+ size int
+}
+
+func (m mArray) getSize() int {
+ return m.size * m.Marshaler.getSize()
+}
+
+func (m mArray) marshal(v reflect.Value, out *encoder) error {
+ for i, len := 0, v.Len(); i < len; i++ {
+ if err := m.Marshaler.marshal(v.Index(i), out); err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+func (m mArray) unmarshal(in *decoder, v reflect.Value) error {
+ for i, len := 0, v.Len(); i < len; i++ {
+ if err := m.Marshaler.unmarshal(in, v.Index(i)); err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+type mVector struct {
+ Marshaler
+ maxSize int
+ sliceTyp reflect.Type
+ isVectorUint8 bool
+}
+
+func (m mVector) getSize() int {
+ return 16
+}
+
+func (m mVector) marshal(v reflect.Value, out *encoder) error {
+ // Bounds check.
+ vLen := v.Len()
+ if m.maxSize < vLen {
+ return newExpectError(ErrVectorTooLong, m.maxSize, vLen)
+ }
+
+ // Vector header.
+ out.writeUint(uint64(vLen), 8)
+ out.writeUint(allocPresent, 8)
+
+ // Early exit if the vector is empty.
+ if vLen == 0 {
+ return nil
+ }
+
+ // Encode in the out-of-line object.
+ oldHead := out.head
+ out.head = out.newObject(vLen * m.Marshaler.getSize())
+
+ // Marshal elements.
+ if m.isVectorUint8 {
+ copy(out.buffer[out.head:], v.Bytes())
+ } else {
+ for i := 0; i < vLen; i++ {
+ if err := m.Marshaler.marshal(v.Index(i), out); err != nil {
+ return err
+ }
+ }
+ }
+
+ // Re-position head.
+ out.head = oldHead
+
+ return nil
+}
+
+func (m mVector) unmarshal(in *decoder, v reflect.Value) error {
+ size, err := in.readUint(8)
+ if err != nil {
+ return err
+ }
+ ptr, err := in.readUint(8)
+ if err != nil {
+ return err
+ }
+ switch ptr {
+ case noAlloc:
+ return newValueError(ErrUnexpectedNullRef, v)
+ case allocPresent:
+ return m.unmarshalWithUncheckedSize(in, v, int(size))
+ default:
+ return newValueError(ErrBadRefEncoding, v)
+ }
+}
+
+func (m mVector) unmarshalWithUncheckedSize(in *decoder, v reflect.Value, size int) error {
+ if size < 0 || m.maxSize < size {
+ return newExpectError(ErrVectorTooLong, m.maxSize, size)
+ }
+
+ // Unmarshal in the out-of-line object.
+ oldHead := in.head
+ in.head = in.nextObject
+ elemSize := m.Marshaler.getSize()
+ in.nextObject += align(size*elemSize, 8)
+
+ // Unmarshal elements.
+ if m.isVectorUint8 {
+ data := make([]uint8, size, size)
+ copy(data, in.buffer[in.head:])
+ v.Set(reflect.ValueOf(data))
+ } else {
+ v.Set(reflect.MakeSlice(m.sliceTyp, size, size))
+ for i := 0; i < size; i++ {
+ if err := m.Marshaler.unmarshal(in, v.Index(i)); err != nil {
+ return err
+ }
+ }
+ }
+
+ // Re-position head.
+ in.head = oldHead
+
+ return nil
+}
+
+type mOptVector mVector
+
+func (m mOptVector) getSize() int {
+ return 16
+}
+
+func (m mOptVector) marshal(v reflect.Value, out *encoder) error {
+ if v.IsNil() {
+ out.writeUint(0, 8)
+ out.writeUint(noAlloc, 8)
+ return nil
+ }
+
+ return mVector(m).marshal(v.Elem(), out)
+}
+
+func (m mOptVector) unmarshal(in *decoder, v reflect.Value) error {
+ size, err := in.readUint(8)
+ if err != nil {
+ return err
+ }
+ ptr, err := in.readUint(8)
+ if err != nil {
+ return err
+ }
+ switch ptr {
+ case noAlloc:
+ v.Set(reflect.Zero(reflect.PtrTo(m.sliceTyp)))
+ return nil
+ case allocPresent:
+ v.Set(reflect.New(m.sliceTyp))
+ return mVector(m).unmarshalWithUncheckedSize(in, v.Elem(), int(size))
+ default:
+ return newValueError(ErrBadRefEncoding, v)
+ }
+}
+
+type mBool struct{}
+
+func (m mBool) getSize() int {
+ return 1
+}
+
+func (m mBool) marshal(v reflect.Value, out *encoder) error {
+ if v.Bool() {
+ out.writeUint(1, 1)
+ } else {
+ out.writeUint(0, 1)
+ }
+ return nil
+}
+
+func (m mBool) unmarshal(in *decoder, v reflect.Value) error {
+ b, err := in.readUint(1)
+ if err != nil {
+ return err
+ }
+ switch b {
+ case 0, 1:
+ v.SetBool(b == 1)
+ return nil
+ default:
+ return newValueError(ErrInvalidBoolValue, b)
+ }
+}
+
+// int is size (1 for int8, 2 for int16, etc.)
+type mInt int
+
+func (m mInt) getSize() int {
+ return int(m)
+}
+
+func (m mInt) marshal(v reflect.Value, out *encoder) error {
+ size := int(m)
+ out.writeUint(uint64(v.Int()), size)
+ return nil
+}
+
+func (m mInt) unmarshal(in *decoder, v reflect.Value) error {
+ size := int(m)
+ val, err := in.readUint(size)
+ if err != nil {
+ return err
+ }
+ v.SetInt(int64(val))
+ return nil
+}
+
+// uint is size (1 for uint8, 2 f or uint16, etc.)
+type mUint int
+
+func (m mUint) getSize() int {
+ return int(m)
+}
+
+func (m mUint) marshal(v reflect.Value, out *encoder) error {
+ size := int(m)
+ out.writeUint(v.Uint(), size)
+ return nil
+}
+
+func (m mUint) unmarshal(in *decoder, v reflect.Value) error {
+ size := int(m)
+ val, err := in.readUint(size)
+ if err != nil {
+ return err
+ }
+ v.SetUint(val)
+ return nil
+}
+
+type mFloat32 struct{}
+
+func (m mFloat32) getSize() int {
+ return 4
+}
+
+func (m mFloat32) marshal(v reflect.Value, out *encoder) error {
+ out.writeUint(uint64(math.Float32bits(float32(v.Float()))), 4)
+ return nil
+}
+
+func (m mFloat32) unmarshal(in *decoder, v reflect.Value) error {
+ val, err := in.readUint(4)
+ if err != nil {
+ return err
+ }
+ v.SetFloat(float64(math.Float32frombits(uint32(val))))
+ return nil
+}
+
+type mFloat64 struct{}
+
+func (m mFloat64) getSize() int {
+ return 8
+}
+
+func (m mFloat64) marshal(v reflect.Value, out *encoder) error {
+ out.writeUint(math.Float64bits(v.Float()), 8)
+ return nil
+}
+
+func (m mFloat64) unmarshal(in *decoder, v reflect.Value) error {
+ val, err := in.readUint(8)
+ if err != nil {
+ return err
+ }
+ v.SetFloat(math.Float64frombits(val))
+ return nil
+}
+
+type mString int
+
+func (m mString) getSize() int {
+ return 16
+}
+
+func (m mString) marshal(v reflect.Value, out *encoder) error {
+ var (
+ maxSize = int(m)
+ s = v.String()
+ length = len(s)
+ )
+ if maxSize < length {
+ return newExpectError(ErrStringTooLong, maxSize, length)
+ }
+
+ // length, allocPresent
+ out.writeUint(uint64(length), 8)
+ out.writeUint(allocPresent, 8)
+
+ // Create a new out-of-line object and write bytes of the string.
+ head := out.newObject(length)
+ copy(out.buffer[head:], s)
+
+ return nil
+}
+
+func (m mString) unmarshal(in *decoder, v reflect.Value) error {
+ size, err := in.readUint(8)
+ if err != nil {
+ return err
+ }
+ ptr, err := in.readUint(8)
+ if err != nil {
+ return err
+ }
+ switch ptr {
+ case noAlloc:
+ return newValueError(ErrUnexpectedNullRef, "string")
+ case allocPresent:
+ return m.unmarshalWithUncheckedSize(in, v, int(size))
+ default:
+ return newValueError(ErrBadRefEncoding, "string")
+ }
+}
+
+func (m mString) unmarshalWithUncheckedSize(in *decoder, v reflect.Value, size int) error {
+ if maxSize := int(m); size < 0 || maxSize < size {
+ return newExpectError(ErrStringTooLong, maxSize, size)
+ }
+ start, end := in.nextObject, in.nextObject+size
+ if len(in.buffer) < end {
+ return newValueError(ErrMessageTooSmall, v)
+ }
+ s := string(in.buffer[start:end])
+ v.SetString(s)
+ in.nextObject += align(size, 8)
+ return nil
+}
+
+type mOptString uint64
+
+func (m mOptString) getSize() int {
+ return 16
+}
+
+func (m mOptString) marshal(v reflect.Value, out *encoder) error {
+ if v.IsNil() {
+ out.writeUint(0, 8)
+ out.writeUint(noAlloc, 8)
+ return nil
+ }
+
+ return mString(m).marshal(v.Elem(), out)
+}
+
+var (
+ nilString = reflect.Zero(reflect.PtrTo(reflect.TypeOf("")))
+ typString = reflect.TypeOf("")
+)
+
+func (m mOptString) unmarshal(in *decoder, v reflect.Value) error {
+ size, err := in.readUint(8)
+ if err != nil {
+ return err
+ }
+ ptr, err := in.readUint(8)
+ if err != nil {
+ return err
+ }
+ switch ptr {
+ case noAlloc:
+ v.Set(nilString)
+ return nil
+ case allocPresent:
+ v.Set(reflect.New(typString))
+ return mString(m).unmarshalWithUncheckedSize(in, v.Elem(), int(size))
+ default:
+ return newValueError(ErrBadRefEncoding, v)
+ }
+}
+
+type mHandle bool
+
+func (m mHandle) getSize() int {
+ return 4
+}
+
+func (m mHandle) isOpt() bool {
+ return bool(m)
+}
+
+func (m mHandle) marshal(v reflect.Value, out *encoder) error {
+ // The underlying type of all the handles is a uint32, so we're
+ // safe calling Uint(). This will panic if that is no longer true.
+ raw := zx.Handle(v.Uint())
+ if raw == zx.HandleInvalid {
+ if !m.isOpt() {
+ return ErrUnexpectedNullHandle
+ }
+ out.writeUint(uint64(noHandle), 4)
+ return nil
+ }
+ out.handles = append(out.handles, raw)
+ out.writeUint(uint64(handlePresent), 4)
+ return nil
+}
+
+func (m mHandle) unmarshal(in *decoder, v reflect.Value) error {
+ h, err := in.readUint(4)
+ if err != nil {
+ return err
+ }
+ switch uint32(h) {
+ case noHandle:
+ if !m.isOpt() {
+ return ErrUnexpectedNullHandle
+ }
+ v.SetUint(uint64(zx.HandleInvalid))
+ return nil
+ case handlePresent:
+ if len(in.handles) == 0 {
+ return ErrNotEnoughHandles
+ }
+ v.SetUint(uint64(in.handles[0]))
+ in.handles = in.handles[1:]
+ return nil
+ default:
+ return newValueError(ErrBadHandleEncoding, h)
+ }
+}
+
+// An interface is represented by a Proxy, whose first field is
+// a zx.Channel, and we can just marshal that. Same goes for an
+// interface request, which is just an InterfaceRequest whose
+// first field is a zx.Channel.
+type mInterface mHandle
+
+func (m mInterface) getSize() int {
+ return mHandle(m).getSize()
+}
+
+func (m mInterface) marshal(v reflect.Value, out *encoder) error {
+ return mHandle(m).marshal(v.Field(0), out)
+}
+
+func (m mInterface) unmarshal(in *decoder, v reflect.Value) error {
+ return mHandle(m).unmarshal(in, v.Field(0))
+}
diff --git a/src/syscall/zx/fidl/errors.go b/src/syscall/zx/fidl/errors.go
new file mode 100644
index 0000000..0015adb
--- /dev/null
+++ b/src/syscall/zx/fidl/errors.go
@@ -0,0 +1,201 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build fuchsia
+
+package fidl
+
+import (
+ "reflect"
+ "strconv"
+)
+
+// ValidationError represents an error produced in validating a FIDL structure.
+type ValidationError interface {
+ error
+
+ // Code returns the underlying ErrorCode value, which all ValidationErrors
+ // must have.
+ Code() ErrorCode
+}
+
+// Assert that valueError and expectError both implement the ValidationError
+// interface.
+var _ = []ValidationError{
+ valueError{},
+ expectError{},
+}
+
+// ErrorCode represents a set of machine-readable error codes each ValidationError
+// has.
+type ErrorCode uint32
+
+const (
+ Invalid ErrorCode = iota
+ ErrUnknownOrdinal
+ ErrInvalidInlineType
+ ErrInvalidPointerType
+ ErrVectorTooLong
+ ErrStringTooLong
+ ErrUnexpectedOrdinal
+ ErrUnexpectedNullHandle
+ ErrUnexpectedNullRef
+ ErrInvalidBoolValue
+ ErrNotEnoughHandles
+ ErrBadHandleEncoding
+ ErrBadRefEncoding
+ ErrMessageTooSmall
+ ErrStructIsNotPayload
+ ErrInvalidUnionTag
+ ErrPayloadTooSmall
+ ErrInvalidEmptyStruct
+ ErrUnexpectedNumBytes
+ ErrUnexpectedNumHandles
+)
+
+var errorCodeNames = []string{
+ Invalid: "Invalid",
+ ErrUnknownOrdinal: "ErrUnknownOrdinal",
+ ErrInvalidInlineType: "ErrInvalidInlineType",
+ ErrInvalidPointerType: "ErrInvalidPointerType",
+ ErrVectorTooLong: "ErrVectorTooLong",
+ ErrStringTooLong: "ErrStringTooLong",
+ ErrUnexpectedOrdinal: "ErrUnexpectedOrdinal",
+ ErrUnexpectedNullHandle: "ErrUnexpectedNullHandle",
+ ErrUnexpectedNullRef: "ErrUnexpectedNullRef",
+ ErrInvalidBoolValue: "ErrInvalidBoolValue",
+ ErrNotEnoughHandles: "ErrNotEnoughHandles",
+ ErrBadHandleEncoding: "ErrBadHandleEncoding",
+ ErrBadRefEncoding: "ErrBadRefEncoding",
+ ErrMessageTooSmall: "ErrMessageTooSmall",
+ ErrStructIsNotPayload: "ErrStructIsNotPayload",
+ ErrInvalidUnionTag: "ErrInvalidUnionTag",
+ ErrPayloadTooSmall: "ErrPayloadTooSmall",
+ ErrInvalidEmptyStruct: "ErrInvalidEmptyStruct",
+ ErrUnexpectedNumBytes: "ErrUnexpectedNumBytes",
+ ErrUnexpectedNumHandles: "ErrUnexpectedNumHandles",
+}
+
+func (c ErrorCode) String() string {
+ if len(errorCodeNames) < int(c) {
+ return strconv.Itoa(int(c))
+ }
+ return errorCodeNames[int(c)]
+}
+
+// Error implements error for ErrorCode
+func (e ErrorCode) Error() string {
+ switch e {
+ case ErrUnknownOrdinal:
+ return "unknown ordinal"
+ case ErrInvalidInlineType:
+ return "invalid inline type"
+ case ErrInvalidPointerType:
+ return "invalid pointer type"
+ case ErrVectorTooLong:
+ return "vector exceeds maximum size"
+ case ErrStringTooLong:
+ return "string exceeds maximum size"
+ case ErrUnexpectedOrdinal:
+ return "unexpected ordinal"
+ case ErrUnexpectedNullHandle:
+ return "unexpected null handle"
+ case ErrUnexpectedNullRef:
+ return "unexpected null reference"
+ case ErrInvalidBoolValue:
+ return "unexpected boolean value"
+ case ErrNotEnoughHandles:
+ return "not enough handles"
+ case ErrBadHandleEncoding:
+ return "bad encoding for handle"
+ case ErrBadRefEncoding:
+ return "bad encoding for ref"
+ case ErrMessageTooSmall:
+ return "message too small to have FIDL header"
+ case ErrStructIsNotPayload:
+ return "golang struct type must implement Payload"
+ case ErrInvalidUnionTag:
+ return "union tag out of bounds"
+ case ErrPayloadTooSmall:
+ return "payload too small"
+ case ErrInvalidEmptyStruct:
+ return "invalid empty struct"
+ case ErrUnexpectedNumBytes:
+ return "unexpected num bytes"
+ case ErrUnexpectedNumHandles:
+ return "unexpected num handles"
+ default:
+ return e.String()
+ }
+}
+
+// Code implements the ValidationError interface.
+func (e ErrorCode) Code() ErrorCode {
+ return e
+}
+
+// stringer is an interface for types for which a string representation
+// may be derived.
+type stringer interface {
+ String() string
+}
+
+// toString generates the string representation for a limited set of types.
+func toString(value interface{}) string {
+ if e, ok := value.(error); ok {
+ return e.Error()
+ }
+ if s, ok := value.(stringer); ok {
+ return s.String()
+ }
+ t := reflect.TypeOf(value)
+ switch t.Kind() {
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+ return strconv.FormatInt(reflect.ValueOf(value).Int(), 10)
+ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
+ return strconv.FormatUint(reflect.ValueOf(value).Uint(), 10)
+ case reflect.String:
+ return value.(string)
+ default:
+ return "##BADVALUE##"
+ }
+}
+
+// valueError represents an error that refers to a single value.
+type valueError struct {
+ ErrorCode
+ value interface{}
+}
+
+func newValueError(code ErrorCode, value interface{}) valueError {
+ return valueError{
+ ErrorCode: code,
+ value: value,
+ }
+}
+
+func (e valueError) Error() string {
+ return e.ErrorCode.Error() + ": " + toString(e.value)
+}
+
+// expectError represents an error that refers to the expectation of a
+// certain value, and displays a comparison between the actual value and
+// the expected value.
+type expectError struct {
+ ErrorCode
+ expect interface{}
+ actual interface{}
+}
+
+func newExpectError(code ErrorCode, expect, actual interface{}) expectError {
+ return expectError{
+ ErrorCode: code,
+ expect: expect,
+ actual: actual,
+ }
+}
+
+func (e expectError) Error() string {
+ return e.ErrorCode.Error() + ": expected " + toString(e.expect) + ", got " + toString(e.actual)
+}
diff --git a/src/syscall/zx/fidl/export_test.go b/src/syscall/zx/fidl/export_test.go
new file mode 100644
index 0000000..9d9db7c
--- /dev/null
+++ b/src/syscall/zx/fidl/export_test.go
@@ -0,0 +1,9 @@
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build fuchsia
+
+package fidl
+
+var WithRetry = withRetry
diff --git a/src/syscall/zx/fidl/fidl_test/bindings_test.go b/src/syscall/zx/fidl/fidl_test/bindings_test.go
new file mode 100644
index 0000000..40bf0f4
--- /dev/null
+++ b/src/syscall/zx/fidl/fidl_test/bindings_test.go
@@ -0,0 +1,129 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build fuchsia
+
+package fidl_test
+
+import (
+ "flag"
+ "fmt"
+ "syscall/zx"
+ "testing"
+ "time"
+
+ . "syscall/zx/fidl"
+ . "syscall/zx/fidl/bindingstest"
+)
+
+func init() { flag.CommandLine.Set("test.v", "true") }
+
+type Test1Impl struct{}
+
+func (t *Test1Impl) Echo(s *string) (*string, error) {
+ return s, nil
+}
+
+func TestEmptyWriteErrors(t *testing.T) {
+ t.Parallel()
+ chErr := make(chan error)
+ errFunc := func(err error) { chErr <- err }
+ chPanic := make(chan error)
+ go func() {
+ defer func() {
+ if r := recover(); r != nil {
+ chPanic <- fmt.Errorf("write panicked: %v", r)
+ }
+ }()
+
+ Serve()
+ }()
+
+ ch, sh, err := zx.NewChannel(0)
+ if err != nil {
+ t.Fatalf("could not create channel: %v", err)
+ }
+ if err := ch.Write([]byte{}, []zx.Handle{}, 0); err != nil {
+ t.Fatalf("could not write to channel: %v", err)
+ }
+
+ server := Test1Service{}
+ if _, err := server.Add(&Test1Impl{}, sh, errFunc); err != nil {
+ t.Fatalf("coudl not add to server: %v", err)
+ }
+
+ select {
+ case <-chErr:
+ // Everything went well.
+ case err := <-chPanic:
+ t.Fatal(err)
+ case <-time.After(time.Second * 5):
+ t.Fatal("test timed out")
+ }
+
+ ch.Close()
+ server.Close()
+}
+
+func TestEcho(t *testing.T) {
+ t.Parallel()
+
+ ch, sh, err := zx.NewChannel(0)
+ if err != nil {
+ t.Fatal(err)
+ }
+ client := Test1Interface(ChannelProxy{Channel: ch})
+ server := Test1Service{}
+ clientKey, err := server.Add(&Test1Impl{}, sh, nil)
+ if err != nil {
+ t.Fatal(err)
+ }
+ go Serve()
+
+ t.Run("Basic", func(t *testing.T) {
+ str := "Hello World!"
+ r, err := client.Echo(&str)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if r == nil {
+ t.Fatal("unexpected nil result")
+ }
+ if *r != str {
+ t.Fatalf("expected %s, got %s", str, *r)
+ }
+ })
+
+ t.Run("Event", func(t *testing.T) {
+ str := "Surprise!"
+ done := make(chan struct{})
+ // Spin up goroutine with waiting client.
+ go func() {
+ s, err := client.ExpectSurprise()
+ if err != nil {
+ t.Fatal(err)
+ }
+ if s != str {
+ t.Fatalf("expected %s, got %s", str, s)
+ }
+ done <- struct{}{}
+ }()
+ // Spin up server goroutine which makes the call.
+ go func() {
+ pxy, ok := server.EventProxyFor(clientKey)
+ if !ok {
+ t.Fatalf("could not create proxy for key %d", clientKey)
+ }
+ if err := pxy.Surprise(str); err != nil {
+ t.Fatal(err)
+ }
+ }()
+ select {
+ case <-done:
+ return
+ case <-time.After(5 * time.Second):
+ t.Fatalf("test timed out")
+ }
+ })
+}
diff --git a/src/syscall/zx/fidl/fidl_test/conformance_test.go b/src/syscall/zx/fidl/fidl_test/conformance_test.go
new file mode 100644
index 0000000..47c5159
--- /dev/null
+++ b/src/syscall/zx/fidl/fidl_test/conformance_test.go
@@ -0,0 +1,514 @@
+// Copyright 2019 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// Code generated by tools/fidl/gidl-conformance-suite/regen.sh; DO NOT EDIT.
+
+// +build fuchsia
+
+//
+package fidl_test
+
+import (
+ "testing"
+
+ "syscall/zx/fidl/conformance"
+)
+
+func TestAllSuccessCases(t *testing.T) {
+ {
+ var v1 conformance.EmptyStruct
+
+ successCase{
+ name: "EmptyStruct",
+ input: &v1,
+ bytes: []byte{
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ },
+ }.check(t)
+ }
+
+ {
+ var v1 conformance.EmptyStructSandwich
+ var v2 conformance.EmptyStruct
+ v1.Es = v2
+ v3 := "after"
+ v1.After = v3
+ v4 := "before"
+ v1.Before = v4
+
+ successCase{
+ name: "EmptyStructSandwich",
+ input: &v1,
+ bytes: []byte{
+ 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x00, 0x00,
+ 0x61, 0x66, 0x74, 0x65, 0x72, 0x00, 0x00, 0x00,
+ },
+ }.check(t)
+ }
+
+ {
+ var v1 conformance.Uint8Uint16Uint32Uint64
+ var v2 uint64 = 579005069656919567
+ v1.F4 = v2
+ var v3 uint8 = 1
+ v1.F1 = v3
+ var v4 uint16 = 515
+ v1.F2 = v4
+ var v5 uint32 = 67438087
+ v1.F3 = v5
+
+ successCase{
+ name: "Uint8Uint16Uint32Uint64",
+ input: &v1,
+ bytes: []byte{
+ 0x01, 0x00, 0x03, 0x02, 0x07, 0x06, 0x05, 0x04,
+ 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08,
+ },
+ }.check(t)
+ }
+
+ {
+ var v1 conformance.Uint64Uint32Uint16Uint8
+ var v2 uint64 = 579005069656919567
+ v1.F1 = v2
+ var v3 uint32 = 67438087
+ v1.F2 = v3
+ var v4 uint16 = 515
+ v1.F3 = v4
+ var v5 uint8 = 1
+ v1.F4 = v5
+
+ successCase{
+ name: "Uint64Uint32Uint16Uint8",
+ input: &v1,
+ bytes: []byte{
+ 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08,
+ 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00,
+ },
+ }.check(t)
+ }
+
+ {
+ var v1 conformance.StructOfSimpleTable
+ var v2 conformance.SimpleTable
+ v1.Table = v2
+
+ successCase{
+ name: "SimpleTableEmpty",
+ input: &v1,
+ bytes: []byte{
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ },
+ }.check(t)
+ }
+
+ {
+ var v1 conformance.StructOfSimpleTable
+ var v2 conformance.SimpleTable
+ var v3 int64 = 42
+ v2.SetX(v3)
+ var v4 int64 = 67
+ v2.SetY(v4)
+ v1.Table = v2
+
+ successCase{
+ name: "SimpleTableXAndY",
+ input: &v1,
+ bytes: []byte{
+ 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0x2a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ },
+ }.check(t)
+ }
+
+ {
+ var v1 conformance.StructOfSimpleTable
+ var v2 conformance.SimpleTable
+ var v3 int64 = 67
+ v2.SetY(v3)
+ v1.Table = v2
+
+ successCase{
+ name: "SimpleTableJustY",
+ input: &v1,
+ bytes: []byte{
+ 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ },
+ }.check(t)
+ }
+
+ {
+ var v1 conformance.StructOfTableWithStringAndVector
+ var v2 conformance.TableWithStringAndVector
+ v3 := "hello"
+ v2.SetFoo(v3)
+ var v4 int32 = 27
+ v2.SetBar(v4)
+ v1.Table = v2
+
+ successCase{
+ name: "TableWithStringAndVectorNoVectorContent",
+ input: &v1,
+ bytes: []byte{
+ 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x00, 0x00, 0x00,
+ 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ },
+ }.check(t)
+ }
+
+ {
+ var v1 conformance.SimpleTableThenUint64
+ var v2 conformance.SimpleTable
+ var v3 int64 = 42
+ v2.SetX(v3)
+ var v4 int64 = 67
+ v2.SetY(v4)
+ v1.Table = v2
+ var v5 uint64 = 16045690984833335023
+ v1.Number = v5
+
+ successCase{
+ name: "SimpleTableThenUint64",
+ input: &v1,
+ bytes: []byte{
+ 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xef, 0xbe, 0xad, 0xde, 0xef, 0xbe, 0xad, 0xde,
+ 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0x2a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ },
+ }.check(t)
+ }
+
+ {
+ var v1 conformance.TestInlineXUnionInStruct
+ v2 := "before"
+ v1.Before = v2
+ var v3 conformance.SampleXUnion
+ var v4 uint32 = 3735928559
+ v3.SetU(v4)
+ v1.Xu = v3
+ v5 := "after"
+ v1.After = v5
+
+ successCase{
+ name: "InlineXUnionInStruct",
+ input: &v1,
+ bytes: []byte{
+ 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xb2, 0x56, 0x9c, 0x38, 0x00, 0x00, 0x00, 0x00,
+ 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x00, 0x00,
+ 0xef, 0xbe, 0xad, 0xde, 0x00, 0x00, 0x00, 0x00,
+ 0x61, 0x66, 0x74, 0x65, 0x72, 0x00, 0x00, 0x00,
+ },
+ }.check(t)
+ }
+
+ {
+ var v1 conformance.TestOptionalXUnionInStruct
+ v2 := "before"
+ v1.Before = v2
+ v3 := "after"
+ v1.After = v3
+
+ successCase{
+ name: "OptionalXUnionInStructAbsent",
+ input: &v1,
+ bytes: []byte{
+ 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x00, 0x00,
+ 0x61, 0x66, 0x74, 0x65, 0x72, 0x00, 0x00, 0x00,
+ },
+ }.check(t)
+ }
+
+ {
+ var v1 conformance.TestOptionalXUnionInStruct
+ v2 := "before"
+ v1.Before = v2
+ var v3 conformance.SampleXUnion
+ var v4 uint32 = 3735928559
+ v3.SetU(v4)
+ v1.Xu = &v3
+ v5 := "after"
+ v1.After = v5
+
+ successCase{
+ name: "OptionalXUnionInStructPresent",
+ input: &v1,
+ bytes: []byte{
+ 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xb2, 0x56, 0x9c, 0x38, 0x00, 0x00, 0x00, 0x00,
+ 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x00, 0x00,
+ 0xef, 0xbe, 0xad, 0xde, 0x00, 0x00, 0x00, 0x00,
+ 0x61, 0x66, 0x74, 0x65, 0x72, 0x00, 0x00, 0x00,
+ },
+ }.check(t)
+ }
+
+ {
+ var v1 conformance.TestXUnionInTable
+ var v2 conformance.XUnionInTable
+ v3 := "before"
+ v2.SetBefore(v3)
+ v4 := "after"
+ v2.SetAfter(v4)
+ v1.Value = v2
+
+ successCase{
+ name: "XUnionInTableXUnionAbsent",
+ input: &v1,
+ bytes: []byte{
+ 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x00, 0x00,
+ 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0x61, 0x66, 0x74, 0x65, 0x72, 0x00, 0x00, 0x00,
+ },
+ }.check(t)
+ }
+
+ {
+ var v1 conformance.TestXUnionInTable
+ var v2 conformance.XUnionInTable
+ var v3 conformance.SampleXUnion
+ var v4 uint32 = 3735928559
+ v3.SetU(v4)
+ v2.SetXu(v3)
+ v5 := "after"
+ v2.SetAfter(v5)
+ v6 := "before"
+ v2.SetBefore(v6)
+ v1.Value = v2
+
+ successCase{
+ name: "XUnionInTableXUnionPresent",
+ input: &v1,
+ bytes: []byte{
+ 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x00, 0x00,
+ 0xb2, 0x56, 0x9c, 0x38, 0x00, 0x00, 0x00, 0x00,
+ 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xef, 0xbe, 0xad, 0xde, 0x00, 0x00, 0x00, 0x00,
+ 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0x61, 0x66, 0x74, 0x65, 0x72, 0x00, 0x00, 0x00,
+ },
+ }.check(t)
+ }
+
+ {
+ var v1 conformance.TestAddEthernetDeviceRequest
+ v2 := "@/dev/sys/pci/00:03.0/e1000/ethernet"
+ v1.TopologicalPath = v2
+ var v3 conformance.InterfaceConfig
+ v4 := "ethp0003"
+ v3.Name = v4
+ var v5 conformance.IpAddressConfig
+ v6 := true
+ v5.SetDhcp(v6)
+ v3.IpAddressConfig = v5
+ v1.Config = v3
+ var v7 uint32 = 4294967295
+ v1.ThisShouldBeAHandle = v7
+
+ successCase{
+ name: "AddEthernetDeviceRequest",
+ input: &v1,
+ bytes: []byte{
+ 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
+ 0x40, 0x2f, 0x64, 0x65, 0x76, 0x2f, 0x73, 0x79,
+ 0x73, 0x2f, 0x70, 0x63, 0x69, 0x2f, 0x30, 0x30,
+ 0x3a, 0x30, 0x33, 0x2e, 0x30, 0x2f, 0x65, 0x31,
+ 0x30, 0x30, 0x30, 0x2f, 0x65, 0x74, 0x68, 0x65,
+ 0x72, 0x6e, 0x65, 0x74, 0x00, 0x00, 0x00, 0x00,
+ 0x65, 0x74, 0x68, 0x70, 0x30, 0x30, 0x30, 0x33,
+ },
+ }.check(t)
+ }
+
+ {
+ var v1 conformance.FileGetAttrResponse
+ var v2 int32 = 2125315759
+ v1.S = v2
+ var v3 conformance.NodeAttributes
+ var v4 uint64 = 72038755451251353
+ v3.ModificationTime = v4
+ var v5 uint32 = 2518909348
+ v3.Mode = v5
+ var v6 uint64 = 1
+ v3.Id = v6
+ var v7 uint64 = 231
+ v3.ContentSize = v7
+ var v8 uint64 = 231
+ v3.StorageSize = v8
+ var v9 uint64 = 1
+ v3.LinkCount = v9
+ var v10 uint64 = 9833440827789222417
+ v3.CreationTime = v10
+ v1.Attributes = v3
+
+ successCase{
+ name: "FileGetAttrResponse",
+ input: &v1,
+ bytes: []byte{
+ 0xaf, 0xbe, 0xad, 0x7e, 0x00, 0x00, 0x00, 0x00,
+ 0xa4, 0x81, 0x23, 0x96, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xe7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xe7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88,
+ 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x00,
+ },
+ }.check(t)
+ }
+
+ {
+ var v1 conformance.StructWithOptionals
+ var v2 conformance.UnionWithEmptyStruct
+ var v3 conformance.EmptyStruct
+ v2.SetS(v3)
+ v1.U = v2
+ var v4 conformance.UnionWithEmptyStruct
+ var v5 conformance.EmptyStruct
+ v4.SetS(v5)
+ v1.U2 = &v4
+ var v6 conformance.EmptyStruct
+ v1.S = v6
+ var v7 conformance.EmptyStruct
+ v1.S2 = &v7
+ var v8 conformance.TableWithEmptyStruct
+ var v9 conformance.EmptyStruct
+ v8.SetS(v9)
+ v1.T = v8
+ var v10 conformance.XUnionWithEmptyStruct
+ var v11 conformance.EmptyStruct
+ v10.SetS(v11)
+ v1.Xu = v10
+ var v12 conformance.XUnionWithEmptyStruct
+ var v13 conformance.EmptyStruct
+ v12.SetS(v13)
+ v1.Xu2 = &v12
+
+ successCase{
+ name: "Optionals",
+ input: &v1,
+ bytes: []byte{
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xfe, 0xe0, 0x99, 0x74, 0x00, 0x00, 0x00, 0x00,
+ 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xfe, 0xe0, 0x99, 0x74, 0x00, 0x00, 0x00, 0x00,
+ 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ },
+ }.check(t)
+ }
+}
diff --git a/src/syscall/zx/fidl/fidl_test/encoding_new_test.go b/src/syscall/zx/fidl/fidl_test/encoding_new_test.go
new file mode 100644
index 0000000..01c4cc9
--- /dev/null
+++ b/src/syscall/zx/fidl/fidl_test/encoding_new_test.go
@@ -0,0 +1,670 @@
+// Copyright 2018 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// +build fuchsia
+
+package fidl_test
+
+import (
+ "fmt"
+ "math/rand"
+ "reflect"
+ "strings"
+ "syscall/zx"
+ "testing"
+
+ . "syscall/zx/fidl"
+ . "syscall/zx/fidl/bindingstest"
+)
+
+type example struct {
+ name string
+ input Message
+ expectSize int
+}
+
+// general provides test cases used to verify correctness, and
+// benchmark against.
+//
+// Keep these as a slice to preserve consistent ordering when running.
+func general() []example {
+ var (
+ s = "bye"
+ s256 = strings.Repeat("hello!!!", 64)
+ s8192 = strings.Repeat("hello!!!", 1024)
+
+ v1 = []int64{-1}
+ v2 = []string{"x", "hello"}
+ v3 = []int64{101010}
+
+ u1 = Union1{}
+ )
+ u1.SetB(TestSimple{X: 555})
+
+ vmo, err := zx.NewVMO(10, 0)
+ if err != nil {
+ panic(fmt.Sprintf("failed to create vmo: %v", err))
+ }
+ defer vmo.Close()
+
+ h0, h1, err := zx.NewChannel(0)
+ defer h0.Close()
+ defer h1.Close()
+ if err != nil {
+ panic(fmt.Sprintf("failed to create vmo: %v", err))
+ }
+
+ st1 := SimpleTable{}
+ st1.SetX(42)
+ st1.SetY(67)
+
+ return []example{
+ // simple (to get started)
+ {"simple", &TestSimple{X: 124}, 8},
+ {"simplebool", &TestSimpleBool{X: true}, 8},
+
+ // alignement
+ {"align1", &TestAlignment1{X: -36, Y: -10, Z: 51}, 8},
+ {"align2", &TestAlignment2{
+ A: 1212141,
+ B: 908935,
+ C: -1,
+ D: 125,
+ E: -22,
+ F: 111,
+ G: 1515,
+ H: 65535,
+ I: 1515,
+ }, 24},
+
+ // floats
+ {"float1", &TestFloat1{A: -36.0}, 8},
+ {"float2", &TestFloat2{A: -1254918271.0}, 8},
+ {"float3", &TestFloat3{A: 1241.1, B: 0.2141, C: 20, D: 0.0}, 32},
+
+ // arrays
+ {"array1", &TestArray1{A: [5]int8{1, 77, 2, 4, 89}}, 8},
+ {"array2", &TestArray2{A: -1.0, B: [1]float32{0.2}}, 16},
+ {"array3", &TestArray3{
+ A: -999,
+ B: [3]uint16{11, 12, 13},
+ C: 1021,
+ }, 24},
+ {"array4", &TestArray4{
+ A: [9]bool{true, false, false, true, false, true, true, true, true},
+ }, 16},
+
+ // strings
+ {"string1", &TestString1{A: "str", B: nil}, 40},
+ {"string1-longer256", &TestString1{A: s256, B: &s256}, 1056},
+ {"string1-longer8192", &TestString1{A: s8192, B: &s8192}, 16416},
+ {"string2", &TestString2{A: [2]string{"hello", "g"}}, 48},
+ {"string3", &TestString3{
+ A: [2]string{"boop", "g"},
+ B: [2]*string{&s, nil},
+ }, 88},
+ {"string-with-bound", &TestStringWithBound{A: "str"}, 24},
+ {"opt-string-with-bound", &TestOptStringWithBound{A: &s}, 24},
+
+ // vectors
+ {"vector1", &TestVector1{
+ A: []int8{1, 2, 3, 4},
+ B: nil,
+ C: []int32{99},
+ D: &v1,
+ }, 88},
+ {"vector2", &TestVector2{
+ A: [2][]int8{{9, -1}, {}},
+ B: [][]int8{{-111, 41}, {-1, -1, -1, -1}},
+ C: []*[]string{nil, &v2},
+ }, 200},
+
+ // structs
+ {"struct1", &TestStruct1{
+ A: TestSimple{
+ X: -9999,
+ },
+ B: &TestSimple{
+ X: 1254125,
+ },
+ }, 24},
+ {"struct2", &TestStruct2{
+ A: TestArray1{
+ A: [5]int8{1, 77, 2, 4, 5},
+ },
+ B: TestFloat1{
+ A: 2.81212,
+ },
+ C: TestVector1{
+ A: []int8{1, 2, 3, 4},
+ B: nil,
+ C: []int32{99},
+ D: &v3,
+ },
+ D: &TestString1{
+ A: "str",
+ B: nil,
+ },
+ }, 152},
+
+ // unions
+ {"union1", &TestUnion1{
+ A: u1,
+ B: nil,
+ }, 24},
+ {"union1-bis", &TestUnion1{
+ A: u1,
+ B: &u1,
+ }, 40},
+ {"union2", &TestUnion2{
+ A: []Union1{u1, u1, u1},
+ B: []*Union1{&u1, nil, nil},
+ }, 120},
+
+ // handles
+ {"handle1", &TestHandle1{
+ A: zx.Handle(22),
+ B: zx.HandleInvalid,
+ C: vmo,
+ D: zx.VMO(zx.HandleInvalid),
+ }, 16},
+ {"handle2", &TestHandle2{
+ A: []zx.Handle{zx.Handle(vmo)},
+ B: []zx.VMO{zx.VMO(zx.HandleInvalid)},
+ }, 48},
+
+ // interfaces
+ {"interface1", &TestInterface1{
+ A: Test1Interface(ChannelProxy{Channel: h0}),
+ B: Test1Interface(ChannelProxy{Channel: zx.Channel(zx.HandleInvalid)}),
+ C: Test1InterfaceRequest(InterfaceRequest{Channel: h1}),
+ D: Test1InterfaceRequest(InterfaceRequest{
+ Channel: zx.Channel(zx.HandleInvalid),
+ }),
+ }, 16},
+
+ // tables
+ {"table1", &TestSimpleTable{
+ Table: st1,
+ }, 112},
+ }
+}
+
+// Using a fixed seed for the randomizer for deterministic behavior of the
+// tests, all the while using 'random looking' data.
+var r = rand.New(rand.NewSource(524287))
+
+func randBytes(num int) []byte {
+ bytes := make([]byte, num, num)
+ if _, err := r.Read(bytes); err != nil {
+ panic(err)
+ }
+ return bytes
+}
+
+// fuchsia provides test cases from fuchsia verify correctness, and
+// benchmark against.
+//
+// Keep these as a slice to preserve consistent ordering when running.
+func fuchsia() []example {
+
+ var (
+ bytes16 = randBytes(16)
+ bytes64 = randBytes(64)
+ bytes256 = randBytes(256)
+ bytes1024 = randBytes(1024)
+ bytes4096 = randBytes(4096)
+ bytes8192 = randBytes(8192)
+ )
+
+ return []example{
+ // fuchsia.io, ReadAt response
+ {"fuchsia.io-readAt-response0", &TestFuchsiaIoReadAtResponse{
+ S: 5,
+ Data: []byte{},
+ }, 24 + 0},
+ {"fuchsia.io-readAt-response16", &TestFuchsiaIoReadAtResponse{
+ S: 5,
+ Data: bytes16,
+ }, 24 + 16},
+ {"fuchsia.io-readAt-response64", &TestFuchsiaIoReadAtResponse{
+ S: 5,
+ Data: bytes64,
+ }, 24 + 64},
+ {"fuchsia.io-readAt-response256", &TestFuchsiaIoReadAtResponse{
+ S: 5,
+ Data: bytes256,
+ }, 24 + 256},
+ {"fuchsia.io-readAt-response1024", &TestFuchsiaIoReadAtResponse{
+ S: 5,
+ Data: bytes1024,
+ }, 24 + 1024},
+ {"fuchsia.io-readAt-response4096", &TestFuchsiaIoReadAtResponse{
+ S: 5,
+ Data: bytes4096,
+ }, 24 + 4096},
+ {"fuchsia.io-readAt-response8192", &TestFuchsiaIoReadAtResponse{
+ S: 5,
+ Data: bytes8192,
+ }, 24 + 8192},
+
+ // fuchsia.io, WriteAt request
+ {"fuchsia.io-writeAt-request0", &TestFuchsiaIoWriteAtRequest{
+ Data: []byte{},
+ Offset: 5,
+ }, 24 + 0},
+ {"fuchsia.io-writeAt-request16", &TestFuchsiaIoWriteAtRequest{
+ Data: bytes16,
+ Offset: 5,
+ }, 24 + 16},
+ {"fuchsia.io-writeAt-request64", &TestFuchsiaIoWriteAtRequest{
+ Data: bytes64,
+ Offset: 5,
+ }, 24 + 64},
+ {"fuchsia.io-writeAt-request256", &TestFuchsiaIoWriteAtRequest{
+ Data: bytes256,
+ Offset: 5,
+ }, 24 + 256},
+ {"fuchsia.io-writeAt-request1024", &TestFuchsiaIoWriteAtRequest{
+ Data: bytes1024,
+ Offset: 5,
+ }, 24 + 1024},
+ {"fuchsia.io-writeAt-request4096", &TestFuchsiaIoWriteAtRequest{
+ Data: bytes4096,
+ Offset: 5,
+ }, 24 + 4096},
+ {"fuchsia.io-writeAt-request8192", &TestFuchsiaIoWriteAtRequest{
+ Data: bytes8192,
+ Offset: 5,
+ }, 24 + 8192},
+ }
+}
+
+// TODO(FIDL-508): Convert all these tests to be conformance tests, using GIDL.
+func check(t *testing.T, input Message, expectSize int) {
+ t.Helper()
+ defer func() {
+ if r := recover(); r != nil {
+ // When running tests on device, this bubbles up the error
+ // on the console launching the tests, rather than having
+ // to look at the device's kernel logs.
+ t.Fatalf("panic: %s", r)
+ panic(r)
+ }
+ }()
+ var respb [zx.ChannelMaxMessageBytes]byte
+ var resph [zx.ChannelMaxMessageHandles]zx.Handle
+ nb, nh, err := MarshalNew(input, respb[:], resph[:])
+ if err != nil {
+ t.Fatalf("marshal: failed: %s", err)
+ }
+ if nb != expectSize {
+ t.Fatalf("marshal: expected size %d but got %d: %v", expectSize, nb, respb[:nb])
+ }
+ output := makeDefault(input)
+ nbActual, nhActual, err := UnmarshalNew(respb[:nb], resph[:nh], output)
+ if err != nil {
+ t.Fatalf("unmarshal: failed: %s", err)
+ }
+ if !reflect.DeepEqual(input, output) {
+ t.Fatalf("unmarshal: expected: %v, got: %v", input, output)
+ }
+ if nb != nbActual {
+ t.Fatalf("unmarshal: num bytes, expected: %d, got: %d", nb, nbActual)
+ }
+ if nh != nhActual {
+ t.Fatalf("unmarshal: num handles, expected: %d, got: %d", nh, nhActual)
+ }
+}
+
+func TestCorrectness(t *testing.T) {
+ for _, ex := range general() {
+ t.Run(ex.name, func(t *testing.T) {
+ check(t, ex.input, ex.expectSize)
+ })
+ }
+ for _, ex := range fuchsia() {
+ t.Run(ex.name, func(t *testing.T) {
+ check(t, ex.input, ex.expectSize)
+ })
+ }
+}
+
+type errorCaseUnmarshal struct {
+ name string
+ message Message
+ input []byte
+ errorCode ErrorCode
+}
+
+var baseErrorCasesUnmarshal = []errorCaseUnmarshal{
+ {"empty-array-TestSimple", &TestSimple{}, []byte{}, ErrPayloadTooSmall},
+ {"nil-array-TestSimple", &TestSimple{}, nil, ErrPayloadTooSmall},
+ {"small-array-TestSimple", &TestSimple{}, []byte{0x00, 0x0}, ErrPayloadTooSmall},
+ {"empty-array-TestSimpleBool", &TestSimpleBool{}, []byte{}, ErrPayloadTooSmall},
+ {"nil-array-TestSimpleBool", &TestSimpleBool{}, nil, ErrPayloadTooSmall},
+ {"empty-array-TestAlignment1", &TestAlignment1{}, []byte{}, ErrPayloadTooSmall},
+ {"nil-array-TestAlignment1", &TestAlignment1{}, nil, ErrPayloadTooSmall},
+ {"small-array-TestAlignment1", &TestAlignment1{}, []byte{0x00, 0x0}, ErrPayloadTooSmall},
+ {"empty-array-TestAlignment2", &TestAlignment2{}, []byte{}, ErrPayloadTooSmall},
+ {"nil-array-TestAlignment2", &TestAlignment2{}, nil, ErrPayloadTooSmall},
+ {"small-array-TestAlignment2", &TestAlignment2{}, []byte{0x00, 0x0}, ErrPayloadTooSmall},
+ {"small-array-TestAlignment2-2", &TestAlignment2{}, make([]byte, 10), ErrPayloadTooSmall},
+ {"empty-array-TestFloat1", &TestFloat1{}, []byte{}, ErrPayloadTooSmall},
+ {"nil-array-TestFloat1", &TestFloat1{}, nil, ErrPayloadTooSmall},
+ {"small-array-TestFloat1", &TestFloat1{}, []byte{0x00, 0x0}, ErrPayloadTooSmall},
+ {"empty-array-TestFloat2", &TestFloat2{}, []byte{}, ErrPayloadTooSmall},
+ {"nil-array-TestFloat2", &TestFloat2{}, nil, ErrPayloadTooSmall},
+ {"small-array-TestFloat2", &TestFloat2{}, []byte{0x00, 0x0}, ErrPayloadTooSmall},
+ {"empty-array-TestFloat3", &TestFloat3{}, []byte{}, ErrPayloadTooSmall},
+ {"nil-array-TestFloat3", &TestFloat3{}, nil, ErrPayloadTooSmall},
+ {"small-array-TestFloat3", &TestFloat3{}, []byte{0x00, 0x0}, ErrPayloadTooSmall},
+ {"small-array-TestFloat3-2", &TestFloat3{}, make([]byte, 6), ErrPayloadTooSmall},
+ {"nil-array-TestArray1", &TestArray1{}, nil, ErrPayloadTooSmall},
+ {"empty-array-TestArray1", &TestArray1{}, []byte{}, ErrPayloadTooSmall},
+ {"two-bytes-array-TestArray1", &TestArray1{}, []byte{0x00, 0x0}, ErrPayloadTooSmall},
+ {"nil-array-TestArray2", &TestArray2{}, nil, ErrPayloadTooSmall},
+ {"empty-array-TestArray2", &TestArray2{}, []byte{}, ErrPayloadTooSmall},
+ {"two-bytes-array-TestArray2", &TestArray2{}, []byte{0x00, 0x0}, ErrPayloadTooSmall},
+ {"six-bytes-array-TestArray2", &TestArray2{}, make([]byte, 6), ErrPayloadTooSmall},
+ {"nil-array-TestArray3", &TestArray3{}, nil, ErrPayloadTooSmall},
+ {"empty-array-TestArray3", &TestArray3{}, []byte{}, ErrPayloadTooSmall},
+ {"two-bytes-array-TestArray3", &TestArray3{}, []byte{0x00, 0x0}, ErrPayloadTooSmall},
+ {"six-bytes-array-TestArray3", &TestArray3{}, make([]byte, 6), ErrPayloadTooSmall},
+ {"thirteen-bytes-array-TestArray3", &TestArray3{}, make([]byte, 13), ErrPayloadTooSmall},
+ {"nil-array-TestArray4", &TestArray4{}, nil, ErrPayloadTooSmall},
+ {"empty-array-TestArray4", &TestArray4{}, []byte{}, ErrPayloadTooSmall},
+ {"two-bytes-array-TestArray4", &TestArray4{}, []byte{0x00, 0x0}, ErrPayloadTooSmall},
+ {"nil-array-TestString1", &TestString1{}, nil, ErrPayloadTooSmall},
+ {"empty-array-TestString1", &TestString1{}, []byte{}, ErrPayloadTooSmall},
+ {"two-bytes-array-TestString1", &TestString1{}, []byte{0x00, 0x0}, ErrPayloadTooSmall},
+ {"nil-array-TestString2", &TestString2{}, nil, ErrPayloadTooSmall},
+ {"empty-array-TestString2", &TestString2{}, []byte{}, ErrPayloadTooSmall},
+ {"two-bytes-array-TestString2", &TestString2{}, []byte{0x00, 0x0}, ErrPayloadTooSmall},
+ {"nil-array-TestStruct2", &TestStruct2{}, nil, ErrPayloadTooSmall},
+ {"empty-array-TestStruct2", &TestStruct2{}, []byte{}, ErrPayloadTooSmall},
+ {"two-bytes-array-TestStruct2", &TestStruct2{}, []byte{0x00, 0x0}, ErrPayloadTooSmall},
+ {"six-bytes-array-TestStruct2", &TestStruct2{}, make([]byte, 6), ErrPayloadTooSmall},
+ {"thirteen-bytes-array-TestStruct2", &TestStruct2{}, make([]byte, 13), ErrPayloadTooSmall},
+ {"empty-array-TestUnion1", &TestUnion1{}, []byte{}, ErrPayloadTooSmall},
+ {"nil-array-TestUnion1", &TestUnion1{}, nil, ErrPayloadTooSmall},
+ {"small-array-TestUnion1", &TestUnion1{}, []byte{0x00, 0x0}, ErrPayloadTooSmall},
+ {"non-zero-or-one-bool", &TestSimpleBool{}, []byte{2}, ErrInvalidBoolValue},
+ {"wrong-tag", &TestUnion1{}, []byte{0, 0, 0, 4}, ErrInvalidUnionTag},
+ {"empty-struct-non-zero", &EmptyStruct{}, emptyStructWithOneInsteadOfZero, ErrInvalidEmptyStruct},
+}
+
+var allErrorCasesUnmarshal = append(baseErrorCasesUnmarshal, []errorCaseUnmarshal{
+ {"string-wrong-ptr-no-alloc", &TestStringWithBound{}, []byte{
+ 3, 0, 0, 0, 0, 0, 0, 0, // length
+ 0, 0, 0, 0, 0, 0, 0, 0, // ptr (no alloc)
+ // no data, unmarshal should fail before
+ }, ErrUnexpectedNullRef},
+ {"string-wrong-ptr-incorrect", &TestStringWithBound{}, []byte{
+ 3, 0, 0, 0, 0, 0, 0, 0, // length
+ 0, 0, 0, 0, 0, 0, 0, 1, // ptr (no alloc)
+ // no data, unmarshal should fail before
+ }, ErrBadRefEncoding},
+ {"string-too-long", &TestStringWithBound{}, []byte{
+ 9, 0, 0, 0, 0, 0, 0, 0, // length (too long)
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // ptr
+ // no data, unmarshal should fail before
+ }, ErrStringTooLong},
+ {"string-has-truncated-data", &TestStringWithBound{}, []byte{
+ 8, 0, 0, 0, 0, 0, 0, 0, // length
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // ptr
+ 0x41, 0x72, 0x67, 0x68, 0x68, 0x68, 0x68, // only 7 bytes
+ }, ErrMessageTooSmall},
+
+ {"opt-string-wrong-ptr-incorrect", &TestOptStringWithBound{}, []byte{
+ 3, 0, 0, 0, 0, 0, 0, 0, // length
+ 0, 0, 0, 0, 0, 0, 0, 1, // ptr (no alloc)
+ // no data, unmarshal should fail before
+ }, ErrBadRefEncoding},
+ {"opt-string-too-long", &TestOptStringWithBound{}, []byte{
+ 9, 0, 0, 0, 0, 0, 0, 0, // length (too long)
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // ptr
+ // no data, unmarshal should fail before
+ }, ErrStringTooLong},
+}...)
+
+var simpleTableWithXY = []byte{
+ 5, 0, 0, 0, 0, 0, 0, 0, // max ordinal
+ 255, 255, 255, 255, 255, 255, 255, 255, // alloc present
+ 8, 0, 0, 0, 0, 0, 0, 0, // envelope 1: num bytes / num handles
+ 255, 255, 255, 255, 255, 255, 255, 255, // alloc present
+ 0, 0, 0, 0, 0, 0, 0, 0, // envelope 2: num bytes / num handles
+ 0, 0, 0, 0, 0, 0, 0, 0, // no alloc
+ 0, 0, 0, 0, 0, 0, 0, 0, // envelope 3: num bytes / num handles
+ 0, 0, 0, 0, 0, 0, 0, 0, // no alloc
+ 0, 0, 0, 0, 0, 0, 0, 0, // envelope 4: num bytes / num handles
+ 0, 0, 0, 0, 0, 0, 0, 0, // no alloc
+ 8, 0, 0, 0, 0, 0, 0, 0, // envelope 5: num bytes / num handles
+ 255, 255, 255, 255, 255, 255, 255, 255, // alloc present
+ 42, 0, 0, 0, 0, 0, 0, 0, // field X
+ 67, 0, 0, 0, 0, 0, 0, 0, // field Y
+}
+
+var simpleTableWithY = []byte{
+ 5, 0, 0, 0, 0, 0, 0, 0, // max ordinal
+ 255, 255, 255, 255, 255, 255, 255, 255, // alloc present
+ 0, 0, 0, 0, 0, 0, 0, 0, // envelope 1: num bytes / num handles
+ 0, 0, 0, 0, 0, 0, 0, 0, // no alloc
+ 0, 0, 0, 0, 0, 0, 0, 0, // envelope 2: num bytes / num handles
+ 0, 0, 0, 0, 0, 0, 0, 0, // no alloc
+ 0, 0, 0, 0, 0, 0, 0, 0, // envelope 3: num bytes / num handles
+ 0, 0, 0, 0, 0, 0, 0, 0, // no alloc
+ 0, 0, 0, 0, 0, 0, 0, 0, // envelope 4: num bytes / num handles
+ 0, 0, 0, 0, 0, 0, 0, 0, // no alloc
+ 8, 0, 0, 0, 0, 0, 0, 0, // envelope 5: num bytes / num handles
+ 255, 255, 255, 255, 255, 255, 255, 255, // alloc present
+ 67, 0, 0, 0, 0, 0, 0, 0, // field Y
+}
+
+var emptyStructWithOneInsteadOfZero = []byte{
+ 1, // empty struct with invalid value of 1 (instead of zero)
+ 0, 0, 0, 0, 0, 0, 0, // 7 bytes of padding after empty struct, to align to 64 bits
+}
+
+func TestAllManualSuccessCases(t *testing.T) {
+ // TODO(FIDL-635): Complete conversion.
+ var ipAddressConfig IpAddressConfig
+ ipAddressConfig.SetDhcp(true)
+ successCase{
+ name: "add-ethernet-device-request",
+ input: &TestAddEthernetDeviceRequest{
+ TopologicalPath: "@/dev/sys/pci/00:03.0/e1000/ethernet",
+ Config: InterfaceConfig{
+ Name: "ethp0003",
+ IpAddressConfig: ipAddressConfig,
+ },
+ Device: EthernetDeviceInterface{zx.Channel(0xdeadbeef)},
+ },
+ bytes: []byte{
+ 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // topological_path
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // topological_path
+ 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // name
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // name
+ 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, // subnet (dhcp variant)
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // padding
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // padding
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // padding
+ 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, // device (handle present)
+ 0x40, 0x2f, 0x64, 0x65, 0x76, 0x2f, 0x73, 0x79, // @/dev/sy
+ 0x73, 0x2f, 0x70, 0x63, 0x69, 0x2f, 0x30, 0x30, // s/pci/00
+ 0x3a, 0x30, 0x33, 0x2e, 0x30, 0x2f, 0x65, 0x31, // :03.0/e1
+ 0x30, 0x30, 0x30, 0x2f, 0x65, 0x74, 0x68, 0x65, // 000/ethe
+ 0x72, 0x6e, 0x65, 0x74, 0x00, 0x00, 0x00, 0x00, // rnet
+ 0x65, 0x74, 0x68, 0x70, 0x30, 0x30, 0x30, 0x33, // ethp0003
+ },
+ handles: []zx.Handle{
+ zx.Handle(0xdeadbeef),
+ },
+ }.check(t)
+}
+
+func TestTableCompatibilityWithXY(t *testing.T) {
+ ost := OlderSimpleTable{}
+ ost.SetX(42)
+ st := SimpleTable{}
+ st.SetX(42)
+ st.SetY(67)
+ nst := NewerSimpleTable{}
+ nst.SetX(42)
+ nst.SetY(67)
+ cases := []Message{
+ &TestOlderSimpleTable{Table: ost},
+ &TestSimpleTable{Table: st},
+ &TestNewerSimpleTable{Table: nst},
+ }
+ for _, expected := range cases {
+ output := makeDefault(expected)
+ if _, _, err := UnmarshalNew(simpleTableWithXY, nil, output); err != nil {
+ t.Fatalf("unmarshal: failed: %s", err)
+ }
+ if !reflect.DeepEqual(expected, output) {
+ t.Fatalf("unmarshal: expected: %v, got: %v", expected, output)
+ }
+ }
+}
+
+func TestTableCompatibilityWithY(t *testing.T) {
+ ost := OlderSimpleTable{}
+ st := SimpleTable{}
+ st.SetY(67)
+ nst := NewerSimpleTable{}
+ nst.SetY(67)
+ cases := []Message{
+ &TestOlderSimpleTable{Table: ost},
+ &TestSimpleTable{Table: st},
+ &TestNewerSimpleTable{Table: nst},
+ }
+ for _, expected := range cases {
+ output := makeDefault(expected)
+ _, _, err := UnmarshalNew(simpleTableWithY, nil, output)
+ if err != nil {
+ t.Fatalf("unmarshal: failed: %s", err)
+ }
+ if !reflect.DeepEqual(expected, output) {
+ t.Fatalf("unmarshal: expected: %v, got: %v", expected, output)
+ }
+ }
+}
+
+func TestFailuresMarshal(t *testing.T) {
+ v1 := []int64{1, 2, 3}
+ cases := []struct {
+ name string
+ input Message
+ errorCode ErrorCode
+ }{
+ {"string3-string-too-long", &TestString3{
+ A: [2]string{
+ "too long!", // limit is 4, provided is longer(tm)
+ "g",
+ },
+ B: [2]*string{nil, nil},
+ }, ErrStringTooLong},
+ {"vector1-C-vector-too-long", &TestVector1{
+ A: []int8{1, 2, 3, 4},
+ B: nil,
+ C: []int32{99, 100, 101}, // limit is 2, provided is 3
+ D: nil,
+ }, ErrVectorTooLong},
+ {"vector1-D-vector-too-long", &TestVector1{
+ A: []int8{1, 2, 3, 4},
+ B: nil,
+ C: []int32{99},
+ D: &v1, // limit is 2, provided is 3
+ }, ErrVectorTooLong},
+ {"union1-A-uninitialized", &TestUnion1{
+ A: Union1{}, // Intentionally don't set any members of the union.
+ B: nil,
+ }, ErrInvalidUnionTag},
+ {"union1-A-tag-out-of-bounds", &TestUnion1{
+ A: Union1{Union1Tag: Union1D + 1},
+ B: nil,
+ }, ErrInvalidUnionTag},
+ }
+ for _, ex := range cases {
+ t.Run(ex.name, func(t *testing.T) {
+ var respb [zx.ChannelMaxMessageBytes]byte
+ var resph [zx.ChannelMaxMessageHandles]zx.Handle
+ _, _, err := MarshalNew(ex.input, respb[:], resph[:])
+ validationErr, ok := err.(ValidationError)
+ if !ok {
+ t.Fatalf("expected ValidationError, was %v", err)
+ }
+ if validationErr.Code() != ex.errorCode {
+ t.Fatalf("expected %s, was %s", ex.errorCode, validationErr.Code())
+ }
+ })
+ }
+}
+
+func TestFailuresUnmarshalNoHandles(t *testing.T) {
+ for _, ex := range allErrorCasesUnmarshal {
+ t.Run(ex.name, func(t *testing.T) {
+ _, _, err := UnmarshalNew(ex.input, nil, ex.message)
+ validationErr, ok := err.(ValidationError)
+ if !ok {
+ t.Fatalf("expected ValidationError, was %v", err)
+ }
+ if validationErr.Code() != ex.errorCode {
+ t.Fatalf("expected %s, was %s", ex.errorCode, validationErr.Code())
+ }
+ })
+ }
+}
+
+func benchmarkMarshal(b *testing.B, ex example) {
+ b.Run(ex.name, func(b *testing.B) {
+ b.StopTimer()
+ var respb [zx.ChannelMaxMessageBytes]byte
+ var resph [zx.ChannelMaxMessageHandles]zx.Handle
+ b.StartTimer()
+ for n := 0; n < b.N; n++ {
+ if _, _, err := MarshalNew(ex.input, respb[:], resph[:]); err != nil {
+ b.Fail()
+ }
+ }
+ })
+}
+
+func BenchmarkMarshal(b *testing.B) {
+ for _, ex := range general() {
+ benchmarkMarshal(b, ex)
+ }
+ for _, ex := range fuchsia() {
+ benchmarkMarshal(b, ex)
+ }
+}
+
+func benchmarkUnmarshal(b *testing.B, ex example) {
+ b.Run(ex.name, func(b *testing.B) {
+ b.StopTimer()
+ var respb [zx.ChannelMaxMessageBytes]byte
+ var resph [zx.ChannelMaxMessageHandles]zx.Handle
+ nb, nh, err := MarshalNew(ex.input, respb[:], resph[:])
+ if err != nil {
+ b.Fail()
+ }
+ output := makeDefault(ex.input)
+ b.StartTimer()
+ for n := 0; n < b.N; n++ {
+ if _, _, err := UnmarshalNew(respb[:nb], resph[:nh], output); err != nil {
+ b.Fail()
+ }
+ }
+ })
+}
+
+func BenchmarkUnmarshal(b *testing.B) {
+ for _, ex := range general() {
+ benchmarkUnmarshal(b, ex)
+ }
+ for _, ex := range fuchsia() {
+ benchmarkUnmarshal(b, ex)
+ }
+}
diff --git a/src/syscall/zx/fidl/fidl_test/testutil_test.go b/src/syscall/zx/fidl/fidl_test/testutil_test.go
new file mode 100644
index 0000000..1c88efc
--- /dev/null
+++ b/src/syscall/zx/fidl/fidl_test/testutil_test.go
@@ -0,0 +1,80 @@
+// Copyright 2019 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// +build fuchsia
+
+package fidl_test
+
+import (
+ "bytes"
+ "fmt"
+ "reflect"
+ "testing"
+
+ "syscall/zx"
+ "syscall/zx/fidl"
+)
+
+func makeDefault(msg fidl.Message) fidl.Message {
+ typ := reflect.TypeOf(msg)
+ if typ.Kind() != reflect.Ptr && typ.Elem().Kind() != reflect.Struct {
+ panic(fmt.Sprintf("expecting *struct, actual %T", msg))
+ }
+ return reflect.New(typ.Elem()).Interface().(fidl.Message)
+}
+
+// successCase represents a golden test for a success case, where encoding
+// and decoding should succceed.
+type successCase struct {
+ name string
+ input fidl.Message
+ bytes []byte
+ handles []zx.Handle
+}
+
+func (ex successCase) check(t *testing.T) {
+ t.Run(ex.name, func(t *testing.T) {
+ defer func() {
+ // When running tests on device, this bubbles up the error on the
+ // console launching the tests, rather than having to look at the
+ // device's kernel logs.
+ if r := recover(); r != nil {
+ t.Fatalf("panic: %s", r)
+ panic(r)
+ }
+ }()
+ var respb [zx.ChannelMaxMessageBytes]byte
+ var resph [zx.ChannelMaxMessageHandles]zx.Handle
+ nb, nh, err := fidl.MarshalNew(ex.input, respb[:], resph[:])
+ if err != nil {
+ t.Fatal(err)
+ }
+ if !bytes.Equal(ex.bytes, respb[:nb]) {
+ t.Fatalf("expected %x, got %x", ex.bytes, respb[:nb])
+ }
+ if len(ex.handles) == 0 {
+ if nh != 0 {
+ t.Fatalf("no handles expected, got %d", nh)
+ }
+ } else {
+ if !reflect.DeepEqual(ex.handles, resph[:nh]) {
+ t.Fatalf("expected %v, got %v", ex.handles, resph[:nh])
+ }
+ }
+ output := makeDefault(ex.input)
+ nbActual, nhActual, err := fidl.UnmarshalNew(respb[:nb], resph[:nh], output)
+ if err != nil {
+ t.Fatalf("unmarshal: failed: %s", err)
+ }
+ if !reflect.DeepEqual(ex.input, output) {
+ t.Fatalf("unmarshal: expected: %v, got: %v", ex.input, output)
+ }
+ if nb != nbActual {
+ t.Fatalf("unmarshal: num bytes, expected: %d, got: %d", nb, nbActual)
+ }
+ if nh != nhActual {
+ t.Fatalf("unmarshal: num handles, expected: %d, got: %d", nh, nhActual)
+ }
+ })
+}
diff --git a/src/syscall/zx/fidl/interface.go b/src/syscall/zx/fidl/interface.go
new file mode 100644
index 0000000..15812db
--- /dev/null
+++ b/src/syscall/zx/fidl/interface.go
@@ -0,0 +1,268 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build fuchsia
+
+package fidl
+
+import (
+ "strconv"
+ "sync"
+ "syscall/zx"
+ "syscall/zx/zxwait"
+)
+
+// ServiceRequest is an abstraction over a FIDL interface request which is
+// intended to be used as part of service discovery.
+type ServiceRequest interface {
+ // Name returns the name of the service being requested.
+ Name() string
+
+ // ToChannel returns the underlying channel of the ServiceRequest.
+ ToChannel() zx.Channel
+}
+
+// InterfaceRequest is a wrapper type around a channel and represents the server side
+// of a FIDL interface, to be sent to a server as a request.
+type InterfaceRequest struct {
+ zx.Channel
+}
+
+// NewInterfaceRequest generates two sides of a channel with one layer of
+// type casts out of the way to minimize the amount of generated code. Semantically,
+// the two sides of the channel represent the interface request and the client
+// side of the interface (the proxy). It returns an error on failure.
+func NewInterfaceRequest() (InterfaceRequest, *ChannelProxy, error) {
+ h0, h1, err := zx.NewChannel(0)
+ if err != nil {
+ return InterfaceRequest{}, nil, err
+ }
+ return InterfaceRequest{Channel: h0}, &ChannelProxy{Channel: h1}, nil
+}
+
+// Proxy represents the client side of a FIDL interface.
+type Proxy interface {
+ IsValid() bool
+ SendNew(ordinal uint32, req Message) error
+ RecvNew(ordinal uint32, resp Message, gen_ordinal ...uint32) error
+ CallNew(ordinal uint32, req Message, resp Message) error
+}
+
+// Stub represents a generated type which wraps the server-side implementation of a
+// FIDL interface.
+//
+// It contains logic which is able to dispatch into the correct implementation given
+// the incoming message ordinal and its data.
+type Stub interface {
+ // Dispatch dispatches into the appropriate method implementation for a FIDL
+ // interface by using the ordinal.
+ //
+ // It also takes the data as bytes and transforms it into arguments usable by
+ // the method implementation. It then optionally returns a response if the
+ // method has a response.
+ DispatchNew(ordinal uint32, bytes []byte, handles []zx.Handle) (Message, error)
+}
+
+// ChannelProxy a Proxy that is backed by a channel.
+type ChannelProxy struct {
+ // Channel is the underlying channel endpoint for this interface.
+ zx.Channel
+}
+
+// Assert that ChannelProxy implements the Proxy interface.
+var _ Proxy = &ChannelProxy{}
+
+// IsValid returns true if the underlying channel is a valid handle.
+func (p *ChannelProxy) IsValid() bool {
+ return p.Channel.Handle().IsValid()
+}
+
+func withRetry(fn func() error, handle zx.Handle, ready, closed zx.Signals) error {
+ signals := ready | closed
+ for {
+ err := fn()
+ if err, ok := err.(*zx.Error); ok && err.Status == zx.ErrShouldWait {
+ obs, err := zxwait.Wait(
+ handle,
+ signals,
+ zx.TimensecInfinite,
+ )
+ if err != nil {
+ return err
+ }
+ if obs&ready != 0 {
+ continue
+ }
+ if obs&closed != 0 {
+ return &zx.Error{Status: zx.ErrPeerClosed}
+ }
+ panic("unexpected signal mask " + strconv.FormatUint(uint64(obs), 2) + " (expected " + strconv.FormatUint(uint64(signals), 2) + ")")
+ }
+ return err
+ }
+}
+
+func unmarshalForOrdinal(ordinal uint32, respb []byte, resph []zx.Handle, resp Message, gen_ordinal ...uint32) error {
+ var header MessageHeader
+ if err := UnmarshalHeaderThenMessage(respb, resph, &header, resp); err != nil {
+ return err
+ }
+ // TODO(FIDL-425): Remove temporary handling of two ordinals.
+ expectedOrdinal := header.Ordinal == ordinal
+ for _, ordinal := range gen_ordinal {
+ expectedOrdinal = expectedOrdinal || header.Ordinal == ordinal
+ }
+ if !expectedOrdinal {
+ return newExpectError(ErrUnexpectedOrdinal, ordinal, header.Ordinal)
+ }
+ return nil
+}
+
+// Send sends the request over the channel with the specified ordinal
+// without a response.
+func (p *ChannelProxy) SendNew(ordinal uint32, req Message) error {
+ respb := messageBytesPool.Get().([]byte)
+ resph := messageHandlesPool.Get().([]zx.Handle)
+
+ defer messageBytesPool.Put(respb)
+ defer messageHandlesPool.Put(resph)
+
+ // Marshal the message into the buffer.
+ header := MessageHeader{
+ Txid: 0, // Txid == 0 for messages without a response.
+ Ordinal: ordinal,
+ }
+ nb, nh, err := MarshalHeaderThenMessage(&header, req, respb[:], resph[:])
+ if err != nil {
+ return err
+ }
+
+ // Write the encoded bytes to the channel.
+ return withRetry(func() error {
+ return p.Channel.Write(respb[:nb], resph[:nh], 0)
+ }, *p.Channel.Handle(), zx.SignalChannelWritable, zx.SignalChannelPeerClosed)
+}
+
+// Recv waits for an event and writes the response into the response.
+func (p *ChannelProxy) RecvNew(ordinal uint32, resp Message, gen_ordinal ...uint32) error {
+ respb := messageBytesPool.Get().([]byte)
+ resph := messageHandlesPool.Get().([]zx.Handle)
+
+ defer messageBytesPool.Put(respb)
+ defer messageHandlesPool.Put(resph)
+
+ var nb, nh uint32
+ if err := withRetry(func() error {
+ var err error
+ nb, nh, err = p.Channel.Read(respb[:], resph[:], 0)
+ return err
+ }, *p.Channel.Handle(), zx.SignalChannelReadable, zx.SignalChannelPeerClosed); err != nil {
+ return err
+ }
+
+ return unmarshalForOrdinal(ordinal, respb[:nb], resph[:nh], resp, gen_ordinal...)
+}
+
+// Call sends the request over the channel with the specified ordinal
+// and synchronously waits for a response. It then writes the response into the
+// response.
+func (p *ChannelProxy) CallNew(ordinal uint32, req Message, resp Message) error {
+ respb := messageBytesPool.Get().([]byte)
+ resph := messageHandlesPool.Get().([]zx.Handle)
+
+ defer messageBytesPool.Put(respb)
+ defer messageHandlesPool.Put(resph)
+
+ // Marshal the message into the buffer
+ header := MessageHeader{
+ Ordinal: ordinal,
+ }
+ nb, nh, err := MarshalHeaderThenMessage(&header, req, respb[:], resph[:])
+ if err != nil {
+ return err
+ }
+
+ // Make the IPC call.
+ cnb, cnh, err := p.Channel.Call(0, zx.TimensecInfinite, respb[:nb], resph[:nh], respb[:], resph[:])
+ if err != nil {
+ return err
+ }
+
+ return unmarshalForOrdinal(ordinal, respb[:cnb], resph[:cnh], resp)
+}
+
+// SocketControlProxy is a Proxy that is backed by the control plane of a socket.
+type SocketControlProxy struct {
+ // Socket is the underlying socket transport for this interface.
+ zx.Socket
+
+ // Mutex is used to implement atomic FIDL calls.
+ sync.Mutex
+}
+
+// Assert that SocketControlProxy implements the Proxy interface.
+var _ Proxy = &SocketControlProxy{}
+
+// IsValid returns true if the underlying socket is a valid handle.
+func (p *SocketControlProxy) IsValid() bool {
+ return p.Socket.Handle().IsValid()
+}
+
+// Send sends the request over the socket control plane with the
+// specified ordinal without a response.
+func (p *SocketControlProxy) SendNew(ordinal uint32, req Message) error {
+ respb := messageBytesPool.Get().([]byte)
+
+ defer messageBytesPool.Put(respb)
+
+ // Marshal the message into the buffer.
+ header := MessageHeader{
+ Txid: 0, // Txid == 0 for messages without a response.
+ Ordinal: ordinal,
+ }
+ nb, _, err := MarshalHeaderThenMessage(&header, req, respb[:], nil)
+ if err != nil {
+ return err
+ }
+
+ // Write the encoded bytes to the socket control plane.
+ return withRetry(func() error {
+ _, err := p.Socket.Write(respb[:nb], zx.SocketControl)
+ return err
+ }, *p.Socket.Handle(), zx.SignalSocketControlWriteable, zx.SignalSocketPeerClosed)
+}
+
+// Recv waits for an event and writes the response.
+func (p *SocketControlProxy) RecvNew(ordinal uint32, resp Message, gen_ordinal ...uint32) error {
+ respb := messageBytesPool.Get().([]byte)
+
+ defer messageBytesPool.Put(respb)
+
+ // Read the encoded bytes from the socket control plane.
+ var nb int
+ if err := withRetry(func() error {
+ var err error
+ nb, err = p.Socket.Read(respb[:], zx.SocketControl)
+ return err
+ }, *p.Socket.Handle(), zx.SignalSocketControlReadable, zx.SignalSocketPeerClosed); err != nil {
+ return err
+ }
+
+ return unmarshalForOrdinal(ordinal, respb[:nb], nil, resp, gen_ordinal...)
+}
+
+// Call sends the request over the socket control plane with the specified
+// ordinal and waits for a response. It then writes the response into the response.
+func (p *SocketControlProxy) CallNew(ordinal uint32, req Message, resp Message) error {
+ p.Mutex.Lock()
+ defer p.Mutex.Unlock()
+
+ if err := p.SendNew(ordinal, req); err != nil {
+ return err
+ }
+ if err := p.RecvNew(ordinal, resp); err != nil {
+ return err
+ }
+ return nil
+}
diff --git a/src/syscall/zx/fidl/interface_test.go b/src/syscall/zx/fidl/interface_test.go
new file mode 100644
index 0000000..a5f1f2c
--- /dev/null
+++ b/src/syscall/zx/fidl/interface_test.go
@@ -0,0 +1,136 @@
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build fuchsia
+
+package fidl_test
+
+import (
+ "fmt"
+ "math/rand"
+ "sync"
+ "syscall/zx"
+ "syscall/zx/fidl"
+ "testing"
+)
+
+var _ fidl.Message = (*message)(nil)
+
+type message struct {
+ _ struct{} `fidl2:"s,1,0"`
+}
+
+var _mMessage = fidl.MustCreateMarshaler(message{})
+
+func (*message) Marshaler() fidl.Marshaler {
+ return _mMessage
+}
+
+func TestProxy(t *testing.T) {
+ const concurrency = 10
+ const numMessages = 100
+
+ c0, c1, err := zx.NewChannel(0)
+ if err != nil {
+ t.Fatal(err)
+ }
+ s0, s1, err := zx.NewSocket(zx.SocketHasControl)
+ if err != nil {
+ t.Fatal(err)
+ }
+ for _, proxies := range [][2]fidl.Proxy{
+ {&fidl.ChannelProxy{Channel: c0}, &fidl.ChannelProxy{Channel: c1}},
+ {&fidl.SocketControlProxy{Socket: s0}, &fidl.SocketControlProxy{Socket: s1}},
+ } {
+ sender, receiver := proxies[0], proxies[1]
+ t.Run(fmt.Sprintf("%T", sender), func(t *testing.T) {
+ var wg sync.WaitGroup
+ errs := make(chan error, concurrency)
+ // Spin up |concurrency| senders, each sending |numMessages|.
+ for i := 0; i < concurrency; i++ {
+ wg.Add(1)
+ go func() {
+ defer wg.Done()
+ errs <- func() error {
+ for i := 0; i < numMessages; i++ {
+ ordinal := rand.Uint32()
+
+ var resp message
+ if err := sender.CallNew(ordinal, &message{}, &resp); err != nil {
+ return err
+ }
+ }
+ return nil
+ }()
+ }()
+ }
+
+ //.Echo the |concurrency*numMessages| messages sent by the senders above.
+ for i := 0; i < concurrency*numMessages; i++ {
+ var respb [zx.ChannelMaxMessageBytes]byte
+ var msg []byte
+
+ switch receiver := receiver.(type) {
+ case *fidl.ChannelProxy:
+ if err := fidl.WithRetry(func() error {
+ nb, _, err := receiver.Channel.Read(respb[:], nil, 0)
+ if err == nil {
+ msg = respb[:nb]
+ }
+ return err
+ }, *receiver.Channel.Handle(), zx.SignalChannelReadable, zx.SignalChannelPeerClosed); err != nil {
+ t.Fatal(err)
+ }
+
+ case *fidl.SocketControlProxy:
+ if err := fidl.WithRetry(func() error {
+ nb, err := receiver.Socket.Read(respb[:], zx.SocketControl)
+ if err == nil {
+ msg = respb[:nb]
+ }
+ return err
+ }, *receiver.Socket.Handle(), zx.SignalSocketControlReadable, zx.SignalSocketPeerClosed); err != nil {
+ t.Fatal(err)
+ }
+
+ default:
+ panic(fmt.Sprintf("unknown type %T", receiver))
+ }
+
+ var header fidl.MessageHeader
+ if _, _, err := fidl.UnmarshalNew(msg, nil, &header); err != nil {
+ t.Fatal(err)
+ }
+ cnb, _, err := fidl.MarshalHeaderThenMessage(&header, &message{}, respb[:], nil)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ switch receiver := receiver.(type) {
+ case *fidl.ChannelProxy:
+ if err := receiver.Channel.Write(respb[:cnb], nil, 0); err != nil {
+ t.Fatal(err)
+ }
+
+ case *fidl.SocketControlProxy:
+ if _, err := receiver.Socket.Write(respb[:cnb], zx.SocketControl); err != nil {
+ t.Fatal(err)
+ }
+
+ default:
+ panic(fmt.Sprintf("unknown type %T", receiver))
+ }
+ }
+
+ wg.Wait()
+ close(errs)
+
+ for err := range errs {
+ if err != nil {
+ t.Error(err)
+ }
+ }
+ })
+ }
+}
diff --git a/src/syscall/zx/fidl/message.go b/src/syscall/zx/fidl/message.go
new file mode 100644
index 0000000..9070f65
--- /dev/null
+++ b/src/syscall/zx/fidl/message.go
@@ -0,0 +1,77 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build fuchsia
+
+package fidl
+
+import (
+ "sync"
+
+ "syscall/zx"
+)
+
+// messageBytesPool is a pool of buffers that can fit the data part of any
+// FIDL message.
+var messageBytesPool = sync.Pool{
+ New: func() interface{} {
+ return make([]byte, zx.ChannelMaxMessageBytes)
+ },
+}
+
+// messageHandlesPool is a pool of buffers that can fit the handles part of
+// any FIDL message.
+var messageHandlesPool = sync.Pool{
+ New: func() interface{} {
+ return make([]zx.Handle, zx.ChannelMaxMessageHandles)
+ },
+}
+
+// MessageHeader represents a transactional message header.
+type MessageHeader struct {
+ _ struct{} `fidl2:"s,16,4"`
+ Txid uint32
+ Reserved uint32
+ Flags uint32
+ Ordinal uint32
+}
+
+var mMessageHeader = MustCreateMarshaler(MessageHeader{})
+
+func (msg *MessageHeader) Marshaler() Marshaler {
+ return mMessageHeader
+}
+
+// MarshalHeaderThenMessage marshals a transactional message
+// (see https://fuchsia.googlesource.com/fuchsia/+/master/docs/development/languages/fidl/reference/wire-format/README.md#messages-for-transactions).
+// It marshals a `MessageHeader`, optionally followed by a `Message` (body).
+func MarshalHeaderThenMessage(header *MessageHeader, body Message, data []byte, handles []zx.Handle) (int, int, error) {
+ if _, _, err := MarshalNew(header, data[:MessageHeaderSize], nil); err != nil {
+ return 0, 0, err
+ }
+ if body == nil {
+ return MessageHeaderSize, 0, nil
+ }
+ nb, nh, err := MarshalNew(body, data[MessageHeaderSize:], handles[:])
+ if err != nil {
+ return 0, 0, err
+ }
+ return nb + MessageHeaderSize, nh, nil
+}
+
+// UnmarshalHeaderThenMessage unmarshals a transactional message
+// (see https://fuchsia.googlesource.com/fuchsia/+/master/docs/development/languages/fidl/reference/wire-format/README.md#messages-for-transactions).
+// It unmarshals a `MessageHeader`, optionally followed by a `Message` (body).
+func UnmarshalHeaderThenMessage(data []byte, handles []zx.Handle, header *MessageHeader, body Message) error {
+ if _, _, err := UnmarshalNew(data[:MessageHeaderSize], nil, header); err != nil {
+ return err
+ }
+ if body == nil {
+ return nil
+ }
+ if _, _, err := UnmarshalNew(data[MessageHeaderSize:], handles[:], body); err != nil {
+ return err
+ }
+ return nil
+}
diff --git a/src/syscall/zx/fidl/stub.go b/src/syscall/zx/fidl/stub.go
new file mode 100644
index 0000000..e642e38
--- /dev/null
+++ b/src/syscall/zx/fidl/stub.go
@@ -0,0 +1,3 @@
+//+build !fuchsia
+
+package fidl
diff --git a/src/syscall/zx/handle.go b/src/syscall/zx/handle.go
new file mode 100644
index 0000000..150c3c6
--- /dev/null
+++ b/src/syscall/zx/handle.go
@@ -0,0 +1,539 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build fuchsia
+
+package zx
+
+import (
+ "sync/atomic"
+ "unsafe"
+)
+
+// Process-wide FDIO handles.
+var (
+ StdioHandles [3]Handle // in/out/err
+ StdioHandleTypes [3]int
+ CwdHandle Handle
+ ProcHandle Handle
+ VMARRoot VMAR
+ RootNSMap map[string]Handle
+)
+
+const ZX_CPRNG_DRAW_MAX_LEN = 256
+
+type HandleInfo uint32
+
+func NewHandleInfo(t, arg uint32) HandleInfo {
+ return HandleInfo((t & 0xFFFF) | ((arg & 0xFFFF) << 16))
+}
+
+func (hi HandleInfo) Type() uint32 {
+ return uint32(hi) & 0xFFFF
+}
+
+func (hi HandleInfo) Arg() uint32 {
+ return (uint32(hi) >> 16) & 0xFFFF
+}
+
+type Socket Handle
+
+func (s *Socket) Handle() *Handle {
+ return (*Handle)(s)
+}
+
+func bytesPtr(data []byte) unsafe.Pointer {
+ if len(data) > 0 {
+ return unsafe.Pointer(&data[0])
+ }
+ return nil
+}
+
+func (s *Socket) Read(data []byte, flags uint32) (int, error) {
+ var actual uint
+ status := sys_socket_read(Handle(*s), flags, bytesPtr(data), uint(len(data)), &actual)
+ if status != ErrOk {
+ return int(actual), &Error{Status: status, Text: "zx.Socket.Read"}
+ }
+ return int(actual), nil
+}
+
+func (s *Socket) Write(data []byte, flags uint32) (int, error) {
+ var actual uint
+ status := sys_socket_write(Handle(*s), flags, bytesPtr(data), uint(len(data)), &actual)
+ if status != ErrOk {
+ return int(actual), &Error{Status: status, Text: "zx.Socket.Write"}
+ }
+ return int(actual), nil
+}
+
+func (s *Socket) Share(h Handle) error {
+ if status := sys_socket_share(Handle(*s), h); status != ErrOk {
+ return &Error{Status: status, Text: "zx.Socket.Share"}
+ }
+ return nil
+}
+
+func (s *Socket) Accept(h *Handle) error {
+ if status := sys_socket_accept(Handle(*s), h); status != ErrOk {
+ return &Error{Status: status, Text: "zx.Socket.Accept"}
+ }
+ return nil
+}
+
+func (s *Socket) Close() error {
+ return s.Handle().Close()
+}
+
+func (s *Socket) Shutdown(flags uint32) error {
+ status := Sys_socket_shutdown(Handle(*s), flags)
+ if status != ErrOk {
+ return &Error{Status: status, Text: "zx.Socket.Shutdown"}
+ }
+ return nil
+}
+
+func NewSocket(flags uint32) (Socket, Socket, error) {
+ var h0, h1 Handle
+ if status := sys_socket_create(flags, &h0, &h1); status != ErrOk {
+ return Socket(HandleInvalid), Socket(HandleInvalid), &Error{Status: status, Text: "zx.Socket"}
+ }
+ return Socket(h0), Socket(h1), nil
+}
+
+type Event Handle
+
+func NewEvent(options uint32) (Event, error) {
+ var h Handle
+ if status := Sys_event_create(options, &h); status != ErrOk {
+ return Event(HandleInvalid), &Error{Status: status, Text: "zx.Event"}
+ }
+ return Event(h), nil
+}
+
+func (e *Event) Handle() *Handle {
+ return (*Handle)(e)
+}
+
+func (e *Event) Close() error {
+ return e.Handle().Close()
+}
+
+func (e *Event) Duplicate(rights Rights) (Event, error) {
+ h := Handle(*e)
+ h, err := h.Duplicate(rights)
+ if err != nil {
+ return Event(HandleInvalid), err
+ }
+ return Event(h), nil
+}
+
+var zxwaitCloseFn = func(Handle) {}
+
+// SetZXWaitCloseFn is used by package zxwait to avoid a circular dependency.
+func SetZXWaitCloseFn(fn func(Handle)) {
+ zxwaitCloseFn = fn
+}
+
+func (h *Handle) Close() error {
+ if handle := Handle(atomic.SwapUint32((*uint32)(h), uint32(HandleInvalid))); handle != HandleInvalid {
+ if status := Sys_handle_close(handle); status != ErrOk {
+ return &Error{Status: status, Text: "zx.Handle.Close"}
+ }
+ zxwaitCloseFn(handle)
+ }
+ return nil
+}
+
+func (h *Handle) Duplicate(rights Rights) (Handle, error) {
+ var dup Handle
+ if status := sys_handle_duplicate(*h, rights, &dup); status != ErrOk {
+ return HandleInvalid, &Error{Status: status, Text: "zx.Handle.Duplicate"}
+ }
+ return dup, nil
+}
+
+func (h *Handle) Signal(clearMask, setMask Signals) error {
+ if status := Sys_object_signal(*h, uint32(clearMask), uint32(setMask)); status != ErrOk {
+ return &Error{Status: status, Text: "zx.Handle.Signal"}
+ }
+ return nil
+}
+
+func (h *Handle) SignalPeer(clearMask, setMask Signals) error {
+ if status := Sys_object_signal_peer(*h, uint32(clearMask), uint32(setMask)); status != ErrOk {
+ return &Error{Status: status, Text: "zx.Handle.SignalPeer"}
+ }
+ return nil
+}
+
+func (h *Handle) GetInfo(topic uint32, data []byte) (actual, avail uint, _ error) {
+ dataBytes := uint(len(data))
+ if status := Sys_object_get_info(*h, topic, bytesPtr(data), dataBytes, &actual, &avail); status != ErrOk {
+ return 0, 0, &Error{Status: status, Text: "zx.Handle.GetInfo"}
+ }
+ return actual, avail, nil
+}
+
+func (h *Handle) GetInfoHandleBasic() (InfoHandleBasic, error) {
+ var info InfoHandleBasic
+ dataBytes := uint(unsafe.Sizeof(info))
+ dataPtr := unsafe.Pointer(&info)
+ if status := Sys_object_get_info(*h, ObjectInfoHandleBasic, dataPtr, dataBytes, nil, nil); status != ErrOk {
+ return info, &Error{Status: status, Text: "zx.Handle.GetInfoHandleBasic"}
+ }
+ return info, nil
+}
+
+func (h *Handle) GetProperty(property uint32, data []byte) error {
+ var numBytes = uint(len(data))
+ if status := Sys_object_get_property(*h, property, bytesPtr(data), numBytes); status != ErrOk {
+ return &Error{Status: status, Text: "zx.Handle.GetProperty"}
+ }
+ return nil
+}
+
+func (h *Handle) SetProperty(property uint32, data []byte) error {
+ var numBytes = uint(len(data))
+ if status := Sys_object_set_property(*h, property, bytesPtr(data), numBytes); status != ErrOk {
+ return &Error{Status: status, Text: "zx.Handle.SetProperty"}
+ }
+ return nil
+}
+
+func (h *Handle) IsValid() bool {
+ return *h > HandleInvalid
+}
+
+func WaitMany(items []WaitItem, timeout Time) error {
+ var ptr *WaitItem
+ if len(items) > 0 {
+ ptr = &items[0]
+ }
+ if status := sys_object_wait_many(ptr, uint(len(items)), timeout); status != ErrOk {
+ return &Error{Status: status, Text: "zx.Handle.WaitMany"}
+ }
+ return nil
+}
+
+const (
+ ChannelMaxMessageBytes = 65536
+ ChannelMaxMessageHandles = 64
+)
+
+type Channel Handle
+
+func (c *Channel) Handle() *Handle {
+ return (*Handle)(c)
+}
+
+func (c *Channel) Close() error {
+ return c.Handle().Close()
+}
+
+func handlePtr(data []Handle) *Handle {
+ if len(data) > 0 {
+ return &data[0]
+ }
+ return nil
+}
+
+func (c *Channel) Read(data []byte, handles []Handle, flags uint32) (numBytes, numHandles uint32, _ error) {
+ numBytes = uint32(len(data))
+ numHandles = uint32(len(handles))
+ if status := sys_channel_read(Handle(*c), flags, bytesPtr(data), handlePtr(handles), numBytes, numHandles, &numBytes, &numHandles); status != ErrOk {
+ return 0, 0, &Error{Status: status, Text: "zx.Channel.Read"}
+ }
+ return numBytes, numHandles, nil
+}
+
+func (c *Channel) Write(data []byte, handles []Handle, flags uint32) error {
+ if status := sys_channel_write(Handle(*c), flags, bytesPtr(data), uint32(len(data)), handlePtr(handles), uint32(len(handles))); status != ErrOk {
+ return &Error{Status: status, Text: "zx.Channel.Write"}
+ }
+ return nil
+}
+
+func (c *Channel) Call(flags uint32, deadline Time, wData []byte, wHandles []Handle, rData []byte, rHandles []Handle) (actualBytes, actualHandles uint32, _ error) {
+ args := &ChannelCallArgs{
+ WriteBytes: bytesPtr(wData),
+ WriteHandles: handlePtr(wHandles),
+ ReadBytes: bytesPtr(rData),
+ ReadHandles: handlePtr(rHandles),
+ WriteNumBytes: uint32(len(wData)),
+ WriteNumHandles: uint32(len(wHandles)),
+ ReadNumBytes: uint32(len(rData)),
+ ReadNumHandles: uint32(len(rHandles)),
+ }
+
+ if status := Sys_channel_call(Handle(*c), flags, deadline, args, &actualBytes, &actualHandles); status != ErrOk {
+ return 0, 0, &Error{Status: status, Text: "zx.Channel.Call"}
+ }
+ return actualBytes, actualHandles, nil
+}
+
+func NewChannel(flags uint32) (Channel, Channel, error) {
+ var h0, h1 Handle
+ if status := sys_channel_create(flags, &h0, &h1); status != ErrOk {
+ return Channel(HandleInvalid), Channel(HandleInvalid), &Error{Status: status, Text: "zx.Channel"}
+ }
+ return Channel(h0), Channel(h1), nil
+}
+
+const (
+ PortWaitAsyncOnce = iota
+ PortWaitAsyncRepeating
+)
+
+const (
+ PortPacketTypeUser = iota
+ PortPacketTypeSignalOne
+ PortPacketTypeSignalRepeating
+)
+
+const (
+ PacketHeaderSize = uint(unsafe.Sizeof(PacketHeader{}))
+ PacketMaxSize = uint(unsafe.Sizeof(Packet{}))
+)
+
+type PacketHeader struct {
+ Key uint64
+ Type uint32
+ Extra uint32
+}
+
+// Packet describes the unit of communication via an FDIO protocol
+type Packet struct {
+ Hdr PacketHeader
+ Bytes [32]uint8
+}
+
+func (p *Packet) Signal() *PacketSignal {
+ return (*PacketSignal)(unsafe.Pointer(p))
+}
+
+type PortPacket interface {
+ Header() *PacketHeader
+ Length() int
+}
+
+// PacketSignal describes packets of type PortPacketTypeSignal
+type PacketSignal struct {
+ Hdr PacketHeader
+ Trigger Signals
+ Observed Signals
+ Count uint64
+}
+
+func (s *PacketSignal) Header() *PacketHeader {
+ return &s.Hdr
+}
+
+func (s *PacketSignal) Length() int {
+ return int(unsafe.Sizeof(*s))
+}
+
+type Port Handle
+
+func (p *Port) Handle() *Handle {
+ return (*Handle)(p)
+}
+
+func (p *Port) Close() error {
+ return p.Handle().Close()
+}
+
+// Queue a PortPacket, which may have a varying size.
+func (p *Port) Queue(packet PortPacket) error {
+ if status := Sys_port_queue(Handle(*p), (*int)(unsafe.Pointer(packet.Header()))); status != ErrOk {
+ return &Error{Status: status, Text: "zx.Port.Queue"}
+ }
+ return nil
+}
+
+// Wait for a Packet, which must be as large as the largest
+// possible packet that may be received.
+func (p *Port) Wait(packet *Packet, deadline Time) error {
+ if status := Sys_port_wait(Handle(*p), deadline, (*int)(unsafe.Pointer(packet))); status != ErrOk {
+ return &Error{Status: status, Text: "zx.Port.Wait"}
+ }
+ return nil
+}
+
+func (p *Port) Cancel(source Handle, key uint64) error {
+ if status := Sys_port_cancel(Handle(*p), source, key); status != ErrOk {
+ return &Error{Status: status, Text: "zx.Port.Cancel"}
+ }
+ return nil
+}
+
+func (p *Port) WaitAsync(handle Handle, key uint64, signals Signals, options uint32) error {
+ if status := Sys_object_wait_async(handle, Handle(*p), key, signals, options); status != ErrOk {
+ return &Error{Status: status, Text: "fdio.Port.WaitAsync"}
+ }
+ return nil
+}
+
+func NewPort(options uint32) (Port, error) {
+ var h Handle
+ if status := Sys_port_create(options, &h); status != ErrOk {
+ return Port(HandleInvalid), &Error{Status: status, Text: "zx.Port"}
+ }
+ return Port(h), nil
+}
+
+type VMO Handle
+
+func (vmo *VMO) Handle() *Handle {
+ return (*Handle)(vmo)
+}
+
+func (vmo *VMO) CreateChild(options uint32, offset, size uint64) (VMO, error) {
+ var h Handle
+ if status := Sys_vmo_create_child(Handle(*vmo), options, offset, size, &h); status != ErrOk {
+ return VMO(HandleInvalid), &Error{Status: status, Text: "zx.VMO.CreateChild"}
+ }
+ return VMO(h), nil
+}
+
+func (vmo *VMO) Read(b []byte, offset uint64) error {
+ if status := sys_vmo_read(Handle(*vmo), bytesPtr(b), offset, uint(len(b))); status != ErrOk {
+ return &Error{Status: status, Text: "zx.VMO.Read"}
+ }
+ return nil
+}
+
+func (vmo *VMO) Write(b []byte, offset uint64) error {
+ if status := sys_vmo_write(Handle(*vmo), bytesPtr(b), offset, uint(len(b))); status != ErrOk {
+ return &Error{Status: status, Text: "zx.VMO.Write"}
+ }
+ return nil
+}
+
+func (vmo *VMO) Size() (uint64, error) {
+ var size uint64
+ if status := sys_vmo_get_size(Handle(*vmo), &size); status != ErrOk {
+ return size, &Error{Status: status, Text: "zx.VMO.Size"}
+ }
+ return size, nil
+}
+
+func (vmo *VMO) SetSize(size uint64) error {
+ if status := sys_vmo_set_size(Handle(*vmo), size); status != ErrOk {
+ return &Error{Status: status, Text: "zx.VMO.SetSize"}
+ }
+ return nil
+}
+
+func (vmo *VMO) OpRange(op uint32, offset, size uint64, b []byte) error {
+ if status := sys_vmo_op_range(Handle(*vmo), op, offset, size, bytesPtr(b), uint(len(b))); status != ErrOk {
+ return &Error{Status: status, Text: "zx.VMO.OpRange"}
+ }
+ return nil
+}
+
+func (vmo *VMO) Close() error {
+ return vmo.Handle().Close()
+}
+
+func NewVMO(size uint64, options VMOOption) (VMO, error) {
+ var h Handle
+ if status := Sys_vmo_create(size, uint32(options), &h); status != ErrOk {
+ return VMO(HandleInvalid), &Error{Status: status, Text: "zx.VMO"}
+ }
+ return VMO(h), nil
+}
+
+type VMAR Handle
+
+func (v VMAR) Destroy() error {
+ if status := sys_vmar_destroy(Handle(v)); status != ErrOk {
+ return &Error{Status: status, Text: "zx.VMAR.Destroy"}
+ }
+ return nil
+}
+
+func (v VMAR) Map(vmarOffset uint64, vmo VMO, vmoOffset, len uint64, flags VMFlag) (Vaddr, error) {
+ var addr Vaddr
+ if status := Sys_vmar_map(Handle(v), flags, uint64(vmarOffset), Handle(vmo), vmoOffset, uint64(len), &addr); status != ErrOk {
+ return 0, &Error{Status: status, Text: "zx.VMAR.Map"}
+ }
+ return addr, nil
+}
+
+func (v VMAR) Unmap(addr Vaddr, len uint64) error {
+ if status := Sys_vmar_unmap(Handle(v), addr, uint64(len)); status != ErrOk {
+ return &Error{Status: status, Text: "zx.VMAR.Unmap"}
+ }
+ return nil
+}
+
+func (v VMAR) Protect(addr Vaddr, len uint64, flags VMFlag) error {
+ if status := Sys_vmar_protect(Handle(v), flags, addr, uint64(len)); status != ErrOk {
+ return &Error{Status: status, Text: "zx.VMAR.Protect"}
+ }
+ return nil
+}
+
+func NewVMAR(parent VMAR, offset, size uint64, flags VMFlag) (VMAR, Vaddr, error) {
+ var childHandle Handle
+ var addr Vaddr
+ if status := sys_vmar_allocate(Handle(parent), flags, uint64(offset), uint64(size), &childHandle, &addr); status != ErrOk {
+ return 0, 0, &Error{Status: status, Text: "zx.NewVMAR"}
+ }
+ return VMAR(childHandle), addr, nil
+}
+
+type Log Handle
+
+func NewLog(options uint32) Log {
+ var h Handle
+ status := Sys_debuglog_create(HandleInvalid, options, &h)
+ if status != ErrOk {
+ return Log(HandleInvalid)
+ }
+ return Log(h)
+}
+
+func (l *Log) Handle() *Handle {
+ return (*Handle)(l)
+}
+
+func (l Log) Write(b []byte) (int, error) {
+ if status := Sys_debuglog_write(Handle(l), 0, bytesPtr(b), uint(len(b))); status != ErrOk {
+ return 0, &Error{Status: status, Text: "zx.Log.Write"}
+ }
+ return len(b), nil
+}
+
+func (l Log) Read(b []byte) (int, error) {
+ if status := Sys_debuglog_read(Handle(l), 0, bytesPtr(b), uint(len(b))); status != ErrOk {
+ return 0, &Error{Status: status, Text: "zx.Log.Read"}
+ }
+ return len(b), nil
+}
+
+func (l *Log) Close() error {
+ return l.Handle().Close()
+}
+
+func RandRead(b []byte) {
+ Sys_cprng_draw(bytesPtr(b), uint(len(b)))
+}
+
+// Error is a Status with associated error text.
+// It is used as a Go error.
+type Error struct {
+ Status Status
+ Text string
+}
+
+var _ error = (*Error)(nil)
+
+func (e *Error) Error() string {
+ if e.Text == "" {
+ return "zx.Status: " + e.Status.String()
+ }
+ return e.Status.String() + ": " + e.Text
+}
diff --git a/src/syscall/zx/io/impl.go b/src/syscall/zx/io/impl.go
new file mode 100644
index 0000000..3689868
--- /dev/null
+++ b/src/syscall/zx/io/impl.go
@@ -0,0 +1,3825 @@
+// Copyright 2018 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// GENERATED FILE: Do not edit!
+//
+// To rebuild this file, invoke third_party/go/regen-fidl.
+
+// +build fuchsia
+
+package io
+
+import (
+ _zx "syscall/zx"
+ _bindings "syscall/zx/fidl"
+ fuchsiamem "syscall/zx/mem"
+)
+
+const (
+ // Indicates the file is ready for reading.
+ FileSignalReadable uint32 = 16777216
+ // Indicates the file is ready for writing.
+ FileSignalWritable uint32 = 33554432
+ // Indicates the device is ready for reading.
+ DeviceSignalReadable uint32 = 16777216
+ // Indicates the device is ready for writing.
+ DeviceSignalWritable uint32 = 33554432
+ // Indicates the device has encountered an error state.
+ DeviceSignalError uint32 = 67108864
+ // Indicates the device has hung up on the current connection.
+ DeviceSignalHangup uint32 = 134217728
+ // Indicates an out-of-band state transition has occurred.
+ DeviceSignalOob uint32 = 268435456
+ // Can read from target object.
+ OpenRightReadable uint32 = 1
+ // Can write to target object.
+ OpenRightWritable uint32 = 2
+ // Connection can mount/umount filesystem.
+ OpenRightAdmin uint32 = 4
+ // Create the object if it doesn't exist.
+ OpenFlagCreate uint32 = 65536
+ // (with Create) Fail if the object already exists.
+ OpenFlagCreateIfAbsent uint32 = 131072
+ // Truncate the object before usage.
+ OpenFlagTruncate uint32 = 262144
+ // Assert that the object to be opened is a directory.
+ // Return an error if the target object is not a directory.
+ OpenFlagDirectory uint32 = 524288
+ // Seek to the end of the object before all writes.
+ OpenFlagAppend uint32 = 1048576
+ // If the object is a mount point, open the local directory.
+ OpenFlagNoRemote uint32 = 2097152
+ // Open a reference to the object, not the object itself.
+ // It is ONLY valid to pass the following flags together with OPEN_FLAG_NODE_REFERENCE:
+ // - OPEN_FLAG_DIRECTORY
+ // - OPEN_FLAG_NOT_DIRECTORY
+ // - OPEN_FLAG_DESCRIBE
+ // otherwise an error is returned.
+ // If an object is opened or cloned using this method, the resulting connection does not carry
+ // any permission flags.
+ // The resulting node allows a limited set of operations: |GetAttr|, |Clone|, |Close|, |Describe|,
+ // and, if the node is a file, these extra operations: |GetFlags|, |SetFlags|.
+ OpenFlagNodeReference uint32 = 4194304
+ // Binary OR of OPEN_FLAG_DIRECTORY, OPEN_FLAG_NOT_DIRECTORY, OPEN_FLAG_DESCRIBE, and
+ // OPEN_FLAG_NODE_REFERENCE. Flags used when opening a node reference must fall within this mask.
+ OpenFlagsAllowedWithNodeReference uint32 = 46661632
+ // Requests that an "OnOpen" event is sent to the interface request.
+ // The event will contain a non-null NodeInfo if the open/clone is successful.
+ OpenFlagDescribe uint32 = 8388608
+ // Specify this flag to request POSIX-compatibility. Currently, it affects permission handling.
+ // During Open:
+ // - If the target path is a directory, the rights on the new connection expands to include
+ // OPEN_RIGHT_WRITABLE if and only if the current connection and all intermediate mount points
+ // are writable.
+ // - Otherwise, this flag is ignored. It is an access denied error to request more rights
+ // than those on the current connection, or any intermediate mount points.
+ //
+ // If the posix compatibility flag is not specified, opening always uses the requested rights,
+ // failing the operation with access denied error if requested rights exceeds the rights attached
+ // to the current connection.
+ //
+ // If the requesting connection is read-only and the requested rights are read-only, the flag
+ // may be ignored by the server, and is not forwarded downstream. This is an implementation detail,
+ // necessary to enforce hierarchical permissions across mount points, and should have no effect
+ // on the expected behavior for clients.
+ OpenFlagPosix uint32 = 16777216
+ // Assert that the object to be opened is not a directory.
+ // Return an error if the target object is a directory.
+ OpenFlagNotDirectory uint32 = 33554432
+ // When used during clone, the new connection inherits the rights on the source connection,
+ // regardless if it is a file or directory. Otherwise, clone attempts to use the requested rights.
+ // It is invalid to pass any of the OPEN_RIGHT_* flags together with CLONE_FLAG_SAME_RIGHTS.
+ CloneFlagSameRights uint32 = 67108864
+ // Bits reserved for posix protections. Native fuchsia filesystems
+ // are not required to set bits contained within MODE_PROTECTION_MASK,
+ // but filesystems that wish to do so may refer to sys/stat.h for their
+ // definitions.
+ ModeProtectionMask uint32 = 4095
+ // Bits indicating node type. The canonical mechanism to check
+ // for a node type is to take 'mode', bitwise AND it with the
+ // MODE_TYPE_MASK, and check exact equality against a mode type.
+ ModeTypeMask uint32 = 1044480
+ ModeTypeDirectory uint32 = 16384
+ ModeTypeBlockDevice uint32 = 24576
+ ModeTypeFile uint32 = 32768
+ ModeTypeSocket uint32 = 49152
+ ModeTypeService uint32 = 65536
+ MaxIoctlHandles uint64 = 2
+ // The maximal buffer size which can be transmitted for buffered operations.
+ // This capacity is currently set somewhat arbitrarily.
+ MaxBuf uint64 = 8192
+ // The maximum length, in bytes, of a filesystem string.
+ MaxPath uint64 = 4096
+ // The maximum length, in bytes, of a single filesystem component.
+ MaxFilename uint64 = 255
+ // The fields of 'attributes' which are used to update the Node are indicated
+ // by the 'flags' argument.
+ NodeAttributeFlagCreationTime uint32 = 1
+ NodeAttributeFlagModificationTime uint32 = 2
+ // Requests that the VMO be readable.
+ VmoFlagRead uint32 = 1
+ // Requests that the VMO be writable.
+ VmoFlagWrite uint32 = 2
+ // Requests that the VMO be executable.
+ VmoFlagExec uint32 = 4
+ // Require a copy-on-write clone of the underlying VMO.
+ // The request should fail if the VMO is not cloned.
+ // May not be supplied with fuchsia_io_VMO_FLAG_EXACT.
+ VmoFlagPrivate uint32 = 65536
+ // Require an exact (non-cloned) handle to the underlying VMO.
+ // The request should fail if a handle to the exact VMO is not returned.
+ // May not be supplied with VMO_FLAG_PRIVATE.
+ VmoFlagExact uint32 = 131072
+ // A dirent with an unknown type.
+ DirentTypeUnknown uint8 = 0
+ // A dirent representing a directory object.
+ DirentTypeDirectory uint8 = 4
+ // A dirent representing a block device object.
+ DirentTypeBlockDevice uint8 = 6
+ // A dirent representing a file object.
+ DirentTypeFile uint8 = 8
+ // A dirent representing a socket object.
+ DirentTypeSocket uint8 = 12
+ // A dirent representing a service object.
+ DirentTypeService uint8 = 16
+ // Nodes which do not have ino values should return this value
+ // from Readdir and GetAttr.
+ InoUnknown uint64 = 18446744073709551615
+ // Indicates the directory being watched has been deleted.
+ WatchEventDeleted uint8 = 0
+ // Indicates a node has been created (either new or moved) into a directory.
+ WatchEventAdded uint8 = 1
+ // Identifies a node has been removed (either deleted or moved) from the directory.
+ WatchEventRemoved uint8 = 2
+ // Identifies a node already existed in the directory when watching started.
+ WatchEventExisting uint8 = 3
+ // Identifies that no more WATCH_EVENT_EXISTING events will be sent.
+ WatchEventIdle uint8 = 4
+ // Used by Directory::Watch. Requests transmission of WATCH_EVENT_DELETED.
+ WatchMaskDeleted uint32 = 1
+ // Used by Directory::Watch. Requests transmission of WATCH_EVENT_ADDED.
+ WatchMaskAdded uint32 = 2
+ // Used by Directory::Watch. Requests transmission of WATCH_EVENT_REMOVED.
+ WatchMaskRemoved uint32 = 4
+ // Used by Directory::Watch. Requests transmission of WATCH_EVENT_EXISTING.
+ WatchMaskExisting uint32 = 8
+ // Used by Directory::Watch. Requests transmission of WATCH_EVENT_IDLE.
+ WatchMaskIdle uint32 = 16
+ // Used by Directory::Watch. Requests transmission of all watcher events.
+ WatchMaskAll uint32 = 31
+ MountCreateFlagReplace uint32 = 1
+ MaxFsNameBuffer uint64 = 32
+)
+
+// Update the Seek offset.
+type SeekOrigin uint32
+
+const (
+ SeekOriginStart SeekOrigin = 0
+ SeekOriginCurrent SeekOrigin = 1
+ SeekOriginEnd SeekOrigin = 2
+)
+
+func (x SeekOrigin) String() string {
+ switch x {
+ case 0:
+ return "Start"
+ case 1:
+ return "Current"
+ case 2:
+ return "End"
+ }
+ return "Unknown"
+}
+
+// The default protocol, interface information must be acquired some
+// other way.
+type Service struct {
+ _ struct{} `fidl2:"s,1,1"`
+}
+
+var _mService = _bindings.CreateLazyMarshaler(Service{})
+
+func (msg *Service) Marshaler() _bindings.Marshaler {
+ return _mService
+}
+
+// The object may be cast to interface 'File'.
+type FileObject struct {
+ _ struct{} `fidl2:"s,4,4"`
+ // An optional event which transmits information about an object's readability
+ // or writability. This event relays information about the underlying object, not
+ // the capability granted to client: this event may be signalled "readable" on a
+ // connection that does not have the capability to read.
+ //
+ // The "FILE_SIGNAL_" values may be observed on this event.
+ Event _zx.Event `fidl:"*" fidl2:"1"`
+}
+
+var _mFileObject = _bindings.CreateLazyMarshaler(FileObject{})
+
+func (msg *FileObject) Marshaler() _bindings.Marshaler {
+ return _mFileObject
+}
+
+// The object may be cast to interface 'Directory'.
+type DirectoryObject struct {
+ _ struct{} `fidl2:"s,1,1"`
+}
+
+var _mDirectoryObject = _bindings.CreateLazyMarshaler(DirectoryObject{})
+
+func (msg *DirectoryObject) Marshaler() _bindings.Marshaler {
+ return _mDirectoryObject
+}
+
+// The object is accompanied by a pipe.
+type Pipe struct {
+ _ struct{} `fidl2:"s,4,4"`
+ Socket _zx.Socket `fidl2:"0"`
+}
+
+var _mPipe = _bindings.CreateLazyMarshaler(Pipe{})
+
+func (msg *Pipe) Marshaler() _bindings.Marshaler {
+ return _mPipe
+}
+
+// The object is a file which is represented as an immutable VMO.
+// Although a VMO is returned as a part of this structure, this underlying object
+// may represent multiple Vmofiles. To identify the logical portion of the VMO
+// that represents the single file, an offset and length parameter are also supplied.
+type Vmofile struct {
+ _ struct{} `fidl2:"s,24,8"`
+ // The VMO which backs this file.
+ Vmo _zx.VMO `fidl2:"0"`
+ // The index into |vmo| which represents the first byte of the file.
+ Offset uint64
+ // The number of bytes, starting at |offset|, which may be used to represent this file.
+ Length uint64
+}
+
+var _mVmofile = _bindings.CreateLazyMarshaler(Vmofile{})
+
+func (msg *Vmofile) Marshaler() _bindings.Marshaler {
+ return _mVmofile
+}
+
+// The object may be cast to interface 'Device'.
+type Device struct {
+ _ struct{} `fidl2:"s,4,4"`
+ // An optional event which transmits information about a device's state.
+ //
+ // The "DEVICE_SIGNAL_" values may be observed on this event.
+ Event _zx.Event `fidl:"*" fidl2:"1"`
+}
+
+var _mDevice = _bindings.CreateLazyMarshaler(Device{})
+
+func (msg *Device) Marshaler() _bindings.Marshaler {
+ return _mDevice
+}
+
+// The object may be cast to interface 'Tty'
+type Tty struct {
+ _ struct{} `fidl2:"s,4,4"`
+ Event _zx.Event `fidl:"*" fidl2:"1"`
+}
+
+var _mTty = _bindings.CreateLazyMarshaler(Tty{})
+
+func (msg *Tty) Marshaler() _bindings.Marshaler {
+ return _mTty
+}
+
+// NodeAttributes defines generic information about a filesystem node.
+type NodeAttributes struct {
+ _ struct{} `fidl2:"s,56,8"`
+ // Protection bits and node type information describe in 'mode'.
+ Mode uint32
+ // A filesystem-unique ID.
+ Id uint64
+ // Node size, in bytes.
+ ContentSize uint64
+ // Space needed to store node (possibly larger than size), in bytes.
+ StorageSize uint64
+ // Hard link count.
+ LinkCount uint64
+ // Time of creation (may be updated manually after creation) in ns since Unix epoch, UTC.
+ CreationTime uint64
+ // Time of last modification in ns since Unix epoch, UTC.
+ ModificationTime uint64
+}
+
+var _mNodeAttributes = _bindings.CreateLazyMarshaler(NodeAttributes{})
+
+func (msg *NodeAttributes) Marshaler() _bindings.Marshaler {
+ return _mNodeAttributes
+}
+
+// TODO(ZX-2645): Unused.
+//
+// WatchedEvent describes events returned from a DirectoryWatcher.
+type WatchedEvent struct {
+ _ struct{} `fidl2:"s,24,8"`
+ Event uint8
+ Len uint8
+ Name []uint8 `fidl:"255" fidl2:"255"`
+}
+
+var _mWatchedEvent = _bindings.CreateLazyMarshaler(WatchedEvent{})
+
+func (msg *WatchedEvent) Marshaler() _bindings.Marshaler {
+ return _mWatchedEvent
+}
+
+type FilesystemInfo struct {
+ _ struct{} `fidl2:"s,96,8"`
+ // The number of data bytes which may be stored in a filesystem.
+ TotalBytes uint64
+ // The number of data bytes which are in use by the filesystem.
+ UsedBytes uint64
+ // The number of nodes which may be stored in the filesystem.
+ TotalNodes uint64
+ // The number of nodes used by the filesystem.
+ UsedNodes uint64
+ // The amount of space which may be allocated from the underlying
+ // volume manager. If unsupported, this will be zero.
+ FreeSharedPoolBytes uint64
+ // A unique identifier for this filesystem instance. Will not be preserved
+ // across reboots.
+ FsId uint64
+ // The size of a single filesystem block.
+ BlockSize uint32
+ // The maximum length of a filesystem name.
+ MaxFilenameSize uint32
+ // A unique identifier for the type of the underlying filesystem.
+ FsType uint32
+ Padding uint32
+ // TODO(smklein): Replace this field with a string when supported
+ // by the "Simple" interface. At the moment, name is a fixed-size,
+ // null-terminated buffer.
+ Name [32]int8
+}
+
+var _mFilesystemInfo = _bindings.CreateLazyMarshaler(FilesystemInfo{})
+
+func (msg *FilesystemInfo) Marshaler() _bindings.Marshaler {
+ return _mFilesystemInfo
+}
+
+type NodeInfoTag uint32
+
+const (
+ _ NodeInfoTag = iota
+ NodeInfoService
+ NodeInfoFile
+ NodeInfoDirectory
+ NodeInfoPipe
+ NodeInfoVmofile
+ NodeInfoDevice
+ NodeInfoTty
+)
+
+// Describes how the connection to an should be handled, as well as
+// how to interpret the optional handle.
+//
+// Refer to |Node::Describe()| and |Node::OnOpen()| for usage.
+type NodeInfo struct {
+ NodeInfoTag `fidl:"tag" fidl2:"u,32,8"`
+ Service Service
+ File FileObject
+ Directory DirectoryObject
+ Pipe Pipe
+ Vmofile Vmofile
+ Device Device
+ Tty Tty
+}
+
+func (u *NodeInfo) Which() NodeInfoTag {
+ return u.NodeInfoTag
+}
+
+func (u *NodeInfo) SetService(service Service) {
+ u.NodeInfoTag = NodeInfoService
+ u.Service = service
+}
+
+func (u *NodeInfo) SetFile(file FileObject) {
+ u.NodeInfoTag = NodeInfoFile
+ u.File = file
+}
+
+func (u *NodeInfo) SetDirectory(directory DirectoryObject) {
+ u.NodeInfoTag = NodeInfoDirectory
+ u.Directory = directory
+}
+
+func (u *NodeInfo) SetPipe(pipe Pipe) {
+ u.NodeInfoTag = NodeInfoPipe
+ u.Pipe = pipe
+}
+
+func (u *NodeInfo) SetVmofile(vmofile Vmofile) {
+ u.NodeInfoTag = NodeInfoVmofile
+ u.Vmofile = vmofile
+}
+
+func (u *NodeInfo) SetDevice(device Device) {
+ u.NodeInfoTag = NodeInfoDevice
+ u.Device = device
+}
+
+func (u *NodeInfo) SetTty(tty Tty) {
+ u.NodeInfoTag = NodeInfoTty
+ u.Tty = tty
+}
+
+const (
+ NodeCloneOrdinal uint32 = 402549324
+ NodeCloneGenOrdinal uint32 = 402549324
+ NodeCloseOrdinal uint32 = 1387878023
+ NodeCloseGenOrdinal uint32 = 1387878023
+ NodeDescribeOrdinal uint32 = 526573406
+ NodeDescribeGenOrdinal uint32 = 526573406
+ NodeOnOpenOrdinal uint32 = 1191225277
+ NodeOnOpenGenOrdinal uint32 = 1191225277
+ NodeSyncOrdinal uint32 = 1648508842
+ NodeSyncGenOrdinal uint32 = 1648508842
+ NodeGetAttrOrdinal uint32 = 1166403528
+ NodeGetAttrGenOrdinal uint32 = 1166403528
+ NodeSetAttrOrdinal uint32 = 198530458
+ NodeSetAttrGenOrdinal uint32 = 198530458
+ NodeIoctlOrdinal uint32 = 905161895
+ NodeIoctlGenOrdinal uint32 = 905161895
+)
+
+type nodeCloneRequest struct {
+ _ struct{} `fidl2:"s,8,0"`
+ Flags uint32
+ Object NodeInterfaceRequest `fidl2:"0"`
+}
+
+var _mnodeCloneRequest = _bindings.CreateLazyMarshaler(nodeCloneRequest{})
+
+func (msg *nodeCloneRequest) Marshaler() _bindings.Marshaler {
+ return _mnodeCloneRequest
+}
+
+type nodeCloseResponse struct {
+ _ struct{} `fidl2:"s,8,0"`
+ S int32
+}
+
+var _mnodeCloseResponse = _bindings.CreateLazyMarshaler(nodeCloseResponse{})
+
+func (msg *nodeCloseResponse) Marshaler() _bindings.Marshaler {
+ return _mnodeCloseResponse
+}
+
+type nodeDescribeResponse struct {
+ _ struct{} `fidl2:"s,32,0"`
+ Info NodeInfo
+}
+
+var _mnodeDescribeResponse = _bindings.CreateLazyMarshaler(nodeDescribeResponse{})
+
+func (msg *nodeDescribeResponse) Marshaler() _bindings.Marshaler {
+ return _mnodeDescribeResponse
+}
+
+type nodeOnOpenResponse struct {
+ _ struct{} `fidl2:"s,16,0"`
+ S int32
+ Info *NodeInfo
+}
+
+var _mnodeOnOpenResponse = _bindings.CreateLazyMarshaler(nodeOnOpenResponse{})
+
+func (msg *nodeOnOpenResponse) Marshaler() _bindings.Marshaler {
+ return _mnodeOnOpenResponse
+}
+
+type nodeSyncResponse struct {
+ _ struct{} `fidl2:"s,8,0"`
+ S int32
+}
+
+var _mnodeSyncResponse = _bindings.CreateLazyMarshaler(nodeSyncResponse{})
+
+func (msg *nodeSyncResponse) Marshaler() _bindings.Marshaler {
+ return _mnodeSyncResponse
+}
+
+type nodeGetAttrResponse struct {
+ _ struct{} `fidl2:"s,64,0"`
+ S int32
+ Attributes NodeAttributes
+}
+
+var _mnodeGetAttrResponse = _bindings.CreateLazyMarshaler(nodeGetAttrResponse{})
+
+func (msg *nodeGetAttrResponse) Marshaler() _bindings.Marshaler {
+ return _mnodeGetAttrResponse
+}
+
+type nodeSetAttrRequest struct {
+ _ struct{} `fidl2:"s,64,0"`
+ Flags uint32
+ Attributes NodeAttributes
+}
+
+var _mnodeSetAttrRequest = _bindings.CreateLazyMarshaler(nodeSetAttrRequest{})
+
+func (msg *nodeSetAttrRequest) Marshaler() _bindings.Marshaler {
+ return _mnodeSetAttrRequest
+}
+
+type nodeSetAttrResponse struct {
+ _ struct{} `fidl2:"s,8,0"`
+ S int32
+}
+
+var _mnodeSetAttrResponse = _bindings.CreateLazyMarshaler(nodeSetAttrResponse{})
+
+func (msg *nodeSetAttrResponse) Marshaler() _bindings.Marshaler {
+ return _mnodeSetAttrResponse
+}
+
+type nodeIoctlRequest struct {
+ _ struct{} `fidl2:"s,48,0"`
+ Opcode uint32
+ MaxOut uint64
+ Handles []_zx.Handle `fidl:"2" fidl2:"2,0"`
+ In []uint8 `fidl:"8192" fidl2:"8192"`
+}
+
+var _mnodeIoctlRequest = _bindings.CreateLazyMarshaler(nodeIoctlRequest{})
+
+func (msg *nodeIoctlRequest) Marshaler() _bindings.Marshaler {
+ return _mnodeIoctlRequest
+}
+
+type nodeIoctlResponse struct {
+ _ struct{} `fidl2:"s,40,0"`
+ S int32
+ Handles []_zx.Handle `fidl:"2" fidl2:"2,0"`
+ Out []uint8 `fidl:"8192" fidl2:"8192"`
+}
+
+var _mnodeIoctlResponse = _bindings.CreateLazyMarshaler(nodeIoctlResponse{})
+
+func (msg *nodeIoctlResponse) Marshaler() _bindings.Marshaler {
+ return _mnodeIoctlResponse
+}
+
+type NodeInterface _bindings.ChannelProxy
+
+// Create another connection to the same remote object.
+//
+// |flags| may be any of:
+// - OPEN_RIGHT_*
+// - OPEN_FLAG_APPEND
+// - OPEN_FLAG_NO_REMOTE
+// - OPEN_FLAG_DESCRIBE
+// - CLONE_FLAG_SAME_RIGHTS
+//
+// All other flags are ignored.
+//
+// The OPEN_RIGHT_* bits in |flags| request corresponding rights over the resulting
+// cloned object.
+// The cloned object must have rights less than or equal to the original object.
+// Alternatively, pass CLONE_FLAG_SAME_RIGHTS to inherit the rights on the source connection.
+// It is invalid to pass any of the OPEN_RIGHT_* flags together with CLONE_FLAG_SAME_RIGHTS.
+func (p *NodeInterface) Clone(flags uint32, object NodeInterfaceRequest) error {
+ req_ := &nodeCloneRequest{
+ Flags: flags,
+ Object: object,
+ }
+ err := ((*_bindings.ChannelProxy)(p)).SendNew(NodeCloneOrdinal, req_)
+ return err
+}
+
+// Terminates connection with object.
+//
+// This method does not require any rights.
+func (p *NodeInterface) Close() (int32, error) {
+ var req_ _bindings.Message
+ resp_ := &nodeCloseResponse{}
+ err := ((*_bindings.ChannelProxy)(p)).CallNew(NodeCloseOrdinal, req_, resp_)
+ return resp_.S, err
+}
+
+// Returns extra information about the type of the object.
+// If the |Describe| operation fails, the connection is closed.
+//
+// This method does not require any rights.
+func (p *NodeInterface) Describe() (NodeInfo, error) {
+ var req_ _bindings.Message
+ resp_ := &nodeDescribeResponse{}
+ err := ((*_bindings.ChannelProxy)(p)).CallNew(NodeDescribeOrdinal, req_, resp_)
+ return resp_.Info, err
+}
+
+// An event produced eagerly by a FIDL server if requested by |OPEN_FLAG_DESCRIBE|.
+//
+// Indicates the success or failure of the open operation, and optionally describes the
+// object. If the status is |ZX_OK|, |info| contains descriptive information about the object
+// (the same as would be returned by |Describe|).
+func (p *NodeInterface) ExpectOnOpen() (int32, *NodeInfo, error) {
+ resp_ := &nodeOnOpenResponse{}
+ err := ((*_bindings.ChannelProxy)(p)).RecvNew(NodeOnOpenOrdinal, resp_)
+ return resp_.S, resp_.Info, err
+}
+
+// Synchronizes updates to the node to the underlying media, if it exists.
+//
+// This method does not require any rights.
+func (p *NodeInterface) Sync() (int32, error) {
+ var req_ _bindings.Message
+ resp_ := &nodeSyncResponse{}
+ err := ((*_bindings.ChannelProxy)(p)).CallNew(NodeSyncOrdinal, req_, resp_)
+ return resp_.S, err
+}
+
+// Acquires information about the node.
+//
+// This method does not require any rights.
+func (p *NodeInterface) GetAttr() (int32, NodeAttributes, error) {
+ var req_ _bindings.Message
+ resp_ := &nodeGetAttrResponse{}
+ err := ((*_bindings.ChannelProxy)(p)).CallNew(NodeGetAttrOrdinal, req_, resp_)
+ return resp_.S, resp_.Attributes, err
+}
+
+// Updates information about the node.
+// |flags| may be any of NODE_ATTRIBUTE_FLAG_*.
+//
+// This method requires following rights: OPEN_RIGHT_WRITABLE.
+func (p *NodeInterface) SetAttr(flags uint32, attributes NodeAttributes) (int32, error) {
+ req_ := &nodeSetAttrRequest{
+ Flags: flags,
+ Attributes: attributes,
+ }
+ resp_ := &nodeSetAttrResponse{}
+ err := ((*_bindings.ChannelProxy)(p)).CallNew(NodeSetAttrOrdinal, req_, resp_)
+ return resp_.S, err
+}
+
+// Deprecated. Only for use with compatibility with devhost.
+func (p *NodeInterface) Ioctl(opcode uint32, maxOut uint64, handles []_zx.Handle, in []uint8) (int32, []_zx.Handle, []uint8, error) {
+ req_ := &nodeIoctlRequest{
+ Opcode: opcode,
+ MaxOut: maxOut,
+ Handles: handles,
+ In: in,
+ }
+ resp_ := &nodeIoctlResponse{}
+ err := ((*_bindings.ChannelProxy)(p)).CallNew(NodeIoctlOrdinal, req_, resp_)
+ return resp_.S, resp_.Handles, resp_.Out, err
+}
+
+// Node defines the minimal interface for entities which can be accessed in a filesystem.
+type Node interface {
+ // Create another connection to the same remote object.
+ //
+ // |flags| may be any of:
+ // - OPEN_RIGHT_*
+ // - OPEN_FLAG_APPEND
+ // - OPEN_FLAG_NO_REMOTE
+ // - OPEN_FLAG_DESCRIBE
+ // - CLONE_FLAG_SAME_RIGHTS
+ //
+ // All other flags are ignored.
+ //
+ // The OPEN_RIGHT_* bits in |flags| request corresponding rights over the resulting
+ // cloned object.
+ // The cloned object must have rights less than or equal to the original object.
+ // Alternatively, pass CLONE_FLAG_SAME_RIGHTS to inherit the rights on the source connection.
+ // It is invalid to pass any of the OPEN_RIGHT_* flags together with CLONE_FLAG_SAME_RIGHTS.
+ Clone(flags uint32, object NodeInterfaceRequest) error
+ // Terminates connection with object.
+ //
+ // This method does not require any rights.
+ Close() (int32, error)
+ // Returns extra information about the type of the object.
+ // If the |Describe| operation fails, the connection is closed.
+ //
+ // This method does not require any rights.
+ Describe() (NodeInfo, error)
+ // An event produced eagerly by a FIDL server if requested by |OPEN_FLAG_DESCRIBE|.
+ //
+ // Indicates the success or failure of the open operation, and optionally describes the
+ // object. If the status is |ZX_OK|, |info| contains descriptive information about the object
+ // (the same as would be returned by |Describe|).
+ // Synchronizes updates to the node to the underlying media, if it exists.
+ //
+ // This method does not require any rights.
+ Sync() (int32, error)
+ // Acquires information about the node.
+ //
+ // This method does not require any rights.
+ GetAttr() (int32, NodeAttributes, error)
+ // Updates information about the node.
+ // |flags| may be any of NODE_ATTRIBUTE_FLAG_*.
+ //
+ // This method requires following rights: OPEN_RIGHT_WRITABLE.
+ SetAttr(flags uint32, attributes NodeAttributes) (int32, error)
+ // Deprecated. Only for use with compatibility with devhost.
+ Ioctl(opcode uint32, maxOut uint64, handles []_zx.Handle, in []uint8) (int32, []_zx.Handle, []uint8, error)
+}
+
+type NodeTransitionalBase struct{}
+
+type NodeInterfaceRequest _bindings.InterfaceRequest
+
+func NewNodeInterfaceRequest() (NodeInterfaceRequest, *NodeInterface, error) {
+ req, cli, err := _bindings.NewInterfaceRequest()
+ return NodeInterfaceRequest(req), (*NodeInterface)(cli), err
+}
+
+type NodeStub struct {
+ Impl Node
+}
+
+func (s *NodeStub) DispatchNew(ord uint32, b_ []byte, h_ []_zx.Handle) (_bindings.Message, error) {
+ switch ord {
+ case NodeCloneOrdinal:
+ in_ := nodeCloneRequest{}
+ if _, _, err_ := _bindings.UnmarshalNew(b_, h_, &in_); err_ != nil {
+ return nil, err_
+ }
+ err_ := s.Impl.Clone(in_.Flags, in_.Object)
+ return nil, err_
+ case NodeCloseOrdinal:
+ s, err_ := s.Impl.Close()
+ out_ := nodeCloseResponse{}
+ out_.S = s
+ return &out_, err_
+ case NodeDescribeOrdinal:
+ info, err_ := s.Impl.Describe()
+ out_ := nodeDescribeResponse{}
+ out_.Info = info
+ return &out_, err_
+ case NodeSyncOrdinal:
+ s, err_ := s.Impl.Sync()
+ out_ := nodeSyncResponse{}
+ out_.S = s
+ return &out_, err_
+ case NodeGetAttrOrdinal:
+ s, attributes, err_ := s.Impl.GetAttr()
+ out_ := nodeGetAttrResponse{}
+ out_.S = s
+ out_.Attributes = attributes
+ return &out_, err_
+ case NodeSetAttrOrdinal:
+ in_ := nodeSetAttrRequest{}
+ if _, _, err_ := _bindings.UnmarshalNew(b_, h_, &in_); err_ != nil {
+ return nil, err_
+ }
+ s, err_ := s.Impl.SetAttr(in_.Flags, in_.Attributes)
+ out_ := nodeSetAttrResponse{}
+ out_.S = s
+ return &out_, err_
+ case NodeIoctlOrdinal:
+ in_ := nodeIoctlRequest{}
+ if _, _, err_ := _bindings.UnmarshalNew(b_, h_, &in_); err_ != nil {
+ return nil, err_
+ }
+ s, handles, out, err_ := s.Impl.Ioctl(in_.Opcode, in_.MaxOut, in_.Handles, in_.In)
+ out_ := nodeIoctlResponse{}
+ out_.S = s
+ out_.Handles = handles
+ out_.Out = out
+ return &out_, err_
+ }
+ return nil, _bindings.ErrUnknownOrdinal
+}
+
+type NodeService struct {
+ _bindings.BindingSet
+}
+
+func (s *NodeService) Add(impl Node, c _zx.Channel, onError func(error)) (_bindings.BindingKey, error) {
+ return s.BindingSet.Add(&NodeStub{Impl: impl}, c, onError)
+}
+
+func (s *NodeService) EventProxyFor(key _bindings.BindingKey) (*NodeEventProxy, bool) {
+ pxy, err := s.BindingSet.ProxyFor(key)
+ return (*NodeEventProxy)(pxy), err
+}
+
+type NodeEventProxy _bindings.ChannelProxy
+
+func (p *NodeEventProxy) OnOpen(s int32, info *NodeInfo) error {
+ event_ := &nodeOnOpenResponse{
+ S: s,
+ Info: info,
+ }
+ return ((*_bindings.ChannelProxy)(p)).SendNew(NodeOnOpenOrdinal, event_)
+}
+
+const (
+ FileCloneOrdinal uint32 = 402549324
+ FileCloneGenOrdinal uint32 = 402549324
+ FileCloseOrdinal uint32 = 1387878023
+ FileCloseGenOrdinal uint32 = 1387878023
+ FileDescribeOrdinal uint32 = 526573406
+ FileDescribeGenOrdinal uint32 = 526573406
+ FileOnOpenOrdinal uint32 = 1191225277
+ FileOnOpenGenOrdinal uint32 = 1191225277
+ FileSyncOrdinal uint32 = 1648508842
+ FileSyncGenOrdinal uint32 = 1648508842
+ FileGetAttrOrdinal uint32 = 1166403528
+ FileGetAttrGenOrdinal uint32 = 1166403528
+ FileSetAttrOrdinal uint32 = 198530458
+ FileSetAttrGenOrdinal uint32 = 198530458
+ FileIoctlOrdinal uint32 = 905161895
+ FileIoctlGenOrdinal uint32 = 905161895
+ FileReadOrdinal uint32 = 636961156
+ FileReadGenOrdinal uint32 = 636961156
+ FileReadAtOrdinal uint32 = 2087865796
+ FileReadAtGenOrdinal uint32 = 2087865796
+ FileWriteOrdinal uint32 = 85125024
+ FileWriteGenOrdinal uint32 = 85125024
+ FileWriteAtOrdinal uint32 = 1045766885
+ FileWriteAtGenOrdinal uint32 = 1045766885
+ FileSeekOrdinal uint32 = 2016048965
+ FileSeekGenOrdinal uint32 = 2016048965
+ FileTruncateOrdinal uint32 = 1118517818
+ FileTruncateGenOrdinal uint32 = 1118517818
+ FileGetFlagsOrdinal uint32 = 1679205366
+ FileGetFlagsGenOrdinal uint32 = 1679205366
+ FileSetFlagsOrdinal uint32 = 1059310710
+ FileSetFlagsGenOrdinal uint32 = 1059310710
+ FileGetBufferOrdinal uint32 = 1958938995
+ FileGetBufferGenOrdinal uint32 = 1958938995
+)
+
+type fileCloneRequest struct {
+ _ struct{} `fidl2:"s,8,0"`
+ Flags uint32
+ Object NodeInterfaceRequest `fidl2:"0"`
+}
+
+var _mfileCloneRequest = _bindings.CreateLazyMarshaler(fileCloneRequest{})
+
+func (msg *fileCloneRequest) Marshaler() _bindings.Marshaler {
+ return _mfileCloneRequest
+}
+
+type fileCloseResponse struct {
+ _ struct{} `fidl2:"s,8,0"`
+ S int32
+}
+
+var _mfileCloseResponse = _bindings.CreateLazyMarshaler(fileCloseResponse{})
+
+func (msg *fileCloseResponse) Marshaler() _bindings.Marshaler {
+ return _mfileCloseResponse
+}
+
+type fileDescribeResponse struct {
+ _ struct{} `fidl2:"s,32,0"`
+ Info NodeInfo
+}
+
+var _mfileDescribeResponse = _bindings.CreateLazyMarshaler(fileDescribeResponse{})
+
+func (msg *fileDescribeResponse) Marshaler() _bindings.Marshaler {
+ return _mfileDescribeResponse
+}
+
+type fileOnOpenResponse struct {
+ _ struct{} `fidl2:"s,16,0"`
+ S int32
+ Info *NodeInfo
+}
+
+var _mfileOnOpenResponse = _bindings.CreateLazyMarshaler(fileOnOpenResponse{})
+
+func (msg *fileOnOpenResponse) Marshaler() _bindings.Marshaler {
+ return _mfileOnOpenResponse
+}
+
+type fileSyncResponse struct {
+ _ struct{} `fidl2:"s,8,0"`
+ S int32
+}
+
+var _mfileSyncResponse = _bindings.CreateLazyMarshaler(fileSyncResponse{})
+
+func (msg *fileSyncResponse) Marshaler() _bindings.Marshaler {
+ return _mfileSyncResponse
+}
+
+type fileGetAttrResponse struct {
+ _ struct{} `fidl2:"s,64,0"`
+ S int32
+ Attributes NodeAttributes
+}
+
+var _mfileGetAttrResponse = _bindings.CreateLazyMarshaler(fileGetAttrResponse{})
+
+func (msg *fileGetAttrResponse) Marshaler() _bindings.Marshaler {
+ return _mfileGetAttrResponse
+}
+
+type fileSetAttrRequest struct {
+ _ struct{} `fidl2:"s,64,0"`
+ Flags uint32
+ Attributes NodeAttributes
+}
+
+var _mfileSetAttrRequest = _bindings.CreateLazyMarshaler(fileSetAttrRequest{})
+
+func (msg *fileSetAttrRequest) Marshaler() _bindings.Marshaler {
+ return _mfileSetAttrRequest
+}
+
+type fileSetAttrResponse struct {
+ _ struct{} `fidl2:"s,8,0"`
+ S int32
+}
+
+var _mfileSetAttrResponse = _bindings.CreateLazyMarshaler(fileSetAttrResponse{})
+
+func (msg *fileSetAttrResponse) Marshaler() _bindings.Marshaler {
+ return _mfileSetAttrResponse
+}
+
+type fileIoctlRequest struct {
+ _ struct{} `fidl2:"s,48,0"`
+ Opcode uint32
+ MaxOut uint64
+ Handles []_zx.Handle `fidl:"2" fidl2:"2,0"`
+ In []uint8 `fidl:"8192" fidl2:"8192"`
+}
+
+var _mfileIoctlRequest = _bindings.CreateLazyMarshaler(fileIoctlRequest{})
+
+func (msg *fileIoctlRequest) Marshaler() _bindings.Marshaler {
+ return _mfileIoctlRequest
+}
+
+type fileIoctlResponse struct {
+ _ struct{} `fidl2:"s,40,0"`
+ S int32
+ Handles []_zx.Handle `fidl:"2" fidl2:"2,0"`
+ Out []uint8 `fidl:"8192" fidl2:"8192"`
+}
+
+var _mfileIoctlResponse = _bindings.CreateLazyMarshaler(fileIoctlResponse{})
+
+func (msg *fileIoctlResponse) Marshaler() _bindings.Marshaler {
+ return _mfileIoctlResponse
+}
+
+type fileReadRequest struct {
+ _ struct{} `fidl2:"s,8,0"`
+ Count uint64
+}
+
+var _mfileReadRequest = _bindings.CreateLazyMarshaler(fileReadRequest{})
+
+func (msg *fileReadRequest) Marshaler() _bindings.Marshaler {
+ return _mfileReadRequest
+}
+
+type fileReadResponse struct {
+ _ struct{} `fidl2:"s,24,0"`
+ S int32
+ Data []uint8 `fidl:"8192" fidl2:"8192"`
+}
+
+var _mfileReadResponse = _bindings.CreateLazyMarshaler(fileReadResponse{})
+
+func (msg *fileReadResponse) Marshaler() _bindings.Marshaler {
+ return _mfileReadResponse
+}
+
+type fileReadAtRequest struct {
+ _ struct{} `fidl2:"s,16,0"`
+ Count uint64
+ Offset uint64
+}
+
+var _mfileReadAtRequest = _bindings.CreateLazyMarshaler(fileReadAtRequest{})
+
+func (msg *fileReadAtRequest) Marshaler() _bindings.Marshaler {
+ return _mfileReadAtRequest
+}
+
+type fileReadAtResponse struct {
+ _ struct{} `fidl2:"s,24,0"`
+ S int32
+ Data []uint8 `fidl:"8192" fidl2:"8192"`
+}
+
+var _mfileReadAtResponse = _bindings.CreateLazyMarshaler(fileReadAtResponse{})
+
+func (msg *fileReadAtResponse) Marshaler() _bindings.Marshaler {
+ return _mfileReadAtResponse
+}
+
+type fileWriteRequest struct {
+ _ struct{} `fidl2:"s,16,0"`
+ Data []uint8 `fidl:"8192" fidl2:"8192"`
+}
+
+var _mfileWriteRequest = _bindings.CreateLazyMarshaler(fileWriteRequest{})
+
+func (msg *fileWriteRequest) Marshaler() _bindings.Marshaler {
+ return _mfileWriteRequest
+}
+
+type fileWriteResponse struct {
+ _ struct{} `fidl2:"s,16,0"`
+ S int32
+ Actual uint64
+}
+
+var _mfileWriteResponse = _bindings.CreateLazyMarshaler(fileWriteResponse{})
+
+func (msg *fileWriteResponse) Marshaler() _bindings.Marshaler {
+ return _mfileWriteResponse
+}
+
+type fileWriteAtRequest struct {
+ _ struct{} `fidl2:"s,24,0"`
+ Data []uint8 `fidl:"8192" fidl2:"8192"`
+ Offset uint64
+}
+
+var _mfileWriteAtRequest = _bindings.CreateLazyMarshaler(fileWriteAtRequest{})
+
+func (msg *fileWriteAtRequest) Marshaler() _bindings.Marshaler {
+ return _mfileWriteAtRequest
+}
+
+type fileWriteAtResponse struct {
+ _ struct{} `fidl2:"s,16,0"`
+ S int32
+ Actual uint64
+}
+
+var _mfileWriteAtResponse = _bindings.CreateLazyMarshaler(fileWriteAtResponse{})
+
+func (msg *fileWriteAtResponse) Marshaler() _bindings.Marshaler {
+ return _mfileWriteAtResponse
+}
+
+type fileSeekRequest struct {
+ _ struct{} `fidl2:"s,16,0"`
+ Offset int64
+ Start SeekOrigin
+}
+
+var _mfileSeekRequest = _bindings.CreateLazyMarshaler(fileSeekRequest{})
+
+func (msg *fileSeekRequest) Marshaler() _bindings.Marshaler {
+ return _mfileSeekRequest
+}
+
+type fileSeekResponse struct {
+ _ struct{} `fidl2:"s,16,0"`
+ S int32
+ Offset uint64
+}
+
+var _mfileSeekResponse = _bindings.CreateLazyMarshaler(fileSeekResponse{})
+
+func (msg *fileSeekResponse) Marshaler() _bindings.Marshaler {
+ return _mfileSeekResponse
+}
+
+type fileTruncateRequest struct {
+ _ struct{} `fidl2:"s,8,0"`
+ Length uint64
+}
+
+var _mfileTruncateRequest = _bindings.CreateLazyMarshaler(fileTruncateRequest{})
+
+func (msg *fileTruncateRequest) Marshaler() _bindings.Marshaler {
+ return _mfileTruncateRequest
+}
+
+type fileTruncateResponse struct {
+ _ struct{} `fidl2:"s,8,0"`
+ S int32
+}
+
+var _mfileTruncateResponse = _bindings.CreateLazyMarshaler(fileTruncateResponse{})
+
+func (msg *fileTruncateResponse) Marshaler() _bindings.Marshaler {
+ return _mfileTruncateResponse
+}
+
+type fileGetFlagsResponse struct {
+ _ struct{} `fidl2:"s,8,0"`
+ S int32
+ Flags uint32
+}
+
+var _mfileGetFlagsResponse = _bindings.CreateLazyMarshaler(fileGetFlagsResponse{})
+
+func (msg *fileGetFlagsResponse) Marshaler() _bindings.Marshaler {
+ return _mfileGetFlagsResponse
+}
+
+type fileSetFlagsRequest struct {
+ _ struct{} `fidl2:"s,8,0"`
+ Flags uint32
+}
+
+var _mfileSetFlagsRequest = _bindings.CreateLazyMarshaler(fileSetFlagsRequest{})
+
+func (msg *fileSetFlagsRequest) Marshaler() _bindings.Marshaler {
+ return _mfileSetFlagsRequest
+}
+
+type fileSetFlagsResponse struct {
+ _ struct{} `fidl2:"s,8,0"`
+ S int32
+}
+
+var _mfileSetFlagsResponse = _bindings.CreateLazyMarshaler(fileSetFlagsResponse{})
+
+func (msg *fileSetFlagsResponse) Marshaler() _bindings.Marshaler {
+ return _mfileSetFlagsResponse
+}
+
+type fileGetBufferRequest struct {
+ _ struct{} `fidl2:"s,8,0"`
+ Flags uint32
+}
+
+var _mfileGetBufferRequest = _bindings.CreateLazyMarshaler(fileGetBufferRequest{})
+
+func (msg *fileGetBufferRequest) Marshaler() _bindings.Marshaler {
+ return _mfileGetBufferRequest
+}
+
+type fileGetBufferResponse struct {
+ _ struct{} `fidl2:"s,16,0"`
+ S int32
+ Buffer *fuchsiamem.Buffer
+}
+
+var _mfileGetBufferResponse = _bindings.CreateLazyMarshaler(fileGetBufferResponse{})
+
+func (msg *fileGetBufferResponse) Marshaler() _bindings.Marshaler {
+ return _mfileGetBufferResponse
+}
+
+type FileInterface _bindings.ChannelProxy
+
+// Create another connection to the same remote object.
+//
+// |flags| may be any of:
+// - OPEN_RIGHT_*
+// - OPEN_FLAG_APPEND
+// - OPEN_FLAG_NO_REMOTE
+// - OPEN_FLAG_DESCRIBE
+// - CLONE_FLAG_SAME_RIGHTS
+//
+// All other flags are ignored.
+//
+// The OPEN_RIGHT_* bits in |flags| request corresponding rights over the resulting
+// cloned object.
+// The cloned object must have rights less than or equal to the original object.
+// Alternatively, pass CLONE_FLAG_SAME_RIGHTS to inherit the rights on the source connection.
+// It is invalid to pass any of the OPEN_RIGHT_* flags together with CLONE_FLAG_SAME_RIGHTS.
+func (p *FileInterface) Clone(flags uint32, object NodeInterfaceRequest) error {
+ req_ := &fileCloneRequest{
+ Flags: flags,
+ Object: object,
+ }
+ err := ((*_bindings.ChannelProxy)(p)).SendNew(FileCloneOrdinal, req_)
+ return err
+}
+
+// Terminates connection with object.
+//
+// This method does not require any rights.
+func (p *FileInterface) Close() (int32, error) {
+ var req_ _bindings.Message
+ resp_ := &fileCloseResponse{}
+ err := ((*_bindings.ChannelProxy)(p)).CallNew(FileCloseOrdinal, req_, resp_)
+ return resp_.S, err
+}
+
+// Returns extra information about the type of the object.
+// If the |Describe| operation fails, the connection is closed.
+//
+// This method does not require any rights.
+func (p *FileInterface) Describe() (NodeInfo, error) {
+ var req_ _bindings.Message
+ resp_ := &fileDescribeResponse{}
+ err := ((*_bindings.ChannelProxy)(p)).CallNew(FileDescribeOrdinal, req_, resp_)
+ return resp_.Info, err
+}
+
+// An event produced eagerly by a FIDL server if requested by |OPEN_FLAG_DESCRIBE|.
+//
+// Indicates the success or failure of the open operation, and optionally describes the
+// object. If the status is |ZX_OK|, |info| contains descriptive information about the object
+// (the same as would be returned by |Describe|).
+func (p *FileInterface) ExpectOnOpen() (int32, *NodeInfo, error) {
+ resp_ := &fileOnOpenResponse{}
+ err := ((*_bindings.ChannelProxy)(p)).RecvNew(FileOnOpenOrdinal, resp_)
+ return resp_.S, resp_.Info, err
+}
+
+// Synchronizes updates to the node to the underlying media, if it exists.
+//
+// This method does not require any rights.
+func (p *FileInterface) Sync() (int32, error) {
+ var req_ _bindings.Message
+ resp_ := &fileSyncResponse{}
+ err := ((*_bindings.ChannelProxy)(p)).CallNew(FileSyncOrdinal, req_, resp_)
+ return resp_.S, err
+}
+
+// Acquires information about the node.
+//
+// This method does not require any rights.
+func (p *FileInterface) GetAttr() (int32, NodeAttributes, error) {
+ var req_ _bindings.Message
+ resp_ := &fileGetAttrResponse{}
+ err := ((*_bindings.ChannelProxy)(p)).CallNew(FileGetAttrOrdinal, req_, resp_)
+ return resp_.S, resp_.Attributes, err
+}
+
+// Updates information about the node.
+// |flags| may be any of NODE_ATTRIBUTE_FLAG_*.
+//
+// This method requires following rights: OPEN_RIGHT_WRITABLE.
+func (p *FileInterface) SetAttr(flags uint32, attributes NodeAttributes) (int32, error) {
+ req_ := &fileSetAttrRequest{
+ Flags: flags,
+ Attributes: attributes,
+ }
+ resp_ := &fileSetAttrResponse{}
+ err := ((*_bindings.ChannelProxy)(p)).CallNew(FileSetAttrOrdinal, req_, resp_)
+ return resp_.S, err
+}
+
+// Deprecated. Only for use with compatibility with devhost.
+func (p *FileInterface) Ioctl(opcode uint32, maxOut uint64, handles []_zx.Handle, in []uint8) (int32, []_zx.Handle, []uint8, error) {
+ req_ := &fileIoctlRequest{
+ Opcode: opcode,
+ MaxOut: maxOut,
+ Handles: handles,
+ In: in,
+ }
+ resp_ := &fileIoctlResponse{}
+ err := ((*_bindings.ChannelProxy)(p)).CallNew(FileIoctlOrdinal, req_, resp_)
+ return resp_.S, resp_.Handles, resp_.Out, err
+}
+
+// Reads 'count' bytes at the seek offset.
+// The seek offset is moved forward by the number of bytes read.
+//
+// This method requires following rights: OPEN_RIGHT_READABLE.
+func (p *FileInterface) Read(count uint64) (int32, []uint8, error) {
+ req_ := &fileReadRequest{
+ Count: count,
+ }
+ resp_ := &fileReadResponse{}
+ err := ((*_bindings.ChannelProxy)(p)).CallNew(FileReadOrdinal, req_, resp_)
+ return resp_.S, resp_.Data, err
+}
+
+// Reads 'count' bytes at the provided offset.
+// Does not affect the seek offset.
+//
+// This method requires following rights: OPEN_RIGHT_READABLE.
+func (p *FileInterface) ReadAt(count uint64, offset uint64) (int32, []uint8, error) {
+ req_ := &fileReadAtRequest{
+ Count: count,
+ Offset: offset,
+ }
+ resp_ := &fileReadAtResponse{}
+ err := ((*_bindings.ChannelProxy)(p)).CallNew(FileReadAtOrdinal, req_, resp_)
+ return resp_.S, resp_.Data, err
+}
+
+// Writes data at the seek offset.
+// The seek offset is moved forward by the number of bytes written.
+//
+// This method requires following rights: OPEN_RIGHT_WRITABLE.
+func (p *FileInterface) Write(data []uint8) (int32, uint64, error) {
+ req_ := &fileWriteRequest{
+ Data: data,
+ }
+ resp_ := &fileWriteResponse{}
+ err := ((*_bindings.ChannelProxy)(p)).CallNew(FileWriteOrdinal, req_, resp_)
+ return resp_.S, resp_.Actual, err
+}
+
+// Writes data to the provided offset.
+// Does not affect the seek offset.
+//
+// This method requires following rights: OPEN_RIGHT_WRITABLE.
+func (p *FileInterface) WriteAt(data []uint8, offset uint64) (int32, uint64, error) {
+ req_ := &fileWriteAtRequest{
+ Data: data,
+ Offset: offset,
+ }
+ resp_ := &fileWriteAtResponse{}
+ err := ((*_bindings.ChannelProxy)(p)).CallNew(FileWriteAtOrdinal, req_, resp_)
+ return resp_.S, resp_.Actual, err
+}
+
+// Moves the offset at which the next invocation of |Read()| or |Write()| will
+// occur.
+//
+// This method does not require any rights.
+func (p *FileInterface) Seek(offset int64, start SeekOrigin) (int32, uint64, error) {
+ req_ := &fileSeekRequest{
+ Offset: offset,
+ Start: start,
+ }
+ resp_ := &fileSeekResponse{}
+ err := ((*_bindings.ChannelProxy)(p)).CallNew(FileSeekOrdinal, req_, resp_)
+ return resp_.S, resp_.Offset, err
+}
+
+// Shrinks the file size to 'length' bytes.
+//
+// This method requires following rights: OPEN_RIGHT_WRITABLE.
+func (p *FileInterface) Truncate(length uint64) (int32, error) {
+ req_ := &fileTruncateRequest{
+ Length: length,
+ }
+ resp_ := &fileTruncateResponse{}
+ err := ((*_bindings.ChannelProxy)(p)).CallNew(FileTruncateOrdinal, req_, resp_)
+ return resp_.S, err
+}
+
+// Acquires the Directory::Open rights and flags used to access this file.
+//
+// This method does not require any rights.
+func (p *FileInterface) GetFlags() (int32, uint32, error) {
+ var req_ _bindings.Message
+ resp_ := &fileGetFlagsResponse{}
+ err := ((*_bindings.ChannelProxy)(p)).CallNew(FileGetFlagsOrdinal, req_, resp_)
+ return resp_.S, resp_.Flags, err
+}
+
+// Changes the Directory::Open flags used to access the file.
+// Supported flags which can be turned on / off:
+// - OPEN_FLAG_APPEND
+//
+// This method does not require any rights.
+func (p *FileInterface) SetFlags(flags uint32) (int32, error) {
+ req_ := &fileSetFlagsRequest{
+ Flags: flags,
+ }
+ resp_ := &fileSetFlagsResponse{}
+ err := ((*_bindings.ChannelProxy)(p)).CallNew(FileSetFlagsOrdinal, req_, resp_)
+ return resp_.S, err
+}
+
+// Acquires a buffer representing this file, if there is one, with the
+// requested access rights.
+//
+// |flags| may be any of VMO_FLAG_*.
+//
+// This method requires following rights:
+// - OPEN_RIGHT_WRITABLE if |flags| includes VMO_FLAG_WRITE.
+// - OPEN_RIGHT_READABLE if |flags| includes VMO_FLAG_READ or VMO_FLAG_EXEC.
+func (p *FileInterface) GetBuffer(flags uint32) (int32, *fuchsiamem.Buffer, error) {
+ req_ := &fileGetBufferRequest{
+ Flags: flags,
+ }
+ resp_ := &fileGetBufferResponse{}
+ err := ((*_bindings.ChannelProxy)(p)).CallNew(FileGetBufferOrdinal, req_, resp_)
+ return resp_.S, resp_.Buffer, err
+}
+
+// File defines the interface of a node which contains a flat layout of data.
+type File interface {
+ // Create another connection to the same remote object.
+ //
+ // |flags| may be any of:
+ // - OPEN_RIGHT_*
+ // - OPEN_FLAG_APPEND
+ // - OPEN_FLAG_NO_REMOTE
+ // - OPEN_FLAG_DESCRIBE
+ // - CLONE_FLAG_SAME_RIGHTS
+ //
+ // All other flags are ignored.
+ //
+ // The OPEN_RIGHT_* bits in |flags| request corresponding rights over the resulting
+ // cloned object.
+ // The cloned object must have rights less than or equal to the original object.
+ // Alternatively, pass CLONE_FLAG_SAME_RIGHTS to inherit the rights on the source connection.
+ // It is invalid to pass any of the OPEN_RIGHT_* flags together with CLONE_FLAG_SAME_RIGHTS.
+ Clone(flags uint32, object NodeInterfaceRequest) error
+ // Terminates connection with object.
+ //
+ // This method does not require any rights.
+ Close() (int32, error)
+ // Returns extra information about the type of the object.
+ // If the |Describe| operation fails, the connection is closed.
+ //
+ // This method does not require any rights.
+ Describe() (NodeInfo, error)
+ // An event produced eagerly by a FIDL server if requested by |OPEN_FLAG_DESCRIBE|.
+ //
+ // Indicates the success or failure of the open operation, and optionally describes the
+ // object. If the status is |ZX_OK|, |info| contains descriptive information about the object
+ // (the same as would be returned by |Describe|).
+ // Synchronizes updates to the node to the underlying media, if it exists.
+ //
+ // This method does not require any rights.
+ Sync() (int32, error)
+ // Acquires information about the node.
+ //
+ // This method does not require any rights.
+ GetAttr() (int32, NodeAttributes, error)
+ // Updates information about the node.
+ // |flags| may be any of NODE_ATTRIBUTE_FLAG_*.
+ //
+ // This method requires following rights: OPEN_RIGHT_WRITABLE.
+ SetAttr(flags uint32, attributes NodeAttributes) (int32, error)
+ // Deprecated. Only for use with compatibility with devhost.
+ Ioctl(opcode uint32, maxOut uint64, handles []_zx.Handle, in []uint8) (int32, []_zx.Handle, []uint8, error)
+ // Reads 'count' bytes at the seek offset.
+ // The seek offset is moved forward by the number of bytes read.
+ //
+ // This method requires following rights: OPEN_RIGHT_READABLE.
+ Read(count uint64) (int32, []uint8, error)
+ // Reads 'count' bytes at the provided offset.
+ // Does not affect the seek offset.
+ //
+ // This method requires following rights: OPEN_RIGHT_READABLE.
+ ReadAt(count uint64, offset uint64) (int32, []uint8, error)
+ // Writes data at the seek offset.
+ // The seek offset is moved forward by the number of bytes written.
+ //
+ // This method requires following rights: OPEN_RIGHT_WRITABLE.
+ Write(data []uint8) (int32, uint64, error)
+ // Writes data to the provided offset.
+ // Does not affect the seek offset.
+ //
+ // This method requires following rights: OPEN_RIGHT_WRITABLE.
+ WriteAt(data []uint8, offset uint64) (int32, uint64, error)
+ // Moves the offset at which the next invocation of |Read()| or |Write()| will
+ // occur.
+ //
+ // This method does not require any rights.
+ Seek(offset int64, start SeekOrigin) (int32, uint64, error)
+ // Shrinks the file size to 'length' bytes.
+ //
+ // This method requires following rights: OPEN_RIGHT_WRITABLE.
+ Truncate(length uint64) (int32, error)
+ // Acquires the Directory::Open rights and flags used to access this file.
+ //
+ // This method does not require any rights.
+ GetFlags() (int32, uint32, error)
+ // Changes the Directory::Open flags used to access the file.
+ // Supported flags which can be turned on / off:
+ // - OPEN_FLAG_APPEND
+ //
+ // This method does not require any rights.
+ SetFlags(flags uint32) (int32, error)
+ // Acquires a buffer representing this file, if there is one, with the
+ // requested access rights.
+ //
+ // |flags| may be any of VMO_FLAG_*.
+ //
+ // This method requires following rights:
+ // - OPEN_RIGHT_WRITABLE if |flags| includes VMO_FLAG_WRITE.
+ // - OPEN_RIGHT_READABLE if |flags| includes VMO_FLAG_READ or VMO_FLAG_EXEC.
+ GetBuffer(flags uint32) (int32, *fuchsiamem.Buffer, error)
+}
+
+type FileTransitionalBase struct{}
+
+type FileInterfaceRequest _bindings.InterfaceRequest
+
+func NewFileInterfaceRequest() (FileInterfaceRequest, *FileInterface, error) {
+ req, cli, err := _bindings.NewInterfaceRequest()
+ return FileInterfaceRequest(req), (*FileInterface)(cli), err
+}
+
+type FileStub struct {
+ Impl File
+}
+
+func (s *FileStub) DispatchNew(ord uint32, b_ []byte, h_ []_zx.Handle) (_bindings.Message, error) {
+ switch ord {
+ case FileCloneOrdinal:
+ in_ := fileCloneRequest{}
+ if _, _, err_ := _bindings.UnmarshalNew(b_, h_, &in_); err_ != nil {
+ return nil, err_
+ }
+ err_ := s.Impl.Clone(in_.Flags, in_.Object)
+ return nil, err_
+ case FileCloseOrdinal:
+ s, err_ := s.Impl.Close()
+ out_ := fileCloseResponse{}
+ out_.S = s
+ return &out_, err_
+ case FileDescribeOrdinal:
+ info, err_ := s.Impl.Describe()
+ out_ := fileDescribeResponse{}
+ out_.Info = info
+ return &out_, err_
+ case FileSyncOrdinal:
+ s, err_ := s.Impl.Sync()
+ out_ := fileSyncResponse{}
+ out_.S = s
+ return &out_, err_
+ case FileGetAttrOrdinal:
+ s, attributes, err_ := s.Impl.GetAttr()
+ out_ := fileGetAttrResponse{}
+ out_.S = s
+ out_.Attributes = attributes
+ return &out_, err_
+ case FileSetAttrOrdinal:
+ in_ := fileSetAttrRequest{}
+ if _, _, err_ := _bindings.UnmarshalNew(b_, h_, &in_); err_ != nil {
+ return nil, err_
+ }
+ s, err_ := s.Impl.SetAttr(in_.Flags, in_.Attributes)
+ out_ := fileSetAttrResponse{}
+ out_.S = s
+ return &out_, err_
+ case FileIoctlOrdinal:
+ in_ := fileIoctlRequest{}
+ if _, _, err_ := _bindings.UnmarshalNew(b_, h_, &in_); err_ != nil {
+ return nil, err_
+ }
+ s, handles, out, err_ := s.Impl.Ioctl(in_.Opcode, in_.MaxOut, in_.Handles, in_.In)
+ out_ := fileIoctlResponse{}
+ out_.S = s
+ out_.Handles = handles
+ out_.Out = out
+ return &out_, err_
+ case FileReadOrdinal:
+ in_ := fileReadRequest{}
+ if _, _, err_ := _bindings.UnmarshalNew(b_, h_, &in_); err_ != nil {
+ return nil, err_
+ }
+ s, data, err_ := s.Impl.Read(in_.Count)
+ out_ := fileReadResponse{}
+ out_.S = s
+ out_.Data = data
+ return &out_, err_
+ case FileReadAtOrdinal:
+ in_ := fileReadAtRequest{}
+ if _, _, err_ := _bindings.UnmarshalNew(b_, h_, &in_); err_ != nil {
+ return nil, err_
+ }
+ s, data, err_ := s.Impl.ReadAt(in_.Count, in_.Offset)
+ out_ := fileReadAtResponse{}
+ out_.S = s
+ out_.Data = data
+ return &out_, err_
+ case FileWriteOrdinal:
+ in_ := fileWriteRequest{}
+ if _, _, err_ := _bindings.UnmarshalNew(b_, h_, &in_); err_ != nil {
+ return nil, err_
+ }
+ s, actual, err_ := s.Impl.Write(in_.Data)
+ out_ := fileWriteResponse{}
+ out_.S = s
+ out_.Actual = actual
+ return &out_, err_
+ case FileWriteAtOrdinal:
+ in_ := fileWriteAtRequest{}
+ if _, _, err_ := _bindings.UnmarshalNew(b_, h_, &in_); err_ != nil {
+ return nil, err_
+ }
+ s, actual, err_ := s.Impl.WriteAt(in_.Data, in_.Offset)
+ out_ := fileWriteAtResponse{}
+ out_.S = s
+ out_.Actual = actual
+ return &out_, err_
+ case FileSeekOrdinal:
+ in_ := fileSeekRequest{}
+ if _, _, err_ := _bindings.UnmarshalNew(b_, h_, &in_); err_ != nil {
+ return nil, err_
+ }
+ s, offset, err_ := s.Impl.Seek(in_.Offset, in_.Start)
+ out_ := fileSeekResponse{}
+ out_.S = s
+ out_.Offset = offset
+ return &out_, err_
+ case FileTruncateOrdinal:
+ in_ := fileTruncateRequest{}
+ if _, _, err_ := _bindings.UnmarshalNew(b_, h_, &in_); err_ != nil {
+ return nil, err_
+ }
+ s, err_ := s.Impl.Truncate(in_.Length)
+ out_ := fileTruncateResponse{}
+ out_.S = s
+ return &out_, err_
+ case FileGetFlagsOrdinal:
+ s, flags, err_ := s.Impl.GetFlags()
+ out_ := fileGetFlagsResponse{}
+ out_.S = s
+ out_.Flags = flags
+ return &out_, err_
+ case FileSetFlagsOrdinal:
+ in_ := fileSetFlagsRequest{}
+ if _, _, err_ := _bindings.UnmarshalNew(b_, h_, &in_); err_ != nil {
+ return nil, err_
+ }
+ s, err_ := s.Impl.SetFlags(in_.Flags)
+ out_ := fileSetFlagsResponse{}
+ out_.S = s
+ return &out_, err_
+ case FileGetBufferOrdinal:
+ in_ := fileGetBufferRequest{}
+ if _, _, err_ := _bindings.UnmarshalNew(b_, h_, &in_); err_ != nil {
+ return nil, err_
+ }
+ s, buffer, err_ := s.Impl.GetBuffer(in_.Flags)
+ out_ := fileGetBufferResponse{}
+ out_.S = s
+ out_.Buffer = buffer
+ return &out_, err_
+ }
+ return nil, _bindings.ErrUnknownOrdinal
+}
+
+type FileService struct {
+ _bindings.BindingSet
+}
+
+func (s *FileService) Add(impl File, c _zx.Channel, onError func(error)) (_bindings.BindingKey, error) {
+ return s.BindingSet.Add(&FileStub{Impl: impl}, c, onError)
+}
+
+func (s *FileService) EventProxyFor(key _bindings.BindingKey) (*FileEventProxy, bool) {
+ pxy, err := s.BindingSet.ProxyFor(key)
+ return (*FileEventProxy)(pxy), err
+}
+
+type FileEventProxy _bindings.ChannelProxy
+
+func (p *FileEventProxy) OnOpen(s int32, info *NodeInfo) error {
+ event_ := &fileOnOpenResponse{
+ S: s,
+ Info: info,
+ }
+ return ((*_bindings.ChannelProxy)(p)).SendNew(FileOnOpenOrdinal, event_)
+}
+
+const (
+ DirectoryWatcherOnEventOrdinal uint32 = 546032797
+ DirectoryWatcherOnEventGenOrdinal uint32 = 546032797
+)
+
+type directoryWatcherOnEventRequest struct {
+ _ struct{} `fidl2:"s,16,0"`
+ Events []uint8 `fidl:"8192" fidl2:"8192"`
+}
+
+var _mdirectoryWatcherOnEventRequest = _bindings.CreateLazyMarshaler(directoryWatcherOnEventRequest{})
+
+func (msg *directoryWatcherOnEventRequest) Marshaler() _bindings.Marshaler {
+ return _mdirectoryWatcherOnEventRequest
+}
+
+type DirectoryWatcherInterface _bindings.ChannelProxy
+
+// TODO(smklein): Convert this to a vector of WatchedEvents, when possible.
+func (p *DirectoryWatcherInterface) OnEvent(events []uint8) error {
+ req_ := &directoryWatcherOnEventRequest{
+ Events: events,
+ }
+ err := ((*_bindings.ChannelProxy)(p)).SendNew(DirectoryWatcherOnEventOrdinal, req_)
+ return err
+}
+
+// TODO(ZX-2645): Unused.
+//
+// DirectoryWatcher transmits messages from a filesystem server
+// about events happening in the filesystem. Clients can register
+// new watchers using the Directory "Watch" method, where they can
+// filter which events they want to receive notifications for.
+type DirectoryWatcher interface {
+ // TODO(smklein): Convert this to a vector of WatchedEvents, when possible.
+ OnEvent(events []uint8) error
+}
+
+type DirectoryWatcherTransitionalBase struct{}
+
+type DirectoryWatcherInterfaceRequest _bindings.InterfaceRequest
+
+func NewDirectoryWatcherInterfaceRequest() (DirectoryWatcherInterfaceRequest, *DirectoryWatcherInterface, error) {
+ req, cli, err := _bindings.NewInterfaceRequest()
+ return DirectoryWatcherInterfaceRequest(req), (*DirectoryWatcherInterface)(cli), err
+}
+
+type DirectoryWatcherStub struct {
+ Impl DirectoryWatcher
+}
+
+func (s *DirectoryWatcherStub) DispatchNew(ord uint32, b_ []byte, h_ []_zx.Handle) (_bindings.Message, error) {
+ switch ord {
+ case DirectoryWatcherOnEventOrdinal:
+ in_ := directoryWatcherOnEventRequest{}
+ if _, _, err_ := _bindings.UnmarshalNew(b_, h_, &in_); err_ != nil {
+ return nil, err_
+ }
+ err_ := s.Impl.OnEvent(in_.Events)
+ return nil, err_
+ }
+ return nil, _bindings.ErrUnknownOrdinal
+}
+
+type DirectoryWatcherService struct {
+ _bindings.BindingSet
+}
+
+func (s *DirectoryWatcherService) Add(impl DirectoryWatcher, c _zx.Channel, onError func(error)) (_bindings.BindingKey, error) {
+ return s.BindingSet.Add(&DirectoryWatcherStub{Impl: impl}, c, onError)
+}
+
+func (s *DirectoryWatcherService) EventProxyFor(key _bindings.BindingKey) (*DirectoryWatcherEventProxy, bool) {
+ pxy, err := s.BindingSet.ProxyFor(key)
+ return (*DirectoryWatcherEventProxy)(pxy), err
+}
+
+type DirectoryWatcherEventProxy _bindings.ChannelProxy
+
+const (
+ DirectoryCloneOrdinal uint32 = 402549324
+ DirectoryCloneGenOrdinal uint32 = 402549324
+ DirectoryCloseOrdinal uint32 = 1387878023
+ DirectoryCloseGenOrdinal uint32 = 1387878023
+ DirectoryDescribeOrdinal uint32 = 526573406
+ DirectoryDescribeGenOrdinal uint32 = 526573406
+ DirectoryOnOpenOrdinal uint32 = 1191225277
+ DirectoryOnOpenGenOrdinal uint32 = 1191225277
+ DirectorySyncOrdinal uint32 = 1648508842
+ DirectorySyncGenOrdinal uint32 = 1648508842
+ DirectoryGetAttrOrdinal uint32 = 1166403528
+ DirectoryGetAttrGenOrdinal uint32 = 1166403528
+ DirectorySetAttrOrdinal uint32 = 198530458
+ DirectorySetAttrGenOrdinal uint32 = 198530458
+ DirectoryIoctlOrdinal uint32 = 905161895
+ DirectoryIoctlGenOrdinal uint32 = 905161895
+ DirectoryOpenOrdinal uint32 = 2011483371
+ DirectoryOpenGenOrdinal uint32 = 2011483371
+ DirectoryUnlinkOrdinal uint32 = 750443289
+ DirectoryUnlinkGenOrdinal uint32 = 750443289
+ DirectoryReadDirentsOrdinal uint32 = 782580781
+ DirectoryReadDirentsGenOrdinal uint32 = 782580781
+ DirectoryRewindOrdinal uint32 = 1886584199
+ DirectoryRewindGenOrdinal uint32 = 1886584199
+ DirectoryGetTokenOrdinal uint32 = 840416493
+ DirectoryGetTokenGenOrdinal uint32 = 840416493
+ DirectoryRenameOrdinal uint32 = 1251258540
+ DirectoryRenameGenOrdinal uint32 = 1251258540
+ DirectoryLinkOrdinal uint32 = 462052964
+ DirectoryLinkGenOrdinal uint32 = 462052964
+ DirectoryWatchOrdinal uint32 = 1522700084
+ DirectoryWatchGenOrdinal uint32 = 1522700084
+)
+
+type directoryCloneRequest struct {
+ _ struct{} `fidl2:"s,8,0"`
+ Flags uint32
+ Object NodeInterfaceRequest `fidl2:"0"`
+}
+
+var _mdirectoryCloneRequest = _bindings.CreateLazyMarshaler(directoryCloneRequest{})
+
+func (msg *directoryCloneRequest) Marshaler() _bindings.Marshaler {
+ return _mdirectoryCloneRequest
+}
+
+type directoryCloseResponse struct {
+ _ struct{} `fidl2:"s,8,0"`
+ S int32
+}
+
+var _mdirectoryCloseResponse = _bindings.CreateLazyMarshaler(directoryCloseResponse{})
+
+func (msg *directoryCloseResponse) Marshaler() _bindings.Marshaler {
+ return _mdirectoryCloseResponse
+}
+
+type directoryDescribeResponse struct {
+ _ struct{} `fidl2:"s,32,0"`
+ Info NodeInfo
+}
+
+var _mdirectoryDescribeResponse = _bindings.CreateLazyMarshaler(directoryDescribeResponse{})
+
+func (msg *directoryDescribeResponse) Marshaler() _bindings.Marshaler {
+ return _mdirectoryDescribeResponse
+}
+
+type directoryOnOpenResponse struct {
+ _ struct{} `fidl2:"s,16,0"`
+ S int32
+ Info *NodeInfo
+}
+
+var _mdirectoryOnOpenResponse = _bindings.CreateLazyMarshaler(directoryOnOpenResponse{})
+
+func (msg *directoryOnOpenResponse) Marshaler() _bindings.Marshaler {
+ return _mdirectoryOnOpenResponse
+}
+
+type directorySyncResponse struct {
+ _ struct{} `fidl2:"s,8,0"`
+ S int32
+}
+
+var _mdirectorySyncResponse = _bindings.CreateLazyMarshaler(directorySyncResponse{})
+
+func (msg *directorySyncResponse) Marshaler() _bindings.Marshaler {
+ return _mdirectorySyncResponse
+}
+
+type directoryGetAttrResponse struct {
+ _ struct{} `fidl2:"s,64,0"`
+ S int32
+ Attributes NodeAttributes
+}
+
+var _mdirectoryGetAttrResponse = _bindings.CreateLazyMarshaler(directoryGetAttrResponse{})
+
+func (msg *directoryGetAttrResponse) Marshaler() _bindings.Marshaler {
+ return _mdirectoryGetAttrResponse
+}
+
+type directorySetAttrRequest struct {
+ _ struct{} `fidl2:"s,64,0"`
+ Flags uint32
+ Attributes NodeAttributes
+}
+
+var _mdirectorySetAttrRequest = _bindings.CreateLazyMarshaler(directorySetAttrRequest{})
+
+func (msg *directorySetAttrRequest) Marshaler() _bindings.Marshaler {
+ return _mdirectorySetAttrRequest
+}
+
+type directorySetAttrResponse struct {
+ _ struct{} `fidl2:"s,8,0"`
+ S int32
+}
+
+var _mdirectorySetAttrResponse = _bindings.CreateLazyMarshaler(directorySetAttrResponse{})
+
+func (msg *directorySetAttrResponse) Marshaler() _bindings.Marshaler {
+ return _mdirectorySetAttrResponse
+}
+
+type directoryIoctlRequest struct {
+ _ struct{} `fidl2:"s,48,0"`
+ Opcode uint32
+ MaxOut uint64
+ Handles []_zx.Handle `fidl:"2" fidl2:"2,0"`
+ In []uint8 `fidl:"8192" fidl2:"8192"`
+}
+
+var _mdirectoryIoctlRequest = _bindings.CreateLazyMarshaler(directoryIoctlRequest{})
+
+func (msg *directoryIoctlRequest) Marshaler() _bindings.Marshaler {
+ return _mdirectoryIoctlRequest
+}
+
+type directoryIoctlResponse struct {
+ _ struct{} `fidl2:"s,40,0"`
+ S int32
+ Handles []_zx.Handle `fidl:"2" fidl2:"2,0"`
+ Out []uint8 `fidl:"8192" fidl2:"8192"`
+}
+
+var _mdirectoryIoctlResponse = _bindings.CreateLazyMarshaler(directoryIoctlResponse{})
+
+func (msg *directoryIoctlResponse) Marshaler() _bindings.Marshaler {
+ return _mdirectoryIoctlResponse
+}
+
+type directoryOpenRequest struct {
+ _ struct{} `fidl2:"s,32,0"`
+ Flags uint32
+ Mode uint32
+ Path string `fidl:"4096" fidl2:"4096"`
+ Object NodeInterfaceRequest `fidl2:"0"`
+}
+
+var _mdirectoryOpenRequest = _bindings.CreateLazyMarshaler(directoryOpenRequest{})
+
+func (msg *directoryOpenRequest) Marshaler() _bindings.Marshaler {
+ return _mdirectoryOpenRequest
+}
+
+type directoryUnlinkRequest struct {
+ _ struct{} `fidl2:"s,16,0"`
+ Path string `fidl:"4096" fidl2:"4096"`
+}
+
+var _mdirectoryUnlinkRequest = _bindings.CreateLazyMarshaler(directoryUnlinkRequest{})
+
+func (msg *directoryUnlinkRequest) Marshaler() _bindings.Marshaler {
+ return _mdirectoryUnlinkRequest
+}
+
+type directoryUnlinkResponse struct {
+ _ struct{} `fidl2:"s,8,0"`
+ S int32
+}
+
+var _mdirectoryUnlinkResponse = _bindings.CreateLazyMarshaler(directoryUnlinkResponse{})
+
+func (msg *directoryUnlinkResponse) Marshaler() _bindings.Marshaler {
+ return _mdirectoryUnlinkResponse
+}
+
+type directoryReadDirentsRequest struct {
+ _ struct{} `fidl2:"s,8,0"`
+ MaxBytes uint64
+}
+
+var _mdirectoryReadDirentsRequest = _bindings.CreateLazyMarshaler(directoryReadDirentsRequest{})
+
+func (msg *directoryReadDirentsRequest) Marshaler() _bindings.Marshaler {
+ return _mdirectoryReadDirentsRequest
+}
+
+type directoryReadDirentsResponse struct {
+ _ struct{} `fidl2:"s,24,0"`
+ S int32
+ Dirents []uint8 `fidl:"8192" fidl2:"8192"`
+}
+
+var _mdirectoryReadDirentsResponse = _bindings.CreateLazyMarshaler(directoryReadDirentsResponse{})
+
+func (msg *directoryReadDirentsResponse) Marshaler() _bindings.Marshaler {
+ return _mdirectoryReadDirentsResponse
+}
+
+type directoryRewindResponse struct {
+ _ struct{} `fidl2:"s,8,0"`
+ S int32
+}
+
+var _mdirectoryRewindResponse = _bindings.CreateLazyMarshaler(directoryRewindResponse{})
+
+func (msg *directoryRewindResponse) Marshaler() _bindings.Marshaler {
+ return _mdirectoryRewindResponse
+}
+
+type directoryGetTokenResponse struct {
+ _ struct{} `fidl2:"s,8,0"`
+ S int32
+ Token _zx.Handle `fidl:"*" fidl2:"1"`
+}
+
+var _mdirectoryGetTokenResponse = _bindings.CreateLazyMarshaler(directoryGetTokenResponse{})
+
+func (msg *directoryGetTokenResponse) Marshaler() _bindings.Marshaler {
+ return _mdirectoryGetTokenResponse
+}
+
+type directoryRenameRequest struct {
+ _ struct{} `fidl2:"s,40,0"`
+ Src string `fidl:"4096" fidl2:"4096"`
+ DstParentToken _zx.Handle `fidl2:"0"`
+ Dst string `fidl:"4096" fidl2:"4096"`
+}
+
+var _mdirectoryRenameRequest = _bindings.CreateLazyMarshaler(directoryRenameRequest{})
+
+func (msg *directoryRenameRequest) Marshaler() _bindings.Marshaler {
+ return _mdirectoryRenameRequest
+}
+
+type directoryRenameResponse struct {
+ _ struct{} `fidl2:"s,8,0"`
+ S int32
+}
+
+var _mdirectoryRenameResponse = _bindings.CreateLazyMarshaler(directoryRenameResponse{})
+
+func (msg *directoryRenameResponse) Marshaler() _bindings.Marshaler {
+ return _mdirectoryRenameResponse
+}
+
+type directoryLinkRequest struct {
+ _ struct{} `fidl2:"s,40,0"`
+ Src string `fidl:"4096" fidl2:"4096"`
+ DstParentToken _zx.Handle `fidl2:"0"`
+ Dst string `fidl:"4096" fidl2:"4096"`
+}
+
+var _mdirectoryLinkRequest = _bindings.CreateLazyMarshaler(directoryLinkRequest{})
+
+func (msg *directoryLinkRequest) Marshaler() _bindings.Marshaler {
+ return _mdirectoryLinkRequest
+}
+
+type directoryLinkResponse struct {
+ _ struct{} `fidl2:"s,8,0"`
+ S int32
+}
+
+var _mdirectoryLinkResponse = _bindings.CreateLazyMarshaler(directoryLinkResponse{})
+
+func (msg *directoryLinkResponse) Marshaler() _bindings.Marshaler {
+ return _mdirectoryLinkResponse
+}
+
+type directoryWatchRequest struct {
+ _ struct{} `fidl2:"s,16,0"`
+ Mask uint32
+ Options uint32
+ Watcher _zx.Channel `fidl2:"0"`
+}
+
+var _mdirectoryWatchRequest = _bindings.CreateLazyMarshaler(directoryWatchRequest{})
+
+func (msg *directoryWatchRequest) Marshaler() _bindings.Marshaler {
+ return _mdirectoryWatchRequest
+}
+
+type directoryWatchResponse struct {
+ _ struct{} `fidl2:"s,8,0"`
+ S int32
+}
+
+var _mdirectoryWatchResponse = _bindings.CreateLazyMarshaler(directoryWatchResponse{})
+
+func (msg *directoryWatchResponse) Marshaler() _bindings.Marshaler {
+ return _mdirectoryWatchResponse
+}
+
+type DirectoryInterface _bindings.ChannelProxy
+
+// Create another connection to the same remote object.
+//
+// |flags| may be any of:
+// - OPEN_RIGHT_*
+// - OPEN_FLAG_APPEND
+// - OPEN_FLAG_NO_REMOTE
+// - OPEN_FLAG_DESCRIBE
+// - CLONE_FLAG_SAME_RIGHTS
+//
+// All other flags are ignored.
+//
+// The OPEN_RIGHT_* bits in |flags| request corresponding rights over the resulting
+// cloned object.
+// The cloned object must have rights less than or equal to the original object.
+// Alternatively, pass CLONE_FLAG_SAME_RIGHTS to inherit the rights on the source connection.
+// It is invalid to pass any of the OPEN_RIGHT_* flags together with CLONE_FLAG_SAME_RIGHTS.
+func (p *DirectoryInterface) Clone(flags uint32, object NodeInterfaceRequest) error {
+ req_ := &directoryCloneRequest{
+ Flags: flags,
+ Object: object,
+ }
+ err := ((*_bindings.ChannelProxy)(p)).SendNew(DirectoryCloneOrdinal, req_)
+ return err
+}
+
+// Terminates connection with object.
+//
+// This method does not require any rights.
+func (p *DirectoryInterface) Close() (int32, error) {
+ var req_ _bindings.Message
+ resp_ := &directoryCloseResponse{}
+ err := ((*_bindings.ChannelProxy)(p)).CallNew(DirectoryCloseOrdinal, req_, resp_)
+ return resp_.S, err
+}
+
+// Returns extra information about the type of the object.
+// If the |Describe| operation fails, the connection is closed.
+//
+// This method does not require any rights.
+func (p *DirectoryInterface) Describe() (NodeInfo, error) {
+ var req_ _bindings.Message
+ resp_ := &directoryDescribeResponse{}
+ err := ((*_bindings.ChannelProxy)(p)).CallNew(DirectoryDescribeOrdinal, req_, resp_)
+ return resp_.Info, err
+}
+
+// An event produced eagerly by a FIDL server if requested by |OPEN_FLAG_DESCRIBE|.
+//
+// Indicates the success or failure of the open operation, and optionally describes the
+// object. If the status is |ZX_OK|, |info| contains descriptive information about the object
+// (the same as would be returned by |Describe|).
+func (p *DirectoryInterface) ExpectOnOpen() (int32, *NodeInfo, error) {
+ resp_ := &directoryOnOpenResponse{}
+ err := ((*_bindings.ChannelProxy)(p)).RecvNew(DirectoryOnOpenOrdinal, resp_)
+ return resp_.S, resp_.Info, err
+}
+
+// Synchronizes updates to the node to the underlying media, if it exists.
+//
+// This method does not require any rights.
+func (p *DirectoryInterface) Sync() (int32, error) {
+ var req_ _bindings.Message
+ resp_ := &directorySyncResponse{}
+ err := ((*_bindings.ChannelProxy)(p)).CallNew(DirectorySyncOrdinal, req_, resp_)
+ return resp_.S, err
+}
+
+// Acquires information about the node.
+//
+// This method does not require any rights.
+func (p *DirectoryInterface) GetAttr() (int32, NodeAttributes, error) {
+ var req_ _bindings.Message
+ resp_ := &directoryGetAttrResponse{}
+ err := ((*_bindings.ChannelProxy)(p)).CallNew(DirectoryGetAttrOrdinal, req_, resp_)
+ return resp_.S, resp_.Attributes, err
+}
+
+// Updates information about the node.
+// |flags| may be any of NODE_ATTRIBUTE_FLAG_*.
+//
+// This method requires following rights: OPEN_RIGHT_WRITABLE.
+func (p *DirectoryInterface) SetAttr(flags uint32, attributes NodeAttributes) (int32, error) {
+ req_ := &directorySetAttrRequest{
+ Flags: flags,
+ Attributes: attributes,
+ }
+ resp_ := &directorySetAttrResponse{}
+ err := ((*_bindings.ChannelProxy)(p)).CallNew(DirectorySetAttrOrdinal, req_, resp_)
+ return resp_.S, err
+}
+
+// Deprecated. Only for use with compatibility with devhost.
+func (p *DirectoryInterface) Ioctl(opcode uint32, maxOut uint64, handles []_zx.Handle, in []uint8) (int32, []_zx.Handle, []uint8, error) {
+ req_ := &directoryIoctlRequest{
+ Opcode: opcode,
+ MaxOut: maxOut,
+ Handles: handles,
+ In: in,
+ }
+ resp_ := &directoryIoctlResponse{}
+ err := ((*_bindings.ChannelProxy)(p)).CallNew(DirectoryIoctlOrdinal, req_, resp_)
+ return resp_.S, resp_.Handles, resp_.Out, err
+}
+
+// Opens a new object relative to this directory object.
+//
+// |path| may contain multiple segments, separated by "/" characters,
+// and should never be empty i.e. "" is an invalid path.
+//
+// |flags| may be any of the OPEN_FLAG_* and OPEN_RIGHT_* values, bitwise ORed together.
+// The OPEN_FLAG_DESCRIBE flag may cause an |OnOpen| event to be transmitted
+// on the |object| handle, indicating the type of object opened.
+//
+// If an unknown value is sent for either flags or mode, the connection should
+// be closed.
+//
+// OPEN_RIGHTS_* flags provided in |flags| will restrict access rights on the |object| channel
+// which will be connected to the opened entity.
+//
+// Rights are never increased. When you open a nested entity within a directory, you may only
+// request the same rights as what the directory connection already has, or a subset of those.
+// Exceeding those rights causes an access denied error to be transmitted in the
+// |OnOpen| event if applicable, and the |object| connection closed.
+//
+// The caller must specify either one or more of the OPEN_RIGHT_* flags, or
+// the OPEN_FLAG_NODE_REFERENCE flag.
+func (p *DirectoryInterface) Open(flags uint32, mode uint32, path string, object NodeInterfaceRequest) error {
+ req_ := &directoryOpenRequest{
+ Flags: flags,
+ Mode: mode,
+ Path: path,
+ Object: object,
+ }
+ err := ((*_bindings.ChannelProxy)(p)).SendNew(DirectoryOpenOrdinal, req_)
+ return err
+}
+
+// Detaches an object from this directory object.
+//
+// The underlying object may or may not be deleted after this method
+// completes: although the link will be removed from the containing directory,
+// objects with multiple references (such as files which are still open)
+// will not actually be destroyed until all references are removed.
+//
+// If a directory is unlinked while it still has an open reference,
+// it must become read-only, preventing new entries from being created
+// until all references close and the directory is destroyed.
+//
+// |path| identifies the file which should be detached.
+// If |path| contains multiple segments, separated by "/" characters,
+// then the directory is traversed, one segment at a time, relative to the
+// originally accessed Directory.
+//
+// Returns:
+// ZX_ERR_ACCESS_DENIED if the connection (or the underlying filesystem) does not
+// allow writable access.
+// ZX_ERR_INVALID_ARGS if |path| contains ".." segments.
+// ZX_ERR_NOT_EMPTY if |path| refers to a non-empty directory.
+// ZX_ERR_UNAVAILABLE if |path| refers to a mount point, containing a remote channel.
+// ZX_ERR_UNAVAILABLE if |path| is ".".
+//
+// Other errors may be returned for filesystem-specific reasons.
+//
+// This method requires following rights: OPEN_RIGHT_WRITABLE.
+func (p *DirectoryInterface) Unlink(path string) (int32, error) {
+ req_ := &directoryUnlinkRequest{
+ Path: path,
+ }
+ resp_ := &directoryUnlinkResponse{}
+ err := ((*_bindings.ChannelProxy)(p)).CallNew(DirectoryUnlinkOrdinal, req_, resp_)
+ return resp_.S, err
+}
+
+// Reads a collection of variably sized dirents into a buffer.
+// The number of dirents in a directory may be very large: akin to
+// calling read multiple times on a file, directories have a seek
+// offset which is updated on subsequent calls to ReadDirents.
+//
+// These dirents are of the form:
+// struct dirent {
+// // Describes the inode of the entry.
+// uint64 ino;
+// // Describes the length of the dirent name.
+// uint8 size;
+// // Describes the type of the entry. Aligned with the
+// /// POSIX d_type values. Use DIRENT_TYPE_* constants.
+// uint8 type;
+// // Unterminated name of entry.
+// char name[0];
+// }
+//
+// This method does not require any rights, since one could always probe for
+// directory contents by triggering name conflicts during file creation.
+func (p *DirectoryInterface) ReadDirents(maxBytes uint64) (int32, []uint8, error) {
+ req_ := &directoryReadDirentsRequest{
+ MaxBytes: maxBytes,
+ }
+ resp_ := &directoryReadDirentsResponse{}
+ err := ((*_bindings.ChannelProxy)(p)).CallNew(DirectoryReadDirentsOrdinal, req_, resp_)
+ return resp_.S, resp_.Dirents, err
+}
+
+// Resets the directory seek offset.
+//
+// This method does not require any rights, similar to ReadDirents.
+func (p *DirectoryInterface) Rewind() (int32, error) {
+ var req_ _bindings.Message
+ resp_ := &directoryRewindResponse{}
+ err := ((*_bindings.ChannelProxy)(p)).CallNew(DirectoryRewindOrdinal, req_, resp_)
+ return resp_.S, err
+}
+
+// Acquires a token to a Directory which can be used to identify
+// access to it at a later point in time.
+//
+// This method requires following rights: OPEN_RIGHT_WRITABLE.
+func (p *DirectoryInterface) GetToken() (int32, _zx.Handle, error) {
+ var req_ _bindings.Message
+ resp_ := &directoryGetTokenResponse{}
+ err := ((*_bindings.ChannelProxy)(p)).CallNew(DirectoryGetTokenOrdinal, req_, resp_)
+ return resp_.S, resp_.Token, err
+}
+
+// Renames an object named src to the name dst, in a directory represented by token.
+//
+// |src/dst| must be resolved object names. Including "/" in any position
+// other than the end of the string will return ZX_ERR_INVALID_ARGS.
+// Returning "/" at the end of either string implies that it must be a
+// directory, or else ZX_ERR_NOT_DIR should be returned.
+//
+// This method requires following rights: OPEN_RIGHT_WRITABLE.
+func (p *DirectoryInterface) Rename(src string, dstParentToken _zx.Handle, dst string) (int32, error) {
+ req_ := &directoryRenameRequest{
+ Src: src,
+ DstParentToken: dstParentToken,
+ Dst: dst,
+ }
+ resp_ := &directoryRenameResponse{}
+ err := ((*_bindings.ChannelProxy)(p)).CallNew(DirectoryRenameOrdinal, req_, resp_)
+ return resp_.S, err
+}
+
+// Creates a link to an object named src by the name dst, within a directory represented by
+// token.
+//
+// |src| must be a resolved object name. Including "/" in the string will
+// return ZX_ERR_INVALID_ARGS.
+//
+// |dst| must be a resolved object name. Including "/" in the string will
+// return ZX_ERR_INVALID_ARGS.
+//
+// This method requires following rights: OPEN_RIGHT_WRITABLE.
+func (p *DirectoryInterface) Link(src string, dstParentToken _zx.Handle, dst string) (int32, error) {
+ req_ := &directoryLinkRequest{
+ Src: src,
+ DstParentToken: dstParentToken,
+ Dst: dst,
+ }
+ resp_ := &directoryLinkResponse{}
+ err := ((*_bindings.ChannelProxy)(p)).CallNew(DirectoryLinkOrdinal, req_, resp_)
+ return resp_.S, err
+}
+
+// Watches a directory, receiving events of added messages on the
+// watcher request channel.
+//
+// The "watcher" handle will send messages of the form:
+// struct {
+// uint8 event;
+// uint8 len;
+// char name[];
+// };
+// Where names are NOT null-terminated.
+//
+// TODO: This API is unstable; in the future, watcher will be a "DirectoryWatcher" client.
+//
+// Mask specifies a bitmask of events to observe.
+// Options must be zero; it is reserved.
+//
+// This method does not require any rights, similar to ReadDirents.
+func (p *DirectoryInterface) Watch(mask uint32, options uint32, watcher _zx.Channel) (int32, error) {
+ req_ := &directoryWatchRequest{
+ Mask: mask,
+ Options: options,
+ Watcher: watcher,
+ }
+ resp_ := &directoryWatchResponse{}
+ err := ((*_bindings.ChannelProxy)(p)).CallNew(DirectoryWatchOrdinal, req_, resp_)
+ return resp_.S, err
+}
+
+// Directory defines a node which is capable of containing other Objects.
+type Directory interface {
+ // Create another connection to the same remote object.
+ //
+ // |flags| may be any of:
+ // - OPEN_RIGHT_*
+ // - OPEN_FLAG_APPEND
+ // - OPEN_FLAG_NO_REMOTE
+ // - OPEN_FLAG_DESCRIBE
+ // - CLONE_FLAG_SAME_RIGHTS
+ //
+ // All other flags are ignored.
+ //
+ // The OPEN_RIGHT_* bits in |flags| request corresponding rights over the resulting
+ // cloned object.
+ // The cloned object must have rights less than or equal to the original object.
+ // Alternatively, pass CLONE_FLAG_SAME_RIGHTS to inherit the rights on the source connection.
+ // It is invalid to pass any of the OPEN_RIGHT_* flags together with CLONE_FLAG_SAME_RIGHTS.
+ Clone(flags uint32, object NodeInterfaceRequest) error
+ // Terminates connection with object.
+ //
+ // This method does not require any rights.
+ Close() (int32, error)
+ // Returns extra information about the type of the object.
+ // If the |Describe| operation fails, the connection is closed.
+ //
+ // This method does not require any rights.
+ Describe() (NodeInfo, error)
+ // An event produced eagerly by a FIDL server if requested by |OPEN_FLAG_DESCRIBE|.
+ //
+ // Indicates the success or failure of the open operation, and optionally describes the
+ // object. If the status is |ZX_OK|, |info| contains descriptive information about the object
+ // (the same as would be returned by |Describe|).
+ // Synchronizes updates to the node to the underlying media, if it exists.
+ //
+ // This method does not require any rights.
+ Sync() (int32, error)
+ // Acquires information about the node.
+ //
+ // This method does not require any rights.
+ GetAttr() (int32, NodeAttributes, error)
+ // Updates information about the node.
+ // |flags| may be any of NODE_ATTRIBUTE_FLAG_*.
+ //
+ // This method requires following rights: OPEN_RIGHT_WRITABLE.
+ SetAttr(flags uint32, attributes NodeAttributes) (int32, error)
+ // Deprecated. Only for use with compatibility with devhost.
+ Ioctl(opcode uint32, maxOut uint64, handles []_zx.Handle, in []uint8) (int32, []_zx.Handle, []uint8, error)
+ // Opens a new object relative to this directory object.
+ //
+ // |path| may contain multiple segments, separated by "/" characters,
+ // and should never be empty i.e. "" is an invalid path.
+ //
+ // |flags| may be any of the OPEN_FLAG_* and OPEN_RIGHT_* values, bitwise ORed together.
+ // The OPEN_FLAG_DESCRIBE flag may cause an |OnOpen| event to be transmitted
+ // on the |object| handle, indicating the type of object opened.
+ //
+ // If an unknown value is sent for either flags or mode, the connection should
+ // be closed.
+ //
+ // OPEN_RIGHTS_* flags provided in |flags| will restrict access rights on the |object| channel
+ // which will be connected to the opened entity.
+ //
+ // Rights are never increased. When you open a nested entity within a directory, you may only
+ // request the same rights as what the directory connection already has, or a subset of those.
+ // Exceeding those rights causes an access denied error to be transmitted in the
+ // |OnOpen| event if applicable, and the |object| connection closed.
+ //
+ // The caller must specify either one or more of the OPEN_RIGHT_* flags, or
+ // the OPEN_FLAG_NODE_REFERENCE flag.
+ Open(flags uint32, mode uint32, path string, object NodeInterfaceRequest) error
+ // Detaches an object from this directory object.
+ //
+ // The underlying object may or may not be deleted after this method
+ // completes: although the link will be removed from the containing directory,
+ // objects with multiple references (such as files which are still open)
+ // will not actually be destroyed until all references are removed.
+ //
+ // If a directory is unlinked while it still has an open reference,
+ // it must become read-only, preventing new entries from being created
+ // until all references close and the directory is destroyed.
+ //
+ // |path| identifies the file which should be detached.
+ // If |path| contains multiple segments, separated by "/" characters,
+ // then the directory is traversed, one segment at a time, relative to the
+ // originally accessed Directory.
+ //
+ // Returns:
+ // ZX_ERR_ACCESS_DENIED if the connection (or the underlying filesystem) does not
+ // allow writable access.
+ // ZX_ERR_INVALID_ARGS if |path| contains ".." segments.
+ // ZX_ERR_NOT_EMPTY if |path| refers to a non-empty directory.
+ // ZX_ERR_UNAVAILABLE if |path| refers to a mount point, containing a remote channel.
+ // ZX_ERR_UNAVAILABLE if |path| is ".".
+ //
+ // Other errors may be returned for filesystem-specific reasons.
+ //
+ // This method requires following rights: OPEN_RIGHT_WRITABLE.
+ Unlink(path string) (int32, error)
+ // Reads a collection of variably sized dirents into a buffer.
+ // The number of dirents in a directory may be very large: akin to
+ // calling read multiple times on a file, directories have a seek
+ // offset which is updated on subsequent calls to ReadDirents.
+ //
+ // These dirents are of the form:
+ // struct dirent {
+ // // Describes the inode of the entry.
+ // uint64 ino;
+ // // Describes the length of the dirent name.
+ // uint8 size;
+ // // Describes the type of the entry. Aligned with the
+ // /// POSIX d_type values. Use DIRENT_TYPE_* constants.
+ // uint8 type;
+ // // Unterminated name of entry.
+ // char name[0];
+ // }
+ //
+ // This method does not require any rights, since one could always probe for
+ // directory contents by triggering name conflicts during file creation.
+ ReadDirents(maxBytes uint64) (int32, []uint8, error)
+ // Resets the directory seek offset.
+ //
+ // This method does not require any rights, similar to ReadDirents.
+ Rewind() (int32, error)
+ // Acquires a token to a Directory which can be used to identify
+ // access to it at a later point in time.
+ //
+ // This method requires following rights: OPEN_RIGHT_WRITABLE.
+ GetToken() (int32, _zx.Handle, error)
+ // Renames an object named src to the name dst, in a directory represented by token.
+ //
+ // |src/dst| must be resolved object names. Including "/" in any position
+ // other than the end of the string will return ZX_ERR_INVALID_ARGS.
+ // Returning "/" at the end of either string implies that it must be a
+ // directory, or else ZX_ERR_NOT_DIR should be returned.
+ //
+ // This method requires following rights: OPEN_RIGHT_WRITABLE.
+ Rename(src string, dstParentToken _zx.Handle, dst string) (int32, error)
+ // Creates a link to an object named src by the name dst, within a directory represented by
+ // token.
+ //
+ // |src| must be a resolved object name. Including "/" in the string will
+ // return ZX_ERR_INVALID_ARGS.
+ //
+ // |dst| must be a resolved object name. Including "/" in the string will
+ // return ZX_ERR_INVALID_ARGS.
+ //
+ // This method requires following rights: OPEN_RIGHT_WRITABLE.
+ Link(src string, dstParentToken _zx.Handle, dst string) (int32, error)
+ // Watches a directory, receiving events of added messages on the
+ // watcher request channel.
+ //
+ // The "watcher" handle will send messages of the form:
+ // struct {
+ // uint8 event;
+ // uint8 len;
+ // char name[];
+ // };
+ // Where names are NOT null-terminated.
+ //
+ // TODO: This API is unstable; in the future, watcher will be a "DirectoryWatcher" client.
+ //
+ // Mask specifies a bitmask of events to observe.
+ // Options must be zero; it is reserved.
+ //
+ // This method does not require any rights, similar to ReadDirents.
+ Watch(mask uint32, options uint32, watcher _zx.Channel) (int32, error)
+}
+
+type DirectoryTransitionalBase struct{}
+
+type DirectoryInterfaceRequest _bindings.InterfaceRequest
+
+func NewDirectoryInterfaceRequest() (DirectoryInterfaceRequest, *DirectoryInterface, error) {
+ req, cli, err := _bindings.NewInterfaceRequest()
+ return DirectoryInterfaceRequest(req), (*DirectoryInterface)(cli), err
+}
+
+type DirectoryStub struct {
+ Impl Directory
+}
+
+func (s *DirectoryStub) DispatchNew(ord uint32, b_ []byte, h_ []_zx.Handle) (_bindings.Message, error) {
+ switch ord {
+ case DirectoryCloneOrdinal:
+ in_ := directoryCloneRequest{}
+ if _, _, err_ := _bindings.UnmarshalNew(b_, h_, &in_); err_ != nil {
+ return nil, err_
+ }
+ err_ := s.Impl.Clone(in_.Flags, in_.Object)
+ return nil, err_
+ case DirectoryCloseOrdinal:
+ s, err_ := s.Impl.Close()
+ out_ := directoryCloseResponse{}
+ out_.S = s
+ return &out_, err_
+ case DirectoryDescribeOrdinal:
+ info, err_ := s.Impl.Describe()
+ out_ := directoryDescribeResponse{}
+ out_.Info = info
+ return &out_, err_
+ case DirectorySyncOrdinal:
+ s, err_ := s.Impl.Sync()
+ out_ := directorySyncResponse{}
+ out_.S = s
+ return &out_, err_
+ case DirectoryGetAttrOrdinal:
+ s, attributes, err_ := s.Impl.GetAttr()
+ out_ := directoryGetAttrResponse{}
+ out_.S = s
+ out_.Attributes = attributes
+ return &out_, err_
+ case DirectorySetAttrOrdinal:
+ in_ := directorySetAttrRequest{}
+ if _, _, err_ := _bindings.UnmarshalNew(b_, h_, &in_); err_ != nil {
+ return nil, err_
+ }
+ s, err_ := s.Impl.SetAttr(in_.Flags, in_.Attributes)
+ out_ := directorySetAttrResponse{}
+ out_.S = s
+ return &out_, err_
+ case DirectoryIoctlOrdinal:
+ in_ := directoryIoctlRequest{}
+ if _, _, err_ := _bindings.UnmarshalNew(b_, h_, &in_); err_ != nil {
+ return nil, err_
+ }
+ s, handles, out, err_ := s.Impl.Ioctl(in_.Opcode, in_.MaxOut, in_.Handles, in_.In)
+ out_ := directoryIoctlResponse{}
+ out_.S = s
+ out_.Handles = handles
+ out_.Out = out
+ return &out_, err_
+ case DirectoryOpenOrdinal:
+ in_ := directoryOpenRequest{}
+ if _, _, err_ := _bindings.UnmarshalNew(b_, h_, &in_); err_ != nil {
+ return nil, err_
+ }
+ err_ := s.Impl.Open(in_.Flags, in_.Mode, in_.Path, in_.Object)
+ return nil, err_
+ case DirectoryUnlinkOrdinal:
+ in_ := directoryUnlinkRequest{}
+ if _, _, err_ := _bindings.UnmarshalNew(b_, h_, &in_); err_ != nil {
+ return nil, err_
+ }
+ s, err_ := s.Impl.Unlink(in_.Path)
+ out_ := directoryUnlinkResponse{}
+ out_.S = s
+ return &out_, err_
+ case DirectoryReadDirentsOrdinal:
+ in_ := directoryReadDirentsRequest{}
+ if _, _, err_ := _bindings.UnmarshalNew(b_, h_, &in_); err_ != nil {
+ return nil, err_
+ }
+ s, dirents, err_ := s.Impl.ReadDirents(in_.MaxBytes)
+ out_ := directoryReadDirentsResponse{}
+ out_.S = s
+ out_.Dirents = dirents
+ return &out_, err_
+ case DirectoryRewindOrdinal:
+ s, err_ := s.Impl.Rewind()
+ out_ := directoryRewindResponse{}
+ out_.S = s
+ return &out_, err_
+ case DirectoryGetTokenOrdinal:
+ s, token, err_ := s.Impl.GetToken()
+ out_ := directoryGetTokenResponse{}
+ out_.S = s
+ out_.Token = token
+ return &out_, err_
+ case DirectoryRenameOrdinal:
+ in_ := directoryRenameRequest{}
+ if _, _, err_ := _bindings.UnmarshalNew(b_, h_, &in_); err_ != nil {
+ return nil, err_
+ }
+ s, err_ := s.Impl.Rename(in_.Src, in_.DstParentToken, in_.Dst)
+ out_ := directoryRenameResponse{}
+ out_.S = s
+ return &out_, err_
+ case DirectoryLinkOrdinal:
+ in_ := directoryLinkRequest{}
+ if _, _, err_ := _bindings.UnmarshalNew(b_, h_, &in_); err_ != nil {
+ return nil, err_
+ }
+ s, err_ := s.Impl.Link(in_.Src, in_.DstParentToken, in_.Dst)
+ out_ := directoryLinkResponse{}
+ out_.S = s
+ return &out_, err_
+ case DirectoryWatchOrdinal:
+ in_ := directoryWatchRequest{}
+ if _, _, err_ := _bindings.UnmarshalNew(b_, h_, &in_); err_ != nil {
+ return nil, err_
+ }
+ s, err_ := s.Impl.Watch(in_.Mask, in_.Options, in_.Watcher)
+ out_ := directoryWatchResponse{}
+ out_.S = s
+ return &out_, err_
+ }
+ return nil, _bindings.ErrUnknownOrdinal
+}
+
+type DirectoryService struct {
+ _bindings.BindingSet
+}
+
+func (s *DirectoryService) Add(impl Directory, c _zx.Channel, onError func(error)) (_bindings.BindingKey, error) {
+ return s.BindingSet.Add(&DirectoryStub{Impl: impl}, c, onError)
+}
+
+func (s *DirectoryService) EventProxyFor(key _bindings.BindingKey) (*DirectoryEventProxy, bool) {
+ pxy, err := s.BindingSet.ProxyFor(key)
+ return (*DirectoryEventProxy)(pxy), err
+}
+
+type DirectoryEventProxy _bindings.ChannelProxy
+
+func (p *DirectoryEventProxy) OnOpen(s int32, info *NodeInfo) error {
+ event_ := &directoryOnOpenResponse{
+ S: s,
+ Info: info,
+ }
+ return ((*_bindings.ChannelProxy)(p)).SendNew(DirectoryOnOpenOrdinal, event_)
+}
+
+const (
+ DirectoryAdminCloneOrdinal uint32 = 402549324
+ DirectoryAdminCloneGenOrdinal uint32 = 402549324
+ DirectoryAdminCloseOrdinal uint32 = 1387878023
+ DirectoryAdminCloseGenOrdinal uint32 = 1387878023
+ DirectoryAdminDescribeOrdinal uint32 = 526573406
+ DirectoryAdminDescribeGenOrdinal uint32 = 526573406
+ DirectoryAdminOnOpenOrdinal uint32 = 1191225277
+ DirectoryAdminOnOpenGenOrdinal uint32 = 1191225277
+ DirectoryAdminSyncOrdinal uint32 = 1648508842
+ DirectoryAdminSyncGenOrdinal uint32 = 1648508842
+ DirectoryAdminGetAttrOrdinal uint32 = 1166403528
+ DirectoryAdminGetAttrGenOrdinal uint32 = 1166403528
+ DirectoryAdminSetAttrOrdinal uint32 = 198530458
+ DirectoryAdminSetAttrGenOrdinal uint32 = 198530458
+ DirectoryAdminIoctlOrdinal uint32 = 905161895
+ DirectoryAdminIoctlGenOrdinal uint32 = 905161895
+ DirectoryAdminOpenOrdinal uint32 = 2011483371
+ DirectoryAdminOpenGenOrdinal uint32 = 2011483371
+ DirectoryAdminUnlinkOrdinal uint32 = 750443289
+ DirectoryAdminUnlinkGenOrdinal uint32 = 750443289
+ DirectoryAdminReadDirentsOrdinal uint32 = 782580781
+ DirectoryAdminReadDirentsGenOrdinal uint32 = 782580781
+ DirectoryAdminRewindOrdinal uint32 = 1886584199
+ DirectoryAdminRewindGenOrdinal uint32 = 1886584199
+ DirectoryAdminGetTokenOrdinal uint32 = 840416493
+ DirectoryAdminGetTokenGenOrdinal uint32 = 840416493
+ DirectoryAdminRenameOrdinal uint32 = 1251258540
+ DirectoryAdminRenameGenOrdinal uint32 = 1251258540
+ DirectoryAdminLinkOrdinal uint32 = 462052964
+ DirectoryAdminLinkGenOrdinal uint32 = 462052964
+ DirectoryAdminWatchOrdinal uint32 = 1522700084
+ DirectoryAdminWatchGenOrdinal uint32 = 1522700084
+ DirectoryAdminMountOrdinal uint32 = 2120159974
+ DirectoryAdminMountGenOrdinal uint32 = 2120159974
+ DirectoryAdminMountAndCreateOrdinal uint32 = 841348753
+ DirectoryAdminMountAndCreateGenOrdinal uint32 = 841348753
+ DirectoryAdminUnmountOrdinal uint32 = 620898132
+ DirectoryAdminUnmountGenOrdinal uint32 = 620898132
+ DirectoryAdminUnmountNodeOrdinal uint32 = 383400103
+ DirectoryAdminUnmountNodeGenOrdinal uint32 = 383400103
+ DirectoryAdminQueryFilesystemOrdinal uint32 = 1713999250
+ DirectoryAdminQueryFilesystemGenOrdinal uint32 = 1713999250
+ DirectoryAdminGetDevicePathOrdinal uint32 = 787943096
+ DirectoryAdminGetDevicePathGenOrdinal uint32 = 787943096
+)
+
+type directoryAdminCloneRequest struct {
+ _ struct{} `fidl2:"s,8,0"`
+ Flags uint32
+ Object NodeInterfaceRequest `fidl2:"0"`
+}
+
+var _mdirectoryAdminCloneRequest = _bindings.CreateLazyMarshaler(directoryAdminCloneRequest{})
+
+func (msg *directoryAdminCloneRequest) Marshaler() _bindings.Marshaler {
+ return _mdirectoryAdminCloneRequest
+}
+
+type directoryAdminCloseResponse struct {
+ _ struct{} `fidl2:"s,8,0"`
+ S int32
+}
+
+var _mdirectoryAdminCloseResponse = _bindings.CreateLazyMarshaler(directoryAdminCloseResponse{})
+
+func (msg *directoryAdminCloseResponse) Marshaler() _bindings.Marshaler {
+ return _mdirectoryAdminCloseResponse
+}
+
+type directoryAdminDescribeResponse struct {
+ _ struct{} `fidl2:"s,32,0"`
+ Info NodeInfo
+}
+
+var _mdirectoryAdminDescribeResponse = _bindings.CreateLazyMarshaler(directoryAdminDescribeResponse{})
+
+func (msg *directoryAdminDescribeResponse) Marshaler() _bindings.Marshaler {
+ return _mdirectoryAdminDescribeResponse
+}
+
+type directoryAdminOnOpenResponse struct {
+ _ struct{} `fidl2:"s,16,0"`
+ S int32
+ Info *NodeInfo
+}
+
+var _mdirectoryAdminOnOpenResponse = _bindings.CreateLazyMarshaler(directoryAdminOnOpenResponse{})
+
+func (msg *directoryAdminOnOpenResponse) Marshaler() _bindings.Marshaler {
+ return _mdirectoryAdminOnOpenResponse
+}
+
+type directoryAdminSyncResponse struct {
+ _ struct{} `fidl2:"s,8,0"`
+ S int32
+}
+
+var _mdirectoryAdminSyncResponse = _bindings.CreateLazyMarshaler(directoryAdminSyncResponse{})
+
+func (msg *directoryAdminSyncResponse) Marshaler() _bindings.Marshaler {
+ return _mdirectoryAdminSyncResponse
+}
+
+type directoryAdminGetAttrResponse struct {
+ _ struct{} `fidl2:"s,64,0"`
+ S int32
+ Attributes NodeAttributes
+}
+
+var _mdirectoryAdminGetAttrResponse = _bindings.CreateLazyMarshaler(directoryAdminGetAttrResponse{})
+
+func (msg *directoryAdminGetAttrResponse) Marshaler() _bindings.Marshaler {
+ return _mdirectoryAdminGetAttrResponse
+}
+
+type directoryAdminSetAttrRequest struct {
+ _ struct{} `fidl2:"s,64,0"`
+ Flags uint32
+ Attributes NodeAttributes
+}
+
+var _mdirectoryAdminSetAttrRequest = _bindings.CreateLazyMarshaler(directoryAdminSetAttrRequest{})
+
+func (msg *directoryAdminSetAttrRequest) Marshaler() _bindings.Marshaler {
+ return _mdirectoryAdminSetAttrRequest
+}
+
+type directoryAdminSetAttrResponse struct {
+ _ struct{} `fidl2:"s,8,0"`
+ S int32
+}
+
+var _mdirectoryAdminSetAttrResponse = _bindings.CreateLazyMarshaler(directoryAdminSetAttrResponse{})
+
+func (msg *directoryAdminSetAttrResponse) Marshaler() _bindings.Marshaler {
+ return _mdirectoryAdminSetAttrResponse
+}
+
+type directoryAdminIoctlRequest struct {
+ _ struct{} `fidl2:"s,48,0"`
+ Opcode uint32
+ MaxOut uint64
+ Handles []_zx.Handle `fidl:"2" fidl2:"2,0"`
+ In []uint8 `fidl:"8192" fidl2:"8192"`
+}
+
+var _mdirectoryAdminIoctlRequest = _bindings.CreateLazyMarshaler(directoryAdminIoctlRequest{})
+
+func (msg *directoryAdminIoctlRequest) Marshaler() _bindings.Marshaler {
+ return _mdirectoryAdminIoctlRequest
+}
+
+type directoryAdminIoctlResponse struct {
+ _ struct{} `fidl2:"s,40,0"`
+ S int32
+ Handles []_zx.Handle `fidl:"2" fidl2:"2,0"`
+ Out []uint8 `fidl:"8192" fidl2:"8192"`
+}
+
+var _mdirectoryAdminIoctlResponse = _bindings.CreateLazyMarshaler(directoryAdminIoctlResponse{})
+
+func (msg *directoryAdminIoctlResponse) Marshaler() _bindings.Marshaler {
+ return _mdirectoryAdminIoctlResponse
+}
+
+type directoryAdminOpenRequest struct {
+ _ struct{} `fidl2:"s,32,0"`
+ Flags uint32
+ Mode uint32
+ Path string `fidl:"4096" fidl2:"4096"`
+ Object NodeInterfaceRequest `fidl2:"0"`
+}
+
+var _mdirectoryAdminOpenRequest = _bindings.CreateLazyMarshaler(directoryAdminOpenRequest{})
+
+func (msg *directoryAdminOpenRequest) Marshaler() _bindings.Marshaler {
+ return _mdirectoryAdminOpenRequest
+}
+
+type directoryAdminUnlinkRequest struct {
+ _ struct{} `fidl2:"s,16,0"`
+ Path string `fidl:"4096" fidl2:"4096"`
+}
+
+var _mdirectoryAdminUnlinkRequest = _bindings.CreateLazyMarshaler(directoryAdminUnlinkRequest{})
+
+func (msg *directoryAdminUnlinkRequest) Marshaler() _bindings.Marshaler {
+ return _mdirectoryAdminUnlinkRequest
+}
+
+type directoryAdminUnlinkResponse struct {
+ _ struct{} `fidl2:"s,8,0"`
+ S int32
+}
+
+var _mdirectoryAdminUnlinkResponse = _bindings.CreateLazyMarshaler(directoryAdminUnlinkResponse{})
+
+func (msg *directoryAdminUnlinkResponse) Marshaler() _bindings.Marshaler {
+ return _mdirectoryAdminUnlinkResponse
+}
+
+type directoryAdminReadDirentsRequest struct {
+ _ struct{} `fidl2:"s,8,0"`
+ MaxBytes uint64
+}
+
+var _mdirectoryAdminReadDirentsRequest = _bindings.CreateLazyMarshaler(directoryAdminReadDirentsRequest{})
+
+func (msg *directoryAdminReadDirentsRequest) Marshaler() _bindings.Marshaler {
+ return _mdirectoryAdminReadDirentsRequest
+}
+
+type directoryAdminReadDirentsResponse struct {
+ _ struct{} `fidl2:"s,24,0"`
+ S int32
+ Dirents []uint8 `fidl:"8192" fidl2:"8192"`
+}
+
+var _mdirectoryAdminReadDirentsResponse = _bindings.CreateLazyMarshaler(directoryAdminReadDirentsResponse{})
+
+func (msg *directoryAdminReadDirentsResponse) Marshaler() _bindings.Marshaler {
+ return _mdirectoryAdminReadDirentsResponse
+}
+
+type directoryAdminRewindResponse struct {
+ _ struct{} `fidl2:"s,8,0"`
+ S int32
+}
+
+var _mdirectoryAdminRewindResponse = _bindings.CreateLazyMarshaler(directoryAdminRewindResponse{})
+
+func (msg *directoryAdminRewindResponse) Marshaler() _bindings.Marshaler {
+ return _mdirectoryAdminRewindResponse
+}
+
+type directoryAdminGetTokenResponse struct {
+ _ struct{} `fidl2:"s,8,0"`
+ S int32
+ Token _zx.Handle `fidl:"*" fidl2:"1"`
+}
+
+var _mdirectoryAdminGetTokenResponse = _bindings.CreateLazyMarshaler(directoryAdminGetTokenResponse{})
+
+func (msg *directoryAdminGetTokenResponse) Marshaler() _bindings.Marshaler {
+ return _mdirectoryAdminGetTokenResponse
+}
+
+type directoryAdminRenameRequest struct {
+ _ struct{} `fidl2:"s,40,0"`
+ Src string `fidl:"4096" fidl2:"4096"`
+ DstParentToken _zx.Handle `fidl2:"0"`
+ Dst string `fidl:"4096" fidl2:"4096"`
+}
+
+var _mdirectoryAdminRenameRequest = _bindings.CreateLazyMarshaler(directoryAdminRenameRequest{})
+
+func (msg *directoryAdminRenameRequest) Marshaler() _bindings.Marshaler {
+ return _mdirectoryAdminRenameRequest
+}
+
+type directoryAdminRenameResponse struct {
+ _ struct{} `fidl2:"s,8,0"`
+ S int32
+}
+
+var _mdirectoryAdminRenameResponse = _bindings.CreateLazyMarshaler(directoryAdminRenameResponse{})
+
+func (msg *directoryAdminRenameResponse) Marshaler() _bindings.Marshaler {
+ return _mdirectoryAdminRenameResponse
+}
+
+type directoryAdminLinkRequest struct {
+ _ struct{} `fidl2:"s,40,0"`
+ Src string `fidl:"4096" fidl2:"4096"`
+ DstParentToken _zx.Handle `fidl2:"0"`
+ Dst string `fidl:"4096" fidl2:"4096"`
+}
+
+var _mdirectoryAdminLinkRequest = _bindings.CreateLazyMarshaler(directoryAdminLinkRequest{})
+
+func (msg *directoryAdminLinkRequest) Marshaler() _bindings.Marshaler {
+ return _mdirectoryAdminLinkRequest
+}
+
+type directoryAdminLinkResponse struct {
+ _ struct{} `fidl2:"s,8,0"`
+ S int32
+}
+
+var _mdirectoryAdminLinkResponse = _bindings.CreateLazyMarshaler(directoryAdminLinkResponse{})
+
+func (msg *directoryAdminLinkResponse) Marshaler() _bindings.Marshaler {
+ return _mdirectoryAdminLinkResponse
+}
+
+type directoryAdminWatchRequest struct {
+ _ struct{} `fidl2:"s,16,0"`
+ Mask uint32
+ Options uint32
+ Watcher _zx.Channel `fidl2:"0"`
+}
+
+var _mdirectoryAdminWatchRequest = _bindings.CreateLazyMarshaler(directoryAdminWatchRequest{})
+
+func (msg *directoryAdminWatchRequest) Marshaler() _bindings.Marshaler {
+ return _mdirectoryAdminWatchRequest
+}
+
+type directoryAdminWatchResponse struct {
+ _ struct{} `fidl2:"s,8,0"`
+ S int32
+}
+
+var _mdirectoryAdminWatchResponse = _bindings.CreateLazyMarshaler(directoryAdminWatchResponse{})
+
+func (msg *directoryAdminWatchResponse) Marshaler() _bindings.Marshaler {
+ return _mdirectoryAdminWatchResponse
+}
+
+type directoryAdminMountRequest struct {
+ _ struct{} `fidl2:"s,8,0"`
+ Remote DirectoryInterface
+}
+
+var _mdirectoryAdminMountRequest = _bindings.CreateLazyMarshaler(directoryAdminMountRequest{})
+
+func (msg *directoryAdminMountRequest) Marshaler() _bindings.Marshaler {
+ return _mdirectoryAdminMountRequest
+}
+
+type directoryAdminMountResponse struct {
+ _ struct{} `fidl2:"s,8,0"`
+ S int32
+}
+
+var _mdirectoryAdminMountResponse = _bindings.CreateLazyMarshaler(directoryAdminMountResponse{})
+
+func (msg *directoryAdminMountResponse) Marshaler() _bindings.Marshaler {
+ return _mdirectoryAdminMountResponse
+}
+
+type directoryAdminMountAndCreateRequest struct {
+ _ struct{} `fidl2:"s,32,0"`
+ Remote DirectoryInterface
+ Name string `fidl:"255" fidl2:"255"`
+ Flags uint32
+}
+
+var _mdirectoryAdminMountAndCreateRequest = _bindings.CreateLazyMarshaler(directoryAdminMountAndCreateRequest{})
+
+func (msg *directoryAdminMountAndCreateRequest) Marshaler() _bindings.Marshaler {
+ return _mdirectoryAdminMountAndCreateRequest
+}
+
+type directoryAdminMountAndCreateResponse struct {
+ _ struct{} `fidl2:"s,8,0"`
+ S int32
+}
+
+var _mdirectoryAdminMountAndCreateResponse = _bindings.CreateLazyMarshaler(directoryAdminMountAndCreateResponse{})
+
+func (msg *directoryAdminMountAndCreateResponse) Marshaler() _bindings.Marshaler {
+ return _mdirectoryAdminMountAndCreateResponse
+}
+
+type directoryAdminUnmountResponse struct {
+ _ struct{} `fidl2:"s,8,0"`
+ S int32
+}
+
+var _mdirectoryAdminUnmountResponse = _bindings.CreateLazyMarshaler(directoryAdminUnmountResponse{})
+
+func (msg *directoryAdminUnmountResponse) Marshaler() _bindings.Marshaler {
+ return _mdirectoryAdminUnmountResponse
+}
+
+type directoryAdminUnmountNodeResponse struct {
+ _ struct{} `fidl2:"s,8,0"`
+ S int32
+ Remote DirectoryInterface `fidl:"*"`
+}
+
+var _mdirectoryAdminUnmountNodeResponse = _bindings.CreateLazyMarshaler(directoryAdminUnmountNodeResponse{})
+
+func (msg *directoryAdminUnmountNodeResponse) Marshaler() _bindings.Marshaler {
+ return _mdirectoryAdminUnmountNodeResponse
+}
+
+type directoryAdminQueryFilesystemResponse struct {
+ _ struct{} `fidl2:"s,16,0"`
+ S int32
+ Info *FilesystemInfo
+}
+
+var _mdirectoryAdminQueryFilesystemResponse = _bindings.CreateLazyMarshaler(directoryAdminQueryFilesystemResponse{})
+
+func (msg *directoryAdminQueryFilesystemResponse) Marshaler() _bindings.Marshaler {
+ return _mdirectoryAdminQueryFilesystemResponse
+}
+
+type directoryAdminGetDevicePathResponse struct {
+ _ struct{} `fidl2:"s,24,0"`
+ S int32
+ Path *string `fidl:"4096" fidl2:"4096"`
+}
+
+var _mdirectoryAdminGetDevicePathResponse = _bindings.CreateLazyMarshaler(directoryAdminGetDevicePathResponse{})
+
+func (msg *directoryAdminGetDevicePathResponse) Marshaler() _bindings.Marshaler {
+ return _mdirectoryAdminGetDevicePathResponse
+}
+
+type DirectoryAdminInterface _bindings.ChannelProxy
+
+// Create another connection to the same remote object.
+//
+// |flags| may be any of:
+// - OPEN_RIGHT_*
+// - OPEN_FLAG_APPEND
+// - OPEN_FLAG_NO_REMOTE
+// - OPEN_FLAG_DESCRIBE
+// - CLONE_FLAG_SAME_RIGHTS
+//
+// All other flags are ignored.
+//
+// The OPEN_RIGHT_* bits in |flags| request corresponding rights over the resulting
+// cloned object.
+// The cloned object must have rights less than or equal to the original object.
+// Alternatively, pass CLONE_FLAG_SAME_RIGHTS to inherit the rights on the source connection.
+// It is invalid to pass any of the OPEN_RIGHT_* flags together with CLONE_FLAG_SAME_RIGHTS.
+func (p *DirectoryAdminInterface) Clone(flags uint32, object NodeInterfaceRequest) error {
+ req_ := &directoryAdminCloneRequest{
+ Flags: flags,
+ Object: object,
+ }
+ err := ((*_bindings.ChannelProxy)(p)).SendNew(DirectoryAdminCloneOrdinal, req_)
+ return err
+}
+
+// Terminates connection with object.
+//
+// This method does not require any rights.
+func (p *DirectoryAdminInterface) Close() (int32, error) {
+ var req_ _bindings.Message
+ resp_ := &directoryAdminCloseResponse{}
+ err := ((*_bindings.ChannelProxy)(p)).CallNew(DirectoryAdminCloseOrdinal, req_, resp_)
+ return resp_.S, err
+}
+
+// Returns extra information about the type of the object.
+// If the |Describe| operation fails, the connection is closed.
+//
+// This method does not require any rights.
+func (p *DirectoryAdminInterface) Describe() (NodeInfo, error) {
+ var req_ _bindings.Message
+ resp_ := &directoryAdminDescribeResponse{}
+ err := ((*_bindings.ChannelProxy)(p)).CallNew(DirectoryAdminDescribeOrdinal, req_, resp_)
+ return resp_.Info, err
+}
+
+// An event produced eagerly by a FIDL server if requested by |OPEN_FLAG_DESCRIBE|.
+//
+// Indicates the success or failure of the open operation, and optionally describes the
+// object. If the status is |ZX_OK|, |info| contains descriptive information about the object
+// (the same as would be returned by |Describe|).
+func (p *DirectoryAdminInterface) ExpectOnOpen() (int32, *NodeInfo, error) {
+ resp_ := &directoryAdminOnOpenResponse{}
+ err := ((*_bindings.ChannelProxy)(p)).RecvNew(DirectoryAdminOnOpenOrdinal, resp_)
+ return resp_.S, resp_.Info, err
+}
+
+// Synchronizes updates to the node to the underlying media, if it exists.
+//
+// This method does not require any rights.
+func (p *DirectoryAdminInterface) Sync() (int32, error) {
+ var req_ _bindings.Message
+ resp_ := &directoryAdminSyncResponse{}
+ err := ((*_bindings.ChannelProxy)(p)).CallNew(DirectoryAdminSyncOrdinal, req_, resp_)
+ return resp_.S, err
+}
+
+// Acquires information about the node.
+//
+// This method does not require any rights.
+func (p *DirectoryAdminInterface) GetAttr() (int32, NodeAttributes, error) {
+ var req_ _bindings.Message
+ resp_ := &directoryAdminGetAttrResponse{}
+ err := ((*_bindings.ChannelProxy)(p)).CallNew(DirectoryAdminGetAttrOrdinal, req_, resp_)
+ return resp_.S, resp_.Attributes, err
+}
+
+// Updates information about the node.
+// |flags| may be any of NODE_ATTRIBUTE_FLAG_*.
+//
+// This method requires following rights: OPEN_RIGHT_WRITABLE.
+func (p *DirectoryAdminInterface) SetAttr(flags uint32, attributes NodeAttributes) (int32, error) {
+ req_ := &directoryAdminSetAttrRequest{
+ Flags: flags,
+ Attributes: attributes,
+ }
+ resp_ := &directoryAdminSetAttrResponse{}
+ err := ((*_bindings.ChannelProxy)(p)).CallNew(DirectoryAdminSetAttrOrdinal, req_, resp_)
+ return resp_.S, err
+}
+
+// Deprecated. Only for use with compatibility with devhost.
+func (p *DirectoryAdminInterface) Ioctl(opcode uint32, maxOut uint64, handles []_zx.Handle, in []uint8) (int32, []_zx.Handle, []uint8, error) {
+ req_ := &directoryAdminIoctlRequest{
+ Opcode: opcode,
+ MaxOut: maxOut,
+ Handles: handles,
+ In: in,
+ }
+ resp_ := &directoryAdminIoctlResponse{}
+ err := ((*_bindings.ChannelProxy)(p)).CallNew(DirectoryAdminIoctlOrdinal, req_, resp_)
+ return resp_.S, resp_.Handles, resp_.Out, err
+}
+
+// Opens a new object relative to this directory object.
+//
+// |path| may contain multiple segments, separated by "/" characters,
+// and should never be empty i.e. "" is an invalid path.
+//
+// |flags| may be any of the OPEN_FLAG_* and OPEN_RIGHT_* values, bitwise ORed together.
+// The OPEN_FLAG_DESCRIBE flag may cause an |OnOpen| event to be transmitted
+// on the |object| handle, indicating the type of object opened.
+//
+// If an unknown value is sent for either flags or mode, the connection should
+// be closed.
+//
+// OPEN_RIGHTS_* flags provided in |flags| will restrict access rights on the |object| channel
+// which will be connected to the opened entity.
+//
+// Rights are never increased. When you open a nested entity within a directory, you may only
+// request the same rights as what the directory connection already has, or a subset of those.
+// Exceeding those rights causes an access denied error to be transmitted in the
+// |OnOpen| event if applicable, and the |object| connection closed.
+//
+// The caller must specify either one or more of the OPEN_RIGHT_* flags, or
+// the OPEN_FLAG_NODE_REFERENCE flag.
+func (p *DirectoryAdminInterface) Open(flags uint32, mode uint32, path string, object NodeInterfaceRequest) error {
+ req_ := &directoryAdminOpenRequest{
+ Flags: flags,
+ Mode: mode,
+ Path: path,
+ Object: object,
+ }
+ err := ((*_bindings.ChannelProxy)(p)).SendNew(DirectoryAdminOpenOrdinal, req_)
+ return err
+}
+
+// Detaches an object from this directory object.
+//
+// The underlying object may or may not be deleted after this method
+// completes: although the link will be removed from the containing directory,
+// objects with multiple references (such as files which are still open)
+// will not actually be destroyed until all references are removed.
+//
+// If a directory is unlinked while it still has an open reference,
+// it must become read-only, preventing new entries from being created
+// until all references close and the directory is destroyed.
+//
+// |path| identifies the file which should be detached.
+// If |path| contains multiple segments, separated by "/" characters,
+// then the directory is traversed, one segment at a time, relative to the
+// originally accessed Directory.
+//
+// Returns:
+// ZX_ERR_ACCESS_DENIED if the connection (or the underlying filesystem) does not
+// allow writable access.
+// ZX_ERR_INVALID_ARGS if |path| contains ".." segments.
+// ZX_ERR_NOT_EMPTY if |path| refers to a non-empty directory.
+// ZX_ERR_UNAVAILABLE if |path| refers to a mount point, containing a remote channel.
+// ZX_ERR_UNAVAILABLE if |path| is ".".
+//
+// Other errors may be returned for filesystem-specific reasons.
+//
+// This method requires following rights: OPEN_RIGHT_WRITABLE.
+func (p *DirectoryAdminInterface) Unlink(path string) (int32, error) {
+ req_ := &directoryAdminUnlinkRequest{
+ Path: path,
+ }
+ resp_ := &directoryAdminUnlinkResponse{}
+ err := ((*_bindings.ChannelProxy)(p)).CallNew(DirectoryAdminUnlinkOrdinal, req_, resp_)
+ return resp_.S, err
+}
+
+// Reads a collection of variably sized dirents into a buffer.
+// The number of dirents in a directory may be very large: akin to
+// calling read multiple times on a file, directories have a seek
+// offset which is updated on subsequent calls to ReadDirents.
+//
+// These dirents are of the form:
+// struct dirent {
+// // Describes the inode of the entry.
+// uint64 ino;
+// // Describes the length of the dirent name.
+// uint8 size;
+// // Describes the type of the entry. Aligned with the
+// /// POSIX d_type values. Use DIRENT_TYPE_* constants.
+// uint8 type;
+// // Unterminated name of entry.
+// char name[0];
+// }
+//
+// This method does not require any rights, since one could always probe for
+// directory contents by triggering name conflicts during file creation.
+func (p *DirectoryAdminInterface) ReadDirents(maxBytes uint64) (int32, []uint8, error) {
+ req_ := &directoryAdminReadDirentsRequest{
+ MaxBytes: maxBytes,
+ }
+ resp_ := &directoryAdminReadDirentsResponse{}
+ err := ((*_bindings.ChannelProxy)(p)).CallNew(DirectoryAdminReadDirentsOrdinal, req_, resp_)
+ return resp_.S, resp_.Dirents, err
+}
+
+// Resets the directory seek offset.
+//
+// This method does not require any rights, similar to ReadDirents.
+func (p *DirectoryAdminInterface) Rewind() (int32, error) {
+ var req_ _bindings.Message
+ resp_ := &directoryAdminRewindResponse{}
+ err := ((*_bindings.ChannelProxy)(p)).CallNew(DirectoryAdminRewindOrdinal, req_, resp_)
+ return resp_.S, err
+}
+
+// Acquires a token to a Directory which can be used to identify
+// access to it at a later point in time.
+//
+// This method requires following rights: OPEN_RIGHT_WRITABLE.
+func (p *DirectoryAdminInterface) GetToken() (int32, _zx.Handle, error) {
+ var req_ _bindings.Message
+ resp_ := &directoryAdminGetTokenResponse{}
+ err := ((*_bindings.ChannelProxy)(p)).CallNew(DirectoryAdminGetTokenOrdinal, req_, resp_)
+ return resp_.S, resp_.Token, err
+}
+
+// Renames an object named src to the name dst, in a directory represented by token.
+//
+// |src/dst| must be resolved object names. Including "/" in any position
+// other than the end of the string will return ZX_ERR_INVALID_ARGS.
+// Returning "/" at the end of either string implies that it must be a
+// directory, or else ZX_ERR_NOT_DIR should be returned.
+//
+// This method requires following rights: OPEN_RIGHT_WRITABLE.
+func (p *DirectoryAdminInterface) Rename(src string, dstParentToken _zx.Handle, dst string) (int32, error) {
+ req_ := &directoryAdminRenameRequest{
+ Src: src,
+ DstParentToken: dstParentToken,
+ Dst: dst,
+ }
+ resp_ := &directoryAdminRenameResponse{}
+ err := ((*_bindings.ChannelProxy)(p)).CallNew(DirectoryAdminRenameOrdinal, req_, resp_)
+ return resp_.S, err
+}
+
+// Creates a link to an object named src by the name dst, within a directory represented by
+// token.
+//
+// |src| must be a resolved object name. Including "/" in the string will
+// return ZX_ERR_INVALID_ARGS.
+//
+// |dst| must be a resolved object name. Including "/" in the string will
+// return ZX_ERR_INVALID_ARGS.
+//
+// This method requires following rights: OPEN_RIGHT_WRITABLE.
+func (p *DirectoryAdminInterface) Link(src string, dstParentToken _zx.Handle, dst string) (int32, error) {
+ req_ := &directoryAdminLinkRequest{
+ Src: src,
+ DstParentToken: dstParentToken,
+ Dst: dst,
+ }
+ resp_ := &directoryAdminLinkResponse{}
+ err := ((*_bindings.ChannelProxy)(p)).CallNew(DirectoryAdminLinkOrdinal, req_, resp_)
+ return resp_.S, err
+}
+
+// Watches a directory, receiving events of added messages on the
+// watcher request channel.
+//
+// The "watcher" handle will send messages of the form:
+// struct {
+// uint8 event;
+// uint8 len;
+// char name[];
+// };
+// Where names are NOT null-terminated.
+//
+// TODO: This API is unstable; in the future, watcher will be a "DirectoryWatcher" client.
+//
+// Mask specifies a bitmask of events to observe.
+// Options must be zero; it is reserved.
+//
+// This method does not require any rights, similar to ReadDirents.
+func (p *DirectoryAdminInterface) Watch(mask uint32, options uint32, watcher _zx.Channel) (int32, error) {
+ req_ := &directoryAdminWatchRequest{
+ Mask: mask,
+ Options: options,
+ Watcher: watcher,
+ }
+ resp_ := &directoryAdminWatchResponse{}
+ err := ((*_bindings.ChannelProxy)(p)).CallNew(DirectoryAdminWatchOrdinal, req_, resp_)
+ return resp_.S, err
+}
+
+// Mount a channel representing a remote filesystem onto this directory.
+// All future requests to this node will be forwarded to the remote filesystem.
+// To re-open a node without forwarding to the remote target, the node
+// should be opened with OPEN_FLAG_NO_REMOTE.
+func (p *DirectoryAdminInterface) Mount(remote DirectoryInterface) (int32, error) {
+ req_ := &directoryAdminMountRequest{
+ Remote: remote,
+ }
+ resp_ := &directoryAdminMountResponse{}
+ err := ((*_bindings.ChannelProxy)(p)).CallNew(DirectoryAdminMountOrdinal, req_, resp_)
+ return resp_.S, err
+}
+
+// Atomically create a directory with a provided path, and mount the
+// remote handle to the newly created directory.
+func (p *DirectoryAdminInterface) MountAndCreate(remote DirectoryInterface, name string, flags uint32) (int32, error) {
+ req_ := &directoryAdminMountAndCreateRequest{
+ Remote: remote,
+ Name: name,
+ Flags: flags,
+ }
+ resp_ := &directoryAdminMountAndCreateResponse{}
+ err := ((*_bindings.ChannelProxy)(p)).CallNew(DirectoryAdminMountAndCreateOrdinal, req_, resp_)
+ return resp_.S, err
+}
+
+// Unmount this filesystem. After this function returns successfully,
+// all connections to the filesystem will be terminated.
+func (p *DirectoryAdminInterface) Unmount() (int32, error) {
+ var req_ _bindings.Message
+ resp_ := &directoryAdminUnmountResponse{}
+ err := ((*_bindings.ChannelProxy)(p)).CallNew(DirectoryAdminUnmountOrdinal, req_, resp_)
+ return resp_.S, err
+}
+
+// Detach a node which was previously attached to this directory
+// with Mount.
+func (p *DirectoryAdminInterface) UnmountNode() (int32, DirectoryInterface, error) {
+ var req_ _bindings.Message
+ resp_ := &directoryAdminUnmountNodeResponse{}
+ err := ((*_bindings.ChannelProxy)(p)).CallNew(DirectoryAdminUnmountNodeOrdinal, req_, resp_)
+ return resp_.S, resp_.Remote, err
+}
+
+// Query the filesystem for filesystem-specific information.
+func (p *DirectoryAdminInterface) QueryFilesystem() (int32, *FilesystemInfo, error) {
+ var req_ _bindings.Message
+ resp_ := &directoryAdminQueryFilesystemResponse{}
+ err := ((*_bindings.ChannelProxy)(p)).CallNew(DirectoryAdminQueryFilesystemOrdinal, req_, resp_)
+ return resp_.S, resp_.Info, err
+}
+
+// Acquire the path to the device backing this filesystem, if there is one.
+func (p *DirectoryAdminInterface) GetDevicePath() (int32, *string, error) {
+ var req_ _bindings.Message
+ resp_ := &directoryAdminGetDevicePathResponse{}
+ err := ((*_bindings.ChannelProxy)(p)).CallNew(DirectoryAdminGetDevicePathOrdinal, req_, resp_)
+ return resp_.S, resp_.Path, err
+}
+
+// DirectoryAdmin defines a directory which is capable of handling
+// administrator tasks within the filesystem.
+type DirectoryAdmin interface {
+ // Create another connection to the same remote object.
+ //
+ // |flags| may be any of:
+ // - OPEN_RIGHT_*
+ // - OPEN_FLAG_APPEND
+ // - OPEN_FLAG_NO_REMOTE
+ // - OPEN_FLAG_DESCRIBE
+ // - CLONE_FLAG_SAME_RIGHTS
+ //
+ // All other flags are ignored.
+ //
+ // The OPEN_RIGHT_* bits in |flags| request corresponding rights over the resulting
+ // cloned object.
+ // The cloned object must have rights less than or equal to the original object.
+ // Alternatively, pass CLONE_FLAG_SAME_RIGHTS to inherit the rights on the source connection.
+ // It is invalid to pass any of the OPEN_RIGHT_* flags together with CLONE_FLAG_SAME_RIGHTS.
+ Clone(flags uint32, object NodeInterfaceRequest) error
+ // Terminates connection with object.
+ //
+ // This method does not require any rights.
+ Close() (int32, error)
+ // Returns extra information about the type of the object.
+ // If the |Describe| operation fails, the connection is closed.
+ //
+ // This method does not require any rights.
+ Describe() (NodeInfo, error)
+ // An event produced eagerly by a FIDL server if requested by |OPEN_FLAG_DESCRIBE|.
+ //
+ // Indicates the success or failure of the open operation, and optionally describes the
+ // object. If the status is |ZX_OK|, |info| contains descriptive information about the object
+ // (the same as would be returned by |Describe|).
+ // Synchronizes updates to the node to the underlying media, if it exists.
+ //
+ // This method does not require any rights.
+ Sync() (int32, error)
+ // Acquires information about the node.
+ //
+ // This method does not require any rights.
+ GetAttr() (int32, NodeAttributes, error)
+ // Updates information about the node.
+ // |flags| may be any of NODE_ATTRIBUTE_FLAG_*.
+ //
+ // This method requires following rights: OPEN_RIGHT_WRITABLE.
+ SetAttr(flags uint32, attributes NodeAttributes) (int32, error)
+ // Deprecated. Only for use with compatibility with devhost.
+ Ioctl(opcode uint32, maxOut uint64, handles []_zx.Handle, in []uint8) (int32, []_zx.Handle, []uint8, error)
+ // Opens a new object relative to this directory object.
+ //
+ // |path| may contain multiple segments, separated by "/" characters,
+ // and should never be empty i.e. "" is an invalid path.
+ //
+ // |flags| may be any of the OPEN_FLAG_* and OPEN_RIGHT_* values, bitwise ORed together.
+ // The OPEN_FLAG_DESCRIBE flag may cause an |OnOpen| event to be transmitted
+ // on the |object| handle, indicating the type of object opened.
+ //
+ // If an unknown value is sent for either flags or mode, the connection should
+ // be closed.
+ //
+ // OPEN_RIGHTS_* flags provided in |flags| will restrict access rights on the |object| channel
+ // which will be connected to the opened entity.
+ //
+ // Rights are never increased. When you open a nested entity within a directory, you may only
+ // request the same rights as what the directory connection already has, or a subset of those.
+ // Exceeding those rights causes an access denied error to be transmitted in the
+ // |OnOpen| event if applicable, and the |object| connection closed.
+ //
+ // The caller must specify either one or more of the OPEN_RIGHT_* flags, or
+ // the OPEN_FLAG_NODE_REFERENCE flag.
+ Open(flags uint32, mode uint32, path string, object NodeInterfaceRequest) error
+ // Detaches an object from this directory object.
+ //
+ // The underlying object may or may not be deleted after this method
+ // completes: although the link will be removed from the containing directory,
+ // objects with multiple references (such as files which are still open)
+ // will not actually be destroyed until all references are removed.
+ //
+ // If a directory is unlinked while it still has an open reference,
+ // it must become read-only, preventing new entries from being created
+ // until all references close and the directory is destroyed.
+ //
+ // |path| identifies the file which should be detached.
+ // If |path| contains multiple segments, separated by "/" characters,
+ // then the directory is traversed, one segment at a time, relative to the
+ // originally accessed Directory.
+ //
+ // Returns:
+ // ZX_ERR_ACCESS_DENIED if the connection (or the underlying filesystem) does not
+ // allow writable access.
+ // ZX_ERR_INVALID_ARGS if |path| contains ".." segments.
+ // ZX_ERR_NOT_EMPTY if |path| refers to a non-empty directory.
+ // ZX_ERR_UNAVAILABLE if |path| refers to a mount point, containing a remote channel.
+ // ZX_ERR_UNAVAILABLE if |path| is ".".
+ //
+ // Other errors may be returned for filesystem-specific reasons.
+ //
+ // This method requires following rights: OPEN_RIGHT_WRITABLE.
+ Unlink(path string) (int32, error)
+ // Reads a collection of variably sized dirents into a buffer.
+ // The number of dirents in a directory may be very large: akin to
+ // calling read multiple times on a file, directories have a seek
+ // offset which is updated on subsequent calls to ReadDirents.
+ //
+ // These dirents are of the form:
+ // struct dirent {
+ // // Describes the inode of the entry.
+ // uint64 ino;
+ // // Describes the length of the dirent name.
+ // uint8 size;
+ // // Describes the type of the entry. Aligned with the
+ // /// POSIX d_type values. Use DIRENT_TYPE_* constants.
+ // uint8 type;
+ // // Unterminated name of entry.
+ // char name[0];
+ // }
+ //
+ // This method does not require any rights, since one could always probe for
+ // directory contents by triggering name conflicts during file creation.
+ ReadDirents(maxBytes uint64) (int32, []uint8, error)
+ // Resets the directory seek offset.
+ //
+ // This method does not require any rights, similar to ReadDirents.
+ Rewind() (int32, error)
+ // Acquires a token to a Directory which can be used to identify
+ // access to it at a later point in time.
+ //
+ // This method requires following rights: OPEN_RIGHT_WRITABLE.
+ GetToken() (int32, _zx.Handle, error)
+ // Renames an object named src to the name dst, in a directory represented by token.
+ //
+ // |src/dst| must be resolved object names. Including "/" in any position
+ // other than the end of the string will return ZX_ERR_INVALID_ARGS.
+ // Returning "/" at the end of either string implies that it must be a
+ // directory, or else ZX_ERR_NOT_DIR should be returned.
+ //
+ // This method requires following rights: OPEN_RIGHT_WRITABLE.
+ Rename(src string, dstParentToken _zx.Handle, dst string) (int32, error)
+ // Creates a link to an object named src by the name dst, within a directory represented by
+ // token.
+ //
+ // |src| must be a resolved object name. Including "/" in the string will
+ // return ZX_ERR_INVALID_ARGS.
+ //
+ // |dst| must be a resolved object name. Including "/" in the string will
+ // return ZX_ERR_INVALID_ARGS.
+ //
+ // This method requires following rights: OPEN_RIGHT_WRITABLE.
+ Link(src string, dstParentToken _zx.Handle, dst string) (int32, error)
+ // Watches a directory, receiving events of added messages on the
+ // watcher request channel.
+ //
+ // The "watcher" handle will send messages of the form:
+ // struct {
+ // uint8 event;
+ // uint8 len;
+ // char name[];
+ // };
+ // Where names are NOT null-terminated.
+ //
+ // TODO: This API is unstable; in the future, watcher will be a "DirectoryWatcher" client.
+ //
+ // Mask specifies a bitmask of events to observe.
+ // Options must be zero; it is reserved.
+ //
+ // This method does not require any rights, similar to ReadDirents.
+ Watch(mask uint32, options uint32, watcher _zx.Channel) (int32, error)
+ // Mount a channel representing a remote filesystem onto this directory.
+ // All future requests to this node will be forwarded to the remote filesystem.
+ // To re-open a node without forwarding to the remote target, the node
+ // should be opened with OPEN_FLAG_NO_REMOTE.
+ Mount(remote DirectoryInterface) (int32, error)
+ // Atomically create a directory with a provided path, and mount the
+ // remote handle to the newly created directory.
+ MountAndCreate(remote DirectoryInterface, name string, flags uint32) (int32, error)
+ // Unmount this filesystem. After this function returns successfully,
+ // all connections to the filesystem will be terminated.
+ Unmount() (int32, error)
+ // Detach a node which was previously attached to this directory
+ // with Mount.
+ UnmountNode() (int32, DirectoryInterface, error)
+ // Query the filesystem for filesystem-specific information.
+ QueryFilesystem() (int32, *FilesystemInfo, error)
+ // Acquire the path to the device backing this filesystem, if there is one.
+ GetDevicePath() (int32, *string, error)
+}
+
+type DirectoryAdminTransitionalBase struct{}
+
+type DirectoryAdminInterfaceRequest _bindings.InterfaceRequest
+
+func NewDirectoryAdminInterfaceRequest() (DirectoryAdminInterfaceRequest, *DirectoryAdminInterface, error) {
+ req, cli, err := _bindings.NewInterfaceRequest()
+ return DirectoryAdminInterfaceRequest(req), (*DirectoryAdminInterface)(cli), err
+}
+
+type DirectoryAdminStub struct {
+ Impl DirectoryAdmin
+}
+
+func (s *DirectoryAdminStub) DispatchNew(ord uint32, b_ []byte, h_ []_zx.Handle) (_bindings.Message, error) {
+ switch ord {
+ case DirectoryAdminCloneOrdinal:
+ in_ := directoryAdminCloneRequest{}
+ if _, _, err_ := _bindings.UnmarshalNew(b_, h_, &in_); err_ != nil {
+ return nil, err_
+ }
+ err_ := s.Impl.Clone(in_.Flags, in_.Object)
+ return nil, err_
+ case DirectoryAdminCloseOrdinal:
+ s, err_ := s.Impl.Close()
+ out_ := directoryAdminCloseResponse{}
+ out_.S = s
+ return &out_, err_
+ case DirectoryAdminDescribeOrdinal:
+ info, err_ := s.Impl.Describe()
+ out_ := directoryAdminDescribeResponse{}
+ out_.Info = info
+ return &out_, err_
+ case DirectoryAdminSyncOrdinal:
+ s, err_ := s.Impl.Sync()
+ out_ := directoryAdminSyncResponse{}
+ out_.S = s
+ return &out_, err_
+ case DirectoryAdminGetAttrOrdinal:
+ s, attributes, err_ := s.Impl.GetAttr()
+ out_ := directoryAdminGetAttrResponse{}
+ out_.S = s
+ out_.Attributes = attributes
+ return &out_, err_
+ case DirectoryAdminSetAttrOrdinal:
+ in_ := directoryAdminSetAttrRequest{}
+ if _, _, err_ := _bindings.UnmarshalNew(b_, h_, &in_); err_ != nil {
+ return nil, err_
+ }
+ s, err_ := s.Impl.SetAttr(in_.Flags, in_.Attributes)
+ out_ := directoryAdminSetAttrResponse{}
+ out_.S = s
+ return &out_, err_
+ case DirectoryAdminIoctlOrdinal:
+ in_ := directoryAdminIoctlRequest{}
+ if _, _, err_ := _bindings.UnmarshalNew(b_, h_, &in_); err_ != nil {
+ return nil, err_
+ }
+ s, handles, out, err_ := s.Impl.Ioctl(in_.Opcode, in_.MaxOut, in_.Handles, in_.In)
+ out_ := directoryAdminIoctlResponse{}
+ out_.S = s
+ out_.Handles = handles
+ out_.Out = out
+ return &out_, err_
+ case DirectoryAdminOpenOrdinal:
+ in_ := directoryAdminOpenRequest{}
+ if _, _, err_ := _bindings.UnmarshalNew(b_, h_, &in_); err_ != nil {
+ return nil, err_
+ }
+ err_ := s.Impl.Open(in_.Flags, in_.Mode, in_.Path, in_.Object)
+ return nil, err_
+ case DirectoryAdminUnlinkOrdinal:
+ in_ := directoryAdminUnlinkRequest{}
+ if _, _, err_ := _bindings.UnmarshalNew(b_, h_, &in_); err_ != nil {
+ return nil, err_
+ }
+ s, err_ := s.Impl.Unlink(in_.Path)
+ out_ := directoryAdminUnlinkResponse{}
+ out_.S = s
+ return &out_, err_
+ case DirectoryAdminReadDirentsOrdinal:
+ in_ := directoryAdminReadDirentsRequest{}
+ if _, _, err_ := _bindings.UnmarshalNew(b_, h_, &in_); err_ != nil {
+ return nil, err_
+ }
+ s, dirents, err_ := s.Impl.ReadDirents(in_.MaxBytes)
+ out_ := directoryAdminReadDirentsResponse{}
+ out_.S = s
+ out_.Dirents = dirents
+ return &out_, err_
+ case DirectoryAdminRewindOrdinal:
+ s, err_ := s.Impl.Rewind()
+ out_ := directoryAdminRewindResponse{}
+ out_.S = s
+ return &out_, err_
+ case DirectoryAdminGetTokenOrdinal:
+ s, token, err_ := s.Impl.GetToken()
+ out_ := directoryAdminGetTokenResponse{}
+ out_.S = s
+ out_.Token = token
+ return &out_, err_
+ case DirectoryAdminRenameOrdinal:
+ in_ := directoryAdminRenameRequest{}
+ if _, _, err_ := _bindings.UnmarshalNew(b_, h_, &in_); err_ != nil {
+ return nil, err_
+ }
+ s, err_ := s.Impl.Rename(in_.Src, in_.DstParentToken, in_.Dst)
+ out_ := directoryAdminRenameResponse{}
+ out_.S = s
+ return &out_, err_
+ case DirectoryAdminLinkOrdinal:
+ in_ := directoryAdminLinkRequest{}
+ if _, _, err_ := _bindings.UnmarshalNew(b_, h_, &in_); err_ != nil {
+ return nil, err_
+ }
+ s, err_ := s.Impl.Link(in_.Src, in_.DstParentToken, in_.Dst)
+ out_ := directoryAdminLinkResponse{}
+ out_.S = s
+ return &out_, err_
+ case DirectoryAdminWatchOrdinal:
+ in_ := directoryAdminWatchRequest{}
+ if _, _, err_ := _bindings.UnmarshalNew(b_, h_, &in_); err_ != nil {
+ return nil, err_
+ }
+ s, err_ := s.Impl.Watch(in_.Mask, in_.Options, in_.Watcher)
+ out_ := directoryAdminWatchResponse{}
+ out_.S = s
+ return &out_, err_
+ case DirectoryAdminMountOrdinal:
+ in_ := directoryAdminMountRequest{}
+ if _, _, err_ := _bindings.UnmarshalNew(b_, h_, &in_); err_ != nil {
+ return nil, err_
+ }
+ s, err_ := s.Impl.Mount(in_.Remote)
+ out_ := directoryAdminMountResponse{}
+ out_.S = s
+ return &out_, err_
+ case DirectoryAdminMountAndCreateOrdinal:
+ in_ := directoryAdminMountAndCreateRequest{}
+ if _, _, err_ := _bindings.UnmarshalNew(b_, h_, &in_); err_ != nil {
+ return nil, err_
+ }
+ s, err_ := s.Impl.MountAndCreate(in_.Remote, in_.Name, in_.Flags)
+ out_ := directoryAdminMountAndCreateResponse{}
+ out_.S = s
+ return &out_, err_
+ case DirectoryAdminUnmountOrdinal:
+ s, err_ := s.Impl.Unmount()
+ out_ := directoryAdminUnmountResponse{}
+ out_.S = s
+ return &out_, err_
+ case DirectoryAdminUnmountNodeOrdinal:
+ s, remote, err_ := s.Impl.UnmountNode()
+ out_ := directoryAdminUnmountNodeResponse{}
+ out_.S = s
+ out_.Remote = remote
+ return &out_, err_
+ case DirectoryAdminQueryFilesystemOrdinal:
+ s, info, err_ := s.Impl.QueryFilesystem()
+ out_ := directoryAdminQueryFilesystemResponse{}
+ out_.S = s
+ out_.Info = info
+ return &out_, err_
+ case DirectoryAdminGetDevicePathOrdinal:
+ s, path, err_ := s.Impl.GetDevicePath()
+ out_ := directoryAdminGetDevicePathResponse{}
+ out_.S = s
+ out_.Path = path
+ return &out_, err_
+ }
+ return nil, _bindings.ErrUnknownOrdinal
+}
+
+type DirectoryAdminService struct {
+ _bindings.BindingSet
+}
+
+func (s *DirectoryAdminService) Add(impl DirectoryAdmin, c _zx.Channel, onError func(error)) (_bindings.BindingKey, error) {
+ return s.BindingSet.Add(&DirectoryAdminStub{Impl: impl}, c, onError)
+}
+
+func (s *DirectoryAdminService) EventProxyFor(key _bindings.BindingKey) (*DirectoryAdminEventProxy, bool) {
+ pxy, err := s.BindingSet.ProxyFor(key)
+ return (*DirectoryAdminEventProxy)(pxy), err
+}
+
+type DirectoryAdminEventProxy _bindings.ChannelProxy
+
+func (p *DirectoryAdminEventProxy) OnOpen(s int32, info *NodeInfo) error {
+ event_ := &directoryAdminOnOpenResponse{
+ S: s,
+ Info: info,
+ }
+ return ((*_bindings.ChannelProxy)(p)).SendNew(DirectoryAdminOnOpenOrdinal, event_)
+}
diff --git a/src/syscall/zx/io/stub.go b/src/syscall/zx/io/stub.go
new file mode 100644
index 0000000..99f32fa
--- /dev/null
+++ b/src/syscall/zx/io/stub.go
@@ -0,0 +1,3 @@
+//+build !fuchsia
+
+package io
diff --git a/src/syscall/zx/mem/impl.go b/src/syscall/zx/mem/impl.go
new file mode 100644
index 0000000..d4a8295
--- /dev/null
+++ b/src/syscall/zx/mem/impl.go
@@ -0,0 +1,38 @@
+// Copyright 2019 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// GENERATED FILE: Do not edit!
+//
+// To rebuild this file, invoke third_party/go/regen-fidl.
+
+// +build fuchsia
+
+package mem
+
+import (
+ _zx "syscall/zx"
+ _bindings "syscall/zx/fidl"
+)
+
+// A Buffer for data whose size is not necessarily a multiple of the page
+// size.
+//
+// VMO objects have a physical size that is always a multiple of the page
+// size. As such, VMO alone cannot serve as a buffer for arbitrarly sized
+// data. |fuchsia.mem.Buffer| is a standard struct that aggregate the VMO
+// and its size.
+type Buffer struct {
+ _ struct{} `fidl2:"s,16,8"`
+ // The vmo.
+ Vmo _zx.VMO `fidl2:"0"`
+ // The size of the data in the vmo in bytes. This size must be smaller
+ // than the physical size of the vmo.
+ Size uint64
+}
+
+var _mBuffer = _bindings.CreateLazyMarshaler(Buffer{})
+
+func (msg *Buffer) Marshaler() _bindings.Marshaler {
+ return _mBuffer
+}
diff --git a/src/syscall/zx/mkfuchsia.go b/src/syscall/zx/mkfuchsia.go
new file mode 100644
index 0000000..556a5a1
--- /dev/null
+++ b/src/syscall/zx/mkfuchsia.go
@@ -0,0 +1,134 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build ignore
+
+// Parses syscalls.abigen of Fuchsia's zircon kernel and produces Go assembly
+// for calling the system calls.
+//
+// Regenerate syscall/zx with:
+//
+// go run mkfuchsia.go -stubs > syscalls_fuchsia.go
+// go run mkfuchsia.go -goarch=amd64 > syscalls_fuchsia_amd64.s
+// go run mkfuchsia.go -goarch=arm64 > syscalls_fuchsia_arm64.s
+// gofmt -w syscalls_fuchsia.go
+package main
+
+import (
+ "bytes"
+ "flag"
+ "fmt"
+ "io/ioutil"
+ "log"
+ "os"
+ "path/filepath"
+
+ "internal/fuchsia/abigen"
+)
+
+var (
+ stubs = flag.Bool("stubs", false, "print only Go function stubs")
+ goarch = flag.String("goarch", "amd64", "arch to print asm for")
+ fuchsiaRoot = flag.String("fuchsia_root", filepath.Join(os.Getenv("HOME"), "fuchsia"), "path to fuchsia root")
+)
+
+func main() {
+ flag.Parse()
+ sdkArch := ""
+ switch *goarch {
+ case "amd64":
+ sdkArch = "x86_64"
+ case "arm64":
+ sdkArch = "aarch64"
+ default:
+ log.Fatalf("GOARCH=%s not supported", *goarch)
+ }
+ _ = sdkArch
+
+ syscallsFile := filepath.Join(*fuchsiaRoot, "/zircon/system/public/zircon/syscalls.abigen")
+ if args := flag.Args(); len(args) != 0 {
+ syscallsFile = args[0]
+ }
+
+ b, err := ioutil.ReadFile(syscallsFile)
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ p := abigen.NewParser(b, syscallsFile)
+ defs, err := p.Parse()
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ buf := new(bytes.Buffer)
+ if *stubs {
+ fmt.Fprint(buf, stubsHeader[1:])
+ for _, def := range defs {
+ fmt.Fprint(buf, "//go:noescape\n")
+ fmt.Fprint(buf, "//go:nosplit\n")
+ printStub(buf, def)
+ fmt.Fprint(buf, "\n")
+ }
+ } else {
+ fmt.Fprint(buf, asmHeader[1:])
+ for _, def := range defs {
+ fmt.Fprint(buf, "// ")
+ printStub(buf, def)
+ printAsm(buf, def)
+ fmt.Fprint(buf, "\n")
+ }
+ }
+ buf.WriteTo(os.Stdout)
+}
+
+const stubsHeader = `
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Zircon system calls for the Fuchsia OS.
+// Generated by mkfuchsia.go, do not edit.
+
+package zx
+
+import "unsafe"
+
+`
+
+const asmHeader = `
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Zircon system calls for the Fuchsia OS.
+// Generated by mkfuchsia.go, do not edit.
+
+#include "textflag.h"
+`
+
+func printStub(buf *bytes.Buffer, def abigen.SysDef) {
+ fmt.Fprintf(buf, "func %s(", def.GoName())
+ for i, arg := range def.Args {
+ if arg.Type == (abigen.SysType{}) {
+ continue
+ }
+ if i > 0 {
+ fmt.Fprint(buf, ", ")
+ }
+ fmt.Fprintf(buf, "%s ", arg.Name)
+ fmt.Fprintf(buf, "%s", arg.Type.GoType())
+ }
+ fmt.Fprint(buf, ")")
+ if def.Ret != (abigen.SysType{}) {
+ fmt.Fprint(buf, " ")
+ fmt.Fprintf(buf, "%s", def.Ret.GoType())
+ }
+ fmt.Fprint(buf, "\n")
+}
+
+func printAsm(buf *bytes.Buffer, def abigen.SysDef) {
+ fmt.Fprintf(buf, "TEXT ·%s(SB),NOSPLIT,$0\n", def.GoName())
+ fmt.Fprintf(buf, "\tJMP runtime·vdsoCall_zx_%s(SB)\n", def.Name)
+}
diff --git a/src/syscall/zx/mxnet/ctypes.go b/src/syscall/zx/mxnet/ctypes.go
new file mode 100644
index 0000000..4cfd784
--- /dev/null
+++ b/src/syscall/zx/mxnet/ctypes.go
@@ -0,0 +1,116 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build fuchsia
+
+package mxnet
+
+// Types from <lib/fdio/socket.h>.
+// These were extracted from cgo by building the program:
+//
+// package typesextract
+//
+// // #include <arpa/inet.h>
+// // #include <netdb.h>
+// // #include <netinet/in.h>
+// // #include <netinet/tcp.h>
+// // #include <sys/ioctl.h>
+// // #include <sys/socket.h>
+// // #include <sys/types.h>
+// // #include <lib/fdio/socket.h>
+// import "C"
+//
+// func F() {
+// _ = C.struct_addrinfo{}
+// _ = C.struct_sockaddr_in{}
+// _ = C.struct_sockaddr_in6{}
+// _ = C.struct_fdio_socket_msg{}
+// _ = C.AF_INET
+// _ = C.AF_INET6
+// _ = C.MXRIO_GAI_REQ_NODE_MAXLEN
+// _ = C.MXRIO_GAI_REQ_SERVICE_MAXLEN
+// _ = C.MXRIO_GAI_REPLY_MAX
+// }
+//
+// Then the names were cleaned up manually, with commands like:
+// s/_t$//
+// s/_Ctype_struct_/c_/
+// s/_Ctype_/c_/
+// ...
+//
+// Two big changes are c_in_port and c_in_addr, which for historcical
+// UNIX reasons have terrible type representations, so we treat them
+// as byte arrays.
+//
+// This will probably all be FIDL one day.
+
+const SOCK_STREAM = 1
+const SOCK_DGRAM = 2
+
+const AF_INET = 2
+const AF_INET6 = 10
+
+const MXRIO_GAI_REQ_NODE_MAXLEN = 256
+const MXRIO_GAI_REQ_SERVICE_MAXLEN = 256
+const MXRIO_GAI_REPLY_MAX = 4
+
+type c_socklen uint32
+type c_in_port [2]byte // uint16 in C, but stored in network order
+type c_sa_family uint16
+type c_in_addr [4]byte // uint32 in C, but stored in network order
+type c_ulong uint64
+
+type c_addrinfo struct {
+ ai_flags int32
+ ai_family int32
+ ai_socktype int32
+ ai_protocol int32
+ ai_addrlen c_socklen
+ _ [4]byte
+ // The following pointers are unused on the wire.
+ ai_addr uintptr // *c_sockaddr
+ ai_canonname uintptr // *int8
+ ai_next uintptr // *c_addrinfo
+}
+
+type c_sockaddr struct {
+ sa_family c_sa_family
+ sa_data [14]uint8
+}
+
+type c_sockaddr_in struct {
+ sin_family c_sa_family
+ sin_port c_in_port // network order
+ sin_addr c_in_addr
+ sin_zero [8]uint8
+}
+
+type c_in6_addr [16]byte
+
+type c_sockaddr_in6 struct {
+ sin6_family c_sa_family
+ sin6_port c_in_port // network order
+ sin6_flowinfo uint32
+ sin6_addr c_in6_addr
+ sin6_scope_id uint32
+}
+
+type c_sockaddr_storage struct {
+ ss_family c_sa_family
+ _ [6]byte
+ __ss_align c_ulong
+ __ss_padding [112]uint8
+}
+
+type c_fdio_socket_msg_hdr struct {
+ addr c_sockaddr_storage
+ addrlen c_socklen
+ flags int32
+}
+
+type c_fdio_socket_msg struct {
+ hdr c_fdio_socket_msg_hdr
+ data [1]uint8
+ _ [7]byte
+}
diff --git a/src/syscall/zx/mxnet/mxnet.go b/src/syscall/zx/mxnet/mxnet.go
new file mode 100644
index 0000000..d9a6dec
--- /dev/null
+++ b/src/syscall/zx/mxnet/mxnet.go
@@ -0,0 +1,153 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build fuchsia
+
+// Package mxnet contains types for talking to Fuchsia's fdio net interface.
+package mxnet
+
+import (
+ "syscall/zx"
+ "unsafe"
+)
+
+const ZX_SOCKET_HALF_CLOSE = 1
+const ZX_SOCKET_READABLE = zx.SignalObject0
+const ZX_SOCKET_WRITABLE = zx.SignalObject1
+const ZX_SOCKET_PEER_CLOSED = zx.SignalObject2
+const MXSIO_SIGNAL_INCOMING = zx.SignalUser0
+const MXSIO_SIGNAL_OUTGOING = zx.SignalUser1
+const MXSIO_SIGNAL_CONNECTED = zx.SignalUser3
+const MXSIO_SIGNAL_HALFCLOSED = zx.SignalUser4
+
+// Addr is an IP address.
+// It has either len == 4 (if it is IPv4) or len == 16 (IPv6).
+type Addr string
+
+// TODO(crawshaw): consider cleaning up these interfaces by migrating to
+// an address type that captures everything:
+//
+// type Address struct {
+// Addr [16]byte
+// IPv4 bool
+// Port uint16
+// }
+
+const SockaddrLen = c_sockaddr_in6_len
+const SockmsgHdrLen = c_fdio_socket_msg_hdr_len
+
+func EncodeSockmsgHdr(dst []byte, addr Addr, port uint16, flags int) (err error) {
+ if len(dst) < SockmsgHdrLen {
+ return errString("mxnet.EncodeSockmsgHdr: dst too short")
+ }
+ var n int
+ if addr != "" || port != 0 {
+ n, err = EncodeSockaddr(dst, addr, port, 0)
+ if err != nil {
+ return err
+ }
+ }
+ hdr := (*c_fdio_socket_msg_hdr)(unsafe.Pointer(&dst[0]))
+ hdr.addrlen = c_socklen(n)
+ hdr.flags = int32(flags)
+ return nil
+}
+
+func DecodeSockmsgHdr(src []byte) (addr Addr, port uint16, flags int, err error) {
+ if len(src) < SockmsgHdrLen {
+ return "", 0, 0, errString("mxnet.DecodeSockmsgHdr: src too short")
+ }
+ addr, port, err = DecodeSockaddr(src)
+ if err != nil {
+ return "", 0, 0, err
+ }
+ hdr := (*c_fdio_socket_msg_hdr)(unsafe.Pointer(&src[0]))
+ flags = int(hdr.flags)
+ return addr, port, flags, nil
+}
+
+func DecodeSockaddr(data []byte) (addr Addr, port uint16, err error) {
+ if len(data) < 2 {
+ return "", 0, errString("mxnet:DecodeSockaddr: data too short")
+ }
+ family := uint16(data[0]) | uint16(data[1])<<8
+ switch family {
+ case AF_INET:
+ if len(data) < int(unsafe.Sizeof(c_sockaddr_in{})) {
+ return "", 0, errString("mxnet:DecodeSockaddr: data too short for ipv4")
+ }
+ v := (*c_sockaddr_in)(unsafe.Pointer(&data[0]))
+ port = uint16(data[3]) | uint16(data[2])<<8
+ if !isZeros(v.sin_addr[:]) {
+ addr = Addr(v.sin_addr[:])
+ }
+ return addr, port, nil
+ case AF_INET6:
+ if len(data) < int(unsafe.Sizeof(c_sockaddr_in6{})) {
+ return "", 0, errString("mxnet:DecodeSockaddr: data too short for ipv6")
+ }
+ v := (*c_sockaddr_in6)(unsafe.Pointer(&data[0]))
+ port = uint16(data[3]) | uint16(data[2])<<8
+ if !isZeros(v.sin6_addr[:]) {
+ addr = Addr(v.sin6_addr[:])
+ }
+ return addr, port, nil
+ default:
+ return "", 0, errString("mxnet:DecodeSockaddr: unknown family")
+ }
+}
+
+func EncodeSockaddr(dst []byte, addr Addr, port uint16, zone uint32) (int, error) {
+ switch len(addr) {
+ case 0, 4:
+ if len(dst) < c_sockaddr_in_len {
+ return 0, errString("mxnet: dst too small for c_sockaddr_in")
+ }
+ sockaddr := c_sockaddr_in{sin_family: AF_INET}
+ sockaddr.sin_port.setPort(port)
+ copy(sockaddr.sin_addr[:], addr)
+ srcb := (*[unsafe.Sizeof(sockaddr)]byte)(unsafe.Pointer(&sockaddr))[:]
+ return copy(dst, srcb), nil
+ case 16:
+ if len(dst) < c_sockaddr_in_len {
+ return 0, errString("mxnet: dst too small for c_sockaddr_in6")
+ }
+ sockaddr := c_sockaddr_in6{sin6_family: AF_INET6}
+ sockaddr.sin6_port.setPort(port)
+ sockaddr.sin6_scope_id = zone
+ copy(sockaddr.sin6_addr[:], addr)
+ srcb := (*[unsafe.Sizeof(sockaddr)]byte)(unsafe.Pointer(&sockaddr))[:]
+ return copy(dst, srcb), nil
+ default:
+ return 0, errString("mxnet: bad address length")
+ }
+}
+
+type errString string
+
+func (err errString) Error() string { return string(err) }
+
+const (
+ c_sockaddr_in_len = int(unsafe.Sizeof(c_sockaddr_in{}))
+ c_sockaddr_in6_len = int(unsafe.Sizeof(c_sockaddr_in6{}))
+ c_fdio_socket_msg_hdr_len = int(unsafe.Sizeof(c_fdio_socket_msg_hdr{}))
+)
+
+func (v c_in_port) port() uint16 {
+ return uint16(v[0])<<8 | uint16(v[1])
+}
+
+func (v *c_in_port) setPort(port uint16) {
+ v[0] = uint8(port >> 8)
+ v[1] = uint8(port)
+}
+
+func isZeros(buf []byte) bool {
+ for i := 0; i < len(buf); i++ {
+ if buf[i] != 0 {
+ return false
+ }
+ }
+ return true
+}
diff --git a/src/syscall/zx/mxnet/stub.go b/src/syscall/zx/mxnet/stub.go
new file mode 100644
index 0000000..9707b18
--- /dev/null
+++ b/src/syscall/zx/mxnet/stub.go
@@ -0,0 +1,3 @@
+//+build !fuchsia
+
+package mxnet
diff --git a/src/syscall/zx/net/impl.go b/src/syscall/zx/net/impl.go
new file mode 100644
index 0000000..4023577
--- /dev/null
+++ b/src/syscall/zx/net/impl.go
@@ -0,0 +1,1245 @@
+// Copyright 2018 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// GENERATED FILE: Do not edit!
+//
+// To rebuild this file, invoke third_party/go/regen-fidl.
+
+// +build fuchsia
+
+package net
+
+import (
+ _zx "syscall/zx"
+ _bindings "syscall/zx/fidl"
+)
+
+const (
+ MaxAddr uint64 = 128
+ MaxBuffer uint64 = 900
+)
+
+type LookupError uint32
+
+const (
+ LookupErrorNotFound LookupError = 1
+ LookupErrorTransient LookupError = 2
+ LookupErrorInvalidArgs LookupError = 3
+ LookupErrorInternalError LookupError = 4
+)
+
+func (x LookupError) String() string {
+ switch x {
+ case 1:
+ return "NotFound"
+ case 2:
+ return "Transient"
+ case 3:
+ return "InvalidArgs"
+ case 4:
+ return "InternalError"
+ }
+ return "Unknown"
+}
+
+type AddrInfoStatus uint32
+
+const (
+ AddrInfoStatusOk AddrInfoStatus = 0
+ AddrInfoStatusBadFlags AddrInfoStatus = 1
+ AddrInfoStatusNoName AddrInfoStatus = 2
+ AddrInfoStatusAgain AddrInfoStatus = 3
+ AddrInfoStatusFail AddrInfoStatus = 4
+ AddrInfoStatusNoData AddrInfoStatus = 5
+ AddrInfoStatusBufferOverflow AddrInfoStatus = 6
+ AddrInfoStatusSystemError AddrInfoStatus = 7
+)
+
+func (x AddrInfoStatus) String() string {
+ switch x {
+ case 0:
+ return "Ok"
+ case 1:
+ return "BadFlags"
+ case 2:
+ return "NoName"
+ case 3:
+ return "Again"
+ case 4:
+ return "Fail"
+ case 5:
+ return "NoData"
+ case 6:
+ return "BufferOverflow"
+ case 7:
+ return "SystemError"
+ }
+ return "Unknown"
+}
+
+type NameLookupLookupIpResponse struct {
+ _ struct{} `fidl2:"s,48,8"`
+ Addr IpAddressInfo
+}
+
+var _mNameLookupLookupIpResponse = _bindings.CreateLazyMarshaler(NameLookupLookupIpResponse{})
+
+func (msg *NameLookupLookupIpResponse) Marshaler() _bindings.Marshaler {
+ return _mNameLookupLookupIpResponse
+}
+
+type NameLookupLookupHostnameResponse struct {
+ _ struct{} `fidl2:"s,16,8"`
+ Hostname string
+}
+
+var _mNameLookupLookupHostnameResponse = _bindings.CreateLazyMarshaler(NameLookupLookupHostnameResponse{})
+
+func (msg *NameLookupLookupHostnameResponse) Marshaler() _bindings.Marshaler {
+ return _mNameLookupLookupHostnameResponse
+}
+
+type IpAddressInfo struct {
+ _ struct{} `fidl2:"s,48,8"`
+ // All of the IPv4 addresses for the requested hostname.
+ Ipv4Addrs []Ipv4Address
+ // All of the IPv6 addresses for the requested hostname.
+ Ipv6Addrs []Ipv6Address
+ // The canonical name of the requested hostname (usually the DNS CNAME record, if one exists).
+ CanonicalName *string
+}
+
+var _mIpAddressInfo = _bindings.CreateLazyMarshaler(IpAddressInfo{})
+
+func (msg *IpAddressInfo) Marshaler() _bindings.Marshaler {
+ return _mIpAddressInfo
+}
+
+// Ipv4Address is expressed in network byte order, so the most significant byte
+// ("127" in the address "127.0.0.1") will be at index 0.
+type Ipv4Address struct {
+ _ struct{} `fidl2:"s,4,1"`
+ Addr [4]uint8
+}
+
+var _mIpv4Address = _bindings.CreateLazyMarshaler(Ipv4Address{})
+
+func (msg *Ipv4Address) Marshaler() _bindings.Marshaler {
+ return _mIpv4Address
+}
+
+// Ipv6Address is expressed in network byte order, so the most significant byte
+// ("ff" in the address "ff02::1") will be at index 0.
+type Ipv6Address struct {
+ _ struct{} `fidl2:"s,16,1"`
+ Addr [16]uint8
+}
+
+var _mIpv6Address = _bindings.CreateLazyMarshaler(Ipv6Address{})
+
+func (msg *Ipv6Address) Marshaler() _bindings.Marshaler {
+ return _mIpv6Address
+}
+
+// Endpoint describes an IP address and port. The network protocol associated
+// with the Endpoint will be known from context or communicated through
+// additional structures.
+type Endpoint struct {
+ _ struct{} `fidl2:"s,24,4"`
+ // The IP address of the endpoint.
+ Addr IpAddress
+ // The port number of the endpoint.
+ Port uint16
+}
+
+var _mEndpoint = _bindings.CreateLazyMarshaler(Endpoint{})
+
+func (msg *Endpoint) Marshaler() _bindings.Marshaler {
+ return _mEndpoint
+}
+
+// Subnet describes an IP subnetwork, where all host IP addresses share the same most significant
+// bits.
+type Subnet struct {
+ _ struct{} `fidl2:"s,24,4"`
+ // The Ipv4 or Ipv6 address. Only the |prefix_len| most significant bits may be set in |addr|;
+ // all bits in the host portion of the address must be zero.
+ Addr IpAddress
+ // The prefix length of the netmask. E.g. for 192.168.1.0/24, the prefix
+ // length is 24, corresponding to a netmask of 255.255.255.0.
+ // For Ipv4, prefix_len must be in the range [0, 32].
+ // For Ipv6, prefix_len must be in the range [0, 128].
+ PrefixLen uint8
+}
+
+var _mSubnet = _bindings.CreateLazyMarshaler(Subnet{})
+
+func (msg *Subnet) Marshaler() _bindings.Marshaler {
+ return _mSubnet
+}
+
+// A MAC address used to identify a network interface on the data link layer within the network.
+type MacAddress struct {
+ _ struct{} `fidl2:"s,6,1"`
+ Octets [6]uint8
+}
+
+var _mMacAddress = _bindings.CreateLazyMarshaler(MacAddress{})
+
+func (msg *MacAddress) Marshaler() _bindings.Marshaler {
+ return _mMacAddress
+}
+
+type AddrInfoHints struct {
+ _ struct{} `fidl2:"s,16,4"`
+ Flags int32
+ Family int32
+ SockType int32
+ Protocol int32
+}
+
+var _mAddrInfoHints = _bindings.CreateLazyMarshaler(AddrInfoHints{})
+
+func (msg *AddrInfoHints) Marshaler() _bindings.Marshaler {
+ return _mAddrInfoHints
+}
+
+type AddrStorage struct {
+ _ struct{} `fidl2:"s,20,4"`
+ Val [16]uint8
+ Len uint32
+}
+
+var _mAddrStorage = _bindings.CreateLazyMarshaler(AddrStorage{})
+
+func (msg *AddrStorage) Marshaler() _bindings.Marshaler {
+ return _mAddrStorage
+}
+
+type AddrInfo struct {
+ _ struct{} `fidl2:"s,40,4"`
+ Flags int32
+ Family int32
+ SockType int32
+ Protocol int32
+ Addr AddrStorage
+ Port uint16
+}
+
+var _mAddrInfo = _bindings.CreateLazyMarshaler(AddrInfo{})
+
+func (msg *AddrInfo) Marshaler() _bindings.Marshaler {
+ return _mAddrInfo
+}
+
+type NameLookupLookupIpResultTag uint32
+
+const (
+ _ NameLookupLookupIpResultTag = iota
+ NameLookupLookupIpResultResponse
+ NameLookupLookupIpResultErr
+)
+
+type NameLookupLookupIpResult struct {
+ NameLookupLookupIpResultTag `fidl:"tag" fidl2:"u,56,8"`
+ Response NameLookupLookupIpResponse
+ Err LookupError
+}
+
+func (u *NameLookupLookupIpResult) Which() NameLookupLookupIpResultTag {
+ return u.NameLookupLookupIpResultTag
+}
+
+func (u *NameLookupLookupIpResult) SetResponse(response NameLookupLookupIpResponse) {
+ u.NameLookupLookupIpResultTag = NameLookupLookupIpResultResponse
+ u.Response = response
+}
+
+func (u *NameLookupLookupIpResult) SetErr(err LookupError) {
+ u.NameLookupLookupIpResultTag = NameLookupLookupIpResultErr
+ u.Err = err
+}
+
+type NameLookupLookupHostnameResultTag uint32
+
+const (
+ _ NameLookupLookupHostnameResultTag = iota
+ NameLookupLookupHostnameResultResponse
+ NameLookupLookupHostnameResultErr
+)
+
+type NameLookupLookupHostnameResult struct {
+ NameLookupLookupHostnameResultTag `fidl:"tag" fidl2:"u,24,8"`
+ Response NameLookupLookupHostnameResponse
+ Err LookupError
+}
+
+func (u *NameLookupLookupHostnameResult) Which() NameLookupLookupHostnameResultTag {
+ return u.NameLookupLookupHostnameResultTag
+}
+
+func (u *NameLookupLookupHostnameResult) SetResponse(response NameLookupLookupHostnameResponse) {
+ u.NameLookupLookupHostnameResultTag = NameLookupLookupHostnameResultResponse
+ u.Response = response
+}
+
+func (u *NameLookupLookupHostnameResult) SetErr(err LookupError) {
+ u.NameLookupLookupHostnameResultTag = NameLookupLookupHostnameResultErr
+ u.Err = err
+}
+
+type IpAddressTag uint32
+
+const (
+ _ IpAddressTag = iota
+ IpAddressIpv4
+ IpAddressIpv6
+)
+
+// Represents an IP address that may be either v4 or v6.
+type IpAddress struct {
+ IpAddressTag `fidl:"tag" fidl2:"u,20,4"`
+ Ipv4 Ipv4Address
+ Ipv6 Ipv6Address
+}
+
+func (u *IpAddress) Which() IpAddressTag {
+ return u.IpAddressTag
+}
+
+func (u *IpAddress) SetIpv4(ipv4 Ipv4Address) {
+ u.IpAddressTag = IpAddressIpv4
+ u.Ipv4 = ipv4
+}
+
+func (u *IpAddress) SetIpv6(ipv6 Ipv6Address) {
+ u.IpAddressTag = IpAddressIpv6
+ u.Ipv6 = ipv6
+}
+
+type LookupIpOptions struct {
+ _ struct{} `fidl2:"t,16,8"`
+ // If the lookup should return IPv4 addresses.
+ // Defaults to true.
+ V4Addrs bool `fidl:"1" fidl2:"1"`
+ V4AddrsPresent bool
+ // If the lookup should return IPv6 addresses.
+ // Defaults to true.
+ V6Addrs bool `fidl:"2" fidl2:"2"`
+ V6AddrsPresent bool
+ // If the lookup should return a canonical_name, if one exists.
+ // Defaults to false.
+ CnameLookup bool `fidl:"3" fidl2:"3"`
+ CnameLookupPresent bool
+}
+
+func (u *LookupIpOptions) SetV4Addrs(v4Addrs bool) {
+ u.V4Addrs = v4Addrs
+ u.V4AddrsPresent = true
+}
+
+func (u *LookupIpOptions) GetV4Addrs() bool {
+ return u.V4Addrs
+}
+
+func (u *LookupIpOptions) GetV4AddrsWithDefault(_default bool) bool {
+ if !u.HasV4Addrs() {
+ return _default
+ }
+ return u.V4Addrs
+}
+
+func (u *LookupIpOptions) HasV4Addrs() bool {
+ return u.V4AddrsPresent
+}
+
+func (u *LookupIpOptions) ClearV4Addrs() {
+ u.V4AddrsPresent = false
+}
+
+func (u *LookupIpOptions) SetV6Addrs(v6Addrs bool) {
+ u.V6Addrs = v6Addrs
+ u.V6AddrsPresent = true
+}
+
+func (u *LookupIpOptions) GetV6Addrs() bool {
+ return u.V6Addrs
+}
+
+func (u *LookupIpOptions) GetV6AddrsWithDefault(_default bool) bool {
+ if !u.HasV6Addrs() {
+ return _default
+ }
+ return u.V6Addrs
+}
+
+func (u *LookupIpOptions) HasV6Addrs() bool {
+ return u.V6AddrsPresent
+}
+
+func (u *LookupIpOptions) ClearV6Addrs() {
+ u.V6AddrsPresent = false
+}
+
+func (u *LookupIpOptions) SetCnameLookup(cnameLookup bool) {
+ u.CnameLookup = cnameLookup
+ u.CnameLookupPresent = true
+}
+
+func (u *LookupIpOptions) GetCnameLookup() bool {
+ return u.CnameLookup
+}
+
+func (u *LookupIpOptions) GetCnameLookupWithDefault(_default bool) bool {
+ if !u.HasCnameLookup() {
+ return _default
+ }
+ return u.CnameLookup
+}
+
+func (u *LookupIpOptions) HasCnameLookup() bool {
+ return u.CnameLookupPresent
+}
+
+func (u *LookupIpOptions) ClearCnameLookup() {
+ u.CnameLookupPresent = false
+}
+
+const (
+ ConnectivityOnNetworkReachableOrdinal uint32 = 1703348424
+ ConnectivityOnNetworkReachableGenOrdinal uint32 = 1703348424
+)
+
+type connectivityOnNetworkReachableResponse struct {
+ _ struct{} `fidl2:"s,8,0"`
+ Reachable bool
+}
+
+var _mconnectivityOnNetworkReachableResponse = _bindings.CreateLazyMarshaler(connectivityOnNetworkReachableResponse{})
+
+func (msg *connectivityOnNetworkReachableResponse) Marshaler() _bindings.Marshaler {
+ return _mconnectivityOnNetworkReachableResponse
+}
+
+type ConnectivityInterface _bindings.ChannelProxy
+
+// This is triggered on a state change in network reachability. Clients
+// should expect that network requests will succeed when |reachable| is
+// true.
+func (p *ConnectivityInterface) ExpectOnNetworkReachable() (bool, error) {
+ resp_ := &connectivityOnNetworkReachableResponse{}
+ err := ((*_bindings.ChannelProxy)(p)).RecvNew(ConnectivityOnNetworkReachableOrdinal, resp_)
+ return resp_.Reachable, err
+}
+
+type Connectivity interface {
+ // This is triggered on a state change in network reachability. Clients
+ // should expect that network requests will succeed when |reachable| is
+ // true.
+}
+
+type ConnectivityTransitionalBase struct{}
+
+type ConnectivityInterfaceRequest _bindings.InterfaceRequest
+
+func NewConnectivityInterfaceRequest() (ConnectivityInterfaceRequest, *ConnectivityInterface, error) {
+ req, cli, err := _bindings.NewInterfaceRequest()
+ return ConnectivityInterfaceRequest(req), (*ConnectivityInterface)(cli), err
+}
+
+// Implements ServiceRequest.
+func (_ ConnectivityInterfaceRequest) Name() string {
+ return "fuchsia.net.Connectivity"
+}
+func (c ConnectivityInterfaceRequest) ToChannel() _zx.Channel {
+ return c.Channel
+}
+
+const ConnectivityName = "fuchsia.net.Connectivity"
+
+type ConnectivityStub struct {
+ Impl Connectivity
+}
+
+func (s *ConnectivityStub) DispatchNew(ord uint32, b_ []byte, h_ []_zx.Handle) (_bindings.Message, error) {
+ switch ord {
+ }
+ return nil, _bindings.ErrUnknownOrdinal
+}
+
+type ConnectivityService struct {
+ _bindings.BindingSet
+}
+
+func (s *ConnectivityService) Add(impl Connectivity, c _zx.Channel, onError func(error)) (_bindings.BindingKey, error) {
+ return s.BindingSet.Add(&ConnectivityStub{Impl: impl}, c, onError)
+}
+
+func (s *ConnectivityService) EventProxyFor(key _bindings.BindingKey) (*ConnectivityEventProxy, bool) {
+ pxy, err := s.BindingSet.ProxyFor(key)
+ return (*ConnectivityEventProxy)(pxy), err
+}
+
+type ConnectivityEventProxy _bindings.ChannelProxy
+
+func (p *ConnectivityEventProxy) OnNetworkReachable(reachable bool) error {
+ event_ := &connectivityOnNetworkReachableResponse{
+ Reachable: reachable,
+ }
+ return ((*_bindings.ChannelProxy)(p)).SendNew(ConnectivityOnNetworkReachableOrdinal, event_)
+}
+
+const (
+ NameLookupLookupIpOrdinal uint32 = 818031436
+ NameLookupLookupIpGenOrdinal uint32 = 818031436
+ NameLookupLookupHostnameOrdinal uint32 = 391654548
+ NameLookupLookupHostnameGenOrdinal uint32 = 391654548
+)
+
+type nameLookupLookupIpRequest struct {
+ _ struct{} `fidl2:"s,32,0"`
+ Hostname string
+ Options LookupIpOptions
+}
+
+var _mnameLookupLookupIpRequest = _bindings.CreateLazyMarshaler(nameLookupLookupIpRequest{})
+
+func (msg *nameLookupLookupIpRequest) Marshaler() _bindings.Marshaler {
+ return _mnameLookupLookupIpRequest
+}
+
+type nameLookupLookupIpResponse struct {
+ _ struct{} `fidl2:"s,56,0"`
+ Result NameLookupLookupIpResult
+}
+
+var _mnameLookupLookupIpResponse = _bindings.CreateLazyMarshaler(nameLookupLookupIpResponse{})
+
+func (msg *nameLookupLookupIpResponse) Marshaler() _bindings.Marshaler {
+ return _mnameLookupLookupIpResponse
+}
+
+type nameLookupLookupHostnameRequest struct {
+ _ struct{} `fidl2:"s,24,0"`
+ Addr IpAddress
+}
+
+var _mnameLookupLookupHostnameRequest = _bindings.CreateLazyMarshaler(nameLookupLookupHostnameRequest{})
+
+func (msg *nameLookupLookupHostnameRequest) Marshaler() _bindings.Marshaler {
+ return _mnameLookupLookupHostnameRequest
+}
+
+type nameLookupLookupHostnameResponse struct {
+ _ struct{} `fidl2:"s,24,0"`
+ Result NameLookupLookupHostnameResult
+}
+
+var _mnameLookupLookupHostnameResponse = _bindings.CreateLazyMarshaler(nameLookupLookupHostnameResponse{})
+
+func (msg *nameLookupLookupHostnameResponse) Marshaler() _bindings.Marshaler {
+ return _mnameLookupLookupHostnameResponse
+}
+
+type NameLookupInterface _bindings.ChannelProxy
+
+// Look up a list of IP addresses by hostname.
+//
+// If |hostname| is an Internationalized Domain Name, it must be encoded as per RFC 3490.
+func (p *NameLookupInterface) LookupIp(hostname string, options LookupIpOptions) (NameLookupLookupIpResult, error) {
+ req_ := &nameLookupLookupIpRequest{
+ Hostname: hostname,
+ Options: options,
+ }
+ resp_ := &nameLookupLookupIpResponse{}
+ err := ((*_bindings.ChannelProxy)(p)).CallNew(NameLookupLookupIpOrdinal, req_, resp_)
+ return resp_.Result, err
+}
+
+// Look up a hostname by IP address.
+func (p *NameLookupInterface) LookupHostname(addr IpAddress) (NameLookupLookupHostnameResult, error) {
+ req_ := &nameLookupLookupHostnameRequest{
+ Addr: addr,
+ }
+ resp_ := &nameLookupLookupHostnameResponse{}
+ err := ((*_bindings.ChannelProxy)(p)).CallNew(NameLookupLookupHostnameOrdinal, req_, resp_)
+ return resp_.Result, err
+}
+
+type NameLookup interface {
+ // Look up a list of IP addresses by hostname.
+ //
+ // If |hostname| is an Internationalized Domain Name, it must be encoded as per RFC 3490.
+ LookupIp(hostname string, options LookupIpOptions) (NameLookupLookupIpResult, error)
+ // Look up a hostname by IP address.
+ LookupHostname(addr IpAddress) (NameLookupLookupHostnameResult, error)
+}
+
+type NameLookupTransitionalBase struct{}
+
+type NameLookupInterfaceRequest _bindings.InterfaceRequest
+
+func NewNameLookupInterfaceRequest() (NameLookupInterfaceRequest, *NameLookupInterface, error) {
+ req, cli, err := _bindings.NewInterfaceRequest()
+ return NameLookupInterfaceRequest(req), (*NameLookupInterface)(cli), err
+}
+
+// Implements ServiceRequest.
+func (_ NameLookupInterfaceRequest) Name() string {
+ return "fuchsia.net.NameLookup"
+}
+func (c NameLookupInterfaceRequest) ToChannel() _zx.Channel {
+ return c.Channel
+}
+
+const NameLookupName = "fuchsia.net.NameLookup"
+
+type NameLookupStub struct {
+ Impl NameLookup
+}
+
+func (s *NameLookupStub) DispatchNew(ord uint32, b_ []byte, h_ []_zx.Handle) (_bindings.Message, error) {
+ switch ord {
+ case NameLookupLookupIpOrdinal:
+ in_ := nameLookupLookupIpRequest{}
+ if _, _, err_ := _bindings.UnmarshalNew(b_, h_, &in_); err_ != nil {
+ return nil, err_
+ }
+ result, err_ := s.Impl.LookupIp(in_.Hostname, in_.Options)
+ out_ := nameLookupLookupIpResponse{}
+ out_.Result = result
+ return &out_, err_
+ case NameLookupLookupHostnameOrdinal:
+ in_ := nameLookupLookupHostnameRequest{}
+ if _, _, err_ := _bindings.UnmarshalNew(b_, h_, &in_); err_ != nil {
+ return nil, err_
+ }
+ result, err_ := s.Impl.LookupHostname(in_.Addr)
+ out_ := nameLookupLookupHostnameResponse{}
+ out_.Result = result
+ return &out_, err_
+ }
+ return nil, _bindings.ErrUnknownOrdinal
+}
+
+type NameLookupService struct {
+ _bindings.BindingSet
+}
+
+func (s *NameLookupService) Add(impl NameLookup, c _zx.Channel, onError func(error)) (_bindings.BindingKey, error) {
+ return s.BindingSet.Add(&NameLookupStub{Impl: impl}, c, onError)
+}
+
+func (s *NameLookupService) EventProxyFor(key _bindings.BindingKey) (*NameLookupEventProxy, bool) {
+ pxy, err := s.BindingSet.ProxyFor(key)
+ return (*NameLookupEventProxy)(pxy), err
+}
+
+type NameLookupEventProxy _bindings.ChannelProxy
+
+const (
+ SocketProviderSocketOrdinal uint32 = 316444173
+ SocketProviderSocketGenOrdinal uint32 = 316444173
+ SocketProviderGetAddrInfoOrdinal uint32 = 498796293
+ SocketProviderGetAddrInfoGenOrdinal uint32 = 498796293
+)
+
+type socketProviderSocketRequest struct {
+ _ struct{} `fidl2:"s,8,0"`
+ Domain int16
+ Type int16
+ Protocol int16
+}
+
+var _msocketProviderSocketRequest = _bindings.CreateLazyMarshaler(socketProviderSocketRequest{})
+
+func (msg *socketProviderSocketRequest) Marshaler() _bindings.Marshaler {
+ return _msocketProviderSocketRequest
+}
+
+type socketProviderSocketResponse struct {
+ _ struct{} `fidl2:"s,8,0"`
+ Code int16
+ S _zx.Socket `fidl:"*" fidl2:"1"`
+}
+
+var _msocketProviderSocketResponse = _bindings.CreateLazyMarshaler(socketProviderSocketResponse{})
+
+func (msg *socketProviderSocketResponse) Marshaler() _bindings.Marshaler {
+ return _msocketProviderSocketResponse
+}
+
+type socketProviderGetAddrInfoRequest struct {
+ _ struct{} `fidl2:"s,40,0"`
+ Node *string `fidl:"256" fidl2:"256"`
+ Service *string `fidl:"256" fidl2:"256"`
+ Hints *AddrInfoHints
+}
+
+var _msocketProviderGetAddrInfoRequest = _bindings.CreateLazyMarshaler(socketProviderGetAddrInfoRequest{})
+
+func (msg *socketProviderGetAddrInfoRequest) Marshaler() _bindings.Marshaler {
+ return _msocketProviderGetAddrInfoRequest
+}
+
+type socketProviderGetAddrInfoResponse struct {
+ _ struct{} `fidl2:"s,168,0"`
+ Status AddrInfoStatus
+ Nres uint32
+ Res [4]AddrInfo
+}
+
+var _msocketProviderGetAddrInfoResponse = _bindings.CreateLazyMarshaler(socketProviderGetAddrInfoResponse{})
+
+func (msg *socketProviderGetAddrInfoResponse) Marshaler() _bindings.Marshaler {
+ return _msocketProviderGetAddrInfoResponse
+}
+
+type SocketProviderInterface _bindings.ChannelProxy
+
+// Requests a socket with the specified parameters. Values for |code| are defined in
+// errno.h.
+func (p *SocketProviderInterface) Socket(domain int16, type_ int16, protocol int16) (int16, _zx.Socket, error) {
+ req_ := &socketProviderSocketRequest{
+ Domain: domain,
+ Type: type_,
+ Protocol: protocol,
+ }
+ resp_ := &socketProviderSocketResponse{}
+ err := ((*_bindings.ChannelProxy)(p)).CallNew(SocketProviderSocketOrdinal, req_, resp_)
+ return resp_.Code, resp_.S, err
+}
+
+// Retrieves information about the address of a node and/or service. The number of valid
+// results in |res| is given by the |count| return value.
+func (p *SocketProviderInterface) GetAddrInfo(node *string, service *string, hints *AddrInfoHints) (AddrInfoStatus, uint32, [4]AddrInfo, error) {
+ req_ := &socketProviderGetAddrInfoRequest{
+ Node: node,
+ Service: service,
+ Hints: hints,
+ }
+ resp_ := &socketProviderGetAddrInfoResponse{}
+ err := ((*_bindings.ChannelProxy)(p)).CallNew(SocketProviderGetAddrInfoOrdinal, req_, resp_)
+ return resp_.Status, resp_.Nres, resp_.Res, err
+}
+
+// SocketProvider implements the POSIX sockets API.
+type SocketProvider interface {
+ // Requests a socket with the specified parameters. Values for |code| are defined in
+ // errno.h.
+ Socket(domain int16, type_ int16, protocol int16) (int16, _zx.Socket, error)
+ // Retrieves information about the address of a node and/or service. The number of valid
+ // results in |res| is given by the |count| return value.
+ GetAddrInfo(node *string, service *string, hints *AddrInfoHints) (AddrInfoStatus, uint32, [4]AddrInfo, error)
+}
+
+type SocketProviderTransitionalBase struct{}
+
+type SocketProviderInterfaceRequest _bindings.InterfaceRequest
+
+func NewSocketProviderInterfaceRequest() (SocketProviderInterfaceRequest, *SocketProviderInterface, error) {
+ req, cli, err := _bindings.NewInterfaceRequest()
+ return SocketProviderInterfaceRequest(req), (*SocketProviderInterface)(cli), err
+}
+
+// Implements ServiceRequest.
+func (_ SocketProviderInterfaceRequest) Name() string {
+ return "fuchsia.net.SocketProvider"
+}
+func (c SocketProviderInterfaceRequest) ToChannel() _zx.Channel {
+ return c.Channel
+}
+
+const SocketProviderName = "fuchsia.net.SocketProvider"
+
+type SocketProviderStub struct {
+ Impl SocketProvider
+}
+
+func (s *SocketProviderStub) DispatchNew(ord uint32, b_ []byte, h_ []_zx.Handle) (_bindings.Message, error) {
+ switch ord {
+ case SocketProviderSocketOrdinal:
+ in_ := socketProviderSocketRequest{}
+ if _, _, err_ := _bindings.UnmarshalNew(b_, h_, &in_); err_ != nil {
+ return nil, err_
+ }
+ code, s, err_ := s.Impl.Socket(in_.Domain, in_.Type, in_.Protocol)
+ out_ := socketProviderSocketResponse{}
+ out_.Code = code
+ out_.S = s
+ return &out_, err_
+ case SocketProviderGetAddrInfoOrdinal:
+ in_ := socketProviderGetAddrInfoRequest{}
+ if _, _, err_ := _bindings.UnmarshalNew(b_, h_, &in_); err_ != nil {
+ return nil, err_
+ }
+ status, nres, res, err_ := s.Impl.GetAddrInfo(in_.Node, in_.Service, in_.Hints)
+ out_ := socketProviderGetAddrInfoResponse{}
+ out_.Status = status
+ out_.Nres = nres
+ out_.Res = res
+ return &out_, err_
+ }
+ return nil, _bindings.ErrUnknownOrdinal
+}
+
+type SocketProviderService struct {
+ _bindings.BindingSet
+}
+
+func (s *SocketProviderService) Add(impl SocketProvider, c _zx.Channel, onError func(error)) (_bindings.BindingKey, error) {
+ return s.BindingSet.Add(&SocketProviderStub{Impl: impl}, c, onError)
+}
+
+func (s *SocketProviderService) EventProxyFor(key _bindings.BindingKey) (*SocketProviderEventProxy, bool) {
+ pxy, err := s.BindingSet.ProxyFor(key)
+ return (*SocketProviderEventProxy)(pxy), err
+}
+
+type SocketProviderEventProxy _bindings.ChannelProxy
+
+const (
+ SocketControlBindOrdinal uint32 = 2092731140
+ SocketControlBindGenOrdinal uint32 = 2092731140
+ SocketControlConnectOrdinal uint32 = 345505709
+ SocketControlConnectGenOrdinal uint32 = 345505709
+ SocketControlListenOrdinal uint32 = 1117818704
+ SocketControlListenGenOrdinal uint32 = 1117818704
+ SocketControlAcceptOrdinal uint32 = 796734679
+ SocketControlAcceptGenOrdinal uint32 = 796734679
+ SocketControlCloseOrdinal uint32 = 506040350
+ SocketControlCloseGenOrdinal uint32 = 506040350
+ SocketControlGetSockNameOrdinal uint32 = 764939941
+ SocketControlGetSockNameGenOrdinal uint32 = 764939941
+ SocketControlGetPeerNameOrdinal uint32 = 472396488
+ SocketControlGetPeerNameGenOrdinal uint32 = 472396488
+ SocketControlSetSockOptOrdinal uint32 = 1365685084
+ SocketControlSetSockOptGenOrdinal uint32 = 1365685084
+ SocketControlGetSockOptOrdinal uint32 = 2132650507
+ SocketControlGetSockOptGenOrdinal uint32 = 2132650507
+ SocketControlIoctlOrdinal uint32 = 1157859964
+ SocketControlIoctlGenOrdinal uint32 = 1157859964
+)
+
+type socketControlBindRequest struct {
+ _ struct{} `fidl2:"s,16,0"`
+ Addr []uint8 `fidl:"128" fidl2:"128"`
+}
+
+var _msocketControlBindRequest = _bindings.CreateLazyMarshaler(socketControlBindRequest{})
+
+func (msg *socketControlBindRequest) Marshaler() _bindings.Marshaler {
+ return _msocketControlBindRequest
+}
+
+type socketControlBindResponse struct {
+ _ struct{} `fidl2:"s,8,0"`
+ Code int16
+}
+
+var _msocketControlBindResponse = _bindings.CreateLazyMarshaler(socketControlBindResponse{})
+
+func (msg *socketControlBindResponse) Marshaler() _bindings.Marshaler {
+ return _msocketControlBindResponse
+}
+
+type socketControlConnectRequest struct {
+ _ struct{} `fidl2:"s,16,0"`
+ Addr []uint8 `fidl:"128" fidl2:"128"`
+}
+
+var _msocketControlConnectRequest = _bindings.CreateLazyMarshaler(socketControlConnectRequest{})
+
+func (msg *socketControlConnectRequest) Marshaler() _bindings.Marshaler {
+ return _msocketControlConnectRequest
+}
+
+type socketControlConnectResponse struct {
+ _ struct{} `fidl2:"s,8,0"`
+ Code int16
+}
+
+var _msocketControlConnectResponse = _bindings.CreateLazyMarshaler(socketControlConnectResponse{})
+
+func (msg *socketControlConnectResponse) Marshaler() _bindings.Marshaler {
+ return _msocketControlConnectResponse
+}
+
+type socketControlListenRequest struct {
+ _ struct{} `fidl2:"s,8,0"`
+ Backlog int16
+}
+
+var _msocketControlListenRequest = _bindings.CreateLazyMarshaler(socketControlListenRequest{})
+
+func (msg *socketControlListenRequest) Marshaler() _bindings.Marshaler {
+ return _msocketControlListenRequest
+}
+
+type socketControlListenResponse struct {
+ _ struct{} `fidl2:"s,8,0"`
+ Code int16
+}
+
+var _msocketControlListenResponse = _bindings.CreateLazyMarshaler(socketControlListenResponse{})
+
+func (msg *socketControlListenResponse) Marshaler() _bindings.Marshaler {
+ return _msocketControlListenResponse
+}
+
+type socketControlAcceptRequest struct {
+ _ struct{} `fidl2:"s,8,0"`
+ Flags int16
+}
+
+var _msocketControlAcceptRequest = _bindings.CreateLazyMarshaler(socketControlAcceptRequest{})
+
+func (msg *socketControlAcceptRequest) Marshaler() _bindings.Marshaler {
+ return _msocketControlAcceptRequest
+}
+
+type socketControlAcceptResponse struct {
+ _ struct{} `fidl2:"s,8,0"`
+ Code int16
+}
+
+var _msocketControlAcceptResponse = _bindings.CreateLazyMarshaler(socketControlAcceptResponse{})
+
+func (msg *socketControlAcceptResponse) Marshaler() _bindings.Marshaler {
+ return _msocketControlAcceptResponse
+}
+
+type socketControlCloseResponse struct {
+ _ struct{} `fidl2:"s,8,0"`
+ Code int16
+}
+
+var _msocketControlCloseResponse = _bindings.CreateLazyMarshaler(socketControlCloseResponse{})
+
+func (msg *socketControlCloseResponse) Marshaler() _bindings.Marshaler {
+ return _msocketControlCloseResponse
+}
+
+type socketControlGetSockNameResponse struct {
+ _ struct{} `fidl2:"s,24,0"`
+ Code int16
+ Addr []uint8 `fidl:"128" fidl2:"128"`
+}
+
+var _msocketControlGetSockNameResponse = _bindings.CreateLazyMarshaler(socketControlGetSockNameResponse{})
+
+func (msg *socketControlGetSockNameResponse) Marshaler() _bindings.Marshaler {
+ return _msocketControlGetSockNameResponse
+}
+
+type socketControlGetPeerNameResponse struct {
+ _ struct{} `fidl2:"s,24,0"`
+ Code int16
+ Addr []uint8 `fidl:"128" fidl2:"128"`
+}
+
+var _msocketControlGetPeerNameResponse = _bindings.CreateLazyMarshaler(socketControlGetPeerNameResponse{})
+
+func (msg *socketControlGetPeerNameResponse) Marshaler() _bindings.Marshaler {
+ return _msocketControlGetPeerNameResponse
+}
+
+type socketControlSetSockOptRequest struct {
+ _ struct{} `fidl2:"s,24,0"`
+ Level int16
+ Optname int16
+ Optval []uint8 `fidl:"900" fidl2:"900"`
+}
+
+var _msocketControlSetSockOptRequest = _bindings.CreateLazyMarshaler(socketControlSetSockOptRequest{})
+
+func (msg *socketControlSetSockOptRequest) Marshaler() _bindings.Marshaler {
+ return _msocketControlSetSockOptRequest
+}
+
+type socketControlSetSockOptResponse struct {
+ _ struct{} `fidl2:"s,8,0"`
+ Code int16
+}
+
+var _msocketControlSetSockOptResponse = _bindings.CreateLazyMarshaler(socketControlSetSockOptResponse{})
+
+func (msg *socketControlSetSockOptResponse) Marshaler() _bindings.Marshaler {
+ return _msocketControlSetSockOptResponse
+}
+
+type socketControlGetSockOptRequest struct {
+ _ struct{} `fidl2:"s,8,0"`
+ Level int16
+ Optname int16
+}
+
+var _msocketControlGetSockOptRequest = _bindings.CreateLazyMarshaler(socketControlGetSockOptRequest{})
+
+func (msg *socketControlGetSockOptRequest) Marshaler() _bindings.Marshaler {
+ return _msocketControlGetSockOptRequest
+}
+
+type socketControlGetSockOptResponse struct {
+ _ struct{} `fidl2:"s,24,0"`
+ Code int16
+ Optval []uint8 `fidl:"900" fidl2:"900"`
+}
+
+var _msocketControlGetSockOptResponse = _bindings.CreateLazyMarshaler(socketControlGetSockOptResponse{})
+
+func (msg *socketControlGetSockOptResponse) Marshaler() _bindings.Marshaler {
+ return _msocketControlGetSockOptResponse
+}
+
+type socketControlIoctlRequest struct {
+ _ struct{} `fidl2:"s,24,0"`
+ Req int16
+ In []uint8 `fidl:"900" fidl2:"900"`
+}
+
+var _msocketControlIoctlRequest = _bindings.CreateLazyMarshaler(socketControlIoctlRequest{})
+
+func (msg *socketControlIoctlRequest) Marshaler() _bindings.Marshaler {
+ return _msocketControlIoctlRequest
+}
+
+type socketControlIoctlResponse struct {
+ _ struct{} `fidl2:"s,24,0"`
+ Code int16
+ Out []uint8 `fidl:"900" fidl2:"900"`
+}
+
+var _msocketControlIoctlResponse = _bindings.CreateLazyMarshaler(socketControlIoctlResponse{})
+
+func (msg *socketControlIoctlResponse) Marshaler() _bindings.Marshaler {
+ return _msocketControlIoctlResponse
+}
+
+type SocketControlInterface _bindings.SocketControlProxy
+
+// Sets the local address used for the socket.
+func (p *SocketControlInterface) Bind(addr []uint8) (int16, error) {
+ req_ := &socketControlBindRequest{
+ Addr: addr,
+ }
+ resp_ := &socketControlBindResponse{}
+ err := ((*_bindings.SocketControlProxy)(p)).CallNew(SocketControlBindOrdinal, req_, resp_)
+ return resp_.Code, err
+}
+
+// Initiates a connection to a network endpoint.
+func (p *SocketControlInterface) Connect(addr []uint8) (int16, error) {
+ req_ := &socketControlConnectRequest{
+ Addr: addr,
+ }
+ resp_ := &socketControlConnectResponse{}
+ err := ((*_bindings.SocketControlProxy)(p)).CallNew(SocketControlConnectOrdinal, req_, resp_)
+ return resp_.Code, err
+}
+
+// Begin listening for new connections from network endpoints. At most |backlog| connections
+// will be buffered.
+func (p *SocketControlInterface) Listen(backlog int16) (int16, error) {
+ req_ := &socketControlListenRequest{
+ Backlog: backlog,
+ }
+ resp_ := &socketControlListenResponse{}
+ err := ((*_bindings.SocketControlProxy)(p)).CallNew(SocketControlListenOrdinal, req_, resp_)
+ return resp_.Code, err
+}
+
+// Accepts an incoming connection from a network endpoint.
+func (p *SocketControlInterface) Accept(flags int16) (int16, error) {
+ req_ := &socketControlAcceptRequest{
+ Flags: flags,
+ }
+ resp_ := &socketControlAcceptResponse{}
+ err := ((*_bindings.SocketControlProxy)(p)).CallNew(SocketControlAcceptOrdinal, req_, resp_)
+ return resp_.Code, err
+}
+
+// Closes the socket.
+func (p *SocketControlInterface) Close() (int16, error) {
+ var req_ _bindings.Message
+ resp_ := &socketControlCloseResponse{}
+ err := ((*_bindings.SocketControlProxy)(p)).CallNew(SocketControlCloseOrdinal, req_, resp_)
+ return resp_.Code, err
+}
+
+// Retrieves the local socket address.
+func (p *SocketControlInterface) GetSockName() (int16, []uint8, error) {
+ var req_ _bindings.Message
+ resp_ := &socketControlGetSockNameResponse{}
+ err := ((*_bindings.SocketControlProxy)(p)).CallNew(SocketControlGetSockNameOrdinal, req_, resp_)
+ return resp_.Code, resp_.Addr, err
+}
+
+// Retrieves the remote socket address.
+func (p *SocketControlInterface) GetPeerName() (int16, []uint8, error) {
+ var req_ _bindings.Message
+ resp_ := &socketControlGetPeerNameResponse{}
+ err := ((*_bindings.SocketControlProxy)(p)).CallNew(SocketControlGetPeerNameOrdinal, req_, resp_)
+ return resp_.Code, resp_.Addr, err
+}
+
+// Sets a socket option. TODO(NET-1699): link to description of supported socket options.
+func (p *SocketControlInterface) SetSockOpt(level int16, optname int16, optval []uint8) (int16, error) {
+ req_ := &socketControlSetSockOptRequest{
+ Level: level,
+ Optname: optname,
+ Optval: optval,
+ }
+ resp_ := &socketControlSetSockOptResponse{}
+ err := ((*_bindings.SocketControlProxy)(p)).CallNew(SocketControlSetSockOptOrdinal, req_, resp_)
+ return resp_.Code, err
+}
+
+// Retrieves the current value of a socket option. TODO(NET-1699): link to description of
+// supported socket options.
+func (p *SocketControlInterface) GetSockOpt(level int16, optname int16) (int16, []uint8, error) {
+ req_ := &socketControlGetSockOptRequest{
+ Level: level,
+ Optname: optname,
+ }
+ resp_ := &socketControlGetSockOptResponse{}
+ err := ((*_bindings.SocketControlProxy)(p)).CallNew(SocketControlGetSockOptOrdinal, req_, resp_)
+ return resp_.Code, resp_.Optval, err
+}
+
+// Runs operations (e.g., get the receive timestamp of the last packet) on the socket.
+func (p *SocketControlInterface) Ioctl(req int16, in []uint8) (int16, []uint8, error) {
+ req_ := &socketControlIoctlRequest{
+ Req: req,
+ In: in,
+ }
+ resp_ := &socketControlIoctlResponse{}
+ err := ((*_bindings.SocketControlProxy)(p)).CallNew(SocketControlIoctlOrdinal, req_, resp_)
+ return resp_.Code, resp_.Out, err
+}
+
+// The control plane for a network socket. Once a socket has been retrieved from a
+// |SocketProvider|, this interface is then used to further configure and use the socket.
+// This interface is essentially POSIX. Its implementation must support Linux-specific arguments
+// to {Get,Set}SockOpt.
+type SocketControl interface {
+ // Sets the local address used for the socket.
+ Bind(addr []uint8) (int16, error)
+ // Initiates a connection to a network endpoint.
+ Connect(addr []uint8) (int16, error)
+ // Begin listening for new connections from network endpoints. At most |backlog| connections
+ // will be buffered.
+ Listen(backlog int16) (int16, error)
+ // Accepts an incoming connection from a network endpoint.
+ Accept(flags int16) (int16, error)
+ // Closes the socket.
+ Close() (int16, error)
+ // Retrieves the local socket address.
+ GetSockName() (int16, []uint8, error)
+ // Retrieves the remote socket address.
+ GetPeerName() (int16, []uint8, error)
+ // Sets a socket option. TODO(NET-1699): link to description of supported socket options.
+ SetSockOpt(level int16, optname int16, optval []uint8) (int16, error)
+ // Retrieves the current value of a socket option. TODO(NET-1699): link to description of
+ // supported socket options.
+ GetSockOpt(level int16, optname int16) (int16, []uint8, error)
+ // Runs operations (e.g., get the receive timestamp of the last packet) on the socket.
+ Ioctl(req int16, in []uint8) (int16, []uint8, error)
+}
+
+type SocketControlTransitionalBase struct{}
+
+type SocketControlStub struct {
+ Impl SocketControl
+}
+
+func (s *SocketControlStub) DispatchNew(ord uint32, b_ []byte, h_ []_zx.Handle) (_bindings.Message, error) {
+ switch ord {
+ case SocketControlBindOrdinal:
+ in_ := socketControlBindRequest{}
+ if _, _, err_ := _bindings.UnmarshalNew(b_, h_, &in_); err_ != nil {
+ return nil, err_
+ }
+ code, err_ := s.Impl.Bind(in_.Addr)
+ out_ := socketControlBindResponse{}
+ out_.Code = code
+ return &out_, err_
+ case SocketControlConnectOrdinal:
+ in_ := socketControlConnectRequest{}
+ if _, _, err_ := _bindings.UnmarshalNew(b_, h_, &in_); err_ != nil {
+ return nil, err_
+ }
+ code, err_ := s.Impl.Connect(in_.Addr)
+ out_ := socketControlConnectResponse{}
+ out_.Code = code
+ return &out_, err_
+ case SocketControlListenOrdinal:
+ in_ := socketControlListenRequest{}
+ if _, _, err_ := _bindings.UnmarshalNew(b_, h_, &in_); err_ != nil {
+ return nil, err_
+ }
+ code, err_ := s.Impl.Listen(in_.Backlog)
+ out_ := socketControlListenResponse{}
+ out_.Code = code
+ return &out_, err_
+ case SocketControlAcceptOrdinal:
+ in_ := socketControlAcceptRequest{}
+ if _, _, err_ := _bindings.UnmarshalNew(b_, h_, &in_); err_ != nil {
+ return nil, err_
+ }
+ code, err_ := s.Impl.Accept(in_.Flags)
+ out_ := socketControlAcceptResponse{}
+ out_.Code = code
+ return &out_, err_
+ case SocketControlCloseOrdinal:
+ code, err_ := s.Impl.Close()
+ out_ := socketControlCloseResponse{}
+ out_.Code = code
+ return &out_, err_
+ case SocketControlGetSockNameOrdinal:
+ code, addr, err_ := s.Impl.GetSockName()
+ out_ := socketControlGetSockNameResponse{}
+ out_.Code = code
+ out_.Addr = addr
+ return &out_, err_
+ case SocketControlGetPeerNameOrdinal:
+ code, addr, err_ := s.Impl.GetPeerName()
+ out_ := socketControlGetPeerNameResponse{}
+ out_.Code = code
+ out_.Addr = addr
+ return &out_, err_
+ case SocketControlSetSockOptOrdinal:
+ in_ := socketControlSetSockOptRequest{}
+ if _, _, err_ := _bindings.UnmarshalNew(b_, h_, &in_); err_ != nil {
+ return nil, err_
+ }
+ code, err_ := s.Impl.SetSockOpt(in_.Level, in_.Optname, in_.Optval)
+ out_ := socketControlSetSockOptResponse{}
+ out_.Code = code
+ return &out_, err_
+ case SocketControlGetSockOptOrdinal:
+ in_ := socketControlGetSockOptRequest{}
+ if _, _, err_ := _bindings.UnmarshalNew(b_, h_, &in_); err_ != nil {
+ return nil, err_
+ }
+ code, optval, err_ := s.Impl.GetSockOpt(in_.Level, in_.Optname)
+ out_ := socketControlGetSockOptResponse{}
+ out_.Code = code
+ out_.Optval = optval
+ return &out_, err_
+ case SocketControlIoctlOrdinal:
+ in_ := socketControlIoctlRequest{}
+ if _, _, err_ := _bindings.UnmarshalNew(b_, h_, &in_); err_ != nil {
+ return nil, err_
+ }
+ code, out, err_ := s.Impl.Ioctl(in_.Req, in_.In)
+ out_ := socketControlIoctlResponse{}
+ out_.Code = code
+ out_.Out = out
+ return &out_, err_
+ }
+ return nil, _bindings.ErrUnknownOrdinal
+}
+
+type SocketControlEventProxy _bindings.SocketControlProxy
diff --git a/src/syscall/zx/net/stub.go b/src/syscall/zx/net/stub.go
new file mode 100644
index 0000000..7acadb6
--- /dev/null
+++ b/src/syscall/zx/net/stub.go
@@ -0,0 +1,3 @@
+//+build !fuchsia
+
+package net
diff --git a/src/syscall/zx/stub.go b/src/syscall/zx/stub.go
new file mode 100644
index 0000000..0aab9e4
--- /dev/null
+++ b/src/syscall/zx/stub.go
@@ -0,0 +1,3 @@
+//+build !fuchsia
+
+package zx
diff --git a/src/syscall/zx/syscalls_fuchsia.go b/src/syscall/zx/syscalls_fuchsia.go
new file mode 100644
index 0000000..264603d
--- /dev/null
+++ b/src/syscall/zx/syscalls_fuchsia.go
@@ -0,0 +1,546 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Zircon system calls for the Fuchsia OS.
+// Generated by mkfuchsia.go, do not edit.
+
+package zx
+
+import "unsafe"
+
+//go:noescape
+//go:nosplit
+func Sys_clock_get(clock_id uint32) Time
+
+//go:noescape
+//go:nosplit
+func Sys_clock_get_new(clock_id uint32, out *Time) Status
+
+//go:noescape
+//go:nosplit
+func Sys_clock_get_monotonic() Time
+
+//go:noescape
+//go:nosplit
+func Sys_nanosleep(deadline Time) Status
+
+//go:noescape
+//go:nosplit
+func Sys_ticks_get() uint64
+
+//go:noescape
+//go:nosplit
+func Sys_ticks_per_second() uint64
+
+//go:noescape
+//go:nosplit
+func Sys_deadline_after(nanoseconds Duration) Time
+
+//go:noescape
+//go:nosplit
+func Sys_clock_adjust(handle Handle, clock_id uint32, offset int64) Status
+
+//go:noescape
+//go:nosplit
+func sys_system_get_dcache_line_size() uint32
+
+//go:noescape
+//go:nosplit
+func Sys_system_get_num_cpus() uint32
+
+//go:noescape
+//go:nosplit
+func Sys_system_get_version(version *uint8, version_size uint) Status
+
+//go:noescape
+//go:nosplit
+func Sys_system_get_physmem() uint64
+
+//go:noescape
+//go:nosplit
+func sys_system_get_features(kind uint32, features *uint32) Status
+
+//go:noescape
+//go:nosplit
+func Sys_cache_flush(addr unsafe.Pointer, size uint, options uint32) Status
+
+//go:noescape
+//go:nosplit
+func Sys_handle_close(handle Handle) Status
+
+//go:noescape
+//go:nosplit
+func Sys_handle_close_many(handles *Handle, num_handles uint) Status
+
+//go:noescape
+//go:nosplit
+func sys_handle_duplicate(handle Handle, rights Rights, out *Handle) Status
+
+//go:noescape
+//go:nosplit
+func Sys_handle_replace(handle Handle, rights Rights, out *Handle) Status
+
+//go:noescape
+//go:nosplit
+func Sys_object_wait_one(handle Handle, signals Signals, deadline Time, observed *Signals) Status
+
+//go:noescape
+//go:nosplit
+func sys_object_wait_many(items *WaitItem, count uint, deadline Time) Status
+
+//go:noescape
+//go:nosplit
+func Sys_object_wait_async(handle Handle, port Handle, key uint64, signals Signals, options uint32) Status
+
+//go:noescape
+//go:nosplit
+func Sys_object_signal(handle Handle, clear_mask uint32, set_mask uint32) Status
+
+//go:noescape
+//go:nosplit
+func Sys_object_signal_peer(handle Handle, clear_mask uint32, set_mask uint32) Status
+
+//go:noescape
+//go:nosplit
+func Sys_object_get_property(handle Handle, property uint32, value unsafe.Pointer, value_size uint) Status
+
+//go:noescape
+//go:nosplit
+func Sys_object_set_property(handle Handle, property uint32, value unsafe.Pointer, value_size uint) Status
+
+//go:noescape
+//go:nosplit
+func Sys_object_get_info(handle Handle, topic uint32, buffer unsafe.Pointer, buffer_size uint, actual *uint, avail *uint) Status
+
+//go:noescape
+//go:nosplit
+func Sys_object_get_child(handle Handle, koid uint64, rights Rights, out *Handle) Status
+
+//go:noescape
+//go:nosplit
+func sys_object_set_profile(handle Handle, profile Handle, options uint32) Status
+
+//go:noescape
+//go:nosplit
+func sys_channel_create(options uint32, out0 *Handle, out1 *Handle) Status
+
+//go:noescape
+//go:nosplit
+func sys_channel_read(handle Handle, options uint32, bytes unsafe.Pointer, handles *Handle, num_bytes uint32, num_handles uint32, actual_bytes *uint32, actual_handles *uint32) Status
+
+//go:noescape
+//go:nosplit
+func sys_channel_read_etc(handle Handle, options uint32, bytes unsafe.Pointer, handles *int, num_bytes uint32, num_handles uint32, actual_bytes *uint32, actual_handles *uint32) Status
+
+//go:noescape
+//go:nosplit
+func sys_channel_write(handle Handle, options uint32, bytes unsafe.Pointer, num_bytes uint32, handles *Handle, num_handles uint32) Status
+
+//go:noescape
+//go:nosplit
+func Sys_channel_call_noretry(handle Handle, options uint32, deadline Time, args *ChannelCallArgs, actual_bytes *uint32, actual_handles *uint32) Status
+
+//go:noescape
+//go:nosplit
+func Sys_channel_call_finish(deadline Time, args *ChannelCallArgs, actual_bytes *uint32, actual_handles *uint32) Status
+
+//go:noescape
+//go:nosplit
+func Sys_channel_call(handle Handle, options uint32, deadline Time, args *ChannelCallArgs, actual_bytes *uint32, actual_handles *uint32) Status
+
+//go:noescape
+//go:nosplit
+func sys_socket_create(options uint32, out0 *Handle, out1 *Handle) Status
+
+//go:noescape
+//go:nosplit
+func sys_socket_write(handle Handle, options uint32, buffer unsafe.Pointer, buffer_size uint, actual *uint) Status
+
+//go:noescape
+//go:nosplit
+func sys_socket_read(handle Handle, options uint32, buffer unsafe.Pointer, buffer_size uint, actual *uint) Status
+
+//go:noescape
+//go:nosplit
+func sys_socket_share(handle Handle, socket_to_share Handle) Status
+
+//go:noescape
+//go:nosplit
+func sys_socket_accept(handle Handle, out_socket *Handle) Status
+
+//go:noescape
+//go:nosplit
+func Sys_socket_shutdown(handle Handle, options uint32) Status
+
+//go:noescape
+//go:nosplit
+func Sys_thread_exit()
+
+//go:noescape
+//go:nosplit
+func Sys_thread_create(process Handle, name *uint8, name_size uint, options uint32, out *Handle) Status
+
+//go:noescape
+//go:nosplit
+func Sys_thread_start(handle Handle, thread_entry Vaddr, stack Vaddr, arg1 uintptr, arg2 uintptr) Status
+
+//go:noescape
+//go:nosplit
+func Sys_thread_read_state(handle Handle, kind uint32, buffer unsafe.Pointer, buffer_size uint) Status
+
+//go:noescape
+//go:nosplit
+func Sys_thread_write_state(handle Handle, kind uint32, buffer unsafe.Pointer, buffer_size uint) Status
+
+//go:noescape
+//go:nosplit
+func Sys_thread_set_priority(prio int32) Status
+
+//go:noescape
+//go:nosplit
+func Sys_process_exit(retcode int64)
+
+//go:noescape
+//go:nosplit
+func Sys_process_create(job Handle, name *uint8, name_size uint, options uint32, proc_handle *Handle, vmar_handle *Handle) Status
+
+//go:noescape
+//go:nosplit
+func Sys_process_start(handle Handle, thread Handle, entry Vaddr, stack Vaddr, arg1 Handle, arg2 uintptr) Status
+
+//go:noescape
+//go:nosplit
+func Sys_process_read_memory(handle Handle, vaddr Vaddr, buffer unsafe.Pointer, buffer_size uint, actual *uint) Status
+
+//go:noescape
+//go:nosplit
+func Sys_process_write_memory(handle Handle, vaddr Vaddr, buffer unsafe.Pointer, buffer_size uint, actual *uint) Status
+
+//go:noescape
+//go:nosplit
+func Sys_job_create(parent_job Handle, options uint32, out *Handle) Status
+
+//go:noescape
+//go:nosplit
+func Sys_job_set_policy(handle Handle, options uint32, topic uint32, policy unsafe.Pointer, count uint32) Status
+
+//go:noescape
+//go:nosplit
+func Sys_task_bind_exception_port(handle Handle, port Handle, key uint64, options uint32) Status
+
+//go:noescape
+//go:nosplit
+func Sys_task_suspend(handle Handle, token *Handle) Status
+
+//go:noescape
+//go:nosplit
+func Sys_task_suspend_token(handle Handle, token *Handle) Status
+
+//go:noescape
+//go:nosplit
+func Sys_task_resume_from_exception(handle Handle, port Handle, options uint32) Status
+
+//go:noescape
+//go:nosplit
+func Sys_task_kill(handle Handle) Status
+
+//go:noescape
+//go:nosplit
+func Sys_event_create(options uint32, out *Handle) Status
+
+//go:noescape
+//go:nosplit
+func Sys_eventpair_create(options uint32, out0 *Handle, out1 *Handle) Status
+
+//go:noescape
+//go:nosplit
+func Sys_futex_wait(value_ptr *int32, current_value int32, new_futex_owner Handle, deadline Time) Status
+
+//go:noescape
+//go:nosplit
+func Sys_futex_wake(value_ptr *int32, wake_count uint32) Status
+
+//go:noescape
+//go:nosplit
+func Sys_futex_requeue(value_ptr *int32, wake_count uint32, current_value int32, requeue_ptr *int32, requeue_count uint32, new_requeue_owner Handle) Status
+
+//go:noescape
+//go:nosplit
+func Sys_futex_wake_single_owner(value_ptr *int32) Status
+
+//go:noescape
+//go:nosplit
+func Sys_futex_requeue_single_owner(value_ptr *int32, current_value int32, requeue_ptr *int32, requeue_count uint32, new_requeue_owner Handle) Status
+
+//go:noescape
+//go:nosplit
+func Sys_futex_get_owner(value_ptr *int32, koid *uint64) Status
+
+//go:noescape
+//go:nosplit
+func Sys_port_create(options uint32, out *Handle) Status
+
+//go:noescape
+//go:nosplit
+func Sys_port_queue(handle Handle, packet *int) Status
+
+//go:noescape
+//go:nosplit
+func Sys_port_wait(handle Handle, deadline Time, packet *int) Status
+
+//go:noescape
+//go:nosplit
+func Sys_port_cancel(handle Handle, source Handle, key uint64) Status
+
+//go:noescape
+//go:nosplit
+func Sys_timer_create(options uint32, clock_id uint32, out *Handle) Status
+
+//go:noescape
+//go:nosplit
+func Sys_timer_set(handle Handle, deadline Time, slack Duration) Status
+
+//go:noescape
+//go:nosplit
+func Sys_timer_cancel(handle Handle) Status
+
+//go:noescape
+//go:nosplit
+func Sys_vmo_create(size uint64, options uint32, out *Handle) Status
+
+//go:noescape
+//go:nosplit
+func sys_vmo_read(handle Handle, buffer unsafe.Pointer, offset uint64, buffer_size uint) Status
+
+//go:noescape
+//go:nosplit
+func sys_vmo_write(handle Handle, buffer unsafe.Pointer, offset uint64, buffer_size uint) Status
+
+//go:noescape
+//go:nosplit
+func sys_vmo_get_size(handle Handle, size *uint64) Status
+
+//go:noescape
+//go:nosplit
+func sys_vmo_set_size(handle Handle, size uint64) Status
+
+//go:noescape
+//go:nosplit
+func sys_vmo_op_range(handle Handle, op uint32, offset uint64, size uint64, buffer unsafe.Pointer, buffer_size uint) Status
+
+//go:noescape
+//go:nosplit
+func Sys_vmo_create_child(handle Handle, options uint32, offset uint64, size uint64, out *Handle) Status
+
+//go:noescape
+//go:nosplit
+func Sys_vmo_set_cache_policy(handle Handle, cache_policy uint32) Status
+
+//go:noescape
+//go:nosplit
+func sys_vmo_replace_as_executable(handle Handle, vmex Handle, out *Handle) Status
+
+//go:noescape
+//go:nosplit
+func sys_vmar_allocate(parent_vmar Handle, options VMFlag, offset uint64, size uint64, child_vmar *Handle, child_addr *Vaddr) Status
+
+//go:noescape
+//go:nosplit
+func sys_vmar_destroy(handle Handle) Status
+
+//go:noescape
+//go:nosplit
+func Sys_vmar_map(handle Handle, options VMFlag, vmar_offset uint64, vmo Handle, vmo_offset uint64, len uint64, mapped_addr *Vaddr) Status
+
+//go:noescape
+//go:nosplit
+func Sys_vmar_unmap(handle Handle, addr Vaddr, len uint64) Status
+
+//go:noescape
+//go:nosplit
+func Sys_vmar_protect(handle Handle, options VMFlag, addr Vaddr, len uint64) Status
+
+//go:noescape
+//go:nosplit
+func Sys_cprng_draw_once(buffer unsafe.Pointer, buffer_size uint) Status
+
+//go:noescape
+//go:nosplit
+func Sys_cprng_draw(buffer unsafe.Pointer, buffer_size uint)
+
+//go:noescape
+//go:nosplit
+func Sys_cprng_add_entropy(buffer unsafe.Pointer, buffer_size uint) Status
+
+//go:noescape
+//go:nosplit
+func Sys_fifo_create(elem_count uint, elem_size uint, options uint32, out0 *Handle, out1 *Handle) Status
+
+//go:noescape
+//go:nosplit
+func Sys_fifo_read(handle Handle, elem_size uint, data unsafe.Pointer, count uint, actual_count *uint) Status
+
+//go:noescape
+//go:nosplit
+func Sys_fifo_write(handle Handle, elem_size uint, data unsafe.Pointer, count uint, actual_count *uint) Status
+
+//go:noescape
+//go:nosplit
+func Sys_profile_create(root_job Handle, profile *int, out *Handle) Status
+
+//go:noescape
+//go:nosplit
+func Sys_vmar_unmap_handle_close_thread_exit(vmar_handle Handle, addr Vaddr, size uint, close_handle Handle) Status
+
+//go:noescape
+//go:nosplit
+func Sys_futex_wake_handle_close_thread_exit(value_ptr *int32, wake_count uint32, new_value int32, close_handle Handle)
+
+//go:noescape
+//go:nosplit
+func Sys_debuglog_create(resource Handle, options uint32, out *Handle) Status
+
+//go:noescape
+//go:nosplit
+func Sys_debuglog_write(handle Handle, options uint32, buffer unsafe.Pointer, buffer_size uint) Status
+
+//go:noescape
+//go:nosplit
+func Sys_debuglog_read(handle Handle, options uint32, buffer unsafe.Pointer, buffer_size uint) Status
+
+//go:noescape
+//go:nosplit
+func Sys_ktrace_read(handle Handle, data unsafe.Pointer, offset uint32, data_size uint, actual *uint) Status
+
+//go:noescape
+//go:nosplit
+func Sys_ktrace_control(handle Handle, action uint32, options uint32, ptr unsafe.Pointer) Status
+
+//go:noescape
+//go:nosplit
+func Sys_ktrace_write(handle Handle, id uint32, arg0 uint32, arg1 uint32) Status
+
+//go:noescape
+//go:nosplit
+func Sys_mtrace_control(handle Handle, kind uint32, action uint32, options uint32, ptr unsafe.Pointer, ptr_size uint) Status
+
+//go:noescape
+//go:nosplit
+func Sys_debug_read(handle Handle, buffer *uint8, buffer_size *uint) Status
+
+//go:noescape
+//go:nosplit
+func Sys_debug_write(buffer *uint8, buffer_size uint) Status
+
+//go:noescape
+//go:nosplit
+func Sys_debug_send_command(resource Handle, buffer *uint8, buffer_size uint) Status
+
+//go:noescape
+//go:nosplit
+func Sys_interrupt_create(src_obj Handle, src_num uint32, options uint32, out_handle *Handle) Status
+
+//go:noescape
+//go:nosplit
+func Sys_interrupt_bind(handle Handle, port_handle Handle, key uint64, options uint32) Status
+
+//go:noescape
+//go:nosplit
+func Sys_interrupt_wait(handle Handle, out_timestamp *Time) Status
+
+//go:noescape
+//go:nosplit
+func Sys_interrupt_destroy(handle Handle) Status
+
+//go:noescape
+//go:nosplit
+func Sys_interrupt_ack(handle Handle) Status
+
+//go:noescape
+//go:nosplit
+func Sys_interrupt_trigger(handle Handle, options uint32, timestamp Time) Status
+
+//go:noescape
+//go:nosplit
+func Sys_interrupt_bind_vcpu(handle Handle, vcpu Handle, options uint32) Status
+
+//go:noescape
+//go:nosplit
+func Sys_ioports_request(resource Handle, io_addr uint16, len uint32) Status
+
+//go:noescape
+//go:nosplit
+func Sys_vmo_create_contiguous(bti Handle, size uint, alignment_log2 uint32, out *Handle) Status
+
+//go:noescape
+//go:nosplit
+func Sys_vmo_create_physical(resource Handle, paddr Paddr, size uint, out *Handle) Status
+
+//go:noescape
+//go:nosplit
+func Sys_iommu_create(resource Handle, typ uint32, desc unsafe.Pointer, desc_size uint, out *Handle) Status
+
+//go:noescape
+//go:nosplit
+func Sys_bti_create(iommu Handle, options uint32, bti_id uint64, out *Handle) Status
+
+//go:noescape
+//go:nosplit
+func Sys_bti_pin(handle Handle, options uint32, vmo Handle, offset uint64, size uint64, addrs *Paddr, addrs_count uint, pmt *Handle) Status
+
+//go:noescape
+//go:nosplit
+func Sys_bti_release_quarantine(handle Handle) Status
+
+//go:noescape
+//go:nosplit
+func Sys_pmt_unpin(handle Handle) Status
+
+//go:noescape
+//go:nosplit
+func Sys_framebuffer_get_info(resource Handle, format *uint32, width *uint32, height *uint32, stride *uint32) Status
+
+//go:noescape
+//go:nosplit
+func Sys_framebuffer_set_range(resource Handle, vmo Handle, len uint32, format uint32, width uint32, height uint32, stride uint32) Status
+
+//go:noescape
+//go:nosplit
+func Sys_pc_firmware_tables(handle Handle, acpi_rsdp *Paddr, smbios *Paddr) Status
+
+//go:noescape
+//go:nosplit
+func Sys_smc_call(handle Handle, parameters *SMCParameters, out_smc_result *SMCResult) Status
+
+//go:noescape
+//go:nosplit
+func Sys_resource_create(parent_rsrc Handle, options uint32, base uint64, size uint, name *uint8, name_size uint, resource_out *Handle) Status
+
+//go:noescape
+//go:nosplit
+func Sys_system_mexec(resource Handle, kernel_vmo Handle, bootimage_vmo Handle) Status
+
+//go:noescape
+//go:nosplit
+func Sys_system_mexec_payload_get(resource Handle, buffer unsafe.Pointer, buffer_size uint) Status
+
+//go:noescape
+//go:nosplit
+func Sys_system_powerctl(resource Handle, cmd uint32, arg *int) Status
+
+//go:noescape
+//go:nosplit
+func Sys_pager_create(options uint32, out *Handle) Status
+
+//go:noescape
+//go:nosplit
+func Sys_pager_create_vmo(pager Handle, options uint32, port Handle, key uint64, size uint64, out *Handle) Status
+
+//go:noescape
+//go:nosplit
+func Sys_pager_detach_vmo(pager Handle, vmo Handle) Status
+
+//go:noescape
+//go:nosplit
+func Sys_pager_supply_pages(pager Handle, pager_vmo Handle, offset uint64, length uint64, aux_vmo Handle, aux_offset uint64) Status
diff --git a/src/syscall/zx/syscalls_fuchsia_amd64.s b/src/syscall/zx/syscalls_fuchsia_amd64.s
new file mode 100644
index 0000000..dbcd1dd
--- /dev/null
+++ b/src/syscall/zx/syscalls_fuchsia_amd64.s
@@ -0,0 +1,540 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Zircon system calls for the Fuchsia OS.
+// Generated by mkfuchsia.go, do not edit.
+
+#include "textflag.h"
+// func Sys_clock_get(clock_id uint32) Time
+TEXT ·Sys_clock_get(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_clock_get(SB)
+
+// func Sys_clock_get_new(clock_id uint32, out *Time) Status
+TEXT ·Sys_clock_get_new(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_clock_get_new(SB)
+
+// func Sys_clock_get_monotonic() Time
+TEXT ·Sys_clock_get_monotonic(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_clock_get_monotonic(SB)
+
+// func Sys_nanosleep(deadline Time) Status
+TEXT ·Sys_nanosleep(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_nanosleep(SB)
+
+// func Sys_ticks_get() uint64
+TEXT ·Sys_ticks_get(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_ticks_get(SB)
+
+// func Sys_ticks_per_second() uint64
+TEXT ·Sys_ticks_per_second(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_ticks_per_second(SB)
+
+// func Sys_deadline_after(nanoseconds Duration) Time
+TEXT ·Sys_deadline_after(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_deadline_after(SB)
+
+// func Sys_clock_adjust(handle Handle, clock_id uint32, offset int64) Status
+TEXT ·Sys_clock_adjust(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_clock_adjust(SB)
+
+// func sys_system_get_dcache_line_size() uint32
+TEXT ·sys_system_get_dcache_line_size(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_system_get_dcache_line_size(SB)
+
+// func Sys_system_get_num_cpus() uint32
+TEXT ·Sys_system_get_num_cpus(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_system_get_num_cpus(SB)
+
+// func Sys_system_get_version(version *uint8, version_size uint) Status
+TEXT ·Sys_system_get_version(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_system_get_version(SB)
+
+// func Sys_system_get_physmem() uint64
+TEXT ·Sys_system_get_physmem(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_system_get_physmem(SB)
+
+// func sys_system_get_features(kind uint32, features *uint32) Status
+TEXT ·sys_system_get_features(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_system_get_features(SB)
+
+// func Sys_cache_flush(addr unsafe.Pointer, size uint, options uint32) Status
+TEXT ·Sys_cache_flush(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_cache_flush(SB)
+
+// func Sys_handle_close(handle Handle) Status
+TEXT ·Sys_handle_close(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_handle_close(SB)
+
+// func Sys_handle_close_many(handles *Handle, num_handles uint) Status
+TEXT ·Sys_handle_close_many(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_handle_close_many(SB)
+
+// func sys_handle_duplicate(handle Handle, rights Rights, out *Handle) Status
+TEXT ·sys_handle_duplicate(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_handle_duplicate(SB)
+
+// func Sys_handle_replace(handle Handle, rights Rights, out *Handle) Status
+TEXT ·Sys_handle_replace(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_handle_replace(SB)
+
+// func Sys_object_wait_one(handle Handle, signals Signals, deadline Time, observed *Signals) Status
+TEXT ·Sys_object_wait_one(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_object_wait_one(SB)
+
+// func sys_object_wait_many(items *WaitItem, count uint, deadline Time) Status
+TEXT ·sys_object_wait_many(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_object_wait_many(SB)
+
+// func Sys_object_wait_async(handle Handle, port Handle, key uint64, signals Signals, options uint32) Status
+TEXT ·Sys_object_wait_async(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_object_wait_async(SB)
+
+// func Sys_object_signal(handle Handle, clear_mask uint32, set_mask uint32) Status
+TEXT ·Sys_object_signal(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_object_signal(SB)
+
+// func Sys_object_signal_peer(handle Handle, clear_mask uint32, set_mask uint32) Status
+TEXT ·Sys_object_signal_peer(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_object_signal_peer(SB)
+
+// func Sys_object_get_property(handle Handle, property uint32, value unsafe.Pointer, value_size uint) Status
+TEXT ·Sys_object_get_property(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_object_get_property(SB)
+
+// func Sys_object_set_property(handle Handle, property uint32, value unsafe.Pointer, value_size uint) Status
+TEXT ·Sys_object_set_property(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_object_set_property(SB)
+
+// func Sys_object_get_info(handle Handle, topic uint32, buffer unsafe.Pointer, buffer_size uint, actual *uint, avail *uint) Status
+TEXT ·Sys_object_get_info(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_object_get_info(SB)
+
+// func Sys_object_get_child(handle Handle, koid uint64, rights Rights, out *Handle) Status
+TEXT ·Sys_object_get_child(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_object_get_child(SB)
+
+// func sys_object_set_profile(handle Handle, profile Handle, options uint32) Status
+TEXT ·sys_object_set_profile(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_object_set_profile(SB)
+
+// func sys_channel_create(options uint32, out0 *Handle, out1 *Handle) Status
+TEXT ·sys_channel_create(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_channel_create(SB)
+
+// func sys_channel_read(handle Handle, options uint32, bytes unsafe.Pointer, handles *Handle, num_bytes uint32, num_handles uint32, actual_bytes *uint32, actual_handles *uint32) Status
+TEXT ·sys_channel_read(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_channel_read(SB)
+
+// func sys_channel_read_etc(handle Handle, options uint32, bytes unsafe.Pointer, handles *int, num_bytes uint32, num_handles uint32, actual_bytes *uint32, actual_handles *uint32) Status
+TEXT ·sys_channel_read_etc(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_channel_read_etc(SB)
+
+// func sys_channel_write(handle Handle, options uint32, bytes unsafe.Pointer, num_bytes uint32, handles *Handle, num_handles uint32) Status
+TEXT ·sys_channel_write(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_channel_write(SB)
+
+// func Sys_channel_call_noretry(handle Handle, options uint32, deadline Time, args *ChannelCallArgs, actual_bytes *uint32, actual_handles *uint32) Status
+TEXT ·Sys_channel_call_noretry(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_channel_call_noretry(SB)
+
+// func Sys_channel_call_finish(deadline Time, args *ChannelCallArgs, actual_bytes *uint32, actual_handles *uint32) Status
+TEXT ·Sys_channel_call_finish(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_channel_call_finish(SB)
+
+// func Sys_channel_call(handle Handle, options uint32, deadline Time, args *ChannelCallArgs, actual_bytes *uint32, actual_handles *uint32) Status
+TEXT ·Sys_channel_call(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_channel_call(SB)
+
+// func sys_socket_create(options uint32, out0 *Handle, out1 *Handle) Status
+TEXT ·sys_socket_create(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_socket_create(SB)
+
+// func sys_socket_write(handle Handle, options uint32, buffer unsafe.Pointer, buffer_size uint, actual *uint) Status
+TEXT ·sys_socket_write(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_socket_write(SB)
+
+// func sys_socket_read(handle Handle, options uint32, buffer unsafe.Pointer, buffer_size uint, actual *uint) Status
+TEXT ·sys_socket_read(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_socket_read(SB)
+
+// func sys_socket_share(handle Handle, socket_to_share Handle) Status
+TEXT ·sys_socket_share(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_socket_share(SB)
+
+// func sys_socket_accept(handle Handle, out_socket *Handle) Status
+TEXT ·sys_socket_accept(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_socket_accept(SB)
+
+// func Sys_socket_shutdown(handle Handle, options uint32) Status
+TEXT ·Sys_socket_shutdown(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_socket_shutdown(SB)
+
+// func Sys_thread_exit()
+TEXT ·Sys_thread_exit(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_thread_exit(SB)
+
+// func Sys_thread_create(process Handle, name *uint8, name_size uint, options uint32, out *Handle) Status
+TEXT ·Sys_thread_create(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_thread_create(SB)
+
+// func Sys_thread_start(handle Handle, thread_entry Vaddr, stack Vaddr, arg1 uintptr, arg2 uintptr) Status
+TEXT ·Sys_thread_start(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_thread_start(SB)
+
+// func Sys_thread_read_state(handle Handle, kind uint32, buffer unsafe.Pointer, buffer_size uint) Status
+TEXT ·Sys_thread_read_state(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_thread_read_state(SB)
+
+// func Sys_thread_write_state(handle Handle, kind uint32, buffer unsafe.Pointer, buffer_size uint) Status
+TEXT ·Sys_thread_write_state(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_thread_write_state(SB)
+
+// func Sys_process_exit(retcode int64)
+TEXT ·Sys_process_exit(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_process_exit(SB)
+
+// func Sys_process_create(job Handle, name *uint8, name_size uint, options uint32, proc_handle *Handle, vmar_handle *Handle) Status
+TEXT ·Sys_process_create(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_process_create(SB)
+
+// func Sys_process_start(handle Handle, thread Handle, entry Vaddr, stack Vaddr, arg1 Handle, arg2 uintptr) Status
+TEXT ·Sys_process_start(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_process_start(SB)
+
+// func Sys_process_read_memory(handle Handle, vaddr Vaddr, buffer unsafe.Pointer, buffer_size uint, actual *uint) Status
+TEXT ·Sys_process_read_memory(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_process_read_memory(SB)
+
+// func Sys_process_write_memory(handle Handle, vaddr Vaddr, buffer unsafe.Pointer, buffer_size uint, actual *uint) Status
+TEXT ·Sys_process_write_memory(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_process_write_memory(SB)
+
+// func Sys_job_create(parent_job Handle, options uint32, out *Handle) Status
+TEXT ·Sys_job_create(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_job_create(SB)
+
+// func Sys_job_set_policy(handle Handle, options uint32, topic uint32, policy unsafe.Pointer, count uint32) Status
+TEXT ·Sys_job_set_policy(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_job_set_policy(SB)
+
+// func Sys_task_bind_exception_port(handle Handle, port Handle, key uint64, options uint32) Status
+TEXT ·Sys_task_bind_exception_port(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_task_bind_exception_port(SB)
+
+// func Sys_task_suspend(handle Handle, token *Handle) Status
+TEXT ·Sys_task_suspend(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_task_suspend(SB)
+
+// func Sys_task_suspend_token(handle Handle, token *Handle) Status
+TEXT ·Sys_task_suspend_token(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_task_suspend_token(SB)
+
+// func Sys_task_resume_from_exception(handle Handle, port Handle, options uint32) Status
+TEXT ·Sys_task_resume_from_exception(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_task_resume_from_exception(SB)
+
+// func Sys_task_kill(handle Handle) Status
+TEXT ·Sys_task_kill(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_task_kill(SB)
+
+// func Sys_event_create(options uint32, out *Handle) Status
+TEXT ·Sys_event_create(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_event_create(SB)
+
+// func Sys_eventpair_create(options uint32, out0 *Handle, out1 *Handle) Status
+TEXT ·Sys_eventpair_create(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_eventpair_create(SB)
+
+// func Sys_futex_wait(value_ptr *int32, current_value int32, new_futex_owner Handle, deadline Time) Status
+TEXT ·Sys_futex_wait(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_futex_wait(SB)
+
+// func Sys_futex_wake(value_ptr *int32, wake_count uint32) Status
+TEXT ·Sys_futex_wake(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_futex_wake(SB)
+
+// func Sys_futex_requeue(value_ptr *int32, wake_count uint32, current_value int32, requeue_ptr *int32, requeue_count uint32, new_requeue_owner Handle) Status
+TEXT ·Sys_futex_requeue(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_futex_requeue(SB)
+
+// func Sys_futex_wake_single_owner(value_ptr *int32) Status
+TEXT ·Sys_futex_wake_single_owner(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_futex_wake_single_owner(SB)
+
+// func Sys_futex_requeue_single_owner(value_ptr *int32, current_value int32, requeue_ptr *int32, requeue_count uint32, new_requeue_owner Handle) Status
+TEXT ·Sys_futex_requeue_single_owner(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_futex_requeue_single_owner(SB)
+
+// func Sys_futex_get_owner(value_ptr *int32, koid *uint64) Status
+TEXT ·Sys_futex_get_owner(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_futex_get_owner(SB)
+
+// func Sys_port_create(options uint32, out *Handle) Status
+TEXT ·Sys_port_create(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_port_create(SB)
+
+// func Sys_port_queue(handle Handle, packet *int) Status
+TEXT ·Sys_port_queue(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_port_queue(SB)
+
+// func Sys_port_wait(handle Handle, deadline Time, packet *int) Status
+TEXT ·Sys_port_wait(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_port_wait(SB)
+
+// func Sys_port_cancel(handle Handle, source Handle, key uint64) Status
+TEXT ·Sys_port_cancel(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_port_cancel(SB)
+
+// func Sys_timer_create(options uint32, clock_id uint32, out *Handle) Status
+TEXT ·Sys_timer_create(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_timer_create(SB)
+
+// func Sys_timer_set(handle Handle, deadline Time, slack Duration) Status
+TEXT ·Sys_timer_set(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_timer_set(SB)
+
+// func Sys_timer_cancel(handle Handle) Status
+TEXT ·Sys_timer_cancel(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_timer_cancel(SB)
+
+// func Sys_vmo_create(size uint64, options uint32, out *Handle) Status
+TEXT ·Sys_vmo_create(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_vmo_create(SB)
+
+// func sys_vmo_read(handle Handle, buffer unsafe.Pointer, offset uint64, buffer_size uint) Status
+TEXT ·sys_vmo_read(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_vmo_read(SB)
+
+// func sys_vmo_write(handle Handle, buffer unsafe.Pointer, offset uint64, buffer_size uint) Status
+TEXT ·sys_vmo_write(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_vmo_write(SB)
+
+// func sys_vmo_get_size(handle Handle, size *uint64) Status
+TEXT ·sys_vmo_get_size(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_vmo_get_size(SB)
+
+// func sys_vmo_set_size(handle Handle, size uint64) Status
+TEXT ·sys_vmo_set_size(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_vmo_set_size(SB)
+
+// func sys_vmo_op_range(handle Handle, op uint32, offset uint64, size uint64, buffer unsafe.Pointer, buffer_size uint) Status
+TEXT ·sys_vmo_op_range(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_vmo_op_range(SB)
+
+// func Sys_vmo_create_child(handle Handle, options uint32, offset uint64, size uint64, out *Handle) Status
+TEXT ·Sys_vmo_create_child(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_vmo_create_child(SB)
+
+// func Sys_vmo_set_cache_policy(handle Handle, cache_policy uint32) Status
+TEXT ·Sys_vmo_set_cache_policy(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_vmo_set_cache_policy(SB)
+
+// func sys_vmo_replace_as_executable(handle Handle, vmex Handle, out *Handle) Status
+TEXT ·sys_vmo_replace_as_executable(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_vmo_replace_as_executable(SB)
+
+// func sys_vmar_allocate(parent_vmar Handle, options VMFlag, offset uint64, size uint64, child_vmar *Handle, child_addr *Vaddr) Status
+TEXT ·sys_vmar_allocate(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_vmar_allocate(SB)
+
+// func sys_vmar_destroy(handle Handle) Status
+TEXT ·sys_vmar_destroy(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_vmar_destroy(SB)
+
+// func Sys_vmar_map(handle Handle, options VMFlag, vmar_offset uint64, vmo Handle, vmo_offset uint64, len uint64, mapped_addr *Vaddr) Status
+TEXT ·Sys_vmar_map(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_vmar_map(SB)
+
+// func Sys_vmar_unmap(handle Handle, addr Vaddr, len uint64) Status
+TEXT ·Sys_vmar_unmap(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_vmar_unmap(SB)
+
+// func Sys_vmar_protect(handle Handle, options VMFlag, addr Vaddr, len uint64) Status
+TEXT ·Sys_vmar_protect(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_vmar_protect(SB)
+
+// func Sys_cprng_draw_once(buffer unsafe.Pointer, buffer_size uint) Status
+TEXT ·Sys_cprng_draw_once(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_cprng_draw_once(SB)
+
+// func Sys_cprng_draw(buffer unsafe.Pointer, buffer_size uint)
+TEXT ·Sys_cprng_draw(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_cprng_draw(SB)
+
+// func Sys_cprng_add_entropy(buffer unsafe.Pointer, buffer_size uint) Status
+TEXT ·Sys_cprng_add_entropy(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_cprng_add_entropy(SB)
+
+// func Sys_fifo_create(elem_count uint, elem_size uint, options uint32, out0 *Handle, out1 *Handle) Status
+TEXT ·Sys_fifo_create(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_fifo_create(SB)
+
+// func Sys_fifo_read(handle Handle, elem_size uint, data unsafe.Pointer, count uint, actual_count *uint) Status
+TEXT ·Sys_fifo_read(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_fifo_read(SB)
+
+// func Sys_fifo_write(handle Handle, elem_size uint, data unsafe.Pointer, count uint, actual_count *uint) Status
+TEXT ·Sys_fifo_write(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_fifo_write(SB)
+
+// func Sys_profile_create(root_job Handle, profile *int, out *Handle) Status
+TEXT ·Sys_profile_create(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_profile_create(SB)
+
+// func Sys_vmar_unmap_handle_close_thread_exit(vmar_handle Handle, addr Vaddr, size uint, close_handle Handle) Status
+TEXT ·Sys_vmar_unmap_handle_close_thread_exit(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_vmar_unmap_handle_close_thread_exit(SB)
+
+// func Sys_futex_wake_handle_close_thread_exit(value_ptr *int32, wake_count uint32, new_value int32, close_handle Handle)
+TEXT ·Sys_futex_wake_handle_close_thread_exit(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_futex_wake_handle_close_thread_exit(SB)
+
+// func Sys_debuglog_create(resource Handle, options uint32, out *Handle) Status
+TEXT ·Sys_debuglog_create(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_debuglog_create(SB)
+
+// func Sys_debuglog_write(handle Handle, options uint32, buffer unsafe.Pointer, buffer_size uint) Status
+TEXT ·Sys_debuglog_write(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_debuglog_write(SB)
+
+// func Sys_debuglog_read(handle Handle, options uint32, buffer unsafe.Pointer, buffer_size uint) Status
+TEXT ·Sys_debuglog_read(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_debuglog_read(SB)
+
+// func Sys_ktrace_read(handle Handle, data unsafe.Pointer, offset uint32, data_size uint, actual *uint) Status
+TEXT ·Sys_ktrace_read(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_ktrace_read(SB)
+
+// func Sys_ktrace_control(handle Handle, action uint32, options uint32, ptr unsafe.Pointer) Status
+TEXT ·Sys_ktrace_control(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_ktrace_control(SB)
+
+// func Sys_ktrace_write(handle Handle, id uint32, arg0 uint32, arg1 uint32) Status
+TEXT ·Sys_ktrace_write(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_ktrace_write(SB)
+
+// func Sys_mtrace_control(handle Handle, kind uint32, action uint32, options uint32, ptr unsafe.Pointer, ptr_size uint) Status
+TEXT ·Sys_mtrace_control(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_mtrace_control(SB)
+
+// func Sys_debug_read(handle Handle, buffer *uint8, buffer_size *uint) Status
+TEXT ·Sys_debug_read(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_debug_read(SB)
+
+// func Sys_debug_write(buffer *uint8, buffer_size uint) Status
+TEXT ·Sys_debug_write(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_debug_write(SB)
+
+// func Sys_debug_send_command(resource Handle, buffer *uint8, buffer_size uint) Status
+TEXT ·Sys_debug_send_command(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_debug_send_command(SB)
+
+// func Sys_interrupt_create(src_obj Handle, src_num uint32, options uint32, out_handle *Handle) Status
+TEXT ·Sys_interrupt_create(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_interrupt_create(SB)
+
+// func Sys_interrupt_bind(handle Handle, port_handle Handle, key uint64, options uint32) Status
+TEXT ·Sys_interrupt_bind(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_interrupt_bind(SB)
+
+// func Sys_interrupt_wait(handle Handle, out_timestamp *Time) Status
+TEXT ·Sys_interrupt_wait(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_interrupt_wait(SB)
+
+// func Sys_interrupt_destroy(handle Handle) Status
+TEXT ·Sys_interrupt_destroy(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_interrupt_destroy(SB)
+
+// func Sys_interrupt_ack(handle Handle) Status
+TEXT ·Sys_interrupt_ack(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_interrupt_ack(SB)
+
+// func Sys_interrupt_trigger(handle Handle, options uint32, timestamp Time) Status
+TEXT ·Sys_interrupt_trigger(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_interrupt_trigger(SB)
+
+// func Sys_interrupt_bind_vcpu(handle Handle, vcpu Handle, options uint32) Status
+TEXT ·Sys_interrupt_bind_vcpu(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_interrupt_bind_vcpu(SB)
+
+// func Sys_ioports_request(resource Handle, io_addr uint16, len uint32) Status
+TEXT ·Sys_ioports_request(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_ioports_request(SB)
+
+// func Sys_vmo_create_contiguous(bti Handle, size uint, alignment_log2 uint32, out *Handle) Status
+TEXT ·Sys_vmo_create_contiguous(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_vmo_create_contiguous(SB)
+
+// func Sys_vmo_create_physical(resource Handle, paddr Paddr, size uint, out *Handle) Status
+TEXT ·Sys_vmo_create_physical(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_vmo_create_physical(SB)
+
+// func Sys_iommu_create(resource Handle, typ uint32, desc unsafe.Pointer, desc_size uint, out *Handle) Status
+TEXT ·Sys_iommu_create(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_iommu_create(SB)
+
+// func Sys_bti_create(iommu Handle, options uint32, bti_id uint64, out *Handle) Status
+TEXT ·Sys_bti_create(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_bti_create(SB)
+
+// func Sys_bti_pin(handle Handle, options uint32, vmo Handle, offset uint64, size uint64, addrs *Paddr, addrs_count uint, pmt *Handle) Status
+TEXT ·Sys_bti_pin(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_bti_pin(SB)
+
+// func Sys_bti_release_quarantine(handle Handle) Status
+TEXT ·Sys_bti_release_quarantine(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_bti_release_quarantine(SB)
+
+// func Sys_pmt_unpin(handle Handle) Status
+TEXT ·Sys_pmt_unpin(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_pmt_unpin(SB)
+
+// func Sys_framebuffer_get_info(resource Handle, format *uint32, width *uint32, height *uint32, stride *uint32) Status
+TEXT ·Sys_framebuffer_get_info(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_framebuffer_get_info(SB)
+
+// func Sys_framebuffer_set_range(resource Handle, vmo Handle, len uint32, format uint32, width uint32, height uint32, stride uint32) Status
+TEXT ·Sys_framebuffer_set_range(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_framebuffer_set_range(SB)
+
+// func Sys_pc_firmware_tables(handle Handle, acpi_rsdp *Paddr, smbios *Paddr) Status
+TEXT ·Sys_pc_firmware_tables(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_pc_firmware_tables(SB)
+
+// func Sys_smc_call(handle Handle, parameters *SMCParameters, out_smc_result *SMCResult) Status
+TEXT ·Sys_smc_call(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_smc_call(SB)
+
+// func Sys_resource_create(parent_rsrc Handle, options uint32, base uint64, size uint, name *uint8, name_size uint, resource_out *Handle) Status
+TEXT ·Sys_resource_create(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_resource_create(SB)
+
+// func Sys_system_mexec(resource Handle, kernel_vmo Handle, bootimage_vmo Handle) Status
+TEXT ·Sys_system_mexec(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_system_mexec(SB)
+
+// func Sys_system_mexec_payload_get(resource Handle, buffer unsafe.Pointer, buffer_size uint) Status
+TEXT ·Sys_system_mexec_payload_get(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_system_mexec_payload_get(SB)
+
+// func Sys_system_powerctl(resource Handle, cmd uint32, arg *int) Status
+TEXT ·Sys_system_powerctl(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_system_powerctl(SB)
+
+// func Sys_pager_create(options uint32, out *Handle) Status
+TEXT ·Sys_pager_create(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_pager_create(SB)
+
+// func Sys_pager_create_vmo(pager Handle, options uint32, port Handle, key uint64, size uint64, out *Handle) Status
+TEXT ·Sys_pager_create_vmo(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_pager_create_vmo(SB)
+
+// func Sys_pager_detach_vmo(pager Handle, vmo Handle) Status
+TEXT ·Sys_pager_detach_vmo(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_pager_detach_vmo(SB)
+
+// func Sys_pager_supply_pages(pager Handle, pager_vmo Handle, offset uint64, length uint64, aux_vmo Handle, aux_offset uint64) Status
+TEXT ·Sys_pager_supply_pages(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_pager_supply_pages(SB)
+
diff --git a/src/syscall/zx/syscalls_fuchsia_arm64.s b/src/syscall/zx/syscalls_fuchsia_arm64.s
new file mode 100644
index 0000000..dbcd1dd
--- /dev/null
+++ b/src/syscall/zx/syscalls_fuchsia_arm64.s
@@ -0,0 +1,540 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Zircon system calls for the Fuchsia OS.
+// Generated by mkfuchsia.go, do not edit.
+
+#include "textflag.h"
+// func Sys_clock_get(clock_id uint32) Time
+TEXT ·Sys_clock_get(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_clock_get(SB)
+
+// func Sys_clock_get_new(clock_id uint32, out *Time) Status
+TEXT ·Sys_clock_get_new(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_clock_get_new(SB)
+
+// func Sys_clock_get_monotonic() Time
+TEXT ·Sys_clock_get_monotonic(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_clock_get_monotonic(SB)
+
+// func Sys_nanosleep(deadline Time) Status
+TEXT ·Sys_nanosleep(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_nanosleep(SB)
+
+// func Sys_ticks_get() uint64
+TEXT ·Sys_ticks_get(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_ticks_get(SB)
+
+// func Sys_ticks_per_second() uint64
+TEXT ·Sys_ticks_per_second(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_ticks_per_second(SB)
+
+// func Sys_deadline_after(nanoseconds Duration) Time
+TEXT ·Sys_deadline_after(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_deadline_after(SB)
+
+// func Sys_clock_adjust(handle Handle, clock_id uint32, offset int64) Status
+TEXT ·Sys_clock_adjust(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_clock_adjust(SB)
+
+// func sys_system_get_dcache_line_size() uint32
+TEXT ·sys_system_get_dcache_line_size(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_system_get_dcache_line_size(SB)
+
+// func Sys_system_get_num_cpus() uint32
+TEXT ·Sys_system_get_num_cpus(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_system_get_num_cpus(SB)
+
+// func Sys_system_get_version(version *uint8, version_size uint) Status
+TEXT ·Sys_system_get_version(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_system_get_version(SB)
+
+// func Sys_system_get_physmem() uint64
+TEXT ·Sys_system_get_physmem(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_system_get_physmem(SB)
+
+// func sys_system_get_features(kind uint32, features *uint32) Status
+TEXT ·sys_system_get_features(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_system_get_features(SB)
+
+// func Sys_cache_flush(addr unsafe.Pointer, size uint, options uint32) Status
+TEXT ·Sys_cache_flush(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_cache_flush(SB)
+
+// func Sys_handle_close(handle Handle) Status
+TEXT ·Sys_handle_close(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_handle_close(SB)
+
+// func Sys_handle_close_many(handles *Handle, num_handles uint) Status
+TEXT ·Sys_handle_close_many(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_handle_close_many(SB)
+
+// func sys_handle_duplicate(handle Handle, rights Rights, out *Handle) Status
+TEXT ·sys_handle_duplicate(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_handle_duplicate(SB)
+
+// func Sys_handle_replace(handle Handle, rights Rights, out *Handle) Status
+TEXT ·Sys_handle_replace(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_handle_replace(SB)
+
+// func Sys_object_wait_one(handle Handle, signals Signals, deadline Time, observed *Signals) Status
+TEXT ·Sys_object_wait_one(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_object_wait_one(SB)
+
+// func sys_object_wait_many(items *WaitItem, count uint, deadline Time) Status
+TEXT ·sys_object_wait_many(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_object_wait_many(SB)
+
+// func Sys_object_wait_async(handle Handle, port Handle, key uint64, signals Signals, options uint32) Status
+TEXT ·Sys_object_wait_async(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_object_wait_async(SB)
+
+// func Sys_object_signal(handle Handle, clear_mask uint32, set_mask uint32) Status
+TEXT ·Sys_object_signal(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_object_signal(SB)
+
+// func Sys_object_signal_peer(handle Handle, clear_mask uint32, set_mask uint32) Status
+TEXT ·Sys_object_signal_peer(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_object_signal_peer(SB)
+
+// func Sys_object_get_property(handle Handle, property uint32, value unsafe.Pointer, value_size uint) Status
+TEXT ·Sys_object_get_property(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_object_get_property(SB)
+
+// func Sys_object_set_property(handle Handle, property uint32, value unsafe.Pointer, value_size uint) Status
+TEXT ·Sys_object_set_property(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_object_set_property(SB)
+
+// func Sys_object_get_info(handle Handle, topic uint32, buffer unsafe.Pointer, buffer_size uint, actual *uint, avail *uint) Status
+TEXT ·Sys_object_get_info(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_object_get_info(SB)
+
+// func Sys_object_get_child(handle Handle, koid uint64, rights Rights, out *Handle) Status
+TEXT ·Sys_object_get_child(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_object_get_child(SB)
+
+// func sys_object_set_profile(handle Handle, profile Handle, options uint32) Status
+TEXT ·sys_object_set_profile(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_object_set_profile(SB)
+
+// func sys_channel_create(options uint32, out0 *Handle, out1 *Handle) Status
+TEXT ·sys_channel_create(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_channel_create(SB)
+
+// func sys_channel_read(handle Handle, options uint32, bytes unsafe.Pointer, handles *Handle, num_bytes uint32, num_handles uint32, actual_bytes *uint32, actual_handles *uint32) Status
+TEXT ·sys_channel_read(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_channel_read(SB)
+
+// func sys_channel_read_etc(handle Handle, options uint32, bytes unsafe.Pointer, handles *int, num_bytes uint32, num_handles uint32, actual_bytes *uint32, actual_handles *uint32) Status
+TEXT ·sys_channel_read_etc(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_channel_read_etc(SB)
+
+// func sys_channel_write(handle Handle, options uint32, bytes unsafe.Pointer, num_bytes uint32, handles *Handle, num_handles uint32) Status
+TEXT ·sys_channel_write(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_channel_write(SB)
+
+// func Sys_channel_call_noretry(handle Handle, options uint32, deadline Time, args *ChannelCallArgs, actual_bytes *uint32, actual_handles *uint32) Status
+TEXT ·Sys_channel_call_noretry(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_channel_call_noretry(SB)
+
+// func Sys_channel_call_finish(deadline Time, args *ChannelCallArgs, actual_bytes *uint32, actual_handles *uint32) Status
+TEXT ·Sys_channel_call_finish(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_channel_call_finish(SB)
+
+// func Sys_channel_call(handle Handle, options uint32, deadline Time, args *ChannelCallArgs, actual_bytes *uint32, actual_handles *uint32) Status
+TEXT ·Sys_channel_call(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_channel_call(SB)
+
+// func sys_socket_create(options uint32, out0 *Handle, out1 *Handle) Status
+TEXT ·sys_socket_create(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_socket_create(SB)
+
+// func sys_socket_write(handle Handle, options uint32, buffer unsafe.Pointer, buffer_size uint, actual *uint) Status
+TEXT ·sys_socket_write(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_socket_write(SB)
+
+// func sys_socket_read(handle Handle, options uint32, buffer unsafe.Pointer, buffer_size uint, actual *uint) Status
+TEXT ·sys_socket_read(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_socket_read(SB)
+
+// func sys_socket_share(handle Handle, socket_to_share Handle) Status
+TEXT ·sys_socket_share(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_socket_share(SB)
+
+// func sys_socket_accept(handle Handle, out_socket *Handle) Status
+TEXT ·sys_socket_accept(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_socket_accept(SB)
+
+// func Sys_socket_shutdown(handle Handle, options uint32) Status
+TEXT ·Sys_socket_shutdown(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_socket_shutdown(SB)
+
+// func Sys_thread_exit()
+TEXT ·Sys_thread_exit(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_thread_exit(SB)
+
+// func Sys_thread_create(process Handle, name *uint8, name_size uint, options uint32, out *Handle) Status
+TEXT ·Sys_thread_create(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_thread_create(SB)
+
+// func Sys_thread_start(handle Handle, thread_entry Vaddr, stack Vaddr, arg1 uintptr, arg2 uintptr) Status
+TEXT ·Sys_thread_start(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_thread_start(SB)
+
+// func Sys_thread_read_state(handle Handle, kind uint32, buffer unsafe.Pointer, buffer_size uint) Status
+TEXT ·Sys_thread_read_state(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_thread_read_state(SB)
+
+// func Sys_thread_write_state(handle Handle, kind uint32, buffer unsafe.Pointer, buffer_size uint) Status
+TEXT ·Sys_thread_write_state(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_thread_write_state(SB)
+
+// func Sys_process_exit(retcode int64)
+TEXT ·Sys_process_exit(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_process_exit(SB)
+
+// func Sys_process_create(job Handle, name *uint8, name_size uint, options uint32, proc_handle *Handle, vmar_handle *Handle) Status
+TEXT ·Sys_process_create(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_process_create(SB)
+
+// func Sys_process_start(handle Handle, thread Handle, entry Vaddr, stack Vaddr, arg1 Handle, arg2 uintptr) Status
+TEXT ·Sys_process_start(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_process_start(SB)
+
+// func Sys_process_read_memory(handle Handle, vaddr Vaddr, buffer unsafe.Pointer, buffer_size uint, actual *uint) Status
+TEXT ·Sys_process_read_memory(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_process_read_memory(SB)
+
+// func Sys_process_write_memory(handle Handle, vaddr Vaddr, buffer unsafe.Pointer, buffer_size uint, actual *uint) Status
+TEXT ·Sys_process_write_memory(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_process_write_memory(SB)
+
+// func Sys_job_create(parent_job Handle, options uint32, out *Handle) Status
+TEXT ·Sys_job_create(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_job_create(SB)
+
+// func Sys_job_set_policy(handle Handle, options uint32, topic uint32, policy unsafe.Pointer, count uint32) Status
+TEXT ·Sys_job_set_policy(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_job_set_policy(SB)
+
+// func Sys_task_bind_exception_port(handle Handle, port Handle, key uint64, options uint32) Status
+TEXT ·Sys_task_bind_exception_port(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_task_bind_exception_port(SB)
+
+// func Sys_task_suspend(handle Handle, token *Handle) Status
+TEXT ·Sys_task_suspend(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_task_suspend(SB)
+
+// func Sys_task_suspend_token(handle Handle, token *Handle) Status
+TEXT ·Sys_task_suspend_token(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_task_suspend_token(SB)
+
+// func Sys_task_resume_from_exception(handle Handle, port Handle, options uint32) Status
+TEXT ·Sys_task_resume_from_exception(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_task_resume_from_exception(SB)
+
+// func Sys_task_kill(handle Handle) Status
+TEXT ·Sys_task_kill(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_task_kill(SB)
+
+// func Sys_event_create(options uint32, out *Handle) Status
+TEXT ·Sys_event_create(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_event_create(SB)
+
+// func Sys_eventpair_create(options uint32, out0 *Handle, out1 *Handle) Status
+TEXT ·Sys_eventpair_create(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_eventpair_create(SB)
+
+// func Sys_futex_wait(value_ptr *int32, current_value int32, new_futex_owner Handle, deadline Time) Status
+TEXT ·Sys_futex_wait(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_futex_wait(SB)
+
+// func Sys_futex_wake(value_ptr *int32, wake_count uint32) Status
+TEXT ·Sys_futex_wake(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_futex_wake(SB)
+
+// func Sys_futex_requeue(value_ptr *int32, wake_count uint32, current_value int32, requeue_ptr *int32, requeue_count uint32, new_requeue_owner Handle) Status
+TEXT ·Sys_futex_requeue(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_futex_requeue(SB)
+
+// func Sys_futex_wake_single_owner(value_ptr *int32) Status
+TEXT ·Sys_futex_wake_single_owner(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_futex_wake_single_owner(SB)
+
+// func Sys_futex_requeue_single_owner(value_ptr *int32, current_value int32, requeue_ptr *int32, requeue_count uint32, new_requeue_owner Handle) Status
+TEXT ·Sys_futex_requeue_single_owner(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_futex_requeue_single_owner(SB)
+
+// func Sys_futex_get_owner(value_ptr *int32, koid *uint64) Status
+TEXT ·Sys_futex_get_owner(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_futex_get_owner(SB)
+
+// func Sys_port_create(options uint32, out *Handle) Status
+TEXT ·Sys_port_create(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_port_create(SB)
+
+// func Sys_port_queue(handle Handle, packet *int) Status
+TEXT ·Sys_port_queue(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_port_queue(SB)
+
+// func Sys_port_wait(handle Handle, deadline Time, packet *int) Status
+TEXT ·Sys_port_wait(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_port_wait(SB)
+
+// func Sys_port_cancel(handle Handle, source Handle, key uint64) Status
+TEXT ·Sys_port_cancel(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_port_cancel(SB)
+
+// func Sys_timer_create(options uint32, clock_id uint32, out *Handle) Status
+TEXT ·Sys_timer_create(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_timer_create(SB)
+
+// func Sys_timer_set(handle Handle, deadline Time, slack Duration) Status
+TEXT ·Sys_timer_set(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_timer_set(SB)
+
+// func Sys_timer_cancel(handle Handle) Status
+TEXT ·Sys_timer_cancel(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_timer_cancel(SB)
+
+// func Sys_vmo_create(size uint64, options uint32, out *Handle) Status
+TEXT ·Sys_vmo_create(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_vmo_create(SB)
+
+// func sys_vmo_read(handle Handle, buffer unsafe.Pointer, offset uint64, buffer_size uint) Status
+TEXT ·sys_vmo_read(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_vmo_read(SB)
+
+// func sys_vmo_write(handle Handle, buffer unsafe.Pointer, offset uint64, buffer_size uint) Status
+TEXT ·sys_vmo_write(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_vmo_write(SB)
+
+// func sys_vmo_get_size(handle Handle, size *uint64) Status
+TEXT ·sys_vmo_get_size(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_vmo_get_size(SB)
+
+// func sys_vmo_set_size(handle Handle, size uint64) Status
+TEXT ·sys_vmo_set_size(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_vmo_set_size(SB)
+
+// func sys_vmo_op_range(handle Handle, op uint32, offset uint64, size uint64, buffer unsafe.Pointer, buffer_size uint) Status
+TEXT ·sys_vmo_op_range(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_vmo_op_range(SB)
+
+// func Sys_vmo_create_child(handle Handle, options uint32, offset uint64, size uint64, out *Handle) Status
+TEXT ·Sys_vmo_create_child(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_vmo_create_child(SB)
+
+// func Sys_vmo_set_cache_policy(handle Handle, cache_policy uint32) Status
+TEXT ·Sys_vmo_set_cache_policy(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_vmo_set_cache_policy(SB)
+
+// func sys_vmo_replace_as_executable(handle Handle, vmex Handle, out *Handle) Status
+TEXT ·sys_vmo_replace_as_executable(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_vmo_replace_as_executable(SB)
+
+// func sys_vmar_allocate(parent_vmar Handle, options VMFlag, offset uint64, size uint64, child_vmar *Handle, child_addr *Vaddr) Status
+TEXT ·sys_vmar_allocate(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_vmar_allocate(SB)
+
+// func sys_vmar_destroy(handle Handle) Status
+TEXT ·sys_vmar_destroy(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_vmar_destroy(SB)
+
+// func Sys_vmar_map(handle Handle, options VMFlag, vmar_offset uint64, vmo Handle, vmo_offset uint64, len uint64, mapped_addr *Vaddr) Status
+TEXT ·Sys_vmar_map(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_vmar_map(SB)
+
+// func Sys_vmar_unmap(handle Handle, addr Vaddr, len uint64) Status
+TEXT ·Sys_vmar_unmap(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_vmar_unmap(SB)
+
+// func Sys_vmar_protect(handle Handle, options VMFlag, addr Vaddr, len uint64) Status
+TEXT ·Sys_vmar_protect(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_vmar_protect(SB)
+
+// func Sys_cprng_draw_once(buffer unsafe.Pointer, buffer_size uint) Status
+TEXT ·Sys_cprng_draw_once(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_cprng_draw_once(SB)
+
+// func Sys_cprng_draw(buffer unsafe.Pointer, buffer_size uint)
+TEXT ·Sys_cprng_draw(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_cprng_draw(SB)
+
+// func Sys_cprng_add_entropy(buffer unsafe.Pointer, buffer_size uint) Status
+TEXT ·Sys_cprng_add_entropy(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_cprng_add_entropy(SB)
+
+// func Sys_fifo_create(elem_count uint, elem_size uint, options uint32, out0 *Handle, out1 *Handle) Status
+TEXT ·Sys_fifo_create(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_fifo_create(SB)
+
+// func Sys_fifo_read(handle Handle, elem_size uint, data unsafe.Pointer, count uint, actual_count *uint) Status
+TEXT ·Sys_fifo_read(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_fifo_read(SB)
+
+// func Sys_fifo_write(handle Handle, elem_size uint, data unsafe.Pointer, count uint, actual_count *uint) Status
+TEXT ·Sys_fifo_write(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_fifo_write(SB)
+
+// func Sys_profile_create(root_job Handle, profile *int, out *Handle) Status
+TEXT ·Sys_profile_create(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_profile_create(SB)
+
+// func Sys_vmar_unmap_handle_close_thread_exit(vmar_handle Handle, addr Vaddr, size uint, close_handle Handle) Status
+TEXT ·Sys_vmar_unmap_handle_close_thread_exit(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_vmar_unmap_handle_close_thread_exit(SB)
+
+// func Sys_futex_wake_handle_close_thread_exit(value_ptr *int32, wake_count uint32, new_value int32, close_handle Handle)
+TEXT ·Sys_futex_wake_handle_close_thread_exit(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_futex_wake_handle_close_thread_exit(SB)
+
+// func Sys_debuglog_create(resource Handle, options uint32, out *Handle) Status
+TEXT ·Sys_debuglog_create(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_debuglog_create(SB)
+
+// func Sys_debuglog_write(handle Handle, options uint32, buffer unsafe.Pointer, buffer_size uint) Status
+TEXT ·Sys_debuglog_write(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_debuglog_write(SB)
+
+// func Sys_debuglog_read(handle Handle, options uint32, buffer unsafe.Pointer, buffer_size uint) Status
+TEXT ·Sys_debuglog_read(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_debuglog_read(SB)
+
+// func Sys_ktrace_read(handle Handle, data unsafe.Pointer, offset uint32, data_size uint, actual *uint) Status
+TEXT ·Sys_ktrace_read(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_ktrace_read(SB)
+
+// func Sys_ktrace_control(handle Handle, action uint32, options uint32, ptr unsafe.Pointer) Status
+TEXT ·Sys_ktrace_control(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_ktrace_control(SB)
+
+// func Sys_ktrace_write(handle Handle, id uint32, arg0 uint32, arg1 uint32) Status
+TEXT ·Sys_ktrace_write(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_ktrace_write(SB)
+
+// func Sys_mtrace_control(handle Handle, kind uint32, action uint32, options uint32, ptr unsafe.Pointer, ptr_size uint) Status
+TEXT ·Sys_mtrace_control(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_mtrace_control(SB)
+
+// func Sys_debug_read(handle Handle, buffer *uint8, buffer_size *uint) Status
+TEXT ·Sys_debug_read(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_debug_read(SB)
+
+// func Sys_debug_write(buffer *uint8, buffer_size uint) Status
+TEXT ·Sys_debug_write(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_debug_write(SB)
+
+// func Sys_debug_send_command(resource Handle, buffer *uint8, buffer_size uint) Status
+TEXT ·Sys_debug_send_command(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_debug_send_command(SB)
+
+// func Sys_interrupt_create(src_obj Handle, src_num uint32, options uint32, out_handle *Handle) Status
+TEXT ·Sys_interrupt_create(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_interrupt_create(SB)
+
+// func Sys_interrupt_bind(handle Handle, port_handle Handle, key uint64, options uint32) Status
+TEXT ·Sys_interrupt_bind(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_interrupt_bind(SB)
+
+// func Sys_interrupt_wait(handle Handle, out_timestamp *Time) Status
+TEXT ·Sys_interrupt_wait(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_interrupt_wait(SB)
+
+// func Sys_interrupt_destroy(handle Handle) Status
+TEXT ·Sys_interrupt_destroy(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_interrupt_destroy(SB)
+
+// func Sys_interrupt_ack(handle Handle) Status
+TEXT ·Sys_interrupt_ack(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_interrupt_ack(SB)
+
+// func Sys_interrupt_trigger(handle Handle, options uint32, timestamp Time) Status
+TEXT ·Sys_interrupt_trigger(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_interrupt_trigger(SB)
+
+// func Sys_interrupt_bind_vcpu(handle Handle, vcpu Handle, options uint32) Status
+TEXT ·Sys_interrupt_bind_vcpu(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_interrupt_bind_vcpu(SB)
+
+// func Sys_ioports_request(resource Handle, io_addr uint16, len uint32) Status
+TEXT ·Sys_ioports_request(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_ioports_request(SB)
+
+// func Sys_vmo_create_contiguous(bti Handle, size uint, alignment_log2 uint32, out *Handle) Status
+TEXT ·Sys_vmo_create_contiguous(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_vmo_create_contiguous(SB)
+
+// func Sys_vmo_create_physical(resource Handle, paddr Paddr, size uint, out *Handle) Status
+TEXT ·Sys_vmo_create_physical(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_vmo_create_physical(SB)
+
+// func Sys_iommu_create(resource Handle, typ uint32, desc unsafe.Pointer, desc_size uint, out *Handle) Status
+TEXT ·Sys_iommu_create(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_iommu_create(SB)
+
+// func Sys_bti_create(iommu Handle, options uint32, bti_id uint64, out *Handle) Status
+TEXT ·Sys_bti_create(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_bti_create(SB)
+
+// func Sys_bti_pin(handle Handle, options uint32, vmo Handle, offset uint64, size uint64, addrs *Paddr, addrs_count uint, pmt *Handle) Status
+TEXT ·Sys_bti_pin(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_bti_pin(SB)
+
+// func Sys_bti_release_quarantine(handle Handle) Status
+TEXT ·Sys_bti_release_quarantine(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_bti_release_quarantine(SB)
+
+// func Sys_pmt_unpin(handle Handle) Status
+TEXT ·Sys_pmt_unpin(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_pmt_unpin(SB)
+
+// func Sys_framebuffer_get_info(resource Handle, format *uint32, width *uint32, height *uint32, stride *uint32) Status
+TEXT ·Sys_framebuffer_get_info(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_framebuffer_get_info(SB)
+
+// func Sys_framebuffer_set_range(resource Handle, vmo Handle, len uint32, format uint32, width uint32, height uint32, stride uint32) Status
+TEXT ·Sys_framebuffer_set_range(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_framebuffer_set_range(SB)
+
+// func Sys_pc_firmware_tables(handle Handle, acpi_rsdp *Paddr, smbios *Paddr) Status
+TEXT ·Sys_pc_firmware_tables(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_pc_firmware_tables(SB)
+
+// func Sys_smc_call(handle Handle, parameters *SMCParameters, out_smc_result *SMCResult) Status
+TEXT ·Sys_smc_call(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_smc_call(SB)
+
+// func Sys_resource_create(parent_rsrc Handle, options uint32, base uint64, size uint, name *uint8, name_size uint, resource_out *Handle) Status
+TEXT ·Sys_resource_create(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_resource_create(SB)
+
+// func Sys_system_mexec(resource Handle, kernel_vmo Handle, bootimage_vmo Handle) Status
+TEXT ·Sys_system_mexec(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_system_mexec(SB)
+
+// func Sys_system_mexec_payload_get(resource Handle, buffer unsafe.Pointer, buffer_size uint) Status
+TEXT ·Sys_system_mexec_payload_get(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_system_mexec_payload_get(SB)
+
+// func Sys_system_powerctl(resource Handle, cmd uint32, arg *int) Status
+TEXT ·Sys_system_powerctl(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_system_powerctl(SB)
+
+// func Sys_pager_create(options uint32, out *Handle) Status
+TEXT ·Sys_pager_create(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_pager_create(SB)
+
+// func Sys_pager_create_vmo(pager Handle, options uint32, port Handle, key uint64, size uint64, out *Handle) Status
+TEXT ·Sys_pager_create_vmo(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_pager_create_vmo(SB)
+
+// func Sys_pager_detach_vmo(pager Handle, vmo Handle) Status
+TEXT ·Sys_pager_detach_vmo(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_pager_detach_vmo(SB)
+
+// func Sys_pager_supply_pages(pager Handle, pager_vmo Handle, offset uint64, length uint64, aux_vmo Handle, aux_offset uint64) Status
+TEXT ·Sys_pager_supply_pages(SB),NOSPLIT,$0
+ JMP runtime·vdsoCall_zx_pager_supply_pages(SB)
+
diff --git a/src/syscall/zx/types.go b/src/syscall/zx/types.go
new file mode 100644
index 0000000..02fd558
--- /dev/null
+++ b/src/syscall/zx/types.go
@@ -0,0 +1,480 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build fuchsia
+
+package zx
+
+import "unsafe"
+
+type Status int32 // zx_status_t
+type Handle uint32 // zx_handle_t
+type Clock uint32 // zx_clock_t,
+type Time int64 // zx_time_t, nanoseconds
+type Duration int64 // zx_duration_t, nanoseconds
+type Signals uint32 // zx_signals_t
+type Rights uint32 // zx_rights_t
+type Paddr uintptr // zx_paddr_t
+type Vaddr uintptr // zx_vaddr_t
+type ObjectType uint32 //zx_obj_type_t
+
+type WaitItem struct {
+ Handle Handle
+ WaitFor Signals
+ Pending Signals
+} // zx_wait_item_t
+
+const HandleInvalid = Handle(0)
+
+// deprecated name
+const HANDLE_INVALID = Handle(0)
+
+const HandleSize = uint64(unsafe.Sizeof(Handle(0)))
+
+const ZX_MAX_NAME_LEN = 32
+
+const (
+ ZX_RREC_DELETED = 0
+ ZX_RREC_SELF = 1
+ ZX_RREC_DATA = 2
+ ZX_RREC_IRQ = 3
+ ZX_RREC_MMIO = 4
+ ZX_RREC_IOPORT = 5
+)
+
+const (
+ ZX_RACT_ENABLE = 1
+ ZX_RACT_DISABLE = 2
+)
+
+const (
+ ZX_RREC_SELF_GENERIC = 0
+ ZX_RREC_SELF_ROOT = 1
+)
+
+type InfoHandleBasic struct {
+ Koid uint64
+ Rights Rights
+ Type ObjectType
+ RelatedKoid uint64
+ Props uint32
+} // zx_info_handle_basic_t
+
+type RrecSelf struct {
+ Type uint16 // ZX_RREC_SELF
+ Subtype uint16
+ Options uint32
+ Koid uint64
+ RecordCount uint32
+ ChildCount uint32
+ _ [2]uint32
+ Name [ZX_MAX_NAME_LEN]uint8
+} // zx_rrec_self_t
+
+type RrecMMIO struct {
+ Type uint16 // ZX_RREC_MMIO
+ Subtype uint16
+ Options uint32
+ PhysBase uint64
+ PhysSize uint64
+ _ [10]uint32
+} // zx_rrec_mmio_t
+
+type RrecIRQ struct {
+ Type uint16 // ZX_RREC_IRQ
+ Subtype uint16
+ Options uint32
+ IRQBase uint32
+ IRQCount uint32
+ _ [12]uint32
+} // zx_rrec_irq_t
+
+type RrecIOPort struct {
+ Type uint16 // ZX_RREC_IOPORT
+ Subtype uint16
+ Options uint32
+ PortBase uint32
+ PortCount uint32
+ _ [12]uint32
+} // zx_rrec_ioport_t
+
+type RrecData struct {
+ Type uint16
+ Subtype uint16
+ Options uint32 // low 4 bits are count
+ Data [56]uint8
+} // zx_rrec_data_t
+
+type Rrec struct {
+ typ uint16
+ _ [62]uint8
+} // zx_rrec_t
+
+func (r *Rrec) Box() RrecValue {
+ switch r.typ {
+ case ZX_RREC_DELETED:
+ return nil
+ case ZX_RREC_SELF:
+ return (*RrecSelf)(unsafe.Pointer(r))
+ case ZX_RREC_DATA:
+ return (*RrecData)(unsafe.Pointer(r))
+ case ZX_RREC_IRQ:
+ return (*RrecIRQ)(unsafe.Pointer(r))
+ case ZX_RREC_MMIO:
+ return (*RrecMMIO)(unsafe.Pointer(r))
+ case ZX_RREC_IOPORT:
+ return (*RrecIOPort)(unsafe.Pointer(r))
+ default:
+ return nil
+ }
+}
+
+type RrecValue interface {
+ rrec()
+}
+
+func (*RrecSelf) rrec() {}
+func (*RrecData) rrec() {}
+func (*RrecIRQ) rrec() {}
+func (*RrecMMIO) rrec() {}
+func (*RrecIOPort) rrec() {}
+
+type ChannelCallArgs struct {
+ WriteBytes unsafe.Pointer
+ WriteHandles *Handle
+ ReadBytes unsafe.Pointer
+ ReadHandles *Handle
+ WriteNumBytes uint32
+ WriteNumHandles uint32
+ ReadNumBytes uint32
+ ReadNumHandles uint32
+}
+
+type FIFOState struct {
+ head, tail uint64
+}
+
+type SMCParameters struct {
+ funcID uint32
+ arg1, arg2, arg3, arg4, arg5, arg6 uint64
+ clientId, secureOSID uint16
+}
+
+type SMCResult struct {
+ arg0, arg1, arg2, arg3 uint64
+}
+
+// Status codes. See zircon/system/public/zircon/errors.h
+const (
+ ErrOk Status = -iota
+ ErrInternal
+ ErrNotSupported
+ ErrNoResources
+ ErrNoMemory
+ ErrCallFailed
+ ErrInterruptedRetry
+ _ // -7
+ _ // -8
+ _ // -9
+ ErrInvalidArgs
+ ErrBadHandle
+ ErrWrongType
+ ErrBadSyscall
+ ErrOutOfRange
+ ErrBufferTooSmall
+ _ // -16
+ _ // -17
+ _ // -18
+ _ // -19
+ ErrBadState
+ ErrTimedOut
+ ErrShouldWait
+ ErrCanceled
+ ErrPeerClosed
+ ErrNotFound
+ ErrAlreadyExists
+ ErrAlreadyBound
+ ErrUnavailable
+ _ // -29
+ ErrAccessDenied
+ _ // -31
+ _ // -32
+ _ // -33
+ _ // -34
+ _ // -35
+ _ // -36
+ _ // -37
+ _ // -38
+ _ // -39
+ ErrIO
+ ErrIORefused
+ ErrIODataIntegrity
+ ErrIODataLoss
+ _ // -44
+ _ // -45
+ _ // -46
+ _ // -47
+ _ // -48
+ _ // -49
+ ErrBadPath
+ ErrNotDir
+ ErrNotFile
+ ErrFileBig
+ ErrNoSpace
+ ErrNotEmpty
+ _ // -56
+ _ // -57
+ _ // -58
+ _ // -59
+ ErrStop
+ ErrNext
+ _ // -62
+ _ // -63
+ _ // -64
+ _ // -65
+ _ // -66
+ _ // -67
+ _ // -68
+ _ // -69
+ ErrProtocolNotSupported
+ ErrAddressUnreachable
+ ErrAddressInUse
+ ErrNotConnected
+ ErrConnectionRefused
+ ErrConnectionReset
+ ErrConnectionAborted
+
+ // deprecated
+ ErrHandleClosed = ErrCanceled
+ ErrRemoteClosed = ErrPeerClosed
+)
+
+const (
+ SignalObject0 = (1 << iota)
+ SignalObject1
+ SignalObject2
+ SignalObject3
+ SignalObject4
+ SignalObject5
+ SignalObject6
+ SignalObject7
+ SignalObject8
+ SignalObject9
+ SignalObject10
+ SignalObject11
+ SignalObject12
+ SignalObject13
+ SignalObject14
+ SignalObject15
+ SignalObject16
+ SignalObject17
+ SignalObject18
+ SignalObject19
+ SignalObject20
+ SignalObject21
+ SignalObject22
+ SignalObject23
+
+ SignalUser0
+ SignalUser1
+ SignalUser2
+ SignalUser3
+ SignalUser4
+ SignalUser5
+ SignalUser6
+ SignalUser7
+
+ // Aliases
+ SignalHandleClosed = SignalObject23
+
+ // Event
+ SignalEventSignaled = SignalObject3
+ SignalEventMask = SignalUserAll | SignalEventSignaled
+
+ // EventPair
+ SignalEpairSignaled = SignalObject3
+ SignalEpairPeerClosed = SignalObject2
+
+ // Channel
+ SignalChannelReadable = SignalObject0
+ SignalChannelWritable = SignalObject1
+ SignalChannelPeerClosed = SignalObject2
+
+ // Socket
+ SignalSocketReadable = SignalObject0
+ SignalSocketWritable = SignalObject1
+ SignalSocketPeerClosed = SignalObject2
+ SignalSocketReadDisabled = SignalObject4
+ SignalSocketWriteDisabled = SignalObject5
+ SignalSocketControlReadable = SignalObject6
+ SignalSocketControlWriteable = SignalObject7
+ SignalSocketAccept = SignalObject8
+ SignalSocketShare = SignalObject9
+
+ // Port
+ SignalPortReadable = SignalObject0
+ SignalPortPeerClosed = SignalObject2
+ SignalPortSignaled = SignalObject3
+
+ // Resource
+ SignalResourceReadable = SignalObject0
+ SignalResourceWritable = SignalObject1
+ SignalResourceChildAdded = SignalObject2
+
+ // Fifo
+ SignalFIFOReadable = SignalObject0
+ SignalFIFOWritable = SignalObject1
+ SignalFIFOPeerClosed = SignalObject2
+ SignalFIFOSignalMask = SignalFIFOReadable | SignalFIFOWritable | SignalFIFOPeerClosed
+
+ // Task signals (process, thread, job)
+ SignalTaskTerminated = SignalObject3
+ SignalTaskSignalMask = SignalObject3
+
+ // Job
+ SignalJobSignaled = SignalObject3
+
+ // Process
+ SignalProccessSignaled = SignalObject3
+
+ // Thread
+ SignalThreadSignaled = SignalObject3
+
+ SignalObjectAll = (0xfffff)
+ SignalUserAll = Signals(15 << 4)
+ SignalNone = Signals(0)
+)
+
+const (
+ RightDuplicate = Rights(1 << iota)
+ RightTransfer
+ RightRead
+ RightWrite
+ RightExecute
+ RightDebug
+ RightSameRights = Rights(1 << 31)
+ RightNone = Rights(0)
+)
+
+// Topics for object_get_info
+const (
+ _ = iota
+ ObjectInfoHandleValid
+ ObjectInfoHandleBasic
+ ObjectInfoProcess
+ ObjectInfoProcessThreads
+ ObjectInfoResourceChildren
+ ObjectInfoResourceRecords
+ ObjectInfoVMAR
+)
+
+const (
+ ObjectTypeNone = ObjectType(iota)
+ ObjectTypeProcess
+ ObjectTypeThread
+ ObjectTypeVmo
+ ObjectTypeChannel
+ ObjectTypeEvent
+ ObjectTypePort
+ _ // 7
+ _ // 8
+ ObjectTypeInterrupt
+ _ // 10
+ ObjectTypePciDevice
+ ObjectTypeLog
+ _ // 13
+ ObjectTypeSocket
+ ObjectTypeResource
+ ObjectTypeEventPair
+ ObjectTypeJob
+ ObjectTypeVmar
+ ObjectTypeFifo
+ ObjectTypeGuest
+ ObjectTypeVcpu
+ ObjectTypeTimer
+ ObjectTypeIommu
+ ObjectTypeBti
+ ObjectTypeProfile
+ ObjectTypePmt
+ ObjectTypeSuspendToken
+ ObjectTypePager
+)
+
+// Options for socket_create
+const (
+ SocketStream = iota // 0
+ SocketDatagram = 1 << (iota - 1) // 1
+ SocketHasControl // 2
+ SocketHasAccept // 4
+)
+
+// Options for socket_write
+const (
+ _ = iota // 0
+ SocketShutdownWrite // 1
+ SocketShutdownRead // 2
+)
+
+// Options for socket_write and socket_read
+const (
+ SocketControl = 1 << 2
+)
+
+const (
+ _ = iota // 0
+ _ // 1
+ PropNumStateKinds // ZX_PROP_NUM_STATE_KINDS
+ PropName // ZX_PROP_NAME
+ PropRegisterFS // ZX_PROP_REGISTER_FS
+ PropProcessDebugAddr // ZX_PROP_PROCESS_DEBUG_ADDR
+ PropProcessVDSOBaseAddress // ZX_PROP_PROCESS_VDSO_BASE_ADDRESS
+ PropJobMaxHeight // ZX_PROP_JOB_MAX_HEIGHT
+)
+
+const (
+ TimensecInfinite = Time(0x7FFFFFFFFFFFFFFF)
+)
+
+// EOF is used like io.EOF.
+//
+// When package io is linked in, at initialization this value is
+// rewritten to be equivalent to io.EOF, so that the io.Readers
+// and io.Writers in this package meet their specs.
+var EOF error = eof{}
+
+type eof struct{}
+
+func (eof) Error() string { return "zx.EOF" }
+
+// EPIPE is used like syscall.EPIPE
+
+// When package syscall is linked in, at initialization this value is
+// rewritten to be equivalent to syscall.EPIPE.
+
+var EPIPE error = epipe{}
+
+type epipe struct{}
+
+func (epipe) Error() string { return "errno(32)" }
+
+type VMOOption int
+
+const (
+ VMOOptionNonResizable VMOOption = 1 << 0 // ZX_VMO_NON_RESIZABLE
+)
+
+type VMFlag uint32
+
+const (
+ VMFlagPermRead VMFlag = 1 << 0 // ZX_VM_PERM_READ
+ VMFlagPermWrite VMFlag = 1 << 1 // ZX_VM_PERM_WRITE
+ VMFlagPermExecute VMFlag = 1 << 2 // ZX_VM_PERM_EXECUTE
+ VMFlagCompact VMFlag = 1 << 3 // ZX_VM_COMPACT
+ VMFlagSpecific VMFlag = 1 << 4 // ZX_VM_SPECIFIC
+ VMFlagSpecificOverwrite VMFlag = 1 << 5 // ZX_VM_SPECIFIC_OVERWRITE
+ VMFlagCanMapSpecific VMFlag = 1 << 6 // ZX_VM_CAN_MAP_SPECIFIC
+ VMFlagCanMapRead VMFlag = 1 << 7 // ZX_VM_CAN_MAP_READ
+ VMFlagCanMapWrite VMFlag = 1 << 8 // ZX_VM_CAN_MAP_WRITE
+ VMFlagCanMapExecute VMFlag = 1 << 9 // ZX_VM_CAN_MAP_EXECUTE
+)
diff --git a/src/syscall/zx/types_string.go b/src/syscall/zx/types_string.go
new file mode 100644
index 0000000..aac9809
--- /dev/null
+++ b/src/syscall/zx/types_string.go
@@ -0,0 +1,68 @@
+// generated by stringer -type=Status; DO NOT EDIT
+
+// +build fuchsia
+
+package zx
+
+const (
+ _Status_name_0 = "ErrNoSpaceErrFileBigErrNotFileErrNotDirErrBadPath"
+ _Status_name_1 = "ErrIODataLossErrIODataIntegrityErrIORefusedErrIO"
+ _Status_name_2 = "ErrAccessDenied"
+ _Status_name_3 = "ErrUnavailableErrAlreadyBoundErrAlreadyExistsErrNotFoundErrPeerClosedErrCanceledErrShouldWaitErrTimedOutErrBadState"
+ _Status_name_4 = "ErrBufferTooSmallErrOutOfRangeErrBadSyscallErrWrongTypeErrBadHandleErrInvalidArgs"
+ _Status_name_5 = "ErrInterruptedRetryErrCallFailedErrNoMemoryErrNoResourcesErrNotSupportedErrInternalErrOk"
+)
+
+var (
+ _Status_index_0 = [...]uint8{0, 10, 20, 30, 39, 49}
+ _Status_index_1 = [...]uint8{0, 13, 31, 43, 48}
+ _Status_index_2 = [...]uint8{0, 15}
+ _Status_index_3 = [...]uint8{0, 14, 29, 45, 56, 69, 80, 93, 104, 115}
+ _Status_index_4 = [...]uint8{0, 17, 30, 43, 55, 67, 81}
+ _Status_index_5 = [...]uint8{0, 19, 32, 43, 57, 72, 83, 88}
+)
+
+func (i Status) String() string {
+ switch {
+ case -54 <= i && i <= -50:
+ i -= -54
+ return _Status_name_0[_Status_index_0[i]:_Status_index_0[i+1]]
+ case -43 <= i && i <= -40:
+ i -= -43
+ return _Status_name_1[_Status_index_1[i]:_Status_index_1[i+1]]
+ case i == -30:
+ return _Status_name_2
+ case -28 <= i && i <= -20:
+ i -= -28
+ return _Status_name_3[_Status_index_3[i]:_Status_index_3[i+1]]
+ case -15 <= i && i <= -10:
+ i -= -15
+ return _Status_name_4[_Status_index_4[i]:_Status_index_4[i+1]]
+ case -6 <= i && i <= 0:
+ i -= -6
+ return _Status_name_5[_Status_index_5[i]:_Status_index_5[i+1]]
+ default:
+ var buf [20]byte
+ return "zx.Status(" + string(itoa(buf[:], int(i))) + ")"
+ }
+}
+
+func itoa(buf []byte, val int) []byte {
+ i := len(buf) - 1
+ neg := false
+ if val < 0 {
+ neg = true
+ val = 0 - val
+ }
+ for val >= 10 {
+ buf[i] = byte(val%10 + '0')
+ i--
+ val /= 10
+ }
+ buf[i] = byte(val + '0')
+ if neg {
+ i--
+ buf[i] = '-'
+ }
+ return buf[i:]
+}
diff --git a/src/syscall/zx/zxsocket/socket.go b/src/syscall/zx/zxsocket/socket.go
new file mode 100644
index 0000000..99bf383
--- /dev/null
+++ b/src/syscall/zx/zxsocket/socket.go
@@ -0,0 +1,303 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build fuchsia
+
+package zxsocket
+
+import (
+ "io"
+ "syscall"
+ "syscall/zx"
+ "syscall/zx/fdio"
+ fidlIo "syscall/zx/io"
+ "syscall/zx/mxnet"
+ "syscall/zx/net"
+ "syscall/zx/zxwait"
+)
+
+// Socket is an fdio.FDIO socket.
+type Socket struct {
+ net.SocketControlInterface
+
+ dgram bool
+ flags uint32
+}
+
+func NewSocket(s zx.Socket) *Socket {
+ return &Socket{
+ SocketControlInterface: net.SocketControlInterface{
+ Socket: s,
+ },
+ }
+}
+
+func (s *Socket) Wait(signals zx.Signals, timeout zx.Time) (zx.Signals, error) {
+ return zxwait.Wait(zx.Handle(s.Socket), signals, timeout)
+}
+
+// Handles returns the underlying handles for this Socket.
+func (s *Socket) Handles() []zx.Handle {
+ return []zx.Handle{zx.Handle(s.Socket)}
+}
+
+// Clone makes a clone of the object.
+func (s *Socket) Clone() (fdio.FDIO, error) {
+ return nil, &zx.Error{Status: zx.ErrNotSupported, Text: "zxsocket.Socket.Clone"}
+}
+
+// Close closes the object.
+func (s *Socket) Close() error {
+ if code, err := s.SocketControlInterface.Close(); err != nil {
+ return err
+ } else if code != 0 {
+ return syscall.Errno(code)
+ }
+
+ return s.Socket.Close()
+}
+
+// Sync implements fdio.FDIO for Socket.
+func (s *Socket) Sync() error {
+ return &zx.Error{Status: zx.ErrNotSupported, Text: "zxsocket.Socket"}
+}
+
+// GetAttr implements fdio.FDIO for Socket.
+func (s *Socket) GetAttr() (fidlIo.NodeAttributes, error) {
+ return fidlIo.NodeAttributes{}, &zx.Error{Status: zx.ErrNotSupported, Text: "zxsocket.Socket"}
+}
+
+// SetAttr implements fdio.FDIO for Socket.
+func (s *Socket) SetAttr(flags uint32, attr fidlIo.NodeAttributes) error {
+ return &zx.Error{Status: zx.ErrNotSupported, Text: "zxsocket.Socket"}
+}
+
+// Ioctl implements fdio.FDIO for Socket.
+func (s *Socket) Ioctl(op uint32, max uint64, in []byte, _ []zx.Handle) ([]byte, []zx.Handle, error) {
+ code, out, err := s.SocketControlInterface.Ioctl(int16(op), in)
+ if err != nil {
+ return nil, nil, err
+ }
+ if code != 0 {
+ return nil, nil, syscall.Errno(code)
+ }
+ return out, nil, nil
+}
+
+// Read implements fdio.FDIO for Socket.
+func (s *Socket) Read(data []byte) (n int, err error) {
+ if s.dgram {
+ b, _, _, _, err := s.RecvMsg(len(data))
+ n = copy(data, b)
+ return n, err
+ }
+ // c.f. zxs_recvmsg_stream in zircon/system/ulib/zxs/zxs.cpp
+ for {
+ n, err := s.Socket.Read(data, 0)
+ if err != nil {
+ if err, ok := err.(*zx.Error); ok {
+ switch err.Status {
+ case zx.ErrPeerClosed:
+ return 0, io.EOF
+ case zx.ErrShouldWait:
+ obs, err := s.Wait(zx.SignalSocketReadable|zx.SignalSocketPeerClosed, zx.TimensecInfinite)
+ if err != nil {
+ if err, ok := err.(*zx.Error); ok {
+ switch err.Status {
+ case zx.ErrBadHandle, zx.ErrCanceled:
+ return 0, io.EOF
+ }
+ }
+ return 0, err
+ }
+ switch {
+ case obs&zx.SignalSocketReadable != 0:
+ continue
+ case obs&zx.SignalSocketPeerClosed != 0:
+ return 0, io.EOF
+ }
+ }
+ }
+ return 0, err
+ }
+ return n, nil
+ }
+}
+
+// ReadAt implements fdio.FDIO for Socket.
+func (s *Socket) ReadAt(data []byte, off int64) (int, error) {
+ return 0, &zx.Error{Status: zx.ErrNotSupported, Text: "zxsocket.Socket"}
+}
+
+// Write implements fdio.FDIO for Socket.
+func (s *Socket) Write(data []byte) (int, error) {
+ if s.dgram {
+ n, err := s.SendMsg(data, "", 0)
+ return n, err
+ }
+
+ // c.f. zxsio_sendmsg_stream
+ var total int
+ for {
+ n, err := s.Socket.Write(data, 0)
+ total += n
+ if err != nil {
+ if err, ok := err.(*zx.Error); ok {
+ switch err.Status {
+ case zx.ErrShouldWait:
+ obs, err := s.Wait(zx.SignalSocketWritable|zx.SignalSocketPeerClosed|zx.SignalSocketWriteDisabled, zx.TimensecInfinite)
+ if err != nil {
+ return total, err
+ }
+ if obs&zx.SignalSocketPeerClosed != 0 || obs&zx.SignalSocketWriteDisabled != 0 {
+ return total, &zx.Error{Status: zx.ErrPeerClosed, Text: "zxsocket.Socket.Write"}
+ }
+ if obs&zx.SignalSocketWritable != 0 {
+ data = data[n:]
+ continue
+ }
+ // This case should be impossible:
+ return total, &zx.Error{Status: zx.ErrInternal, Text: "zxsocket.Socket.Write(impossible state)"}
+ }
+ }
+ return total, err
+ }
+ return total, nil
+ }
+}
+
+// WriteAt implements fdio.FDIO for Socket.
+func (s *Socket) WriteAt(data []byte, off int64) (int, error) {
+ return 0, &zx.Error{Status: zx.ErrNotSupported, Text: "zxsocket.Socket"}
+}
+
+// Seek implements fdio.FDIO for Socket.
+func (s *Socket) Seek(offset int64, whence int) (int64, error) {
+ return 0, &zx.Error{Status: zx.ErrNotSupported, Text: "zxsocket.Socket"}
+}
+
+// Truncate implements fdio.FDIO for Socket.
+func (s *Socket) Truncate(length uint64) error {
+ return &zx.Error{Status: zx.ErrNotSupported, Text: "zxsocket.Socket"}
+}
+
+// Open implements fdio.FDIO for Socket.
+func (s *Socket) Open(path string, flags uint32, mode uint32) (fdio.FDIO, error) {
+ return nil, &zx.Error{Status: zx.ErrNotSupported, Text: "zxsocket.Socket"}
+}
+
+// Link implements fdio.FDIO for Socket.
+func (s *Socket) Link(oldpath, newpath string) error {
+ return &zx.Error{Status: zx.ErrNotSupported, Text: "zxsocket.Socket"}
+}
+
+// Rename implements fdio.FDIO for Socket.
+func (s *Socket) Rename(oldpath, newpath string) error {
+ return &zx.Error{Status: zx.ErrNotSupported, Text: "zxsocket.Socket"}
+}
+
+// Unlink implements fdio.FDIO for Socket.
+func (s *Socket) Unlink(path string) error {
+ return &zx.Error{Status: zx.ErrNotSupported, Text: "zxsocket.Socket"}
+}
+
+// ReadDirents implements fdio.FDIO for Socket.
+func (s *Socket) ReadDirents(max uint64) ([]byte, error) {
+ return nil, &zx.Error{Status: zx.ErrNotSupported, Text: "zxsocket.Socket"}
+}
+
+// Rewind implements fdio.FDIO for Socket.
+func (s *Socket) Rewind() error {
+ return &zx.Error{Status: zx.ErrNotSupported, Text: "zxsocket.Socket"}
+}
+
+func (s *Socket) RecvMsg(maxLen int) (b []byte, flags int, addr string, port uint16, err error) {
+ mlen := maxLen + mxnet.SockmsgHdrLen
+ msgdata := make([]byte, mlen)
+ n, err := s.recvMsg(msgdata)
+ if err != nil {
+ return nil, 0, "", 0, err
+ }
+ msgdata = msgdata[:n]
+ addrstr, port, flags, err := mxnet.DecodeSockmsgHdr(msgdata)
+ if err != nil {
+ return nil, 0, "", 0, err
+ }
+ return msgdata[mxnet.SockmsgHdrLen:], flags, string(addrstr), port, nil
+}
+
+func (s *Socket) recvMsg(data []byte) (int, error) {
+ for {
+ n, err := s.Socket.Read(data, 0)
+ if err != nil {
+ if err, ok := err.(*zx.Error); ok {
+ switch err.Status {
+ case zx.ErrShouldWait:
+ if n != 0 {
+ return n, &zx.Error{Status: zx.ErrInternal, Text: "zsocket.Socket.recvMsg(datagram short-read)"}
+ }
+ obs, err := s.Wait(zx.SignalSocketReadable|zx.SignalSocketPeerClosed|zx.SignalSocketReadDisabled, zx.TimensecInfinite)
+ if err != nil {
+ return n, err
+ }
+ if obs&zx.SignalSocketReadable != 0 {
+ continue
+ }
+ if obs&zx.SignalSocketPeerClosed != 0 || obs&zx.SignalSocketReadDisabled != 0 {
+ return n, &zx.Error{Status: zx.ErrPeerClosed, Text: "zxsocket.Socket.recvMsg"}
+ }
+ return n, &zx.Error{Status: zx.ErrInternal, Text: "zxsocket.Socket.recvMsg(impossible state))"}
+ }
+ }
+ return n, err
+ }
+ return n, nil
+ }
+}
+
+func (s *Socket) SendMsg(b []byte, addr string, port uint16) (int, error) {
+ data := make([]byte, len(b)+mxnet.SockmsgHdrLen)
+ err := mxnet.EncodeSockmsgHdr(data, mxnet.Addr(addr), port, 0)
+ if err != nil {
+ return 0, err
+ }
+ copy(data[mxnet.SockmsgHdrLen:], b)
+
+ for {
+ n, err := s.Socket.Write(data, 0)
+ if err != nil {
+ if err, ok := err.(*zx.Error); ok {
+ switch err.Status {
+ case zx.ErrShouldWait:
+ if n != 0 {
+ return n, &zx.Error{Status: zx.ErrInternal, Text: "zxsocket.Socket.SendMsg(datagram short-write)"}
+ }
+
+ obs, err := s.Wait(zx.SignalSocketWritable|zx.SignalSocketPeerClosed|zx.SignalSocketWriteDisabled, zx.TimensecInfinite)
+ if err != nil {
+ return 0, err
+ }
+ if obs&zx.SignalSocketWritable != 0 {
+ continue
+ }
+ if obs&zx.SignalSocketPeerClosed != 0 || obs&zx.SignalSocketWriteDisabled != 0 {
+ return 0, &zx.Error{Status: zx.ErrPeerClosed, Text: "zxsocket.Socket.SendMsg"}
+ }
+ return 0, &zx.Error{Status: zx.ErrInternal, Text: "zxsocket.Socket.SendMsg(impossible state)"}
+ }
+ }
+ if n != 0 {
+ return n, &zx.Error{Status: zx.ErrInternal, Text: "zxsocket.Socket.SendMsg(datagram short-write)"}
+ }
+ return 0, err
+ }
+ return len(b), nil
+ }
+}
+
+// SetDgram marks a *Socket as a datagram (UDP) socket.
+// A different protocol is used internally.
+func (s *Socket) SetDgram() {
+ s.dgram = true
+}
diff --git a/src/syscall/zx/zxsocket/stub.go b/src/syscall/zx/zxsocket/stub.go
new file mode 100644
index 0000000..3eed571
--- /dev/null
+++ b/src/syscall/zx/zxsocket/stub.go
@@ -0,0 +1,3 @@
+//+build !fuchsia
+
+package zxsocket
diff --git a/src/syscall/zx/zxwait/zxwait.go b/src/syscall/zx/zxwait/zxwait.go
new file mode 100644
index 0000000..9b1f924
--- /dev/null
+++ b/src/syscall/zx/zxwait/zxwait.go
@@ -0,0 +1,201 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build fuchsia
+
+// Package zxwait implements a Zircon port waiter compatible with goroutines.
+//
+// The function Wait can be used to wait on a handle without consuming
+// an OS thread or resorting to event-driven programming.
+package zxwait
+
+import (
+ "sync"
+ "sync/atomic"
+ "syscall/zx"
+
+ _ "unsafe" // for go:linkname
+)
+
+// Wait waits for signals on handle.
+//
+// The goroutine that calls Wait is parked until a signal is observed or the
+// handle is closed. No OS thread is tied up while Wait is blocked.
+//
+// Semantically it is equivalent to calling the WaitOne method on a zx.Handle.
+// However it is not implemented with zx_object_wait_one, instead it uses
+// zx_object_wait_async and a port to wait for signals.
+func Wait(handle zx.Handle, signals zx.Signals, timeout zx.Time) (zx.Signals, error) {
+ // TODO: support finite timeouts.
+ if timeout != zx.TimensecInfinite {
+ var observed zx.Signals
+ if status := zx.Sys_object_wait_one(handle, signals, timeout, &observed); status != zx.ErrOk {
+ return observed, &zx.Error{Status: status, Text: "zxwait.Wait"}
+ }
+ return observed, nil
+ }
+ sysWaiterOnce.Do(sysWaiterInit)
+ return sysWaiter.Wait(handle, signals)
+}
+
+//go:linkname gopark runtime.gopark
+func gopark(unlockf func(g uintptr, waiting *waitingG) bool, waitng *waitingG, reason uint8, traceEv byte, traceskip int)
+
+//go:linkname goready runtime.goready
+func goready(g uintptr, traceskip int)
+
+// waitingG is used to track a parked g waiting for a signal.
+//
+// A waitingG is represented by a unique key, which is also its positional
+// index in the waiter's all slice. This key is not a GCed pointer, so it can
+// be safely passed to the kernel and returned at a later time.
+type waitingG struct {
+ // key is an index into the waiter's all slice. It is never modified.
+ key uint64
+
+ parked uintptr
+ g uintptr
+
+ // handle is the handle on which the g is waiting for a signal. It is
+ // always manipulated under the waiter's lock; before unparking the g,
+ // it is set to the sentinel value zx.HandleInvalid to protect against
+ // double unparking (can happen when local handles are closed).
+ handle zx.Handle
+ obs zx.Signals
+}
+
+// A waiter is a zircon port that parks goroutines waiting on signals.
+//
+// Currently there is only one instance of waiter per process, stored
+// in sysWaiter. It is however a self-contained object and multiple
+// of them can safely exist concurrently.
+type waiter struct {
+ port zx.Port
+
+ mu struct {
+ sync.Mutex
+ free []*waitingG
+ all []*waitingG
+ }
+}
+
+func init() {
+ port, err := zx.NewPort(0)
+ if err != nil {
+ panic(err) // misuse of system call, no useful recovery
+ }
+ sysWaiter = &waiter{port: port}
+ zx.SetZXWaitCloseFn(sysWaiter.close)
+}
+
+var sysWaiterOnce sync.Once
+var sysWaiter *waiter
+
+func sysWaiterInit() {
+ go sysWaiter.dequeue()
+}
+
+// dequeue is a dedicated goroutine to waiting on the waiter's port.
+func (w *waiter) dequeue() {
+ var pkt zx.Packet
+ for {
+ if err := w.port.Wait(&pkt, zx.TimensecInfinite); err != nil {
+ panic(err)
+ }
+
+ w.mu.Lock()
+ waiting := w.mu.all[pkt.Hdr.Key]
+ handle := waiting.handle
+ waiting.handle = zx.HandleInvalid
+ w.mu.Unlock()
+
+ if handle != zx.HandleInvalid {
+ waiting.wakeup(pkt.Signal().Observed)
+ }
+ }
+}
+
+func (waiting *waitingG) wakeup(obs zx.Signals) {
+ waiting.obs = obs
+
+ if running := atomic.CompareAndSwapUintptr(&waiting.parked, 0, 1); !running {
+ goready(atomic.SwapUintptr(&waiting.g, 0), 0)
+ }
+}
+
+func (w *waiter) close(handle zx.Handle) {
+ w.mu.Lock()
+ for _, waiting := range w.mu.all {
+ if waiting.handle == handle {
+ waiting.handle = zx.HandleInvalid
+ waiting.wakeup(zx.SignalHandleClosed)
+ }
+ }
+ w.mu.Unlock()
+}
+
+// Wait waits for signals on handle.
+//
+// See the package function Wait for more commentary.
+func (w *waiter) Wait(handle zx.Handle, signals zx.Signals) (zx.Signals, error) {
+ var waiting *waitingG
+
+ w.mu.Lock()
+ if len(w.mu.free) == 0 {
+ waiting = &waitingG{
+ key: uint64(len(w.mu.all)),
+ }
+ w.mu.all = append(w.mu.all, waiting)
+ } else {
+ waiting = w.mu.free[len(w.mu.free)-1]
+ w.mu.free = w.mu.free[:len(w.mu.free)-1]
+
+ // parked will have been set to 1 at the end of the previous use.
+ waiting.parked = 0
+ }
+ waiting.handle = handle
+ w.mu.Unlock()
+
+ if err := w.port.WaitAsync(handle, waiting.key, signals, zx.PortWaitAsyncOnce); err != nil {
+ return 0, err
+ }
+
+ const waitReasonZXWait = 24
+ const traceEvGoBlockSelect = 24
+ gopark(w.unlockf, waiting, waitReasonZXWait, traceEvGoBlockSelect, 0)
+
+ obs := waiting.obs
+
+ w.mu.Lock()
+ w.mu.free = append(w.mu.free, waiting)
+ w.mu.Unlock()
+
+ var err error
+ if obs == zx.SignalHandleClosed {
+ err = &zx.Error{Status: zx.ErrCanceled, Text: "zxwait.Wait"}
+ }
+
+ return obs, err
+}
+
+// unlockf is passed as a callback to gopark.
+//
+// Reporting true will park the goroutine until goready is called.
+//
+// Reporting false will immediately start running the goroutine
+// again, and nothing else should call goready.
+//
+// This method is called without a 'g', so it can do very little.
+// Avoid the stack. Don't use anything with 'g'-based runtime
+// support (like sync.Mutex). Do as little as possible.
+func (w *waiter) unlockf(g uintptr, waiting *waitingG) bool {
+ atomic.StoreUintptr(&waiting.g, g)
+
+ // If we can set ready, then this executed before dequeue
+ // and the goroutine will be parked.
+ //
+ // If we cannot set it, then dequeue has already run and
+ // waiting.obs is set, so do not park the goroutine.
+ return atomic.CompareAndSwapUintptr(&waiting.parked, 0, 1)
+}
diff --git a/src/syscall/zx/zxwait/zxwait.s b/src/syscall/zx/zxwait/zxwait.s
new file mode 100644
index 0000000..a35105e
--- /dev/null
+++ b/src/syscall/zx/zxwait/zxwait.s
@@ -0,0 +1,5 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Empty assembly file so empty func definitions work.
diff --git a/src/syscall/zx/zxwait/zxwait_test.go b/src/syscall/zx/zxwait/zxwait_test.go
new file mode 100644
index 0000000..261c837
--- /dev/null
+++ b/src/syscall/zx/zxwait/zxwait_test.go
@@ -0,0 +1,133 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build fuchsia
+
+package zxwait_test
+
+import (
+ "sync"
+ "syscall/zx"
+ "syscall/zx/zxwait"
+ "testing"
+)
+
+func TestWaitPreexisting(t *testing.T) {
+ c0, c1, err := zx.NewChannel(0)
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer func() {
+ _ = c0.Close()
+ _ = c1.Close()
+ }()
+
+ for _, ch := range [...]zx.Channel{c0, c1} {
+ obs, err := zxwait.Wait(*ch.Handle(), zx.SignalChannelWritable, zx.TimensecInfinite)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if want := zx.Signals(zx.SignalChannelWritable); obs != want {
+ t.Errorf("got obs = %x, want = %x", obs, want)
+ }
+ }
+}
+
+type waitResult struct {
+ obs zx.Signals
+ err error
+}
+
+func TestWait(t *testing.T) {
+ var pairs [][2]zx.Channel
+
+ ch := make(chan waitResult, 100)
+ for i := 0; i < cap(ch); i++ {
+ ch1, ch2, err := zx.NewChannel(0)
+ if err != nil {
+ t.Fatal(err)
+ }
+ pair := [...]zx.Channel{ch1, ch2}
+ pairs = append(pairs, pair)
+ go func() {
+ obs, err := zxwait.Wait(*pair[0].Handle(), zx.SignalChannelReadable, zx.TimensecInfinite)
+ ch <- waitResult{obs: obs, err: err}
+ }()
+ }
+
+ b := []byte("hello")
+ for i, pair := range pairs {
+ if err := pair[1].Write(b, nil, 0); err != nil {
+ t.Fatalf("%d: %s", i, err)
+ }
+ }
+
+ for i := 0; i < cap(ch); i++ {
+ waitResult := <-ch
+ if err := waitResult.err; err != nil {
+ t.Fatal(err)
+ }
+ if obs, want := waitResult.obs, zx.Signals(zx.SignalChannelReadable|zx.SignalChannelWritable); obs != want {
+ t.Errorf("%d: got obs = %b, want = %b", i, obs, want)
+ }
+ }
+}
+
+func TestWait_LocalClose(t *testing.T) {
+ event, err := zx.NewEvent(0)
+ if err != nil {
+ t.Fatal(err)
+ }
+ ch := make(chan waitResult, 100)
+ var wg sync.WaitGroup
+ for i := 0; i < cap(ch)-1; i++ {
+ wg.Add(1)
+ go func() {
+ wg.Done()
+ obs, err := zxwait.Wait(*event.Handle(), 0, zx.TimensecInfinite)
+ ch <- waitResult{obs: obs, err: err}
+ }()
+ }
+ // Wait for all goroutines to be scheduled.
+ wg.Wait()
+ if err := event.Close(); err != nil {
+ t.Fatal(err)
+ }
+ // Guarantee at least one result happens after local close.
+ {
+ obs, err := zxwait.Wait(*event.Handle(), 0, zx.TimensecInfinite)
+ ch <- waitResult{obs: obs, err: err}
+ }
+ var badHandle, cancelled int
+ for i := 0; i < cap(ch); i++ {
+ waitResult := <-ch
+ err := waitResult.err
+ switch err := err.(type) {
+ case *zx.Error:
+ obs := waitResult.obs
+ switch err.Status {
+ case zx.ErrBadHandle:
+ // This goroutine didn't get scheduled in time.
+ if want := zx.Signals(0); obs != want {
+ t.Errorf("%d: got obs = %b, want = %b", i, obs, want)
+ }
+ badHandle++
+ continue
+ case zx.ErrCanceled:
+ if want := zx.Signals(zx.SignalHandleClosed); obs != want {
+ t.Errorf("%d: got obs = %b, want = %b", i, obs, want)
+ }
+ cancelled++
+ continue
+ }
+ }
+ t.Errorf("%d: got zxwait.Wait(<closed handle>) = (_, %s), want = (_, %s or %s)", i, err, zx.ErrBadHandle, zx.ErrCanceled)
+ }
+ if badHandle == 0 {
+ t.Errorf("failed to observe post-close condition")
+ }
+ if cancelled == 0 {
+ t.Error("failed to observe pre-close condition")
+ }
+}
diff --git a/src/time/sys_fuchsia.go b/src/time/sys_fuchsia.go
new file mode 100644
index 0000000..2a28362
--- /dev/null
+++ b/src/time/sys_fuchsia.go
@@ -0,0 +1,33 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package time
+
+// for testing: whatever interrupts a sleep
+func interrupt() {
+}
+
+func initLocal() {
+ localLoc.name = "UTC"
+}
+
+func read(fd uintptr, buf []byte) (int, error) {
+ panic("TODO")
+}
+
+func open(name string) (uintptr, error) {
+ panic("TODO")
+}
+
+func closefd(fd uintptr) {
+ panic("TODO")
+}
+
+func preadn(fd uintptr, buf []byte, off int) error {
+ panic("TODO")
+}
+
+func isNotExist(err error) bool {
+ panic("TODO")
+}
diff --git a/src/time/zoneinfo_fuchsia.go b/src/time/zoneinfo_fuchsia.go
new file mode 100644
index 0000000..09a6696
--- /dev/null
+++ b/src/time/zoneinfo_fuchsia.go
@@ -0,0 +1,7 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package time
+
+var zoneSources = []string{}