deps: update runc to 1.1.0
This updates vendored runc/libcontainer to 1.1.0, and google/cadvisor to a version updated to runc 1.1.0 (google/cadvisor#3048). Changes in vendor are generated by (roughly): ./hack/pin-dependency.sh github.com/google/cadvisor v0.44.0 ./hack/pin-dependency.sh github.com/opencontainers/runc v1.1.0 ./hack/update-vendor.sh ./hack/lint-dependencies.sh # And follow all its recommendations. ./hack/update-vendor.sh ./hack/update-internal-modules.sh ./hack/lint-dependencies.sh # Re-check everything again. Co-Authored-By: Kir Kolyshkin <kolyshkin@gmail.com>
This commit is contained in:
parent
41830a1f79
commit
07af1bab70
31
LICENSES/vendor/github.com/bits-and-blooms/bitset/LICENSE
generated
vendored
31
LICENSES/vendor/github.com/bits-and-blooms/bitset/LICENSE
generated
vendored
@ -1,31 +0,0 @@
|
|||||||
= vendor/github.com/bits-and-blooms/bitset licensed under: =
|
|
||||||
|
|
||||||
Copyright (c) 2014 Will Fitzgerald. All rights reserved.
|
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
|
||||||
modification, are permitted provided that the following conditions are
|
|
||||||
met:
|
|
||||||
|
|
||||||
* Redistributions of source code must retain the above copyright
|
|
||||||
notice, this list of conditions and the following disclaimer.
|
|
||||||
* Redistributions in binary form must reproduce the above
|
|
||||||
copyright notice, this list of conditions and the following disclaimer
|
|
||||||
in the documentation and/or other materials provided with the
|
|
||||||
distribution.
|
|
||||||
* Neither the name of Google Inc. nor the names of its
|
|
||||||
contributors may be used to endorse or promote products derived from
|
|
||||||
this software without specific prior written permission.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
= vendor/github.com/bits-and-blooms/bitset/LICENSE 0d2b5d66dabaff0df8e1ffe191a21bd1
|
|
37
go.mod
37
go.mod
@ -31,7 +31,7 @@ require (
|
|||||||
github.com/coreos/go-systemd/v22 v22.3.2
|
github.com/coreos/go-systemd/v22 v22.3.2
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.1
|
github.com/cpuguy83/go-md2man/v2 v2.0.1
|
||||||
github.com/davecgh/go-spew v1.1.1
|
github.com/davecgh/go-spew v1.1.1
|
||||||
github.com/docker/distribution v2.7.1+incompatible
|
github.com/docker/distribution v2.8.0+incompatible
|
||||||
github.com/docker/go-units v0.4.0
|
github.com/docker/go-units v0.4.0
|
||||||
github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153
|
github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153
|
||||||
github.com/emicklei/go-restful v2.9.5+incompatible
|
github.com/emicklei/go-restful v2.9.5+incompatible
|
||||||
@ -39,12 +39,12 @@ require (
|
|||||||
github.com/fsnotify/fsnotify v1.4.9
|
github.com/fsnotify/fsnotify v1.4.9
|
||||||
github.com/go-logr/logr v1.2.0
|
github.com/go-logr/logr v1.2.0
|
||||||
github.com/go-ozzo/ozzo-validation v3.5.0+incompatible // indirect
|
github.com/go-ozzo/ozzo-validation v3.5.0+incompatible // indirect
|
||||||
github.com/godbus/dbus/v5 v5.0.4
|
github.com/godbus/dbus/v5 v5.0.6
|
||||||
github.com/gogo/protobuf v1.3.2
|
github.com/gogo/protobuf v1.3.2
|
||||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da
|
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da
|
||||||
github.com/golang/mock v1.5.0
|
github.com/golang/mock v1.5.0
|
||||||
github.com/golang/protobuf v1.5.2
|
github.com/golang/protobuf v1.5.2
|
||||||
github.com/google/cadvisor v0.43.0
|
github.com/google/cadvisor v0.44.0
|
||||||
github.com/google/gnostic v0.5.7-v3refs
|
github.com/google/gnostic v0.5.7-v3refs
|
||||||
github.com/google/go-cmp v0.5.5
|
github.com/google/go-cmp v0.5.5
|
||||||
github.com/google/gofuzz v1.1.0
|
github.com/google/gofuzz v1.1.0
|
||||||
@ -63,8 +63,8 @@ require (
|
|||||||
github.com/mvdan/xurls v1.1.0
|
github.com/mvdan/xurls v1.1.0
|
||||||
github.com/onsi/ginkgo v1.14.0
|
github.com/onsi/ginkgo v1.14.0
|
||||||
github.com/onsi/gomega v1.10.1
|
github.com/onsi/gomega v1.10.1
|
||||||
github.com/opencontainers/runc v1.0.3
|
github.com/opencontainers/runc v1.1.0
|
||||||
github.com/opencontainers/selinux v1.8.2
|
github.com/opencontainers/selinux v1.10.0
|
||||||
github.com/pkg/errors v0.9.1
|
github.com/pkg/errors v0.9.1
|
||||||
github.com/pmezard/go-difflib v1.0.0
|
github.com/pmezard/go-difflib v1.0.0
|
||||||
github.com/prometheus/client_golang v1.12.1
|
github.com/prometheus/client_golang v1.12.1
|
||||||
@ -178,7 +178,6 @@ replace (
|
|||||||
github.com/aws/aws-sdk-go => github.com/aws/aws-sdk-go v1.38.49
|
github.com/aws/aws-sdk-go => github.com/aws/aws-sdk-go v1.38.49
|
||||||
github.com/benbjohnson/clock => github.com/benbjohnson/clock v1.1.0
|
github.com/benbjohnson/clock => github.com/benbjohnson/clock v1.1.0
|
||||||
github.com/beorn7/perks => github.com/beorn7/perks v1.0.1
|
github.com/beorn7/perks => github.com/beorn7/perks v1.0.1
|
||||||
github.com/bits-and-blooms/bitset => github.com/bits-and-blooms/bitset v1.2.0
|
|
||||||
github.com/blang/semver => github.com/blang/semver v3.5.1+incompatible
|
github.com/blang/semver => github.com/blang/semver v3.5.1+incompatible
|
||||||
github.com/blang/semver/v4 => github.com/blang/semver/v4 v4.0.0
|
github.com/blang/semver/v4 => github.com/blang/semver/v4 v4.0.0
|
||||||
github.com/boltdb/bolt => github.com/boltdb/bolt v1.3.1
|
github.com/boltdb/bolt => github.com/boltdb/bolt v1.3.1
|
||||||
@ -187,11 +186,11 @@ replace (
|
|||||||
github.com/cespare/xxhash => github.com/cespare/xxhash v1.1.0
|
github.com/cespare/xxhash => github.com/cespare/xxhash v1.1.0
|
||||||
github.com/cespare/xxhash/v2 => github.com/cespare/xxhash/v2 v2.1.2
|
github.com/cespare/xxhash/v2 => github.com/cespare/xxhash/v2 v2.1.2
|
||||||
github.com/chai2010/gettext-go => github.com/chai2010/gettext-go v0.0.0-20160711120539-c6fed771bfd5
|
github.com/chai2010/gettext-go => github.com/chai2010/gettext-go v0.0.0-20160711120539-c6fed771bfd5
|
||||||
github.com/checkpoint-restore/go-criu/v5 => github.com/checkpoint-restore/go-criu/v5 v5.0.0
|
github.com/checkpoint-restore/go-criu/v5 => github.com/checkpoint-restore/go-criu/v5 v5.3.0
|
||||||
github.com/chzyer/logex => github.com/chzyer/logex v1.1.10
|
github.com/chzyer/logex => github.com/chzyer/logex v1.1.10
|
||||||
github.com/chzyer/readline => github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e
|
github.com/chzyer/readline => github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e
|
||||||
github.com/chzyer/test => github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1
|
github.com/chzyer/test => github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1
|
||||||
github.com/cilium/ebpf => github.com/cilium/ebpf v0.6.2
|
github.com/cilium/ebpf => github.com/cilium/ebpf v0.7.0
|
||||||
github.com/clusterhq/flocker-go => github.com/clusterhq/flocker-go v0.0.0-20160920122132-2b8b7259d313
|
github.com/clusterhq/flocker-go => github.com/clusterhq/flocker-go v0.0.0-20160920122132-2b8b7259d313
|
||||||
github.com/cncf/udpa/go => github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403
|
github.com/cncf/udpa/go => github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403
|
||||||
github.com/cncf/xds/go => github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed
|
github.com/cncf/xds/go => github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed
|
||||||
@ -200,8 +199,8 @@ replace (
|
|||||||
github.com/cockroachdb/logtags => github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f
|
github.com/cockroachdb/logtags => github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f
|
||||||
github.com/container-storage-interface/spec => github.com/container-storage-interface/spec v1.5.0
|
github.com/container-storage-interface/spec => github.com/container-storage-interface/spec v1.5.0
|
||||||
github.com/containerd/cgroups => github.com/containerd/cgroups v1.0.1
|
github.com/containerd/cgroups => github.com/containerd/cgroups v1.0.1
|
||||||
github.com/containerd/console => github.com/containerd/console v1.0.2
|
github.com/containerd/console => github.com/containerd/console v1.0.3
|
||||||
github.com/containerd/containerd => github.com/containerd/containerd v1.4.11
|
github.com/containerd/containerd => github.com/containerd/containerd v1.4.12
|
||||||
github.com/containerd/continuity => github.com/containerd/continuity v0.1.0
|
github.com/containerd/continuity => github.com/containerd/continuity v0.1.0
|
||||||
github.com/containerd/fifo => github.com/containerd/fifo v1.0.0
|
github.com/containerd/fifo => github.com/containerd/fifo v1.0.0
|
||||||
github.com/containerd/go-runc => github.com/containerd/go-runc v1.0.0
|
github.com/containerd/go-runc => github.com/containerd/go-runc v1.0.0
|
||||||
@ -214,12 +213,12 @@ replace (
|
|||||||
github.com/coreos/go-systemd/v22 => github.com/coreos/go-systemd/v22 v22.3.2
|
github.com/coreos/go-systemd/v22 => github.com/coreos/go-systemd/v22 v22.3.2
|
||||||
github.com/cpuguy83/go-md2man/v2 => github.com/cpuguy83/go-md2man/v2 v2.0.1
|
github.com/cpuguy83/go-md2man/v2 => github.com/cpuguy83/go-md2man/v2 v2.0.1
|
||||||
github.com/creack/pty => github.com/creack/pty v1.1.11
|
github.com/creack/pty => github.com/creack/pty v1.1.11
|
||||||
github.com/cyphar/filepath-securejoin => github.com/cyphar/filepath-securejoin v0.2.2
|
github.com/cyphar/filepath-securejoin => github.com/cyphar/filepath-securejoin v0.2.3
|
||||||
github.com/davecgh/go-spew => github.com/davecgh/go-spew v1.1.1
|
github.com/davecgh/go-spew => github.com/davecgh/go-spew v1.1.1
|
||||||
github.com/daviddengcn/go-colortext => github.com/daviddengcn/go-colortext v0.0.0-20160507010035-511bcaf42ccd
|
github.com/daviddengcn/go-colortext => github.com/daviddengcn/go-colortext v0.0.0-20160507010035-511bcaf42ccd
|
||||||
github.com/dnaeon/go-vcr => github.com/dnaeon/go-vcr v1.0.1
|
github.com/dnaeon/go-vcr => github.com/dnaeon/go-vcr v1.0.1
|
||||||
github.com/docker/distribution => github.com/docker/distribution v2.7.1+incompatible
|
github.com/docker/distribution => github.com/docker/distribution v2.8.0+incompatible
|
||||||
github.com/docker/docker => github.com/docker/docker v20.10.7+incompatible
|
github.com/docker/docker => github.com/docker/docker v20.10.12+incompatible
|
||||||
github.com/docker/go-connections => github.com/docker/go-connections v0.4.0
|
github.com/docker/go-connections => github.com/docker/go-connections v0.4.0
|
||||||
github.com/docker/go-units => github.com/docker/go-units v0.4.0
|
github.com/docker/go-units => github.com/docker/go-units v0.4.0
|
||||||
github.com/docopt/docopt-go => github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815
|
github.com/docopt/docopt-go => github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815
|
||||||
@ -254,7 +253,7 @@ replace (
|
|||||||
github.com/go-openapi/swag => github.com/go-openapi/swag v0.19.14
|
github.com/go-openapi/swag => github.com/go-openapi/swag v0.19.14
|
||||||
github.com/go-ozzo/ozzo-validation => github.com/go-ozzo/ozzo-validation v3.5.0+incompatible
|
github.com/go-ozzo/ozzo-validation => github.com/go-ozzo/ozzo-validation v3.5.0+incompatible
|
||||||
github.com/go-stack/stack => github.com/go-stack/stack v1.8.0
|
github.com/go-stack/stack => github.com/go-stack/stack v1.8.0
|
||||||
github.com/godbus/dbus/v5 => github.com/godbus/dbus/v5 v5.0.4
|
github.com/godbus/dbus/v5 => github.com/godbus/dbus/v5 v5.0.6
|
||||||
github.com/gofrs/uuid => github.com/gofrs/uuid v4.0.0+incompatible
|
github.com/gofrs/uuid => github.com/gofrs/uuid v4.0.0+incompatible
|
||||||
github.com/gogo/protobuf => github.com/gogo/protobuf v1.3.2
|
github.com/gogo/protobuf => github.com/gogo/protobuf v1.3.2
|
||||||
github.com/golang/freetype => github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0
|
github.com/golang/freetype => github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0
|
||||||
@ -264,7 +263,7 @@ replace (
|
|||||||
github.com/golang/protobuf => github.com/golang/protobuf v1.5.2
|
github.com/golang/protobuf => github.com/golang/protobuf v1.5.2
|
||||||
github.com/golangplus/testing => github.com/golangplus/testing v0.0.0-20180327235837-af21d9c3145e
|
github.com/golangplus/testing => github.com/golangplus/testing v0.0.0-20180327235837-af21d9c3145e
|
||||||
github.com/google/btree => github.com/google/btree v1.0.1
|
github.com/google/btree => github.com/google/btree v1.0.1
|
||||||
github.com/google/cadvisor => github.com/google/cadvisor v0.43.0
|
github.com/google/cadvisor => github.com/google/cadvisor v0.44.0
|
||||||
github.com/google/cel-go => github.com/google/cel-go v0.10.1
|
github.com/google/cel-go => github.com/google/cel-go v0.10.1
|
||||||
github.com/google/cel-spec => github.com/google/cel-spec v0.6.0
|
github.com/google/cel-spec => github.com/google/cel-spec v0.6.0
|
||||||
github.com/google/gnostic => github.com/google/gnostic v0.5.7-v3refs
|
github.com/google/gnostic => github.com/google/gnostic v0.5.7-v3refs
|
||||||
@ -337,10 +336,10 @@ replace (
|
|||||||
github.com/onsi/ginkgo => github.com/onsi/ginkgo v1.14.0
|
github.com/onsi/ginkgo => github.com/onsi/ginkgo v1.14.0
|
||||||
github.com/onsi/gomega => github.com/onsi/gomega v1.10.1
|
github.com/onsi/gomega => github.com/onsi/gomega v1.10.1
|
||||||
github.com/opencontainers/go-digest => github.com/opencontainers/go-digest v1.0.0
|
github.com/opencontainers/go-digest => github.com/opencontainers/go-digest v1.0.0
|
||||||
github.com/opencontainers/image-spec => github.com/opencontainers/image-spec v1.0.1
|
github.com/opencontainers/image-spec => github.com/opencontainers/image-spec v1.0.2
|
||||||
github.com/opencontainers/runc => github.com/opencontainers/runc v1.0.3
|
github.com/opencontainers/runc => github.com/opencontainers/runc v1.1.0
|
||||||
github.com/opencontainers/runtime-spec => github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417
|
github.com/opencontainers/runtime-spec => github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417
|
||||||
github.com/opencontainers/selinux => github.com/opencontainers/selinux v1.8.2
|
github.com/opencontainers/selinux => github.com/opencontainers/selinux v1.10.0
|
||||||
github.com/opentracing/opentracing-go => github.com/opentracing/opentracing-go v1.1.0
|
github.com/opentracing/opentracing-go => github.com/opentracing/opentracing-go v1.1.0
|
||||||
github.com/peterbourgon/diskv => github.com/peterbourgon/diskv v2.0.1+incompatible
|
github.com/peterbourgon/diskv => github.com/peterbourgon/diskv v2.0.1+incompatible
|
||||||
github.com/pkg/errors => github.com/pkg/errors v0.9.1
|
github.com/pkg/errors => github.com/pkg/errors v0.9.1
|
||||||
@ -359,7 +358,7 @@ replace (
|
|||||||
github.com/rubiojr/go-vhd => github.com/rubiojr/go-vhd v0.0.0-20200706105327-02e210299021
|
github.com/rubiojr/go-vhd => github.com/rubiojr/go-vhd v0.0.0-20200706105327-02e210299021
|
||||||
github.com/russross/blackfriday => github.com/russross/blackfriday v1.5.2
|
github.com/russross/blackfriday => github.com/russross/blackfriday v1.5.2
|
||||||
github.com/russross/blackfriday/v2 => github.com/russross/blackfriday/v2 v2.1.0
|
github.com/russross/blackfriday/v2 => github.com/russross/blackfriday/v2 v2.1.0
|
||||||
github.com/seccomp/libseccomp-golang => github.com/seccomp/libseccomp-golang v0.9.1
|
github.com/seccomp/libseccomp-golang => github.com/seccomp/libseccomp-golang v0.9.2-0.20210429002308-3879420cc921
|
||||||
github.com/sergi/go-diff => github.com/sergi/go-diff v1.1.0
|
github.com/sergi/go-diff => github.com/sergi/go-diff v1.1.0
|
||||||
github.com/sirupsen/logrus => github.com/sirupsen/logrus v1.8.1
|
github.com/sirupsen/logrus => github.com/sirupsen/logrus v1.8.1
|
||||||
github.com/smartystreets/assertions => github.com/smartystreets/assertions v1.1.0
|
github.com/smartystreets/assertions => github.com/smartystreets/assertions v1.1.0
|
||||||
|
54
go.sum
54
go.sum
@ -66,8 +66,6 @@ github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLj
|
|||||||
github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
|
github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
|
||||||
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
||||||
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
||||||
github.com/bits-and-blooms/bitset v1.2.0 h1:Kn4yilvwNtMACtf1eYDlG8H77R07mZSPbMjLyS07ChA=
|
|
||||||
github.com/bits-and-blooms/bitset v1.2.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA=
|
|
||||||
github.com/blang/semver v3.5.1+incompatible h1:cQNTCjp13qL8KC3Nbxr/y2Bqb63oX6wdnnjpJbkM4JQ=
|
github.com/blang/semver v3.5.1+incompatible h1:cQNTCjp13qL8KC3Nbxr/y2Bqb63oX6wdnnjpJbkM4JQ=
|
||||||
github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
|
github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
|
||||||
github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM=
|
github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM=
|
||||||
@ -83,13 +81,13 @@ github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cb
|
|||||||
github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||||
github.com/chai2010/gettext-go v0.0.0-20160711120539-c6fed771bfd5 h1:7aWHqerlJ41y6FOsEUvknqgXnGmJyJSbjhAWq5pO4F8=
|
github.com/chai2010/gettext-go v0.0.0-20160711120539-c6fed771bfd5 h1:7aWHqerlJ41y6FOsEUvknqgXnGmJyJSbjhAWq5pO4F8=
|
||||||
github.com/chai2010/gettext-go v0.0.0-20160711120539-c6fed771bfd5/go.mod h1:/iP1qXHoty45bqomnu2LM+VVyAEdWN+vtSHGlQgyxbw=
|
github.com/chai2010/gettext-go v0.0.0-20160711120539-c6fed771bfd5/go.mod h1:/iP1qXHoty45bqomnu2LM+VVyAEdWN+vtSHGlQgyxbw=
|
||||||
github.com/checkpoint-restore/go-criu/v5 v5.0.0 h1:TW8f/UvntYoVDMN1K2HlT82qH1rb0sOjpGw3m6Ym+i4=
|
github.com/checkpoint-restore/go-criu/v5 v5.3.0 h1:wpFFOoomK3389ue2lAb0Boag6XPht5QYpipxmSNL4d8=
|
||||||
github.com/checkpoint-restore/go-criu/v5 v5.0.0/go.mod h1:cfwC0EG7HMUenopBsUf9d89JlCLQIfgVcNsNN0t6T2M=
|
github.com/checkpoint-restore/go-criu/v5 v5.3.0/go.mod h1:E/eQpaFtUKGOOSEBZgmKAcn+zUUwWxqcaKZlF54wK8E=
|
||||||
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
||||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
||||||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
||||||
github.com/cilium/ebpf v0.6.2 h1:iHsfF/t4aW4heW2YKfeHrVPGdtYTL4C4KocpM8KTSnI=
|
github.com/cilium/ebpf v0.7.0 h1:1k/q3ATgxSXRdrmPfH8d7YK0GfqVsEKZAX9dQZvs56k=
|
||||||
github.com/cilium/ebpf v0.6.2/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs=
|
github.com/cilium/ebpf v0.7.0/go.mod h1:/oI2+1shJiTGAMgl6/RgJr36Eo1jzrRcAWbcXO2usCA=
|
||||||
github.com/clusterhq/flocker-go v0.0.0-20160920122132-2b8b7259d313 h1:eIHD9GNM3Hp7kcRW5mvcz7WTR3ETeoYYKwpgA04kaXE=
|
github.com/clusterhq/flocker-go v0.0.0-20160920122132-2b8b7259d313 h1:eIHD9GNM3Hp7kcRW5mvcz7WTR3ETeoYYKwpgA04kaXE=
|
||||||
github.com/clusterhq/flocker-go v0.0.0-20160920122132-2b8b7259d313/go.mod h1:P1wt9Z3DP8O6W3rvwCt0REIlshg1InHImaLW0t3ObY0=
|
github.com/clusterhq/flocker-go v0.0.0-20160920122132-2b8b7259d313/go.mod h1:P1wt9Z3DP8O6W3rvwCt0REIlshg1InHImaLW0t3ObY0=
|
||||||
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
|
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
|
||||||
@ -104,10 +102,10 @@ github.com/container-storage-interface/spec v1.5.0 h1:lvKxe3uLgqQeVQcrnL2CPQKISo
|
|||||||
github.com/container-storage-interface/spec v1.5.0/go.mod h1:8K96oQNkJ7pFcC2R9Z1ynGGBB1I93kcS6PGg3SsOk8s=
|
github.com/container-storage-interface/spec v1.5.0/go.mod h1:8K96oQNkJ7pFcC2R9Z1ynGGBB1I93kcS6PGg3SsOk8s=
|
||||||
github.com/containerd/cgroups v1.0.1 h1:iJnMvco9XGvKUvNQkv88bE4uJXxRQH18efbKo9w5vHQ=
|
github.com/containerd/cgroups v1.0.1 h1:iJnMvco9XGvKUvNQkv88bE4uJXxRQH18efbKo9w5vHQ=
|
||||||
github.com/containerd/cgroups v1.0.1/go.mod h1:0SJrPIenamHDcZhEcJMNBB85rHcUsw4f25ZfBiPYRkU=
|
github.com/containerd/cgroups v1.0.1/go.mod h1:0SJrPIenamHDcZhEcJMNBB85rHcUsw4f25ZfBiPYRkU=
|
||||||
github.com/containerd/console v1.0.2 h1:Pi6D+aZXM+oUw1czuKgH5IJ+y0jhYcwBJfx5/Ghn9dE=
|
github.com/containerd/console v1.0.3 h1:lIr7SlA5PxZyMV30bDW0MGbiOPXwc63yRuCP0ARubLw=
|
||||||
github.com/containerd/console v1.0.2/go.mod h1:ytZPjGgY2oeTkAONYafi2kSj0aYggsf8acV1PGKCbzQ=
|
github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U=
|
||||||
github.com/containerd/containerd v1.4.11 h1:QCGOUN+i70jEEL/A6JVIbhy4f4fanzAzSR4kNG7SlcE=
|
github.com/containerd/containerd v1.4.12 h1:V+SHzYmhng/iju6M5nFrpTTusrhidoxKTwdwLw+u4c4=
|
||||||
github.com/containerd/containerd v1.4.11/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
|
github.com/containerd/containerd v1.4.12/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
|
||||||
github.com/containerd/continuity v0.1.0/go.mod h1:ICJu0PwR54nI0yPEnJ6jcS+J7CZAUXrLh8lPo2knzsM=
|
github.com/containerd/continuity v0.1.0/go.mod h1:ICJu0PwR54nI0yPEnJ6jcS+J7CZAUXrLh8lPo2knzsM=
|
||||||
github.com/containerd/fifo v1.0.0/go.mod h1:ocF/ME1SX5b1AOlWi9r677YJmCPSwwWnQ9O123vzpE4=
|
github.com/containerd/fifo v1.0.0/go.mod h1:ocF/ME1SX5b1AOlWi9r677YJmCPSwwWnQ9O123vzpE4=
|
||||||
github.com/containerd/go-runc v1.0.0/go.mod h1:cNU0ZbCgCQVZK4lgG3P+9tn9/PaJNmoDXPpoJhDR+Ok=
|
github.com/containerd/go-runc v1.0.0/go.mod h1:cNU0ZbCgCQVZK4lgG3P+9tn9/PaJNmoDXPpoJhDR+Ok=
|
||||||
@ -129,18 +127,18 @@ github.com/cpuguy83/go-md2man/v2 v2.0.1 h1:r/myEWzV9lfsM1tFLgDyu0atFtJ1fXn261LKY
|
|||||||
github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||||
github.com/creack/pty v1.1.11 h1:07n33Z8lZxZ2qwegKbObQohDhXDQxiMMz1NOUGYlesw=
|
github.com/creack/pty v1.1.11 h1:07n33Z8lZxZ2qwegKbObQohDhXDQxiMMz1NOUGYlesw=
|
||||||
github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||||
github.com/cyphar/filepath-securejoin v0.2.2 h1:jCwT2GTP+PY5nBz3c/YL5PAIbusElVrPujOBSCj8xRg=
|
github.com/cyphar/filepath-securejoin v0.2.3 h1:YX6ebbZCZP7VkM3scTTokDgBL2TY741X51MTk3ycuNI=
|
||||||
github.com/cyphar/filepath-securejoin v0.2.2/go.mod h1:FpkQEhXnPnOthhzymB7CGsFk2G9VLXONKD9G7QGMM+4=
|
github.com/cyphar/filepath-securejoin v0.2.3/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4=
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/daviddengcn/go-colortext v0.0.0-20160507010035-511bcaf42ccd h1:uVsMphB1eRx7xB1njzL3fuMdWRN8HtVzoUOItHMwv5c=
|
github.com/daviddengcn/go-colortext v0.0.0-20160507010035-511bcaf42ccd h1:uVsMphB1eRx7xB1njzL3fuMdWRN8HtVzoUOItHMwv5c=
|
||||||
github.com/daviddengcn/go-colortext v0.0.0-20160507010035-511bcaf42ccd/go.mod h1:dv4zxwHi5C/8AeI+4gX4dCWOIvNi7I6JCSX0HvlKPgE=
|
github.com/daviddengcn/go-colortext v0.0.0-20160507010035-511bcaf42ccd/go.mod h1:dv4zxwHi5C/8AeI+4gX4dCWOIvNi7I6JCSX0HvlKPgE=
|
||||||
github.com/dnaeon/go-vcr v1.0.1 h1:r8L/HqC0Hje5AXMu1ooW8oyQyOFv4GxqpL0nRP7SLLY=
|
github.com/dnaeon/go-vcr v1.0.1 h1:r8L/HqC0Hje5AXMu1ooW8oyQyOFv4GxqpL0nRP7SLLY=
|
||||||
github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E=
|
github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E=
|
||||||
github.com/docker/distribution v2.7.1+incompatible h1:a5mlkVzth6W5A4fOsS3D2EO5BUmsJpcB+cRlLU7cSug=
|
github.com/docker/distribution v2.8.0+incompatible h1:l9EaZDICImO1ngI+uTifW+ZYvvz7fKISBAKpg+MbWbY=
|
||||||
github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
github.com/docker/distribution v2.8.0+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
||||||
github.com/docker/docker v20.10.7+incompatible h1:Z6O9Nhsjv+ayUEeI1IojKbYcsGdgYSNqxe1s2MYzUhQ=
|
github.com/docker/docker v20.10.12+incompatible h1:CEeNmFM0QZIsJCZKMkZx0ZcahTiewkrgiwfYD+dfl1U=
|
||||||
github.com/docker/docker v20.10.7+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
github.com/docker/docker v20.10.12+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||||
github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ=
|
github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ=
|
||||||
github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
|
github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
|
||||||
github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw=
|
github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw=
|
||||||
@ -197,8 +195,8 @@ github.com/go-openapi/swag v0.19.14/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/
|
|||||||
github.com/go-ozzo/ozzo-validation v3.5.0+incompatible h1:sUy/in/P6askYr16XJgTKq/0SZhiWsdg4WZGaLsGQkM=
|
github.com/go-ozzo/ozzo-validation v3.5.0+incompatible h1:sUy/in/P6askYr16XJgTKq/0SZhiWsdg4WZGaLsGQkM=
|
||||||
github.com/go-ozzo/ozzo-validation v3.5.0+incompatible/go.mod h1:gsEKFIVnabGBt6mXmxK0MoFy+cZoTJY6mu5Ll3LVLBU=
|
github.com/go-ozzo/ozzo-validation v3.5.0+incompatible/go.mod h1:gsEKFIVnabGBt6mXmxK0MoFy+cZoTJY6mu5Ll3LVLBU=
|
||||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||||
github.com/godbus/dbus/v5 v5.0.4 h1:9349emZab16e7zQvpmsbtjc18ykshndd8y2PG3sgJbA=
|
github.com/godbus/dbus/v5 v5.0.6 h1:mkgN1ofwASrYnJ5W6U/BxG15eXXXjirgZc7CLqkcaro=
|
||||||
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
github.com/godbus/dbus/v5 v5.0.6/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||||
github.com/gofrs/uuid v4.0.0+incompatible h1:1SD/1F5pU8p29ybwgQSwpQk+mwdRrXCYuPhW6m+TnJw=
|
github.com/gofrs/uuid v4.0.0+incompatible h1:1SD/1F5pU8p29ybwgQSwpQk+mwdRrXCYuPhW6m+TnJw=
|
||||||
github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
|
github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
|
||||||
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
||||||
@ -215,8 +213,8 @@ github.com/golangplus/testing v0.0.0-20180327235837-af21d9c3145e h1:KhcknUwkWHKZ
|
|||||||
github.com/golangplus/testing v0.0.0-20180327235837-af21d9c3145e/go.mod h1:0AA//k/eakGydO4jKRoRL2j92ZKSzTgj9tclaCrvXHk=
|
github.com/golangplus/testing v0.0.0-20180327235837-af21d9c3145e/go.mod h1:0AA//k/eakGydO4jKRoRL2j92ZKSzTgj9tclaCrvXHk=
|
||||||
github.com/google/btree v1.0.1 h1:gK4Kx5IaGY9CD5sPJ36FHiBJ6ZXl0kilRiiCj+jdYp4=
|
github.com/google/btree v1.0.1 h1:gK4Kx5IaGY9CD5sPJ36FHiBJ6ZXl0kilRiiCj+jdYp4=
|
||||||
github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA=
|
github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA=
|
||||||
github.com/google/cadvisor v0.43.0 h1:z0ULgYPKZ7L/c7Zjq+ZD6ltklWwYdCSvBMgSjNC/hGo=
|
github.com/google/cadvisor v0.44.0 h1:523mBK94XHKAsU1TIQl/tYoPyYpWQdalf2CQ8Gv2Xek=
|
||||||
github.com/google/cadvisor v0.43.0/go.mod h1:+RdMSbc3FVr5NYCD2dOEJy/LI0jYJ/0xJXkzWXEyiFQ=
|
github.com/google/cadvisor v0.44.0/go.mod h1:GQ9KQfz0iNHQk3D6ftzJWK4TXabfIgM10Oy3FkR+Gzg=
|
||||||
github.com/google/cel-go v0.10.1 h1:MQBGSZGnDwh7T/un+mzGKOMz3x+4E/GDPprWjDL+1Jg=
|
github.com/google/cel-go v0.10.1 h1:MQBGSZGnDwh7T/un+mzGKOMz3x+4E/GDPprWjDL+1Jg=
|
||||||
github.com/google/cel-go v0.10.1/go.mod h1:U7ayypeSkw23szu4GaQTPJGx66c20mx8JklMSxrmI1w=
|
github.com/google/cel-go v0.10.1/go.mod h1:U7ayypeSkw23szu4GaQTPJGx66c20mx8JklMSxrmI1w=
|
||||||
github.com/google/cel-spec v0.6.0/go.mod h1:Nwjgxy5CbjlPrtCWjeDjUyKMl8w41YBYGjsyDdqk0xA=
|
github.com/google/cel-spec v0.6.0/go.mod h1:Nwjgxy5CbjlPrtCWjeDjUyKMl8w41YBYGjsyDdqk0xA=
|
||||||
@ -343,14 +341,14 @@ github.com/onsi/gomega v1.10.1 h1:o0+MgICZLuZ7xjH7Vx6zS/zcu93/BEp1VwkIW1mEXCE=
|
|||||||
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
|
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
|
||||||
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
|
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
|
||||||
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
|
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
|
||||||
github.com/opencontainers/image-spec v1.0.1 h1:JMemWkRwHx4Zj+fVxWoMCFm/8sYGGrUVojFA6h/TRcI=
|
github.com/opencontainers/image-spec v1.0.2 h1:9yCKha/T5XdGtO0q9Q9a6T5NUCsTn/DrBg0D7ufOcFM=
|
||||||
github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
|
github.com/opencontainers/image-spec v1.0.2/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
|
||||||
github.com/opencontainers/runc v1.0.3 h1:1hbqejyQWCJBvtKAfdO0b1FmaEf2z/bxnjqbARass5k=
|
github.com/opencontainers/runc v1.1.0 h1:O9+X96OcDjkmmZyfaG996kV7yq8HsoU2h1XRRQcefG8=
|
||||||
github.com/opencontainers/runc v1.0.3/go.mod h1:aTaHFFwQXuA71CiyxOdFFIorAoemI04suvGRQFzWTD0=
|
github.com/opencontainers/runc v1.1.0/go.mod h1:Tj1hFw6eFWp/o33uxGf5yF2BX5yz2Z6iptFpuvbbKqc=
|
||||||
github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417 h1:3snG66yBm59tKhhSPQrQ/0bCrv1LQbKt40LnUPiUxdc=
|
github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417 h1:3snG66yBm59tKhhSPQrQ/0bCrv1LQbKt40LnUPiUxdc=
|
||||||
github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
||||||
github.com/opencontainers/selinux v1.8.2 h1:c4ca10UMgRcvZ6h0K4HtS15UaVSBEaE+iln2LVpAuGc=
|
github.com/opencontainers/selinux v1.10.0 h1:rAiKF8hTcgLI3w0DHm6i0ylVVcOrlgR1kK99DRLDhyU=
|
||||||
github.com/opencontainers/selinux v1.8.2/go.mod h1:MUIHuUEvKB1wtJjQdOyYRgOnLD2xAPP8dBsCoU0KuF8=
|
github.com/opencontainers/selinux v1.10.0/go.mod h1:2i0OySw99QjzBBQByd1Gr9gSjvuho1lHsJxIJ3gGbJI=
|
||||||
github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
|
github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
|
||||||
github.com/peterbourgon/diskv v2.0.1+incompatible h1:UBdAOUP5p4RWqPBg048CAvpKN+vxiaj6gdUUzhl4XmI=
|
github.com/peterbourgon/diskv v2.0.1+incompatible h1:UBdAOUP5p4RWqPBg048CAvpKN+vxiaj6gdUUzhl4XmI=
|
||||||
github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
|
github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
|
||||||
@ -382,8 +380,8 @@ github.com/russross/blackfriday v1.5.2 h1:HyvC0ARfnZBqnXwABFeSZHpKvJHJJfPz81GNue
|
|||||||
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
|
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
|
||||||
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
|
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
|
||||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||||
github.com/seccomp/libseccomp-golang v0.9.1 h1:NJjM5DNFOs0s3kYE1WUOr6G8V97sdt46rlXTMfXGWBo=
|
github.com/seccomp/libseccomp-golang v0.9.2-0.20210429002308-3879420cc921 h1:58EBmR2dMNL2n/FnbQewK3D14nXr0V9CObDSvMJLq+Y=
|
||||||
github.com/seccomp/libseccomp-golang v0.9.1/go.mod h1:GbW5+tmTXfcxTToHLXlScSlAvWlF4P2Ca7zGrPiEpWo=
|
github.com/seccomp/libseccomp-golang v0.9.2-0.20210429002308-3879420cc921/go.mod h1:JA8cRccbGaA1s33RQf7Y1+q9gHmZX1yB/z9WDN1C6fg=
|
||||||
github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0=
|
github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0=
|
||||||
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
|
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
|
||||||
github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE=
|
github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE=
|
||||||
|
@ -9,7 +9,7 @@ require (
|
|||||||
github.com/chai2010/gettext-go v0.0.0-20160711120539-c6fed771bfd5
|
github.com/chai2010/gettext-go v0.0.0-20160711120539-c6fed771bfd5
|
||||||
github.com/davecgh/go-spew v1.1.1
|
github.com/davecgh/go-spew v1.1.1
|
||||||
github.com/daviddengcn/go-colortext v0.0.0-20160507010035-511bcaf42ccd
|
github.com/daviddengcn/go-colortext v0.0.0-20160507010035-511bcaf42ccd
|
||||||
github.com/docker/distribution v2.7.1+incompatible
|
github.com/docker/distribution v2.8.0+incompatible
|
||||||
github.com/evanphx/json-patch v4.12.0+incompatible
|
github.com/evanphx/json-patch v4.12.0+incompatible
|
||||||
github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d
|
github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d
|
||||||
github.com/fatih/camelcase v1.0.0
|
github.com/fatih/camelcase v1.0.0
|
||||||
|
4
staging/src/k8s.io/kubectl/go.sum
generated
4
staging/src/k8s.io/kubectl/go.sum
generated
@ -104,8 +104,8 @@ github.com/daviddengcn/go-colortext v0.0.0-20160507010035-511bcaf42ccd h1:uVsMph
|
|||||||
github.com/daviddengcn/go-colortext v0.0.0-20160507010035-511bcaf42ccd/go.mod h1:dv4zxwHi5C/8AeI+4gX4dCWOIvNi7I6JCSX0HvlKPgE=
|
github.com/daviddengcn/go-colortext v0.0.0-20160507010035-511bcaf42ccd/go.mod h1:dv4zxwHi5C/8AeI+4gX4dCWOIvNi7I6JCSX0HvlKPgE=
|
||||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
||||||
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
|
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
|
||||||
github.com/docker/distribution v2.7.1+incompatible h1:a5mlkVzth6W5A4fOsS3D2EO5BUmsJpcB+cRlLU7cSug=
|
github.com/docker/distribution v2.8.0+incompatible h1:l9EaZDICImO1ngI+uTifW+ZYvvz7fKISBAKpg+MbWbY=
|
||||||
github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
github.com/docker/distribution v2.8.0+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
||||||
github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE=
|
github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE=
|
||||||
github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153 h1:yUdfgN0XgIJw7foRItutHYUIhlcKzcSf5vDpdhQAKTc=
|
github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153 h1:yUdfgN0XgIJw7foRItutHYUIhlcKzcSf5vDpdhQAKTc=
|
||||||
github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc=
|
github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc=
|
||||||
|
26
vendor/github.com/bits-and-blooms/bitset/.gitignore
generated
vendored
26
vendor/github.com/bits-and-blooms/bitset/.gitignore
generated
vendored
@ -1,26 +0,0 @@
|
|||||||
# Compiled Object files, Static and Dynamic libs (Shared Objects)
|
|
||||||
*.o
|
|
||||||
*.a
|
|
||||||
*.so
|
|
||||||
|
|
||||||
# Folders
|
|
||||||
_obj
|
|
||||||
_test
|
|
||||||
|
|
||||||
# Architecture specific extensions/prefixes
|
|
||||||
*.[568vq]
|
|
||||||
[568vq].out
|
|
||||||
|
|
||||||
*.cgo1.go
|
|
||||||
*.cgo2.c
|
|
||||||
_cgo_defun.c
|
|
||||||
_cgo_gotypes.go
|
|
||||||
_cgo_export.*
|
|
||||||
|
|
||||||
_testmain.go
|
|
||||||
|
|
||||||
*.exe
|
|
||||||
*.test
|
|
||||||
*.prof
|
|
||||||
|
|
||||||
target
|
|
37
vendor/github.com/bits-and-blooms/bitset/.travis.yml
generated
vendored
37
vendor/github.com/bits-and-blooms/bitset/.travis.yml
generated
vendored
@ -1,37 +0,0 @@
|
|||||||
language: go
|
|
||||||
|
|
||||||
sudo: false
|
|
||||||
|
|
||||||
branches:
|
|
||||||
except:
|
|
||||||
- release
|
|
||||||
|
|
||||||
branches:
|
|
||||||
only:
|
|
||||||
- master
|
|
||||||
- travis
|
|
||||||
|
|
||||||
go:
|
|
||||||
- "1.11.x"
|
|
||||||
- tip
|
|
||||||
|
|
||||||
matrix:
|
|
||||||
allow_failures:
|
|
||||||
- go: tip
|
|
||||||
|
|
||||||
before_install:
|
|
||||||
- if [ -n "$GH_USER" ]; then git config --global github.user ${GH_USER}; fi;
|
|
||||||
- if [ -n "$GH_TOKEN" ]; then git config --global github.token ${GH_TOKEN}; fi;
|
|
||||||
- go get github.com/mattn/goveralls
|
|
||||||
|
|
||||||
before_script:
|
|
||||||
- make deps
|
|
||||||
|
|
||||||
script:
|
|
||||||
- make qa
|
|
||||||
|
|
||||||
after_failure:
|
|
||||||
- cat ./target/test/report.xml
|
|
||||||
|
|
||||||
after_success:
|
|
||||||
- if [ "$TRAVIS_GO_VERSION" = "1.11.1" ]; then $HOME/gopath/bin/goveralls -covermode=count -coverprofile=target/report/coverage.out -service=travis-ci; fi;
|
|
27
vendor/github.com/bits-and-blooms/bitset/LICENSE
generated
vendored
27
vendor/github.com/bits-and-blooms/bitset/LICENSE
generated
vendored
@ -1,27 +0,0 @@
|
|||||||
Copyright (c) 2014 Will Fitzgerald. All rights reserved.
|
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
|
||||||
modification, are permitted provided that the following conditions are
|
|
||||||
met:
|
|
||||||
|
|
||||||
* Redistributions of source code must retain the above copyright
|
|
||||||
notice, this list of conditions and the following disclaimer.
|
|
||||||
* Redistributions in binary form must reproduce the above
|
|
||||||
copyright notice, this list of conditions and the following disclaimer
|
|
||||||
in the documentation and/or other materials provided with the
|
|
||||||
distribution.
|
|
||||||
* Neither the name of Google Inc. nor the names of its
|
|
||||||
contributors may be used to endorse or promote products derived from
|
|
||||||
this software without specific prior written permission.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
93
vendor/github.com/bits-and-blooms/bitset/README.md
generated
vendored
93
vendor/github.com/bits-and-blooms/bitset/README.md
generated
vendored
@ -1,93 +0,0 @@
|
|||||||
# bitset
|
|
||||||
|
|
||||||
*Go language library to map between non-negative integers and boolean values*
|
|
||||||
|
|
||||||
[](https://github.com/willf/bitset/actions?query=workflow%3ATest)
|
|
||||||
[](https://goreportcard.com/report/github.com/willf/bitset)
|
|
||||||
[](https://pkg.go.dev/github.com/bits-and-blooms/bitset?tab=doc)
|
|
||||||
|
|
||||||
|
|
||||||
## Description
|
|
||||||
|
|
||||||
Package bitset implements bitsets, a mapping between non-negative integers and boolean values.
|
|
||||||
It should be more efficient than map[uint] bool.
|
|
||||||
|
|
||||||
It provides methods for setting, clearing, flipping, and testing individual integers.
|
|
||||||
|
|
||||||
But it also provides set intersection, union, difference, complement, and symmetric operations, as well as tests to check whether any, all, or no bits are set, and querying a bitset's current length and number of positive bits.
|
|
||||||
|
|
||||||
BitSets are expanded to the size of the largest set bit; the memory allocation is approximately Max bits, where Max is the largest set bit. BitSets are never shrunk. On creation, a hint can be given for the number of bits that will be used.
|
|
||||||
|
|
||||||
Many of the methods, including Set, Clear, and Flip, return a BitSet pointer, which allows for chaining.
|
|
||||||
|
|
||||||
### Example use:
|
|
||||||
|
|
||||||
```go
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"math/rand"
|
|
||||||
|
|
||||||
"github.com/bits-and-blooms/bitset"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
fmt.Printf("Hello from BitSet!\n")
|
|
||||||
var b bitset.BitSet
|
|
||||||
// play some Go Fish
|
|
||||||
for i := 0; i < 100; i++ {
|
|
||||||
card1 := uint(rand.Intn(52))
|
|
||||||
card2 := uint(rand.Intn(52))
|
|
||||||
b.Set(card1)
|
|
||||||
if b.Test(card2) {
|
|
||||||
fmt.Println("Go Fish!")
|
|
||||||
}
|
|
||||||
b.Clear(card1)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Chaining
|
|
||||||
b.Set(10).Set(11)
|
|
||||||
|
|
||||||
for i, e := b.NextSet(0); e; i, e = b.NextSet(i + 1) {
|
|
||||||
fmt.Println("The following bit is set:", i)
|
|
||||||
}
|
|
||||||
if b.Intersection(bitset.New(100).Set(10)).Count() == 1 {
|
|
||||||
fmt.Println("Intersection works.")
|
|
||||||
} else {
|
|
||||||
fmt.Println("Intersection doesn't work???")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
As an alternative to BitSets, one should check out the 'big' package, which provides a (less set-theoretical) view of bitsets.
|
|
||||||
|
|
||||||
Package documentation is at: https://pkg.go.dev/github.com/bits-and-blooms/bitset?tab=doc
|
|
||||||
|
|
||||||
## Memory Usage
|
|
||||||
|
|
||||||
The memory usage of a bitset using N bits is at least N/8 bytes. The number of bits in a bitset is at least as large as one plus the greatest bit index you have accessed. Thus it is possible to run out of memory while using a bitset. If you have lots of bits, you might prefer compressed bitsets, like the [Roaring bitmaps](http://roaringbitmap.org) and its [Go implementation](https://github.com/RoaringBitmap/roaring).
|
|
||||||
|
|
||||||
## Implementation Note
|
|
||||||
|
|
||||||
Go 1.9 introduced a native `math/bits` library. We provide backward compatibility to Go 1.7, which might be removed.
|
|
||||||
|
|
||||||
It is possible that a later version will match the `math/bits` return signature for counts (which is `int`, rather than our library's `unit64`). If so, the version will be bumped.
|
|
||||||
|
|
||||||
## Installation
|
|
||||||
|
|
||||||
```bash
|
|
||||||
go get github.com/bits-and-blooms/bitset
|
|
||||||
```
|
|
||||||
|
|
||||||
## Contributing
|
|
||||||
|
|
||||||
If you wish to contribute to this project, please branch and issue a pull request against master ("[GitHub Flow](https://guides.github.com/introduction/flow/)")
|
|
||||||
|
|
||||||
## Running all tests
|
|
||||||
|
|
||||||
Before committing the code, please check if it passes tests, has adequate coverage, etc.
|
|
||||||
```bash
|
|
||||||
go test
|
|
||||||
go test -cover
|
|
||||||
```
|
|
39
vendor/github.com/bits-and-blooms/bitset/azure-pipelines.yml
generated
vendored
39
vendor/github.com/bits-and-blooms/bitset/azure-pipelines.yml
generated
vendored
@ -1,39 +0,0 @@
|
|||||||
# Go
|
|
||||||
# Build your Go project.
|
|
||||||
# Add steps that test, save build artifacts, deploy, and more:
|
|
||||||
# https://docs.microsoft.com/azure/devops/pipelines/languages/go
|
|
||||||
|
|
||||||
trigger:
|
|
||||||
- master
|
|
||||||
|
|
||||||
pool:
|
|
||||||
vmImage: 'Ubuntu-16.04'
|
|
||||||
|
|
||||||
variables:
|
|
||||||
GOBIN: '$(GOPATH)/bin' # Go binaries path
|
|
||||||
GOROOT: '/usr/local/go1.11' # Go installation path
|
|
||||||
GOPATH: '$(system.defaultWorkingDirectory)/gopath' # Go workspace path
|
|
||||||
modulePath: '$(GOPATH)/src/github.com/$(build.repository.name)' # Path to the module's code
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- script: |
|
|
||||||
mkdir -p '$(GOBIN)'
|
|
||||||
mkdir -p '$(GOPATH)/pkg'
|
|
||||||
mkdir -p '$(modulePath)'
|
|
||||||
shopt -s extglob
|
|
||||||
shopt -s dotglob
|
|
||||||
mv !(gopath) '$(modulePath)'
|
|
||||||
echo '##vso[task.prependpath]$(GOBIN)'
|
|
||||||
echo '##vso[task.prependpath]$(GOROOT)/bin'
|
|
||||||
displayName: 'Set up the Go workspace'
|
|
||||||
|
|
||||||
- script: |
|
|
||||||
go version
|
|
||||||
go get -v -t -d ./...
|
|
||||||
if [ -f Gopkg.toml ]; then
|
|
||||||
curl https://raw.githubusercontent.com/golang/dep/master/install.sh | sh
|
|
||||||
dep ensure
|
|
||||||
fi
|
|
||||||
go build -v .
|
|
||||||
workingDirectory: '$(modulePath)'
|
|
||||||
displayName: 'Get dependencies, then build'
|
|
952
vendor/github.com/bits-and-blooms/bitset/bitset.go
generated
vendored
952
vendor/github.com/bits-and-blooms/bitset/bitset.go
generated
vendored
@ -1,952 +0,0 @@
|
|||||||
/*
|
|
||||||
Package bitset implements bitsets, a mapping
|
|
||||||
between non-negative integers and boolean values. It should be more
|
|
||||||
efficient than map[uint] bool.
|
|
||||||
|
|
||||||
It provides methods for setting, clearing, flipping, and testing
|
|
||||||
individual integers.
|
|
||||||
|
|
||||||
But it also provides set intersection, union, difference,
|
|
||||||
complement, and symmetric operations, as well as tests to
|
|
||||||
check whether any, all, or no bits are set, and querying a
|
|
||||||
bitset's current length and number of positive bits.
|
|
||||||
|
|
||||||
BitSets are expanded to the size of the largest set bit; the
|
|
||||||
memory allocation is approximately Max bits, where Max is
|
|
||||||
the largest set bit. BitSets are never shrunk. On creation,
|
|
||||||
a hint can be given for the number of bits that will be used.
|
|
||||||
|
|
||||||
Many of the methods, including Set,Clear, and Flip, return
|
|
||||||
a BitSet pointer, which allows for chaining.
|
|
||||||
|
|
||||||
Example use:
|
|
||||||
|
|
||||||
import "bitset"
|
|
||||||
var b BitSet
|
|
||||||
b.Set(10).Set(11)
|
|
||||||
if b.Test(1000) {
|
|
||||||
b.Clear(1000)
|
|
||||||
}
|
|
||||||
if B.Intersection(bitset.New(100).Set(10)).Count() > 1 {
|
|
||||||
fmt.Println("Intersection works.")
|
|
||||||
}
|
|
||||||
|
|
||||||
As an alternative to BitSets, one should check out the 'big' package,
|
|
||||||
which provides a (less set-theoretical) view of bitsets.
|
|
||||||
|
|
||||||
*/
|
|
||||||
package bitset
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bufio"
|
|
||||||
"bytes"
|
|
||||||
"encoding/base64"
|
|
||||||
"encoding/binary"
|
|
||||||
"encoding/json"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"strconv"
|
|
||||||
)
|
|
||||||
|
|
||||||
// the wordSize of a bit set
|
|
||||||
const wordSize = uint(64)
|
|
||||||
|
|
||||||
// log2WordSize is lg(wordSize)
|
|
||||||
const log2WordSize = uint(6)
|
|
||||||
|
|
||||||
// allBits has every bit set
|
|
||||||
const allBits uint64 = 0xffffffffffffffff
|
|
||||||
|
|
||||||
// default binary BigEndian
|
|
||||||
var binaryOrder binary.ByteOrder = binary.BigEndian
|
|
||||||
|
|
||||||
// default json encoding base64.URLEncoding
|
|
||||||
var base64Encoding = base64.URLEncoding
|
|
||||||
|
|
||||||
// Base64StdEncoding Marshal/Unmarshal BitSet with base64.StdEncoding(Default: base64.URLEncoding)
|
|
||||||
func Base64StdEncoding() { base64Encoding = base64.StdEncoding }
|
|
||||||
|
|
||||||
// LittleEndian Marshal/Unmarshal Binary as Little Endian(Default: binary.BigEndian)
|
|
||||||
func LittleEndian() { binaryOrder = binary.LittleEndian }
|
|
||||||
|
|
||||||
// A BitSet is a set of bits. The zero value of a BitSet is an empty set of length 0.
|
|
||||||
type BitSet struct {
|
|
||||||
length uint
|
|
||||||
set []uint64
|
|
||||||
}
|
|
||||||
|
|
||||||
// Error is used to distinguish errors (panics) generated in this package.
|
|
||||||
type Error string
|
|
||||||
|
|
||||||
// safeSet will fixup b.set to be non-nil and return the field value
|
|
||||||
func (b *BitSet) safeSet() []uint64 {
|
|
||||||
if b.set == nil {
|
|
||||||
b.set = make([]uint64, wordsNeeded(0))
|
|
||||||
}
|
|
||||||
return b.set
|
|
||||||
}
|
|
||||||
|
|
||||||
// From is a constructor used to create a BitSet from an array of integers
|
|
||||||
func From(buf []uint64) *BitSet {
|
|
||||||
return &BitSet{uint(len(buf)) * 64, buf}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Bytes returns the bitset as array of integers
|
|
||||||
func (b *BitSet) Bytes() []uint64 {
|
|
||||||
return b.set
|
|
||||||
}
|
|
||||||
|
|
||||||
// wordsNeeded calculates the number of words needed for i bits
|
|
||||||
func wordsNeeded(i uint) int {
|
|
||||||
if i > (Cap() - wordSize + 1) {
|
|
||||||
return int(Cap() >> log2WordSize)
|
|
||||||
}
|
|
||||||
return int((i + (wordSize - 1)) >> log2WordSize)
|
|
||||||
}
|
|
||||||
|
|
||||||
// New creates a new BitSet with a hint that length bits will be required
|
|
||||||
func New(length uint) (bset *BitSet) {
|
|
||||||
defer func() {
|
|
||||||
if r := recover(); r != nil {
|
|
||||||
bset = &BitSet{
|
|
||||||
0,
|
|
||||||
make([]uint64, 0),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
bset = &BitSet{
|
|
||||||
length,
|
|
||||||
make([]uint64, wordsNeeded(length)),
|
|
||||||
}
|
|
||||||
|
|
||||||
return bset
|
|
||||||
}
|
|
||||||
|
|
||||||
// Cap returns the total possible capacity, or number of bits
|
|
||||||
func Cap() uint {
|
|
||||||
return ^uint(0)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Len returns the number of bits in the BitSet.
|
|
||||||
// Note the difference to method Count, see example.
|
|
||||||
func (b *BitSet) Len() uint {
|
|
||||||
return b.length
|
|
||||||
}
|
|
||||||
|
|
||||||
// extendSetMaybe adds additional words to incorporate new bits if needed
|
|
||||||
func (b *BitSet) extendSetMaybe(i uint) {
|
|
||||||
if i >= b.length { // if we need more bits, make 'em
|
|
||||||
if i >= Cap() {
|
|
||||||
panic("You are exceeding the capacity")
|
|
||||||
}
|
|
||||||
nsize := wordsNeeded(i + 1)
|
|
||||||
if b.set == nil {
|
|
||||||
b.set = make([]uint64, nsize)
|
|
||||||
} else if cap(b.set) >= nsize {
|
|
||||||
b.set = b.set[:nsize] // fast resize
|
|
||||||
} else if len(b.set) < nsize {
|
|
||||||
newset := make([]uint64, nsize, 2*nsize) // increase capacity 2x
|
|
||||||
copy(newset, b.set)
|
|
||||||
b.set = newset
|
|
||||||
}
|
|
||||||
b.length = i + 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test whether bit i is set.
|
|
||||||
func (b *BitSet) Test(i uint) bool {
|
|
||||||
if i >= b.length {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return b.set[i>>log2WordSize]&(1<<(i&(wordSize-1))) != 0
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set bit i to 1, the capacity of the bitset is automatically
|
|
||||||
// increased accordingly.
|
|
||||||
// If i>= Cap(), this function will panic.
|
|
||||||
// Warning: using a very large value for 'i'
|
|
||||||
// may lead to a memory shortage and a panic: the caller is responsible
|
|
||||||
// for providing sensible parameters in line with their memory capacity.
|
|
||||||
func (b *BitSet) Set(i uint) *BitSet {
|
|
||||||
b.extendSetMaybe(i)
|
|
||||||
b.set[i>>log2WordSize] |= 1 << (i & (wordSize - 1))
|
|
||||||
return b
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clear bit i to 0
|
|
||||||
func (b *BitSet) Clear(i uint) *BitSet {
|
|
||||||
if i >= b.length {
|
|
||||||
return b
|
|
||||||
}
|
|
||||||
b.set[i>>log2WordSize] &^= 1 << (i & (wordSize - 1))
|
|
||||||
return b
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetTo sets bit i to value.
|
|
||||||
// If i>= Cap(), this function will panic.
|
|
||||||
// Warning: using a very large value for 'i'
|
|
||||||
// may lead to a memory shortage and a panic: the caller is responsible
|
|
||||||
// for providing sensible parameters in line with their memory capacity.
|
|
||||||
func (b *BitSet) SetTo(i uint, value bool) *BitSet {
|
|
||||||
if value {
|
|
||||||
return b.Set(i)
|
|
||||||
}
|
|
||||||
return b.Clear(i)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Flip bit at i.
|
|
||||||
// If i>= Cap(), this function will panic.
|
|
||||||
// Warning: using a very large value for 'i'
|
|
||||||
// may lead to a memory shortage and a panic: the caller is responsible
|
|
||||||
// for providing sensible parameters in line with their memory capacity.
|
|
||||||
func (b *BitSet) Flip(i uint) *BitSet {
|
|
||||||
if i >= b.length {
|
|
||||||
return b.Set(i)
|
|
||||||
}
|
|
||||||
b.set[i>>log2WordSize] ^= 1 << (i & (wordSize - 1))
|
|
||||||
return b
|
|
||||||
}
|
|
||||||
|
|
||||||
// FlipRange bit in [start, end).
|
|
||||||
// If end>= Cap(), this function will panic.
|
|
||||||
// Warning: using a very large value for 'end'
|
|
||||||
// may lead to a memory shortage and a panic: the caller is responsible
|
|
||||||
// for providing sensible parameters in line with their memory capacity.
|
|
||||||
func (b *BitSet) FlipRange(start, end uint) *BitSet {
|
|
||||||
if start >= end {
|
|
||||||
return b
|
|
||||||
}
|
|
||||||
|
|
||||||
b.extendSetMaybe(end - 1)
|
|
||||||
var startWord uint = start >> log2WordSize
|
|
||||||
var endWord uint = end >> log2WordSize
|
|
||||||
b.set[startWord] ^= ^(^uint64(0) << (start & (wordSize - 1)))
|
|
||||||
for i := startWord; i < endWord; i++ {
|
|
||||||
b.set[i] = ^b.set[i]
|
|
||||||
}
|
|
||||||
b.set[endWord] ^= ^uint64(0) >> (-end & (wordSize - 1))
|
|
||||||
return b
|
|
||||||
}
|
|
||||||
|
|
||||||
// Shrink shrinks BitSet so that the provided value is the last possible
|
|
||||||
// set value. It clears all bits > the provided index and reduces the size
|
|
||||||
// and length of the set.
|
|
||||||
//
|
|
||||||
// Note that the parameter value is not the new length in bits: it is the
|
|
||||||
// maximal value that can be stored in the bitset after the function call.
|
|
||||||
// The new length in bits is the parameter value + 1. Thus it is not possible
|
|
||||||
// to use this function to set the length to 0, the minimal value of the length
|
|
||||||
// after this function call is 1.
|
|
||||||
//
|
|
||||||
// A new slice is allocated to store the new bits, so you may see an increase in
|
|
||||||
// memory usage until the GC runs. Normally this should not be a problem, but if you
|
|
||||||
// have an extremely large BitSet its important to understand that the old BitSet will
|
|
||||||
// remain in memory until the GC frees it.
|
|
||||||
func (b *BitSet) Shrink(lastbitindex uint) *BitSet {
|
|
||||||
length := lastbitindex + 1
|
|
||||||
idx := wordsNeeded(length)
|
|
||||||
if idx > len(b.set) {
|
|
||||||
return b
|
|
||||||
}
|
|
||||||
shrunk := make([]uint64, idx)
|
|
||||||
copy(shrunk, b.set[:idx])
|
|
||||||
b.set = shrunk
|
|
||||||
b.length = length
|
|
||||||
b.set[idx-1] &= (allBits >> (uint64(64) - uint64(length&(wordSize-1))))
|
|
||||||
return b
|
|
||||||
}
|
|
||||||
|
|
||||||
// Compact shrinks BitSet to so that we preserve all set bits, while minimizing
|
|
||||||
// memory usage. Compact calls Shrink.
|
|
||||||
func (b *BitSet) Compact() *BitSet {
|
|
||||||
idx := len(b.set) - 1
|
|
||||||
for ; idx >= 0 && b.set[idx] == 0; idx-- {
|
|
||||||
}
|
|
||||||
newlength := uint((idx + 1) << log2WordSize)
|
|
||||||
if newlength >= b.length {
|
|
||||||
return b // nothing to do
|
|
||||||
}
|
|
||||||
if newlength > 0 {
|
|
||||||
return b.Shrink(newlength - 1)
|
|
||||||
}
|
|
||||||
// We preserve one word
|
|
||||||
return b.Shrink(63)
|
|
||||||
}
|
|
||||||
|
|
||||||
// InsertAt takes an index which indicates where a bit should be
|
|
||||||
// inserted. Then it shifts all the bits in the set to the left by 1, starting
|
|
||||||
// from the given index position, and sets the index position to 0.
|
|
||||||
//
|
|
||||||
// Depending on the size of your BitSet, and where you are inserting the new entry,
|
|
||||||
// this method could be extremely slow and in some cases might cause the entire BitSet
|
|
||||||
// to be recopied.
|
|
||||||
func (b *BitSet) InsertAt(idx uint) *BitSet {
|
|
||||||
insertAtElement := (idx >> log2WordSize)
|
|
||||||
|
|
||||||
// if length of set is a multiple of wordSize we need to allocate more space first
|
|
||||||
if b.isLenExactMultiple() {
|
|
||||||
b.set = append(b.set, uint64(0))
|
|
||||||
}
|
|
||||||
|
|
||||||
var i uint
|
|
||||||
for i = uint(len(b.set) - 1); i > insertAtElement; i-- {
|
|
||||||
// all elements above the position where we want to insert can simply by shifted
|
|
||||||
b.set[i] <<= 1
|
|
||||||
|
|
||||||
// we take the most significant bit of the previous element and set it as
|
|
||||||
// the least significant bit of the current element
|
|
||||||
b.set[i] |= (b.set[i-1] & 0x8000000000000000) >> 63
|
|
||||||
}
|
|
||||||
|
|
||||||
// generate a mask to extract the data that we need to shift left
|
|
||||||
// within the element where we insert a bit
|
|
||||||
dataMask := ^(uint64(1)<<uint64(idx&(wordSize-1)) - 1)
|
|
||||||
|
|
||||||
// extract that data that we'll shift
|
|
||||||
data := b.set[i] & dataMask
|
|
||||||
|
|
||||||
// set the positions of the data mask to 0 in the element where we insert
|
|
||||||
b.set[i] &= ^dataMask
|
|
||||||
|
|
||||||
// shift data mask to the left and insert its data to the slice element
|
|
||||||
b.set[i] |= data << 1
|
|
||||||
|
|
||||||
// add 1 to length of BitSet
|
|
||||||
b.length++
|
|
||||||
|
|
||||||
return b
|
|
||||||
}
|
|
||||||
|
|
||||||
// String creates a string representation of the Bitmap
|
|
||||||
func (b *BitSet) String() string {
|
|
||||||
// follows code from https://github.com/RoaringBitmap/roaring
|
|
||||||
var buffer bytes.Buffer
|
|
||||||
start := []byte("{")
|
|
||||||
buffer.Write(start)
|
|
||||||
counter := 0
|
|
||||||
i, e := b.NextSet(0)
|
|
||||||
for e {
|
|
||||||
counter = counter + 1
|
|
||||||
// to avoid exhausting the memory
|
|
||||||
if counter > 0x40000 {
|
|
||||||
buffer.WriteString("...")
|
|
||||||
break
|
|
||||||
}
|
|
||||||
buffer.WriteString(strconv.FormatInt(int64(i), 10))
|
|
||||||
i, e = b.NextSet(i + 1)
|
|
||||||
if e {
|
|
||||||
buffer.WriteString(",")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
buffer.WriteString("}")
|
|
||||||
return buffer.String()
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeleteAt deletes the bit at the given index position from
|
|
||||||
// within the bitset
|
|
||||||
// All the bits residing on the left of the deleted bit get
|
|
||||||
// shifted right by 1
|
|
||||||
// The running time of this operation may potentially be
|
|
||||||
// relatively slow, O(length)
|
|
||||||
func (b *BitSet) DeleteAt(i uint) *BitSet {
|
|
||||||
// the index of the slice element where we'll delete a bit
|
|
||||||
deleteAtElement := i >> log2WordSize
|
|
||||||
|
|
||||||
// generate a mask for the data that needs to be shifted right
|
|
||||||
// within that slice element that gets modified
|
|
||||||
dataMask := ^((uint64(1) << (i & (wordSize - 1))) - 1)
|
|
||||||
|
|
||||||
// extract the data that we'll shift right from the slice element
|
|
||||||
data := b.set[deleteAtElement] & dataMask
|
|
||||||
|
|
||||||
// set the masked area to 0 while leaving the rest as it is
|
|
||||||
b.set[deleteAtElement] &= ^dataMask
|
|
||||||
|
|
||||||
// shift the previously extracted data to the right and then
|
|
||||||
// set it in the previously masked area
|
|
||||||
b.set[deleteAtElement] |= (data >> 1) & dataMask
|
|
||||||
|
|
||||||
// loop over all the consecutive slice elements to copy each
|
|
||||||
// lowest bit into the highest position of the previous element,
|
|
||||||
// then shift the entire content to the right by 1
|
|
||||||
for i := int(deleteAtElement) + 1; i < len(b.set); i++ {
|
|
||||||
b.set[i-1] |= (b.set[i] & 1) << 63
|
|
||||||
b.set[i] >>= 1
|
|
||||||
}
|
|
||||||
|
|
||||||
b.length = b.length - 1
|
|
||||||
|
|
||||||
return b
|
|
||||||
}
|
|
||||||
|
|
||||||
// NextSet returns the next bit set from the specified index,
|
|
||||||
// including possibly the current index
|
|
||||||
// along with an error code (true = valid, false = no set bit found)
|
|
||||||
// for i,e := v.NextSet(0); e; i,e = v.NextSet(i + 1) {...}
|
|
||||||
//
|
|
||||||
// Users concerned with performance may want to use NextSetMany to
|
|
||||||
// retrieve several values at once.
|
|
||||||
func (b *BitSet) NextSet(i uint) (uint, bool) {
|
|
||||||
x := int(i >> log2WordSize)
|
|
||||||
if x >= len(b.set) {
|
|
||||||
return 0, false
|
|
||||||
}
|
|
||||||
w := b.set[x]
|
|
||||||
w = w >> (i & (wordSize - 1))
|
|
||||||
if w != 0 {
|
|
||||||
return i + trailingZeroes64(w), true
|
|
||||||
}
|
|
||||||
x = x + 1
|
|
||||||
for x < len(b.set) {
|
|
||||||
if b.set[x] != 0 {
|
|
||||||
return uint(x)*wordSize + trailingZeroes64(b.set[x]), true
|
|
||||||
}
|
|
||||||
x = x + 1
|
|
||||||
|
|
||||||
}
|
|
||||||
return 0, false
|
|
||||||
}
|
|
||||||
|
|
||||||
// NextSetMany returns many next bit sets from the specified index,
|
|
||||||
// including possibly the current index and up to cap(buffer).
|
|
||||||
// If the returned slice has len zero, then no more set bits were found
|
|
||||||
//
|
|
||||||
// buffer := make([]uint, 256) // this should be reused
|
|
||||||
// j := uint(0)
|
|
||||||
// j, buffer = bitmap.NextSetMany(j, buffer)
|
|
||||||
// for ; len(buffer) > 0; j, buffer = bitmap.NextSetMany(j,buffer) {
|
|
||||||
// for k := range buffer {
|
|
||||||
// do something with buffer[k]
|
|
||||||
// }
|
|
||||||
// j += 1
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// It is possible to retrieve all set bits as follow:
|
|
||||||
//
|
|
||||||
// indices := make([]uint, bitmap.Count())
|
|
||||||
// bitmap.NextSetMany(0, indices)
|
|
||||||
//
|
|
||||||
// However if bitmap.Count() is large, it might be preferable to
|
|
||||||
// use several calls to NextSetMany, for performance reasons.
|
|
||||||
func (b *BitSet) NextSetMany(i uint, buffer []uint) (uint, []uint) {
|
|
||||||
myanswer := buffer
|
|
||||||
capacity := cap(buffer)
|
|
||||||
x := int(i >> log2WordSize)
|
|
||||||
if x >= len(b.set) || capacity == 0 {
|
|
||||||
return 0, myanswer[:0]
|
|
||||||
}
|
|
||||||
skip := i & (wordSize - 1)
|
|
||||||
word := b.set[x] >> skip
|
|
||||||
myanswer = myanswer[:capacity]
|
|
||||||
size := int(0)
|
|
||||||
for word != 0 {
|
|
||||||
r := trailingZeroes64(word)
|
|
||||||
t := word & ((^word) + 1)
|
|
||||||
myanswer[size] = r + i
|
|
||||||
size++
|
|
||||||
if size == capacity {
|
|
||||||
goto End
|
|
||||||
}
|
|
||||||
word = word ^ t
|
|
||||||
}
|
|
||||||
x++
|
|
||||||
for idx, word := range b.set[x:] {
|
|
||||||
for word != 0 {
|
|
||||||
r := trailingZeroes64(word)
|
|
||||||
t := word & ((^word) + 1)
|
|
||||||
myanswer[size] = r + (uint(x+idx) << 6)
|
|
||||||
size++
|
|
||||||
if size == capacity {
|
|
||||||
goto End
|
|
||||||
}
|
|
||||||
word = word ^ t
|
|
||||||
}
|
|
||||||
}
|
|
||||||
End:
|
|
||||||
if size > 0 {
|
|
||||||
return myanswer[size-1], myanswer[:size]
|
|
||||||
}
|
|
||||||
return 0, myanswer[:0]
|
|
||||||
}
|
|
||||||
|
|
||||||
// NextClear returns the next clear bit from the specified index,
|
|
||||||
// including possibly the current index
|
|
||||||
// along with an error code (true = valid, false = no bit found i.e. all bits are set)
|
|
||||||
func (b *BitSet) NextClear(i uint) (uint, bool) {
|
|
||||||
x := int(i >> log2WordSize)
|
|
||||||
if x >= len(b.set) {
|
|
||||||
return 0, false
|
|
||||||
}
|
|
||||||
w := b.set[x]
|
|
||||||
w = w >> (i & (wordSize - 1))
|
|
||||||
wA := allBits >> (i & (wordSize - 1))
|
|
||||||
index := i + trailingZeroes64(^w)
|
|
||||||
if w != wA && index < b.length {
|
|
||||||
return index, true
|
|
||||||
}
|
|
||||||
x++
|
|
||||||
for x < len(b.set) {
|
|
||||||
index = uint(x)*wordSize + trailingZeroes64(^b.set[x])
|
|
||||||
if b.set[x] != allBits && index < b.length {
|
|
||||||
return index, true
|
|
||||||
}
|
|
||||||
x++
|
|
||||||
}
|
|
||||||
return 0, false
|
|
||||||
}
|
|
||||||
|
|
||||||
// ClearAll clears the entire BitSet
|
|
||||||
func (b *BitSet) ClearAll() *BitSet {
|
|
||||||
if b != nil && b.set != nil {
|
|
||||||
for i := range b.set {
|
|
||||||
b.set[i] = 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return b
|
|
||||||
}
|
|
||||||
|
|
||||||
// wordCount returns the number of words used in a bit set
|
|
||||||
func (b *BitSet) wordCount() int {
|
|
||||||
return len(b.set)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clone this BitSet
|
|
||||||
func (b *BitSet) Clone() *BitSet {
|
|
||||||
c := New(b.length)
|
|
||||||
if b.set != nil { // Clone should not modify current object
|
|
||||||
copy(c.set, b.set)
|
|
||||||
}
|
|
||||||
return c
|
|
||||||
}
|
|
||||||
|
|
||||||
// Copy into a destination BitSet
|
|
||||||
// Returning the size of the destination BitSet
|
|
||||||
// like array copy
|
|
||||||
func (b *BitSet) Copy(c *BitSet) (count uint) {
|
|
||||||
if c == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if b.set != nil { // Copy should not modify current object
|
|
||||||
copy(c.set, b.set)
|
|
||||||
}
|
|
||||||
count = c.length
|
|
||||||
if b.length < c.length {
|
|
||||||
count = b.length
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Count (number of set bits).
|
|
||||||
// Also known as "popcount" or "population count".
|
|
||||||
func (b *BitSet) Count() uint {
|
|
||||||
if b != nil && b.set != nil {
|
|
||||||
return uint(popcntSlice(b.set))
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
// Equal tests the equivalence of two BitSets.
|
|
||||||
// False if they are of different sizes, otherwise true
|
|
||||||
// only if all the same bits are set
|
|
||||||
func (b *BitSet) Equal(c *BitSet) bool {
|
|
||||||
if c == nil || b == nil {
|
|
||||||
return c == b
|
|
||||||
}
|
|
||||||
if b.length != c.length {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if b.length == 0 { // if they have both length == 0, then could have nil set
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
// testing for equality shoud not transform the bitset (no call to safeSet)
|
|
||||||
|
|
||||||
for p, v := range b.set {
|
|
||||||
if c.set[p] != v {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
func panicIfNull(b *BitSet) {
|
|
||||||
if b == nil {
|
|
||||||
panic(Error("BitSet must not be null"))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Difference of base set and other set
|
|
||||||
// This is the BitSet equivalent of &^ (and not)
|
|
||||||
func (b *BitSet) Difference(compare *BitSet) (result *BitSet) {
|
|
||||||
panicIfNull(b)
|
|
||||||
panicIfNull(compare)
|
|
||||||
result = b.Clone() // clone b (in case b is bigger than compare)
|
|
||||||
l := int(compare.wordCount())
|
|
||||||
if l > int(b.wordCount()) {
|
|
||||||
l = int(b.wordCount())
|
|
||||||
}
|
|
||||||
for i := 0; i < l; i++ {
|
|
||||||
result.set[i] = b.set[i] &^ compare.set[i]
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// DifferenceCardinality computes the cardinality of the differnce
|
|
||||||
func (b *BitSet) DifferenceCardinality(compare *BitSet) uint {
|
|
||||||
panicIfNull(b)
|
|
||||||
panicIfNull(compare)
|
|
||||||
l := int(compare.wordCount())
|
|
||||||
if l > int(b.wordCount()) {
|
|
||||||
l = int(b.wordCount())
|
|
||||||
}
|
|
||||||
cnt := uint64(0)
|
|
||||||
cnt += popcntMaskSlice(b.set[:l], compare.set[:l])
|
|
||||||
cnt += popcntSlice(b.set[l:])
|
|
||||||
return uint(cnt)
|
|
||||||
}
|
|
||||||
|
|
||||||
// InPlaceDifference computes the difference of base set and other set
|
|
||||||
// This is the BitSet equivalent of &^ (and not)
|
|
||||||
func (b *BitSet) InPlaceDifference(compare *BitSet) {
|
|
||||||
panicIfNull(b)
|
|
||||||
panicIfNull(compare)
|
|
||||||
l := int(compare.wordCount())
|
|
||||||
if l > int(b.wordCount()) {
|
|
||||||
l = int(b.wordCount())
|
|
||||||
}
|
|
||||||
for i := 0; i < l; i++ {
|
|
||||||
b.set[i] &^= compare.set[i]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Convenience function: return two bitsets ordered by
|
|
||||||
// increasing length. Note: neither can be nil
|
|
||||||
func sortByLength(a *BitSet, b *BitSet) (ap *BitSet, bp *BitSet) {
|
|
||||||
if a.length <= b.length {
|
|
||||||
ap, bp = a, b
|
|
||||||
} else {
|
|
||||||
ap, bp = b, a
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Intersection of base set and other set
|
|
||||||
// This is the BitSet equivalent of & (and)
|
|
||||||
func (b *BitSet) Intersection(compare *BitSet) (result *BitSet) {
|
|
||||||
panicIfNull(b)
|
|
||||||
panicIfNull(compare)
|
|
||||||
b, compare = sortByLength(b, compare)
|
|
||||||
result = New(b.length)
|
|
||||||
for i, word := range b.set {
|
|
||||||
result.set[i] = word & compare.set[i]
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// IntersectionCardinality computes the cardinality of the union
|
|
||||||
func (b *BitSet) IntersectionCardinality(compare *BitSet) uint {
|
|
||||||
panicIfNull(b)
|
|
||||||
panicIfNull(compare)
|
|
||||||
b, compare = sortByLength(b, compare)
|
|
||||||
cnt := popcntAndSlice(b.set, compare.set)
|
|
||||||
return uint(cnt)
|
|
||||||
}
|
|
||||||
|
|
||||||
// InPlaceIntersection destructively computes the intersection of
|
|
||||||
// base set and the compare set.
|
|
||||||
// This is the BitSet equivalent of & (and)
|
|
||||||
func (b *BitSet) InPlaceIntersection(compare *BitSet) {
|
|
||||||
panicIfNull(b)
|
|
||||||
panicIfNull(compare)
|
|
||||||
l := int(compare.wordCount())
|
|
||||||
if l > int(b.wordCount()) {
|
|
||||||
l = int(b.wordCount())
|
|
||||||
}
|
|
||||||
for i := 0; i < l; i++ {
|
|
||||||
b.set[i] &= compare.set[i]
|
|
||||||
}
|
|
||||||
for i := l; i < len(b.set); i++ {
|
|
||||||
b.set[i] = 0
|
|
||||||
}
|
|
||||||
if compare.length > 0 {
|
|
||||||
b.extendSetMaybe(compare.length - 1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Union of base set and other set
|
|
||||||
// This is the BitSet equivalent of | (or)
|
|
||||||
func (b *BitSet) Union(compare *BitSet) (result *BitSet) {
|
|
||||||
panicIfNull(b)
|
|
||||||
panicIfNull(compare)
|
|
||||||
b, compare = sortByLength(b, compare)
|
|
||||||
result = compare.Clone()
|
|
||||||
for i, word := range b.set {
|
|
||||||
result.set[i] = word | compare.set[i]
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// UnionCardinality computes the cardinality of the uniton of the base set
|
|
||||||
// and the compare set.
|
|
||||||
func (b *BitSet) UnionCardinality(compare *BitSet) uint {
|
|
||||||
panicIfNull(b)
|
|
||||||
panicIfNull(compare)
|
|
||||||
b, compare = sortByLength(b, compare)
|
|
||||||
cnt := popcntOrSlice(b.set, compare.set)
|
|
||||||
if len(compare.set) > len(b.set) {
|
|
||||||
cnt += popcntSlice(compare.set[len(b.set):])
|
|
||||||
}
|
|
||||||
return uint(cnt)
|
|
||||||
}
|
|
||||||
|
|
||||||
// InPlaceUnion creates the destructive union of base set and compare set.
|
|
||||||
// This is the BitSet equivalent of | (or).
|
|
||||||
func (b *BitSet) InPlaceUnion(compare *BitSet) {
|
|
||||||
panicIfNull(b)
|
|
||||||
panicIfNull(compare)
|
|
||||||
l := int(compare.wordCount())
|
|
||||||
if l > int(b.wordCount()) {
|
|
||||||
l = int(b.wordCount())
|
|
||||||
}
|
|
||||||
if compare.length > 0 {
|
|
||||||
b.extendSetMaybe(compare.length - 1)
|
|
||||||
}
|
|
||||||
for i := 0; i < l; i++ {
|
|
||||||
b.set[i] |= compare.set[i]
|
|
||||||
}
|
|
||||||
if len(compare.set) > l {
|
|
||||||
for i := l; i < len(compare.set); i++ {
|
|
||||||
b.set[i] = compare.set[i]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// SymmetricDifference of base set and other set
|
|
||||||
// This is the BitSet equivalent of ^ (xor)
|
|
||||||
func (b *BitSet) SymmetricDifference(compare *BitSet) (result *BitSet) {
|
|
||||||
panicIfNull(b)
|
|
||||||
panicIfNull(compare)
|
|
||||||
b, compare = sortByLength(b, compare)
|
|
||||||
// compare is bigger, so clone it
|
|
||||||
result = compare.Clone()
|
|
||||||
for i, word := range b.set {
|
|
||||||
result.set[i] = word ^ compare.set[i]
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// SymmetricDifferenceCardinality computes the cardinality of the symmetric difference
|
|
||||||
func (b *BitSet) SymmetricDifferenceCardinality(compare *BitSet) uint {
|
|
||||||
panicIfNull(b)
|
|
||||||
panicIfNull(compare)
|
|
||||||
b, compare = sortByLength(b, compare)
|
|
||||||
cnt := popcntXorSlice(b.set, compare.set)
|
|
||||||
if len(compare.set) > len(b.set) {
|
|
||||||
cnt += popcntSlice(compare.set[len(b.set):])
|
|
||||||
}
|
|
||||||
return uint(cnt)
|
|
||||||
}
|
|
||||||
|
|
||||||
// InPlaceSymmetricDifference creates the destructive SymmetricDifference of base set and other set
|
|
||||||
// This is the BitSet equivalent of ^ (xor)
|
|
||||||
func (b *BitSet) InPlaceSymmetricDifference(compare *BitSet) {
|
|
||||||
panicIfNull(b)
|
|
||||||
panicIfNull(compare)
|
|
||||||
l := int(compare.wordCount())
|
|
||||||
if l > int(b.wordCount()) {
|
|
||||||
l = int(b.wordCount())
|
|
||||||
}
|
|
||||||
if compare.length > 0 {
|
|
||||||
b.extendSetMaybe(compare.length - 1)
|
|
||||||
}
|
|
||||||
for i := 0; i < l; i++ {
|
|
||||||
b.set[i] ^= compare.set[i]
|
|
||||||
}
|
|
||||||
if len(compare.set) > l {
|
|
||||||
for i := l; i < len(compare.set); i++ {
|
|
||||||
b.set[i] = compare.set[i]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Is the length an exact multiple of word sizes?
|
|
||||||
func (b *BitSet) isLenExactMultiple() bool {
|
|
||||||
return b.length%wordSize == 0
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clean last word by setting unused bits to 0
|
|
||||||
func (b *BitSet) cleanLastWord() {
|
|
||||||
if !b.isLenExactMultiple() {
|
|
||||||
b.set[len(b.set)-1] &= allBits >> (wordSize - b.length%wordSize)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Complement computes the (local) complement of a biset (up to length bits)
|
|
||||||
func (b *BitSet) Complement() (result *BitSet) {
|
|
||||||
panicIfNull(b)
|
|
||||||
result = New(b.length)
|
|
||||||
for i, word := range b.set {
|
|
||||||
result.set[i] = ^word
|
|
||||||
}
|
|
||||||
result.cleanLastWord()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// All returns true if all bits are set, false otherwise. Returns true for
|
|
||||||
// empty sets.
|
|
||||||
func (b *BitSet) All() bool {
|
|
||||||
panicIfNull(b)
|
|
||||||
return b.Count() == b.length
|
|
||||||
}
|
|
||||||
|
|
||||||
// None returns true if no bit is set, false otherwise. Returns true for
|
|
||||||
// empty sets.
|
|
||||||
func (b *BitSet) None() bool {
|
|
||||||
panicIfNull(b)
|
|
||||||
if b != nil && b.set != nil {
|
|
||||||
for _, word := range b.set {
|
|
||||||
if word > 0 {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// Any returns true if any bit is set, false otherwise
|
|
||||||
func (b *BitSet) Any() bool {
|
|
||||||
panicIfNull(b)
|
|
||||||
return !b.None()
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsSuperSet returns true if this is a superset of the other set
|
|
||||||
func (b *BitSet) IsSuperSet(other *BitSet) bool {
|
|
||||||
for i, e := other.NextSet(0); e; i, e = other.NextSet(i + 1) {
|
|
||||||
if !b.Test(i) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsStrictSuperSet returns true if this is a strict superset of the other set
|
|
||||||
func (b *BitSet) IsStrictSuperSet(other *BitSet) bool {
|
|
||||||
return b.Count() > other.Count() && b.IsSuperSet(other)
|
|
||||||
}
|
|
||||||
|
|
||||||
// DumpAsBits dumps a bit set as a string of bits
|
|
||||||
func (b *BitSet) DumpAsBits() string {
|
|
||||||
if b.set == nil {
|
|
||||||
return "."
|
|
||||||
}
|
|
||||||
buffer := bytes.NewBufferString("")
|
|
||||||
i := len(b.set) - 1
|
|
||||||
for ; i >= 0; i-- {
|
|
||||||
fmt.Fprintf(buffer, "%064b.", b.set[i])
|
|
||||||
}
|
|
||||||
return buffer.String()
|
|
||||||
}
|
|
||||||
|
|
||||||
// BinaryStorageSize returns the binary storage requirements
|
|
||||||
func (b *BitSet) BinaryStorageSize() int {
|
|
||||||
return binary.Size(uint64(0)) + binary.Size(b.set)
|
|
||||||
}
|
|
||||||
|
|
||||||
// WriteTo writes a BitSet to a stream
|
|
||||||
func (b *BitSet) WriteTo(stream io.Writer) (int64, error) {
|
|
||||||
length := uint64(b.length)
|
|
||||||
|
|
||||||
// Write length
|
|
||||||
err := binary.Write(stream, binaryOrder, length)
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Write set
|
|
||||||
err = binary.Write(stream, binaryOrder, b.set)
|
|
||||||
return int64(b.BinaryStorageSize()), err
|
|
||||||
}
|
|
||||||
|
|
||||||
// ReadFrom reads a BitSet from a stream written using WriteTo
|
|
||||||
func (b *BitSet) ReadFrom(stream io.Reader) (int64, error) {
|
|
||||||
var length uint64
|
|
||||||
|
|
||||||
// Read length first
|
|
||||||
err := binary.Read(stream, binaryOrder, &length)
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
newset := New(uint(length))
|
|
||||||
|
|
||||||
if uint64(newset.length) != length {
|
|
||||||
return 0, errors.New("unmarshalling error: type mismatch")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read remaining bytes as set
|
|
||||||
err = binary.Read(stream, binaryOrder, newset.set)
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
*b = *newset
|
|
||||||
return int64(b.BinaryStorageSize()), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// MarshalBinary encodes a BitSet into a binary form and returns the result.
|
|
||||||
func (b *BitSet) MarshalBinary() ([]byte, error) {
|
|
||||||
var buf bytes.Buffer
|
|
||||||
writer := bufio.NewWriter(&buf)
|
|
||||||
|
|
||||||
_, err := b.WriteTo(writer)
|
|
||||||
if err != nil {
|
|
||||||
return []byte{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
err = writer.Flush()
|
|
||||||
|
|
||||||
return buf.Bytes(), err
|
|
||||||
}
|
|
||||||
|
|
||||||
// UnmarshalBinary decodes the binary form generated by MarshalBinary.
|
|
||||||
func (b *BitSet) UnmarshalBinary(data []byte) error {
|
|
||||||
buf := bytes.NewReader(data)
|
|
||||||
reader := bufio.NewReader(buf)
|
|
||||||
|
|
||||||
_, err := b.ReadFrom(reader)
|
|
||||||
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// MarshalJSON marshals a BitSet as a JSON structure
|
|
||||||
func (b *BitSet) MarshalJSON() ([]byte, error) {
|
|
||||||
buffer := bytes.NewBuffer(make([]byte, 0, b.BinaryStorageSize()))
|
|
||||||
_, err := b.WriteTo(buffer)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// URLEncode all bytes
|
|
||||||
return json.Marshal(base64Encoding.EncodeToString(buffer.Bytes()))
|
|
||||||
}
|
|
||||||
|
|
||||||
// UnmarshalJSON unmarshals a BitSet from JSON created using MarshalJSON
|
|
||||||
func (b *BitSet) UnmarshalJSON(data []byte) error {
|
|
||||||
// Unmarshal as string
|
|
||||||
var s string
|
|
||||||
err := json.Unmarshal(data, &s)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// URLDecode string
|
|
||||||
buf, err := base64Encoding.DecodeString(s)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = b.ReadFrom(bytes.NewReader(buf))
|
|
||||||
return err
|
|
||||||
}
|
|
3
vendor/github.com/bits-and-blooms/bitset/go.mod
generated
vendored
3
vendor/github.com/bits-and-blooms/bitset/go.mod
generated
vendored
@ -1,3 +0,0 @@
|
|||||||
module github.com/bits-and-blooms/bitset
|
|
||||||
|
|
||||||
go 1.14
|
|
0
vendor/github.com/bits-and-blooms/bitset/go.sum
generated
vendored
0
vendor/github.com/bits-and-blooms/bitset/go.sum
generated
vendored
53
vendor/github.com/bits-and-blooms/bitset/popcnt.go
generated
vendored
53
vendor/github.com/bits-and-blooms/bitset/popcnt.go
generated
vendored
@ -1,53 +0,0 @@
|
|||||||
package bitset
|
|
||||||
|
|
||||||
// bit population count, take from
|
|
||||||
// https://code.google.com/p/go/issues/detail?id=4988#c11
|
|
||||||
// credit: https://code.google.com/u/arnehormann/
|
|
||||||
func popcount(x uint64) (n uint64) {
|
|
||||||
x -= (x >> 1) & 0x5555555555555555
|
|
||||||
x = (x>>2)&0x3333333333333333 + x&0x3333333333333333
|
|
||||||
x += x >> 4
|
|
||||||
x &= 0x0f0f0f0f0f0f0f0f
|
|
||||||
x *= 0x0101010101010101
|
|
||||||
return x >> 56
|
|
||||||
}
|
|
||||||
|
|
||||||
func popcntSliceGo(s []uint64) uint64 {
|
|
||||||
cnt := uint64(0)
|
|
||||||
for _, x := range s {
|
|
||||||
cnt += popcount(x)
|
|
||||||
}
|
|
||||||
return cnt
|
|
||||||
}
|
|
||||||
|
|
||||||
func popcntMaskSliceGo(s, m []uint64) uint64 {
|
|
||||||
cnt := uint64(0)
|
|
||||||
for i := range s {
|
|
||||||
cnt += popcount(s[i] &^ m[i])
|
|
||||||
}
|
|
||||||
return cnt
|
|
||||||
}
|
|
||||||
|
|
||||||
func popcntAndSliceGo(s, m []uint64) uint64 {
|
|
||||||
cnt := uint64(0)
|
|
||||||
for i := range s {
|
|
||||||
cnt += popcount(s[i] & m[i])
|
|
||||||
}
|
|
||||||
return cnt
|
|
||||||
}
|
|
||||||
|
|
||||||
func popcntOrSliceGo(s, m []uint64) uint64 {
|
|
||||||
cnt := uint64(0)
|
|
||||||
for i := range s {
|
|
||||||
cnt += popcount(s[i] | m[i])
|
|
||||||
}
|
|
||||||
return cnt
|
|
||||||
}
|
|
||||||
|
|
||||||
func popcntXorSliceGo(s, m []uint64) uint64 {
|
|
||||||
cnt := uint64(0)
|
|
||||||
for i := range s {
|
|
||||||
cnt += popcount(s[i] ^ m[i])
|
|
||||||
}
|
|
||||||
return cnt
|
|
||||||
}
|
|
45
vendor/github.com/bits-and-blooms/bitset/popcnt_19.go
generated
vendored
45
vendor/github.com/bits-and-blooms/bitset/popcnt_19.go
generated
vendored
@ -1,45 +0,0 @@
|
|||||||
// +build go1.9
|
|
||||||
|
|
||||||
package bitset
|
|
||||||
|
|
||||||
import "math/bits"
|
|
||||||
|
|
||||||
func popcntSlice(s []uint64) uint64 {
|
|
||||||
var cnt int
|
|
||||||
for _, x := range s {
|
|
||||||
cnt += bits.OnesCount64(x)
|
|
||||||
}
|
|
||||||
return uint64(cnt)
|
|
||||||
}
|
|
||||||
|
|
||||||
func popcntMaskSlice(s, m []uint64) uint64 {
|
|
||||||
var cnt int
|
|
||||||
for i := range s {
|
|
||||||
cnt += bits.OnesCount64(s[i] &^ m[i])
|
|
||||||
}
|
|
||||||
return uint64(cnt)
|
|
||||||
}
|
|
||||||
|
|
||||||
func popcntAndSlice(s, m []uint64) uint64 {
|
|
||||||
var cnt int
|
|
||||||
for i := range s {
|
|
||||||
cnt += bits.OnesCount64(s[i] & m[i])
|
|
||||||
}
|
|
||||||
return uint64(cnt)
|
|
||||||
}
|
|
||||||
|
|
||||||
func popcntOrSlice(s, m []uint64) uint64 {
|
|
||||||
var cnt int
|
|
||||||
for i := range s {
|
|
||||||
cnt += bits.OnesCount64(s[i] | m[i])
|
|
||||||
}
|
|
||||||
return uint64(cnt)
|
|
||||||
}
|
|
||||||
|
|
||||||
func popcntXorSlice(s, m []uint64) uint64 {
|
|
||||||
var cnt int
|
|
||||||
for i := range s {
|
|
||||||
cnt += bits.OnesCount64(s[i] ^ m[i])
|
|
||||||
}
|
|
||||||
return uint64(cnt)
|
|
||||||
}
|
|
68
vendor/github.com/bits-and-blooms/bitset/popcnt_amd64.go
generated
vendored
68
vendor/github.com/bits-and-blooms/bitset/popcnt_amd64.go
generated
vendored
@ -1,68 +0,0 @@
|
|||||||
// +build !go1.9
|
|
||||||
// +build amd64,!appengine
|
|
||||||
|
|
||||||
package bitset
|
|
||||||
|
|
||||||
// *** the following functions are defined in popcnt_amd64.s
|
|
||||||
|
|
||||||
//go:noescape
|
|
||||||
|
|
||||||
func hasAsm() bool
|
|
||||||
|
|
||||||
// useAsm is a flag used to select the GO or ASM implementation of the popcnt function
|
|
||||||
var useAsm = hasAsm()
|
|
||||||
|
|
||||||
//go:noescape
|
|
||||||
|
|
||||||
func popcntSliceAsm(s []uint64) uint64
|
|
||||||
|
|
||||||
//go:noescape
|
|
||||||
|
|
||||||
func popcntMaskSliceAsm(s, m []uint64) uint64
|
|
||||||
|
|
||||||
//go:noescape
|
|
||||||
|
|
||||||
func popcntAndSliceAsm(s, m []uint64) uint64
|
|
||||||
|
|
||||||
//go:noescape
|
|
||||||
|
|
||||||
func popcntOrSliceAsm(s, m []uint64) uint64
|
|
||||||
|
|
||||||
//go:noescape
|
|
||||||
|
|
||||||
func popcntXorSliceAsm(s, m []uint64) uint64
|
|
||||||
|
|
||||||
func popcntSlice(s []uint64) uint64 {
|
|
||||||
if useAsm {
|
|
||||||
return popcntSliceAsm(s)
|
|
||||||
}
|
|
||||||
return popcntSliceGo(s)
|
|
||||||
}
|
|
||||||
|
|
||||||
func popcntMaskSlice(s, m []uint64) uint64 {
|
|
||||||
if useAsm {
|
|
||||||
return popcntMaskSliceAsm(s, m)
|
|
||||||
}
|
|
||||||
return popcntMaskSliceGo(s, m)
|
|
||||||
}
|
|
||||||
|
|
||||||
func popcntAndSlice(s, m []uint64) uint64 {
|
|
||||||
if useAsm {
|
|
||||||
return popcntAndSliceAsm(s, m)
|
|
||||||
}
|
|
||||||
return popcntAndSliceGo(s, m)
|
|
||||||
}
|
|
||||||
|
|
||||||
func popcntOrSlice(s, m []uint64) uint64 {
|
|
||||||
if useAsm {
|
|
||||||
return popcntOrSliceAsm(s, m)
|
|
||||||
}
|
|
||||||
return popcntOrSliceGo(s, m)
|
|
||||||
}
|
|
||||||
|
|
||||||
func popcntXorSlice(s, m []uint64) uint64 {
|
|
||||||
if useAsm {
|
|
||||||
return popcntXorSliceAsm(s, m)
|
|
||||||
}
|
|
||||||
return popcntXorSliceGo(s, m)
|
|
||||||
}
|
|
104
vendor/github.com/bits-and-blooms/bitset/popcnt_amd64.s
generated
vendored
104
vendor/github.com/bits-and-blooms/bitset/popcnt_amd64.s
generated
vendored
@ -1,104 +0,0 @@
|
|||||||
// +build !go1.9
|
|
||||||
// +build amd64,!appengine
|
|
||||||
|
|
||||||
TEXT ·hasAsm(SB),4,$0-1
|
|
||||||
MOVQ $1, AX
|
|
||||||
CPUID
|
|
||||||
SHRQ $23, CX
|
|
||||||
ANDQ $1, CX
|
|
||||||
MOVB CX, ret+0(FP)
|
|
||||||
RET
|
|
||||||
|
|
||||||
#define POPCNTQ_DX_DX BYTE $0xf3; BYTE $0x48; BYTE $0x0f; BYTE $0xb8; BYTE $0xd2
|
|
||||||
|
|
||||||
TEXT ·popcntSliceAsm(SB),4,$0-32
|
|
||||||
XORQ AX, AX
|
|
||||||
MOVQ s+0(FP), SI
|
|
||||||
MOVQ s_len+8(FP), CX
|
|
||||||
TESTQ CX, CX
|
|
||||||
JZ popcntSliceEnd
|
|
||||||
popcntSliceLoop:
|
|
||||||
BYTE $0xf3; BYTE $0x48; BYTE $0x0f; BYTE $0xb8; BYTE $0x16 // POPCNTQ (SI), DX
|
|
||||||
ADDQ DX, AX
|
|
||||||
ADDQ $8, SI
|
|
||||||
LOOP popcntSliceLoop
|
|
||||||
popcntSliceEnd:
|
|
||||||
MOVQ AX, ret+24(FP)
|
|
||||||
RET
|
|
||||||
|
|
||||||
TEXT ·popcntMaskSliceAsm(SB),4,$0-56
|
|
||||||
XORQ AX, AX
|
|
||||||
MOVQ s+0(FP), SI
|
|
||||||
MOVQ s_len+8(FP), CX
|
|
||||||
TESTQ CX, CX
|
|
||||||
JZ popcntMaskSliceEnd
|
|
||||||
MOVQ m+24(FP), DI
|
|
||||||
popcntMaskSliceLoop:
|
|
||||||
MOVQ (DI), DX
|
|
||||||
NOTQ DX
|
|
||||||
ANDQ (SI), DX
|
|
||||||
POPCNTQ_DX_DX
|
|
||||||
ADDQ DX, AX
|
|
||||||
ADDQ $8, SI
|
|
||||||
ADDQ $8, DI
|
|
||||||
LOOP popcntMaskSliceLoop
|
|
||||||
popcntMaskSliceEnd:
|
|
||||||
MOVQ AX, ret+48(FP)
|
|
||||||
RET
|
|
||||||
|
|
||||||
TEXT ·popcntAndSliceAsm(SB),4,$0-56
|
|
||||||
XORQ AX, AX
|
|
||||||
MOVQ s+0(FP), SI
|
|
||||||
MOVQ s_len+8(FP), CX
|
|
||||||
TESTQ CX, CX
|
|
||||||
JZ popcntAndSliceEnd
|
|
||||||
MOVQ m+24(FP), DI
|
|
||||||
popcntAndSliceLoop:
|
|
||||||
MOVQ (DI), DX
|
|
||||||
ANDQ (SI), DX
|
|
||||||
POPCNTQ_DX_DX
|
|
||||||
ADDQ DX, AX
|
|
||||||
ADDQ $8, SI
|
|
||||||
ADDQ $8, DI
|
|
||||||
LOOP popcntAndSliceLoop
|
|
||||||
popcntAndSliceEnd:
|
|
||||||
MOVQ AX, ret+48(FP)
|
|
||||||
RET
|
|
||||||
|
|
||||||
TEXT ·popcntOrSliceAsm(SB),4,$0-56
|
|
||||||
XORQ AX, AX
|
|
||||||
MOVQ s+0(FP), SI
|
|
||||||
MOVQ s_len+8(FP), CX
|
|
||||||
TESTQ CX, CX
|
|
||||||
JZ popcntOrSliceEnd
|
|
||||||
MOVQ m+24(FP), DI
|
|
||||||
popcntOrSliceLoop:
|
|
||||||
MOVQ (DI), DX
|
|
||||||
ORQ (SI), DX
|
|
||||||
POPCNTQ_DX_DX
|
|
||||||
ADDQ DX, AX
|
|
||||||
ADDQ $8, SI
|
|
||||||
ADDQ $8, DI
|
|
||||||
LOOP popcntOrSliceLoop
|
|
||||||
popcntOrSliceEnd:
|
|
||||||
MOVQ AX, ret+48(FP)
|
|
||||||
RET
|
|
||||||
|
|
||||||
TEXT ·popcntXorSliceAsm(SB),4,$0-56
|
|
||||||
XORQ AX, AX
|
|
||||||
MOVQ s+0(FP), SI
|
|
||||||
MOVQ s_len+8(FP), CX
|
|
||||||
TESTQ CX, CX
|
|
||||||
JZ popcntXorSliceEnd
|
|
||||||
MOVQ m+24(FP), DI
|
|
||||||
popcntXorSliceLoop:
|
|
||||||
MOVQ (DI), DX
|
|
||||||
XORQ (SI), DX
|
|
||||||
POPCNTQ_DX_DX
|
|
||||||
ADDQ DX, AX
|
|
||||||
ADDQ $8, SI
|
|
||||||
ADDQ $8, DI
|
|
||||||
LOOP popcntXorSliceLoop
|
|
||||||
popcntXorSliceEnd:
|
|
||||||
MOVQ AX, ret+48(FP)
|
|
||||||
RET
|
|
24
vendor/github.com/bits-and-blooms/bitset/popcnt_generic.go
generated
vendored
24
vendor/github.com/bits-and-blooms/bitset/popcnt_generic.go
generated
vendored
@ -1,24 +0,0 @@
|
|||||||
// +build !go1.9
|
|
||||||
// +build !amd64 appengine
|
|
||||||
|
|
||||||
package bitset
|
|
||||||
|
|
||||||
func popcntSlice(s []uint64) uint64 {
|
|
||||||
return popcntSliceGo(s)
|
|
||||||
}
|
|
||||||
|
|
||||||
func popcntMaskSlice(s, m []uint64) uint64 {
|
|
||||||
return popcntMaskSliceGo(s, m)
|
|
||||||
}
|
|
||||||
|
|
||||||
func popcntAndSlice(s, m []uint64) uint64 {
|
|
||||||
return popcntAndSliceGo(s, m)
|
|
||||||
}
|
|
||||||
|
|
||||||
func popcntOrSlice(s, m []uint64) uint64 {
|
|
||||||
return popcntOrSliceGo(s, m)
|
|
||||||
}
|
|
||||||
|
|
||||||
func popcntXorSlice(s, m []uint64) uint64 {
|
|
||||||
return popcntXorSliceGo(s, m)
|
|
||||||
}
|
|
14
vendor/github.com/bits-and-blooms/bitset/trailing_zeros_18.go
generated
vendored
14
vendor/github.com/bits-and-blooms/bitset/trailing_zeros_18.go
generated
vendored
@ -1,14 +0,0 @@
|
|||||||
// +build !go1.9
|
|
||||||
|
|
||||||
package bitset
|
|
||||||
|
|
||||||
var deBruijn = [...]byte{
|
|
||||||
0, 1, 56, 2, 57, 49, 28, 3, 61, 58, 42, 50, 38, 29, 17, 4,
|
|
||||||
62, 47, 59, 36, 45, 43, 51, 22, 53, 39, 33, 30, 24, 18, 12, 5,
|
|
||||||
63, 55, 48, 27, 60, 41, 37, 16, 46, 35, 44, 21, 52, 32, 23, 11,
|
|
||||||
54, 26, 40, 15, 34, 20, 31, 10, 25, 14, 19, 9, 13, 8, 7, 6,
|
|
||||||
}
|
|
||||||
|
|
||||||
func trailingZeroes64(v uint64) uint {
|
|
||||||
return uint(deBruijn[((v&-v)*0x03f79d71b4ca8b09)>>58])
|
|
||||||
}
|
|
9
vendor/github.com/bits-and-blooms/bitset/trailing_zeros_19.go
generated
vendored
9
vendor/github.com/bits-and-blooms/bitset/trailing_zeros_19.go
generated
vendored
@ -1,9 +0,0 @@
|
|||||||
// +build go1.9
|
|
||||||
|
|
||||||
package bitset
|
|
||||||
|
|
||||||
import "math/bits"
|
|
||||||
|
|
||||||
func trailingZeroes64(v uint64) uint {
|
|
||||||
return uint(bits.TrailingZeros64(v))
|
|
||||||
}
|
|
6
vendor/github.com/checkpoint-restore/go-criu/v5/.gitignore
generated
vendored
6
vendor/github.com/checkpoint-restore/go-criu/v5/.gitignore
generated
vendored
@ -1,6 +1,6 @@
|
|||||||
test/test
|
test/test
|
||||||
|
test/test.coverage
|
||||||
test/piggie/piggie
|
test/piggie/piggie
|
||||||
test/phaul
|
test/phaul/phaul
|
||||||
|
test/phaul/phaul.coverage
|
||||||
image
|
image
|
||||||
rpc/rpc.proto
|
|
||||||
stats/stats.proto
|
|
||||||
|
68
vendor/github.com/checkpoint-restore/go-criu/v5/Makefile
generated
vendored
68
vendor/github.com/checkpoint-restore/go-criu/v5/Makefile
generated
vendored
@ -1,5 +1,12 @@
|
|||||||
|
SHELL = /bin/bash
|
||||||
GO ?= go
|
GO ?= go
|
||||||
CC ?= gcc
|
CC ?= gcc
|
||||||
|
COVERAGE_PATH ?= $(shell pwd)/.coverage
|
||||||
|
CRIU_FEATURE_MEM_TRACK = $(shell if criu check --feature mem_dirty_track > /dev/null; then echo 1; else echo 0; fi)
|
||||||
|
CRIU_FEATURE_LAZY_PAGES = $(shell if criu check --feature uffd-noncoop > /dev/null; then echo 1; else echo 0; fi)
|
||||||
|
CRIU_FEATURE_PIDFD_STORE = $(shell if criu check --feature pidfd_store > /dev/null; then echo 1; else echo 0; fi)
|
||||||
|
|
||||||
|
export CRIU_FEATURE_MEM_TRACK CRIU_FEATURE_LAZY_PAGES CRIU_FEATURE_PIDFD_STORE
|
||||||
|
|
||||||
all: build test phaul-test
|
all: build test phaul-test
|
||||||
|
|
||||||
@ -9,13 +16,15 @@ lint:
|
|||||||
build:
|
build:
|
||||||
$(GO) build -v ./...
|
$(GO) build -v ./...
|
||||||
|
|
||||||
TEST_BINARIES := test/test test/piggie/piggie test/phaul/phaul
|
TEST_PAYLOAD := test/piggie/piggie
|
||||||
|
TEST_BINARIES := test/test $(TEST_PAYLOAD) test/phaul/phaul
|
||||||
|
COVERAGE_BINARIES := test/test.coverage test/phaul/phaul.coverage
|
||||||
test-bin: $(TEST_BINARIES)
|
test-bin: $(TEST_BINARIES)
|
||||||
|
|
||||||
test/piggie/piggie: test/piggie/piggie.c
|
test/piggie/piggie: test/piggie/piggie.c
|
||||||
$(CC) $^ -o $@
|
$(CC) $^ -o $@
|
||||||
|
|
||||||
test/test: test/*.go
|
test/test: test/main.go
|
||||||
$(GO) build -v -o $@ $^
|
$(GO) build -v -o $@ $^
|
||||||
|
|
||||||
test: $(TEST_BINARIES)
|
test: $(TEST_BINARIES)
|
||||||
@ -27,7 +36,7 @@ test: $(TEST_BINARIES)
|
|||||||
}
|
}
|
||||||
rm -rf image
|
rm -rf image
|
||||||
|
|
||||||
test/phaul/phaul: test/phaul/*.go
|
test/phaul/phaul: test/phaul/main.go
|
||||||
$(GO) build -v -o $@ $^
|
$(GO) build -v -o $@ $^
|
||||||
|
|
||||||
phaul-test: $(TEST_BINARIES)
|
phaul-test: $(TEST_BINARIES)
|
||||||
@ -37,10 +46,41 @@ phaul-test: $(TEST_BINARIES)
|
|||||||
pkill -9 piggie; \
|
pkill -9 piggie; \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test/test.coverage: test/*.go
|
||||||
|
$(GO) test \
|
||||||
|
-covermode=count \
|
||||||
|
-coverpkg=./... \
|
||||||
|
-mod=vendor \
|
||||||
|
-tags coverage \
|
||||||
|
-buildmode=pie -c -o $@ $^
|
||||||
|
|
||||||
|
test/phaul/phaul.coverage: test/phaul/*.go
|
||||||
|
$(GO) test \
|
||||||
|
-covermode=count \
|
||||||
|
-coverpkg=./... \
|
||||||
|
-mod=vendor \
|
||||||
|
-tags coverage \
|
||||||
|
-buildmode=pie -c -o $@ $^
|
||||||
|
|
||||||
|
coverage: $(COVERAGE_BINARIES) $(TEST_PAYLOAD)
|
||||||
|
mkdir -p $(COVERAGE_PATH)
|
||||||
|
mkdir -p image
|
||||||
|
PID=$$(test/piggie/piggie) && { \
|
||||||
|
test/test.coverage -test.coverprofile=coverprofile.integration.$$RANDOM -test.outputdir=${COVERAGE_PATH} COVERAGE dump $$PID image && \
|
||||||
|
test/test.coverage -test.coverprofile=coverprofile.integration.$$RANDOM -test.outputdir=${COVERAGE_PATH} COVERAGE restore image; \
|
||||||
|
pkill -9 piggie; \
|
||||||
|
}
|
||||||
|
rm -rf image
|
||||||
|
PID=$$(test/piggie/piggie) && { \
|
||||||
|
test/phaul/phaul.coverage -test.coverprofile=coverprofile.integration.$$RANDOM -test.outputdir=${COVERAGE_PATH} COVERAGE $$PID; \
|
||||||
|
pkill -9 piggie; \
|
||||||
|
}
|
||||||
|
echo "mode: set" > .coverage/coverage.out && cat .coverage/coverprofile* | \
|
||||||
|
grep -v mode: | sort -r | awk '{if($$1 != last) {print $$0;last=$$1}}' >> .coverage/coverage.out
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
@rm -f $(TEST_BINARIES)
|
@rm -f $(TEST_BINARIES) $(COVERAGE_BINARIES) codecov
|
||||||
@rm -rf image
|
@rm -rf image $(COVERAGE_PATH)
|
||||||
@rm -f rpc/rpc.proto stats/stats.proto
|
|
||||||
|
|
||||||
rpc/rpc.proto:
|
rpc/rpc.proto:
|
||||||
curl -sSL https://raw.githubusercontent.com/checkpoint-restore/criu/master/images/rpc.proto -o $@
|
curl -sSL https://raw.githubusercontent.com/checkpoint-restore/criu/master/images/rpc.proto -o $@
|
||||||
@ -49,9 +89,19 @@ stats/stats.proto:
|
|||||||
curl -sSL https://raw.githubusercontent.com/checkpoint-restore/criu/master/images/stats.proto -o $@
|
curl -sSL https://raw.githubusercontent.com/checkpoint-restore/criu/master/images/stats.proto -o $@
|
||||||
|
|
||||||
rpc/rpc.pb.go: rpc/rpc.proto
|
rpc/rpc.pb.go: rpc/rpc.proto
|
||||||
protoc --go_out=. $^
|
protoc --go_out=. --go_opt=M$^=rpc/ $^
|
||||||
|
|
||||||
stats/stats.pb.go: stats/stats.proto
|
stats/stats.pb.go: stats/stats.proto
|
||||||
protoc --go_out=. $^
|
protoc --go_out=. --go_opt=M$^=stats/ $^
|
||||||
|
|
||||||
.PHONY: build test phaul-test test-bin clean lint
|
vendor:
|
||||||
|
GO111MODULE=on $(GO) mod tidy
|
||||||
|
GO111MODULE=on $(GO) mod vendor
|
||||||
|
GO111MODULE=on $(GO) mod verify
|
||||||
|
|
||||||
|
codecov:
|
||||||
|
curl -Os https://uploader.codecov.io/latest/linux/codecov
|
||||||
|
chmod +x codecov
|
||||||
|
./codecov -f '.coverage/coverage.out'
|
||||||
|
|
||||||
|
.PHONY: build test phaul-test test-bin clean lint vendor coverage codecov
|
||||||
|
3
vendor/github.com/checkpoint-restore/go-criu/v5/README.md
generated
vendored
3
vendor/github.com/checkpoint-restore/go-criu/v5/README.md
generated
vendored
@ -16,7 +16,7 @@ The following example would print the version of CRIU:
|
|||||||
import (
|
import (
|
||||||
"log"
|
"log"
|
||||||
|
|
||||||
"github.com/checkpoint/restore/go-criu/v5"
|
"github.com/checkpoint-restore/go-criu/v5"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
@ -50,6 +50,7 @@ The following table shows the relation between go-criu and criu versions:
|
|||||||
|
|
||||||
| Major version | Latest release | CRIU version |
|
| Major version | Latest release | CRIU version |
|
||||||
| -------------- | -------------- | ------------ |
|
| -------------- | -------------- | ------------ |
|
||||||
|
| v5 | 5.2.0 | 3.16 |
|
||||||
| v5 | 5.0.0 | 3.15 |
|
| v5 | 5.0.0 | 3.15 |
|
||||||
| v4 | 4.1.0 | 3.14 |
|
| v4 | 4.1.0 | 3.14 |
|
||||||
|
|
||||||
|
45
vendor/github.com/checkpoint-restore/go-criu/v5/features.go
generated
vendored
Normal file
45
vendor/github.com/checkpoint-restore/go-criu/v5/features.go
generated
vendored
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
package criu
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/checkpoint-restore/go-criu/v5/rpc"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Feature checking in go-criu is based on the libcriu feature checking function.
|
||||||
|
|
||||||
|
// Feature checking allows the user to check if CRIU supports
|
||||||
|
// certain features. There are CRIU features which do not depend
|
||||||
|
// on the version of CRIU but on kernel features or architecture.
|
||||||
|
//
|
||||||
|
// One example is memory tracking. Memory tracking can be disabled
|
||||||
|
// in the kernel or there are architectures which do not support
|
||||||
|
// it (aarch64 for example). By using the feature check a libcriu
|
||||||
|
// user can easily query CRIU if a certain feature is available.
|
||||||
|
//
|
||||||
|
// The features which should be checked can be marked in the
|
||||||
|
// structure 'struct criu_feature_check'. Each structure member
|
||||||
|
// that is set to true will result in CRIU checking for the
|
||||||
|
// availability of that feature in the current combination of
|
||||||
|
// CRIU/kernel/architecture.
|
||||||
|
//
|
||||||
|
// Available features will be set to true when the function
|
||||||
|
// returns successfully. Missing features will be set to false.
|
||||||
|
|
||||||
|
func (c *Criu) FeatureCheck(features *rpc.CriuFeatures) (*rpc.CriuFeatures, error) {
|
||||||
|
resp, err := c.doSwrkWithResp(
|
||||||
|
rpc.CriuReqType_FEATURE_CHECK,
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
|
features,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if resp.GetType() != rpc.CriuReqType_FEATURE_CHECK {
|
||||||
|
return nil, fmt.Errorf("Unexpected CRIU RPC response")
|
||||||
|
}
|
||||||
|
|
||||||
|
return features, nil
|
||||||
|
}
|
3
vendor/github.com/checkpoint-restore/go-criu/v5/go.mod
generated
vendored
3
vendor/github.com/checkpoint-restore/go-criu/v5/go.mod
generated
vendored
@ -3,7 +3,6 @@ module github.com/checkpoint-restore/go-criu/v5
|
|||||||
go 1.13
|
go 1.13
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/golang/protobuf v1.4.3
|
|
||||||
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c
|
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c
|
||||||
google.golang.org/protobuf v1.23.0
|
google.golang.org/protobuf v1.27.1
|
||||||
)
|
)
|
||||||
|
24
vendor/github.com/checkpoint-restore/go-criu/v5/go.sum
generated
vendored
24
vendor/github.com/checkpoint-restore/go-criu/v5/go.sum
generated
vendored
@ -1,22 +1,10 @@
|
|||||||
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
|
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||||
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
|
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
|
||||||
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
|
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
|
|
||||||
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
|
|
||||||
github.com/golang/protobuf v1.4.3 h1:JjCZWpVbqXDqFVmTfYWEVTMIYrL/NPdPSCHPJ0T/raM=
|
|
||||||
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
|
||||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
|
||||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
|
||||||
github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4=
|
|
||||||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
|
||||||
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c h1:VwygUrnw9jn88c4u8GD3rZQbqrP/tgas88tPUbBxQrk=
|
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c h1:VwygUrnw9jn88c4u8GD3rZQbqrP/tgas88tPUbBxQrk=
|
||||||
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ=
|
||||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||||
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
|
|
||||||
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
|
|
||||||
google.golang.org/protobuf v1.23.0 h1:4MY060fB1DLGMB/7MBTLnwQUY6+F09GEiz6SsrNqyzM=
|
|
||||||
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
|
||||||
|
14
vendor/github.com/checkpoint-restore/go-criu/v5/main.go
generated
vendored
14
vendor/github.com/checkpoint-restore/go-criu/v5/main.go
generated
vendored
@ -87,19 +87,19 @@ func (c *Criu) sendAndRecv(reqB []byte) ([]byte, int, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Criu) doSwrk(reqType rpc.CriuReqType, opts *rpc.CriuOpts, nfy Notify) error {
|
func (c *Criu) doSwrk(reqType rpc.CriuReqType, opts *rpc.CriuOpts, nfy Notify) error {
|
||||||
resp, err := c.doSwrkWithResp(reqType, opts, nfy)
|
resp, err := c.doSwrkWithResp(reqType, opts, nfy, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
respType := resp.GetType()
|
respType := resp.GetType()
|
||||||
if respType != reqType {
|
if respType != reqType {
|
||||||
return errors.New("unexpected responce")
|
return errors.New("unexpected CRIU RPC response")
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Criu) doSwrkWithResp(reqType rpc.CriuReqType, opts *rpc.CriuOpts, nfy Notify) (*rpc.CriuResp, error) {
|
func (c *Criu) doSwrkWithResp(reqType rpc.CriuReqType, opts *rpc.CriuOpts, nfy Notify, features *rpc.CriuFeatures) (*rpc.CriuResp, error) {
|
||||||
var resp *rpc.CriuResp
|
var resp *rpc.CriuResp
|
||||||
|
|
||||||
req := rpc.CriuReq{
|
req := rpc.CriuReq{
|
||||||
@ -111,6 +111,10 @@ func (c *Criu) doSwrkWithResp(reqType rpc.CriuReqType, opts *rpc.CriuOpts, nfy N
|
|||||||
opts.NotifyScripts = proto.Bool(true)
|
opts.NotifyScripts = proto.Bool(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if features != nil {
|
||||||
|
req.Features = features
|
||||||
|
}
|
||||||
|
|
||||||
if c.swrkCmd == nil {
|
if c.swrkCmd == nil {
|
||||||
err := c.Prepare()
|
err := c.Prepare()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -209,7 +213,7 @@ func (c *Criu) StartPageServer(opts *rpc.CriuOpts) error {
|
|||||||
|
|
||||||
// StartPageServerChld starts the page server and returns PID and port
|
// StartPageServerChld starts the page server and returns PID and port
|
||||||
func (c *Criu) StartPageServerChld(opts *rpc.CriuOpts) (int, int, error) {
|
func (c *Criu) StartPageServerChld(opts *rpc.CriuOpts) (int, int, error) {
|
||||||
resp, err := c.doSwrkWithResp(rpc.CriuReqType_PAGE_SERVER_CHLD, opts, nil)
|
resp, err := c.doSwrkWithResp(rpc.CriuReqType_PAGE_SERVER_CHLD, opts, nil, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, 0, err
|
return 0, 0, err
|
||||||
}
|
}
|
||||||
@ -220,7 +224,7 @@ func (c *Criu) StartPageServerChld(opts *rpc.CriuOpts) (int, int, error) {
|
|||||||
// GetCriuVersion executes the VERSION RPC call and returns the version
|
// GetCriuVersion executes the VERSION RPC call and returns the version
|
||||||
// as an integer. Major * 10000 + Minor * 100 + SubLevel
|
// as an integer. Major * 10000 + Minor * 100 + SubLevel
|
||||||
func (c *Criu) GetCriuVersion() (int, error) {
|
func (c *Criu) GetCriuVersion() (int, error) {
|
||||||
resp, err := c.doSwrkWithResp(rpc.CriuReqType_VERSION, nil, nil)
|
resp, err := c.doSwrkWithResp(rpc.CriuReqType_VERSION, nil, nil, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
221
vendor/github.com/checkpoint-restore/go-criu/v5/rpc/rpc.pb.go
generated
vendored
221
vendor/github.com/checkpoint-restore/go-criu/v5/rpc/rpc.pb.go
generated
vendored
@ -1,13 +1,14 @@
|
|||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||||
// versions:
|
// versions:
|
||||||
// protoc-gen-go v1.25.0
|
// protoc-gen-go v1.27.1
|
||||||
// protoc v3.12.4
|
// protoc v3.12.4
|
||||||
// source: rpc/rpc.proto
|
// source: rpc/rpc.proto
|
||||||
|
|
||||||
package rpc
|
package rpc
|
||||||
|
|
||||||
import (
|
import (
|
||||||
proto "github.com/golang/protobuf/proto"
|
|
||||||
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||||
reflect "reflect"
|
reflect "reflect"
|
||||||
@ -21,10 +22,6 @@ const (
|
|||||||
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||||
)
|
)
|
||||||
|
|
||||||
// This is a compile-time assertion that a sufficiently up-to-date version
|
|
||||||
// of the legacy proto package is being used.
|
|
||||||
const _ = proto.ProtoPackageIsVersion4
|
|
||||||
|
|
||||||
type CriuCgMode int32
|
type CriuCgMode int32
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -706,7 +703,9 @@ type CriuOpts struct {
|
|||||||
Tls *bool `protobuf:"varint,58,opt,name=tls" json:"tls,omitempty"`
|
Tls *bool `protobuf:"varint,58,opt,name=tls" json:"tls,omitempty"`
|
||||||
TlsNoCnVerify *bool `protobuf:"varint,59,opt,name=tls_no_cn_verify,json=tlsNoCnVerify" json:"tls_no_cn_verify,omitempty"`
|
TlsNoCnVerify *bool `protobuf:"varint,59,opt,name=tls_no_cn_verify,json=tlsNoCnVerify" json:"tls_no_cn_verify,omitempty"`
|
||||||
CgroupYard *string `protobuf:"bytes,60,opt,name=cgroup_yard,json=cgroupYard" json:"cgroup_yard,omitempty"`
|
CgroupYard *string `protobuf:"bytes,60,opt,name=cgroup_yard,json=cgroupYard" json:"cgroup_yard,omitempty"`
|
||||||
PreDumpMode *CriuPreDumpMode `protobuf:"varint,61,opt,name=pre_dump_mode,json=preDumpMode,enum=CriuPreDumpMode,def=1" json:"pre_dump_mode,omitempty"` // optional bool check_mounts = 128;
|
PreDumpMode *CriuPreDumpMode `protobuf:"varint,61,opt,name=pre_dump_mode,json=preDumpMode,enum=CriuPreDumpMode,def=1" json:"pre_dump_mode,omitempty"`
|
||||||
|
PidfdStoreSk *int32 `protobuf:"varint,62,opt,name=pidfd_store_sk,json=pidfdStoreSk" json:"pidfd_store_sk,omitempty"`
|
||||||
|
LsmMountContext *string `protobuf:"bytes,63,opt,name=lsm_mount_context,json=lsmMountContext" json:"lsm_mount_context,omitempty"` // optional bool check_mounts = 128;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Default values for CriuOpts fields.
|
// Default values for CriuOpts fields.
|
||||||
@ -1169,6 +1168,20 @@ func (x *CriuOpts) GetPreDumpMode() CriuPreDumpMode {
|
|||||||
return Default_CriuOpts_PreDumpMode
|
return Default_CriuOpts_PreDumpMode
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (x *CriuOpts) GetPidfdStoreSk() int32 {
|
||||||
|
if x != nil && x.PidfdStoreSk != nil {
|
||||||
|
return *x.PidfdStoreSk
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *CriuOpts) GetLsmMountContext() string {
|
||||||
|
if x != nil && x.LsmMountContext != nil {
|
||||||
|
return *x.LsmMountContext
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
type CriuDumpResp struct {
|
type CriuDumpResp struct {
|
||||||
state protoimpl.MessageState
|
state protoimpl.MessageState
|
||||||
sizeCache protoimpl.SizeCache
|
sizeCache protoimpl.SizeCache
|
||||||
@ -1326,8 +1339,9 @@ type CriuFeatures struct {
|
|||||||
sizeCache protoimpl.SizeCache
|
sizeCache protoimpl.SizeCache
|
||||||
unknownFields protoimpl.UnknownFields
|
unknownFields protoimpl.UnknownFields
|
||||||
|
|
||||||
MemTrack *bool `protobuf:"varint,1,opt,name=mem_track,json=memTrack" json:"mem_track,omitempty"`
|
MemTrack *bool `protobuf:"varint,1,opt,name=mem_track,json=memTrack" json:"mem_track,omitempty"`
|
||||||
LazyPages *bool `protobuf:"varint,2,opt,name=lazy_pages,json=lazyPages" json:"lazy_pages,omitempty"`
|
LazyPages *bool `protobuf:"varint,2,opt,name=lazy_pages,json=lazyPages" json:"lazy_pages,omitempty"`
|
||||||
|
PidfdStore *bool `protobuf:"varint,3,opt,name=pidfd_store,json=pidfdStore" json:"pidfd_store,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *CriuFeatures) Reset() {
|
func (x *CriuFeatures) Reset() {
|
||||||
@ -1376,6 +1390,13 @@ func (x *CriuFeatures) GetLazyPages() bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (x *CriuFeatures) GetPidfdStore() bool {
|
||||||
|
if x != nil && x.PidfdStore != nil {
|
||||||
|
return *x.PidfdStore
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
type CriuReq struct {
|
type CriuReq struct {
|
||||||
state protoimpl.MessageState
|
state protoimpl.MessageState
|
||||||
sizeCache protoimpl.SizeCache
|
sizeCache protoimpl.SizeCache
|
||||||
@ -1718,7 +1739,7 @@ var file_rpc_rpc_proto_rawDesc = []byte{
|
|||||||
0x52, 0x04, 0x63, 0x74, 0x72, 0x6c, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x02,
|
0x52, 0x04, 0x63, 0x74, 0x72, 0x6c, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x02,
|
||||||
0x20, 0x02, 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x22, 0x1f, 0x0a, 0x07, 0x75, 0x6e,
|
0x20, 0x02, 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x22, 0x1f, 0x0a, 0x07, 0x75, 0x6e,
|
||||||
0x69, 0x78, 0x5f, 0x73, 0x6b, 0x12, 0x14, 0x0a, 0x05, 0x69, 0x6e, 0x6f, 0x64, 0x65, 0x18, 0x01,
|
0x69, 0x78, 0x5f, 0x73, 0x6b, 0x12, 0x14, 0x0a, 0x05, 0x69, 0x6e, 0x6f, 0x64, 0x65, 0x18, 0x01,
|
||||||
0x20, 0x02, 0x28, 0x0d, 0x52, 0x05, 0x69, 0x6e, 0x6f, 0x64, 0x65, 0x22, 0xba, 0x10, 0x0a, 0x09,
|
0x20, 0x02, 0x28, 0x0d, 0x52, 0x05, 0x69, 0x6e, 0x6f, 0x64, 0x65, 0x22, 0x8c, 0x11, 0x0a, 0x09,
|
||||||
0x63, 0x72, 0x69, 0x75, 0x5f, 0x6f, 0x70, 0x74, 0x73, 0x12, 0x22, 0x0a, 0x0d, 0x69, 0x6d, 0x61,
|
0x63, 0x72, 0x69, 0x75, 0x5f, 0x6f, 0x70, 0x74, 0x73, 0x12, 0x22, 0x0a, 0x0d, 0x69, 0x6d, 0x61,
|
||||||
0x67, 0x65, 0x73, 0x5f, 0x64, 0x69, 0x72, 0x5f, 0x66, 0x64, 0x18, 0x01, 0x20, 0x02, 0x28, 0x05,
|
0x67, 0x65, 0x73, 0x5f, 0x64, 0x69, 0x72, 0x5f, 0x66, 0x64, 0x18, 0x01, 0x20, 0x02, 0x28, 0x05,
|
||||||
0x52, 0x0b, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x73, 0x44, 0x69, 0x72, 0x46, 0x64, 0x12, 0x10, 0x0a,
|
0x52, 0x0b, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x73, 0x44, 0x69, 0x72, 0x46, 0x64, 0x12, 0x10, 0x0a,
|
||||||
@ -1850,92 +1871,100 @@ var file_rpc_rpc_proto_rawDesc = []byte{
|
|||||||
0x75, 0x6d, 0x70, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x18, 0x3d, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x13,
|
0x75, 0x6d, 0x70, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x18, 0x3d, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x13,
|
||||||
0x2e, 0x63, 0x72, 0x69, 0x75, 0x5f, 0x70, 0x72, 0x65, 0x5f, 0x64, 0x75, 0x6d, 0x70, 0x5f, 0x6d,
|
0x2e, 0x63, 0x72, 0x69, 0x75, 0x5f, 0x70, 0x72, 0x65, 0x5f, 0x64, 0x75, 0x6d, 0x70, 0x5f, 0x6d,
|
||||||
0x6f, 0x64, 0x65, 0x3a, 0x06, 0x53, 0x50, 0x4c, 0x49, 0x43, 0x45, 0x52, 0x0b, 0x70, 0x72, 0x65,
|
0x6f, 0x64, 0x65, 0x3a, 0x06, 0x53, 0x50, 0x4c, 0x49, 0x43, 0x45, 0x52, 0x0b, 0x70, 0x72, 0x65,
|
||||||
0x44, 0x75, 0x6d, 0x70, 0x4d, 0x6f, 0x64, 0x65, 0x22, 0x2c, 0x0a, 0x0e, 0x63, 0x72, 0x69, 0x75,
|
0x44, 0x75, 0x6d, 0x70, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x24, 0x0a, 0x0e, 0x70, 0x69, 0x64, 0x66,
|
||||||
0x5f, 0x64, 0x75, 0x6d, 0x70, 0x5f, 0x72, 0x65, 0x73, 0x70, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65,
|
0x64, 0x5f, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x5f, 0x73, 0x6b, 0x18, 0x3e, 0x20, 0x01, 0x28, 0x05,
|
||||||
0x73, 0x74, 0x6f, 0x72, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x72, 0x65,
|
0x52, 0x0c, 0x70, 0x69, 0x64, 0x66, 0x64, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x53, 0x6b, 0x12, 0x2a,
|
||||||
0x73, 0x74, 0x6f, 0x72, 0x65, 0x64, 0x22, 0x25, 0x0a, 0x11, 0x63, 0x72, 0x69, 0x75, 0x5f, 0x72,
|
0x0a, 0x11, 0x6c, 0x73, 0x6d, 0x5f, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x74,
|
||||||
0x65, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x5f, 0x72, 0x65, 0x73, 0x70, 0x12, 0x10, 0x0a, 0x03, 0x70,
|
0x65, 0x78, 0x74, 0x18, 0x3f, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x6c, 0x73, 0x6d, 0x4d, 0x6f,
|
||||||
0x69, 0x64, 0x18, 0x01, 0x20, 0x02, 0x28, 0x05, 0x52, 0x03, 0x70, 0x69, 0x64, 0x22, 0x37, 0x0a,
|
0x75, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x22, 0x2c, 0x0a, 0x0e, 0x63, 0x72,
|
||||||
0x0b, 0x63, 0x72, 0x69, 0x75, 0x5f, 0x6e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x12, 0x16, 0x0a, 0x06,
|
0x69, 0x75, 0x5f, 0x64, 0x75, 0x6d, 0x70, 0x5f, 0x72, 0x65, 0x73, 0x70, 0x12, 0x1a, 0x0a, 0x08,
|
||||||
0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x63,
|
0x72, 0x65, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08,
|
||||||
0x72, 0x69, 0x70, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x70, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28,
|
0x72, 0x65, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x64, 0x22, 0x25, 0x0a, 0x11, 0x63, 0x72, 0x69, 0x75,
|
||||||
0x05, 0x52, 0x03, 0x70, 0x69, 0x64, 0x22, 0x4b, 0x0a, 0x0d, 0x63, 0x72, 0x69, 0x75, 0x5f, 0x66,
|
0x5f, 0x72, 0x65, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x5f, 0x72, 0x65, 0x73, 0x70, 0x12, 0x10, 0x0a,
|
||||||
0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x6d, 0x65, 0x6d, 0x5f, 0x74,
|
0x03, 0x70, 0x69, 0x64, 0x18, 0x01, 0x20, 0x02, 0x28, 0x05, 0x52, 0x03, 0x70, 0x69, 0x64, 0x22,
|
||||||
0x72, 0x61, 0x63, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x6d, 0x65, 0x6d, 0x54,
|
0x37, 0x0a, 0x0b, 0x63, 0x72, 0x69, 0x75, 0x5f, 0x6e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x12, 0x16,
|
||||||
0x72, 0x61, 0x63, 0x6b, 0x12, 0x1d, 0x0a, 0x0a, 0x6c, 0x61, 0x7a, 0x79, 0x5f, 0x70, 0x61, 0x67,
|
0x0a, 0x06, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06,
|
||||||
0x65, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x6c, 0x61, 0x7a, 0x79, 0x50, 0x61,
|
0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x70, 0x69, 0x64, 0x18, 0x02, 0x20,
|
||||||
0x67, 0x65, 0x73, 0x22, 0xd0, 0x01, 0x0a, 0x08, 0x63, 0x72, 0x69, 0x75, 0x5f, 0x72, 0x65, 0x71,
|
0x01, 0x28, 0x05, 0x52, 0x03, 0x70, 0x69, 0x64, 0x22, 0x6c, 0x0a, 0x0d, 0x63, 0x72, 0x69, 0x75,
|
||||||
0x12, 0x22, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x02, 0x28, 0x0e, 0x32, 0x0e,
|
0x5f, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x6d, 0x65, 0x6d,
|
||||||
0x2e, 0x63, 0x72, 0x69, 0x75, 0x5f, 0x72, 0x65, 0x71, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x52, 0x04,
|
0x5f, 0x74, 0x72, 0x61, 0x63, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x6d, 0x65,
|
||||||
0x74, 0x79, 0x70, 0x65, 0x12, 0x1e, 0x0a, 0x04, 0x6f, 0x70, 0x74, 0x73, 0x18, 0x02, 0x20, 0x01,
|
0x6d, 0x54, 0x72, 0x61, 0x63, 0x6b, 0x12, 0x1d, 0x0a, 0x0a, 0x6c, 0x61, 0x7a, 0x79, 0x5f, 0x70,
|
||||||
0x28, 0x0b, 0x32, 0x0a, 0x2e, 0x63, 0x72, 0x69, 0x75, 0x5f, 0x6f, 0x70, 0x74, 0x73, 0x52, 0x04,
|
0x61, 0x67, 0x65, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x6c, 0x61, 0x7a, 0x79,
|
||||||
0x6f, 0x70, 0x74, 0x73, 0x12, 0x25, 0x0a, 0x0e, 0x6e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x5f, 0x73,
|
0x50, 0x61, 0x67, 0x65, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x70, 0x69, 0x64, 0x66, 0x64, 0x5f, 0x73,
|
||||||
0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x6e, 0x6f,
|
0x74, 0x6f, 0x72, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x70, 0x69, 0x64, 0x66,
|
||||||
0x74, 0x69, 0x66, 0x79, 0x53, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x6b,
|
0x64, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x22, 0xd0, 0x01, 0x0a, 0x08, 0x63, 0x72, 0x69, 0x75, 0x5f,
|
||||||
0x65, 0x65, 0x70, 0x5f, 0x6f, 0x70, 0x65, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08,
|
0x72, 0x65, 0x71, 0x12, 0x22, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x02, 0x28,
|
||||||
0x6b, 0x65, 0x65, 0x70, 0x4f, 0x70, 0x65, 0x6e, 0x12, 0x2a, 0x0a, 0x08, 0x66, 0x65, 0x61, 0x74,
|
0x0e, 0x32, 0x0e, 0x2e, 0x63, 0x72, 0x69, 0x75, 0x5f, 0x72, 0x65, 0x71, 0x5f, 0x74, 0x79, 0x70,
|
||||||
0x75, 0x72, 0x65, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x63, 0x72, 0x69,
|
0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x1e, 0x0a, 0x04, 0x6f, 0x70, 0x74, 0x73, 0x18,
|
||||||
0x75, 0x5f, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x52, 0x08, 0x66, 0x65, 0x61, 0x74,
|
0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0a, 0x2e, 0x63, 0x72, 0x69, 0x75, 0x5f, 0x6f, 0x70, 0x74,
|
||||||
0x75, 0x72, 0x65, 0x73, 0x12, 0x10, 0x0a, 0x03, 0x70, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28,
|
0x73, 0x52, 0x04, 0x6f, 0x70, 0x74, 0x73, 0x12, 0x25, 0x0a, 0x0e, 0x6e, 0x6f, 0x74, 0x69, 0x66,
|
||||||
0x0d, 0x52, 0x03, 0x70, 0x69, 0x64, 0x22, 0x8f, 0x03, 0x0a, 0x09, 0x63, 0x72, 0x69, 0x75, 0x5f,
|
0x79, 0x5f, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52,
|
||||||
0x72, 0x65, 0x73, 0x70, 0x12, 0x22, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x02,
|
0x0d, 0x6e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x53, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x12, 0x1b,
|
||||||
0x28, 0x0e, 0x32, 0x0e, 0x2e, 0x63, 0x72, 0x69, 0x75, 0x5f, 0x72, 0x65, 0x71, 0x5f, 0x74, 0x79,
|
0x0a, 0x09, 0x6b, 0x65, 0x65, 0x70, 0x5f, 0x6f, 0x70, 0x65, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28,
|
||||||
0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x75, 0x63, 0x63,
|
0x08, 0x52, 0x08, 0x6b, 0x65, 0x65, 0x70, 0x4f, 0x70, 0x65, 0x6e, 0x12, 0x2a, 0x0a, 0x08, 0x66,
|
||||||
0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x02, 0x28, 0x08, 0x52, 0x07, 0x73, 0x75, 0x63, 0x63, 0x65,
|
0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e,
|
||||||
0x73, 0x73, 0x12, 0x23, 0x0a, 0x04, 0x64, 0x75, 0x6d, 0x70, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b,
|
0x63, 0x72, 0x69, 0x75, 0x5f, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x52, 0x08, 0x66,
|
||||||
0x32, 0x0f, 0x2e, 0x63, 0x72, 0x69, 0x75, 0x5f, 0x64, 0x75, 0x6d, 0x70, 0x5f, 0x72, 0x65, 0x73,
|
0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x12, 0x10, 0x0a, 0x03, 0x70, 0x69, 0x64, 0x18, 0x06,
|
||||||
0x70, 0x52, 0x04, 0x64, 0x75, 0x6d, 0x70, 0x12, 0x2c, 0x0a, 0x07, 0x72, 0x65, 0x73, 0x74, 0x6f,
|
0x20, 0x01, 0x28, 0x0d, 0x52, 0x03, 0x70, 0x69, 0x64, 0x22, 0x8f, 0x03, 0x0a, 0x09, 0x63, 0x72,
|
||||||
0x72, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x72, 0x69, 0x75, 0x5f,
|
0x69, 0x75, 0x5f, 0x72, 0x65, 0x73, 0x70, 0x12, 0x22, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18,
|
||||||
0x72, 0x65, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x5f, 0x72, 0x65, 0x73, 0x70, 0x52, 0x07, 0x72, 0x65,
|
0x01, 0x20, 0x02, 0x28, 0x0e, 0x32, 0x0e, 0x2e, 0x63, 0x72, 0x69, 0x75, 0x5f, 0x72, 0x65, 0x71,
|
||||||
0x73, 0x74, 0x6f, 0x72, 0x65, 0x12, 0x24, 0x0a, 0x06, 0x6e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x18,
|
0x5f, 0x74, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x73,
|
||||||
0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x63, 0x72, 0x69, 0x75, 0x5f, 0x6e, 0x6f, 0x74,
|
0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x02, 0x28, 0x08, 0x52, 0x07, 0x73, 0x75,
|
||||||
0x69, 0x66, 0x79, 0x52, 0x06, 0x6e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x12, 0x26, 0x0a, 0x02, 0x70,
|
0x63, 0x63, 0x65, 0x73, 0x73, 0x12, 0x23, 0x0a, 0x04, 0x64, 0x75, 0x6d, 0x70, 0x18, 0x03, 0x20,
|
||||||
0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x63, 0x72, 0x69, 0x75, 0x5f, 0x70,
|
0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x63, 0x72, 0x69, 0x75, 0x5f, 0x64, 0x75, 0x6d, 0x70, 0x5f,
|
||||||
0x61, 0x67, 0x65, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x52,
|
0x72, 0x65, 0x73, 0x70, 0x52, 0x04, 0x64, 0x75, 0x6d, 0x70, 0x12, 0x2c, 0x0a, 0x07, 0x72, 0x65,
|
||||||
0x02, 0x70, 0x73, 0x12, 0x19, 0x0a, 0x08, 0x63, 0x72, 0x5f, 0x65, 0x72, 0x72, 0x6e, 0x6f, 0x18,
|
0x73, 0x74, 0x6f, 0x72, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x72,
|
||||||
0x07, 0x20, 0x01, 0x28, 0x05, 0x52, 0x07, 0x63, 0x72, 0x45, 0x72, 0x72, 0x6e, 0x6f, 0x12, 0x2a,
|
0x69, 0x75, 0x5f, 0x72, 0x65, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x5f, 0x72, 0x65, 0x73, 0x70, 0x52,
|
||||||
0x0a, 0x08, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b,
|
0x07, 0x72, 0x65, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x12, 0x24, 0x0a, 0x06, 0x6e, 0x6f, 0x74, 0x69,
|
||||||
0x32, 0x0e, 0x2e, 0x63, 0x72, 0x69, 0x75, 0x5f, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73,
|
0x66, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x63, 0x72, 0x69, 0x75, 0x5f,
|
||||||
0x52, 0x08, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x63, 0x72,
|
0x6e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x52, 0x06, 0x6e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x12, 0x26,
|
||||||
0x5f, 0x65, 0x72, 0x72, 0x6d, 0x73, 0x67, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x63,
|
0x0a, 0x02, 0x70, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x63, 0x72, 0x69,
|
||||||
0x72, 0x45, 0x72, 0x72, 0x6d, 0x73, 0x67, 0x12, 0x27, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69,
|
0x75, 0x5f, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x69, 0x6e,
|
||||||
0x6f, 0x6e, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x63, 0x72, 0x69, 0x75, 0x5f,
|
0x66, 0x6f, 0x52, 0x02, 0x70, 0x73, 0x12, 0x19, 0x0a, 0x08, 0x63, 0x72, 0x5f, 0x65, 0x72, 0x72,
|
||||||
0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e,
|
0x6e, 0x6f, 0x18, 0x07, 0x20, 0x01, 0x28, 0x05, 0x52, 0x07, 0x63, 0x72, 0x45, 0x72, 0x72, 0x6e,
|
||||||
0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x05,
|
0x6f, 0x12, 0x2a, 0x0a, 0x08, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x18, 0x08, 0x20,
|
||||||
0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0xb0, 0x01, 0x0a, 0x0c, 0x63, 0x72, 0x69,
|
0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x63, 0x72, 0x69, 0x75, 0x5f, 0x66, 0x65, 0x61, 0x74, 0x75,
|
||||||
0x75, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x21, 0x0a, 0x0c, 0x6d, 0x61, 0x6a,
|
0x72, 0x65, 0x73, 0x52, 0x08, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x12, 0x1b, 0x0a,
|
||||||
0x6f, 0x72, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x01, 0x20, 0x02, 0x28, 0x05, 0x52,
|
0x09, 0x63, 0x72, 0x5f, 0x65, 0x72, 0x72, 0x6d, 0x73, 0x67, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09,
|
||||||
0x0b, 0x6d, 0x61, 0x6a, 0x6f, 0x72, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x21, 0x0a, 0x0c,
|
0x52, 0x08, 0x63, 0x72, 0x45, 0x72, 0x72, 0x6d, 0x73, 0x67, 0x12, 0x27, 0x0a, 0x07, 0x76, 0x65,
|
||||||
0x6d, 0x69, 0x6e, 0x6f, 0x72, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x02, 0x20, 0x02,
|
0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x63, 0x72,
|
||||||
0x28, 0x05, 0x52, 0x0b, 0x6d, 0x69, 0x6e, 0x6f, 0x72, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12,
|
0x69, 0x75, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73,
|
||||||
0x14, 0x0a, 0x05, 0x67, 0x69, 0x74, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05,
|
0x69, 0x6f, 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x0b, 0x20,
|
||||||
0x67, 0x69, 0x74, 0x69, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x73, 0x75, 0x62, 0x6c, 0x65, 0x76, 0x65,
|
0x01, 0x28, 0x05, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0xb0, 0x01, 0x0a, 0x0c,
|
||||||
0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x73, 0x75, 0x62, 0x6c, 0x65, 0x76, 0x65,
|
0x63, 0x72, 0x69, 0x75, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x21, 0x0a, 0x0c,
|
||||||
0x6c, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x78, 0x74, 0x72, 0x61, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05,
|
0x6d, 0x61, 0x6a, 0x6f, 0x72, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x01, 0x20, 0x02,
|
||||||
0x52, 0x05, 0x65, 0x78, 0x74, 0x72, 0x61, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18,
|
0x28, 0x05, 0x52, 0x0b, 0x6d, 0x61, 0x6a, 0x6f, 0x72, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12,
|
||||||
0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x2a, 0x5f, 0x0a, 0x0c, 0x63,
|
0x21, 0x0a, 0x0c, 0x6d, 0x69, 0x6e, 0x6f, 0x72, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18,
|
||||||
0x72, 0x69, 0x75, 0x5f, 0x63, 0x67, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x12, 0x0a, 0x0a, 0x06, 0x49,
|
0x02, 0x20, 0x02, 0x28, 0x05, 0x52, 0x0b, 0x6d, 0x69, 0x6e, 0x6f, 0x72, 0x4e, 0x75, 0x6d, 0x62,
|
||||||
0x47, 0x4e, 0x4f, 0x52, 0x45, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x43, 0x47, 0x5f, 0x4e, 0x4f,
|
0x65, 0x72, 0x12, 0x14, 0x0a, 0x05, 0x67, 0x69, 0x74, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28,
|
||||||
0x4e, 0x45, 0x10, 0x01, 0x12, 0x09, 0x0a, 0x05, 0x50, 0x52, 0x4f, 0x50, 0x53, 0x10, 0x02, 0x12,
|
0x09, 0x52, 0x05, 0x67, 0x69, 0x74, 0x69, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x73, 0x75, 0x62, 0x6c,
|
||||||
0x08, 0x0a, 0x04, 0x53, 0x4f, 0x46, 0x54, 0x10, 0x03, 0x12, 0x08, 0x0a, 0x04, 0x46, 0x55, 0x4c,
|
0x65, 0x76, 0x65, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x73, 0x75, 0x62, 0x6c,
|
||||||
0x4c, 0x10, 0x04, 0x12, 0x0a, 0x0a, 0x06, 0x53, 0x54, 0x52, 0x49, 0x43, 0x54, 0x10, 0x05, 0x12,
|
0x65, 0x76, 0x65, 0x6c, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x78, 0x74, 0x72, 0x61, 0x18, 0x05, 0x20,
|
||||||
0x0b, 0x0a, 0x07, 0x44, 0x45, 0x46, 0x41, 0x55, 0x4c, 0x54, 0x10, 0x06, 0x2a, 0x2d, 0x0a, 0x12,
|
0x01, 0x28, 0x05, 0x52, 0x05, 0x65, 0x78, 0x74, 0x72, 0x61, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61,
|
||||||
0x63, 0x72, 0x69, 0x75, 0x5f, 0x70, 0x72, 0x65, 0x5f, 0x64, 0x75, 0x6d, 0x70, 0x5f, 0x6d, 0x6f,
|
0x6d, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x2a, 0x5f,
|
||||||
0x64, 0x65, 0x12, 0x0a, 0x0a, 0x06, 0x53, 0x50, 0x4c, 0x49, 0x43, 0x45, 0x10, 0x01, 0x12, 0x0b,
|
0x0a, 0x0c, 0x63, 0x72, 0x69, 0x75, 0x5f, 0x63, 0x67, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x12, 0x0a,
|
||||||
0x0a, 0x07, 0x56, 0x4d, 0x5f, 0x52, 0x45, 0x41, 0x44, 0x10, 0x02, 0x2a, 0xd0, 0x01, 0x0a, 0x0d,
|
0x0a, 0x06, 0x49, 0x47, 0x4e, 0x4f, 0x52, 0x45, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x43, 0x47,
|
||||||
0x63, 0x72, 0x69, 0x75, 0x5f, 0x72, 0x65, 0x71, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x12, 0x09, 0x0a,
|
0x5f, 0x4e, 0x4f, 0x4e, 0x45, 0x10, 0x01, 0x12, 0x09, 0x0a, 0x05, 0x50, 0x52, 0x4f, 0x50, 0x53,
|
||||||
0x05, 0x45, 0x4d, 0x50, 0x54, 0x59, 0x10, 0x00, 0x12, 0x08, 0x0a, 0x04, 0x44, 0x55, 0x4d, 0x50,
|
0x10, 0x02, 0x12, 0x08, 0x0a, 0x04, 0x53, 0x4f, 0x46, 0x54, 0x10, 0x03, 0x12, 0x08, 0x0a, 0x04,
|
||||||
0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x52, 0x45, 0x53, 0x54, 0x4f, 0x52, 0x45, 0x10, 0x02, 0x12,
|
0x46, 0x55, 0x4c, 0x4c, 0x10, 0x04, 0x12, 0x0a, 0x0a, 0x06, 0x53, 0x54, 0x52, 0x49, 0x43, 0x54,
|
||||||
0x09, 0x0a, 0x05, 0x43, 0x48, 0x45, 0x43, 0x4b, 0x10, 0x03, 0x12, 0x0c, 0x0a, 0x08, 0x50, 0x52,
|
0x10, 0x05, 0x12, 0x0b, 0x0a, 0x07, 0x44, 0x45, 0x46, 0x41, 0x55, 0x4c, 0x54, 0x10, 0x06, 0x2a,
|
||||||
0x45, 0x5f, 0x44, 0x55, 0x4d, 0x50, 0x10, 0x04, 0x12, 0x0f, 0x0a, 0x0b, 0x50, 0x41, 0x47, 0x45,
|
0x2d, 0x0a, 0x12, 0x63, 0x72, 0x69, 0x75, 0x5f, 0x70, 0x72, 0x65, 0x5f, 0x64, 0x75, 0x6d, 0x70,
|
||||||
0x5f, 0x53, 0x45, 0x52, 0x56, 0x45, 0x52, 0x10, 0x05, 0x12, 0x0a, 0x0a, 0x06, 0x4e, 0x4f, 0x54,
|
0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x12, 0x0a, 0x0a, 0x06, 0x53, 0x50, 0x4c, 0x49, 0x43, 0x45, 0x10,
|
||||||
0x49, 0x46, 0x59, 0x10, 0x06, 0x12, 0x10, 0x0a, 0x0c, 0x43, 0x50, 0x55, 0x49, 0x4e, 0x46, 0x4f,
|
0x01, 0x12, 0x0b, 0x0a, 0x07, 0x56, 0x4d, 0x5f, 0x52, 0x45, 0x41, 0x44, 0x10, 0x02, 0x2a, 0xd0,
|
||||||
0x5f, 0x44, 0x55, 0x4d, 0x50, 0x10, 0x07, 0x12, 0x11, 0x0a, 0x0d, 0x43, 0x50, 0x55, 0x49, 0x4e,
|
0x01, 0x0a, 0x0d, 0x63, 0x72, 0x69, 0x75, 0x5f, 0x72, 0x65, 0x71, 0x5f, 0x74, 0x79, 0x70, 0x65,
|
||||||
0x46, 0x4f, 0x5f, 0x43, 0x48, 0x45, 0x43, 0x4b, 0x10, 0x08, 0x12, 0x11, 0x0a, 0x0d, 0x46, 0x45,
|
0x12, 0x09, 0x0a, 0x05, 0x45, 0x4d, 0x50, 0x54, 0x59, 0x10, 0x00, 0x12, 0x08, 0x0a, 0x04, 0x44,
|
||||||
0x41, 0x54, 0x55, 0x52, 0x45, 0x5f, 0x43, 0x48, 0x45, 0x43, 0x4b, 0x10, 0x09, 0x12, 0x0b, 0x0a,
|
0x55, 0x4d, 0x50, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x52, 0x45, 0x53, 0x54, 0x4f, 0x52, 0x45,
|
||||||
0x07, 0x56, 0x45, 0x52, 0x53, 0x49, 0x4f, 0x4e, 0x10, 0x0a, 0x12, 0x0c, 0x0a, 0x08, 0x57, 0x41,
|
0x10, 0x02, 0x12, 0x09, 0x0a, 0x05, 0x43, 0x48, 0x45, 0x43, 0x4b, 0x10, 0x03, 0x12, 0x0c, 0x0a,
|
||||||
0x49, 0x54, 0x5f, 0x50, 0x49, 0x44, 0x10, 0x0b, 0x12, 0x14, 0x0a, 0x10, 0x50, 0x41, 0x47, 0x45,
|
0x08, 0x50, 0x52, 0x45, 0x5f, 0x44, 0x55, 0x4d, 0x50, 0x10, 0x04, 0x12, 0x0f, 0x0a, 0x0b, 0x50,
|
||||||
0x5f, 0x53, 0x45, 0x52, 0x56, 0x45, 0x52, 0x5f, 0x43, 0x48, 0x4c, 0x44, 0x10, 0x0c,
|
0x41, 0x47, 0x45, 0x5f, 0x53, 0x45, 0x52, 0x56, 0x45, 0x52, 0x10, 0x05, 0x12, 0x0a, 0x0a, 0x06,
|
||||||
|
0x4e, 0x4f, 0x54, 0x49, 0x46, 0x59, 0x10, 0x06, 0x12, 0x10, 0x0a, 0x0c, 0x43, 0x50, 0x55, 0x49,
|
||||||
|
0x4e, 0x46, 0x4f, 0x5f, 0x44, 0x55, 0x4d, 0x50, 0x10, 0x07, 0x12, 0x11, 0x0a, 0x0d, 0x43, 0x50,
|
||||||
|
0x55, 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x43, 0x48, 0x45, 0x43, 0x4b, 0x10, 0x08, 0x12, 0x11, 0x0a,
|
||||||
|
0x0d, 0x46, 0x45, 0x41, 0x54, 0x55, 0x52, 0x45, 0x5f, 0x43, 0x48, 0x45, 0x43, 0x4b, 0x10, 0x09,
|
||||||
|
0x12, 0x0b, 0x0a, 0x07, 0x56, 0x45, 0x52, 0x53, 0x49, 0x4f, 0x4e, 0x10, 0x0a, 0x12, 0x0c, 0x0a,
|
||||||
|
0x08, 0x57, 0x41, 0x49, 0x54, 0x5f, 0x50, 0x49, 0x44, 0x10, 0x0b, 0x12, 0x14, 0x0a, 0x10, 0x50,
|
||||||
|
0x41, 0x47, 0x45, 0x5f, 0x53, 0x45, 0x52, 0x56, 0x45, 0x52, 0x5f, 0x43, 0x48, 0x4c, 0x44, 0x10,
|
||||||
|
0x0c,
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
239
vendor/github.com/checkpoint-restore/go-criu/v5/rpc/rpc.proto
generated
vendored
Normal file
239
vendor/github.com/checkpoint-restore/go-criu/v5/rpc/rpc.proto
generated
vendored
Normal file
@ -0,0 +1,239 @@
|
|||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
syntax = "proto2";
|
||||||
|
|
||||||
|
message criu_page_server_info {
|
||||||
|
optional string address = 1;
|
||||||
|
optional int32 port = 2;
|
||||||
|
optional int32 pid = 3;
|
||||||
|
optional int32 fd = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
message criu_veth_pair {
|
||||||
|
required string if_in = 1;
|
||||||
|
required string if_out = 2;
|
||||||
|
};
|
||||||
|
|
||||||
|
message ext_mount_map {
|
||||||
|
required string key = 1;
|
||||||
|
required string val = 2;
|
||||||
|
};
|
||||||
|
|
||||||
|
message join_namespace {
|
||||||
|
required string ns = 1;
|
||||||
|
required string ns_file = 2;
|
||||||
|
optional string extra_opt = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message inherit_fd {
|
||||||
|
required string key = 1;
|
||||||
|
required int32 fd = 2;
|
||||||
|
};
|
||||||
|
|
||||||
|
message cgroup_root {
|
||||||
|
optional string ctrl = 1;
|
||||||
|
required string path = 2;
|
||||||
|
};
|
||||||
|
|
||||||
|
message unix_sk {
|
||||||
|
required uint32 inode = 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum criu_cg_mode {
|
||||||
|
IGNORE = 0;
|
||||||
|
CG_NONE = 1;
|
||||||
|
PROPS = 2;
|
||||||
|
SOFT = 3;
|
||||||
|
FULL = 4;
|
||||||
|
STRICT = 5;
|
||||||
|
DEFAULT = 6;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum criu_pre_dump_mode {
|
||||||
|
SPLICE = 1;
|
||||||
|
VM_READ = 2;
|
||||||
|
};
|
||||||
|
|
||||||
|
message criu_opts {
|
||||||
|
required int32 images_dir_fd = 1;
|
||||||
|
optional int32 pid = 2; /* if not set on dump, will dump requesting process */
|
||||||
|
|
||||||
|
optional bool leave_running = 3;
|
||||||
|
optional bool ext_unix_sk = 4;
|
||||||
|
optional bool tcp_established = 5;
|
||||||
|
optional bool evasive_devices = 6;
|
||||||
|
optional bool shell_job = 7;
|
||||||
|
optional bool file_locks = 8;
|
||||||
|
optional int32 log_level = 9 [default = 2];
|
||||||
|
optional string log_file = 10; /* No subdirs are allowed. Consider using work-dir */
|
||||||
|
|
||||||
|
optional criu_page_server_info ps = 11;
|
||||||
|
|
||||||
|
optional bool notify_scripts = 12;
|
||||||
|
|
||||||
|
optional string root = 13;
|
||||||
|
optional string parent_img = 14;
|
||||||
|
optional bool track_mem = 15;
|
||||||
|
optional bool auto_dedup = 16;
|
||||||
|
|
||||||
|
optional int32 work_dir_fd = 17;
|
||||||
|
optional bool link_remap = 18;
|
||||||
|
repeated criu_veth_pair veths = 19; /* DEPRECATED, use external instead */
|
||||||
|
|
||||||
|
optional uint32 cpu_cap = 20 [default = 0xffffffff];
|
||||||
|
optional bool force_irmap = 21;
|
||||||
|
repeated string exec_cmd = 22;
|
||||||
|
|
||||||
|
repeated ext_mount_map ext_mnt = 23; /* DEPRECATED, use external instead */
|
||||||
|
optional bool manage_cgroups = 24; /* backward compatibility */
|
||||||
|
repeated cgroup_root cg_root = 25;
|
||||||
|
|
||||||
|
optional bool rst_sibling = 26; /* swrk only */
|
||||||
|
repeated inherit_fd inherit_fd = 27; /* swrk only */
|
||||||
|
|
||||||
|
optional bool auto_ext_mnt = 28;
|
||||||
|
optional bool ext_sharing = 29;
|
||||||
|
optional bool ext_masters = 30;
|
||||||
|
|
||||||
|
repeated string skip_mnt = 31;
|
||||||
|
repeated string enable_fs = 32;
|
||||||
|
|
||||||
|
repeated unix_sk unix_sk_ino = 33; /* DEPRECATED, use external instead */
|
||||||
|
|
||||||
|
optional criu_cg_mode manage_cgroups_mode = 34;
|
||||||
|
optional uint32 ghost_limit = 35 [default = 0x100000];
|
||||||
|
repeated string irmap_scan_paths = 36;
|
||||||
|
repeated string external = 37;
|
||||||
|
optional uint32 empty_ns = 38;
|
||||||
|
repeated join_namespace join_ns = 39;
|
||||||
|
|
||||||
|
optional string cgroup_props = 41;
|
||||||
|
optional string cgroup_props_file = 42;
|
||||||
|
repeated string cgroup_dump_controller = 43;
|
||||||
|
|
||||||
|
optional string freeze_cgroup = 44;
|
||||||
|
optional uint32 timeout = 45;
|
||||||
|
optional bool tcp_skip_in_flight = 46;
|
||||||
|
optional bool weak_sysctls = 47;
|
||||||
|
optional bool lazy_pages = 48;
|
||||||
|
optional int32 status_fd = 49;
|
||||||
|
optional bool orphan_pts_master = 50;
|
||||||
|
optional string config_file = 51;
|
||||||
|
optional bool tcp_close = 52;
|
||||||
|
optional string lsm_profile = 53;
|
||||||
|
optional string tls_cacert = 54;
|
||||||
|
optional string tls_cacrl = 55;
|
||||||
|
optional string tls_cert = 56;
|
||||||
|
optional string tls_key = 57;
|
||||||
|
optional bool tls = 58;
|
||||||
|
optional bool tls_no_cn_verify = 59;
|
||||||
|
optional string cgroup_yard = 60;
|
||||||
|
optional criu_pre_dump_mode pre_dump_mode = 61 [default = SPLICE];
|
||||||
|
optional int32 pidfd_store_sk = 62;
|
||||||
|
optional string lsm_mount_context = 63;
|
||||||
|
/* optional bool check_mounts = 128; */
|
||||||
|
}
|
||||||
|
|
||||||
|
message criu_dump_resp {
|
||||||
|
optional bool restored = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message criu_restore_resp {
|
||||||
|
required int32 pid = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message criu_notify {
|
||||||
|
optional string script = 1;
|
||||||
|
optional int32 pid = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum criu_req_type {
|
||||||
|
EMPTY = 0;
|
||||||
|
DUMP = 1;
|
||||||
|
RESTORE = 2;
|
||||||
|
CHECK = 3;
|
||||||
|
PRE_DUMP = 4;
|
||||||
|
PAGE_SERVER = 5;
|
||||||
|
|
||||||
|
NOTIFY = 6;
|
||||||
|
|
||||||
|
CPUINFO_DUMP = 7;
|
||||||
|
CPUINFO_CHECK = 8;
|
||||||
|
|
||||||
|
FEATURE_CHECK = 9;
|
||||||
|
|
||||||
|
VERSION = 10;
|
||||||
|
|
||||||
|
WAIT_PID = 11;
|
||||||
|
PAGE_SERVER_CHLD = 12;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* List of features which can queried via
|
||||||
|
* CRIU_REQ_TYPE__FEATURE_CHECK
|
||||||
|
*/
|
||||||
|
message criu_features {
|
||||||
|
optional bool mem_track = 1;
|
||||||
|
optional bool lazy_pages = 2;
|
||||||
|
optional bool pidfd_store = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Request -- each type corresponds to must-be-there
|
||||||
|
* request arguments of respective type
|
||||||
|
*/
|
||||||
|
|
||||||
|
message criu_req {
|
||||||
|
required criu_req_type type = 1;
|
||||||
|
|
||||||
|
optional criu_opts opts = 2;
|
||||||
|
optional bool notify_success = 3;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* When set service won't close the connection but
|
||||||
|
* will wait for more req-s to appear. Works not
|
||||||
|
* for all request types.
|
||||||
|
*/
|
||||||
|
optional bool keep_open = 4;
|
||||||
|
/*
|
||||||
|
* 'features' can be used to query which features
|
||||||
|
* are supported by the installed criu/kernel
|
||||||
|
* via RPC.
|
||||||
|
*/
|
||||||
|
optional criu_features features = 5;
|
||||||
|
|
||||||
|
/* 'pid' is used for WAIT_PID */
|
||||||
|
optional uint32 pid = 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Response -- it states whether the request was served
|
||||||
|
* and additional request-specific information
|
||||||
|
*/
|
||||||
|
|
||||||
|
message criu_resp {
|
||||||
|
required criu_req_type type = 1;
|
||||||
|
required bool success = 2;
|
||||||
|
|
||||||
|
optional criu_dump_resp dump = 3;
|
||||||
|
optional criu_restore_resp restore = 4;
|
||||||
|
optional criu_notify notify = 5;
|
||||||
|
optional criu_page_server_info ps = 6;
|
||||||
|
|
||||||
|
optional int32 cr_errno = 7;
|
||||||
|
optional criu_features features = 8;
|
||||||
|
optional string cr_errmsg = 9;
|
||||||
|
optional criu_version version = 10;
|
||||||
|
|
||||||
|
optional int32 status = 11;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Answer for criu_req_type.VERSION requests */
|
||||||
|
message criu_version {
|
||||||
|
required int32 major_number = 1;
|
||||||
|
required int32 minor_number = 2;
|
||||||
|
optional string gitid = 3;
|
||||||
|
optional int32 sublevel = 4;
|
||||||
|
optional int32 extra = 5;
|
||||||
|
optional string name = 6;
|
||||||
|
}
|
1
vendor/github.com/cilium/ebpf/.gitignore
generated
vendored
1
vendor/github.com/cilium/ebpf/.gitignore
generated
vendored
@ -5,6 +5,7 @@
|
|||||||
*.so
|
*.so
|
||||||
*.dylib
|
*.dylib
|
||||||
*.o
|
*.o
|
||||||
|
!*_bpf*.o
|
||||||
|
|
||||||
# Test binary, build with `go test -c`
|
# Test binary, build with `go test -c`
|
||||||
*.test
|
*.test
|
||||||
|
1
vendor/github.com/cilium/ebpf/.golangci.yaml
generated
vendored
1
vendor/github.com/cilium/ebpf/.golangci.yaml
generated
vendored
@ -24,6 +24,5 @@ linters:
|
|||||||
|
|
||||||
# Could be enabled later:
|
# Could be enabled later:
|
||||||
# - gocyclo
|
# - gocyclo
|
||||||
# - prealloc
|
|
||||||
# - maligned
|
# - maligned
|
||||||
# - gosec
|
# - gosec
|
||||||
|
4
vendor/github.com/cilium/ebpf/ARCHITECTURE.md
generated
vendored
4
vendor/github.com/cilium/ebpf/ARCHITECTURE.md
generated
vendored
@ -57,7 +57,7 @@ Objects
|
|||||||
loading a spec will fail because the kernel is too old, or a feature is not
|
loading a spec will fail because the kernel is too old, or a feature is not
|
||||||
enabled. There are multiple ways the library deals with that:
|
enabled. There are multiple ways the library deals with that:
|
||||||
|
|
||||||
* Fallback: older kernels don't allowing naming programs and maps. The library
|
* Fallback: older kernels don't allow naming programs and maps. The library
|
||||||
automatically detects support for names, and omits them during load if
|
automatically detects support for names, and omits them during load if
|
||||||
necessary. This works since name is primarily a debug aid.
|
necessary. This works since name is primarily a debug aid.
|
||||||
|
|
||||||
@ -68,7 +68,7 @@ enabled. There are multiple ways the library deals with that:
|
|||||||
Once program and map objects are loaded they expose the kernel's low-level API,
|
Once program and map objects are loaded they expose the kernel's low-level API,
|
||||||
e.g. `NextKey`. Often this API is awkward to use in Go, so there are safer
|
e.g. `NextKey`. Often this API is awkward to use in Go, so there are safer
|
||||||
wrappers on top of the low-level API, like `MapIterator`. The low-level API is
|
wrappers on top of the low-level API, like `MapIterator`. The low-level API is
|
||||||
useful as an out when our higher-level API doesn't support a particular use case.
|
useful when our higher-level API doesn't support a particular use case.
|
||||||
|
|
||||||
Links
|
Links
|
||||||
---
|
---
|
||||||
|
4
vendor/github.com/cilium/ebpf/CONTRIBUTING.md
generated
vendored
4
vendor/github.com/cilium/ebpf/CONTRIBUTING.md
generated
vendored
@ -6,8 +6,8 @@ are welcome. Please take a look at [the architecture](ARCHITECTURE.md) to get
|
|||||||
a better understanding for the high-level goals.
|
a better understanding for the high-level goals.
|
||||||
|
|
||||||
New features must be accompanied by tests. Before starting work on any large
|
New features must be accompanied by tests. Before starting work on any large
|
||||||
feature, please [join](https://cilium.herokuapp.com/) the
|
feature, please [join](https://ebpf.io/slack) the
|
||||||
[#libbpf-go](https://cilium.slack.com/messages/libbpf-go) channel on Slack to
|
[#ebpf-go](https://cilium.slack.com/messages/ebpf-go) channel on Slack to
|
||||||
discuss the design first.
|
discuss the design first.
|
||||||
|
|
||||||
When submitting pull requests, consider writing details about what problem you
|
When submitting pull requests, consider writing details about what problem you
|
||||||
|
5
vendor/github.com/cilium/ebpf/Makefile
generated
vendored
5
vendor/github.com/cilium/ebpf/Makefile
generated
vendored
@ -18,11 +18,14 @@ TARGETS := \
|
|||||||
testdata/loader-clang-7 \
|
testdata/loader-clang-7 \
|
||||||
testdata/loader-clang-9 \
|
testdata/loader-clang-9 \
|
||||||
testdata/loader-$(CLANG) \
|
testdata/loader-$(CLANG) \
|
||||||
|
testdata/btf_map_init \
|
||||||
testdata/invalid_map \
|
testdata/invalid_map \
|
||||||
testdata/raw_tracepoint \
|
testdata/raw_tracepoint \
|
||||||
testdata/invalid_map_static \
|
testdata/invalid_map_static \
|
||||||
testdata/initialized_btf_map \
|
testdata/invalid_btf_map_init \
|
||||||
testdata/strings \
|
testdata/strings \
|
||||||
|
testdata/freplace \
|
||||||
|
testdata/iproute2_map_compat \
|
||||||
internal/btf/testdata/relocs
|
internal/btf/testdata/relocs
|
||||||
|
|
||||||
.PHONY: all clean docker-all docker-shell
|
.PHONY: all clean docker-all docker-shell
|
||||||
|
62
vendor/github.com/cilium/ebpf/README.md
generated
vendored
62
vendor/github.com/cilium/ebpf/README.md
generated
vendored
@ -2,28 +2,16 @@
|
|||||||
|
|
||||||
[](https://pkg.go.dev/github.com/cilium/ebpf)
|
[](https://pkg.go.dev/github.com/cilium/ebpf)
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
eBPF is a pure Go library that provides utilities for loading, compiling, and
|
eBPF is a pure Go library that provides utilities for loading, compiling, and
|
||||||
debugging eBPF programs. It has minimal external dependencies and is intended to
|
debugging eBPF programs. It has minimal external dependencies and is intended to
|
||||||
be used in long running processes.
|
be used in long running processes.
|
||||||
|
|
||||||
* [asm](https://pkg.go.dev/github.com/cilium/ebpf/asm) contains a basic
|
|
||||||
assembler
|
|
||||||
* [link](https://pkg.go.dev/github.com/cilium/ebpf/link) allows attaching eBPF
|
|
||||||
to various hooks
|
|
||||||
* [perf](https://pkg.go.dev/github.com/cilium/ebpf/perf) allows reading from a
|
|
||||||
`PERF_EVENT_ARRAY`
|
|
||||||
* [cmd/bpf2go](https://pkg.go.dev/github.com/cilium/ebpf/cmd/bpf2go) allows
|
|
||||||
compiling and embedding eBPF programs in Go code
|
|
||||||
|
|
||||||
The library is maintained by [Cloudflare](https://www.cloudflare.com) and
|
The library is maintained by [Cloudflare](https://www.cloudflare.com) and
|
||||||
[Cilium](https://www.cilium.io). Feel free to
|
[Cilium](https://www.cilium.io).
|
||||||
[join](https://cilium.herokuapp.com/) the
|
|
||||||
[#libbpf-go](https://cilium.slack.com/messages/libbpf-go) channel on Slack.
|
|
||||||
|
|
||||||
## Current status
|
See [ebpf.io](https://ebpf.io) for other projects from the eBPF ecosystem.
|
||||||
|
|
||||||
The package is production ready, but **the API is explicitly unstable right
|
|
||||||
now**. Expect to update your code if you want to follow along.
|
|
||||||
|
|
||||||
## Getting Started
|
## Getting Started
|
||||||
|
|
||||||
@ -33,21 +21,37 @@ your own tools can be found under [examples/](examples/).
|
|||||||
Contributions are highly encouraged, as they highlight certain use cases of
|
Contributions are highly encouraged, as they highlight certain use cases of
|
||||||
eBPF and the library, and help shape the future of the project.
|
eBPF and the library, and help shape the future of the project.
|
||||||
|
|
||||||
|
## Getting Help
|
||||||
|
|
||||||
|
Please
|
||||||
|
[join](https://ebpf.io/slack) the
|
||||||
|
[#ebpf-go](https://cilium.slack.com/messages/ebpf-go) channel on Slack if you
|
||||||
|
have questions regarding the library.
|
||||||
|
|
||||||
|
## Packages
|
||||||
|
|
||||||
|
This library includes the following packages:
|
||||||
|
|
||||||
|
* [asm](https://pkg.go.dev/github.com/cilium/ebpf/asm) contains a basic
|
||||||
|
assembler, allowing you to write eBPF assembly instructions directly
|
||||||
|
within your Go code. (You don't need to use this if you prefer to write your eBPF program in C.)
|
||||||
|
* [cmd/bpf2go](https://pkg.go.dev/github.com/cilium/ebpf/cmd/bpf2go) allows
|
||||||
|
compiling and embedding eBPF programs written in C within Go code. As well as
|
||||||
|
compiling the C code, it auto-generates Go code for loading and manipulating
|
||||||
|
the eBPF program and map objects.
|
||||||
|
* [link](https://pkg.go.dev/github.com/cilium/ebpf/link) allows attaching eBPF
|
||||||
|
to various hooks
|
||||||
|
* [perf](https://pkg.go.dev/github.com/cilium/ebpf/perf) allows reading from a
|
||||||
|
`PERF_EVENT_ARRAY`
|
||||||
|
* [ringbuf](https://pkg.go.dev/github.com/cilium/ebpf/ringbuf) allows reading from a
|
||||||
|
`BPF_MAP_TYPE_RINGBUF` map
|
||||||
|
|
||||||
|
|
||||||
## Requirements
|
## Requirements
|
||||||
|
|
||||||
* A version of Go that is [supported by
|
* A version of Go that is [supported by
|
||||||
upstream](https://golang.org/doc/devel/release.html#policy)
|
upstream](https://golang.org/doc/devel/release.html#policy)
|
||||||
* Linux 4.9, 4.19 or 5.4 (versions in-between should work, but are not tested)
|
* Linux >= 4.9. CI is run against LTS releases.
|
||||||
|
|
||||||
## Useful resources
|
|
||||||
|
|
||||||
* [eBPF.io](https://ebpf.io) (recommended)
|
|
||||||
* [Cilium eBPF documentation](https://docs.cilium.io/en/latest/bpf/#bpf-guide)
|
|
||||||
(recommended)
|
|
||||||
* [Linux documentation on
|
|
||||||
BPF](https://www.kernel.org/doc/html/latest/networking/filter.html)
|
|
||||||
* [eBPF features by Linux
|
|
||||||
version](https://github.com/iovisor/bcc/blob/master/docs/kernel-versions.md)
|
|
||||||
|
|
||||||
## Regenerating Testdata
|
## Regenerating Testdata
|
||||||
|
|
||||||
@ -60,3 +64,7 @@ The toolchain image build files are kept in [testdata/docker/](testdata/docker/)
|
|||||||
## License
|
## License
|
||||||
|
|
||||||
MIT
|
MIT
|
||||||
|
|
||||||
|
### eBPF Gopher
|
||||||
|
|
||||||
|
The eBPF honeygopher is based on the Go gopher designed by Renee French.
|
||||||
|
6
vendor/github.com/cilium/ebpf/asm/func.go
generated
vendored
6
vendor/github.com/cilium/ebpf/asm/func.go
generated
vendored
@ -184,6 +184,12 @@ const (
|
|||||||
FnKtimeGetCoarseNs
|
FnKtimeGetCoarseNs
|
||||||
FnImaInodeHash
|
FnImaInodeHash
|
||||||
FnSockFromFile
|
FnSockFromFile
|
||||||
|
FnCheckMtu
|
||||||
|
FnForEachMapElem
|
||||||
|
FnSnprintf
|
||||||
|
FnSysBpf
|
||||||
|
FnBtfFindByNameKind
|
||||||
|
FnSysClose
|
||||||
)
|
)
|
||||||
|
|
||||||
// Call emits a function call.
|
// Call emits a function call.
|
||||||
|
10
vendor/github.com/cilium/ebpf/asm/func_string.go
generated
vendored
10
vendor/github.com/cilium/ebpf/asm/func_string.go
generated
vendored
@ -171,11 +171,17 @@ func _() {
|
|||||||
_ = x[FnKtimeGetCoarseNs-160]
|
_ = x[FnKtimeGetCoarseNs-160]
|
||||||
_ = x[FnImaInodeHash-161]
|
_ = x[FnImaInodeHash-161]
|
||||||
_ = x[FnSockFromFile-162]
|
_ = x[FnSockFromFile-162]
|
||||||
|
_ = x[FnCheckMtu-163]
|
||||||
|
_ = x[FnForEachMapElem-164]
|
||||||
|
_ = x[FnSnprintf-165]
|
||||||
|
_ = x[FnSysBpf-166]
|
||||||
|
_ = x[FnBtfFindByNameKind-167]
|
||||||
|
_ = x[FnSysClose-168]
|
||||||
}
|
}
|
||||||
|
|
||||||
const _BuiltinFunc_name = "FnUnspecFnMapLookupElemFnMapUpdateElemFnMapDeleteElemFnProbeReadFnKtimeGetNsFnTracePrintkFnGetPrandomU32FnGetSmpProcessorIdFnSkbStoreBytesFnL3CsumReplaceFnL4CsumReplaceFnTailCallFnCloneRedirectFnGetCurrentPidTgidFnGetCurrentUidGidFnGetCurrentCommFnGetCgroupClassidFnSkbVlanPushFnSkbVlanPopFnSkbGetTunnelKeyFnSkbSetTunnelKeyFnPerfEventReadFnRedirectFnGetRouteRealmFnPerfEventOutputFnSkbLoadBytesFnGetStackidFnCsumDiffFnSkbGetTunnelOptFnSkbSetTunnelOptFnSkbChangeProtoFnSkbChangeTypeFnSkbUnderCgroupFnGetHashRecalcFnGetCurrentTaskFnProbeWriteUserFnCurrentTaskUnderCgroupFnSkbChangeTailFnSkbPullDataFnCsumUpdateFnSetHashInvalidFnGetNumaNodeIdFnSkbChangeHeadFnXdpAdjustHeadFnProbeReadStrFnGetSocketCookieFnGetSocketUidFnSetHashFnSetsockoptFnSkbAdjustRoomFnRedirectMapFnSkRedirectMapFnSockMapUpdateFnXdpAdjustMetaFnPerfEventReadValueFnPerfProgReadValueFnGetsockoptFnOverrideReturnFnSockOpsCbFlagsSetFnMsgRedirectMapFnMsgApplyBytesFnMsgCorkBytesFnMsgPullDataFnBindFnXdpAdjustTailFnSkbGetXfrmStateFnGetStackFnSkbLoadBytesRelativeFnFibLookupFnSockHashUpdateFnMsgRedirectHashFnSkRedirectHashFnLwtPushEncapFnLwtSeg6StoreBytesFnLwtSeg6AdjustSrhFnLwtSeg6ActionFnRcRepeatFnRcKeydownFnSkbCgroupIdFnGetCurrentCgroupIdFnGetLocalStorageFnSkSelectReuseportFnSkbAncestorCgroupIdFnSkLookupTcpFnSkLookupUdpFnSkReleaseFnMapPushElemFnMapPopElemFnMapPeekElemFnMsgPushDataFnMsgPopDataFnRcPointerRelFnSpinLockFnSpinUnlockFnSkFullsockFnTcpSockFnSkbEcnSetCeFnGetListenerSockFnSkcLookupTcpFnTcpCheckSyncookieFnSysctlGetNameFnSysctlGetCurrentValueFnSysctlGetNewValueFnSysctlSetNewValueFnStrtolFnStrtoulFnSkStorageGetFnSkStorageDeleteFnSendSignalFnTcpGenSyncookieFnSkbOutputFnProbeReadUserFnProbeReadKernelFnProbeReadUserStrFnProbeReadKernelStrFnTcpSendAckFnSendSignalThreadFnJiffies64FnReadBranchRecordsFnGetNsCurrentPidTgidFnXdpOutputFnGetNetnsCookieFnGetCurrentAncestorCgroupIdFnSkAssignFnKtimeGetBootNsFnSeqPrintfFnSeqWriteFnSkCgroupIdFnSkAncestorCgroupIdFnRingbufOutputFnRingbufReserveFnRingbufSubmitFnRingbufDiscardFnRingbufQueryFnCsumLevelFnSkcToTcp6SockFnSkcToTcpSockFnSkcToTcpTimewaitSockFnSkcToTcpRequestSockFnSkcToUdp6SockFnGetTaskStackFnLoadHdrOptFnStoreHdrOptFnReserveHdrOptFnInodeStorageGetFnInodeStorageDeleteFnDPathFnCopyFromUserFnSnprintfBtfFnSeqPrintfBtfFnSkbCgroupClassidFnRedirectNeighFnPerCpuPtrFnThisCpuPtrFnRedirectPeerFnTaskStorageGetFnTaskStorageDeleteFnGetCurrentTaskBtfFnBprmOptsSetFnKtimeGetCoarseNsFnImaInodeHashFnSockFromFile"
|
const _BuiltinFunc_name = "FnUnspecFnMapLookupElemFnMapUpdateElemFnMapDeleteElemFnProbeReadFnKtimeGetNsFnTracePrintkFnGetPrandomU32FnGetSmpProcessorIdFnSkbStoreBytesFnL3CsumReplaceFnL4CsumReplaceFnTailCallFnCloneRedirectFnGetCurrentPidTgidFnGetCurrentUidGidFnGetCurrentCommFnGetCgroupClassidFnSkbVlanPushFnSkbVlanPopFnSkbGetTunnelKeyFnSkbSetTunnelKeyFnPerfEventReadFnRedirectFnGetRouteRealmFnPerfEventOutputFnSkbLoadBytesFnGetStackidFnCsumDiffFnSkbGetTunnelOptFnSkbSetTunnelOptFnSkbChangeProtoFnSkbChangeTypeFnSkbUnderCgroupFnGetHashRecalcFnGetCurrentTaskFnProbeWriteUserFnCurrentTaskUnderCgroupFnSkbChangeTailFnSkbPullDataFnCsumUpdateFnSetHashInvalidFnGetNumaNodeIdFnSkbChangeHeadFnXdpAdjustHeadFnProbeReadStrFnGetSocketCookieFnGetSocketUidFnSetHashFnSetsockoptFnSkbAdjustRoomFnRedirectMapFnSkRedirectMapFnSockMapUpdateFnXdpAdjustMetaFnPerfEventReadValueFnPerfProgReadValueFnGetsockoptFnOverrideReturnFnSockOpsCbFlagsSetFnMsgRedirectMapFnMsgApplyBytesFnMsgCorkBytesFnMsgPullDataFnBindFnXdpAdjustTailFnSkbGetXfrmStateFnGetStackFnSkbLoadBytesRelativeFnFibLookupFnSockHashUpdateFnMsgRedirectHashFnSkRedirectHashFnLwtPushEncapFnLwtSeg6StoreBytesFnLwtSeg6AdjustSrhFnLwtSeg6ActionFnRcRepeatFnRcKeydownFnSkbCgroupIdFnGetCurrentCgroupIdFnGetLocalStorageFnSkSelectReuseportFnSkbAncestorCgroupIdFnSkLookupTcpFnSkLookupUdpFnSkReleaseFnMapPushElemFnMapPopElemFnMapPeekElemFnMsgPushDataFnMsgPopDataFnRcPointerRelFnSpinLockFnSpinUnlockFnSkFullsockFnTcpSockFnSkbEcnSetCeFnGetListenerSockFnSkcLookupTcpFnTcpCheckSyncookieFnSysctlGetNameFnSysctlGetCurrentValueFnSysctlGetNewValueFnSysctlSetNewValueFnStrtolFnStrtoulFnSkStorageGetFnSkStorageDeleteFnSendSignalFnTcpGenSyncookieFnSkbOutputFnProbeReadUserFnProbeReadKernelFnProbeReadUserStrFnProbeReadKernelStrFnTcpSendAckFnSendSignalThreadFnJiffies64FnReadBranchRecordsFnGetNsCurrentPidTgidFnXdpOutputFnGetNetnsCookieFnGetCurrentAncestorCgroupIdFnSkAssignFnKtimeGetBootNsFnSeqPrintfFnSeqWriteFnSkCgroupIdFnSkAncestorCgroupIdFnRingbufOutputFnRingbufReserveFnRingbufSubmitFnRingbufDiscardFnRingbufQueryFnCsumLevelFnSkcToTcp6SockFnSkcToTcpSockFnSkcToTcpTimewaitSockFnSkcToTcpRequestSockFnSkcToUdp6SockFnGetTaskStackFnLoadHdrOptFnStoreHdrOptFnReserveHdrOptFnInodeStorageGetFnInodeStorageDeleteFnDPathFnCopyFromUserFnSnprintfBtfFnSeqPrintfBtfFnSkbCgroupClassidFnRedirectNeighFnPerCpuPtrFnThisCpuPtrFnRedirectPeerFnTaskStorageGetFnTaskStorageDeleteFnGetCurrentTaskBtfFnBprmOptsSetFnKtimeGetCoarseNsFnImaInodeHashFnSockFromFileFnCheckMtuFnForEachMapElemFnSnprintfFnSysBpfFnBtfFindByNameKindFnSysClose"
|
||||||
|
|
||||||
var _BuiltinFunc_index = [...]uint16{0, 8, 23, 38, 53, 64, 76, 89, 104, 123, 138, 153, 168, 178, 193, 212, 230, 246, 264, 277, 289, 306, 323, 338, 348, 363, 380, 394, 406, 416, 433, 450, 466, 481, 497, 512, 528, 544, 568, 583, 596, 608, 624, 639, 654, 669, 683, 700, 714, 723, 735, 750, 763, 778, 793, 808, 828, 847, 859, 875, 894, 910, 925, 939, 952, 958, 973, 990, 1000, 1022, 1033, 1049, 1066, 1082, 1096, 1115, 1133, 1148, 1158, 1169, 1182, 1202, 1219, 1238, 1259, 1272, 1285, 1296, 1309, 1321, 1334, 1347, 1359, 1373, 1383, 1395, 1407, 1416, 1429, 1446, 1460, 1479, 1494, 1517, 1536, 1555, 1563, 1572, 1586, 1603, 1615, 1632, 1643, 1658, 1675, 1693, 1713, 1725, 1743, 1754, 1773, 1794, 1805, 1821, 1849, 1859, 1875, 1886, 1896, 1908, 1928, 1943, 1959, 1974, 1990, 2004, 2015, 2030, 2044, 2066, 2087, 2102, 2116, 2128, 2141, 2156, 2173, 2193, 2200, 2214, 2227, 2241, 2259, 2274, 2285, 2297, 2311, 2327, 2346, 2365, 2378, 2396, 2410, 2424}
|
var _BuiltinFunc_index = [...]uint16{0, 8, 23, 38, 53, 64, 76, 89, 104, 123, 138, 153, 168, 178, 193, 212, 230, 246, 264, 277, 289, 306, 323, 338, 348, 363, 380, 394, 406, 416, 433, 450, 466, 481, 497, 512, 528, 544, 568, 583, 596, 608, 624, 639, 654, 669, 683, 700, 714, 723, 735, 750, 763, 778, 793, 808, 828, 847, 859, 875, 894, 910, 925, 939, 952, 958, 973, 990, 1000, 1022, 1033, 1049, 1066, 1082, 1096, 1115, 1133, 1148, 1158, 1169, 1182, 1202, 1219, 1238, 1259, 1272, 1285, 1296, 1309, 1321, 1334, 1347, 1359, 1373, 1383, 1395, 1407, 1416, 1429, 1446, 1460, 1479, 1494, 1517, 1536, 1555, 1563, 1572, 1586, 1603, 1615, 1632, 1643, 1658, 1675, 1693, 1713, 1725, 1743, 1754, 1773, 1794, 1805, 1821, 1849, 1859, 1875, 1886, 1896, 1908, 1928, 1943, 1959, 1974, 1990, 2004, 2015, 2030, 2044, 2066, 2087, 2102, 2116, 2128, 2141, 2156, 2173, 2193, 2200, 2214, 2227, 2241, 2259, 2274, 2285, 2297, 2311, 2327, 2346, 2365, 2378, 2396, 2410, 2424, 2434, 2450, 2460, 2468, 2487, 2497}
|
||||||
|
|
||||||
func (i BuiltinFunc) String() string {
|
func (i BuiltinFunc) String() string {
|
||||||
if i < 0 || i >= BuiltinFunc(len(_BuiltinFunc_index)-1) {
|
if i < 0 || i >= BuiltinFunc(len(_BuiltinFunc_index)-1) {
|
||||||
|
5
vendor/github.com/cilium/ebpf/asm/instruction.go
generated
vendored
5
vendor/github.com/cilium/ebpf/asm/instruction.go
generated
vendored
@ -181,6 +181,11 @@ func (ins *Instruction) IsFunctionCall() bool {
|
|||||||
return ins.OpCode.JumpOp() == Call && ins.Src == PseudoCall
|
return ins.OpCode.JumpOp() == Call && ins.Src == PseudoCall
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IsBuiltinCall returns true if the instruction is a built-in call, i.e. BPF helper call.
|
||||||
|
func (ins *Instruction) IsBuiltinCall() bool {
|
||||||
|
return ins.OpCode.JumpOp() == Call && ins.Src == R0 && ins.Dst == R0
|
||||||
|
}
|
||||||
|
|
||||||
// IsConstantLoad returns true if the instruction loads a constant of the
|
// IsConstantLoad returns true if the instruction loads a constant of the
|
||||||
// given size.
|
// given size.
|
||||||
func (ins *Instruction) IsConstantLoad(size Size) bool {
|
func (ins *Instruction) IsConstantLoad(size Size) bool {
|
||||||
|
65
vendor/github.com/cilium/ebpf/attachtype_string.go
generated
vendored
Normal file
65
vendor/github.com/cilium/ebpf/attachtype_string.go
generated
vendored
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
// Code generated by "stringer -type AttachType -trimprefix Attach"; DO NOT EDIT.
|
||||||
|
|
||||||
|
package ebpf
|
||||||
|
|
||||||
|
import "strconv"
|
||||||
|
|
||||||
|
func _() {
|
||||||
|
// An "invalid array index" compiler error signifies that the constant values have changed.
|
||||||
|
// Re-run the stringer command to generate them again.
|
||||||
|
var x [1]struct{}
|
||||||
|
_ = x[AttachNone-0]
|
||||||
|
_ = x[AttachCGroupInetIngress-0]
|
||||||
|
_ = x[AttachCGroupInetEgress-1]
|
||||||
|
_ = x[AttachCGroupInetSockCreate-2]
|
||||||
|
_ = x[AttachCGroupSockOps-3]
|
||||||
|
_ = x[AttachSkSKBStreamParser-4]
|
||||||
|
_ = x[AttachSkSKBStreamVerdict-5]
|
||||||
|
_ = x[AttachCGroupDevice-6]
|
||||||
|
_ = x[AttachSkMsgVerdict-7]
|
||||||
|
_ = x[AttachCGroupInet4Bind-8]
|
||||||
|
_ = x[AttachCGroupInet6Bind-9]
|
||||||
|
_ = x[AttachCGroupInet4Connect-10]
|
||||||
|
_ = x[AttachCGroupInet6Connect-11]
|
||||||
|
_ = x[AttachCGroupInet4PostBind-12]
|
||||||
|
_ = x[AttachCGroupInet6PostBind-13]
|
||||||
|
_ = x[AttachCGroupUDP4Sendmsg-14]
|
||||||
|
_ = x[AttachCGroupUDP6Sendmsg-15]
|
||||||
|
_ = x[AttachLircMode2-16]
|
||||||
|
_ = x[AttachFlowDissector-17]
|
||||||
|
_ = x[AttachCGroupSysctl-18]
|
||||||
|
_ = x[AttachCGroupUDP4Recvmsg-19]
|
||||||
|
_ = x[AttachCGroupUDP6Recvmsg-20]
|
||||||
|
_ = x[AttachCGroupGetsockopt-21]
|
||||||
|
_ = x[AttachCGroupSetsockopt-22]
|
||||||
|
_ = x[AttachTraceRawTp-23]
|
||||||
|
_ = x[AttachTraceFEntry-24]
|
||||||
|
_ = x[AttachTraceFExit-25]
|
||||||
|
_ = x[AttachModifyReturn-26]
|
||||||
|
_ = x[AttachLSMMac-27]
|
||||||
|
_ = x[AttachTraceIter-28]
|
||||||
|
_ = x[AttachCgroupInet4GetPeername-29]
|
||||||
|
_ = x[AttachCgroupInet6GetPeername-30]
|
||||||
|
_ = x[AttachCgroupInet4GetSockname-31]
|
||||||
|
_ = x[AttachCgroupInet6GetSockname-32]
|
||||||
|
_ = x[AttachXDPDevMap-33]
|
||||||
|
_ = x[AttachCgroupInetSockRelease-34]
|
||||||
|
_ = x[AttachXDPCPUMap-35]
|
||||||
|
_ = x[AttachSkLookup-36]
|
||||||
|
_ = x[AttachXDP-37]
|
||||||
|
_ = x[AttachSkSKBVerdict-38]
|
||||||
|
_ = x[AttachSkReuseportSelect-39]
|
||||||
|
_ = x[AttachSkReuseportSelectOrMigrate-40]
|
||||||
|
_ = x[AttachPerfEvent-41]
|
||||||
|
}
|
||||||
|
|
||||||
|
const _AttachType_name = "NoneCGroupInetEgressCGroupInetSockCreateCGroupSockOpsSkSKBStreamParserSkSKBStreamVerdictCGroupDeviceSkMsgVerdictCGroupInet4BindCGroupInet6BindCGroupInet4ConnectCGroupInet6ConnectCGroupInet4PostBindCGroupInet6PostBindCGroupUDP4SendmsgCGroupUDP6SendmsgLircMode2FlowDissectorCGroupSysctlCGroupUDP4RecvmsgCGroupUDP6RecvmsgCGroupGetsockoptCGroupSetsockoptTraceRawTpTraceFEntryTraceFExitModifyReturnLSMMacTraceIterCgroupInet4GetPeernameCgroupInet6GetPeernameCgroupInet4GetSocknameCgroupInet6GetSocknameXDPDevMapCgroupInetSockReleaseXDPCPUMapSkLookupXDPSkSKBVerdictSkReuseportSelectSkReuseportSelectOrMigratePerfEvent"
|
||||||
|
|
||||||
|
var _AttachType_index = [...]uint16{0, 4, 20, 40, 53, 70, 88, 100, 112, 127, 142, 160, 178, 197, 216, 233, 250, 259, 272, 284, 301, 318, 334, 350, 360, 371, 381, 393, 399, 408, 430, 452, 474, 496, 505, 526, 535, 543, 546, 558, 575, 601, 610}
|
||||||
|
|
||||||
|
func (i AttachType) String() string {
|
||||||
|
if i >= AttachType(len(_AttachType_index)-1) {
|
||||||
|
return "AttachType(" + strconv.FormatInt(int64(i), 10) + ")"
|
||||||
|
}
|
||||||
|
return _AttachType_name[_AttachType_index[i]:_AttachType_index[i+1]]
|
||||||
|
}
|
532
vendor/github.com/cilium/ebpf/collection.go
generated
vendored
532
vendor/github.com/cilium/ebpf/collection.go
generated
vendored
@ -1,6 +1,7 @@
|
|||||||
package ebpf
|
package ebpf
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/binary"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
@ -25,6 +26,10 @@ type CollectionOptions struct {
|
|||||||
type CollectionSpec struct {
|
type CollectionSpec struct {
|
||||||
Maps map[string]*MapSpec
|
Maps map[string]*MapSpec
|
||||||
Programs map[string]*ProgramSpec
|
Programs map[string]*ProgramSpec
|
||||||
|
|
||||||
|
// ByteOrder specifies whether the ELF was compiled for
|
||||||
|
// big-endian or little-endian architectures.
|
||||||
|
ByteOrder binary.ByteOrder
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy returns a recursive copy of the spec.
|
// Copy returns a recursive copy of the spec.
|
||||||
@ -34,8 +39,9 @@ func (cs *CollectionSpec) Copy() *CollectionSpec {
|
|||||||
}
|
}
|
||||||
|
|
||||||
cpy := CollectionSpec{
|
cpy := CollectionSpec{
|
||||||
Maps: make(map[string]*MapSpec, len(cs.Maps)),
|
Maps: make(map[string]*MapSpec, len(cs.Maps)),
|
||||||
Programs: make(map[string]*ProgramSpec, len(cs.Programs)),
|
Programs: make(map[string]*ProgramSpec, len(cs.Programs)),
|
||||||
|
ByteOrder: cs.ByteOrder,
|
||||||
}
|
}
|
||||||
|
|
||||||
for name, spec := range cs.Maps {
|
for name, spec := range cs.Maps {
|
||||||
@ -123,7 +129,7 @@ func (cs *CollectionSpec) RewriteConstants(consts map[string]interface{}) error
|
|||||||
buf := make([]byte, len(value))
|
buf := make([]byte, len(value))
|
||||||
copy(buf, value)
|
copy(buf, value)
|
||||||
|
|
||||||
err := patchValue(buf, btf.MapValue(rodata.BTF), consts)
|
err := patchValue(buf, rodata.BTF.Value, consts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -134,15 +140,15 @@ func (cs *CollectionSpec) RewriteConstants(consts map[string]interface{}) error
|
|||||||
|
|
||||||
// Assign the contents of a CollectionSpec to a struct.
|
// Assign the contents of a CollectionSpec to a struct.
|
||||||
//
|
//
|
||||||
// This function is a short-cut to manually checking the presence
|
// This function is a shortcut to manually checking the presence
|
||||||
// of maps and programs in a collection spec. Consider using bpf2go if this
|
// of maps and programs in a CollectionSpec. Consider using bpf2go
|
||||||
// sounds useful.
|
// if this sounds useful.
|
||||||
//
|
//
|
||||||
// The argument to must be a pointer to a struct. A field of the
|
// 'to' must be a pointer to a struct. A field of the
|
||||||
// struct is updated with values from Programs or Maps if it
|
// struct is updated with values from Programs or Maps if it
|
||||||
// has an `ebpf` tag and its type is *ProgramSpec or *MapSpec.
|
// has an `ebpf` tag and its type is *ProgramSpec or *MapSpec.
|
||||||
// The tag gives the name of the program or map as found in
|
// The tag's value specifies the name of the program or map as
|
||||||
// the CollectionSpec.
|
// found in the CollectionSpec.
|
||||||
//
|
//
|
||||||
// struct {
|
// struct {
|
||||||
// Foo *ebpf.ProgramSpec `ebpf:"xdp_foo"`
|
// Foo *ebpf.ProgramSpec `ebpf:"xdp_foo"`
|
||||||
@ -150,42 +156,47 @@ func (cs *CollectionSpec) RewriteConstants(consts map[string]interface{}) error
|
|||||||
// Ignored int
|
// Ignored int
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// Returns an error if any of the fields can't be found, or
|
// Returns an error if any of the eBPF objects can't be found, or
|
||||||
// if the same map or program is assigned multiple times.
|
// if the same MapSpec or ProgramSpec is assigned multiple times.
|
||||||
func (cs *CollectionSpec) Assign(to interface{}) error {
|
func (cs *CollectionSpec) Assign(to interface{}) error {
|
||||||
valueOf := func(typ reflect.Type, name string) (reflect.Value, error) {
|
// Assign() only supports assigning ProgramSpecs and MapSpecs,
|
||||||
|
// so doesn't load any resources into the kernel.
|
||||||
|
getValue := func(typ reflect.Type, name string) (interface{}, error) {
|
||||||
switch typ {
|
switch typ {
|
||||||
|
|
||||||
case reflect.TypeOf((*ProgramSpec)(nil)):
|
case reflect.TypeOf((*ProgramSpec)(nil)):
|
||||||
p := cs.Programs[name]
|
if p := cs.Programs[name]; p != nil {
|
||||||
if p == nil {
|
return p, nil
|
||||||
return reflect.Value{}, fmt.Errorf("missing program %q", name)
|
|
||||||
}
|
}
|
||||||
return reflect.ValueOf(p), nil
|
return nil, fmt.Errorf("missing program %q", name)
|
||||||
|
|
||||||
case reflect.TypeOf((*MapSpec)(nil)):
|
case reflect.TypeOf((*MapSpec)(nil)):
|
||||||
m := cs.Maps[name]
|
if m := cs.Maps[name]; m != nil {
|
||||||
if m == nil {
|
return m, nil
|
||||||
return reflect.Value{}, fmt.Errorf("missing map %q", name)
|
|
||||||
}
|
}
|
||||||
return reflect.ValueOf(m), nil
|
return nil, fmt.Errorf("missing map %q", name)
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return reflect.Value{}, fmt.Errorf("unsupported type %s", typ)
|
return nil, fmt.Errorf("unsupported type %s", typ)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return assignValues(to, valueOf)
|
return assignValues(to, getValue)
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoadAndAssign maps and programs into the kernel and assign them to a struct.
|
// LoadAndAssign loads Maps and Programs into the kernel and assigns them
|
||||||
|
// to a struct.
|
||||||
//
|
//
|
||||||
// This function is a short-cut to manually checking the presence
|
// This function is a shortcut to manually checking the presence
|
||||||
// of maps and programs in a collection spec. Consider using bpf2go if this
|
// of maps and programs in a CollectionSpec. Consider using bpf2go
|
||||||
// sounds useful.
|
// if this sounds useful.
|
||||||
//
|
//
|
||||||
// The argument to must be a pointer to a struct. A field of the
|
// 'to' must be a pointer to a struct. A field of the struct is updated with
|
||||||
// struct is updated with values from Programs or Maps if it
|
// a Program or Map if it has an `ebpf` tag and its type is *Program or *Map.
|
||||||
// has an `ebpf` tag and its type is *Program or *Map.
|
// The tag's value specifies the name of the program or map as found in the
|
||||||
// The tag gives the name of the program or map as found in
|
// CollectionSpec. Before updating the struct, the requested objects and their
|
||||||
// the CollectionSpec.
|
// dependent resources are loaded into the kernel and populated with values if
|
||||||
|
// specified.
|
||||||
//
|
//
|
||||||
// struct {
|
// struct {
|
||||||
// Foo *ebpf.Program `ebpf:"xdp_foo"`
|
// Foo *ebpf.Program `ebpf:"xdp_foo"`
|
||||||
@ -196,39 +207,53 @@ func (cs *CollectionSpec) Assign(to interface{}) error {
|
|||||||
// opts may be nil.
|
// opts may be nil.
|
||||||
//
|
//
|
||||||
// Returns an error if any of the fields can't be found, or
|
// Returns an error if any of the fields can't be found, or
|
||||||
// if the same map or program is assigned multiple times.
|
// if the same Map or Program is assigned multiple times.
|
||||||
func (cs *CollectionSpec) LoadAndAssign(to interface{}, opts *CollectionOptions) error {
|
func (cs *CollectionSpec) LoadAndAssign(to interface{}, opts *CollectionOptions) error {
|
||||||
if opts == nil {
|
loader := newCollectionLoader(cs, opts)
|
||||||
opts = &CollectionOptions{}
|
defer loader.cleanup()
|
||||||
}
|
|
||||||
|
|
||||||
loadMap, loadProgram, done, cleanup := lazyLoadCollection(cs, opts)
|
// Support assigning Programs and Maps, lazy-loading the required objects.
|
||||||
defer cleanup()
|
assignedMaps := make(map[string]bool)
|
||||||
|
getValue := func(typ reflect.Type, name string) (interface{}, error) {
|
||||||
valueOf := func(typ reflect.Type, name string) (reflect.Value, error) {
|
|
||||||
switch typ {
|
switch typ {
|
||||||
|
|
||||||
case reflect.TypeOf((*Program)(nil)):
|
case reflect.TypeOf((*Program)(nil)):
|
||||||
p, err := loadProgram(name)
|
return loader.loadProgram(name)
|
||||||
if err != nil {
|
|
||||||
return reflect.Value{}, err
|
|
||||||
}
|
|
||||||
return reflect.ValueOf(p), nil
|
|
||||||
case reflect.TypeOf((*Map)(nil)):
|
case reflect.TypeOf((*Map)(nil)):
|
||||||
m, err := loadMap(name)
|
assignedMaps[name] = true
|
||||||
if err != nil {
|
return loader.loadMap(name)
|
||||||
return reflect.Value{}, err
|
|
||||||
}
|
|
||||||
return reflect.ValueOf(m), nil
|
|
||||||
default:
|
default:
|
||||||
return reflect.Value{}, fmt.Errorf("unsupported type %s", typ)
|
return nil, fmt.Errorf("unsupported type %s", typ)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := assignValues(to, valueOf); err != nil {
|
// Load the Maps and Programs requested by the annotated struct.
|
||||||
|
if err := assignValues(to, getValue); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
done()
|
// Populate the requested maps. Has a chance of lazy-loading other dependent maps.
|
||||||
|
if err := loader.populateMaps(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Evaluate the loader's objects after all (lazy)loading has taken place.
|
||||||
|
for n, m := range loader.maps {
|
||||||
|
switch m.typ {
|
||||||
|
case ProgramArray:
|
||||||
|
// Require all lazy-loaded ProgramArrays to be assigned to the given object.
|
||||||
|
// Without any references, they will be closed on the first GC and all tail
|
||||||
|
// calls into them will miss.
|
||||||
|
if !assignedMaps[n] {
|
||||||
|
return fmt.Errorf("ProgramArray %s must be assigned to prevent missed tail calls", n)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
loader.finalize()
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -246,24 +271,32 @@ func NewCollection(spec *CollectionSpec) (*Collection, error) {
|
|||||||
|
|
||||||
// NewCollectionWithOptions creates a Collection from a specification.
|
// NewCollectionWithOptions creates a Collection from a specification.
|
||||||
func NewCollectionWithOptions(spec *CollectionSpec, opts CollectionOptions) (*Collection, error) {
|
func NewCollectionWithOptions(spec *CollectionSpec, opts CollectionOptions) (*Collection, error) {
|
||||||
loadMap, loadProgram, done, cleanup := lazyLoadCollection(spec, &opts)
|
loader := newCollectionLoader(spec, &opts)
|
||||||
defer cleanup()
|
defer loader.cleanup()
|
||||||
|
|
||||||
|
// Create maps first, as their fds need to be linked into programs.
|
||||||
for mapName := range spec.Maps {
|
for mapName := range spec.Maps {
|
||||||
_, err := loadMap(mapName)
|
if _, err := loader.loadMap(mapName); err != nil {
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for progName := range spec.Programs {
|
for progName := range spec.Programs {
|
||||||
_, err := loadProgram(progName)
|
if _, err := loader.loadProgram(progName); err != nil {
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
maps, progs := done()
|
// Maps can contain Program and Map stubs, so populate them after
|
||||||
|
// all Maps and Programs have been successfully loaded.
|
||||||
|
if err := loader.populateMaps(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
maps, progs := loader.maps, loader.programs
|
||||||
|
|
||||||
|
loader.finalize()
|
||||||
|
|
||||||
return &Collection{
|
return &Collection{
|
||||||
progs,
|
progs,
|
||||||
maps,
|
maps,
|
||||||
@ -314,113 +347,154 @@ func (hc handleCache) close() {
|
|||||||
for _, handle := range hc.btfHandles {
|
for _, handle := range hc.btfHandles {
|
||||||
handle.Close()
|
handle.Close()
|
||||||
}
|
}
|
||||||
hc.btfHandles = nil
|
|
||||||
hc.btfSpecs = nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func lazyLoadCollection(coll *CollectionSpec, opts *CollectionOptions) (
|
type collectionLoader struct {
|
||||||
loadMap func(string) (*Map, error),
|
coll *CollectionSpec
|
||||||
loadProgram func(string) (*Program, error),
|
opts *CollectionOptions
|
||||||
done func() (map[string]*Map, map[string]*Program),
|
maps map[string]*Map
|
||||||
cleanup func(),
|
programs map[string]*Program
|
||||||
) {
|
handles *handleCache
|
||||||
var (
|
}
|
||||||
maps = make(map[string]*Map)
|
|
||||||
progs = make(map[string]*Program)
|
|
||||||
handles = newHandleCache()
|
|
||||||
skipMapsAndProgs = false
|
|
||||||
)
|
|
||||||
|
|
||||||
cleanup = func() {
|
func newCollectionLoader(coll *CollectionSpec, opts *CollectionOptions) *collectionLoader {
|
||||||
handles.close()
|
if opts == nil {
|
||||||
|
opts = &CollectionOptions{}
|
||||||
if skipMapsAndProgs {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, m := range maps {
|
|
||||||
m.Close()
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, p := range progs {
|
|
||||||
p.Close()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
done = func() (map[string]*Map, map[string]*Program) {
|
return &collectionLoader{
|
||||||
skipMapsAndProgs = true
|
coll,
|
||||||
return maps, progs
|
opts,
|
||||||
|
make(map[string]*Map),
|
||||||
|
make(map[string]*Program),
|
||||||
|
newHandleCache(),
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
loadMap = func(mapName string) (*Map, error) {
|
// finalize should be called when all the collectionLoader's resources
|
||||||
if m := maps[mapName]; m != nil {
|
// have been successfully loaded into the kernel and populated with values.
|
||||||
return m, nil
|
func (cl *collectionLoader) finalize() {
|
||||||
}
|
cl.maps, cl.programs = nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
mapSpec := coll.Maps[mapName]
|
// cleanup cleans up all resources left over in the collectionLoader.
|
||||||
if mapSpec == nil {
|
// Call finalize() when Map and Program creation/population is successful
|
||||||
return nil, fmt.Errorf("missing map %s", mapName)
|
// to prevent them from getting closed.
|
||||||
}
|
func (cl *collectionLoader) cleanup() {
|
||||||
|
cl.handles.close()
|
||||||
|
for _, m := range cl.maps {
|
||||||
|
m.Close()
|
||||||
|
}
|
||||||
|
for _, p := range cl.programs {
|
||||||
|
p.Close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
m, err := newMapWithOptions(mapSpec, opts.Maps, handles)
|
func (cl *collectionLoader) loadMap(mapName string) (*Map, error) {
|
||||||
if err != nil {
|
if m := cl.maps[mapName]; m != nil {
|
||||||
return nil, fmt.Errorf("map %s: %w", mapName, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
maps[mapName] = m
|
|
||||||
return m, nil
|
return m, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
loadProgram = func(progName string) (*Program, error) {
|
mapSpec := cl.coll.Maps[mapName]
|
||||||
if prog := progs[progName]; prog != nil {
|
if mapSpec == nil {
|
||||||
return prog, nil
|
return nil, fmt.Errorf("missing map %s", mapName)
|
||||||
|
}
|
||||||
|
|
||||||
|
m, err := newMapWithOptions(mapSpec, cl.opts.Maps, cl.handles)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("map %s: %w", mapName, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
cl.maps[mapName] = m
|
||||||
|
return m, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cl *collectionLoader) loadProgram(progName string) (*Program, error) {
|
||||||
|
if prog := cl.programs[progName]; prog != nil {
|
||||||
|
return prog, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
progSpec := cl.coll.Programs[progName]
|
||||||
|
if progSpec == nil {
|
||||||
|
return nil, fmt.Errorf("unknown program %s", progName)
|
||||||
|
}
|
||||||
|
|
||||||
|
progSpec = progSpec.Copy()
|
||||||
|
|
||||||
|
// Rewrite any reference to a valid map.
|
||||||
|
for i := range progSpec.Instructions {
|
||||||
|
ins := &progSpec.Instructions[i]
|
||||||
|
|
||||||
|
if !ins.IsLoadFromMap() || ins.Reference == "" {
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
progSpec := coll.Programs[progName]
|
if uint32(ins.Constant) != math.MaxUint32 {
|
||||||
if progSpec == nil {
|
// Don't overwrite maps already rewritten, users can
|
||||||
return nil, fmt.Errorf("unknown program %s", progName)
|
// rewrite programs in the spec themselves
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
progSpec = progSpec.Copy()
|
m, err := cl.loadMap(ins.Reference)
|
||||||
|
|
||||||
// Rewrite any reference to a valid map.
|
|
||||||
for i := range progSpec.Instructions {
|
|
||||||
ins := &progSpec.Instructions[i]
|
|
||||||
|
|
||||||
if !ins.IsLoadFromMap() || ins.Reference == "" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if uint32(ins.Constant) != math.MaxUint32 {
|
|
||||||
// Don't overwrite maps already rewritten, users can
|
|
||||||
// rewrite programs in the spec themselves
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
m, err := loadMap(ins.Reference)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("program %s: %w", progName, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
fd := m.FD()
|
|
||||||
if fd < 0 {
|
|
||||||
return nil, fmt.Errorf("map %s: %w", ins.Reference, internal.ErrClosedFd)
|
|
||||||
}
|
|
||||||
if err := ins.RewriteMapPtr(m.FD()); err != nil {
|
|
||||||
return nil, fmt.Errorf("progam %s: map %s: %w", progName, ins.Reference, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
prog, err := newProgramWithOptions(progSpec, opts.Programs, handles)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("program %s: %w", progName, err)
|
return nil, fmt.Errorf("program %s: %w", progName, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
progs[progName] = prog
|
fd := m.FD()
|
||||||
return prog, nil
|
if fd < 0 {
|
||||||
|
return nil, fmt.Errorf("map %s: %w", ins.Reference, internal.ErrClosedFd)
|
||||||
|
}
|
||||||
|
if err := ins.RewriteMapPtr(m.FD()); err != nil {
|
||||||
|
return nil, fmt.Errorf("program %s: map %s: %w", progName, ins.Reference, err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
prog, err := newProgramWithOptions(progSpec, cl.opts.Programs, cl.handles)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("program %s: %w", progName, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
cl.programs[progName] = prog
|
||||||
|
return prog, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cl *collectionLoader) populateMaps() error {
|
||||||
|
for mapName, m := range cl.maps {
|
||||||
|
mapSpec, ok := cl.coll.Maps[mapName]
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("missing map spec %s", mapName)
|
||||||
|
}
|
||||||
|
|
||||||
|
mapSpec = mapSpec.Copy()
|
||||||
|
|
||||||
|
// Replace any object stubs with loaded objects.
|
||||||
|
for i, kv := range mapSpec.Contents {
|
||||||
|
switch v := kv.Value.(type) {
|
||||||
|
case programStub:
|
||||||
|
// loadProgram is idempotent and could return an existing Program.
|
||||||
|
prog, err := cl.loadProgram(string(v))
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("loading program %s, for map %s: %w", v, mapName, err)
|
||||||
|
}
|
||||||
|
mapSpec.Contents[i] = MapKV{kv.Key, prog}
|
||||||
|
|
||||||
|
case mapStub:
|
||||||
|
// loadMap is idempotent and could return an existing Map.
|
||||||
|
innerMap, err := cl.loadMap(string(v))
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("loading inner map %s, for map %s: %w", v, mapName, err)
|
||||||
|
}
|
||||||
|
mapSpec.Contents[i] = MapKV{kv.Key, innerMap}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Populate and freeze the map if specified.
|
||||||
|
if err := m.finalize(mapSpec); err != nil {
|
||||||
|
return fmt.Errorf("populating map %s: %w", mapName, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoadCollection parses an object file and converts it to a collection.
|
// LoadCollection parses an object file and converts it to a collection.
|
||||||
@ -466,108 +540,81 @@ func (coll *Collection) DetachProgram(name string) *Program {
|
|||||||
return p
|
return p
|
||||||
}
|
}
|
||||||
|
|
||||||
// Assign the contents of a collection to a struct.
|
// structField represents a struct field containing the ebpf struct tag.
|
||||||
//
|
type structField struct {
|
||||||
// Deprecated: use CollectionSpec.Assign instead. It provides the same
|
reflect.StructField
|
||||||
// functionality but creates only the maps and programs requested.
|
value reflect.Value
|
||||||
func (coll *Collection) Assign(to interface{}) error {
|
|
||||||
assignedMaps := make(map[string]struct{})
|
|
||||||
assignedPrograms := make(map[string]struct{})
|
|
||||||
valueOf := func(typ reflect.Type, name string) (reflect.Value, error) {
|
|
||||||
switch typ {
|
|
||||||
case reflect.TypeOf((*Program)(nil)):
|
|
||||||
p := coll.Programs[name]
|
|
||||||
if p == nil {
|
|
||||||
return reflect.Value{}, fmt.Errorf("missing program %q", name)
|
|
||||||
}
|
|
||||||
assignedPrograms[name] = struct{}{}
|
|
||||||
return reflect.ValueOf(p), nil
|
|
||||||
case reflect.TypeOf((*Map)(nil)):
|
|
||||||
m := coll.Maps[name]
|
|
||||||
if m == nil {
|
|
||||||
return reflect.Value{}, fmt.Errorf("missing map %q", name)
|
|
||||||
}
|
|
||||||
assignedMaps[name] = struct{}{}
|
|
||||||
return reflect.ValueOf(m), nil
|
|
||||||
default:
|
|
||||||
return reflect.Value{}, fmt.Errorf("unsupported type %s", typ)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := assignValues(to, valueOf); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
for name := range assignedPrograms {
|
|
||||||
coll.DetachProgram(name)
|
|
||||||
}
|
|
||||||
|
|
||||||
for name := range assignedMaps {
|
|
||||||
coll.DetachMap(name)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func assignValues(to interface{}, valueOf func(reflect.Type, string) (reflect.Value, error)) error {
|
// ebpfFields extracts field names tagged with 'ebpf' from a struct type.
|
||||||
type structField struct {
|
// Keep track of visited types to avoid infinite recursion.
|
||||||
reflect.StructField
|
func ebpfFields(structVal reflect.Value, visited map[reflect.Type]bool) ([]structField, error) {
|
||||||
value reflect.Value
|
if visited == nil {
|
||||||
|
visited = make(map[reflect.Type]bool)
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
structType := structVal.Type()
|
||||||
fields []structField
|
if structType.Kind() != reflect.Struct {
|
||||||
visitedTypes = make(map[reflect.Type]bool)
|
return nil, fmt.Errorf("%s is not a struct", structType)
|
||||||
flattenStruct func(reflect.Value) error
|
}
|
||||||
)
|
|
||||||
|
|
||||||
flattenStruct = func(structVal reflect.Value) error {
|
if visited[structType] {
|
||||||
structType := structVal.Type()
|
return nil, fmt.Errorf("recursion on type %s", structType)
|
||||||
if structType.Kind() != reflect.Struct {
|
}
|
||||||
return fmt.Errorf("%s is not a struct", structType)
|
|
||||||
|
fields := make([]structField, 0, structType.NumField())
|
||||||
|
for i := 0; i < structType.NumField(); i++ {
|
||||||
|
field := structField{structType.Field(i), structVal.Field(i)}
|
||||||
|
|
||||||
|
// If the field is tagged, gather it and move on.
|
||||||
|
name := field.Tag.Get("ebpf")
|
||||||
|
if name != "" {
|
||||||
|
fields = append(fields, field)
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if visitedTypes[structType] {
|
// If the field does not have an ebpf tag, but is a struct or a pointer
|
||||||
return fmt.Errorf("recursion on type %s", structType)
|
// to a struct, attempt to gather its fields as well.
|
||||||
}
|
var v reflect.Value
|
||||||
|
switch field.Type.Kind() {
|
||||||
for i := 0; i < structType.NumField(); i++ {
|
case reflect.Ptr:
|
||||||
field := structField{structType.Field(i), structVal.Field(i)}
|
if field.Type.Elem().Kind() != reflect.Struct {
|
||||||
|
|
||||||
name := field.Tag.Get("ebpf")
|
|
||||||
if name != "" {
|
|
||||||
fields = append(fields, field)
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
var err error
|
if field.value.IsNil() {
|
||||||
switch field.Type.Kind() {
|
return nil, fmt.Errorf("nil pointer to %s", structType)
|
||||||
case reflect.Ptr:
|
|
||||||
if field.Type.Elem().Kind() != reflect.Struct {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if field.value.IsNil() {
|
|
||||||
return fmt.Errorf("nil pointer to %s", structType)
|
|
||||||
}
|
|
||||||
|
|
||||||
err = flattenStruct(field.value.Elem())
|
|
||||||
|
|
||||||
case reflect.Struct:
|
|
||||||
err = flattenStruct(field.value)
|
|
||||||
|
|
||||||
default:
|
|
||||||
continue
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
// Obtain the destination type of the pointer.
|
||||||
return fmt.Errorf("field %s: %w", field.Name, err)
|
v = field.value.Elem()
|
||||||
}
|
|
||||||
|
case reflect.Struct:
|
||||||
|
// Reference the value's type directly.
|
||||||
|
v = field.value
|
||||||
|
|
||||||
|
default:
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
inner, err := ebpfFields(v, visited)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("field %s: %w", field.Name, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
fields = append(fields, inner...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return fields, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// assignValues attempts to populate all fields of 'to' tagged with 'ebpf'.
|
||||||
|
//
|
||||||
|
// getValue is called for every tagged field of 'to' and must return the value
|
||||||
|
// to be assigned to the field with the given typ and name.
|
||||||
|
func assignValues(to interface{},
|
||||||
|
getValue func(typ reflect.Type, name string) (interface{}, error)) error {
|
||||||
|
|
||||||
toValue := reflect.ValueOf(to)
|
toValue := reflect.ValueOf(to)
|
||||||
if toValue.Type().Kind() != reflect.Ptr {
|
if toValue.Type().Kind() != reflect.Ptr {
|
||||||
return fmt.Errorf("%T is not a pointer to struct", to)
|
return fmt.Errorf("%T is not a pointer to struct", to)
|
||||||
@ -577,7 +624,8 @@ func assignValues(to interface{}, valueOf func(reflect.Type, string) (reflect.Va
|
|||||||
return fmt.Errorf("nil pointer to %T", to)
|
return fmt.Errorf("nil pointer to %T", to)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := flattenStruct(toValue.Elem()); err != nil {
|
fields, err := ebpfFields(toValue.Elem(), nil)
|
||||||
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -587,19 +635,23 @@ func assignValues(to interface{}, valueOf func(reflect.Type, string) (reflect.Va
|
|||||||
name string
|
name string
|
||||||
}
|
}
|
||||||
|
|
||||||
assignedTo := make(map[elem]string)
|
assigned := make(map[elem]string)
|
||||||
for _, field := range fields {
|
for _, field := range fields {
|
||||||
name := field.Tag.Get("ebpf")
|
// Get string value the field is tagged with.
|
||||||
if strings.Contains(name, ",") {
|
tag := field.Tag.Get("ebpf")
|
||||||
|
if strings.Contains(tag, ",") {
|
||||||
return fmt.Errorf("field %s: ebpf tag contains a comma", field.Name)
|
return fmt.Errorf("field %s: ebpf tag contains a comma", field.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
e := elem{field.Type, name}
|
// Check if the eBPF object with the requested
|
||||||
if assignedField := assignedTo[e]; assignedField != "" {
|
// type and tag was already assigned elsewhere.
|
||||||
return fmt.Errorf("field %s: %q was already assigned to %s", field.Name, name, assignedField)
|
e := elem{field.Type, tag}
|
||||||
|
if af := assigned[e]; af != "" {
|
||||||
|
return fmt.Errorf("field %s: object %q was already assigned to %s", field.Name, tag, af)
|
||||||
}
|
}
|
||||||
|
|
||||||
value, err := valueOf(field.Type, name)
|
// Get the eBPF object referred to by the tag.
|
||||||
|
value, err := getValue(field.Type, tag)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("field %s: %w", field.Name, err)
|
return fmt.Errorf("field %s: %w", field.Name, err)
|
||||||
}
|
}
|
||||||
@ -607,9 +659,9 @@ func assignValues(to interface{}, valueOf func(reflect.Type, string) (reflect.Va
|
|||||||
if !field.value.CanSet() {
|
if !field.value.CanSet() {
|
||||||
return fmt.Errorf("field %s: can't set value", field.Name)
|
return fmt.Errorf("field %s: can't set value", field.Name)
|
||||||
}
|
}
|
||||||
|
field.value.Set(reflect.ValueOf(value))
|
||||||
|
|
||||||
field.value.Set(value)
|
assigned[e] = field.Name
|
||||||
assignedTo[e] = field.Name
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
180
vendor/github.com/cilium/ebpf/elf_reader.go
generated
vendored
180
vendor/github.com/cilium/ebpf/elf_reader.go
generated
vendored
@ -19,7 +19,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// elfCode is a convenience to reduce the amount of arguments that have to
|
// elfCode is a convenience to reduce the amount of arguments that have to
|
||||||
// be passed around explicitly. You should treat it's contents as immutable.
|
// be passed around explicitly. You should treat its contents as immutable.
|
||||||
type elfCode struct {
|
type elfCode struct {
|
||||||
*internal.SafeELFFile
|
*internal.SafeELFFile
|
||||||
sections map[elf.SectionIndex]*elfSection
|
sections map[elf.SectionIndex]*elfSection
|
||||||
@ -188,7 +188,7 @@ func LoadCollectionSpecFromReader(rd io.ReaderAt) (*CollectionSpec, error) {
|
|||||||
return nil, fmt.Errorf("load programs: %w", err)
|
return nil, fmt.Errorf("load programs: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return &CollectionSpec{maps, progs}, nil
|
return &CollectionSpec{maps, progs, ec.ByteOrder}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadLicense(sec *elf.Section) (string, error) {
|
func loadLicense(sec *elf.Section) (string, error) {
|
||||||
@ -520,8 +520,12 @@ func (ec *elfCode) loadMaps(maps map[string]*MapSpec) error {
|
|||||||
return fmt.Errorf("map %s: missing flags", mapName)
|
return fmt.Errorf("map %s: missing flags", mapName)
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err := io.Copy(internal.DiscardZeroes{}, lr); err != nil {
|
extra, err := io.ReadAll(lr)
|
||||||
return fmt.Errorf("map %s: unknown and non-zero fields in definition", mapName)
|
if err != nil {
|
||||||
|
return fmt.Errorf("map %s: reading map tail: %w", mapName, err)
|
||||||
|
}
|
||||||
|
if len(extra) > 0 {
|
||||||
|
spec.Extra = *bytes.NewReader(extra)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := spec.clampPerfEventArraySize(); err != nil {
|
if err := spec.clampPerfEventArraySize(); err != nil {
|
||||||
@ -535,6 +539,9 @@ func (ec *elfCode) loadMaps(maps map[string]*MapSpec) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// loadBTFMaps iterates over all ELF sections marked as BTF map sections
|
||||||
|
// (like .maps) and parses them into MapSpecs. Dump the .maps section and
|
||||||
|
// any relocations with `readelf -x .maps -r <elf_file>`.
|
||||||
func (ec *elfCode) loadBTFMaps(maps map[string]*MapSpec) error {
|
func (ec *elfCode) loadBTFMaps(maps map[string]*MapSpec) error {
|
||||||
for _, sec := range ec.sections {
|
for _, sec := range ec.sections {
|
||||||
if sec.kind != btfMapSection {
|
if sec.kind != btfMapSection {
|
||||||
@ -545,33 +552,46 @@ func (ec *elfCode) loadBTFMaps(maps map[string]*MapSpec) error {
|
|||||||
return fmt.Errorf("missing BTF")
|
return fmt.Errorf("missing BTF")
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err := io.Copy(internal.DiscardZeroes{}, bufio.NewReader(sec.Open()))
|
// Each section must appear as a DataSec in the ELF's BTF blob.
|
||||||
if err != nil {
|
var ds *btf.Datasec
|
||||||
return fmt.Errorf("section %v: initializing BTF map definitions: %w", sec.Name, internal.ErrNotSupported)
|
|
||||||
}
|
|
||||||
|
|
||||||
var ds btf.Datasec
|
|
||||||
if err := ec.btf.FindType(sec.Name, &ds); err != nil {
|
if err := ec.btf.FindType(sec.Name, &ds); err != nil {
|
||||||
return fmt.Errorf("cannot find section '%s' in BTF: %w", sec.Name, err)
|
return fmt.Errorf("cannot find section '%s' in BTF: %w", sec.Name, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Open a Reader to the ELF's raw section bytes so we can assert that all
|
||||||
|
// of them are zero on a per-map (per-Var) basis. For now, the section's
|
||||||
|
// sole purpose is to receive relocations, so all must be zero.
|
||||||
|
rs := sec.Open()
|
||||||
|
|
||||||
for _, vs := range ds.Vars {
|
for _, vs := range ds.Vars {
|
||||||
|
// BPF maps are declared as and assigned to global variables,
|
||||||
|
// so iterate over each Var in the DataSec and validate their types.
|
||||||
v, ok := vs.Type.(*btf.Var)
|
v, ok := vs.Type.(*btf.Var)
|
||||||
if !ok {
|
if !ok {
|
||||||
return fmt.Errorf("section %v: unexpected type %s", sec.Name, vs.Type)
|
return fmt.Errorf("section %v: unexpected type %s", sec.Name, vs.Type)
|
||||||
}
|
}
|
||||||
name := string(v.Name)
|
name := string(v.Name)
|
||||||
|
|
||||||
|
// The BTF metadata for each Var contains the full length of the map
|
||||||
|
// declaration, so read the corresponding amount of bytes from the ELF.
|
||||||
|
// This way, we can pinpoint which map declaration contains unexpected
|
||||||
|
// (and therefore unsupported) data.
|
||||||
|
_, err := io.Copy(internal.DiscardZeroes{}, io.LimitReader(rs, int64(vs.Size)))
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("section %v: map %s: initializing BTF map definitions: %w", sec.Name, name, internal.ErrNotSupported)
|
||||||
|
}
|
||||||
|
|
||||||
if maps[name] != nil {
|
if maps[name] != nil {
|
||||||
return fmt.Errorf("section %v: map %s already exists", sec.Name, name)
|
return fmt.Errorf("section %v: map %s already exists", sec.Name, name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Each Var representing a BTF map definition contains a Struct.
|
||||||
mapStruct, ok := v.Type.(*btf.Struct)
|
mapStruct, ok := v.Type.(*btf.Struct)
|
||||||
if !ok {
|
if !ok {
|
||||||
return fmt.Errorf("expected struct, got %s", v.Type)
|
return fmt.Errorf("expected struct, got %s", v.Type)
|
||||||
}
|
}
|
||||||
|
|
||||||
mapSpec, err := mapSpecFromBTF(name, mapStruct, false, ec.btf)
|
mapSpec, err := mapSpecFromBTF(sec, &vs, mapStruct, ec.btf, name, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("map %v: %w", name, err)
|
return fmt.Errorf("map %v: %w", name, err)
|
||||||
}
|
}
|
||||||
@ -582,32 +602,52 @@ func (ec *elfCode) loadBTFMaps(maps map[string]*MapSpec) error {
|
|||||||
|
|
||||||
maps[name] = mapSpec
|
maps[name] = mapSpec
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Drain the ELF section reader to make sure all bytes are accounted for
|
||||||
|
// with BTF metadata.
|
||||||
|
i, err := io.Copy(io.Discard, rs)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("section %v: unexpected error reading remainder of ELF section: %w", sec.Name, err)
|
||||||
|
}
|
||||||
|
if i > 0 {
|
||||||
|
return fmt.Errorf("section %v: %d unexpected remaining bytes in ELF section, invalid BTF?", sec.Name, i)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// A programStub is a placeholder for a Program to be inserted at a certain map key.
|
||||||
|
// It needs to be resolved into a Program later on in the loader process.
|
||||||
|
type programStub string
|
||||||
|
|
||||||
|
// A mapStub is a placeholder for a Map to be inserted at a certain map key.
|
||||||
|
// It needs to be resolved into a Map later on in the loader process.
|
||||||
|
type mapStub string
|
||||||
|
|
||||||
// mapSpecFromBTF produces a MapSpec based on a btf.Struct def representing
|
// mapSpecFromBTF produces a MapSpec based on a btf.Struct def representing
|
||||||
// a BTF map definition. The name and spec arguments will be copied to the
|
// a BTF map definition. The name and spec arguments will be copied to the
|
||||||
// resulting MapSpec, and inner must be true on any resursive invocations.
|
// resulting MapSpec, and inner must be true on any resursive invocations.
|
||||||
func mapSpecFromBTF(name string, def *btf.Struct, inner bool, spec *btf.Spec) (*MapSpec, error) {
|
func mapSpecFromBTF(es *elfSection, vs *btf.VarSecinfo, def *btf.Struct, spec *btf.Spec, name string, inner bool) (*MapSpec, error) {
|
||||||
|
|
||||||
var (
|
var (
|
||||||
key, value btf.Type
|
key, value btf.Type
|
||||||
keySize, valueSize uint32
|
keySize, valueSize uint32
|
||||||
mapType, flags, maxEntries uint32
|
mapType MapType
|
||||||
pinType PinType
|
flags, maxEntries uint32
|
||||||
innerMapSpec *MapSpec
|
pinType PinType
|
||||||
err error
|
innerMapSpec *MapSpec
|
||||||
|
contents []MapKV
|
||||||
|
err error
|
||||||
)
|
)
|
||||||
|
|
||||||
for i, member := range def.Members {
|
for i, member := range def.Members {
|
||||||
switch member.Name {
|
switch member.Name {
|
||||||
case "type":
|
case "type":
|
||||||
mapType, err = uintFromBTF(member.Type)
|
mt, err := uintFromBTF(member.Type)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("can't get type: %w", err)
|
return nil, fmt.Errorf("can't get type: %w", err)
|
||||||
}
|
}
|
||||||
|
mapType = MapType(mt)
|
||||||
|
|
||||||
case "map_flags":
|
case "map_flags":
|
||||||
flags, err = uintFromBTF(member.Type)
|
flags, err = uintFromBTF(member.Type)
|
||||||
@ -717,7 +757,7 @@ func mapSpecFromBTF(name string, def *btf.Struct, inner bool, spec *btf.Spec) (*
|
|||||||
case *btf.Struct:
|
case *btf.Struct:
|
||||||
// The values member pointing to an array of structs means we're expecting
|
// The values member pointing to an array of structs means we're expecting
|
||||||
// a map-in-map declaration.
|
// a map-in-map declaration.
|
||||||
if MapType(mapType) != ArrayOfMaps && MapType(mapType) != HashOfMaps {
|
if mapType != ArrayOfMaps && mapType != HashOfMaps {
|
||||||
return nil, errors.New("outer map needs to be an array or a hash of maps")
|
return nil, errors.New("outer map needs to be an array or a hash of maps")
|
||||||
}
|
}
|
||||||
if inner {
|
if inner {
|
||||||
@ -731,21 +771,38 @@ func mapSpecFromBTF(name string, def *btf.Struct, inner bool, spec *btf.Spec) (*
|
|||||||
// on kernels 5.2 and up)
|
// on kernels 5.2 and up)
|
||||||
// Pass the BTF spec from the parent object, since both parent and
|
// Pass the BTF spec from the parent object, since both parent and
|
||||||
// child must be created from the same BTF blob (on kernels that support BTF).
|
// child must be created from the same BTF blob (on kernels that support BTF).
|
||||||
innerMapSpec, err = mapSpecFromBTF(name+"_inner", t, true, spec)
|
innerMapSpec, err = mapSpecFromBTF(es, vs, t, spec, name+"_inner", true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("can't parse BTF map definition of inner map: %w", err)
|
return nil, fmt.Errorf("can't parse BTF map definition of inner map: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case *btf.FuncProto:
|
||||||
|
// The values member contains an array of function pointers, meaning an
|
||||||
|
// autopopulated PROG_ARRAY.
|
||||||
|
if mapType != ProgramArray {
|
||||||
|
return nil, errors.New("map needs to be a program array")
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return nil, fmt.Errorf("unsupported value type %q in 'values' field", t)
|
return nil, fmt.Errorf("unsupported value type %q in 'values' field", t)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
contents, err = resolveBTFValuesContents(es, vs, member)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("resolving values contents: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return nil, fmt.Errorf("unrecognized field %s in BTF map definition", member.Name)
|
return nil, fmt.Errorf("unrecognized field %s in BTF map definition", member.Name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bm := btf.NewMap(spec, key, value)
|
if key == nil {
|
||||||
|
key = &btf.Void{}
|
||||||
|
}
|
||||||
|
if value == nil {
|
||||||
|
value = &btf.Void{}
|
||||||
|
}
|
||||||
|
|
||||||
return &MapSpec{
|
return &MapSpec{
|
||||||
Name: SanitizeName(name, -1),
|
Name: SanitizeName(name, -1),
|
||||||
@ -754,9 +811,10 @@ func mapSpecFromBTF(name string, def *btf.Struct, inner bool, spec *btf.Spec) (*
|
|||||||
ValueSize: valueSize,
|
ValueSize: valueSize,
|
||||||
MaxEntries: maxEntries,
|
MaxEntries: maxEntries,
|
||||||
Flags: flags,
|
Flags: flags,
|
||||||
BTF: &bm,
|
BTF: &btf.Map{Spec: spec, Key: key, Value: value},
|
||||||
Pinning: pinType,
|
Pinning: pinType,
|
||||||
InnerMap: innerMapSpec,
|
InnerMap: innerMapSpec,
|
||||||
|
Contents: contents,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -793,6 +851,64 @@ func resolveBTFArrayMacro(typ btf.Type) (btf.Type, error) {
|
|||||||
return ptr.Target, nil
|
return ptr.Target, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// resolveBTFValuesContents resolves relocations into ELF sections belonging
|
||||||
|
// to btf.VarSecinfo's. This can be used on the 'values' member in BTF map
|
||||||
|
// definitions to extract static declarations of map contents.
|
||||||
|
func resolveBTFValuesContents(es *elfSection, vs *btf.VarSecinfo, member btf.Member) ([]MapKV, error) {
|
||||||
|
// The elements of a .values pointer array are not encoded in BTF.
|
||||||
|
// Instead, relocations are generated into each array index.
|
||||||
|
// However, it's possible to leave certain array indices empty, so all
|
||||||
|
// indices' offsets need to be checked for emitted relocations.
|
||||||
|
|
||||||
|
// The offset of the 'values' member within the _struct_ (in bits)
|
||||||
|
// is the starting point of the array. Convert to bytes. Add VarSecinfo
|
||||||
|
// offset to get the absolute position in the ELF blob.
|
||||||
|
start := (member.OffsetBits / 8) + vs.Offset
|
||||||
|
// 'values' is encoded in BTF as a zero (variable) length struct
|
||||||
|
// member, and its contents run until the end of the VarSecinfo.
|
||||||
|
// Add VarSecinfo offset to get the absolute position in the ELF blob.
|
||||||
|
end := vs.Size + vs.Offset
|
||||||
|
// The size of an address in this section. This determines the width of
|
||||||
|
// an index in the array.
|
||||||
|
align := uint32(es.SectionHeader.Addralign)
|
||||||
|
|
||||||
|
// Check if variable-length section is aligned.
|
||||||
|
if (end-start)%align != 0 {
|
||||||
|
return nil, errors.New("unaligned static values section")
|
||||||
|
}
|
||||||
|
elems := (end - start) / align
|
||||||
|
|
||||||
|
if elems == 0 {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
contents := make([]MapKV, 0, elems)
|
||||||
|
|
||||||
|
// k is the array index, off is its corresponding ELF section offset.
|
||||||
|
for k, off := uint32(0), start; k < elems; k, off = k+1, off+align {
|
||||||
|
r, ok := es.relocations[uint64(off)]
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// Relocation exists for the current offset in the ELF section.
|
||||||
|
// Emit a value stub based on the type of relocation to be replaced by
|
||||||
|
// a real fd later in the pipeline before populating the map.
|
||||||
|
// Map keys are encoded in MapKV entries, so empty array indices are
|
||||||
|
// skipped here.
|
||||||
|
switch t := elf.ST_TYPE(r.Info); t {
|
||||||
|
case elf.STT_FUNC:
|
||||||
|
contents = append(contents, MapKV{uint32(k), programStub(r.Name)})
|
||||||
|
case elf.STT_OBJECT:
|
||||||
|
contents = append(contents, MapKV{uint32(k), mapStub(r.Name)})
|
||||||
|
default:
|
||||||
|
return nil, fmt.Errorf("unknown relocation type %v", t)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return contents, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (ec *elfCode) loadDataSections(maps map[string]*MapSpec) error {
|
func (ec *elfCode) loadDataSections(maps map[string]*MapSpec) error {
|
||||||
for _, sec := range ec.sections {
|
for _, sec := range ec.sections {
|
||||||
if sec.kind != dataSection {
|
if sec.kind != dataSection {
|
||||||
@ -809,9 +925,9 @@ func (ec *elfCode) loadDataSections(maps map[string]*MapSpec) error {
|
|||||||
return errors.New("data sections require BTF, make sure all consts are marked as static")
|
return errors.New("data sections require BTF, make sure all consts are marked as static")
|
||||||
}
|
}
|
||||||
|
|
||||||
btfMap, err := ec.btf.Datasec(sec.Name)
|
var datasec *btf.Datasec
|
||||||
if err != nil {
|
if err := ec.btf.FindType(sec.Name, &datasec); err != nil {
|
||||||
return err
|
return fmt.Errorf("data section %s: can't get BTF: %w", sec.Name, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
data, err := sec.Data()
|
data, err := sec.Data()
|
||||||
@ -830,7 +946,7 @@ func (ec *elfCode) loadDataSections(maps map[string]*MapSpec) error {
|
|||||||
ValueSize: uint32(len(data)),
|
ValueSize: uint32(len(data)),
|
||||||
MaxEntries: 1,
|
MaxEntries: 1,
|
||||||
Contents: []MapKV{{uint32(0), data}},
|
Contents: []MapKV{{uint32(0), data}},
|
||||||
BTF: btfMap,
|
BTF: &btf.Map{Spec: ec.btf, Key: &btf.Void{}, Value: datasec},
|
||||||
}
|
}
|
||||||
|
|
||||||
switch sec.Name {
|
switch sec.Name {
|
||||||
@ -855,6 +971,8 @@ func getProgType(sectionName string) (ProgramType, AttachType, uint32, string) {
|
|||||||
}{
|
}{
|
||||||
// From https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/tools/lib/bpf/libbpf.c
|
// From https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/tools/lib/bpf/libbpf.c
|
||||||
"socket": {SocketFilter, AttachNone, 0},
|
"socket": {SocketFilter, AttachNone, 0},
|
||||||
|
"sk_reuseport/migrate": {SkReuseport, AttachSkReuseportSelectOrMigrate, 0},
|
||||||
|
"sk_reuseport": {SkReuseport, AttachSkReuseportSelect, 0},
|
||||||
"seccomp": {SocketFilter, AttachNone, 0},
|
"seccomp": {SocketFilter, AttachNone, 0},
|
||||||
"kprobe/": {Kprobe, AttachNone, 0},
|
"kprobe/": {Kprobe, AttachNone, 0},
|
||||||
"uprobe/": {Kprobe, AttachNone, 0},
|
"uprobe/": {Kprobe, AttachNone, 0},
|
||||||
@ -884,6 +1002,7 @@ func getProgType(sectionName string) (ProgramType, AttachType, uint32, string) {
|
|||||||
"fmod_ret.s/": {Tracing, AttachModifyReturn, unix.BPF_F_SLEEPABLE},
|
"fmod_ret.s/": {Tracing, AttachModifyReturn, unix.BPF_F_SLEEPABLE},
|
||||||
"fexit.s/": {Tracing, AttachTraceFExit, unix.BPF_F_SLEEPABLE},
|
"fexit.s/": {Tracing, AttachTraceFExit, unix.BPF_F_SLEEPABLE},
|
||||||
"sk_lookup/": {SkLookup, AttachSkLookup, 0},
|
"sk_lookup/": {SkLookup, AttachSkLookup, 0},
|
||||||
|
"freplace/": {Extension, AttachNone, 0},
|
||||||
"lsm/": {LSM, AttachLSMMac, 0},
|
"lsm/": {LSM, AttachLSMMac, 0},
|
||||||
"lsm.s/": {LSM, AttachLSMMac, unix.BPF_F_SLEEPABLE},
|
"lsm.s/": {LSM, AttachLSMMac, unix.BPF_F_SLEEPABLE},
|
||||||
|
|
||||||
@ -907,6 +1026,11 @@ func getProgType(sectionName string) (ProgramType, AttachType, uint32, string) {
|
|||||||
"cgroup/setsockopt": {CGroupSockopt, AttachCGroupSetsockopt, 0},
|
"cgroup/setsockopt": {CGroupSockopt, AttachCGroupSetsockopt, 0},
|
||||||
"classifier": {SchedCLS, AttachNone, 0},
|
"classifier": {SchedCLS, AttachNone, 0},
|
||||||
"action": {SchedACT, AttachNone, 0},
|
"action": {SchedACT, AttachNone, 0},
|
||||||
|
|
||||||
|
"cgroup/getsockname4": {CGroupSockAddr, AttachCgroupInet4GetSockname, 0},
|
||||||
|
"cgroup/getsockname6": {CGroupSockAddr, AttachCgroupInet6GetSockname, 0},
|
||||||
|
"cgroup/getpeername4": {CGroupSockAddr, AttachCgroupInet4GetPeername, 0},
|
||||||
|
"cgroup/getpeername6": {CGroupSockAddr, AttachCgroupInet6GetPeername, 0},
|
||||||
}
|
}
|
||||||
|
|
||||||
for prefix, t := range types {
|
for prefix, t := range types {
|
||||||
|
1
vendor/github.com/cilium/ebpf/elf_reader_fuzz.go
generated
vendored
1
vendor/github.com/cilium/ebpf/elf_reader_fuzz.go
generated
vendored
@ -1,3 +1,4 @@
|
|||||||
|
//go:build gofuzz
|
||||||
// +build gofuzz
|
// +build gofuzz
|
||||||
|
|
||||||
// Use with https://github.com/dvyukov/go-fuzz
|
// Use with https://github.com/dvyukov/go-fuzz
|
||||||
|
4
vendor/github.com/cilium/ebpf/go.mod
generated
vendored
4
vendor/github.com/cilium/ebpf/go.mod
generated
vendored
@ -1,9 +1,9 @@
|
|||||||
module github.com/cilium/ebpf
|
module github.com/cilium/ebpf
|
||||||
|
|
||||||
go 1.15
|
go 1.16
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/frankban/quicktest v1.11.3
|
github.com/frankban/quicktest v1.11.3
|
||||||
github.com/google/go-cmp v0.5.4
|
github.com/google/go-cmp v0.5.4
|
||||||
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c
|
golang.org/x/sys v0.0.0-20210906170528-6f6e22806c34
|
||||||
)
|
)
|
||||||
|
4
vendor/github.com/cilium/ebpf/go.sum
generated
vendored
4
vendor/github.com/cilium/ebpf/go.sum
generated
vendored
@ -7,7 +7,7 @@ github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfn
|
|||||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||||
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||||
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c h1:VwygUrnw9jn88c4u8GD3rZQbqrP/tgas88tPUbBxQrk=
|
golang.org/x/sys v0.0.0-20210906170528-6f6e22806c34 h1:GkvMjFtXUmahfDtashnc1mnrCtuBVcwse5QV2lUk/tI=
|
||||||
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210906170528-6f6e22806c34/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
|
36
vendor/github.com/cilium/ebpf/info.go
generated
vendored
36
vendor/github.com/cilium/ebpf/info.go
generated
vendored
@ -12,6 +12,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/cilium/ebpf/internal"
|
"github.com/cilium/ebpf/internal"
|
||||||
|
"github.com/cilium/ebpf/internal/btf"
|
||||||
)
|
)
|
||||||
|
|
||||||
// MapInfo describes a map.
|
// MapInfo describes a map.
|
||||||
@ -87,12 +88,16 @@ type ProgramInfo struct {
|
|||||||
Tag string
|
Tag string
|
||||||
// Name as supplied by user space at load time.
|
// Name as supplied by user space at load time.
|
||||||
Name string
|
Name string
|
||||||
|
// BTF for the program.
|
||||||
|
btf btf.ID
|
||||||
|
// IDS map ids related to program.
|
||||||
|
ids []MapID
|
||||||
|
|
||||||
stats *programStats
|
stats *programStats
|
||||||
}
|
}
|
||||||
|
|
||||||
func newProgramInfoFromFd(fd *internal.FD) (*ProgramInfo, error) {
|
func newProgramInfoFromFd(fd *internal.FD) (*ProgramInfo, error) {
|
||||||
info, err := bpfGetProgInfoByFD(fd)
|
info, err := bpfGetProgInfoByFD(fd, nil)
|
||||||
if errors.Is(err, syscall.EINVAL) {
|
if errors.Is(err, syscall.EINVAL) {
|
||||||
return newProgramInfoFromProc(fd)
|
return newProgramInfoFromProc(fd)
|
||||||
}
|
}
|
||||||
@ -100,6 +105,15 @@ func newProgramInfoFromFd(fd *internal.FD) (*ProgramInfo, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var mapIDs []MapID
|
||||||
|
if info.nr_map_ids > 0 {
|
||||||
|
mapIDs = make([]MapID, info.nr_map_ids)
|
||||||
|
info, err = bpfGetProgInfoByFD(fd, mapIDs)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return &ProgramInfo{
|
return &ProgramInfo{
|
||||||
Type: ProgramType(info.prog_type),
|
Type: ProgramType(info.prog_type),
|
||||||
id: ProgramID(info.id),
|
id: ProgramID(info.id),
|
||||||
@ -107,6 +121,8 @@ func newProgramInfoFromFd(fd *internal.FD) (*ProgramInfo, error) {
|
|||||||
Tag: hex.EncodeToString(info.tag[:]),
|
Tag: hex.EncodeToString(info.tag[:]),
|
||||||
// name is available from 4.15.
|
// name is available from 4.15.
|
||||||
Name: internal.CString(info.name[:]),
|
Name: internal.CString(info.name[:]),
|
||||||
|
btf: btf.ID(info.btf_id),
|
||||||
|
ids: mapIDs,
|
||||||
stats: &programStats{
|
stats: &programStats{
|
||||||
runtime: time.Duration(info.run_time_ns),
|
runtime: time.Duration(info.run_time_ns),
|
||||||
runCount: info.run_cnt,
|
runCount: info.run_cnt,
|
||||||
@ -142,6 +158,17 @@ func (pi *ProgramInfo) ID() (ProgramID, bool) {
|
|||||||
return pi.id, pi.id > 0
|
return pi.id, pi.id > 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// BTFID returns the BTF ID associated with the program.
|
||||||
|
//
|
||||||
|
// Available from 5.0.
|
||||||
|
//
|
||||||
|
// The bool return value indicates whether this optional field is available and
|
||||||
|
// populated. (The field may be available but not populated if the kernel
|
||||||
|
// supports the field but the program was loaded without BTF information.)
|
||||||
|
func (pi *ProgramInfo) BTFID() (btf.ID, bool) {
|
||||||
|
return pi.btf, pi.btf > 0
|
||||||
|
}
|
||||||
|
|
||||||
// RunCount returns the total number of times the program was called.
|
// RunCount returns the total number of times the program was called.
|
||||||
//
|
//
|
||||||
// Can return 0 if the collection of statistics is not enabled. See EnableStats().
|
// Can return 0 if the collection of statistics is not enabled. See EnableStats().
|
||||||
@ -164,6 +191,13 @@ func (pi *ProgramInfo) Runtime() (time.Duration, bool) {
|
|||||||
return time.Duration(0), false
|
return time.Duration(0), false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MapIDs returns the maps related to the program.
|
||||||
|
//
|
||||||
|
// The bool return value indicates whether this optional field is available.
|
||||||
|
func (pi *ProgramInfo) MapIDs() ([]MapID, bool) {
|
||||||
|
return pi.ids, pi.ids != nil
|
||||||
|
}
|
||||||
|
|
||||||
func scanFdInfo(fd *internal.FD, fields map[string]interface{}) error {
|
func scanFdInfo(fd *internal.FD, fields map[string]interface{}) error {
|
||||||
raw, err := fd.Value()
|
raw, err := fd.Value()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
6
vendor/github.com/cilium/ebpf/internal/align.go
generated
vendored
Normal file
6
vendor/github.com/cilium/ebpf/internal/align.go
generated
vendored
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
package internal
|
||||||
|
|
||||||
|
// Align returns 'n' updated to 'alignment' boundary.
|
||||||
|
func Align(n, alignment int) int {
|
||||||
|
return (int(n) + alignment - 1) / alignment * alignment
|
||||||
|
}
|
293
vendor/github.com/cilium/ebpf/internal/btf/btf.go
generated
vendored
293
vendor/github.com/cilium/ebpf/internal/btf/btf.go
generated
vendored
@ -7,7 +7,6 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
|
||||||
"math"
|
"math"
|
||||||
"os"
|
"os"
|
||||||
"reflect"
|
"reflect"
|
||||||
@ -27,12 +26,15 @@ var (
|
|||||||
ErrNoExtendedInfo = errors.New("no extended info")
|
ErrNoExtendedInfo = errors.New("no extended info")
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// ID represents the unique ID of a BTF object.
|
||||||
|
type ID uint32
|
||||||
|
|
||||||
// Spec represents decoded BTF.
|
// Spec represents decoded BTF.
|
||||||
type Spec struct {
|
type Spec struct {
|
||||||
rawTypes []rawType
|
rawTypes []rawType
|
||||||
strings stringTable
|
strings stringTable
|
||||||
types []Type
|
types []Type
|
||||||
namedTypes map[string][]namedType
|
namedTypes map[string][]NamedType
|
||||||
funcInfos map[string]extInfo
|
funcInfos map[string]extInfo
|
||||||
lineInfos map[string]extInfo
|
lineInfos map[string]extInfo
|
||||||
coreRelos map[string]coreRelos
|
coreRelos map[string]coreRelos
|
||||||
@ -61,15 +63,6 @@ func LoadSpecFromReader(rd io.ReaderAt) (*Spec, error) {
|
|||||||
}
|
}
|
||||||
defer file.Close()
|
defer file.Close()
|
||||||
|
|
||||||
btfSection, btfExtSection, sectionSizes, err := findBtfSections(file)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if btfSection == nil {
|
|
||||||
return nil, fmt.Errorf("btf: %w", ErrNotFound)
|
|
||||||
}
|
|
||||||
|
|
||||||
symbols, err := file.Symbols()
|
symbols, err := file.Symbols()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("can't read symbols: %v", err)
|
return nil, fmt.Errorf("can't read symbols: %v", err)
|
||||||
@ -87,10 +80,6 @@ func LoadSpecFromReader(rd io.ReaderAt) (*Spec, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
secName := file.Sections[symbol.Section].Name
|
secName := file.Sections[symbol.Section].Name
|
||||||
if _, ok := sectionSizes[secName]; !ok {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if symbol.Value > math.MaxUint32 {
|
if symbol.Value > math.MaxUint32 {
|
||||||
return nil, fmt.Errorf("section %s: symbol %s: size exceeds maximum", secName, symbol.Name)
|
return nil, fmt.Errorf("section %s: symbol %s: size exceeds maximum", secName, symbol.Name)
|
||||||
}
|
}
|
||||||
@ -98,24 +87,10 @@ func LoadSpecFromReader(rd io.ReaderAt) (*Spec, error) {
|
|||||||
variableOffsets[variable{secName, symbol.Name}] = uint32(symbol.Value)
|
variableOffsets[variable{secName, symbol.Name}] = uint32(symbol.Value)
|
||||||
}
|
}
|
||||||
|
|
||||||
spec, err := loadNakedSpec(btfSection.Open(), file.ByteOrder, sectionSizes, variableOffsets)
|
return loadSpecFromELF(file, variableOffsets)
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if btfExtSection == nil {
|
|
||||||
return spec, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
spec.funcInfos, spec.lineInfos, spec.coreRelos, err = parseExtInfos(btfExtSection.Open(), file.ByteOrder, spec.strings)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("can't read ext info: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return spec, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func findBtfSections(file *internal.SafeELFFile) (*elf.Section, *elf.Section, map[string]uint32, error) {
|
func loadSpecFromELF(file *internal.SafeELFFile, variableOffsets map[variable]uint32) (*Spec, error) {
|
||||||
var (
|
var (
|
||||||
btfSection *elf.Section
|
btfSection *elf.Section
|
||||||
btfExtSection *elf.Section
|
btfExtSection *elf.Section
|
||||||
@ -134,33 +109,45 @@ func findBtfSections(file *internal.SafeELFFile) (*elf.Section, *elf.Section, ma
|
|||||||
}
|
}
|
||||||
|
|
||||||
if sec.Size > math.MaxUint32 {
|
if sec.Size > math.MaxUint32 {
|
||||||
return nil, nil, nil, fmt.Errorf("section %s exceeds maximum size", sec.Name)
|
return nil, fmt.Errorf("section %s exceeds maximum size", sec.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
sectionSizes[sec.Name] = uint32(sec.Size)
|
sectionSizes[sec.Name] = uint32(sec.Size)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return btfSection, btfExtSection, sectionSizes, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func loadSpecFromVmlinux(rd io.ReaderAt) (*Spec, error) {
|
if btfSection == nil {
|
||||||
file, err := internal.NewSafeELFFile(rd)
|
return nil, fmt.Errorf("btf: %w", ErrNotFound)
|
||||||
|
}
|
||||||
|
|
||||||
|
spec, err := loadRawSpec(btfSection.Open(), file.ByteOrder, sectionSizes, variableOffsets)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer file.Close()
|
|
||||||
|
|
||||||
btfSection, _, _, err := findBtfSections(file)
|
if btfExtSection == nil {
|
||||||
|
return spec, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
spec.funcInfos, spec.lineInfos, spec.coreRelos, err = parseExtInfos(btfExtSection.Open(), file.ByteOrder, spec.strings)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf(".BTF ELF section: %s", err)
|
return nil, fmt.Errorf("can't read ext info: %w", err)
|
||||||
}
|
}
|
||||||
if btfSection == nil {
|
|
||||||
return nil, fmt.Errorf("unable to find .BTF ELF section")
|
return spec, nil
|
||||||
}
|
|
||||||
return loadNakedSpec(btfSection.Open(), file.ByteOrder, nil, nil)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadNakedSpec(btf io.ReadSeeker, bo binary.ByteOrder, sectionSizes map[string]uint32, variableOffsets map[variable]uint32) (*Spec, error) {
|
// LoadRawSpec reads a blob of BTF data that isn't wrapped in an ELF file.
|
||||||
|
//
|
||||||
|
// Prefer using LoadSpecFromReader, since this function only supports a subset
|
||||||
|
// of BTF.
|
||||||
|
func LoadRawSpec(btf io.Reader, bo binary.ByteOrder) (*Spec, error) {
|
||||||
|
// This will return an error if we encounter a Datasec, since we can't fix
|
||||||
|
// it up.
|
||||||
|
return loadRawSpec(btf, bo, nil, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func loadRawSpec(btf io.Reader, bo binary.ByteOrder, sectionSizes map[string]uint32, variableOffsets map[variable]uint32) (*Spec, error) {
|
||||||
rawTypes, rawStrings, err := parseBTF(btf, bo)
|
rawTypes, rawStrings, err := parseBTF(btf, bo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -217,7 +204,7 @@ func loadKernelSpec() (*Spec, error) {
|
|||||||
if err == nil {
|
if err == nil {
|
||||||
defer fh.Close()
|
defer fh.Close()
|
||||||
|
|
||||||
return loadNakedSpec(fh, internal.NativeEndian, nil, nil)
|
return LoadRawSpec(fh, internal.NativeEndian)
|
||||||
}
|
}
|
||||||
|
|
||||||
// use same list of locations as libbpf
|
// use same list of locations as libbpf
|
||||||
@ -241,14 +228,20 @@ func loadKernelSpec() (*Spec, error) {
|
|||||||
}
|
}
|
||||||
defer fh.Close()
|
defer fh.Close()
|
||||||
|
|
||||||
return loadSpecFromVmlinux(fh)
|
file, err := internal.NewSafeELFFile(fh)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer file.Close()
|
||||||
|
|
||||||
|
return loadSpecFromELF(file, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, fmt.Errorf("no BTF for kernel version %s: %w", release, internal.ErrNotSupported)
|
return nil, fmt.Errorf("no BTF for kernel version %s: %w", release, internal.ErrNotSupported)
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseBTF(btf io.ReadSeeker, bo binary.ByteOrder) ([]rawType, stringTable, error) {
|
func parseBTF(btf io.Reader, bo binary.ByteOrder) ([]rawType, stringTable, error) {
|
||||||
rawBTF, err := ioutil.ReadAll(btf)
|
rawBTF, err := io.ReadAll(btf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, fmt.Errorf("can't read BTF: %v", err)
|
return nil, nil, fmt.Errorf("can't read BTF: %v", err)
|
||||||
}
|
}
|
||||||
@ -357,6 +350,30 @@ func fixupDatasec(rawTypes []rawType, rawStrings stringTable, sectionSizes map[s
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Copy creates a copy of Spec.
|
||||||
|
func (s *Spec) Copy() *Spec {
|
||||||
|
types, _ := copyTypes(s.types, nil)
|
||||||
|
namedTypes := make(map[string][]NamedType)
|
||||||
|
for _, typ := range types {
|
||||||
|
if named, ok := typ.(NamedType); ok {
|
||||||
|
name := essentialName(named.TypeName())
|
||||||
|
namedTypes[name] = append(namedTypes[name], named)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NB: Other parts of spec are not copied since they are immutable.
|
||||||
|
return &Spec{
|
||||||
|
s.rawTypes,
|
||||||
|
s.strings,
|
||||||
|
types,
|
||||||
|
namedTypes,
|
||||||
|
s.funcInfos,
|
||||||
|
s.lineInfos,
|
||||||
|
s.coreRelos,
|
||||||
|
s.byteOrder,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
type marshalOpts struct {
|
type marshalOpts struct {
|
||||||
ByteOrder binary.ByteOrder
|
ByteOrder binary.ByteOrder
|
||||||
StripFuncLinkage bool
|
StripFuncLinkage bool
|
||||||
@ -447,36 +464,37 @@ func (s *Spec) Program(name string, length uint64) (*Program, error) {
|
|||||||
return &Program{s, length, funcInfos, lineInfos, relos}, nil
|
return &Program{s, length, funcInfos, lineInfos, relos}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Datasec returns the BTF required to create maps which represent data sections.
|
|
||||||
func (s *Spec) Datasec(name string) (*Map, error) {
|
|
||||||
var datasec Datasec
|
|
||||||
if err := s.FindType(name, &datasec); err != nil {
|
|
||||||
return nil, fmt.Errorf("data section %s: can't get BTF: %w", name, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
m := NewMap(s, &Void{}, &datasec)
|
|
||||||
return &m, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// FindType searches for a type with a specific name.
|
// FindType searches for a type with a specific name.
|
||||||
//
|
//
|
||||||
// hint determines the type of the returned Type.
|
// Called T a type that satisfies Type, typ must be a non-nil **T.
|
||||||
|
// On success, the address of the found type will be copied in typ.
|
||||||
//
|
//
|
||||||
// Returns an error wrapping ErrNotFound if no matching
|
// Returns an error wrapping ErrNotFound if no matching
|
||||||
// type exists in spec.
|
// type exists in spec.
|
||||||
func (s *Spec) FindType(name string, typ Type) error {
|
func (s *Spec) FindType(name string, typ interface{}) error {
|
||||||
var (
|
typValue := reflect.ValueOf(typ)
|
||||||
wanted = reflect.TypeOf(typ)
|
if typValue.Kind() != reflect.Ptr {
|
||||||
candidate Type
|
return fmt.Errorf("%T is not a pointer", typ)
|
||||||
)
|
}
|
||||||
|
|
||||||
|
typPtr := typValue.Elem()
|
||||||
|
if !typPtr.CanSet() {
|
||||||
|
return fmt.Errorf("%T cannot be set", typ)
|
||||||
|
}
|
||||||
|
|
||||||
|
wanted := typPtr.Type()
|
||||||
|
if !wanted.AssignableTo(reflect.TypeOf((*Type)(nil)).Elem()) {
|
||||||
|
return fmt.Errorf("%T does not satisfy Type interface", typ)
|
||||||
|
}
|
||||||
|
|
||||||
|
var candidate Type
|
||||||
for _, typ := range s.namedTypes[essentialName(name)] {
|
for _, typ := range s.namedTypes[essentialName(name)] {
|
||||||
if reflect.TypeOf(typ) != wanted {
|
if reflect.TypeOf(typ) != wanted {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// Match against the full name, not just the essential one.
|
// Match against the full name, not just the essential one.
|
||||||
if typ.name() != name {
|
if typ.TypeName() != name {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -491,15 +509,15 @@ func (s *Spec) FindType(name string, typ Type) error {
|
|||||||
return fmt.Errorf("type %s: %w", name, ErrNotFound)
|
return fmt.Errorf("type %s: %w", name, ErrNotFound)
|
||||||
}
|
}
|
||||||
|
|
||||||
cpy, _ := copyType(candidate, nil)
|
typPtr.Set(reflect.ValueOf(candidate))
|
||||||
value := reflect.Indirect(reflect.ValueOf(cpy))
|
|
||||||
reflect.Indirect(reflect.ValueOf(typ)).Set(value)
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle is a reference to BTF loaded into the kernel.
|
// Handle is a reference to BTF loaded into the kernel.
|
||||||
type Handle struct {
|
type Handle struct {
|
||||||
fd *internal.FD
|
spec *Spec
|
||||||
|
fd *internal.FD
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewHandle loads BTF into the kernel.
|
// NewHandle loads BTF into the kernel.
|
||||||
@ -541,7 +559,32 @@ func NewHandle(spec *Spec) (*Handle, error) {
|
|||||||
return nil, internal.ErrorWithLog(err, logBuf, logErr)
|
return nil, internal.ErrorWithLog(err, logBuf, logErr)
|
||||||
}
|
}
|
||||||
|
|
||||||
return &Handle{fd}, nil
|
return &Handle{spec.Copy(), fd}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewHandleFromID returns the BTF handle for a given id.
|
||||||
|
//
|
||||||
|
// Returns ErrNotExist, if there is no BTF with the given id.
|
||||||
|
//
|
||||||
|
// Requires CAP_SYS_ADMIN.
|
||||||
|
func NewHandleFromID(id ID) (*Handle, error) {
|
||||||
|
fd, err := internal.BPFObjGetFDByID(internal.BPF_BTF_GET_FD_BY_ID, uint32(id))
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("get BTF by id: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
info, err := newInfoFromFd(fd)
|
||||||
|
if err != nil {
|
||||||
|
_ = fd.Close()
|
||||||
|
return nil, fmt.Errorf("get BTF spec for handle: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &Handle{info.BTF, fd}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Spec returns the Spec that defined the BTF loaded into the kernel.
|
||||||
|
func (h *Handle) Spec() *Spec {
|
||||||
|
return h.spec
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close destroys the handle.
|
// Close destroys the handle.
|
||||||
@ -563,43 +606,8 @@ func (h *Handle) FD() int {
|
|||||||
|
|
||||||
// Map is the BTF for a map.
|
// Map is the BTF for a map.
|
||||||
type Map struct {
|
type Map struct {
|
||||||
spec *Spec
|
Spec *Spec
|
||||||
key, value Type
|
Key, Value Type
|
||||||
}
|
|
||||||
|
|
||||||
// NewMap returns a new Map containing the given values.
|
|
||||||
// The key and value arguments are initialized to Void if nil values are given.
|
|
||||||
func NewMap(spec *Spec, key Type, value Type) Map {
|
|
||||||
if key == nil {
|
|
||||||
key = &Void{}
|
|
||||||
}
|
|
||||||
if value == nil {
|
|
||||||
value = &Void{}
|
|
||||||
}
|
|
||||||
|
|
||||||
return Map{
|
|
||||||
spec: spec,
|
|
||||||
key: key,
|
|
||||||
value: value,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// MapSpec should be a method on Map, but is a free function
|
|
||||||
// to hide it from users of the ebpf package.
|
|
||||||
func MapSpec(m *Map) *Spec {
|
|
||||||
return m.spec
|
|
||||||
}
|
|
||||||
|
|
||||||
// MapKey should be a method on Map, but is a free function
|
|
||||||
// to hide it from users of the ebpf package.
|
|
||||||
func MapKey(m *Map) Type {
|
|
||||||
return m.key
|
|
||||||
}
|
|
||||||
|
|
||||||
// MapValue should be a method on Map, but is a free function
|
|
||||||
// to hide it from users of the ebpf package.
|
|
||||||
func MapValue(m *Map) Type {
|
|
||||||
return m.value
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Program is the BTF information for a stream of instructions.
|
// Program is the BTF information for a stream of instructions.
|
||||||
@ -610,68 +618,59 @@ type Program struct {
|
|||||||
coreRelos coreRelos
|
coreRelos coreRelos
|
||||||
}
|
}
|
||||||
|
|
||||||
// ProgramSpec returns the Spec needed for loading function and line infos into the kernel.
|
// Spec returns the BTF spec of this program.
|
||||||
//
|
func (p *Program) Spec() *Spec {
|
||||||
// This is a free function instead of a method to hide it from users
|
return p.spec
|
||||||
// of package ebpf.
|
|
||||||
func ProgramSpec(s *Program) *Spec {
|
|
||||||
return s.spec
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ProgramAppend the information from other to the Program.
|
// Append the information from other to the Program.
|
||||||
//
|
func (p *Program) Append(other *Program) error {
|
||||||
// This is a free function instead of a method to hide it from users
|
if other.spec != p.spec {
|
||||||
// of package ebpf.
|
return fmt.Errorf("can't append program with different BTF specs")
|
||||||
func ProgramAppend(s, other *Program) error {
|
}
|
||||||
funcInfos, err := s.funcInfos.append(other.funcInfos, s.length)
|
|
||||||
|
funcInfos, err := p.funcInfos.append(other.funcInfos, p.length)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("func infos: %w", err)
|
return fmt.Errorf("func infos: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
lineInfos, err := s.lineInfos.append(other.lineInfos, s.length)
|
lineInfos, err := p.lineInfos.append(other.lineInfos, p.length)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("line infos: %w", err)
|
return fmt.Errorf("line infos: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
s.funcInfos = funcInfos
|
p.funcInfos = funcInfos
|
||||||
s.lineInfos = lineInfos
|
p.lineInfos = lineInfos
|
||||||
s.coreRelos = s.coreRelos.append(other.coreRelos, s.length)
|
p.coreRelos = p.coreRelos.append(other.coreRelos, p.length)
|
||||||
s.length += other.length
|
p.length += other.length
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ProgramFuncInfos returns the binary form of BTF function infos.
|
// FuncInfos returns the binary form of BTF function infos.
|
||||||
//
|
func (p *Program) FuncInfos() (recordSize uint32, bytes []byte, err error) {
|
||||||
// This is a free function instead of a method to hide it from users
|
bytes, err = p.funcInfos.MarshalBinary()
|
||||||
// of package ebpf.
|
|
||||||
func ProgramFuncInfos(s *Program) (recordSize uint32, bytes []byte, err error) {
|
|
||||||
bytes, err = s.funcInfos.MarshalBinary()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, nil, err
|
return 0, nil, fmt.Errorf("func infos: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return s.funcInfos.recordSize, bytes, nil
|
return p.funcInfos.recordSize, bytes, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ProgramLineInfos returns the binary form of BTF line infos.
|
// LineInfos returns the binary form of BTF line infos.
|
||||||
//
|
func (p *Program) LineInfos() (recordSize uint32, bytes []byte, err error) {
|
||||||
// This is a free function instead of a method to hide it from users
|
bytes, err = p.lineInfos.MarshalBinary()
|
||||||
// of package ebpf.
|
|
||||||
func ProgramLineInfos(s *Program) (recordSize uint32, bytes []byte, err error) {
|
|
||||||
bytes, err = s.lineInfos.MarshalBinary()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, nil, err
|
return 0, nil, fmt.Errorf("line infos: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return s.lineInfos.recordSize, bytes, nil
|
return p.lineInfos.recordSize, bytes, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ProgramFixups returns the changes required to adjust the program to the target.
|
// Fixups returns the changes required to adjust the program to the target.
|
||||||
//
|
//
|
||||||
// This is a free function instead of a method to hide it from users
|
// Passing a nil target will relocate against the running kernel.
|
||||||
// of package ebpf.
|
func (p *Program) Fixups(target *Spec) (COREFixups, error) {
|
||||||
func ProgramFixups(s *Program, target *Spec) (COREFixups, error) {
|
if len(p.coreRelos) == 0 {
|
||||||
if len(s.coreRelos) == 0 {
|
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -683,7 +682,7 @@ func ProgramFixups(s *Program, target *Spec) (COREFixups, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return coreRelocate(s.spec, target, s.coreRelos)
|
return coreRelocate(p.spec, target, p.coreRelos)
|
||||||
}
|
}
|
||||||
|
|
||||||
type bpfLoadBTFAttr struct {
|
type bpfLoadBTFAttr struct {
|
||||||
|
11
vendor/github.com/cilium/ebpf/internal/btf/btf_types.go
generated
vendored
11
vendor/github.com/cilium/ebpf/internal/btf/btf_types.go
generated
vendored
@ -31,6 +31,8 @@ const (
|
|||||||
// Added ~5.1
|
// Added ~5.1
|
||||||
kindVar
|
kindVar
|
||||||
kindDatasec
|
kindDatasec
|
||||||
|
// Added ~5.13
|
||||||
|
kindFloat
|
||||||
)
|
)
|
||||||
|
|
||||||
// FuncLinkage describes BTF function linkage metadata.
|
// FuncLinkage describes BTF function linkage metadata.
|
||||||
@ -54,7 +56,7 @@ const (
|
|||||||
|
|
||||||
const (
|
const (
|
||||||
btfTypeKindShift = 24
|
btfTypeKindShift = 24
|
||||||
btfTypeKindLen = 4
|
btfTypeKindLen = 5
|
||||||
btfTypeVlenShift = 0
|
btfTypeVlenShift = 0
|
||||||
btfTypeVlenMask = 16
|
btfTypeVlenMask = 16
|
||||||
btfTypeKindFlagShift = 31
|
btfTypeKindFlagShift = 31
|
||||||
@ -67,8 +69,8 @@ type btfType struct {
|
|||||||
/* "info" bits arrangement
|
/* "info" bits arrangement
|
||||||
* bits 0-15: vlen (e.g. # of struct's members), linkage
|
* bits 0-15: vlen (e.g. # of struct's members), linkage
|
||||||
* bits 16-23: unused
|
* bits 16-23: unused
|
||||||
* bits 24-27: kind (e.g. int, ptr, array...etc)
|
* bits 24-28: kind (e.g. int, ptr, array...etc)
|
||||||
* bits 28-30: unused
|
* bits 29-30: unused
|
||||||
* bit 31: kind_flag, currently used by
|
* bit 31: kind_flag, currently used by
|
||||||
* struct, union and fwd
|
* struct, union and fwd
|
||||||
*/
|
*/
|
||||||
@ -117,6 +119,8 @@ func (k btfKind) String() string {
|
|||||||
return "Variable"
|
return "Variable"
|
||||||
case kindDatasec:
|
case kindDatasec:
|
||||||
return "Section"
|
return "Section"
|
||||||
|
case kindFloat:
|
||||||
|
return "Float"
|
||||||
default:
|
default:
|
||||||
return fmt.Sprintf("Unknown (%d)", k)
|
return fmt.Sprintf("Unknown (%d)", k)
|
||||||
}
|
}
|
||||||
@ -260,6 +264,7 @@ func readTypes(r io.Reader, bo binary.ByteOrder) ([]rawType, error) {
|
|||||||
data = new(btfVariable)
|
data = new(btfVariable)
|
||||||
case kindDatasec:
|
case kindDatasec:
|
||||||
data = make([]btfVarSecinfo, header.Vlen())
|
data = make([]btfVarSecinfo, header.Vlen())
|
||||||
|
case kindFloat:
|
||||||
default:
|
default:
|
||||||
return nil, fmt.Errorf("type id %v: unknown kind: %v", id, header.Kind())
|
return nil, fmt.Errorf("type id %v: unknown kind: %v", id, header.Kind())
|
||||||
}
|
}
|
||||||
|
33
vendor/github.com/cilium/ebpf/internal/btf/core.go
generated
vendored
33
vendor/github.com/cilium/ebpf/internal/btf/core.go
generated
vendored
@ -234,13 +234,13 @@ func coreRelocate(local, target *Spec, relos coreRelos) (COREFixups, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
localType := local.types[id]
|
localType := local.types[id]
|
||||||
named, ok := localType.(namedType)
|
named, ok := localType.(NamedType)
|
||||||
if !ok || named.name() == "" {
|
if !ok || named.TypeName() == "" {
|
||||||
return nil, fmt.Errorf("relocate unnamed or anonymous type %s: %w", localType, ErrNotSupported)
|
return nil, fmt.Errorf("relocate unnamed or anonymous type %s: %w", localType, ErrNotSupported)
|
||||||
}
|
}
|
||||||
|
|
||||||
relos := relosByID[id]
|
relos := relosByID[id]
|
||||||
targets := target.namedTypes[named.essentialName()]
|
targets := target.namedTypes[essentialName(named.TypeName())]
|
||||||
fixups, err := coreCalculateFixups(localType, targets, relos)
|
fixups, err := coreCalculateFixups(localType, targets, relos)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("relocate %s: %w", localType, err)
|
return nil, fmt.Errorf("relocate %s: %w", localType, err)
|
||||||
@ -262,7 +262,7 @@ var errImpossibleRelocation = errors.New("impossible relocation")
|
|||||||
//
|
//
|
||||||
// The best target is determined by scoring: the less poisoning we have to do
|
// The best target is determined by scoring: the less poisoning we have to do
|
||||||
// the better the target is.
|
// the better the target is.
|
||||||
func coreCalculateFixups(local Type, targets []namedType, relos coreRelos) ([]COREFixup, error) {
|
func coreCalculateFixups(local Type, targets []NamedType, relos coreRelos) ([]COREFixup, error) {
|
||||||
localID := local.ID()
|
localID := local.ID()
|
||||||
local, err := copyType(local, skipQualifierAndTypedef)
|
local, err := copyType(local, skipQualifierAndTypedef)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -467,8 +467,8 @@ func parseCoreAccessor(accessor string) (coreAccessor, error) {
|
|||||||
return nil, fmt.Errorf("empty accessor")
|
return nil, fmt.Errorf("empty accessor")
|
||||||
}
|
}
|
||||||
|
|
||||||
var result coreAccessor
|
|
||||||
parts := strings.Split(accessor, ":")
|
parts := strings.Split(accessor, ":")
|
||||||
|
result := make(coreAccessor, 0, len(parts))
|
||||||
for _, part := range parts {
|
for _, part := range parts {
|
||||||
// 31 bits to avoid overflowing int on 32 bit platforms.
|
// 31 bits to avoid overflowing int on 32 bit platforms.
|
||||||
index, err := strconv.ParseUint(part, 10, 31)
|
index, err := strconv.ParseUint(part, 10, 31)
|
||||||
@ -564,7 +564,7 @@ func coreFindField(local Type, localAcc coreAccessor, target Type) (_, _ coreFie
|
|||||||
|
|
||||||
// This is an anonymous struct or union, ignore it.
|
// This is an anonymous struct or union, ignore it.
|
||||||
local = localMember.Type
|
local = localMember.Type
|
||||||
localOffset += localMember.Offset
|
localOffset += localMember.OffsetBits
|
||||||
localMaybeFlex = false
|
localMaybeFlex = false
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@ -585,10 +585,10 @@ func coreFindField(local Type, localAcc coreAccessor, target Type) (_, _ coreFie
|
|||||||
|
|
||||||
local = localMember.Type
|
local = localMember.Type
|
||||||
localMaybeFlex = acc == len(localMembers)-1
|
localMaybeFlex = acc == len(localMembers)-1
|
||||||
localOffset += localMember.Offset
|
localOffset += localMember.OffsetBits
|
||||||
target = targetMember.Type
|
target = targetMember.Type
|
||||||
targetMaybeFlex = last
|
targetMaybeFlex = last
|
||||||
targetOffset += targetMember.Offset
|
targetOffset += targetMember.OffsetBits
|
||||||
|
|
||||||
case *Array:
|
case *Array:
|
||||||
// For arrays, acc is the index in the target.
|
// For arrays, acc is the index in the target.
|
||||||
@ -639,7 +639,7 @@ func coreFindField(local Type, localAcc coreAccessor, target Type) (_, _ coreFie
|
|||||||
|
|
||||||
// coreFindMember finds a member in a composite type while handling anonymous
|
// coreFindMember finds a member in a composite type while handling anonymous
|
||||||
// structs and unions.
|
// structs and unions.
|
||||||
func coreFindMember(typ composite, name Name) (Member, bool, error) {
|
func coreFindMember(typ composite, name string) (Member, bool, error) {
|
||||||
if name == "" {
|
if name == "" {
|
||||||
return Member{}, false, errors.New("can't search for anonymous member")
|
return Member{}, false, errors.New("can't search for anonymous member")
|
||||||
}
|
}
|
||||||
@ -670,7 +670,7 @@ func coreFindMember(typ composite, name Name) (Member, bool, error) {
|
|||||||
for j, member := range members {
|
for j, member := range members {
|
||||||
if member.Name == name {
|
if member.Name == name {
|
||||||
// NB: This is safe because member is a copy.
|
// NB: This is safe because member is a copy.
|
||||||
member.Offset += target.offset
|
member.OffsetBits += target.offset
|
||||||
return member, j == len(members)-1, nil
|
return member, j == len(members)-1, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -685,7 +685,7 @@ func coreFindMember(typ composite, name Name) (Member, bool, error) {
|
|||||||
return Member{}, false, fmt.Errorf("anonymous non-composite type %T not allowed", member.Type)
|
return Member{}, false, fmt.Errorf("anonymous non-composite type %T not allowed", member.Type)
|
||||||
}
|
}
|
||||||
|
|
||||||
targets = append(targets, offsetTarget{comp, target.offset + member.Offset})
|
targets = append(targets, offsetTarget{comp, target.offset + member.OffsetBits})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -704,9 +704,9 @@ func coreFindEnumValue(local Type, localAcc coreAccessor, target Type) (localVal
|
|||||||
return nil, nil, errImpossibleRelocation
|
return nil, nil, errImpossibleRelocation
|
||||||
}
|
}
|
||||||
|
|
||||||
localName := localValue.Name.essentialName()
|
localName := essentialName(localValue.Name)
|
||||||
for i, targetValue := range targetEnum.Values {
|
for i, targetValue := range targetEnum.Values {
|
||||||
if targetValue.Name.essentialName() != localName {
|
if essentialName(targetValue.Name) != localName {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -813,6 +813,7 @@ func coreAreTypesCompatible(localType Type, targetType Type) error {
|
|||||||
* least one of enums should be anonymous;
|
* least one of enums should be anonymous;
|
||||||
* - for ENUMs, check sizes, names are ignored;
|
* - for ENUMs, check sizes, names are ignored;
|
||||||
* - for INT, size and signedness are ignored;
|
* - for INT, size and signedness are ignored;
|
||||||
|
* - any two FLOATs are always compatible;
|
||||||
* - for ARRAY, dimensionality is ignored, element types are checked for
|
* - for ARRAY, dimensionality is ignored, element types are checked for
|
||||||
* compatibility recursively;
|
* compatibility recursively;
|
||||||
* [ NB: coreAreMembersCompatible doesn't recurse, this check is done
|
* [ NB: coreAreMembersCompatible doesn't recurse, this check is done
|
||||||
@ -848,16 +849,16 @@ func coreAreMembersCompatible(localType Type, targetType Type) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch lv := localType.(type) {
|
switch lv := localType.(type) {
|
||||||
case *Array, *Pointer:
|
case *Array, *Pointer, *Float:
|
||||||
return nil
|
return nil
|
||||||
|
|
||||||
case *Enum:
|
case *Enum:
|
||||||
tv := targetType.(*Enum)
|
tv := targetType.(*Enum)
|
||||||
return doNamesMatch(lv.name(), tv.name())
|
return doNamesMatch(lv.Name, tv.Name)
|
||||||
|
|
||||||
case *Fwd:
|
case *Fwd:
|
||||||
tv := targetType.(*Fwd)
|
tv := targetType.(*Fwd)
|
||||||
return doNamesMatch(lv.name(), tv.name())
|
return doNamesMatch(lv.Name, tv.Name)
|
||||||
|
|
||||||
case *Int:
|
case *Int:
|
||||||
tv := targetType.(*Int)
|
tv := targetType.(*Int)
|
||||||
|
15
vendor/github.com/cilium/ebpf/internal/btf/ext_info.go
generated
vendored
15
vendor/github.com/cilium/ebpf/internal/btf/ext_info.go
generated
vendored
@ -7,7 +7,6 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
|
||||||
|
|
||||||
"github.com/cilium/ebpf/asm"
|
"github.com/cilium/ebpf/asm"
|
||||||
"github.com/cilium/ebpf/internal"
|
"github.com/cilium/ebpf/internal"
|
||||||
@ -64,7 +63,7 @@ func parseExtInfos(r io.ReadSeeker, bo binary.ByteOrder, strings stringTable) (f
|
|||||||
|
|
||||||
// Of course, the .BTF.ext header has different semantics than the
|
// Of course, the .BTF.ext header has different semantics than the
|
||||||
// .BTF ext header. We need to ignore non-null values.
|
// .BTF ext header. We need to ignore non-null values.
|
||||||
_, err = io.CopyN(ioutil.Discard, r, remainder)
|
_, err = io.CopyN(io.Discard, r, remainder)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, nil, fmt.Errorf("header padding: %v", err)
|
return nil, nil, nil, fmt.Errorf("header padding: %v", err)
|
||||||
}
|
}
|
||||||
@ -114,11 +113,16 @@ type extInfoRecord struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type extInfo struct {
|
type extInfo struct {
|
||||||
|
byteOrder binary.ByteOrder
|
||||||
recordSize uint32
|
recordSize uint32
|
||||||
records []extInfoRecord
|
records []extInfoRecord
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ei extInfo) append(other extInfo, offset uint64) (extInfo, error) {
|
func (ei extInfo) append(other extInfo, offset uint64) (extInfo, error) {
|
||||||
|
if other.byteOrder != ei.byteOrder {
|
||||||
|
return extInfo{}, fmt.Errorf("ext_info byte order mismatch, want %v (got %v)", ei.byteOrder, other.byteOrder)
|
||||||
|
}
|
||||||
|
|
||||||
if other.recordSize != ei.recordSize {
|
if other.recordSize != ei.recordSize {
|
||||||
return extInfo{}, fmt.Errorf("ext_info record size mismatch, want %d (got %d)", ei.recordSize, other.recordSize)
|
return extInfo{}, fmt.Errorf("ext_info record size mismatch, want %d (got %d)", ei.recordSize, other.recordSize)
|
||||||
}
|
}
|
||||||
@ -131,10 +135,14 @@ func (ei extInfo) append(other extInfo, offset uint64) (extInfo, error) {
|
|||||||
Opaque: info.Opaque,
|
Opaque: info.Opaque,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
return extInfo{ei.recordSize, records}, nil
|
return extInfo{ei.byteOrder, ei.recordSize, records}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ei extInfo) MarshalBinary() ([]byte, error) {
|
func (ei extInfo) MarshalBinary() ([]byte, error) {
|
||||||
|
if ei.byteOrder != internal.NativeEndian {
|
||||||
|
return nil, fmt.Errorf("%s is not the native byte order", ei.byteOrder)
|
||||||
|
}
|
||||||
|
|
||||||
if len(ei.records) == 0 {
|
if len(ei.records) == 0 {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
@ -197,6 +205,7 @@ func parseExtInfo(r io.Reader, bo binary.ByteOrder, strings stringTable) (map[st
|
|||||||
}
|
}
|
||||||
|
|
||||||
result[secName] = extInfo{
|
result[secName] = extInfo{
|
||||||
|
bo,
|
||||||
recordSize,
|
recordSize,
|
||||||
records,
|
records,
|
||||||
}
|
}
|
||||||
|
1
vendor/github.com/cilium/ebpf/internal/btf/fuzz.go
generated
vendored
1
vendor/github.com/cilium/ebpf/internal/btf/fuzz.go
generated
vendored
@ -1,3 +1,4 @@
|
|||||||
|
//go:build gofuzz
|
||||||
// +build gofuzz
|
// +build gofuzz
|
||||||
|
|
||||||
// Use with https://github.com/dvyukov/go-fuzz
|
// Use with https://github.com/dvyukov/go-fuzz
|
||||||
|
48
vendor/github.com/cilium/ebpf/internal/btf/info.go
generated
vendored
Normal file
48
vendor/github.com/cilium/ebpf/internal/btf/info.go
generated
vendored
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
package btf
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
|
||||||
|
"github.com/cilium/ebpf/internal"
|
||||||
|
)
|
||||||
|
|
||||||
|
// info describes a BTF object.
|
||||||
|
type info struct {
|
||||||
|
BTF *Spec
|
||||||
|
ID ID
|
||||||
|
// Name is an identifying name for the BTF, currently only used by the
|
||||||
|
// kernel.
|
||||||
|
Name string
|
||||||
|
// KernelBTF is true if the BTf originated with the kernel and not
|
||||||
|
// userspace.
|
||||||
|
KernelBTF bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func newInfoFromFd(fd *internal.FD) (*info, error) {
|
||||||
|
// We invoke the syscall once with a empty BTF and name buffers to get size
|
||||||
|
// information to allocate buffers. Then we invoke it a second time with
|
||||||
|
// buffers to receive the data.
|
||||||
|
bpfInfo, err := bpfGetBTFInfoByFD(fd, nil, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
btfBuffer := make([]byte, bpfInfo.btfSize)
|
||||||
|
nameBuffer := make([]byte, bpfInfo.nameLen)
|
||||||
|
bpfInfo, err = bpfGetBTFInfoByFD(fd, btfBuffer, nameBuffer)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
spec, err := loadRawSpec(bytes.NewReader(btfBuffer), internal.NativeEndian, nil, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &info{
|
||||||
|
BTF: spec,
|
||||||
|
ID: ID(bpfInfo.id),
|
||||||
|
Name: internal.CString(nameBuffer),
|
||||||
|
KernelBTF: bpfInfo.kernelBTF != 0,
|
||||||
|
}, nil
|
||||||
|
}
|
8
vendor/github.com/cilium/ebpf/internal/btf/strings.go
generated
vendored
8
vendor/github.com/cilium/ebpf/internal/btf/strings.go
generated
vendored
@ -5,13 +5,12 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type stringTable []byte
|
type stringTable []byte
|
||||||
|
|
||||||
func readStringTable(r io.Reader) (stringTable, error) {
|
func readStringTable(r io.Reader) (stringTable, error) {
|
||||||
contents, err := ioutil.ReadAll(r)
|
contents, err := io.ReadAll(r)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("can't read string table: %v", err)
|
return nil, fmt.Errorf("can't read string table: %v", err)
|
||||||
}
|
}
|
||||||
@ -53,8 +52,3 @@ func (st stringTable) Lookup(offset uint32) (string, error) {
|
|||||||
|
|
||||||
return string(str[:end]), nil
|
return string(str[:end]), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (st stringTable) LookupName(offset uint32) (Name, error) {
|
|
||||||
str, err := st.Lookup(offset)
|
|
||||||
return Name(str), err
|
|
||||||
}
|
|
||||||
|
31
vendor/github.com/cilium/ebpf/internal/btf/syscalls.go
generated
vendored
Normal file
31
vendor/github.com/cilium/ebpf/internal/btf/syscalls.go
generated
vendored
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
package btf
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"github.com/cilium/ebpf/internal"
|
||||||
|
)
|
||||||
|
|
||||||
|
type bpfBTFInfo struct {
|
||||||
|
btf internal.Pointer
|
||||||
|
btfSize uint32
|
||||||
|
id uint32
|
||||||
|
name internal.Pointer
|
||||||
|
nameLen uint32
|
||||||
|
kernelBTF uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
func bpfGetBTFInfoByFD(fd *internal.FD, btf, name []byte) (*bpfBTFInfo, error) {
|
||||||
|
info := bpfBTFInfo{
|
||||||
|
btf: internal.NewSlicePointer(btf),
|
||||||
|
btfSize: uint32(len(btf)),
|
||||||
|
name: internal.NewSlicePointer(name),
|
||||||
|
nameLen: uint32(len(name)),
|
||||||
|
}
|
||||||
|
if err := internal.BPFObjGetInfoByFD(fd, unsafe.Pointer(&info), unsafe.Sizeof(info)); err != nil {
|
||||||
|
return nil, fmt.Errorf("can't get program info: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &info, nil
|
||||||
|
}
|
190
vendor/github.com/cilium/ebpf/internal/btf/types.go
generated
vendored
190
vendor/github.com/cilium/ebpf/internal/btf/types.go
generated
vendored
@ -30,27 +30,26 @@ type Type interface {
|
|||||||
walk(*typeDeque)
|
walk(*typeDeque)
|
||||||
}
|
}
|
||||||
|
|
||||||
// namedType is a type with a name.
|
// NamedType is a type with a name.
|
||||||
//
|
type NamedType interface {
|
||||||
// Most named types simply embed Name.
|
|
||||||
type namedType interface {
|
|
||||||
Type
|
Type
|
||||||
name() string
|
|
||||||
essentialName() string
|
// Name of the type, empty for anonymous types.
|
||||||
|
TypeName() string
|
||||||
}
|
}
|
||||||
|
|
||||||
// Name identifies a type.
|
var (
|
||||||
//
|
_ NamedType = (*Int)(nil)
|
||||||
// Anonymous types have an empty name.
|
_ NamedType = (*Struct)(nil)
|
||||||
type Name string
|
_ NamedType = (*Union)(nil)
|
||||||
|
_ NamedType = (*Enum)(nil)
|
||||||
func (n Name) name() string {
|
_ NamedType = (*Fwd)(nil)
|
||||||
return string(n)
|
_ NamedType = (*Func)(nil)
|
||||||
}
|
_ NamedType = (*Typedef)(nil)
|
||||||
|
_ NamedType = (*Var)(nil)
|
||||||
func (n Name) essentialName() string {
|
_ NamedType = (*Datasec)(nil)
|
||||||
return essentialName(string(n))
|
_ NamedType = (*Float)(nil)
|
||||||
}
|
)
|
||||||
|
|
||||||
// Void is the unit type of BTF.
|
// Void is the unit type of BTF.
|
||||||
type Void struct{}
|
type Void struct{}
|
||||||
@ -72,19 +71,17 @@ const (
|
|||||||
// Int is an integer of a given length.
|
// Int is an integer of a given length.
|
||||||
type Int struct {
|
type Int struct {
|
||||||
TypeID
|
TypeID
|
||||||
Name
|
Name string
|
||||||
|
|
||||||
// The size of the integer in bytes.
|
// The size of the integer in bytes.
|
||||||
Size uint32
|
Size uint32
|
||||||
Encoding IntEncoding
|
Encoding IntEncoding
|
||||||
// Offset is the starting bit offset. Currently always 0.
|
// OffsetBits is the starting bit offset. Currently always 0.
|
||||||
// See https://www.kernel.org/doc/html/latest/bpf/btf.html#btf-kind-int
|
// See https://www.kernel.org/doc/html/latest/bpf/btf.html#btf-kind-int
|
||||||
Offset uint32
|
OffsetBits uint32
|
||||||
Bits byte
|
Bits byte
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ namedType = (*Int)(nil)
|
|
||||||
|
|
||||||
func (i *Int) String() string {
|
func (i *Int) String() string {
|
||||||
var s strings.Builder
|
var s strings.Builder
|
||||||
|
|
||||||
@ -110,15 +107,16 @@ func (i *Int) String() string {
|
|||||||
return s.String()
|
return s.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *Int) size() uint32 { return i.Size }
|
func (i *Int) TypeName() string { return i.Name }
|
||||||
func (i *Int) walk(*typeDeque) {}
|
func (i *Int) size() uint32 { return i.Size }
|
||||||
|
func (i *Int) walk(*typeDeque) {}
|
||||||
func (i *Int) copy() Type {
|
func (i *Int) copy() Type {
|
||||||
cpy := *i
|
cpy := *i
|
||||||
return &cpy
|
return &cpy
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *Int) isBitfield() bool {
|
func (i *Int) isBitfield() bool {
|
||||||
return i.Offset > 0
|
return i.OffsetBits > 0
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pointer is a pointer to another type.
|
// Pointer is a pointer to another type.
|
||||||
@ -158,7 +156,7 @@ func (arr *Array) copy() Type {
|
|||||||
// Struct is a compound type of consecutive members.
|
// Struct is a compound type of consecutive members.
|
||||||
type Struct struct {
|
type Struct struct {
|
||||||
TypeID
|
TypeID
|
||||||
Name
|
Name string
|
||||||
// The size of the struct including padding, in bytes
|
// The size of the struct including padding, in bytes
|
||||||
Size uint32
|
Size uint32
|
||||||
Members []Member
|
Members []Member
|
||||||
@ -168,6 +166,8 @@ func (s *Struct) String() string {
|
|||||||
return fmt.Sprintf("struct#%d[%q]", s.TypeID, s.Name)
|
return fmt.Sprintf("struct#%d[%q]", s.TypeID, s.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Struct) TypeName() string { return s.Name }
|
||||||
|
|
||||||
func (s *Struct) size() uint32 { return s.Size }
|
func (s *Struct) size() uint32 { return s.Size }
|
||||||
|
|
||||||
func (s *Struct) walk(tdq *typeDeque) {
|
func (s *Struct) walk(tdq *typeDeque) {
|
||||||
@ -189,7 +189,7 @@ func (s *Struct) members() []Member {
|
|||||||
// Union is a compound type where members occupy the same memory.
|
// Union is a compound type where members occupy the same memory.
|
||||||
type Union struct {
|
type Union struct {
|
||||||
TypeID
|
TypeID
|
||||||
Name
|
Name string
|
||||||
// The size of the union including padding, in bytes.
|
// The size of the union including padding, in bytes.
|
||||||
Size uint32
|
Size uint32
|
||||||
Members []Member
|
Members []Member
|
||||||
@ -199,6 +199,8 @@ func (u *Union) String() string {
|
|||||||
return fmt.Sprintf("union#%d[%q]", u.TypeID, u.Name)
|
return fmt.Sprintf("union#%d[%q]", u.TypeID, u.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (u *Union) TypeName() string { return u.Name }
|
||||||
|
|
||||||
func (u *Union) size() uint32 { return u.Size }
|
func (u *Union) size() uint32 { return u.Size }
|
||||||
|
|
||||||
func (u *Union) walk(tdq *typeDeque) {
|
func (u *Union) walk(tdq *typeDeque) {
|
||||||
@ -236,17 +238,17 @@ var (
|
|||||||
//
|
//
|
||||||
// It is not a valid Type.
|
// It is not a valid Type.
|
||||||
type Member struct {
|
type Member struct {
|
||||||
Name
|
Name string
|
||||||
Type Type
|
Type Type
|
||||||
// Offset is the bit offset of this member
|
// OffsetBits is the bit offset of this member.
|
||||||
Offset uint32
|
OffsetBits uint32
|
||||||
BitfieldSize uint32
|
BitfieldSize uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enum lists possible values.
|
// Enum lists possible values.
|
||||||
type Enum struct {
|
type Enum struct {
|
||||||
TypeID
|
TypeID
|
||||||
Name
|
Name string
|
||||||
Values []EnumValue
|
Values []EnumValue
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -254,11 +256,13 @@ func (e *Enum) String() string {
|
|||||||
return fmt.Sprintf("enum#%d[%q]", e.TypeID, e.Name)
|
return fmt.Sprintf("enum#%d[%q]", e.TypeID, e.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (e *Enum) TypeName() string { return e.Name }
|
||||||
|
|
||||||
// EnumValue is part of an Enum
|
// EnumValue is part of an Enum
|
||||||
//
|
//
|
||||||
// Is is not a valid Type
|
// Is is not a valid Type
|
||||||
type EnumValue struct {
|
type EnumValue struct {
|
||||||
Name
|
Name string
|
||||||
Value int32
|
Value int32
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -294,7 +298,7 @@ func (fk FwdKind) String() string {
|
|||||||
// Fwd is a forward declaration of a Type.
|
// Fwd is a forward declaration of a Type.
|
||||||
type Fwd struct {
|
type Fwd struct {
|
||||||
TypeID
|
TypeID
|
||||||
Name
|
Name string
|
||||||
Kind FwdKind
|
Kind FwdKind
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -302,6 +306,8 @@ func (f *Fwd) String() string {
|
|||||||
return fmt.Sprintf("fwd#%d[%s %q]", f.TypeID, f.Kind, f.Name)
|
return fmt.Sprintf("fwd#%d[%s %q]", f.TypeID, f.Kind, f.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (f *Fwd) TypeName() string { return f.Name }
|
||||||
|
|
||||||
func (f *Fwd) walk(*typeDeque) {}
|
func (f *Fwd) walk(*typeDeque) {}
|
||||||
func (f *Fwd) copy() Type {
|
func (f *Fwd) copy() Type {
|
||||||
cpy := *f
|
cpy := *f
|
||||||
@ -311,7 +317,7 @@ func (f *Fwd) copy() Type {
|
|||||||
// Typedef is an alias of a Type.
|
// Typedef is an alias of a Type.
|
||||||
type Typedef struct {
|
type Typedef struct {
|
||||||
TypeID
|
TypeID
|
||||||
Name
|
Name string
|
||||||
Type Type
|
Type Type
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -319,6 +325,8 @@ func (td *Typedef) String() string {
|
|||||||
return fmt.Sprintf("typedef#%d[%q #%d]", td.TypeID, td.Name, td.Type.ID())
|
return fmt.Sprintf("typedef#%d[%q #%d]", td.TypeID, td.Name, td.Type.ID())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (td *Typedef) TypeName() string { return td.Name }
|
||||||
|
|
||||||
func (td *Typedef) walk(tdq *typeDeque) { tdq.push(&td.Type) }
|
func (td *Typedef) walk(tdq *typeDeque) { tdq.push(&td.Type) }
|
||||||
func (td *Typedef) copy() Type {
|
func (td *Typedef) copy() Type {
|
||||||
cpy := *td
|
cpy := *td
|
||||||
@ -379,7 +387,7 @@ func (r *Restrict) copy() Type {
|
|||||||
// Func is a function definition.
|
// Func is a function definition.
|
||||||
type Func struct {
|
type Func struct {
|
||||||
TypeID
|
TypeID
|
||||||
Name
|
Name string
|
||||||
Type Type
|
Type Type
|
||||||
Linkage FuncLinkage
|
Linkage FuncLinkage
|
||||||
}
|
}
|
||||||
@ -388,6 +396,8 @@ func (f *Func) String() string {
|
|||||||
return fmt.Sprintf("func#%d[%s %q proto=#%d]", f.TypeID, f.Linkage, f.Name, f.Type.ID())
|
return fmt.Sprintf("func#%d[%s %q proto=#%d]", f.TypeID, f.Linkage, f.Name, f.Type.ID())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (f *Func) TypeName() string { return f.Name }
|
||||||
|
|
||||||
func (f *Func) walk(tdq *typeDeque) { tdq.push(&f.Type) }
|
func (f *Func) walk(tdq *typeDeque) { tdq.push(&f.Type) }
|
||||||
func (f *Func) copy() Type {
|
func (f *Func) copy() Type {
|
||||||
cpy := *f
|
cpy := *f
|
||||||
@ -426,14 +436,14 @@ func (fp *FuncProto) copy() Type {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type FuncParam struct {
|
type FuncParam struct {
|
||||||
Name
|
Name string
|
||||||
Type Type
|
Type Type
|
||||||
}
|
}
|
||||||
|
|
||||||
// Var is a global variable.
|
// Var is a global variable.
|
||||||
type Var struct {
|
type Var struct {
|
||||||
TypeID
|
TypeID
|
||||||
Name
|
Name string
|
||||||
Type Type
|
Type Type
|
||||||
Linkage VarLinkage
|
Linkage VarLinkage
|
||||||
}
|
}
|
||||||
@ -442,6 +452,8 @@ func (v *Var) String() string {
|
|||||||
return fmt.Sprintf("var#%d[%s %q]", v.TypeID, v.Linkage, v.Name)
|
return fmt.Sprintf("var#%d[%s %q]", v.TypeID, v.Linkage, v.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (v *Var) TypeName() string { return v.Name }
|
||||||
|
|
||||||
func (v *Var) walk(tdq *typeDeque) { tdq.push(&v.Type) }
|
func (v *Var) walk(tdq *typeDeque) { tdq.push(&v.Type) }
|
||||||
func (v *Var) copy() Type {
|
func (v *Var) copy() Type {
|
||||||
cpy := *v
|
cpy := *v
|
||||||
@ -451,7 +463,7 @@ func (v *Var) copy() Type {
|
|||||||
// Datasec is a global program section containing data.
|
// Datasec is a global program section containing data.
|
||||||
type Datasec struct {
|
type Datasec struct {
|
||||||
TypeID
|
TypeID
|
||||||
Name
|
Name string
|
||||||
Size uint32
|
Size uint32
|
||||||
Vars []VarSecinfo
|
Vars []VarSecinfo
|
||||||
}
|
}
|
||||||
@ -460,6 +472,8 @@ func (ds *Datasec) String() string {
|
|||||||
return fmt.Sprintf("section#%d[%q]", ds.TypeID, ds.Name)
|
return fmt.Sprintf("section#%d[%q]", ds.TypeID, ds.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ds *Datasec) TypeName() string { return ds.Name }
|
||||||
|
|
||||||
func (ds *Datasec) size() uint32 { return ds.Size }
|
func (ds *Datasec) size() uint32 { return ds.Size }
|
||||||
|
|
||||||
func (ds *Datasec) walk(tdq *typeDeque) {
|
func (ds *Datasec) walk(tdq *typeDeque) {
|
||||||
@ -475,7 +489,7 @@ func (ds *Datasec) copy() Type {
|
|||||||
return &cpy
|
return &cpy
|
||||||
}
|
}
|
||||||
|
|
||||||
// VarSecinfo describes variable in a Datasec
|
// VarSecinfo describes variable in a Datasec.
|
||||||
//
|
//
|
||||||
// It is not a valid Type.
|
// It is not a valid Type.
|
||||||
type VarSecinfo struct {
|
type VarSecinfo struct {
|
||||||
@ -484,6 +498,27 @@ type VarSecinfo struct {
|
|||||||
Size uint32
|
Size uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Float is a float of a given length.
|
||||||
|
type Float struct {
|
||||||
|
TypeID
|
||||||
|
Name string
|
||||||
|
|
||||||
|
// The size of the float in bytes.
|
||||||
|
Size uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *Float) String() string {
|
||||||
|
return fmt.Sprintf("float%d#%d[%q]", f.Size*8, f.TypeID, f.Name)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *Float) TypeName() string { return f.Name }
|
||||||
|
func (f *Float) size() uint32 { return f.Size }
|
||||||
|
func (f *Float) walk(*typeDeque) {}
|
||||||
|
func (f *Float) copy() Type {
|
||||||
|
cpy := *f
|
||||||
|
return &cpy
|
||||||
|
}
|
||||||
|
|
||||||
type sizer interface {
|
type sizer interface {
|
||||||
size() uint32
|
size() uint32
|
||||||
}
|
}
|
||||||
@ -565,14 +600,36 @@ func Sizeof(typ Type) (int, error) {
|
|||||||
//
|
//
|
||||||
// Returns any errors from transform verbatim.
|
// Returns any errors from transform verbatim.
|
||||||
func copyType(typ Type, transform func(Type) (Type, error)) (Type, error) {
|
func copyType(typ Type, transform func(Type) (Type, error)) (Type, error) {
|
||||||
var (
|
copies := make(copier)
|
||||||
copies = make(map[Type]Type)
|
return typ, copies.copy(&typ, transform)
|
||||||
work typeDeque
|
}
|
||||||
)
|
|
||||||
|
|
||||||
for t := &typ; t != nil; t = work.pop() {
|
// copy a slice of Types recursively.
|
||||||
|
//
|
||||||
|
// Types may form a cycle.
|
||||||
|
//
|
||||||
|
// Returns any errors from transform verbatim.
|
||||||
|
func copyTypes(types []Type, transform func(Type) (Type, error)) ([]Type, error) {
|
||||||
|
result := make([]Type, len(types))
|
||||||
|
copy(result, types)
|
||||||
|
|
||||||
|
copies := make(copier)
|
||||||
|
for i := range result {
|
||||||
|
if err := copies.copy(&result[i], transform); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type copier map[Type]Type
|
||||||
|
|
||||||
|
func (c copier) copy(typ *Type, transform func(Type) (Type, error)) error {
|
||||||
|
var work typeDeque
|
||||||
|
for t := typ; t != nil; t = work.pop() {
|
||||||
// *t is the identity of the type.
|
// *t is the identity of the type.
|
||||||
if cpy := copies[*t]; cpy != nil {
|
if cpy := c[*t]; cpy != nil {
|
||||||
*t = cpy
|
*t = cpy
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@ -581,21 +638,21 @@ func copyType(typ Type, transform func(Type) (Type, error)) (Type, error) {
|
|||||||
if transform != nil {
|
if transform != nil {
|
||||||
tf, err := transform(*t)
|
tf, err := transform(*t)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("copy %s: %w", typ, err)
|
return fmt.Errorf("copy %s: %w", *t, err)
|
||||||
}
|
}
|
||||||
cpy = tf.copy()
|
cpy = tf.copy()
|
||||||
} else {
|
} else {
|
||||||
cpy = (*t).copy()
|
cpy = (*t).copy()
|
||||||
}
|
}
|
||||||
|
|
||||||
copies[*t] = cpy
|
c[*t] = cpy
|
||||||
*t = cpy
|
*t = cpy
|
||||||
|
|
||||||
// Mark any nested types for copying.
|
// Mark any nested types for copying.
|
||||||
cpy.walk(&work)
|
cpy.walk(&work)
|
||||||
}
|
}
|
||||||
|
|
||||||
return typ, nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// typeDeque keeps track of pointers to types which still
|
// typeDeque keeps track of pointers to types which still
|
||||||
@ -606,6 +663,10 @@ type typeDeque struct {
|
|||||||
mask uint64
|
mask uint64
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (dq *typeDeque) empty() bool {
|
||||||
|
return dq.read == dq.write
|
||||||
|
}
|
||||||
|
|
||||||
// push adds a type to the stack.
|
// push adds a type to the stack.
|
||||||
func (dq *typeDeque) push(t *Type) {
|
func (dq *typeDeque) push(t *Type) {
|
||||||
if dq.write-dq.read < uint64(len(dq.types)) {
|
if dq.write-dq.read < uint64(len(dq.types)) {
|
||||||
@ -632,7 +693,7 @@ func (dq *typeDeque) push(t *Type) {
|
|||||||
|
|
||||||
// shift returns the first element or null.
|
// shift returns the first element or null.
|
||||||
func (dq *typeDeque) shift() *Type {
|
func (dq *typeDeque) shift() *Type {
|
||||||
if dq.read == dq.write {
|
if dq.empty() {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -645,7 +706,7 @@ func (dq *typeDeque) shift() *Type {
|
|||||||
|
|
||||||
// pop returns the last element or null.
|
// pop returns the last element or null.
|
||||||
func (dq *typeDeque) pop() *Type {
|
func (dq *typeDeque) pop() *Type {
|
||||||
if dq.read == dq.write {
|
if dq.empty() {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -674,7 +735,7 @@ func (dq *typeDeque) all() []*Type {
|
|||||||
// Returns a map of named types (so, where NameOff is non-zero) and a slice of types
|
// Returns a map of named types (so, where NameOff is non-zero) and a slice of types
|
||||||
// indexed by TypeID. Since BTF ignores compilation units, multiple types may share
|
// indexed by TypeID. Since BTF ignores compilation units, multiple types may share
|
||||||
// the same name. A Type may form a cyclic graph by pointing at itself.
|
// the same name. A Type may form a cyclic graph by pointing at itself.
|
||||||
func inflateRawTypes(rawTypes []rawType, rawStrings stringTable) (types []Type, namedTypes map[string][]namedType, err error) {
|
func inflateRawTypes(rawTypes []rawType, rawStrings stringTable) (types []Type, namedTypes map[string][]NamedType, err error) {
|
||||||
type fixupDef struct {
|
type fixupDef struct {
|
||||||
id TypeID
|
id TypeID
|
||||||
expectedKind btfKind
|
expectedKind btfKind
|
||||||
@ -691,17 +752,17 @@ func inflateRawTypes(rawTypes []rawType, rawStrings stringTable) (types []Type,
|
|||||||
// work, since otherwise append might re-allocate members.
|
// work, since otherwise append might re-allocate members.
|
||||||
members := make([]Member, 0, len(raw))
|
members := make([]Member, 0, len(raw))
|
||||||
for i, btfMember := range raw {
|
for i, btfMember := range raw {
|
||||||
name, err := rawStrings.LookupName(btfMember.NameOff)
|
name, err := rawStrings.Lookup(btfMember.NameOff)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("can't get name for member %d: %w", i, err)
|
return nil, fmt.Errorf("can't get name for member %d: %w", i, err)
|
||||||
}
|
}
|
||||||
m := Member{
|
m := Member{
|
||||||
Name: name,
|
Name: name,
|
||||||
Offset: btfMember.Offset,
|
OffsetBits: btfMember.Offset,
|
||||||
}
|
}
|
||||||
if kindFlag {
|
if kindFlag {
|
||||||
m.BitfieldSize = btfMember.Offset >> 24
|
m.BitfieldSize = btfMember.Offset >> 24
|
||||||
m.Offset &= 0xffffff
|
m.OffsetBits &= 0xffffff
|
||||||
}
|
}
|
||||||
members = append(members, m)
|
members = append(members, m)
|
||||||
}
|
}
|
||||||
@ -713,7 +774,7 @@ func inflateRawTypes(rawTypes []rawType, rawStrings stringTable) (types []Type,
|
|||||||
|
|
||||||
types = make([]Type, 0, len(rawTypes))
|
types = make([]Type, 0, len(rawTypes))
|
||||||
types = append(types, (*Void)(nil))
|
types = append(types, (*Void)(nil))
|
||||||
namedTypes = make(map[string][]namedType)
|
namedTypes = make(map[string][]NamedType)
|
||||||
|
|
||||||
for i, raw := range rawTypes {
|
for i, raw := range rawTypes {
|
||||||
var (
|
var (
|
||||||
@ -723,7 +784,7 @@ func inflateRawTypes(rawTypes []rawType, rawStrings stringTable) (types []Type,
|
|||||||
typ Type
|
typ Type
|
||||||
)
|
)
|
||||||
|
|
||||||
name, err := rawStrings.LookupName(raw.NameOff)
|
name, err := rawStrings.Lookup(raw.NameOff)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, fmt.Errorf("get name for type id %d: %w", id, err)
|
return nil, nil, fmt.Errorf("get name for type id %d: %w", id, err)
|
||||||
}
|
}
|
||||||
@ -765,7 +826,7 @@ func inflateRawTypes(rawTypes []rawType, rawStrings stringTable) (types []Type,
|
|||||||
rawvals := raw.data.([]btfEnum)
|
rawvals := raw.data.([]btfEnum)
|
||||||
vals := make([]EnumValue, 0, len(rawvals))
|
vals := make([]EnumValue, 0, len(rawvals))
|
||||||
for i, btfVal := range rawvals {
|
for i, btfVal := range rawvals {
|
||||||
name, err := rawStrings.LookupName(btfVal.NameOff)
|
name, err := rawStrings.Lookup(btfVal.NameOff)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, fmt.Errorf("get name for enum value %d: %s", i, err)
|
return nil, nil, fmt.Errorf("get name for enum value %d: %s", i, err)
|
||||||
}
|
}
|
||||||
@ -812,7 +873,7 @@ func inflateRawTypes(rawTypes []rawType, rawStrings stringTable) (types []Type,
|
|||||||
rawparams := raw.data.([]btfParam)
|
rawparams := raw.data.([]btfParam)
|
||||||
params := make([]FuncParam, 0, len(rawparams))
|
params := make([]FuncParam, 0, len(rawparams))
|
||||||
for i, param := range rawparams {
|
for i, param := range rawparams {
|
||||||
name, err := rawStrings.LookupName(param.NameOff)
|
name, err := rawStrings.Lookup(param.NameOff)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, fmt.Errorf("get name for func proto parameter %d: %s", i, err)
|
return nil, nil, fmt.Errorf("get name for func proto parameter %d: %s", i, err)
|
||||||
}
|
}
|
||||||
@ -848,14 +909,17 @@ func inflateRawTypes(rawTypes []rawType, rawStrings stringTable) (types []Type,
|
|||||||
}
|
}
|
||||||
typ = &Datasec{id, name, raw.SizeType, vars}
|
typ = &Datasec{id, name, raw.SizeType, vars}
|
||||||
|
|
||||||
|
case kindFloat:
|
||||||
|
typ = &Float{id, name, raw.Size()}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return nil, nil, fmt.Errorf("type id %d: unknown kind: %v", id, raw.Kind())
|
return nil, nil, fmt.Errorf("type id %d: unknown kind: %v", id, raw.Kind())
|
||||||
}
|
}
|
||||||
|
|
||||||
types = append(types, typ)
|
types = append(types, typ)
|
||||||
|
|
||||||
if named, ok := typ.(namedType); ok {
|
if named, ok := typ.(NamedType); ok {
|
||||||
if name := essentialName(named.name()); name != "" {
|
if name := essentialName(named.TypeName()); name != "" {
|
||||||
namedTypes[name] = append(namedTypes[name], named)
|
namedTypes[name] = append(namedTypes[name], named)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
4
vendor/github.com/cilium/ebpf/internal/cpu.go
generated
vendored
4
vendor/github.com/cilium/ebpf/internal/cpu.go
generated
vendored
@ -2,7 +2,7 @@ package internal
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
)
|
)
|
||||||
@ -24,7 +24,7 @@ func PossibleCPUs() (int, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func parseCPUsFromFile(path string) (int, error) {
|
func parseCPUsFromFile(path string) (int, error) {
|
||||||
spec, err := ioutil.ReadFile(path)
|
spec, err := os.ReadFile(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
1
vendor/github.com/cilium/ebpf/internal/ptr_32_be.go
generated
vendored
1
vendor/github.com/cilium/ebpf/internal/ptr_32_be.go
generated
vendored
@ -1,3 +1,4 @@
|
|||||||
|
//go:build armbe || mips || mips64p32
|
||||||
// +build armbe mips mips64p32
|
// +build armbe mips mips64p32
|
||||||
|
|
||||||
package internal
|
package internal
|
||||||
|
1
vendor/github.com/cilium/ebpf/internal/ptr_32_le.go
generated
vendored
1
vendor/github.com/cilium/ebpf/internal/ptr_32_le.go
generated
vendored
@ -1,3 +1,4 @@
|
|||||||
|
//go:build 386 || amd64p32 || arm || mipsle || mips64p32le
|
||||||
// +build 386 amd64p32 arm mipsle mips64p32le
|
// +build 386 amd64p32 arm mipsle mips64p32le
|
||||||
|
|
||||||
package internal
|
package internal
|
||||||
|
4
vendor/github.com/cilium/ebpf/internal/ptr_64.go
generated
vendored
4
vendor/github.com/cilium/ebpf/internal/ptr_64.go
generated
vendored
@ -1,5 +1,5 @@
|
|||||||
// +build !386,!amd64p32,!arm,!mipsle,!mips64p32le
|
//go:build !386 && !amd64p32 && !arm && !mipsle && !mips64p32le && !armbe && !mips && !mips64p32
|
||||||
// +build !armbe,!mips,!mips64p32
|
// +build !386,!amd64p32,!arm,!mipsle,!mips64p32le,!armbe,!mips,!mips64p32
|
||||||
|
|
||||||
package internal
|
package internal
|
||||||
|
|
||||||
|
59
vendor/github.com/cilium/ebpf/internal/syscall.go
generated
vendored
59
vendor/github.com/cilium/ebpf/internal/syscall.go
generated
vendored
@ -1,6 +1,7 @@
|
|||||||
package internal
|
package internal
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
@ -68,6 +69,48 @@ func BPF(cmd BPFCmd, attr unsafe.Pointer, size uintptr) (uintptr, error) {
|
|||||||
return r1, err
|
return r1, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type BPFProgLoadAttr struct {
|
||||||
|
ProgType uint32
|
||||||
|
InsCount uint32
|
||||||
|
Instructions Pointer
|
||||||
|
License Pointer
|
||||||
|
LogLevel uint32
|
||||||
|
LogSize uint32
|
||||||
|
LogBuf Pointer
|
||||||
|
KernelVersion uint32 // since 4.1 2541517c32be
|
||||||
|
ProgFlags uint32 // since 4.11 e07b98d9bffe
|
||||||
|
ProgName BPFObjName // since 4.15 067cae47771c
|
||||||
|
ProgIfIndex uint32 // since 4.15 1f6f4cb7ba21
|
||||||
|
ExpectedAttachType uint32 // since 4.17 5e43f899b03a
|
||||||
|
ProgBTFFd uint32
|
||||||
|
FuncInfoRecSize uint32
|
||||||
|
FuncInfo Pointer
|
||||||
|
FuncInfoCnt uint32
|
||||||
|
LineInfoRecSize uint32
|
||||||
|
LineInfo Pointer
|
||||||
|
LineInfoCnt uint32
|
||||||
|
AttachBTFID uint32
|
||||||
|
AttachProgFd uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
// BPFProgLoad wraps BPF_PROG_LOAD.
|
||||||
|
func BPFProgLoad(attr *BPFProgLoadAttr) (*FD, error) {
|
||||||
|
for {
|
||||||
|
fd, err := BPF(BPF_PROG_LOAD, unsafe.Pointer(attr), unsafe.Sizeof(*attr))
|
||||||
|
// As of ~4.20 the verifier can be interrupted by a signal,
|
||||||
|
// and returns EAGAIN in that case.
|
||||||
|
if errors.Is(err, unix.EAGAIN) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return NewFD(uint32(fd)), nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
type BPFProgAttachAttr struct {
|
type BPFProgAttachAttr struct {
|
||||||
TargetFd uint32
|
TargetFd uint32
|
||||||
AttachBpfFd uint32
|
AttachBpfFd uint32
|
||||||
@ -180,6 +223,22 @@ func BPFObjGetInfoByFD(fd *FD, info unsafe.Pointer, size uintptr) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type bpfGetFDByIDAttr struct {
|
||||||
|
id uint32
|
||||||
|
next uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
// BPFObjGetInfoByFD wraps BPF_*_GET_FD_BY_ID.
|
||||||
|
//
|
||||||
|
// Available from 4.13.
|
||||||
|
func BPFObjGetFDByID(cmd BPFCmd, id uint32) (*FD, error) {
|
||||||
|
attr := bpfGetFDByIDAttr{
|
||||||
|
id: id,
|
||||||
|
}
|
||||||
|
ptr, err := BPF(cmd, unsafe.Pointer(&attr), unsafe.Sizeof(attr))
|
||||||
|
return NewFD(uint32(ptr)), err
|
||||||
|
}
|
||||||
|
|
||||||
// BPFObjName is a null-terminated string made up of
|
// BPFObjName is a null-terminated string made up of
|
||||||
// 'A-Za-z0-9_' characters.
|
// 'A-Za-z0-9_' characters.
|
||||||
type BPFObjName [unix.BPF_OBJ_NAME_LEN]byte
|
type BPFObjName [unix.BPF_OBJ_NAME_LEN]byte
|
||||||
|
16
vendor/github.com/cilium/ebpf/internal/unix/types_linux.go
generated
vendored
16
vendor/github.com/cilium/ebpf/internal/unix/types_linux.go
generated
vendored
@ -1,3 +1,4 @@
|
|||||||
|
//go:build linux
|
||||||
// +build linux
|
// +build linux
|
||||||
|
|
||||||
package unix
|
package unix
|
||||||
@ -20,10 +21,11 @@ const (
|
|||||||
EPERM = linux.EPERM
|
EPERM = linux.EPERM
|
||||||
ESRCH = linux.ESRCH
|
ESRCH = linux.ESRCH
|
||||||
ENODEV = linux.ENODEV
|
ENODEV = linux.ENODEV
|
||||||
|
EBADF = linux.EBADF
|
||||||
|
E2BIG = linux.E2BIG
|
||||||
// ENOTSUPP is not the same as ENOTSUP or EOPNOTSUP
|
// ENOTSUPP is not the same as ENOTSUP or EOPNOTSUP
|
||||||
ENOTSUPP = syscall.Errno(0x20c)
|
ENOTSUPP = syscall.Errno(0x20c)
|
||||||
|
|
||||||
EBADF = linux.EBADF
|
|
||||||
BPF_F_NO_PREALLOC = linux.BPF_F_NO_PREALLOC
|
BPF_F_NO_PREALLOC = linux.BPF_F_NO_PREALLOC
|
||||||
BPF_F_NUMA_NODE = linux.BPF_F_NUMA_NODE
|
BPF_F_NUMA_NODE = linux.BPF_F_NUMA_NODE
|
||||||
BPF_F_RDONLY = linux.BPF_F_RDONLY
|
BPF_F_RDONLY = linux.BPF_F_RDONLY
|
||||||
@ -35,6 +37,9 @@ const (
|
|||||||
BPF_F_INNER_MAP = linux.BPF_F_INNER_MAP
|
BPF_F_INNER_MAP = linux.BPF_F_INNER_MAP
|
||||||
BPF_OBJ_NAME_LEN = linux.BPF_OBJ_NAME_LEN
|
BPF_OBJ_NAME_LEN = linux.BPF_OBJ_NAME_LEN
|
||||||
BPF_TAG_SIZE = linux.BPF_TAG_SIZE
|
BPF_TAG_SIZE = linux.BPF_TAG_SIZE
|
||||||
|
BPF_RINGBUF_BUSY_BIT = linux.BPF_RINGBUF_BUSY_BIT
|
||||||
|
BPF_RINGBUF_DISCARD_BIT = linux.BPF_RINGBUF_DISCARD_BIT
|
||||||
|
BPF_RINGBUF_HDR_SZ = linux.BPF_RINGBUF_HDR_SZ
|
||||||
SYS_BPF = linux.SYS_BPF
|
SYS_BPF = linux.SYS_BPF
|
||||||
F_DUPFD_CLOEXEC = linux.F_DUPFD_CLOEXEC
|
F_DUPFD_CLOEXEC = linux.F_DUPFD_CLOEXEC
|
||||||
EPOLL_CTL_ADD = linux.EPOLL_CTL_ADD
|
EPOLL_CTL_ADD = linux.EPOLL_CTL_ADD
|
||||||
@ -69,11 +74,6 @@ type Statfs_t = linux.Statfs_t
|
|||||||
// Rlimit is a wrapper
|
// Rlimit is a wrapper
|
||||||
type Rlimit = linux.Rlimit
|
type Rlimit = linux.Rlimit
|
||||||
|
|
||||||
// Setrlimit is a wrapper
|
|
||||||
func Setrlimit(resource int, rlim *Rlimit) (err error) {
|
|
||||||
return linux.Setrlimit(resource, rlim)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Syscall is a wrapper
|
// Syscall is a wrapper
|
||||||
func Syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err syscall.Errno) {
|
func Syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err syscall.Errno) {
|
||||||
return linux.Syscall(trap, a1, a2, a3)
|
return linux.Syscall(trap, a1, a2, a3)
|
||||||
@ -202,3 +202,7 @@ func KernelRelease() (string, error) {
|
|||||||
release := string(uname.Release[:end])
|
release := string(uname.Release[:end])
|
||||||
return release, nil
|
return release, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Prlimit(pid, resource int, new, old *Rlimit) error {
|
||||||
|
return linux.Prlimit(pid, resource, new, old)
|
||||||
|
}
|
||||||
|
14
vendor/github.com/cilium/ebpf/internal/unix/types_other.go
generated
vendored
14
vendor/github.com/cilium/ebpf/internal/unix/types_other.go
generated
vendored
@ -1,3 +1,4 @@
|
|||||||
|
//go:build !linux
|
||||||
// +build !linux
|
// +build !linux
|
||||||
|
|
||||||
package unix
|
package unix
|
||||||
@ -21,6 +22,7 @@ const (
|
|||||||
ESRCH = syscall.ESRCH
|
ESRCH = syscall.ESRCH
|
||||||
ENODEV = syscall.ENODEV
|
ENODEV = syscall.ENODEV
|
||||||
EBADF = syscall.Errno(0)
|
EBADF = syscall.Errno(0)
|
||||||
|
E2BIG = syscall.Errno(0)
|
||||||
// ENOTSUPP is not the same as ENOTSUP or EOPNOTSUP
|
// ENOTSUPP is not the same as ENOTSUP or EOPNOTSUP
|
||||||
ENOTSUPP = syscall.Errno(0x20c)
|
ENOTSUPP = syscall.Errno(0x20c)
|
||||||
|
|
||||||
@ -35,6 +37,9 @@ const (
|
|||||||
BPF_F_INNER_MAP = 0
|
BPF_F_INNER_MAP = 0
|
||||||
BPF_OBJ_NAME_LEN = 0x10
|
BPF_OBJ_NAME_LEN = 0x10
|
||||||
BPF_TAG_SIZE = 0x8
|
BPF_TAG_SIZE = 0x8
|
||||||
|
BPF_RINGBUF_BUSY_BIT = 0
|
||||||
|
BPF_RINGBUF_DISCARD_BIT = 0
|
||||||
|
BPF_RINGBUF_HDR_SZ = 0
|
||||||
SYS_BPF = 321
|
SYS_BPF = 321
|
||||||
F_DUPFD_CLOEXEC = 0x406
|
F_DUPFD_CLOEXEC = 0x406
|
||||||
EPOLLIN = 0x1
|
EPOLLIN = 0x1
|
||||||
@ -86,11 +91,6 @@ type Rlimit struct {
|
|||||||
Max uint64
|
Max uint64
|
||||||
}
|
}
|
||||||
|
|
||||||
// Setrlimit is a wrapper
|
|
||||||
func Setrlimit(resource int, rlim *Rlimit) (err error) {
|
|
||||||
return errNonLinux
|
|
||||||
}
|
|
||||||
|
|
||||||
// Syscall is a wrapper
|
// Syscall is a wrapper
|
||||||
func Syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err syscall.Errno) {
|
func Syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err syscall.Errno) {
|
||||||
return 0, 0, syscall.Errno(1)
|
return 0, 0, syscall.Errno(1)
|
||||||
@ -261,3 +261,7 @@ func Renameat2(olddirfd int, oldpath string, newdirfd int, newpath string, flags
|
|||||||
func KernelRelease() (string, error) {
|
func KernelRelease() (string, error) {
|
||||||
return "", errNonLinux
|
return "", errNonLinux
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Prlimit(pid, resource int, new, old *Rlimit) error {
|
||||||
|
return errNonLinux
|
||||||
|
}
|
||||||
|
4
vendor/github.com/cilium/ebpf/internal/version.go
generated
vendored
4
vendor/github.com/cilium/ebpf/internal/version.go
generated
vendored
@ -2,7 +2,7 @@ package internal
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"os"
|
||||||
"regexp"
|
"regexp"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
@ -109,7 +109,7 @@ func detectKernelVersion() (Version, error) {
|
|||||||
// Example format: Ubuntu 4.15.0-91.92-generic 4.15.18
|
// Example format: Ubuntu 4.15.0-91.92-generic 4.15.18
|
||||||
// This method exists in the kernel itself, see d18acd15c
|
// This method exists in the kernel itself, see d18acd15c
|
||||||
// ("perf tools: Fix kernel version error in ubuntu").
|
// ("perf tools: Fix kernel version error in ubuntu").
|
||||||
if pvs, err := ioutil.ReadFile("/proc/version_signature"); err == nil {
|
if pvs, err := os.ReadFile("/proc/version_signature"); err == nil {
|
||||||
// If /proc/version_signature exists, failing to parse it is an error.
|
// If /proc/version_signature exists, failing to parse it is an error.
|
||||||
// It only exists on Ubuntu, where the real patch level is not obtainable
|
// It only exists on Ubuntu, where the real patch level is not obtainable
|
||||||
// through any other method.
|
// through any other method.
|
||||||
|
88
vendor/github.com/cilium/ebpf/link/freplace.go
generated
vendored
Normal file
88
vendor/github.com/cilium/ebpf/link/freplace.go
generated
vendored
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
package link
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/cilium/ebpf"
|
||||||
|
"github.com/cilium/ebpf/internal/btf"
|
||||||
|
)
|
||||||
|
|
||||||
|
type FreplaceLink struct {
|
||||||
|
RawLink
|
||||||
|
}
|
||||||
|
|
||||||
|
// AttachFreplace attaches the given eBPF program to the function it replaces.
|
||||||
|
//
|
||||||
|
// The program and name can either be provided at link time, or can be provided
|
||||||
|
// at program load time. If they were provided at load time, they should be nil
|
||||||
|
// and empty respectively here, as they will be ignored by the kernel.
|
||||||
|
// Examples:
|
||||||
|
//
|
||||||
|
// AttachFreplace(dispatcher, "function", replacement)
|
||||||
|
// AttachFreplace(nil, "", replacement)
|
||||||
|
func AttachFreplace(targetProg *ebpf.Program, name string, prog *ebpf.Program) (*FreplaceLink, error) {
|
||||||
|
if (name == "") != (targetProg == nil) {
|
||||||
|
return nil, fmt.Errorf("must provide both or neither of name and targetProg: %w", errInvalidInput)
|
||||||
|
}
|
||||||
|
if prog == nil {
|
||||||
|
return nil, fmt.Errorf("prog cannot be nil: %w", errInvalidInput)
|
||||||
|
}
|
||||||
|
if prog.Type() != ebpf.Extension {
|
||||||
|
return nil, fmt.Errorf("eBPF program type %s is not an Extension: %w", prog.Type(), errInvalidInput)
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
target int
|
||||||
|
typeID btf.TypeID
|
||||||
|
)
|
||||||
|
if targetProg != nil {
|
||||||
|
info, err := targetProg.Info()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
btfID, ok := info.BTFID()
|
||||||
|
if !ok {
|
||||||
|
return nil, fmt.Errorf("could not get BTF ID for program %s: %w", info.Name, errInvalidInput)
|
||||||
|
}
|
||||||
|
btfHandle, err := btf.NewHandleFromID(btfID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer btfHandle.Close()
|
||||||
|
|
||||||
|
var function *btf.Func
|
||||||
|
if err := btfHandle.Spec().FindType(name, &function); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
target = targetProg.FD()
|
||||||
|
typeID = function.ID()
|
||||||
|
}
|
||||||
|
|
||||||
|
link, err := AttachRawLink(RawLinkOptions{
|
||||||
|
Target: target,
|
||||||
|
Program: prog,
|
||||||
|
Attach: ebpf.AttachNone,
|
||||||
|
BTF: typeID,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &FreplaceLink{*link}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update implements the Link interface.
|
||||||
|
func (f *FreplaceLink) Update(new *ebpf.Program) error {
|
||||||
|
return fmt.Errorf("freplace update: %w", ErrNotSupported)
|
||||||
|
}
|
||||||
|
|
||||||
|
// LoadPinnedFreplace loads a pinned iterator from a bpffs.
|
||||||
|
func LoadPinnedFreplace(fileName string, opts *ebpf.LoadPinOptions) (*FreplaceLink, error) {
|
||||||
|
link, err := LoadPinnedRawLink(fileName, TracingType, opts)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &FreplaceLink{*link}, err
|
||||||
|
}
|
38
vendor/github.com/cilium/ebpf/link/kprobe.go
generated
vendored
38
vendor/github.com/cilium/ebpf/link/kprobe.go
generated
vendored
@ -5,7 +5,6 @@ import (
|
|||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
@ -72,10 +71,11 @@ func (pt probeType) RetprobeBit() (uint64, error) {
|
|||||||
// given kernel symbol starts executing. See /proc/kallsyms for available
|
// given kernel symbol starts executing. See /proc/kallsyms for available
|
||||||
// symbols. For example, printk():
|
// symbols. For example, printk():
|
||||||
//
|
//
|
||||||
// Kprobe("printk", prog)
|
// kp, err := Kprobe("printk", prog)
|
||||||
//
|
//
|
||||||
// The resulting Link must be Closed during program shutdown to avoid leaking
|
// Losing the reference to the resulting Link (kp) will close the Kprobe
|
||||||
// system resources.
|
// and prevent further execution of prog. The Link must be Closed during
|
||||||
|
// program shutdown to avoid leaking system resources.
|
||||||
func Kprobe(symbol string, prog *ebpf.Program) (Link, error) {
|
func Kprobe(symbol string, prog *ebpf.Program) (Link, error) {
|
||||||
k, err := kprobe(symbol, prog, false)
|
k, err := kprobe(symbol, prog, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -95,10 +95,11 @@ func Kprobe(symbol string, prog *ebpf.Program) (Link, error) {
|
|||||||
// before the given kernel symbol exits, with the function stack left intact.
|
// before the given kernel symbol exits, with the function stack left intact.
|
||||||
// See /proc/kallsyms for available symbols. For example, printk():
|
// See /proc/kallsyms for available symbols. For example, printk():
|
||||||
//
|
//
|
||||||
// Kretprobe("printk", prog)
|
// kp, err := Kretprobe("printk", prog)
|
||||||
//
|
//
|
||||||
// The resulting Link must be Closed during program shutdown to avoid leaking
|
// Losing the reference to the resulting Link (kp) will close the Kretprobe
|
||||||
// system resources.
|
// and prevent further execution of prog. The Link must be Closed during
|
||||||
|
// program shutdown to avoid leaking system resources.
|
||||||
func Kretprobe(symbol string, prog *ebpf.Program) (Link, error) {
|
func Kretprobe(symbol string, prog *ebpf.Program) (Link, error) {
|
||||||
k, err := kprobe(symbol, prog, true)
|
k, err := kprobe(symbol, prog, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -157,7 +158,7 @@ func kprobe(symbol string, prog *ebpf.Program, ret bool) (*perfEvent, error) {
|
|||||||
// pmuKprobe opens a perf event based on the kprobe PMU.
|
// pmuKprobe opens a perf event based on the kprobe PMU.
|
||||||
// Returns os.ErrNotExist if the given symbol does not exist in the kernel.
|
// Returns os.ErrNotExist if the given symbol does not exist in the kernel.
|
||||||
func pmuKprobe(symbol string, ret bool) (*perfEvent, error) {
|
func pmuKprobe(symbol string, ret bool) (*perfEvent, error) {
|
||||||
return pmuProbe(kprobeType, symbol, "", 0, ret)
|
return pmuProbe(kprobeType, symbol, "", 0, perfAllThreads, ret)
|
||||||
}
|
}
|
||||||
|
|
||||||
// pmuProbe opens a perf event based on a Performance Monitoring Unit.
|
// pmuProbe opens a perf event based on a Performance Monitoring Unit.
|
||||||
@ -167,7 +168,7 @@ func pmuKprobe(symbol string, ret bool) (*perfEvent, error) {
|
|||||||
// 33ea4b24277b "perf/core: Implement the 'perf_uprobe' PMU"
|
// 33ea4b24277b "perf/core: Implement the 'perf_uprobe' PMU"
|
||||||
//
|
//
|
||||||
// Returns ErrNotSupported if the kernel doesn't support perf_[k,u]probe PMU
|
// Returns ErrNotSupported if the kernel doesn't support perf_[k,u]probe PMU
|
||||||
func pmuProbe(typ probeType, symbol, path string, offset uint64, ret bool) (*perfEvent, error) {
|
func pmuProbe(typ probeType, symbol, path string, offset uint64, pid int, ret bool) (*perfEvent, error) {
|
||||||
// Getting the PMU type will fail if the kernel doesn't support
|
// Getting the PMU type will fail if the kernel doesn't support
|
||||||
// the perf_[k,u]probe PMU.
|
// the perf_[k,u]probe PMU.
|
||||||
et, err := getPMUEventType(typ)
|
et, err := getPMUEventType(typ)
|
||||||
@ -191,7 +192,7 @@ func pmuProbe(typ probeType, symbol, path string, offset uint64, ret bool) (*per
|
|||||||
switch typ {
|
switch typ {
|
||||||
case kprobeType:
|
case kprobeType:
|
||||||
// Create a pointer to a NUL-terminated string for the kernel.
|
// Create a pointer to a NUL-terminated string for the kernel.
|
||||||
sp, err := unsafeStringPtr(symbol)
|
sp, err = unsafeStringPtr(symbol)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -202,7 +203,7 @@ func pmuProbe(typ probeType, symbol, path string, offset uint64, ret bool) (*per
|
|||||||
Config: config, // Retprobe flag
|
Config: config, // Retprobe flag
|
||||||
}
|
}
|
||||||
case uprobeType:
|
case uprobeType:
|
||||||
sp, err := unsafeStringPtr(path)
|
sp, err = unsafeStringPtr(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -220,7 +221,7 @@ func pmuProbe(typ probeType, symbol, path string, offset uint64, ret bool) (*per
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fd, err := unix.PerfEventOpen(&attr, perfAllThreads, 0, -1, unix.PERF_FLAG_FD_CLOEXEC)
|
fd, err := unix.PerfEventOpen(&attr, pid, 0, -1, unix.PERF_FLAG_FD_CLOEXEC)
|
||||||
|
|
||||||
// Since commit 97c753e62e6c, ENOENT is correctly returned instead of EINVAL
|
// Since commit 97c753e62e6c, ENOENT is correctly returned instead of EINVAL
|
||||||
// when trying to create a kretprobe for a missing symbol. Make sure ENOENT
|
// when trying to create a kretprobe for a missing symbol. Make sure ENOENT
|
||||||
@ -228,6 +229,11 @@ func pmuProbe(typ probeType, symbol, path string, offset uint64, ret bool) (*per
|
|||||||
if errors.Is(err, os.ErrNotExist) || errors.Is(err, unix.EINVAL) {
|
if errors.Is(err, os.ErrNotExist) || errors.Is(err, unix.EINVAL) {
|
||||||
return nil, fmt.Errorf("symbol '%s' not found: %w", symbol, os.ErrNotExist)
|
return nil, fmt.Errorf("symbol '%s' not found: %w", symbol, os.ErrNotExist)
|
||||||
}
|
}
|
||||||
|
// Since at least commit cb9a19fe4aa51, ENOTSUPP is returned
|
||||||
|
// when attempting to set a uprobe on a trap instruction.
|
||||||
|
if errors.Is(err, unix.ENOTSUPP) {
|
||||||
|
return nil, fmt.Errorf("failed setting uprobe on offset %#x (possible trap insn): %w", offset, err)
|
||||||
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("opening perf event: %w", err)
|
return nil, fmt.Errorf("opening perf event: %w", err)
|
||||||
}
|
}
|
||||||
@ -246,7 +252,7 @@ func pmuProbe(typ probeType, symbol, path string, offset uint64, ret bool) (*per
|
|||||||
|
|
||||||
// tracefsKprobe creates a Kprobe tracefs entry.
|
// tracefsKprobe creates a Kprobe tracefs entry.
|
||||||
func tracefsKprobe(symbol string, ret bool) (*perfEvent, error) {
|
func tracefsKprobe(symbol string, ret bool) (*perfEvent, error) {
|
||||||
return tracefsProbe(kprobeType, symbol, "", 0, ret)
|
return tracefsProbe(kprobeType, symbol, "", 0, perfAllThreads, ret)
|
||||||
}
|
}
|
||||||
|
|
||||||
// tracefsProbe creates a trace event by writing an entry to <tracefs>/[k,u]probe_events.
|
// tracefsProbe creates a trace event by writing an entry to <tracefs>/[k,u]probe_events.
|
||||||
@ -255,7 +261,7 @@ func tracefsKprobe(symbol string, ret bool) (*perfEvent, error) {
|
|||||||
// Path and offset are only set in the case of uprobe(s) and are used to set
|
// Path and offset are only set in the case of uprobe(s) and are used to set
|
||||||
// the executable/library path on the filesystem and the offset where the probe is inserted.
|
// the executable/library path on the filesystem and the offset where the probe is inserted.
|
||||||
// A perf event is then opened on the newly-created trace event and returned to the caller.
|
// A perf event is then opened on the newly-created trace event and returned to the caller.
|
||||||
func tracefsProbe(typ probeType, symbol, path string, offset uint64, ret bool) (*perfEvent, error) {
|
func tracefsProbe(typ probeType, symbol, path string, offset uint64, pid int, ret bool) (*perfEvent, error) {
|
||||||
// Generate a random string for each trace event we attempt to create.
|
// Generate a random string for each trace event we attempt to create.
|
||||||
// This value is used as the 'group' token in tracefs to allow creating
|
// This value is used as the 'group' token in tracefs to allow creating
|
||||||
// multiple kprobe trace events with the same name.
|
// multiple kprobe trace events with the same name.
|
||||||
@ -288,7 +294,7 @@ func tracefsProbe(typ probeType, symbol, path string, offset uint64, ret bool) (
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Kprobes are ephemeral tracepoints and share the same perf event type.
|
// Kprobes are ephemeral tracepoints and share the same perf event type.
|
||||||
fd, err := openTracepointPerfEvent(tid)
|
fd, err := openTracepointPerfEvent(tid, pid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -413,7 +419,7 @@ func probePrefix(ret bool) string {
|
|||||||
func determineRetprobeBit(typ probeType) (uint64, error) {
|
func determineRetprobeBit(typ probeType) (uint64, error) {
|
||||||
p := filepath.Join("/sys/bus/event_source/devices/", typ.String(), "/format/retprobe")
|
p := filepath.Join("/sys/bus/event_source/devices/", typ.String(), "/format/retprobe")
|
||||||
|
|
||||||
data, err := ioutil.ReadFile(p)
|
data, err := os.ReadFile(p)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
14
vendor/github.com/cilium/ebpf/link/link.go
generated
vendored
14
vendor/github.com/cilium/ebpf/link/link.go
generated
vendored
@ -6,6 +6,7 @@ import (
|
|||||||
|
|
||||||
"github.com/cilium/ebpf"
|
"github.com/cilium/ebpf"
|
||||||
"github.com/cilium/ebpf/internal"
|
"github.com/cilium/ebpf/internal"
|
||||||
|
"github.com/cilium/ebpf/internal/btf"
|
||||||
)
|
)
|
||||||
|
|
||||||
var ErrNotSupported = internal.ErrNotSupported
|
var ErrNotSupported = internal.ErrNotSupported
|
||||||
@ -29,8 +30,8 @@ type Link interface {
|
|||||||
|
|
||||||
// Close frees resources.
|
// Close frees resources.
|
||||||
//
|
//
|
||||||
// The link will be broken unless it has been pinned. A link
|
// The link will be broken unless it has been successfully pinned.
|
||||||
// may continue past the lifetime of the process if Close is
|
// A link may continue past the lifetime of the process if Close is
|
||||||
// not called.
|
// not called.
|
||||||
Close() error
|
Close() error
|
||||||
|
|
||||||
@ -49,6 +50,8 @@ type RawLinkOptions struct {
|
|||||||
Program *ebpf.Program
|
Program *ebpf.Program
|
||||||
// Attach must match the attach type of Program.
|
// Attach must match the attach type of Program.
|
||||||
Attach ebpf.AttachType
|
Attach ebpf.AttachType
|
||||||
|
// BTF is the BTF of the attachment target.
|
||||||
|
BTF btf.TypeID
|
||||||
}
|
}
|
||||||
|
|
||||||
// RawLinkInfo contains metadata on a link.
|
// RawLinkInfo contains metadata on a link.
|
||||||
@ -83,9 +86,10 @@ func AttachRawLink(opts RawLinkOptions) (*RawLink, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
attr := bpfLinkCreateAttr{
|
attr := bpfLinkCreateAttr{
|
||||||
targetFd: uint32(opts.Target),
|
targetFd: uint32(opts.Target),
|
||||||
progFd: uint32(progFd),
|
progFd: uint32(progFd),
|
||||||
attachType: opts.Attach,
|
attachType: opts.Attach,
|
||||||
|
targetBTFID: uint32(opts.BTF),
|
||||||
}
|
}
|
||||||
fd, err := bpfLinkCreate(&attr)
|
fd, err := bpfLinkCreate(&attr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
7
vendor/github.com/cilium/ebpf/link/perf_event.go
generated
vendored
7
vendor/github.com/cilium/ebpf/link/perf_event.go
generated
vendored
@ -4,7 +4,6 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"regexp"
|
"regexp"
|
||||||
@ -236,7 +235,7 @@ func getPMUEventType(typ probeType) (uint64, error) {
|
|||||||
// openTracepointPerfEvent opens a tracepoint-type perf event. System-wide
|
// openTracepointPerfEvent opens a tracepoint-type perf event. System-wide
|
||||||
// [k,u]probes created by writing to <tracefs>/[k,u]probe_events are tracepoints
|
// [k,u]probes created by writing to <tracefs>/[k,u]probe_events are tracepoints
|
||||||
// behind the scenes, and can be attached to using these perf events.
|
// behind the scenes, and can be attached to using these perf events.
|
||||||
func openTracepointPerfEvent(tid uint64) (*internal.FD, error) {
|
func openTracepointPerfEvent(tid uint64, pid int) (*internal.FD, error) {
|
||||||
attr := unix.PerfEventAttr{
|
attr := unix.PerfEventAttr{
|
||||||
Type: unix.PERF_TYPE_TRACEPOINT,
|
Type: unix.PERF_TYPE_TRACEPOINT,
|
||||||
Config: tid,
|
Config: tid,
|
||||||
@ -245,7 +244,7 @@ func openTracepointPerfEvent(tid uint64) (*internal.FD, error) {
|
|||||||
Wakeup: 1,
|
Wakeup: 1,
|
||||||
}
|
}
|
||||||
|
|
||||||
fd, err := unix.PerfEventOpen(&attr, perfAllThreads, 0, -1, unix.PERF_FLAG_FD_CLOEXEC)
|
fd, err := unix.PerfEventOpen(&attr, pid, 0, -1, unix.PERF_FLAG_FD_CLOEXEC)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("opening tracepoint perf event: %w", err)
|
return nil, fmt.Errorf("opening tracepoint perf event: %w", err)
|
||||||
}
|
}
|
||||||
@ -263,7 +262,7 @@ func uint64FromFile(base string, path ...string) (uint64, error) {
|
|||||||
return 0, fmt.Errorf("path '%s' attempts to escape base path '%s': %w", l, base, errInvalidInput)
|
return 0, fmt.Errorf("path '%s' attempts to escape base path '%s': %w", l, base, errInvalidInput)
|
||||||
}
|
}
|
||||||
|
|
||||||
data, err := ioutil.ReadFile(p)
|
data, err := os.ReadFile(p)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, fmt.Errorf("reading file %s: %w", p, err)
|
return 0, fmt.Errorf("reading file %s: %w", p, err)
|
||||||
}
|
}
|
||||||
|
9
vendor/github.com/cilium/ebpf/link/syscalls.go
generated
vendored
9
vendor/github.com/cilium/ebpf/link/syscalls.go
generated
vendored
@ -88,10 +88,11 @@ var haveProgAttachReplace = internal.FeatureTest("BPF_PROG_ATTACH atomic replace
|
|||||||
})
|
})
|
||||||
|
|
||||||
type bpfLinkCreateAttr struct {
|
type bpfLinkCreateAttr struct {
|
||||||
progFd uint32
|
progFd uint32
|
||||||
targetFd uint32
|
targetFd uint32
|
||||||
attachType ebpf.AttachType
|
attachType ebpf.AttachType
|
||||||
flags uint32
|
flags uint32
|
||||||
|
targetBTFID uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
func bpfLinkCreate(attr *bpfLinkCreateAttr) (*internal.FD, error) {
|
func bpfLinkCreate(attr *bpfLinkCreateAttr) (*internal.FD, error) {
|
||||||
|
8
vendor/github.com/cilium/ebpf/link/tracepoint.go
generated
vendored
8
vendor/github.com/cilium/ebpf/link/tracepoint.go
generated
vendored
@ -11,7 +11,11 @@ import (
|
|||||||
// tracepoints. The top-level directory is the group, the event's subdirectory
|
// tracepoints. The top-level directory is the group, the event's subdirectory
|
||||||
// is the name. Example:
|
// is the name. Example:
|
||||||
//
|
//
|
||||||
// Tracepoint("syscalls", "sys_enter_fork", prog)
|
// tp, err := Tracepoint("syscalls", "sys_enter_fork", prog)
|
||||||
|
//
|
||||||
|
// Losing the reference to the resulting Link (tp) will close the Tracepoint
|
||||||
|
// and prevent further execution of prog. The Link must be Closed during
|
||||||
|
// program shutdown to avoid leaking system resources.
|
||||||
//
|
//
|
||||||
// Note that attaching eBPF programs to syscalls (sys_enter_*/sys_exit_*) is
|
// Note that attaching eBPF programs to syscalls (sys_enter_*/sys_exit_*) is
|
||||||
// only possible as of kernel 4.14 (commit cf5f5ce).
|
// only possible as of kernel 4.14 (commit cf5f5ce).
|
||||||
@ -34,7 +38,7 @@ func Tracepoint(group, name string, prog *ebpf.Program) (Link, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
fd, err := openTracepointPerfEvent(tid)
|
fd, err := openTracepointPerfEvent(tid, perfAllThreads)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
135
vendor/github.com/cilium/ebpf/link/uprobe.go
generated
vendored
135
vendor/github.com/cilium/ebpf/link/uprobe.go
generated
vendored
@ -25,14 +25,18 @@ var (
|
|||||||
value uint64
|
value uint64
|
||||||
err error
|
err error
|
||||||
}{}
|
}{}
|
||||||
|
|
||||||
|
// ErrNoSymbol indicates that the given symbol was not found
|
||||||
|
// in the ELF symbols table.
|
||||||
|
ErrNoSymbol = errors.New("not found")
|
||||||
)
|
)
|
||||||
|
|
||||||
// Executable defines an executable program on the filesystem.
|
// Executable defines an executable program on the filesystem.
|
||||||
type Executable struct {
|
type Executable struct {
|
||||||
// Path of the executable on the filesystem.
|
// Path of the executable on the filesystem.
|
||||||
path string
|
path string
|
||||||
// Parsed ELF symbols and dynamic symbols.
|
// Parsed ELF symbols and dynamic symbols offsets.
|
||||||
symbols map[string]elf.Symbol
|
offsets map[string]uint64
|
||||||
}
|
}
|
||||||
|
|
||||||
// UprobeOptions defines additional parameters that will be used
|
// UprobeOptions defines additional parameters that will be used
|
||||||
@ -41,6 +45,9 @@ type UprobeOptions struct {
|
|||||||
// Symbol offset. Must be provided in case of external symbols (shared libs).
|
// Symbol offset. Must be provided in case of external symbols (shared libs).
|
||||||
// If set, overrides the offset eventually parsed from the executable.
|
// If set, overrides the offset eventually parsed from the executable.
|
||||||
Offset uint64
|
Offset uint64
|
||||||
|
// Only set the uprobe on the given process ID. Useful when tracing
|
||||||
|
// shared library calls or programs that have many running instances.
|
||||||
|
PID int
|
||||||
}
|
}
|
||||||
|
|
||||||
// To open a new Executable, use:
|
// To open a new Executable, use:
|
||||||
@ -64,42 +71,84 @@ func OpenExecutable(path string) (*Executable, error) {
|
|||||||
return nil, fmt.Errorf("parse ELF file: %w", err)
|
return nil, fmt.Errorf("parse ELF file: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
var ex = Executable{
|
if se.Type != elf.ET_EXEC && se.Type != elf.ET_DYN {
|
||||||
path: path,
|
// ELF is not an executable or a shared object.
|
||||||
symbols: make(map[string]elf.Symbol),
|
return nil, errors.New("the given file is not an executable or a shared object")
|
||||||
}
|
|
||||||
if err := ex.addSymbols(se.Symbols); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := ex.addSymbols(se.DynamicSymbols); err != nil {
|
ex := Executable{
|
||||||
|
path: path,
|
||||||
|
offsets: make(map[string]uint64),
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := ex.load(se); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return &ex, nil
|
return &ex, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ex *Executable) addSymbols(f func() ([]elf.Symbol, error)) error {
|
func (ex *Executable) load(f *internal.SafeELFFile) error {
|
||||||
// elf.Symbols and elf.DynamicSymbols return ErrNoSymbols if the section is not found.
|
syms, err := f.Symbols()
|
||||||
syms, err := f()
|
|
||||||
if err != nil && !errors.Is(err, elf.ErrNoSymbols) {
|
if err != nil && !errors.Is(err, elf.ErrNoSymbols) {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dynsyms, err := f.DynamicSymbols()
|
||||||
|
if err != nil && !errors.Is(err, elf.ErrNoSymbols) {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
syms = append(syms, dynsyms...)
|
||||||
|
|
||||||
for _, s := range syms {
|
for _, s := range syms {
|
||||||
if elf.ST_TYPE(s.Info) != elf.STT_FUNC {
|
if elf.ST_TYPE(s.Info) != elf.STT_FUNC {
|
||||||
// Symbol not associated with a function or other executable code.
|
// Symbol not associated with a function or other executable code.
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
ex.symbols[s.Name] = s
|
|
||||||
|
off := s.Value
|
||||||
|
|
||||||
|
// Loop over ELF segments.
|
||||||
|
for _, prog := range f.Progs {
|
||||||
|
// Skip uninteresting segments.
|
||||||
|
if prog.Type != elf.PT_LOAD || (prog.Flags&elf.PF_X) == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if prog.Vaddr <= s.Value && s.Value < (prog.Vaddr+prog.Memsz) {
|
||||||
|
// If the symbol value is contained in the segment, calculate
|
||||||
|
// the symbol offset.
|
||||||
|
//
|
||||||
|
// fn symbol offset = fn symbol VA - .text VA + .text offset
|
||||||
|
//
|
||||||
|
// stackoverflow.com/a/40249502
|
||||||
|
off = s.Value - prog.Vaddr + prog.Off
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ex.offsets[s.Name] = off
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ex *Executable) symbol(symbol string) (*elf.Symbol, error) {
|
func (ex *Executable) offset(symbol string) (uint64, error) {
|
||||||
if s, ok := ex.symbols[symbol]; ok {
|
if off, ok := ex.offsets[symbol]; ok {
|
||||||
return &s, nil
|
// Symbols with location 0 from section undef are shared library calls and
|
||||||
|
// are relocated before the binary is executed. Dynamic linking is not
|
||||||
|
// implemented by the library, so mark this as unsupported for now.
|
||||||
|
//
|
||||||
|
// Since only offset values are stored and not elf.Symbol, if the value is 0,
|
||||||
|
// assume it's an external symbol.
|
||||||
|
if off == 0 {
|
||||||
|
return 0, fmt.Errorf("cannot resolve %s library call '%s', "+
|
||||||
|
"consider providing the offset via options: %w", ex.path, symbol, ErrNotSupported)
|
||||||
|
}
|
||||||
|
return off, nil
|
||||||
}
|
}
|
||||||
return nil, fmt.Errorf("symbol %s not found", symbol)
|
return 0, fmt.Errorf("symbol %s: %w", symbol, ErrNoSymbol)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Uprobe attaches the given eBPF program to a perf event that fires when the
|
// Uprobe attaches the given eBPF program to a perf event that fires when the
|
||||||
@ -112,11 +161,14 @@ func (ex *Executable) symbol(symbol string) (*elf.Symbol, error) {
|
|||||||
// When using symbols which belongs to shared libraries,
|
// When using symbols which belongs to shared libraries,
|
||||||
// an offset must be provided via options:
|
// an offset must be provided via options:
|
||||||
//
|
//
|
||||||
// ex.Uprobe("main", prog, &UprobeOptions{Offset: 0x123})
|
// up, err := ex.Uprobe("main", prog, &UprobeOptions{Offset: 0x123})
|
||||||
//
|
//
|
||||||
// The resulting Link must be Closed during program shutdown to avoid leaking
|
// Losing the reference to the resulting Link (up) will close the Uprobe
|
||||||
// system resources. Functions provided by shared libraries can currently not
|
// and prevent further execution of prog. The Link must be Closed during
|
||||||
// be traced and will result in an ErrNotSupported.
|
// program shutdown to avoid leaking system resources.
|
||||||
|
//
|
||||||
|
// Functions provided by shared libraries can currently not be traced and
|
||||||
|
// will result in an ErrNotSupported.
|
||||||
func (ex *Executable) Uprobe(symbol string, prog *ebpf.Program, opts *UprobeOptions) (Link, error) {
|
func (ex *Executable) Uprobe(symbol string, prog *ebpf.Program, opts *UprobeOptions) (Link, error) {
|
||||||
u, err := ex.uprobe(symbol, prog, opts, false)
|
u, err := ex.uprobe(symbol, prog, opts, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -141,11 +193,14 @@ func (ex *Executable) Uprobe(symbol string, prog *ebpf.Program, opts *UprobeOpti
|
|||||||
// When using symbols which belongs to shared libraries,
|
// When using symbols which belongs to shared libraries,
|
||||||
// an offset must be provided via options:
|
// an offset must be provided via options:
|
||||||
//
|
//
|
||||||
// ex.Uretprobe("main", prog, &UprobeOptions{Offset: 0x123})
|
// up, err := ex.Uretprobe("main", prog, &UprobeOptions{Offset: 0x123})
|
||||||
//
|
//
|
||||||
// The resulting Link must be Closed during program shutdown to avoid leaking
|
// Losing the reference to the resulting Link (up) will close the Uprobe
|
||||||
// system resources. Functions provided by shared libraries can currently not
|
// and prevent further execution of prog. The Link must be Closed during
|
||||||
// be traced and will result in an ErrNotSupported.
|
// program shutdown to avoid leaking system resources.
|
||||||
|
//
|
||||||
|
// Functions provided by shared libraries can currently not be traced and
|
||||||
|
// will result in an ErrNotSupported.
|
||||||
func (ex *Executable) Uretprobe(symbol string, prog *ebpf.Program, opts *UprobeOptions) (Link, error) {
|
func (ex *Executable) Uretprobe(symbol string, prog *ebpf.Program, opts *UprobeOptions) (Link, error) {
|
||||||
u, err := ex.uprobe(symbol, prog, opts, true)
|
u, err := ex.uprobe(symbol, prog, opts, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -175,24 +230,20 @@ func (ex *Executable) uprobe(symbol string, prog *ebpf.Program, opts *UprobeOpti
|
|||||||
if opts != nil && opts.Offset != 0 {
|
if opts != nil && opts.Offset != 0 {
|
||||||
offset = opts.Offset
|
offset = opts.Offset
|
||||||
} else {
|
} else {
|
||||||
sym, err := ex.symbol(symbol)
|
off, err := ex.offset(symbol)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("symbol '%s' not found: %w", symbol, err)
|
return nil, err
|
||||||
}
|
}
|
||||||
|
offset = off
|
||||||
|
}
|
||||||
|
|
||||||
// Symbols with location 0 from section undef are shared library calls and
|
pid := perfAllThreads
|
||||||
// are relocated before the binary is executed. Dynamic linking is not
|
if opts != nil && opts.PID != 0 {
|
||||||
// implemented by the library, so mark this as unsupported for now.
|
pid = opts.PID
|
||||||
if sym.Section == elf.SHN_UNDEF && sym.Value == 0 {
|
|
||||||
return nil, fmt.Errorf("cannot resolve %s library call '%s', "+
|
|
||||||
"consider providing the offset via options: %w", ex.path, symbol, ErrNotSupported)
|
|
||||||
}
|
|
||||||
|
|
||||||
offset = sym.Value
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use uprobe PMU if the kernel has it available.
|
// Use uprobe PMU if the kernel has it available.
|
||||||
tp, err := pmuUprobe(symbol, ex.path, offset, ret)
|
tp, err := pmuUprobe(symbol, ex.path, offset, pid, ret)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return tp, nil
|
return tp, nil
|
||||||
}
|
}
|
||||||
@ -201,7 +252,7 @@ func (ex *Executable) uprobe(symbol string, prog *ebpf.Program, opts *UprobeOpti
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Use tracefs if uprobe PMU is missing.
|
// Use tracefs if uprobe PMU is missing.
|
||||||
tp, err = tracefsUprobe(uprobeSanitizedSymbol(symbol), ex.path, offset, ret)
|
tp, err = tracefsUprobe(uprobeSanitizedSymbol(symbol), ex.path, offset, pid, ret)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("creating trace event '%s:%s' in tracefs: %w", ex.path, symbol, err)
|
return nil, fmt.Errorf("creating trace event '%s:%s' in tracefs: %w", ex.path, symbol, err)
|
||||||
}
|
}
|
||||||
@ -210,13 +261,13 @@ func (ex *Executable) uprobe(symbol string, prog *ebpf.Program, opts *UprobeOpti
|
|||||||
}
|
}
|
||||||
|
|
||||||
// pmuUprobe opens a perf event based on the uprobe PMU.
|
// pmuUprobe opens a perf event based on the uprobe PMU.
|
||||||
func pmuUprobe(symbol, path string, offset uint64, ret bool) (*perfEvent, error) {
|
func pmuUprobe(symbol, path string, offset uint64, pid int, ret bool) (*perfEvent, error) {
|
||||||
return pmuProbe(uprobeType, symbol, path, offset, ret)
|
return pmuProbe(uprobeType, symbol, path, offset, pid, ret)
|
||||||
}
|
}
|
||||||
|
|
||||||
// tracefsUprobe creates a Uprobe tracefs entry.
|
// tracefsUprobe creates a Uprobe tracefs entry.
|
||||||
func tracefsUprobe(symbol, path string, offset uint64, ret bool) (*perfEvent, error) {
|
func tracefsUprobe(symbol, path string, offset uint64, pid int, ret bool) (*perfEvent, error) {
|
||||||
return tracefsProbe(uprobeType, symbol, path, offset, ret)
|
return tracefsProbe(uprobeType, symbol, path, offset, pid, ret)
|
||||||
}
|
}
|
||||||
|
|
||||||
// uprobeSanitizedSymbol replaces every invalid characted for the tracefs api with an underscore.
|
// uprobeSanitizedSymbol replaces every invalid characted for the tracefs api with an underscore.
|
||||||
|
23
vendor/github.com/cilium/ebpf/linker.go
generated
vendored
23
vendor/github.com/cilium/ebpf/linker.go
generated
vendored
@ -4,7 +4,6 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/cilium/ebpf/asm"
|
"github.com/cilium/ebpf/asm"
|
||||||
"github.com/cilium/ebpf/internal/btf"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// link resolves bpf-to-bpf calls.
|
// link resolves bpf-to-bpf calls.
|
||||||
@ -40,7 +39,7 @@ func link(prog *ProgramSpec, libs []*ProgramSpec) error {
|
|||||||
pending = append(pending, lib.Instructions)
|
pending = append(pending, lib.Instructions)
|
||||||
|
|
||||||
if prog.BTF != nil && lib.BTF != nil {
|
if prog.BTF != nil && lib.BTF != nil {
|
||||||
if err := btf.ProgramAppend(prog.BTF, lib.BTF); err != nil {
|
if err := prog.BTF.Append(lib.BTF); err != nil {
|
||||||
return fmt.Errorf("linking BTF of %s: %w", lib.Name, err)
|
return fmt.Errorf("linking BTF of %s: %w", lib.Name, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -136,5 +135,25 @@ func fixupJumpsAndCalls(insns asm.Instructions) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// fixupBPFCalls replaces bpf_probe_read_{kernel,user}[_str] with bpf_probe_read[_str] on older kernels
|
||||||
|
// https://github.com/libbpf/libbpf/blob/master/src/libbpf.c#L6009
|
||||||
|
iter = insns.Iterate()
|
||||||
|
for iter.Next() {
|
||||||
|
ins := iter.Ins
|
||||||
|
if !ins.IsBuiltinCall() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
switch asm.BuiltinFunc(ins.Constant) {
|
||||||
|
case asm.FnProbeReadKernel, asm.FnProbeReadUser:
|
||||||
|
if err := haveProbeReadKernel(); err != nil {
|
||||||
|
ins.Constant = int64(asm.FnProbeRead)
|
||||||
|
}
|
||||||
|
case asm.FnProbeReadKernelStr, asm.FnProbeReadUserStr:
|
||||||
|
if err := haveProbeReadKernel(); err != nil {
|
||||||
|
ins.Constant = int64(asm.FnProbeReadStr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
95
vendor/github.com/cilium/ebpf/map.go
generated
vendored
95
vendor/github.com/cilium/ebpf/map.go
generated
vendored
@ -1,6 +1,7 @@
|
|||||||
package ebpf
|
package ebpf
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
@ -65,6 +66,11 @@ type MapSpec struct {
|
|||||||
// InnerMap is used as a template for ArrayOfMaps and HashOfMaps
|
// InnerMap is used as a template for ArrayOfMaps and HashOfMaps
|
||||||
InnerMap *MapSpec
|
InnerMap *MapSpec
|
||||||
|
|
||||||
|
// Extra trailing bytes found in the ELF map definition when using structs
|
||||||
|
// larger than libbpf's bpf_map_def. Must be empty before instantiating
|
||||||
|
// the MapSpec into a Map.
|
||||||
|
Extra bytes.Reader
|
||||||
|
|
||||||
// The BTF associated with this map.
|
// The BTF associated with this map.
|
||||||
BTF *btf.Map
|
BTF *btf.Map
|
||||||
}
|
}
|
||||||
@ -82,9 +88,12 @@ func (ms *MapSpec) Copy() *MapSpec {
|
|||||||
}
|
}
|
||||||
|
|
||||||
cpy := *ms
|
cpy := *ms
|
||||||
|
|
||||||
cpy.Contents = make([]MapKV, len(ms.Contents))
|
cpy.Contents = make([]MapKV, len(ms.Contents))
|
||||||
copy(cpy.Contents, ms.Contents)
|
copy(cpy.Contents, ms.Contents)
|
||||||
|
|
||||||
cpy.InnerMap = ms.InnerMap.Copy()
|
cpy.InnerMap = ms.InnerMap.Copy()
|
||||||
|
|
||||||
return &cpy
|
return &cpy
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -188,14 +197,24 @@ func NewMap(spec *MapSpec) (*Map, error) {
|
|||||||
//
|
//
|
||||||
// The caller is responsible for ensuring the process' rlimit is set
|
// The caller is responsible for ensuring the process' rlimit is set
|
||||||
// sufficiently high for locking memory during map creation. This can be done
|
// sufficiently high for locking memory during map creation. This can be done
|
||||||
// by calling unix.Setrlimit with unix.RLIMIT_MEMLOCK prior to calling NewMapWithOptions.
|
// by calling rlimit.RemoveMemlock() prior to calling NewMapWithOptions.
|
||||||
//
|
//
|
||||||
// May return an error wrapping ErrMapIncompatible.
|
// May return an error wrapping ErrMapIncompatible.
|
||||||
func NewMapWithOptions(spec *MapSpec, opts MapOptions) (*Map, error) {
|
func NewMapWithOptions(spec *MapSpec, opts MapOptions) (*Map, error) {
|
||||||
handles := newHandleCache()
|
handles := newHandleCache()
|
||||||
defer handles.close()
|
defer handles.close()
|
||||||
|
|
||||||
return newMapWithOptions(spec, opts, handles)
|
m, err := newMapWithOptions(spec, opts, handles)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("creating map: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = m.finalize(spec)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("populating map: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return m, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func newMapWithOptions(spec *MapSpec, opts MapOptions, handles *handleCache) (_ *Map, err error) {
|
func newMapWithOptions(spec *MapSpec, opts MapOptions, handles *handleCache) (_ *Map, err error) {
|
||||||
@ -207,8 +226,12 @@ func newMapWithOptions(spec *MapSpec, opts MapOptions, handles *handleCache) (_
|
|||||||
|
|
||||||
switch spec.Pinning {
|
switch spec.Pinning {
|
||||||
case PinByName:
|
case PinByName:
|
||||||
if spec.Name == "" || opts.PinPath == "" {
|
if spec.Name == "" {
|
||||||
return nil, fmt.Errorf("pin by name: missing Name or PinPath")
|
return nil, fmt.Errorf("pin by name: missing Name")
|
||||||
|
}
|
||||||
|
|
||||||
|
if opts.PinPath == "" {
|
||||||
|
return nil, fmt.Errorf("pin by name: missing MapOptions.PinPath")
|
||||||
}
|
}
|
||||||
|
|
||||||
path := filepath.Join(opts.PinPath, spec.Name)
|
path := filepath.Join(opts.PinPath, spec.Name)
|
||||||
@ -244,16 +267,19 @@ func newMapWithOptions(spec *MapSpec, opts MapOptions, handles *handleCache) (_
|
|||||||
return nil, errors.New("inner maps cannot be pinned")
|
return nil, errors.New("inner maps cannot be pinned")
|
||||||
}
|
}
|
||||||
|
|
||||||
template, err := createMap(spec.InnerMap, nil, opts, handles)
|
template, err := spec.InnerMap.createMap(nil, opts, handles)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, fmt.Errorf("inner map: %w", err)
|
||||||
}
|
}
|
||||||
defer template.Close()
|
defer template.Close()
|
||||||
|
|
||||||
|
// Intentionally skip populating and freezing (finalizing)
|
||||||
|
// the inner map template since it will be removed shortly.
|
||||||
|
|
||||||
innerFd = template.fd
|
innerFd = template.fd
|
||||||
}
|
}
|
||||||
|
|
||||||
m, err := createMap(spec, innerFd, opts, handles)
|
m, err := spec.createMap(innerFd, opts, handles)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -269,7 +295,9 @@ func newMapWithOptions(spec *MapSpec, opts MapOptions, handles *handleCache) (_
|
|||||||
return m, nil
|
return m, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func createMap(spec *MapSpec, inner *internal.FD, opts MapOptions, handles *handleCache) (_ *Map, err error) {
|
// createMap validates the spec's properties and creates the map in the kernel
|
||||||
|
// using the given opts. It does not populate or freeze the map.
|
||||||
|
func (spec *MapSpec) createMap(inner *internal.FD, opts MapOptions, handles *handleCache) (_ *Map, err error) {
|
||||||
closeOnError := func(closer io.Closer) {
|
closeOnError := func(closer io.Closer) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
closer.Close()
|
closer.Close()
|
||||||
@ -278,10 +306,16 @@ func createMap(spec *MapSpec, inner *internal.FD, opts MapOptions, handles *hand
|
|||||||
|
|
||||||
spec = spec.Copy()
|
spec = spec.Copy()
|
||||||
|
|
||||||
|
// Kernels 4.13 through 5.4 used a struct bpf_map_def that contained
|
||||||
|
// additional 'inner_map_idx' and later 'numa_node' fields.
|
||||||
|
// In order to support loading these definitions, tolerate the presence of
|
||||||
|
// extra bytes, but require them to be zeroes.
|
||||||
|
if _, err := io.Copy(internal.DiscardZeroes{}, &spec.Extra); err != nil {
|
||||||
|
return nil, errors.New("extra contains unhandled non-zero bytes, drain before creating map")
|
||||||
|
}
|
||||||
|
|
||||||
switch spec.Type {
|
switch spec.Type {
|
||||||
case ArrayOfMaps:
|
case ArrayOfMaps, HashOfMaps:
|
||||||
fallthrough
|
|
||||||
case HashOfMaps:
|
|
||||||
if err := haveNestedMaps(); err != nil {
|
if err := haveNestedMaps(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -350,7 +384,7 @@ func createMap(spec *MapSpec, inner *internal.FD, opts MapOptions, handles *hand
|
|||||||
|
|
||||||
var btfDisabled bool
|
var btfDisabled bool
|
||||||
if spec.BTF != nil {
|
if spec.BTF != nil {
|
||||||
handle, err := handles.btfHandle(btf.MapSpec(spec.BTF))
|
handle, err := handles.btfHandle(spec.BTF.Spec)
|
||||||
btfDisabled = errors.Is(err, btf.ErrNotSupported)
|
btfDisabled = errors.Is(err, btf.ErrNotSupported)
|
||||||
if err != nil && !btfDisabled {
|
if err != nil && !btfDisabled {
|
||||||
return nil, fmt.Errorf("load BTF: %w", err)
|
return nil, fmt.Errorf("load BTF: %w", err)
|
||||||
@ -358,15 +392,15 @@ func createMap(spec *MapSpec, inner *internal.FD, opts MapOptions, handles *hand
|
|||||||
|
|
||||||
if handle != nil {
|
if handle != nil {
|
||||||
attr.BTFFd = uint32(handle.FD())
|
attr.BTFFd = uint32(handle.FD())
|
||||||
attr.BTFKeyTypeID = uint32(btf.MapKey(spec.BTF).ID())
|
attr.BTFKeyTypeID = uint32(spec.BTF.Key.ID())
|
||||||
attr.BTFValueTypeID = uint32(btf.MapValue(spec.BTF).ID())
|
attr.BTFValueTypeID = uint32(spec.BTF.Value.ID())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fd, err := internal.BPFMapCreate(&attr)
|
fd, err := internal.BPFMapCreate(&attr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Is(err, unix.EPERM) {
|
if errors.Is(err, unix.EPERM) {
|
||||||
return nil, fmt.Errorf("map create: RLIMIT_MEMLOCK may be too low: %w", err)
|
return nil, fmt.Errorf("map create: %w (MEMLOCK bay be too low, consider rlimit.RemoveMemlock)", err)
|
||||||
}
|
}
|
||||||
if btfDisabled {
|
if btfDisabled {
|
||||||
return nil, fmt.Errorf("map create without BTF: %w", err)
|
return nil, fmt.Errorf("map create without BTF: %w", err)
|
||||||
@ -380,19 +414,11 @@ func createMap(spec *MapSpec, inner *internal.FD, opts MapOptions, handles *hand
|
|||||||
return nil, fmt.Errorf("map create: %w", err)
|
return nil, fmt.Errorf("map create: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := m.populate(spec.Contents); err != nil {
|
|
||||||
return nil, fmt.Errorf("map create: can't set initial contents: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if spec.Freeze {
|
|
||||||
if err := m.Freeze(); err != nil {
|
|
||||||
return nil, fmt.Errorf("can't freeze map: %w", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return m, nil
|
return m, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// newMap allocates and returns a new Map structure.
|
||||||
|
// Sets the fullValueSize on per-CPU maps.
|
||||||
func newMap(fd *internal.FD, name string, typ MapType, keySize, valueSize, maxEntries, flags uint32) (*Map, error) {
|
func newMap(fd *internal.FD, name string, typ MapType, keySize, valueSize, maxEntries, flags uint32) (*Map, error) {
|
||||||
m := &Map{
|
m := &Map{
|
||||||
name,
|
name,
|
||||||
@ -415,7 +441,7 @@ func newMap(fd *internal.FD, name string, typ MapType, keySize, valueSize, maxEn
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
m.fullValueSize = align(int(valueSize), 8) * possibleCPUs
|
m.fullValueSize = internal.Align(int(valueSize), 8) * possibleCPUs
|
||||||
return m, nil
|
return m, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -892,12 +918,21 @@ func (m *Map) Freeze() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Map) populate(contents []MapKV) error {
|
// finalize populates the Map according to the Contents specified
|
||||||
for _, kv := range contents {
|
// in spec and freezes the Map if requested by spec.
|
||||||
|
func (m *Map) finalize(spec *MapSpec) error {
|
||||||
|
for _, kv := range spec.Contents {
|
||||||
if err := m.Put(kv.Key, kv.Value); err != nil {
|
if err := m.Put(kv.Key, kv.Value); err != nil {
|
||||||
return fmt.Errorf("key %v: %w", kv.Key, err)
|
return fmt.Errorf("putting value: key %v: %w", kv.Key, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if spec.Freeze {
|
||||||
|
if err := m.Freeze(); err != nil {
|
||||||
|
return fmt.Errorf("freezing map: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1212,7 +1247,7 @@ func MapGetNextID(startID MapID) (MapID, error) {
|
|||||||
//
|
//
|
||||||
// Returns ErrNotExist, if there is no eBPF map with the given id.
|
// Returns ErrNotExist, if there is no eBPF map with the given id.
|
||||||
func NewMapFromID(id MapID) (*Map, error) {
|
func NewMapFromID(id MapID) (*Map, error) {
|
||||||
fd, err := bpfObjGetFDByID(internal.BPF_MAP_GET_FD_BY_ID, uint32(id))
|
fd, err := internal.BPFObjGetFDByID(internal.BPF_MAP_GET_FD_BY_ID, uint32(id))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
63
vendor/github.com/cilium/ebpf/marshalers.go
generated
vendored
63
vendor/github.com/cilium/ebpf/marshalers.go
generated
vendored
@ -8,6 +8,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"reflect"
|
"reflect"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
"sync"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
"github.com/cilium/ebpf/internal"
|
"github.com/cilium/ebpf/internal"
|
||||||
@ -39,6 +40,10 @@ func marshalPtr(data interface{}, length int) (internal.Pointer, error) {
|
|||||||
// Returns an error if the given value isn't representable in exactly
|
// Returns an error if the given value isn't representable in exactly
|
||||||
// length bytes.
|
// length bytes.
|
||||||
func marshalBytes(data interface{}, length int) (buf []byte, err error) {
|
func marshalBytes(data interface{}, length int) (buf []byte, err error) {
|
||||||
|
if data == nil {
|
||||||
|
return nil, errors.New("can't marshal a nil value")
|
||||||
|
}
|
||||||
|
|
||||||
switch value := data.(type) {
|
switch value := data.(type) {
|
||||||
case encoding.BinaryMarshaler:
|
case encoding.BinaryMarshaler:
|
||||||
buf, err = value.MarshalBinary()
|
buf, err = value.MarshalBinary()
|
||||||
@ -77,22 +82,30 @@ func makeBuffer(dst interface{}, length int) (internal.Pointer, []byte) {
|
|||||||
return internal.NewSlicePointer(buf), buf
|
return internal.NewSlicePointer(buf), buf
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var bytesReaderPool = sync.Pool{
|
||||||
|
New: func() interface{} {
|
||||||
|
return new(bytes.Reader)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
// unmarshalBytes converts a byte buffer into an arbitrary value.
|
// unmarshalBytes converts a byte buffer into an arbitrary value.
|
||||||
//
|
//
|
||||||
// Prefer using Map.unmarshalKey and Map.unmarshalValue if possible, since
|
// Prefer using Map.unmarshalKey and Map.unmarshalValue if possible, since
|
||||||
// those have special cases that allow more types to be encoded.
|
// those have special cases that allow more types to be encoded.
|
||||||
|
//
|
||||||
|
// The common int32 and int64 types are directly handled to avoid
|
||||||
|
// unnecessary heap allocations as happening in the default case.
|
||||||
func unmarshalBytes(data interface{}, buf []byte) error {
|
func unmarshalBytes(data interface{}, buf []byte) error {
|
||||||
switch value := data.(type) {
|
switch value := data.(type) {
|
||||||
case unsafe.Pointer:
|
case unsafe.Pointer:
|
||||||
// This could be solved in Go 1.17 by unsafe.Slice instead. (https://github.com/golang/go/issues/19367)
|
var dst []byte
|
||||||
// We could opt for removing unsafe.Pointer support in the lib as well.
|
// Use unsafe.Slice when we drop support for pre1.17 (https://github.com/golang/go/issues/19367)
|
||||||
sh := &reflect.SliceHeader{ //nolint:govet
|
// We could opt for removing unsafe.Pointer support in the lib as well
|
||||||
Data: uintptr(value),
|
sh := (*reflect.SliceHeader)(unsafe.Pointer(&dst))
|
||||||
Len: len(buf),
|
sh.Data = uintptr(value)
|
||||||
Cap: len(buf),
|
sh.Len = len(buf)
|
||||||
}
|
sh.Cap = len(buf)
|
||||||
|
|
||||||
dst := *(*[]byte)(unsafe.Pointer(sh))
|
|
||||||
copy(dst, buf)
|
copy(dst, buf)
|
||||||
runtime.KeepAlive(value)
|
runtime.KeepAlive(value)
|
||||||
return nil
|
return nil
|
||||||
@ -106,12 +119,38 @@ func unmarshalBytes(data interface{}, buf []byte) error {
|
|||||||
case *[]byte:
|
case *[]byte:
|
||||||
*value = buf
|
*value = buf
|
||||||
return nil
|
return nil
|
||||||
|
case *int32:
|
||||||
|
if len(buf) < 4 {
|
||||||
|
return errors.New("int32 requires 4 bytes")
|
||||||
|
}
|
||||||
|
*value = int32(internal.NativeEndian.Uint32(buf))
|
||||||
|
return nil
|
||||||
|
case *uint32:
|
||||||
|
if len(buf) < 4 {
|
||||||
|
return errors.New("uint32 requires 4 bytes")
|
||||||
|
}
|
||||||
|
*value = internal.NativeEndian.Uint32(buf)
|
||||||
|
return nil
|
||||||
|
case *int64:
|
||||||
|
if len(buf) < 8 {
|
||||||
|
return errors.New("int64 requires 8 bytes")
|
||||||
|
}
|
||||||
|
*value = int64(internal.NativeEndian.Uint64(buf))
|
||||||
|
return nil
|
||||||
|
case *uint64:
|
||||||
|
if len(buf) < 8 {
|
||||||
|
return errors.New("uint64 requires 8 bytes")
|
||||||
|
}
|
||||||
|
*value = internal.NativeEndian.Uint64(buf)
|
||||||
|
return nil
|
||||||
case string:
|
case string:
|
||||||
return errors.New("require pointer to string")
|
return errors.New("require pointer to string")
|
||||||
case []byte:
|
case []byte:
|
||||||
return errors.New("require pointer to []byte")
|
return errors.New("require pointer to []byte")
|
||||||
default:
|
default:
|
||||||
rd := bytes.NewReader(buf)
|
rd := bytesReaderPool.Get().(*bytes.Reader)
|
||||||
|
rd.Reset(buf)
|
||||||
|
defer bytesReaderPool.Put(rd)
|
||||||
if err := binary.Read(rd, internal.NativeEndian, value); err != nil {
|
if err := binary.Read(rd, internal.NativeEndian, value); err != nil {
|
||||||
return fmt.Errorf("decoding %T: %v", value, err)
|
return fmt.Errorf("decoding %T: %v", value, err)
|
||||||
}
|
}
|
||||||
@ -142,7 +181,7 @@ func marshalPerCPUValue(slice interface{}, elemLength int) (internal.Pointer, er
|
|||||||
return internal.Pointer{}, fmt.Errorf("per-CPU value exceeds number of CPUs")
|
return internal.Pointer{}, fmt.Errorf("per-CPU value exceeds number of CPUs")
|
||||||
}
|
}
|
||||||
|
|
||||||
alignedElemLength := align(elemLength, 8)
|
alignedElemLength := internal.Align(elemLength, 8)
|
||||||
buf := make([]byte, alignedElemLength*possibleCPUs)
|
buf := make([]byte, alignedElemLength*possibleCPUs)
|
||||||
|
|
||||||
for i := 0; i < sliceLen; i++ {
|
for i := 0; i < sliceLen; i++ {
|
||||||
@ -212,7 +251,3 @@ func unmarshalPerCPUValue(slicePtr interface{}, elemLength int, buf []byte) erro
|
|||||||
reflect.ValueOf(slicePtr).Elem().Set(slice)
|
reflect.ValueOf(slicePtr).Elem().Set(slice)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func align(n, alignment int) int {
|
|
||||||
return (int(n) + alignment - 1) / alignment * alignment
|
|
||||||
}
|
|
||||||
|
123
vendor/github.com/cilium/ebpf/prog.go
generated
vendored
123
vendor/github.com/cilium/ebpf/prog.go
generated
vendored
@ -57,16 +57,21 @@ type ProgramSpec struct {
|
|||||||
// Name is passed to the kernel as a debug aid. Must only contain
|
// Name is passed to the kernel as a debug aid. Must only contain
|
||||||
// alpha numeric and '_' characters.
|
// alpha numeric and '_' characters.
|
||||||
Name string
|
Name string
|
||||||
|
|
||||||
// Type determines at which hook in the kernel a program will run.
|
// Type determines at which hook in the kernel a program will run.
|
||||||
Type ProgramType
|
Type ProgramType
|
||||||
AttachType AttachType
|
AttachType AttachType
|
||||||
// Name of a kernel data structure to attach to. It's interpretation
|
// Name of a kernel data structure or function to attach to. Its
|
||||||
// depends on Type and AttachType.
|
// interpretation depends on Type and AttachType.
|
||||||
AttachTo string
|
AttachTo string
|
||||||
|
// The program to attach to. Must be provided manually.
|
||||||
|
AttachTarget *Program
|
||||||
Instructions asm.Instructions
|
Instructions asm.Instructions
|
||||||
|
|
||||||
// Flags is passed to the kernel and specifies additional program
|
// Flags is passed to the kernel and specifies additional program
|
||||||
// load attributes.
|
// load attributes.
|
||||||
Flags uint32
|
Flags uint32
|
||||||
|
|
||||||
// License of the program. Some helpers are only available if
|
// License of the program. Some helpers are only available if
|
||||||
// the license is deemed compatible with the GPL.
|
// the license is deemed compatible with the GPL.
|
||||||
//
|
//
|
||||||
@ -146,7 +151,7 @@ func NewProgramWithOptions(spec *ProgramSpec, opts ProgramOptions) (*Program, er
|
|||||||
|
|
||||||
func newProgramWithOptions(spec *ProgramSpec, opts ProgramOptions, handles *handleCache) (*Program, error) {
|
func newProgramWithOptions(spec *ProgramSpec, opts ProgramOptions, handles *handleCache) (*Program, error) {
|
||||||
if len(spec.Instructions) == 0 {
|
if len(spec.Instructions) == 0 {
|
||||||
return nil, errors.New("Instructions cannot be empty")
|
return nil, errors.New("instructions cannot be empty")
|
||||||
}
|
}
|
||||||
|
|
||||||
if spec.ByteOrder != nil && spec.ByteOrder != internal.NativeEndian {
|
if spec.ByteOrder != nil && spec.ByteOrder != internal.NativeEndian {
|
||||||
@ -166,16 +171,16 @@ func newProgramWithOptions(spec *ProgramSpec, opts ProgramOptions, handles *hand
|
|||||||
kv = v.Kernel()
|
kv = v.Kernel()
|
||||||
}
|
}
|
||||||
|
|
||||||
attr := &bpfProgLoadAttr{
|
attr := &internal.BPFProgLoadAttr{
|
||||||
progType: spec.Type,
|
ProgType: uint32(spec.Type),
|
||||||
progFlags: spec.Flags,
|
ProgFlags: spec.Flags,
|
||||||
expectedAttachType: spec.AttachType,
|
ExpectedAttachType: uint32(spec.AttachType),
|
||||||
license: internal.NewStringPointer(spec.License),
|
License: internal.NewStringPointer(spec.License),
|
||||||
kernelVersion: kv,
|
KernelVersion: kv,
|
||||||
}
|
}
|
||||||
|
|
||||||
if haveObjName() == nil {
|
if haveObjName() == nil {
|
||||||
attr.progName = internal.NewBPFObjName(spec.Name)
|
attr.ProgName = internal.NewBPFObjName(spec.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
@ -190,35 +195,35 @@ func newProgramWithOptions(spec *ProgramSpec, opts ProgramOptions, handles *hand
|
|||||||
var btfDisabled bool
|
var btfDisabled bool
|
||||||
var core btf.COREFixups
|
var core btf.COREFixups
|
||||||
if spec.BTF != nil {
|
if spec.BTF != nil {
|
||||||
core, err = btf.ProgramFixups(spec.BTF, targetBTF)
|
core, err = spec.BTF.Fixups(targetBTF)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("CO-RE relocations: %w", err)
|
return nil, fmt.Errorf("CO-RE relocations: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
handle, err := handles.btfHandle(btf.ProgramSpec(spec.BTF))
|
handle, err := handles.btfHandle(spec.BTF.Spec())
|
||||||
btfDisabled = errors.Is(err, btf.ErrNotSupported)
|
btfDisabled = errors.Is(err, btf.ErrNotSupported)
|
||||||
if err != nil && !btfDisabled {
|
if err != nil && !btfDisabled {
|
||||||
return nil, fmt.Errorf("load BTF: %w", err)
|
return nil, fmt.Errorf("load BTF: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if handle != nil {
|
if handle != nil {
|
||||||
attr.progBTFFd = uint32(handle.FD())
|
attr.ProgBTFFd = uint32(handle.FD())
|
||||||
|
|
||||||
recSize, bytes, err := btf.ProgramLineInfos(spec.BTF)
|
recSize, bytes, err := spec.BTF.LineInfos()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("get BTF line infos: %w", err)
|
return nil, fmt.Errorf("get BTF line infos: %w", err)
|
||||||
}
|
}
|
||||||
attr.lineInfoRecSize = recSize
|
attr.LineInfoRecSize = recSize
|
||||||
attr.lineInfoCnt = uint32(uint64(len(bytes)) / uint64(recSize))
|
attr.LineInfoCnt = uint32(uint64(len(bytes)) / uint64(recSize))
|
||||||
attr.lineInfo = internal.NewSlicePointer(bytes)
|
attr.LineInfo = internal.NewSlicePointer(bytes)
|
||||||
|
|
||||||
recSize, bytes, err = btf.ProgramFuncInfos(spec.BTF)
|
recSize, bytes, err = spec.BTF.FuncInfos()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("get BTF function infos: %w", err)
|
return nil, fmt.Errorf("get BTF function infos: %w", err)
|
||||||
}
|
}
|
||||||
attr.funcInfoRecSize = recSize
|
attr.FuncInfoRecSize = recSize
|
||||||
attr.funcInfoCnt = uint32(uint64(len(bytes)) / uint64(recSize))
|
attr.FuncInfoCnt = uint32(uint64(len(bytes)) / uint64(recSize))
|
||||||
attr.funcInfo = internal.NewSlicePointer(bytes)
|
attr.FuncInfo = internal.NewSlicePointer(bytes)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -238,16 +243,41 @@ func newProgramWithOptions(spec *ProgramSpec, opts ProgramOptions, handles *hand
|
|||||||
}
|
}
|
||||||
|
|
||||||
bytecode := buf.Bytes()
|
bytecode := buf.Bytes()
|
||||||
attr.instructions = internal.NewSlicePointer(bytecode)
|
attr.Instructions = internal.NewSlicePointer(bytecode)
|
||||||
attr.insCount = uint32(len(bytecode) / asm.InstructionSize)
|
attr.InsCount = uint32(len(bytecode) / asm.InstructionSize)
|
||||||
|
|
||||||
if spec.AttachTo != "" {
|
if spec.AttachTo != "" {
|
||||||
|
if spec.AttachTarget != nil {
|
||||||
|
info, err := spec.AttachTarget.Info()
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("load target BTF: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
btfID, ok := info.BTFID()
|
||||||
|
if !ok {
|
||||||
|
return nil, fmt.Errorf("load target BTF: no BTF info available")
|
||||||
|
}
|
||||||
|
btfHandle, err := btf.NewHandleFromID(btfID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("load target BTF: %w", err)
|
||||||
|
}
|
||||||
|
defer btfHandle.Close()
|
||||||
|
|
||||||
|
targetBTF = btfHandle.Spec()
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("load target BTF: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
target, err := resolveBTFType(targetBTF, spec.AttachTo, spec.Type, spec.AttachType)
|
target, err := resolveBTFType(targetBTF, spec.AttachTo, spec.Type, spec.AttachType)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if target != nil {
|
if target != nil {
|
||||||
attr.attachBTFID = target.ID()
|
attr.AttachBTFID = uint32(target.ID())
|
||||||
|
}
|
||||||
|
if spec.AttachTarget != nil {
|
||||||
|
attr.AttachProgFd = uint32(spec.AttachTarget.FD())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -259,12 +289,12 @@ func newProgramWithOptions(spec *ProgramSpec, opts ProgramOptions, handles *hand
|
|||||||
var logBuf []byte
|
var logBuf []byte
|
||||||
if opts.LogLevel > 0 {
|
if opts.LogLevel > 0 {
|
||||||
logBuf = make([]byte, logSize)
|
logBuf = make([]byte, logSize)
|
||||||
attr.logLevel = opts.LogLevel
|
attr.LogLevel = opts.LogLevel
|
||||||
attr.logSize = uint32(len(logBuf))
|
attr.LogSize = uint32(len(logBuf))
|
||||||
attr.logBuf = internal.NewSlicePointer(logBuf)
|
attr.LogBuf = internal.NewSlicePointer(logBuf)
|
||||||
}
|
}
|
||||||
|
|
||||||
fd, err := bpfProgLoad(attr)
|
fd, err := internal.BPFProgLoad(attr)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return &Program{internal.CString(logBuf), fd, spec.Name, "", spec.Type}, nil
|
return &Program{internal.CString(logBuf), fd, spec.Name, "", spec.Type}, nil
|
||||||
}
|
}
|
||||||
@ -273,17 +303,20 @@ func newProgramWithOptions(spec *ProgramSpec, opts ProgramOptions, handles *hand
|
|||||||
if opts.LogLevel == 0 && opts.LogSize >= 0 {
|
if opts.LogLevel == 0 && opts.LogSize >= 0 {
|
||||||
// Re-run with the verifier enabled to get better error messages.
|
// Re-run with the verifier enabled to get better error messages.
|
||||||
logBuf = make([]byte, logSize)
|
logBuf = make([]byte, logSize)
|
||||||
attr.logLevel = 1
|
attr.LogLevel = 1
|
||||||
attr.logSize = uint32(len(logBuf))
|
attr.LogSize = uint32(len(logBuf))
|
||||||
attr.logBuf = internal.NewSlicePointer(logBuf)
|
attr.LogBuf = internal.NewSlicePointer(logBuf)
|
||||||
|
|
||||||
_, logErr = bpfProgLoad(attr)
|
fd, logErr = internal.BPFProgLoad(attr)
|
||||||
|
if logErr == nil {
|
||||||
|
fd.Close()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if errors.Is(logErr, unix.EPERM) && logBuf[0] == 0 {
|
if errors.Is(logErr, unix.EPERM) && logBuf[0] == 0 {
|
||||||
// EPERM due to RLIMIT_MEMLOCK happens before the verifier, so we can
|
// EPERM due to RLIMIT_MEMLOCK happens before the verifier, so we can
|
||||||
// check that the log is empty to reduce false positives.
|
// check that the log is empty to reduce false positives.
|
||||||
return nil, fmt.Errorf("load program: RLIMIT_MEMLOCK may be too low: %w", logErr)
|
return nil, fmt.Errorf("load program: %w (MEMLOCK bay be too low, consider rlimit.RemoveMemlock)", logErr)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = internal.ErrorWithLog(err, logBuf, logErr)
|
err = internal.ErrorWithLog(err, logBuf, logErr)
|
||||||
@ -310,7 +343,7 @@ func NewProgramFromFD(fd int) (*Program, error) {
|
|||||||
//
|
//
|
||||||
// Returns ErrNotExist, if there is no eBPF program with the given id.
|
// Returns ErrNotExist, if there is no eBPF program with the given id.
|
||||||
func NewProgramFromID(id ProgramID) (*Program, error) {
|
func NewProgramFromID(id ProgramID) (*Program, error) {
|
||||||
fd, err := bpfObjGetFDByID(internal.BPF_PROG_GET_FD_BY_ID, uint32(id))
|
fd, err := internal.BPFObjGetFDByID(internal.BPF_PROG_GET_FD_BY_ID, uint32(id))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("get program by id: %w", err)
|
return nil, fmt.Errorf("get program by id: %w", err)
|
||||||
}
|
}
|
||||||
@ -677,45 +710,44 @@ func ProgramGetNextID(startID ProgramID) (ProgramID, error) {
|
|||||||
//
|
//
|
||||||
// Deprecated: use ProgramInfo.ID() instead.
|
// Deprecated: use ProgramInfo.ID() instead.
|
||||||
func (p *Program) ID() (ProgramID, error) {
|
func (p *Program) ID() (ProgramID, error) {
|
||||||
info, err := bpfGetProgInfoByFD(p.fd)
|
info, err := bpfGetProgInfoByFD(p.fd, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ProgramID(0), err
|
return ProgramID(0), err
|
||||||
}
|
}
|
||||||
return ProgramID(info.id), nil
|
return ProgramID(info.id), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func resolveBTFType(kernel *btf.Spec, name string, progType ProgramType, attachType AttachType) (btf.Type, error) {
|
func resolveBTFType(spec *btf.Spec, name string, progType ProgramType, attachType AttachType) (btf.Type, error) {
|
||||||
type match struct {
|
type match struct {
|
||||||
p ProgramType
|
p ProgramType
|
||||||
a AttachType
|
a AttachType
|
||||||
}
|
}
|
||||||
|
|
||||||
var target btf.Type
|
|
||||||
var typeName, featureName string
|
var typeName, featureName string
|
||||||
switch (match{progType, attachType}) {
|
switch (match{progType, attachType}) {
|
||||||
case match{LSM, AttachLSMMac}:
|
case match{LSM, AttachLSMMac}:
|
||||||
target = new(btf.Func)
|
|
||||||
typeName = "bpf_lsm_" + name
|
typeName = "bpf_lsm_" + name
|
||||||
featureName = name + " LSM hook"
|
featureName = name + " LSM hook"
|
||||||
|
|
||||||
case match{Tracing, AttachTraceIter}:
|
case match{Tracing, AttachTraceIter}:
|
||||||
target = new(btf.Func)
|
|
||||||
typeName = "bpf_iter_" + name
|
typeName = "bpf_iter_" + name
|
||||||
featureName = name + " iterator"
|
featureName = name + " iterator"
|
||||||
|
case match{Extension, AttachNone}:
|
||||||
|
typeName = name
|
||||||
|
featureName = fmt.Sprintf("freplace %s", name)
|
||||||
default:
|
default:
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if kernel == nil {
|
if spec == nil {
|
||||||
var err error
|
var err error
|
||||||
kernel, err = btf.LoadKernelSpec()
|
spec, err = btf.LoadKernelSpec()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("load kernel spec: %w", err)
|
return nil, fmt.Errorf("load kernel spec: %w", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
err := kernel.FindType(typeName, target)
|
var target *btf.Func
|
||||||
|
err := spec.FindType(typeName, &target)
|
||||||
if errors.Is(err, btf.ErrNotFound) {
|
if errors.Is(err, btf.ErrNotFound) {
|
||||||
return nil, &internal.UnsupportedFeatureError{
|
return nil, &internal.UnsupportedFeatureError{
|
||||||
Name: featureName,
|
Name: featureName,
|
||||||
@ -724,5 +756,6 @@ func resolveBTFType(kernel *btf.Spec, name string, progType ProgramType, attachT
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("resolve BTF for %s: %w", featureName, err)
|
return nil, fmt.Errorf("resolve BTF for %s: %w", featureName, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return target, nil
|
return target, nil
|
||||||
}
|
}
|
||||||
|
22
vendor/github.com/cilium/ebpf/run-tests.sh
generated
vendored
22
vendor/github.com/cilium/ebpf/run-tests.sh
generated
vendored
@ -5,7 +5,7 @@
|
|||||||
# Run all tests on a 5.4 kernel
|
# Run all tests on a 5.4 kernel
|
||||||
# $ ./run-tests.sh 5.4
|
# $ ./run-tests.sh 5.4
|
||||||
# Run a subset of tests:
|
# Run a subset of tests:
|
||||||
# $ ./run-tests.sh 5.4 go test ./link
|
# $ ./run-tests.sh 5.4 ./link
|
||||||
|
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
@ -48,15 +48,17 @@ if [[ "${1:-}" = "--exec-vm" ]]; then
|
|||||||
rm "${output}/fake-stdin"
|
rm "${output}/fake-stdin"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
$sudo virtme-run --kimg "${input}/bzImage" --memory 768M --pwd \
|
if ! $sudo virtme-run --kimg "${input}/bzImage" --memory 768M --pwd \
|
||||||
--rwdir="${testdir}=${testdir}" \
|
--rwdir="${testdir}=${testdir}" \
|
||||||
--rodir=/run/input="${input}" \
|
--rodir=/run/input="${input}" \
|
||||||
--rwdir=/run/output="${output}" \
|
--rwdir=/run/output="${output}" \
|
||||||
--script-sh "PATH=\"$PATH\" \"$script\" --exec-test $cmd" \
|
--script-sh "PATH=\"$PATH\" \"$script\" --exec-test $cmd" \
|
||||||
--qemu-opts -smp 2 # need at least two CPUs for some tests
|
--kopt possible_cpus=2; then # need at least two CPUs for some tests
|
||||||
|
exit 23
|
||||||
|
fi
|
||||||
|
|
||||||
if [[ ! -e "${output}/success" ]]; then
|
if [[ ! -e "${output}/success" ]]; then
|
||||||
exit 1
|
exit 42
|
||||||
fi
|
fi
|
||||||
|
|
||||||
$sudo rm -r "$output"
|
$sudo rm -r "$output"
|
||||||
@ -74,7 +76,7 @@ elif [[ "${1:-}" = "--exec-test" ]]; then
|
|||||||
dmesg -C
|
dmesg -C
|
||||||
if ! "$@"; then
|
if ! "$@"; then
|
||||||
dmesg
|
dmesg
|
||||||
exit 1
|
exit 1 # this return code is "swallowed" by qemu
|
||||||
fi
|
fi
|
||||||
touch "/run/output/success"
|
touch "/run/output/success"
|
||||||
exit 0
|
exit 0
|
||||||
@ -108,7 +110,7 @@ else
|
|||||||
echo "No selftests found, disabling"
|
echo "No selftests found, disabling"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
args=(-v -short -coverpkg=./... -coverprofile=coverage.out -count 1 ./...)
|
args=(-short -coverpkg=./... -coverprofile=coverage.out -count 1 ./...)
|
||||||
if (( $# > 0 )); then
|
if (( $# > 0 )); then
|
||||||
args=("$@")
|
args=("$@")
|
||||||
fi
|
fi
|
||||||
|
94
vendor/github.com/cilium/ebpf/syscalls.go
generated
vendored
94
vendor/github.com/cilium/ebpf/syscalls.go
generated
vendored
@ -1,13 +1,14 @@
|
|||||||
package ebpf
|
package ebpf
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
|
"github.com/cilium/ebpf/asm"
|
||||||
"github.com/cilium/ebpf/internal"
|
"github.com/cilium/ebpf/internal"
|
||||||
"github.com/cilium/ebpf/internal/btf"
|
|
||||||
"github.com/cilium/ebpf/internal/unix"
|
"github.com/cilium/ebpf/internal/unix"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -73,30 +74,6 @@ type bpfMapInfo struct {
|
|||||||
btf_value_type_id uint32
|
btf_value_type_id uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
type bpfProgLoadAttr struct {
|
|
||||||
progType ProgramType
|
|
||||||
insCount uint32
|
|
||||||
instructions internal.Pointer
|
|
||||||
license internal.Pointer
|
|
||||||
logLevel uint32
|
|
||||||
logSize uint32
|
|
||||||
logBuf internal.Pointer
|
|
||||||
kernelVersion uint32 // since 4.1 2541517c32be
|
|
||||||
progFlags uint32 // since 4.11 e07b98d9bffe
|
|
||||||
progName internal.BPFObjName // since 4.15 067cae47771c
|
|
||||||
progIfIndex uint32 // since 4.15 1f6f4cb7ba21
|
|
||||||
expectedAttachType AttachType // since 4.17 5e43f899b03a
|
|
||||||
progBTFFd uint32
|
|
||||||
funcInfoRecSize uint32
|
|
||||||
funcInfo internal.Pointer
|
|
||||||
funcInfoCnt uint32
|
|
||||||
lineInfoRecSize uint32
|
|
||||||
lineInfo internal.Pointer
|
|
||||||
lineInfoCnt uint32
|
|
||||||
attachBTFID btf.TypeID
|
|
||||||
attachProgFd uint32
|
|
||||||
}
|
|
||||||
|
|
||||||
type bpfProgInfo struct {
|
type bpfProgInfo struct {
|
||||||
prog_type uint32
|
prog_type uint32
|
||||||
id uint32
|
id uint32
|
||||||
@ -107,7 +84,7 @@ type bpfProgInfo struct {
|
|||||||
xlated_prog_insns internal.Pointer
|
xlated_prog_insns internal.Pointer
|
||||||
load_time uint64 // since 4.15 cb4d2b3f03d8
|
load_time uint64 // since 4.15 cb4d2b3f03d8
|
||||||
created_by_uid uint32
|
created_by_uid uint32
|
||||||
nr_map_ids uint32
|
nr_map_ids uint32 // since 4.15 cb4d2b3f03d8
|
||||||
map_ids internal.Pointer
|
map_ids internal.Pointer
|
||||||
name internal.BPFObjName // since 4.15 067cae47771c
|
name internal.BPFObjName // since 4.15 067cae47771c
|
||||||
ifindex uint32
|
ifindex uint32
|
||||||
@ -145,11 +122,6 @@ type bpfProgTestRunAttr struct {
|
|||||||
duration uint32
|
duration uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
type bpfGetFDByIDAttr struct {
|
|
||||||
id uint32
|
|
||||||
next uint32
|
|
||||||
}
|
|
||||||
|
|
||||||
type bpfMapFreezeAttr struct {
|
type bpfMapFreezeAttr struct {
|
||||||
mapFd uint32
|
mapFd uint32
|
||||||
}
|
}
|
||||||
@ -160,23 +132,6 @@ type bpfObjGetNextIDAttr struct {
|
|||||||
openFlags uint32
|
openFlags uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
func bpfProgLoad(attr *bpfProgLoadAttr) (*internal.FD, error) {
|
|
||||||
for {
|
|
||||||
fd, err := internal.BPF(internal.BPF_PROG_LOAD, unsafe.Pointer(attr), unsafe.Sizeof(*attr))
|
|
||||||
// As of ~4.20 the verifier can be interrupted by a signal,
|
|
||||||
// and returns EAGAIN in that case.
|
|
||||||
if errors.Is(err, unix.EAGAIN) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return internal.NewFD(uint32(fd)), nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func bpfProgTestRun(attr *bpfProgTestRunAttr) error {
|
func bpfProgTestRun(attr *bpfProgTestRunAttr) error {
|
||||||
_, err := internal.BPF(internal.BPF_PROG_TEST_RUN, unsafe.Pointer(attr), unsafe.Sizeof(*attr))
|
_, err := internal.BPF(internal.BPF_PROG_TEST_RUN, unsafe.Pointer(attr), unsafe.Sizeof(*attr))
|
||||||
return err
|
return err
|
||||||
@ -372,6 +327,10 @@ func wrapMapError(err error) error {
|
|||||||
return internal.SyscallError(ErrNotSupported, unix.ENOTSUPP)
|
return internal.SyscallError(ErrNotSupported, unix.ENOTSUPP)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if errors.Is(err, unix.E2BIG) {
|
||||||
|
return fmt.Errorf("key too big for map: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -388,8 +347,13 @@ func bpfMapFreeze(m *internal.FD) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func bpfGetProgInfoByFD(fd *internal.FD) (*bpfProgInfo, error) {
|
func bpfGetProgInfoByFD(fd *internal.FD, ids []MapID) (*bpfProgInfo, error) {
|
||||||
var info bpfProgInfo
|
var info bpfProgInfo
|
||||||
|
if len(ids) > 0 {
|
||||||
|
info.nr_map_ids = uint32(len(ids))
|
||||||
|
info.map_ids = internal.NewPointer(unsafe.Pointer(&ids[0]))
|
||||||
|
}
|
||||||
|
|
||||||
if err := internal.BPFObjGetInfoByFD(fd, unsafe.Pointer(&info), unsafe.Sizeof(info)); err != nil {
|
if err := internal.BPFObjGetInfoByFD(fd, unsafe.Pointer(&info), unsafe.Sizeof(info)); err != nil {
|
||||||
return nil, fmt.Errorf("can't get program info: %w", err)
|
return nil, fmt.Errorf("can't get program info: %w", err)
|
||||||
}
|
}
|
||||||
@ -471,10 +435,30 @@ var haveBatchAPI = internal.FeatureTest("map batch api", "5.6", func() error {
|
|||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
|
|
||||||
func bpfObjGetFDByID(cmd internal.BPFCmd, id uint32) (*internal.FD, error) {
|
var haveProbeReadKernel = internal.FeatureTest("bpf_probe_read_kernel", "5.5", func() error {
|
||||||
attr := bpfGetFDByIDAttr{
|
insns := asm.Instructions{
|
||||||
id: id,
|
asm.Mov.Reg(asm.R1, asm.R10),
|
||||||
|
asm.Add.Imm(asm.R1, -8),
|
||||||
|
asm.Mov.Imm(asm.R2, 8),
|
||||||
|
asm.Mov.Imm(asm.R3, 0),
|
||||||
|
asm.FnProbeReadKernel.Call(),
|
||||||
|
asm.Return(),
|
||||||
}
|
}
|
||||||
ptr, err := internal.BPF(cmd, unsafe.Pointer(&attr), unsafe.Sizeof(attr))
|
buf := bytes.NewBuffer(make([]byte, 0, len(insns)*asm.InstructionSize))
|
||||||
return internal.NewFD(uint32(ptr)), err
|
if err := insns.Marshal(buf, internal.NativeEndian); err != nil {
|
||||||
}
|
return err
|
||||||
|
}
|
||||||
|
bytecode := buf.Bytes()
|
||||||
|
|
||||||
|
fd, err := internal.BPFProgLoad(&internal.BPFProgLoadAttr{
|
||||||
|
ProgType: uint32(Kprobe),
|
||||||
|
License: internal.NewStringPointer("GPL"),
|
||||||
|
Instructions: internal.NewSlicePointer(bytecode),
|
||||||
|
InsCount: uint32(len(bytecode) / asm.InstructionSize),
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return internal.ErrNotSupported
|
||||||
|
}
|
||||||
|
_ = fd.Close()
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
36
vendor/github.com/cilium/ebpf/types.go
generated
vendored
36
vendor/github.com/cilium/ebpf/types.go
generated
vendored
@ -4,12 +4,17 @@ import (
|
|||||||
"github.com/cilium/ebpf/internal/unix"
|
"github.com/cilium/ebpf/internal/unix"
|
||||||
)
|
)
|
||||||
|
|
||||||
//go:generate stringer -output types_string.go -type=MapType,ProgramType,AttachType,PinType
|
//go:generate stringer -output types_string.go -type=MapType,ProgramType,PinType
|
||||||
|
|
||||||
// MapType indicates the type map structure
|
// MapType indicates the type map structure
|
||||||
// that will be initialized in the kernel.
|
// that will be initialized in the kernel.
|
||||||
type MapType uint32
|
type MapType uint32
|
||||||
|
|
||||||
|
// Max returns the latest supported MapType.
|
||||||
|
func (_ MapType) Max() MapType {
|
||||||
|
return maxMapType - 1
|
||||||
|
}
|
||||||
|
|
||||||
// All the various map types that can be created
|
// All the various map types that can be created
|
||||||
const (
|
const (
|
||||||
UnspecifiedMap MapType = iota
|
UnspecifiedMap MapType = iota
|
||||||
@ -85,15 +90,28 @@ const (
|
|||||||
SkStorage
|
SkStorage
|
||||||
// DevMapHash - Hash-based indexing scheme for references to network devices.
|
// DevMapHash - Hash-based indexing scheme for references to network devices.
|
||||||
DevMapHash
|
DevMapHash
|
||||||
StructOpts
|
// StructOpsMap - This map holds a kernel struct with its function pointer implemented in a BPF
|
||||||
|
// program.
|
||||||
|
StructOpsMap
|
||||||
|
// RingBuf - Similar to PerfEventArray, but shared across all CPUs.
|
||||||
RingBuf
|
RingBuf
|
||||||
|
// InodeStorage - Specialized local storage map for inodes.
|
||||||
InodeStorage
|
InodeStorage
|
||||||
|
// TaskStorage - Specialized local storage map for task_struct.
|
||||||
TaskStorage
|
TaskStorage
|
||||||
|
// maxMapType - Bound enum of MapTypes, has to be last in enum.
|
||||||
|
maxMapType
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Deprecated: StructOpts was a typo, use StructOpsMap instead.
|
||||||
|
//
|
||||||
|
// Declared as a variable to prevent stringer from picking it up
|
||||||
|
// as an enum value.
|
||||||
|
var StructOpts MapType = StructOpsMap
|
||||||
|
|
||||||
// hasPerCPUValue returns true if the Map stores a value per CPU.
|
// hasPerCPUValue returns true if the Map stores a value per CPU.
|
||||||
func (mt MapType) hasPerCPUValue() bool {
|
func (mt MapType) hasPerCPUValue() bool {
|
||||||
return mt == PerCPUHash || mt == PerCPUArray || mt == LRUCPUHash
|
return mt == PerCPUHash || mt == PerCPUArray || mt == LRUCPUHash || mt == PerCPUCGroupStorage
|
||||||
}
|
}
|
||||||
|
|
||||||
// canStoreMap returns true if the map type accepts a map fd
|
// canStoreMap returns true if the map type accepts a map fd
|
||||||
@ -111,6 +129,11 @@ func (mt MapType) canStoreProgram() bool {
|
|||||||
// ProgramType of the eBPF program
|
// ProgramType of the eBPF program
|
||||||
type ProgramType uint32
|
type ProgramType uint32
|
||||||
|
|
||||||
|
// Max return the latest supported ProgramType.
|
||||||
|
func (_ ProgramType) Max() ProgramType {
|
||||||
|
return maxProgramType - 1
|
||||||
|
}
|
||||||
|
|
||||||
// eBPF program types
|
// eBPF program types
|
||||||
const (
|
const (
|
||||||
UnspecifiedProgram ProgramType = iota
|
UnspecifiedProgram ProgramType = iota
|
||||||
@ -144,6 +167,7 @@ const (
|
|||||||
Extension
|
Extension
|
||||||
LSM
|
LSM
|
||||||
SkLookup
|
SkLookup
|
||||||
|
maxProgramType
|
||||||
)
|
)
|
||||||
|
|
||||||
// AttachType of the eBPF program, needed to differentiate allowed context accesses in
|
// AttachType of the eBPF program, needed to differentiate allowed context accesses in
|
||||||
@ -151,6 +175,8 @@ const (
|
|||||||
// Will cause invalid argument (EINVAL) at program load time if set incorrectly.
|
// Will cause invalid argument (EINVAL) at program load time if set incorrectly.
|
||||||
type AttachType uint32
|
type AttachType uint32
|
||||||
|
|
||||||
|
//go:generate stringer -type AttachType -trimprefix Attach
|
||||||
|
|
||||||
// AttachNone is an alias for AttachCGroupInetIngress for readability reasons.
|
// AttachNone is an alias for AttachCGroupInetIngress for readability reasons.
|
||||||
const AttachNone AttachType = 0
|
const AttachNone AttachType = 0
|
||||||
|
|
||||||
@ -193,6 +219,10 @@ const (
|
|||||||
AttachXDPCPUMap
|
AttachXDPCPUMap
|
||||||
AttachSkLookup
|
AttachSkLookup
|
||||||
AttachXDP
|
AttachXDP
|
||||||
|
AttachSkSKBVerdict
|
||||||
|
AttachSkReuseportSelect
|
||||||
|
AttachSkReuseportSelectOrMigrate
|
||||||
|
AttachPerfEvent
|
||||||
)
|
)
|
||||||
|
|
||||||
// AttachFlags of the eBPF program used in BPF_PROG_ATTACH command
|
// AttachFlags of the eBPF program used in BPF_PROG_ATTACH command
|
||||||
|
69
vendor/github.com/cilium/ebpf/types_string.go
generated
vendored
69
vendor/github.com/cilium/ebpf/types_string.go
generated
vendored
@ -1,4 +1,4 @@
|
|||||||
// Code generated by "stringer -output types_string.go -type=MapType,ProgramType,AttachType,PinType"; DO NOT EDIT.
|
// Code generated by "stringer -output types_string.go -type=MapType,ProgramType,PinType"; DO NOT EDIT.
|
||||||
|
|
||||||
package ebpf
|
package ebpf
|
||||||
|
|
||||||
@ -34,15 +34,16 @@ func _() {
|
|||||||
_ = x[Stack-23]
|
_ = x[Stack-23]
|
||||||
_ = x[SkStorage-24]
|
_ = x[SkStorage-24]
|
||||||
_ = x[DevMapHash-25]
|
_ = x[DevMapHash-25]
|
||||||
_ = x[StructOpts-26]
|
_ = x[StructOpsMap-26]
|
||||||
_ = x[RingBuf-27]
|
_ = x[RingBuf-27]
|
||||||
_ = x[InodeStorage-28]
|
_ = x[InodeStorage-28]
|
||||||
_ = x[TaskStorage-29]
|
_ = x[TaskStorage-29]
|
||||||
|
_ = x[maxMapType-30]
|
||||||
}
|
}
|
||||||
|
|
||||||
const _MapType_name = "UnspecifiedMapHashArrayProgramArrayPerfEventArrayPerCPUHashPerCPUArrayStackTraceCGroupArrayLRUHashLRUCPUHashLPMTrieArrayOfMapsHashOfMapsDevMapSockMapCPUMapXSKMapSockHashCGroupStorageReusePortSockArrayPerCPUCGroupStorageQueueStackSkStorageDevMapHashStructOptsRingBufInodeStorageTaskStorage"
|
const _MapType_name = "UnspecifiedMapHashArrayProgramArrayPerfEventArrayPerCPUHashPerCPUArrayStackTraceCGroupArrayLRUHashLRUCPUHashLPMTrieArrayOfMapsHashOfMapsDevMapSockMapCPUMapXSKMapSockHashCGroupStorageReusePortSockArrayPerCPUCGroupStorageQueueStackSkStorageDevMapHashStructOpsMapRingBufInodeStorageTaskStoragemaxMapType"
|
||||||
|
|
||||||
var _MapType_index = [...]uint16{0, 14, 18, 23, 35, 49, 59, 70, 80, 91, 98, 108, 115, 126, 136, 142, 149, 155, 161, 169, 182, 200, 219, 224, 229, 238, 248, 258, 265, 277, 288}
|
var _MapType_index = [...]uint16{0, 14, 18, 23, 35, 49, 59, 70, 80, 91, 98, 108, 115, 126, 136, 142, 149, 155, 161, 169, 182, 200, 219, 224, 229, 238, 248, 260, 267, 279, 290, 300}
|
||||||
|
|
||||||
func (i MapType) String() string {
|
func (i MapType) String() string {
|
||||||
if i >= MapType(len(_MapType_index)-1) {
|
if i >= MapType(len(_MapType_index)-1) {
|
||||||
@ -85,11 +86,12 @@ func _() {
|
|||||||
_ = x[Extension-28]
|
_ = x[Extension-28]
|
||||||
_ = x[LSM-29]
|
_ = x[LSM-29]
|
||||||
_ = x[SkLookup-30]
|
_ = x[SkLookup-30]
|
||||||
|
_ = x[maxProgramType-31]
|
||||||
}
|
}
|
||||||
|
|
||||||
const _ProgramType_name = "UnspecifiedProgramSocketFilterKprobeSchedCLSSchedACTTracePointXDPPerfEventCGroupSKBCGroupSockLWTInLWTOutLWTXmitSockOpsSkSKBCGroupDeviceSkMsgRawTracepointCGroupSockAddrLWTSeg6LocalLircMode2SkReuseportFlowDissectorCGroupSysctlRawTracepointWritableCGroupSockoptTracingStructOpsExtensionLSMSkLookup"
|
const _ProgramType_name = "UnspecifiedProgramSocketFilterKprobeSchedCLSSchedACTTracePointXDPPerfEventCGroupSKBCGroupSockLWTInLWTOutLWTXmitSockOpsSkSKBCGroupDeviceSkMsgRawTracepointCGroupSockAddrLWTSeg6LocalLircMode2SkReuseportFlowDissectorCGroupSysctlRawTracepointWritableCGroupSockoptTracingStructOpsExtensionLSMSkLookupmaxProgramType"
|
||||||
|
|
||||||
var _ProgramType_index = [...]uint16{0, 18, 30, 36, 44, 52, 62, 65, 74, 83, 93, 98, 104, 111, 118, 123, 135, 140, 153, 167, 179, 188, 199, 212, 224, 245, 258, 265, 274, 283, 286, 294}
|
var _ProgramType_index = [...]uint16{0, 18, 30, 36, 44, 52, 62, 65, 74, 83, 93, 98, 104, 111, 118, 123, 135, 140, 153, 167, 179, 188, 199, 212, 224, 245, 258, 265, 274, 283, 286, 294, 308}
|
||||||
|
|
||||||
func (i ProgramType) String() string {
|
func (i ProgramType) String() string {
|
||||||
if i >= ProgramType(len(_ProgramType_index)-1) {
|
if i >= ProgramType(len(_ProgramType_index)-1) {
|
||||||
@ -97,61 +99,6 @@ func (i ProgramType) String() string {
|
|||||||
}
|
}
|
||||||
return _ProgramType_name[_ProgramType_index[i]:_ProgramType_index[i+1]]
|
return _ProgramType_name[_ProgramType_index[i]:_ProgramType_index[i+1]]
|
||||||
}
|
}
|
||||||
func _() {
|
|
||||||
// An "invalid array index" compiler error signifies that the constant values have changed.
|
|
||||||
// Re-run the stringer command to generate them again.
|
|
||||||
var x [1]struct{}
|
|
||||||
_ = x[AttachNone-0]
|
|
||||||
_ = x[AttachCGroupInetIngress-0]
|
|
||||||
_ = x[AttachCGroupInetEgress-1]
|
|
||||||
_ = x[AttachCGroupInetSockCreate-2]
|
|
||||||
_ = x[AttachCGroupSockOps-3]
|
|
||||||
_ = x[AttachSkSKBStreamParser-4]
|
|
||||||
_ = x[AttachSkSKBStreamVerdict-5]
|
|
||||||
_ = x[AttachCGroupDevice-6]
|
|
||||||
_ = x[AttachSkMsgVerdict-7]
|
|
||||||
_ = x[AttachCGroupInet4Bind-8]
|
|
||||||
_ = x[AttachCGroupInet6Bind-9]
|
|
||||||
_ = x[AttachCGroupInet4Connect-10]
|
|
||||||
_ = x[AttachCGroupInet6Connect-11]
|
|
||||||
_ = x[AttachCGroupInet4PostBind-12]
|
|
||||||
_ = x[AttachCGroupInet6PostBind-13]
|
|
||||||
_ = x[AttachCGroupUDP4Sendmsg-14]
|
|
||||||
_ = x[AttachCGroupUDP6Sendmsg-15]
|
|
||||||
_ = x[AttachLircMode2-16]
|
|
||||||
_ = x[AttachFlowDissector-17]
|
|
||||||
_ = x[AttachCGroupSysctl-18]
|
|
||||||
_ = x[AttachCGroupUDP4Recvmsg-19]
|
|
||||||
_ = x[AttachCGroupUDP6Recvmsg-20]
|
|
||||||
_ = x[AttachCGroupGetsockopt-21]
|
|
||||||
_ = x[AttachCGroupSetsockopt-22]
|
|
||||||
_ = x[AttachTraceRawTp-23]
|
|
||||||
_ = x[AttachTraceFEntry-24]
|
|
||||||
_ = x[AttachTraceFExit-25]
|
|
||||||
_ = x[AttachModifyReturn-26]
|
|
||||||
_ = x[AttachLSMMac-27]
|
|
||||||
_ = x[AttachTraceIter-28]
|
|
||||||
_ = x[AttachCgroupInet4GetPeername-29]
|
|
||||||
_ = x[AttachCgroupInet6GetPeername-30]
|
|
||||||
_ = x[AttachCgroupInet4GetSockname-31]
|
|
||||||
_ = x[AttachCgroupInet6GetSockname-32]
|
|
||||||
_ = x[AttachXDPDevMap-33]
|
|
||||||
_ = x[AttachCgroupInetSockRelease-34]
|
|
||||||
_ = x[AttachXDPCPUMap-35]
|
|
||||||
_ = x[AttachSkLookup-36]
|
|
||||||
_ = x[AttachXDP-37]
|
|
||||||
}
|
|
||||||
|
|
||||||
const _AttachType_name = "AttachNoneAttachCGroupInetEgressAttachCGroupInetSockCreateAttachCGroupSockOpsAttachSkSKBStreamParserAttachSkSKBStreamVerdictAttachCGroupDeviceAttachSkMsgVerdictAttachCGroupInet4BindAttachCGroupInet6BindAttachCGroupInet4ConnectAttachCGroupInet6ConnectAttachCGroupInet4PostBindAttachCGroupInet6PostBindAttachCGroupUDP4SendmsgAttachCGroupUDP6SendmsgAttachLircMode2AttachFlowDissectorAttachCGroupSysctlAttachCGroupUDP4RecvmsgAttachCGroupUDP6RecvmsgAttachCGroupGetsockoptAttachCGroupSetsockoptAttachTraceRawTpAttachTraceFEntryAttachTraceFExitAttachModifyReturnAttachLSMMacAttachTraceIterAttachCgroupInet4GetPeernameAttachCgroupInet6GetPeernameAttachCgroupInet4GetSocknameAttachCgroupInet6GetSocknameAttachXDPDevMapAttachCgroupInetSockReleaseAttachXDPCPUMapAttachSkLookupAttachXDP"
|
|
||||||
|
|
||||||
var _AttachType_index = [...]uint16{0, 10, 32, 58, 77, 100, 124, 142, 160, 181, 202, 226, 250, 275, 300, 323, 346, 361, 380, 398, 421, 444, 466, 488, 504, 521, 537, 555, 567, 582, 610, 638, 666, 694, 709, 736, 751, 765, 774}
|
|
||||||
|
|
||||||
func (i AttachType) String() string {
|
|
||||||
if i >= AttachType(len(_AttachType_index)-1) {
|
|
||||||
return "AttachType(" + strconv.FormatInt(int64(i), 10) + ")"
|
|
||||||
}
|
|
||||||
return _AttachType_name[_AttachType_index[i]:_AttachType_index[i+1]]
|
|
||||||
}
|
|
||||||
func _() {
|
func _() {
|
||||||
// An "invalid array index" compiler error signifies that the constant values have changed.
|
// An "invalid array index" compiler error signifies that the constant values have changed.
|
||||||
// Re-run the stringer command to generate them again.
|
// Re-run the stringer command to generate them again.
|
||||||
|
10
vendor/github.com/containerd/console/console_windows.go
generated
vendored
10
vendor/github.com/containerd/console/console_windows.go
generated
vendored
@ -17,10 +17,10 @@
|
|||||||
package console
|
package console
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
"golang.org/x/sys/windows"
|
"golang.org/x/sys/windows"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -103,7 +103,7 @@ func (m *master) Reset() error {
|
|||||||
{m.err, m.errMode},
|
{m.err, m.errMode},
|
||||||
} {
|
} {
|
||||||
if err := windows.SetConsoleMode(s.fd, s.mode); err != nil {
|
if err := windows.SetConsoleMode(s.fd, s.mode); err != nil {
|
||||||
return errors.Wrap(err, "unable to restore console mode")
|
return fmt.Errorf("unable to restore console mode: %w", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -114,7 +114,7 @@ func (m *master) Size() (WinSize, error) {
|
|||||||
var info windows.ConsoleScreenBufferInfo
|
var info windows.ConsoleScreenBufferInfo
|
||||||
err := windows.GetConsoleScreenBufferInfo(m.out, &info)
|
err := windows.GetConsoleScreenBufferInfo(m.out, &info)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return WinSize{}, errors.Wrap(err, "unable to get console info")
|
return WinSize{}, fmt.Errorf("unable to get console info: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
winsize := WinSize{
|
winsize := WinSize{
|
||||||
@ -139,7 +139,7 @@ func (m *master) DisableEcho() error {
|
|||||||
mode |= windows.ENABLE_LINE_INPUT
|
mode |= windows.ENABLE_LINE_INPUT
|
||||||
|
|
||||||
if err := windows.SetConsoleMode(m.in, mode); err != nil {
|
if err := windows.SetConsoleMode(m.in, mode); err != nil {
|
||||||
return errors.Wrap(err, "unable to set console to disable echo")
|
return fmt.Errorf("unable to set console to disable echo: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
@ -192,7 +192,7 @@ func makeInputRaw(fd windows.Handle, mode uint32) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if err := windows.SetConsoleMode(fd, mode); err != nil {
|
if err := windows.SetConsoleMode(fd, mode); err != nil {
|
||||||
return errors.Wrap(err, "unable to set console to raw mode")
|
return fmt.Errorf("unable to set console to raw mode: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
163
vendor/github.com/containerd/console/console_zos.go
generated
vendored
Normal file
163
vendor/github.com/containerd/console/console_zos.go
generated
vendored
Normal file
@ -0,0 +1,163 @@
|
|||||||
|
// +build zos
|
||||||
|
|
||||||
|
/*
|
||||||
|
Copyright The containerd Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package console
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"golang.org/x/sys/unix"
|
||||||
|
)
|
||||||
|
|
||||||
|
// NewPty creates a new pty pair
|
||||||
|
// The master is returned as the first console and a string
|
||||||
|
// with the path to the pty slave is returned as the second
|
||||||
|
func NewPty() (Console, string, error) {
|
||||||
|
var f File
|
||||||
|
var err error
|
||||||
|
var slave string
|
||||||
|
for i := 0;; i++ {
|
||||||
|
ptyp := fmt.Sprintf("/dev/ptyp%04d", i)
|
||||||
|
f, err = os.OpenFile(ptyp, os.O_RDWR, 0600)
|
||||||
|
if err == nil {
|
||||||
|
slave = fmt.Sprintf("/dev/ttyp%04d", i)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if os.IsNotExist(err) {
|
||||||
|
return nil, "", err
|
||||||
|
}
|
||||||
|
// else probably Resource Busy
|
||||||
|
}
|
||||||
|
m, err := newMaster(f)
|
||||||
|
if err != nil {
|
||||||
|
return nil, "", err
|
||||||
|
}
|
||||||
|
return m, slave, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type master struct {
|
||||||
|
f File
|
||||||
|
original *unix.Termios
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *master) Read(b []byte) (int, error) {
|
||||||
|
return m.f.Read(b)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *master) Write(b []byte) (int, error) {
|
||||||
|
return m.f.Write(b)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *master) Close() error {
|
||||||
|
return m.f.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *master) Resize(ws WinSize) error {
|
||||||
|
return tcswinsz(m.f.Fd(), ws)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *master) ResizeFrom(c Console) error {
|
||||||
|
ws, err := c.Size()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return m.Resize(ws)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *master) Reset() error {
|
||||||
|
if m.original == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return tcset(m.f.Fd(), m.original)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *master) getCurrent() (unix.Termios, error) {
|
||||||
|
var termios unix.Termios
|
||||||
|
if err := tcget(m.f.Fd(), &termios); err != nil {
|
||||||
|
return unix.Termios{}, err
|
||||||
|
}
|
||||||
|
return termios, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *master) SetRaw() error {
|
||||||
|
rawState, err := m.getCurrent()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
rawState = cfmakeraw(rawState)
|
||||||
|
rawState.Oflag = rawState.Oflag | unix.OPOST
|
||||||
|
return tcset(m.f.Fd(), &rawState)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *master) DisableEcho() error {
|
||||||
|
rawState, err := m.getCurrent()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
rawState.Lflag = rawState.Lflag &^ unix.ECHO
|
||||||
|
return tcset(m.f.Fd(), &rawState)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *master) Size() (WinSize, error) {
|
||||||
|
return tcgwinsz(m.f.Fd())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *master) Fd() uintptr {
|
||||||
|
return m.f.Fd()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *master) Name() string {
|
||||||
|
return m.f.Name()
|
||||||
|
}
|
||||||
|
|
||||||
|
// checkConsole checks if the provided file is a console
|
||||||
|
func checkConsole(f File) error {
|
||||||
|
var termios unix.Termios
|
||||||
|
if tcget(f.Fd(), &termios) != nil {
|
||||||
|
return ErrNotAConsole
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func newMaster(f File) (Console, error) {
|
||||||
|
m := &master{
|
||||||
|
f: f,
|
||||||
|
}
|
||||||
|
t, err := m.getCurrent()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
m.original = &t
|
||||||
|
return m, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ClearONLCR sets the necessary tty_ioctl(4)s to ensure that a pty pair
|
||||||
|
// created by us acts normally. In particular, a not-very-well-known default of
|
||||||
|
// Linux unix98 ptys is that they have +onlcr by default. While this isn't a
|
||||||
|
// problem for terminal emulators, because we relay data from the terminal we
|
||||||
|
// also relay that funky line discipline.
|
||||||
|
func ClearONLCR(fd uintptr) error {
|
||||||
|
return setONLCR(fd, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetONLCR sets the necessary tty_ioctl(4)s to ensure that a pty pair
|
||||||
|
// created by us acts as intended for a terminal emulator.
|
||||||
|
func SetONLCR(fd uintptr) error {
|
||||||
|
return setONLCR(fd, true)
|
||||||
|
}
|
5
vendor/github.com/containerd/console/go.mod
generated
vendored
5
vendor/github.com/containerd/console/go.mod
generated
vendored
@ -2,7 +2,4 @@ module github.com/containerd/console
|
|||||||
|
|
||||||
go 1.13
|
go 1.13
|
||||||
|
|
||||||
require (
|
require golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c
|
||||||
github.com/pkg/errors v0.9.1
|
|
||||||
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c
|
|
||||||
)
|
|
||||||
|
2
vendor/github.com/containerd/console/go.sum
generated
vendored
2
vendor/github.com/containerd/console/go.sum
generated
vendored
@ -1,4 +1,2 @@
|
|||||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
|
||||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
|
||||||
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c h1:VwygUrnw9jn88c4u8GD3rZQbqrP/tgas88tPUbBxQrk=
|
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c h1:VwygUrnw9jn88c4u8GD3rZQbqrP/tgas88tPUbBxQrk=
|
||||||
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
2
vendor/github.com/containerd/console/tc_unix.go
generated
vendored
2
vendor/github.com/containerd/console/tc_unix.go
generated
vendored
@ -1,4 +1,4 @@
|
|||||||
// +build darwin freebsd linux netbsd openbsd solaris
|
// +build darwin freebsd linux netbsd openbsd solaris zos
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Copyright The containerd Authors.
|
Copyright The containerd Authors.
|
||||||
|
26
vendor/github.com/containerd/console/tc_zos.go
generated
vendored
Normal file
26
vendor/github.com/containerd/console/tc_zos.go
generated
vendored
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
/*
|
||||||
|
Copyright The containerd Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package console
|
||||||
|
|
||||||
|
import (
|
||||||
|
"golang.org/x/sys/unix"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
cmdTcGet = unix.TCGETS
|
||||||
|
cmdTcSet = unix.TCSETS
|
||||||
|
)
|
8
vendor/github.com/cyphar/filepath-securejoin/.travis.yml
generated
vendored
8
vendor/github.com/cyphar/filepath-securejoin/.travis.yml
generated
vendored
@ -4,10 +4,12 @@
|
|||||||
|
|
||||||
language: go
|
language: go
|
||||||
go:
|
go:
|
||||||
- 1.7.x
|
- 1.13.x
|
||||||
- 1.8.x
|
- 1.16.x
|
||||||
- tip
|
- tip
|
||||||
|
arch:
|
||||||
|
- AMD64
|
||||||
|
- ppc64le
|
||||||
os:
|
os:
|
||||||
- linux
|
- linux
|
||||||
- osx
|
- osx
|
||||||
|
20
vendor/github.com/cyphar/filepath-securejoin/README.md
generated
vendored
20
vendor/github.com/cyphar/filepath-securejoin/README.md
generated
vendored
@ -7,6 +7,19 @@ standard library][go#20126]. The purpose of this function is to be a "secure"
|
|||||||
alternative to `filepath.Join`, and in particular it provides certain
|
alternative to `filepath.Join`, and in particular it provides certain
|
||||||
guarantees that are not provided by `filepath.Join`.
|
guarantees that are not provided by `filepath.Join`.
|
||||||
|
|
||||||
|
> **NOTE**: This code is *only* safe if you are not at risk of other processes
|
||||||
|
> modifying path components after you've used `SecureJoin`. If it is possible
|
||||||
|
> for a malicious process to modify path components of the resolved path, then
|
||||||
|
> you will be vulnerable to some fairly trivial TOCTOU race conditions. [There
|
||||||
|
> are some Linux kernel patches I'm working on which might allow for a better
|
||||||
|
> solution.][lwn-obeneath]
|
||||||
|
>
|
||||||
|
> In addition, with a slightly modified API it might be possible to use
|
||||||
|
> `O_PATH` and verify that the opened path is actually the resolved one -- but
|
||||||
|
> I have not done that yet. I might add it in the future as a helper function
|
||||||
|
> to help users verify the path (we can't just return `/proc/self/fd/<foo>`
|
||||||
|
> because that doesn't always work transparently for all users).
|
||||||
|
|
||||||
This is the function prototype:
|
This is the function prototype:
|
||||||
|
|
||||||
```go
|
```go
|
||||||
@ -16,8 +29,8 @@ func SecureJoin(root, unsafePath string) (string, error)
|
|||||||
This library **guarantees** the following:
|
This library **guarantees** the following:
|
||||||
|
|
||||||
* If no error is set, the resulting string **must** be a child path of
|
* If no error is set, the resulting string **must** be a child path of
|
||||||
`SecureJoin` and will not contain any symlink path components (they will all
|
`root` and will not contain any symlink path components (they will all be
|
||||||
be expanded).
|
expanded).
|
||||||
|
|
||||||
* When expanding symlinks, all symlink path components **must** be resolved
|
* When expanding symlinks, all symlink path components **must** be resolved
|
||||||
relative to the provided root. In particular, this can be considered a
|
relative to the provided root. In particular, this can be considered a
|
||||||
@ -25,7 +38,7 @@ This library **guarantees** the following:
|
|||||||
these symlinks will **not** be expanded lexically (`filepath.Clean` is not
|
these symlinks will **not** be expanded lexically (`filepath.Clean` is not
|
||||||
called on the input before processing).
|
called on the input before processing).
|
||||||
|
|
||||||
* Non-existant path components are unaffected by `SecureJoin` (similar to
|
* Non-existent path components are unaffected by `SecureJoin` (similar to
|
||||||
`filepath.EvalSymlinks`'s semantics).
|
`filepath.EvalSymlinks`'s semantics).
|
||||||
|
|
||||||
* The returned path will always be `filepath.Clean`ed and thus not contain any
|
* The returned path will always be `filepath.Clean`ed and thus not contain any
|
||||||
@ -57,6 +70,7 @@ func SecureJoin(root, unsafePath string) (string, error) {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
[lwn-obeneath]: https://lwn.net/Articles/767547/
|
||||||
[go#20126]: https://github.com/golang/go/issues/20126
|
[go#20126]: https://github.com/golang/go/issues/20126
|
||||||
|
|
||||||
### License ###
|
### License ###
|
||||||
|
2
vendor/github.com/cyphar/filepath-securejoin/VERSION
generated
vendored
2
vendor/github.com/cyphar/filepath-securejoin/VERSION
generated
vendored
@ -1 +1 @@
|
|||||||
0.2.2
|
0.2.3
|
||||||
|
3
vendor/github.com/cyphar/filepath-securejoin/go.mod
generated
vendored
Normal file
3
vendor/github.com/cyphar/filepath-securejoin/go.mod
generated
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
module github.com/cyphar/filepath-securejoin
|
||||||
|
|
||||||
|
go 1.13
|
25
vendor/github.com/cyphar/filepath-securejoin/join.go
generated
vendored
25
vendor/github.com/cyphar/filepath-securejoin/join.go
generated
vendored
@ -12,39 +12,20 @@ package securejoin
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"errors"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// ErrSymlinkLoop is returned by SecureJoinVFS when too many symlinks have been
|
|
||||||
// evaluated in attempting to securely join the two given paths.
|
|
||||||
var ErrSymlinkLoop = errors.Wrap(syscall.ELOOP, "secure join")
|
|
||||||
|
|
||||||
// IsNotExist tells you if err is an error that implies that either the path
|
// IsNotExist tells you if err is an error that implies that either the path
|
||||||
// accessed does not exist (or path components don't exist). This is
|
// accessed does not exist (or path components don't exist). This is
|
||||||
// effectively a more broad version of os.IsNotExist.
|
// effectively a more broad version of os.IsNotExist.
|
||||||
func IsNotExist(err error) bool {
|
func IsNotExist(err error) bool {
|
||||||
// If it's a bone-fide ENOENT just bail.
|
|
||||||
if os.IsNotExist(errors.Cause(err)) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check that it's not actually an ENOTDIR, which in some cases is a more
|
// Check that it's not actually an ENOTDIR, which in some cases is a more
|
||||||
// convoluted case of ENOENT (usually involving weird paths).
|
// convoluted case of ENOENT (usually involving weird paths).
|
||||||
var errno error
|
return errors.Is(err, os.ErrNotExist) || errors.Is(err, syscall.ENOTDIR) || errors.Is(err, syscall.ENOENT)
|
||||||
switch err := errors.Cause(err).(type) {
|
|
||||||
case *os.PathError:
|
|
||||||
errno = err.Err
|
|
||||||
case *os.LinkError:
|
|
||||||
errno = err.Err
|
|
||||||
case *os.SyscallError:
|
|
||||||
errno = err.Err
|
|
||||||
}
|
|
||||||
return errno == syscall.ENOTDIR || errno == syscall.ENOENT
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// SecureJoinVFS joins the two given path components (similar to Join) except
|
// SecureJoinVFS joins the two given path components (similar to Join) except
|
||||||
@ -68,7 +49,7 @@ func SecureJoinVFS(root, unsafePath string, vfs VFS) (string, error) {
|
|||||||
n := 0
|
n := 0
|
||||||
for unsafePath != "" {
|
for unsafePath != "" {
|
||||||
if n > 255 {
|
if n > 255 {
|
||||||
return "", ErrSymlinkLoop
|
return "", &os.PathError{Op: "SecureJoin", Path: root + "/" + unsafePath, Err: syscall.ELOOP}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Next path component, p.
|
// Next path component, p.
|
||||||
|
1
vendor/github.com/cyphar/filepath-securejoin/vendor.conf
generated
vendored
1
vendor/github.com/cyphar/filepath-securejoin/vendor.conf
generated
vendored
@ -1 +0,0 @@
|
|||||||
github.com/pkg/errors v0.8.0
|
|
29
vendor/github.com/docker/distribution/reference/normalize.go
generated
vendored
29
vendor/github.com/docker/distribution/reference/normalize.go
generated
vendored
@ -56,6 +56,35 @@ func ParseNormalizedNamed(s string) (Named, error) {
|
|||||||
return named, nil
|
return named, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ParseDockerRef normalizes the image reference following the docker convention. This is added
|
||||||
|
// mainly for backward compatibility.
|
||||||
|
// The reference returned can only be either tagged or digested. For reference contains both tag
|
||||||
|
// and digest, the function returns digested reference, e.g. docker.io/library/busybox:latest@
|
||||||
|
// sha256:7cc4b5aefd1d0cadf8d97d4350462ba51c694ebca145b08d7d41b41acc8db5aa will be returned as
|
||||||
|
// docker.io/library/busybox@sha256:7cc4b5aefd1d0cadf8d97d4350462ba51c694ebca145b08d7d41b41acc8db5aa.
|
||||||
|
func ParseDockerRef(ref string) (Named, error) {
|
||||||
|
named, err := ParseNormalizedNamed(ref)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if _, ok := named.(NamedTagged); ok {
|
||||||
|
if canonical, ok := named.(Canonical); ok {
|
||||||
|
// The reference is both tagged and digested, only
|
||||||
|
// return digested.
|
||||||
|
newNamed, err := WithName(canonical.Name())
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
newCanonical, err := WithDigest(newNamed, canonical.Digest())
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return newCanonical, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return TagNameOnly(named), nil
|
||||||
|
}
|
||||||
|
|
||||||
// splitDockerDomain splits a repository name to domain and remotename string.
|
// splitDockerDomain splits a repository name to domain and remotename string.
|
||||||
// If no valid domain is found, the default domain is used. Repository name
|
// If no valid domain is found, the default domain is used. Repository name
|
||||||
// needs to be already validated before.
|
// needs to be already validated before.
|
||||||
|
2
vendor/github.com/docker/distribution/reference/reference.go
generated
vendored
2
vendor/github.com/docker/distribution/reference/reference.go
generated
vendored
@ -205,7 +205,7 @@ func Parse(s string) (Reference, error) {
|
|||||||
var repo repository
|
var repo repository
|
||||||
|
|
||||||
nameMatch := anchoredNameRegexp.FindStringSubmatch(matches[1])
|
nameMatch := anchoredNameRegexp.FindStringSubmatch(matches[1])
|
||||||
if nameMatch != nil && len(nameMatch) == 3 {
|
if len(nameMatch) == 3 {
|
||||||
repo.domain = nameMatch[1]
|
repo.domain = nameMatch[1]
|
||||||
repo.path = nameMatch[2]
|
repo.path = nameMatch[2]
|
||||||
} else {
|
} else {
|
||||||
|
@ -14,14 +14,12 @@ D-Bus message bus system.
|
|||||||
|
|
||||||
### Installation
|
### Installation
|
||||||
|
|
||||||
This packages requires Go 1.7. If you installed it and set up your GOPATH, just run:
|
This packages requires Go 1.12 or later. It can be installed by running the command below:
|
||||||
|
|
||||||
```
|
```
|
||||||
go get github.com/godbus/dbus
|
go get github.com/godbus/dbus/v5
|
||||||
```
|
```
|
||||||
|
|
||||||
If you want to use the subpackages, you can install them the same way.
|
|
||||||
|
|
||||||
### Usage
|
### Usage
|
||||||
|
|
||||||
The complete package documentation and some simple examples are available at
|
The complete package documentation and some simple examples are available at
|
||||||
@ -30,10 +28,12 @@ The complete package documentation and some simple examples are available at
|
|||||||
gives a short overview over the basic usage.
|
gives a short overview over the basic usage.
|
||||||
|
|
||||||
#### Projects using godbus
|
#### Projects using godbus
|
||||||
- [notify](https://github.com/esiqveland/notify) provides desktop notifications over dbus into a library.
|
- [fyne](https://github.com/fyne-io/fyne) a cross platform GUI in Go inspired by Material Design.
|
||||||
|
- [fynedesk](https://github.com/fyne-io/fynedesk) a full desktop environment for Linux/Unix using Fyne.
|
||||||
- [go-bluetooth](https://github.com/muka/go-bluetooth) provides a bluetooth client over bluez dbus API.
|
- [go-bluetooth](https://github.com/muka/go-bluetooth) provides a bluetooth client over bluez dbus API.
|
||||||
- [playerbm](https://github.com/altdesktop/playerbm) a bookmark utility for media players.
|
|
||||||
- [iwd](https://github.com/shibumi/iwd) go bindings for the internet wireless daemon "iwd".
|
- [iwd](https://github.com/shibumi/iwd) go bindings for the internet wireless daemon "iwd".
|
||||||
|
- [notify](https://github.com/esiqveland/notify) provides desktop notifications over dbus into a library.
|
||||||
|
- [playerbm](https://github.com/altdesktop/playerbm) a bookmark utility for media players.
|
||||||
|
|
||||||
Please note that the API is considered unstable for now and may change without
|
Please note that the API is considered unstable for now and may change without
|
||||||
further notice.
|
further notice.
|
15
vendor/github.com/godbus/dbus/v5/auth.go
generated
vendored
15
vendor/github.com/godbus/dbus/v5/auth.go
generated
vendored
@ -53,7 +53,7 @@ type Auth interface {
|
|||||||
// bus. Auth must not be called on shared connections.
|
// bus. Auth must not be called on shared connections.
|
||||||
func (conn *Conn) Auth(methods []Auth) error {
|
func (conn *Conn) Auth(methods []Auth) error {
|
||||||
if methods == nil {
|
if methods == nil {
|
||||||
uid := strconv.Itoa(os.Getuid())
|
uid := strconv.Itoa(os.Geteuid())
|
||||||
methods = []Auth{AuthExternal(uid), AuthCookieSha1(uid, getHomeDir())}
|
methods = []Auth{AuthExternal(uid), AuthCookieSha1(uid, getHomeDir())}
|
||||||
}
|
}
|
||||||
in := bufio.NewReader(conn.transport)
|
in := bufio.NewReader(conn.transport)
|
||||||
@ -75,9 +75,9 @@ func (conn *Conn) Auth(methods []Auth) error {
|
|||||||
s = s[1:]
|
s = s[1:]
|
||||||
for _, v := range s {
|
for _, v := range s {
|
||||||
for _, m := range methods {
|
for _, m := range methods {
|
||||||
if name, data, status := m.FirstData(); bytes.Equal(v, name) {
|
if name, _, status := m.FirstData(); bytes.Equal(v, name) {
|
||||||
var ok bool
|
var ok bool
|
||||||
err = authWriteLine(conn.transport, []byte("AUTH"), v, data)
|
err = authWriteLine(conn.transport, []byte("AUTH"), v)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -194,11 +194,14 @@ func (conn *Conn) tryAuth(m Auth, state authState, in *bufio.Reader) (error, boo
|
|||||||
}
|
}
|
||||||
conn.uuid = string(s[1])
|
conn.uuid = string(s[1])
|
||||||
return nil, true
|
return nil, true
|
||||||
|
case state == waitingForOk && string(s[0]) == "DATA":
|
||||||
|
err = authWriteLine(conn.transport, []byte("DATA"))
|
||||||
|
if err != nil {
|
||||||
|
return err, false
|
||||||
|
}
|
||||||
case state == waitingForOk && string(s[0]) == "REJECTED":
|
case state == waitingForOk && string(s[0]) == "REJECTED":
|
||||||
return nil, false
|
return nil, false
|
||||||
case state == waitingForOk && (string(s[0]) == "DATA" ||
|
case state == waitingForOk && string(s[0]) == "ERROR":
|
||||||
string(s[0]) == "ERROR"):
|
|
||||||
|
|
||||||
err = authWriteLine(conn.transport, []byte("CANCEL"))
|
err = authWriteLine(conn.transport, []byte("CANCEL"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err, false
|
return err, false
|
||||||
|
36
vendor/github.com/godbus/dbus/v5/conn.go
generated
vendored
36
vendor/github.com/godbus/dbus/v5/conn.go
generated
vendored
@ -73,7 +73,7 @@ func SessionBus() (conn *Conn, err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func getSessionBusAddress() (string, error) {
|
func getSessionBusAddress(autolaunch bool) (string, error) {
|
||||||
if address := os.Getenv("DBUS_SESSION_BUS_ADDRESS"); address != "" && address != "autolaunch:" {
|
if address := os.Getenv("DBUS_SESSION_BUS_ADDRESS"); address != "" && address != "autolaunch:" {
|
||||||
return address, nil
|
return address, nil
|
||||||
|
|
||||||
@ -81,12 +81,26 @@ func getSessionBusAddress() (string, error) {
|
|||||||
os.Setenv("DBUS_SESSION_BUS_ADDRESS", address)
|
os.Setenv("DBUS_SESSION_BUS_ADDRESS", address)
|
||||||
return address, nil
|
return address, nil
|
||||||
}
|
}
|
||||||
|
if !autolaunch {
|
||||||
|
return "", errors.New("dbus: couldn't determine address of session bus")
|
||||||
|
}
|
||||||
return getSessionBusPlatformAddress()
|
return getSessionBusPlatformAddress()
|
||||||
}
|
}
|
||||||
|
|
||||||
// SessionBusPrivate returns a new private connection to the session bus.
|
// SessionBusPrivate returns a new private connection to the session bus.
|
||||||
func SessionBusPrivate(opts ...ConnOption) (*Conn, error) {
|
func SessionBusPrivate(opts ...ConnOption) (*Conn, error) {
|
||||||
address, err := getSessionBusAddress()
|
address, err := getSessionBusAddress(true)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return Dial(address, opts...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SessionBusPrivate returns a new private connection to the session bus. If
|
||||||
|
// the session bus is not already open, do not attempt to launch it.
|
||||||
|
func SessionBusPrivateNoAutoStartup(opts ...ConnOption) (*Conn, error) {
|
||||||
|
address, err := getSessionBusAddress(false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -121,7 +135,7 @@ func SystemBus() (conn *Conn, err error) {
|
|||||||
|
|
||||||
// ConnectSessionBus connects to the session bus.
|
// ConnectSessionBus connects to the session bus.
|
||||||
func ConnectSessionBus(opts ...ConnOption) (*Conn, error) {
|
func ConnectSessionBus(opts ...ConnOption) (*Conn, error) {
|
||||||
address, err := getSessionBusAddress()
|
address, err := getSessionBusAddress(true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -180,7 +194,7 @@ func Dial(address string, opts ...ConnOption) (*Conn, error) {
|
|||||||
//
|
//
|
||||||
// Deprecated: use Dial with options instead.
|
// Deprecated: use Dial with options instead.
|
||||||
func DialHandler(address string, handler Handler, signalHandler SignalHandler) (*Conn, error) {
|
func DialHandler(address string, handler Handler, signalHandler SignalHandler) (*Conn, error) {
|
||||||
return Dial(address, WithSignalHandler(signalHandler))
|
return Dial(address, WithHandler(handler), WithSignalHandler(signalHandler))
|
||||||
}
|
}
|
||||||
|
|
||||||
// ConnOption is a connection option.
|
// ConnOption is a connection option.
|
||||||
@ -478,14 +492,24 @@ func (conn *Conn) sendMessageAndIfClosed(msg *Message, ifClosed func()) {
|
|||||||
conn.outInt(msg)
|
conn.outInt(msg)
|
||||||
}
|
}
|
||||||
err := conn.outHandler.sendAndIfClosed(msg, ifClosed)
|
err := conn.outHandler.sendAndIfClosed(msg, ifClosed)
|
||||||
conn.calls.handleSendError(msg, err)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
conn.serialGen.RetireSerial(msg.serial)
|
conn.handleSendError(msg, err)
|
||||||
} else if msg.Type != TypeMethodCall {
|
} else if msg.Type != TypeMethodCall {
|
||||||
conn.serialGen.RetireSerial(msg.serial)
|
conn.serialGen.RetireSerial(msg.serial)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (conn *Conn) handleSendError(msg *Message, err error) {
|
||||||
|
if msg.Type == TypeMethodCall {
|
||||||
|
conn.calls.handleSendError(msg, err)
|
||||||
|
} else if msg.Type == TypeMethodReply {
|
||||||
|
if _, ok := err.(FormatError); ok {
|
||||||
|
conn.sendError(err, msg.Headers[FieldDestination].value.(string), msg.Headers[FieldReplySerial].value.(uint32))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
conn.serialGen.RetireSerial(msg.serial)
|
||||||
|
}
|
||||||
|
|
||||||
// Send sends the given message to the message bus. You usually don't need to
|
// Send sends the given message to the message bus. You usually don't need to
|
||||||
// use this; use the higher-level equivalents (Call / Go, Emit and Export)
|
// use this; use the higher-level equivalents (Call / Go, Emit and Export)
|
||||||
// instead. If msg is a method call and NoReplyExpected is not set, a non-nil
|
// instead. If msg is a method call and NoReplyExpected is not set, a non-nil
|
||||||
|
16
vendor/github.com/godbus/dbus/v5/decoder.go
generated
vendored
16
vendor/github.com/godbus/dbus/v5/decoder.go
generated
vendored
@ -10,14 +10,16 @@ type decoder struct {
|
|||||||
in io.Reader
|
in io.Reader
|
||||||
order binary.ByteOrder
|
order binary.ByteOrder
|
||||||
pos int
|
pos int
|
||||||
|
fds []int
|
||||||
}
|
}
|
||||||
|
|
||||||
// newDecoder returns a new decoder that reads values from in. The input is
|
// newDecoder returns a new decoder that reads values from in. The input is
|
||||||
// expected to be in the given byte order.
|
// expected to be in the given byte order.
|
||||||
func newDecoder(in io.Reader, order binary.ByteOrder) *decoder {
|
func newDecoder(in io.Reader, order binary.ByteOrder, fds []int) *decoder {
|
||||||
dec := new(decoder)
|
dec := new(decoder)
|
||||||
dec.in = in
|
dec.in = in
|
||||||
dec.order = order
|
dec.order = order
|
||||||
|
dec.fds = fds
|
||||||
return dec
|
return dec
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -53,7 +55,7 @@ func (dec *decoder) Decode(sig Signature) (vs []interface{}, err error) {
|
|||||||
vs = make([]interface{}, 0)
|
vs = make([]interface{}, 0)
|
||||||
s := sig.str
|
s := sig.str
|
||||||
for s != "" {
|
for s != "" {
|
||||||
err, rem := validSingle(s, 0)
|
err, rem := validSingle(s, &depthCounter{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -150,7 +152,7 @@ func (dec *decoder) decode(s string, depth int) interface{} {
|
|||||||
if len(sig.str) == 0 {
|
if len(sig.str) == 0 {
|
||||||
panic(FormatError("variant signature is empty"))
|
panic(FormatError("variant signature is empty"))
|
||||||
}
|
}
|
||||||
err, rem := validSingle(sig.str, 0)
|
err, rem := validSingle(sig.str, &depthCounter{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
@ -161,7 +163,11 @@ func (dec *decoder) decode(s string, depth int) interface{} {
|
|||||||
variant.value = dec.decode(sig.str, depth+1)
|
variant.value = dec.decode(sig.str, depth+1)
|
||||||
return variant
|
return variant
|
||||||
case 'h':
|
case 'h':
|
||||||
return UnixFDIndex(dec.decode("u", depth).(uint32))
|
idx := dec.decode("u", depth).(uint32)
|
||||||
|
if int(idx) < len(dec.fds) {
|
||||||
|
return UnixFD(dec.fds[idx])
|
||||||
|
}
|
||||||
|
return UnixFDIndex(idx)
|
||||||
case 'a':
|
case 'a':
|
||||||
if len(s) > 1 && s[1] == '{' {
|
if len(s) > 1 && s[1] == '{' {
|
||||||
ksig := s[2:3]
|
ksig := s[2:3]
|
||||||
@ -219,7 +225,7 @@ func (dec *decoder) decode(s string, depth int) interface{} {
|
|||||||
v := make([]interface{}, 0)
|
v := make([]interface{}, 0)
|
||||||
s = s[1 : len(s)-1]
|
s = s[1 : len(s)-1]
|
||||||
for s != "" {
|
for s != "" {
|
||||||
err, rem := validSingle(s, 0)
|
err, rem := validSingle(s, &depthCounter{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
61
vendor/github.com/godbus/dbus/v5/encoder.go
generated
vendored
61
vendor/github.com/godbus/dbus/v5/encoder.go
generated
vendored
@ -5,28 +5,33 @@ import (
|
|||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"io"
|
"io"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
"strings"
|
||||||
|
"unicode/utf8"
|
||||||
)
|
)
|
||||||
|
|
||||||
// An encoder encodes values to the D-Bus wire format.
|
// An encoder encodes values to the D-Bus wire format.
|
||||||
type encoder struct {
|
type encoder struct {
|
||||||
out io.Writer
|
out io.Writer
|
||||||
|
fds []int
|
||||||
order binary.ByteOrder
|
order binary.ByteOrder
|
||||||
pos int
|
pos int
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewEncoder returns a new encoder that writes to out in the given byte order.
|
// NewEncoder returns a new encoder that writes to out in the given byte order.
|
||||||
func newEncoder(out io.Writer, order binary.ByteOrder) *encoder {
|
func newEncoder(out io.Writer, order binary.ByteOrder, fds []int) *encoder {
|
||||||
return newEncoderAtOffset(out, 0, order)
|
enc := newEncoderAtOffset(out, 0, order, fds)
|
||||||
|
return enc
|
||||||
}
|
}
|
||||||
|
|
||||||
// newEncoderAtOffset returns a new encoder that writes to out in the given
|
// newEncoderAtOffset returns a new encoder that writes to out in the given
|
||||||
// byte order. Specify the offset to initialize pos for proper alignment
|
// byte order. Specify the offset to initialize pos for proper alignment
|
||||||
// computation.
|
// computation.
|
||||||
func newEncoderAtOffset(out io.Writer, offset int, order binary.ByteOrder) *encoder {
|
func newEncoderAtOffset(out io.Writer, offset int, order binary.ByteOrder, fds []int) *encoder {
|
||||||
enc := new(encoder)
|
enc := new(encoder)
|
||||||
enc.out = out
|
enc.out = out
|
||||||
enc.order = order
|
enc.order = order
|
||||||
enc.pos = offset
|
enc.pos = offset
|
||||||
|
enc.fds = fds
|
||||||
return enc
|
return enc
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -75,6 +80,9 @@ func (enc *encoder) Encode(vs ...interface{}) (err error) {
|
|||||||
// encode encodes the given value to the writer and panics on error. depth holds
|
// encode encodes the given value to the writer and panics on error. depth holds
|
||||||
// the depth of the container nesting.
|
// the depth of the container nesting.
|
||||||
func (enc *encoder) encode(v reflect.Value, depth int) {
|
func (enc *encoder) encode(v reflect.Value, depth int) {
|
||||||
|
if depth > 64 {
|
||||||
|
panic(FormatError("input exceeds depth limitation"))
|
||||||
|
}
|
||||||
enc.align(alignment(v.Type()))
|
enc.align(alignment(v.Type()))
|
||||||
switch v.Kind() {
|
switch v.Kind() {
|
||||||
case reflect.Uint8:
|
case reflect.Uint8:
|
||||||
@ -97,7 +105,14 @@ func (enc *encoder) encode(v reflect.Value, depth int) {
|
|||||||
enc.binwrite(uint16(v.Uint()))
|
enc.binwrite(uint16(v.Uint()))
|
||||||
enc.pos += 2
|
enc.pos += 2
|
||||||
case reflect.Int, reflect.Int32:
|
case reflect.Int, reflect.Int32:
|
||||||
enc.binwrite(int32(v.Int()))
|
if v.Type() == unixFDType {
|
||||||
|
fd := v.Int()
|
||||||
|
idx := len(enc.fds)
|
||||||
|
enc.fds = append(enc.fds, int(fd))
|
||||||
|
enc.binwrite(uint32(idx))
|
||||||
|
} else {
|
||||||
|
enc.binwrite(int32(v.Int()))
|
||||||
|
}
|
||||||
enc.pos += 4
|
enc.pos += 4
|
||||||
case reflect.Uint, reflect.Uint32:
|
case reflect.Uint, reflect.Uint32:
|
||||||
enc.binwrite(uint32(v.Uint()))
|
enc.binwrite(uint32(v.Uint()))
|
||||||
@ -112,9 +127,21 @@ func (enc *encoder) encode(v reflect.Value, depth int) {
|
|||||||
enc.binwrite(v.Float())
|
enc.binwrite(v.Float())
|
||||||
enc.pos += 8
|
enc.pos += 8
|
||||||
case reflect.String:
|
case reflect.String:
|
||||||
enc.encode(reflect.ValueOf(uint32(len(v.String()))), depth)
|
str := v.String()
|
||||||
|
if !utf8.ValidString(str) {
|
||||||
|
panic(FormatError("input has a not-utf8 char in string"))
|
||||||
|
}
|
||||||
|
if strings.IndexByte(str, byte(0)) != -1 {
|
||||||
|
panic(FormatError("input has a null char('\\000') in string"))
|
||||||
|
}
|
||||||
|
if v.Type() == objectPathType {
|
||||||
|
if !ObjectPath(str).IsValid() {
|
||||||
|
panic(FormatError("invalid object path"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
enc.encode(reflect.ValueOf(uint32(len(str))), depth)
|
||||||
b := make([]byte, v.Len()+1)
|
b := make([]byte, v.Len()+1)
|
||||||
copy(b, v.String())
|
copy(b, str)
|
||||||
b[len(b)-1] = 0
|
b[len(b)-1] = 0
|
||||||
n, err := enc.out.Write(b)
|
n, err := enc.out.Write(b)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -124,20 +151,23 @@ func (enc *encoder) encode(v reflect.Value, depth int) {
|
|||||||
case reflect.Ptr:
|
case reflect.Ptr:
|
||||||
enc.encode(v.Elem(), depth)
|
enc.encode(v.Elem(), depth)
|
||||||
case reflect.Slice, reflect.Array:
|
case reflect.Slice, reflect.Array:
|
||||||
if depth >= 64 {
|
|
||||||
panic(FormatError("input exceeds container depth limit"))
|
|
||||||
}
|
|
||||||
// Lookahead offset: 4 bytes for uint32 length (with alignment),
|
// Lookahead offset: 4 bytes for uint32 length (with alignment),
|
||||||
// plus alignment for elements.
|
// plus alignment for elements.
|
||||||
n := enc.padding(0, 4) + 4
|
n := enc.padding(0, 4) + 4
|
||||||
offset := enc.pos + n + enc.padding(n, alignment(v.Type().Elem()))
|
offset := enc.pos + n + enc.padding(n, alignment(v.Type().Elem()))
|
||||||
|
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
bufenc := newEncoderAtOffset(&buf, offset, enc.order)
|
bufenc := newEncoderAtOffset(&buf, offset, enc.order, enc.fds)
|
||||||
|
|
||||||
for i := 0; i < v.Len(); i++ {
|
for i := 0; i < v.Len(); i++ {
|
||||||
bufenc.encode(v.Index(i), depth+1)
|
bufenc.encode(v.Index(i), depth+1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if buf.Len() > 1<<26 {
|
||||||
|
panic(FormatError("input exceeds array size limitation"))
|
||||||
|
}
|
||||||
|
|
||||||
|
enc.fds = bufenc.fds
|
||||||
enc.encode(reflect.ValueOf(uint32(buf.Len())), depth)
|
enc.encode(reflect.ValueOf(uint32(buf.Len())), depth)
|
||||||
length := buf.Len()
|
length := buf.Len()
|
||||||
enc.align(alignment(v.Type().Elem()))
|
enc.align(alignment(v.Type().Elem()))
|
||||||
@ -146,13 +176,10 @@ func (enc *encoder) encode(v reflect.Value, depth int) {
|
|||||||
}
|
}
|
||||||
enc.pos += length
|
enc.pos += length
|
||||||
case reflect.Struct:
|
case reflect.Struct:
|
||||||
if depth >= 64 && v.Type() != signatureType {
|
|
||||||
panic(FormatError("input exceeds container depth limit"))
|
|
||||||
}
|
|
||||||
switch t := v.Type(); t {
|
switch t := v.Type(); t {
|
||||||
case signatureType:
|
case signatureType:
|
||||||
str := v.Field(0)
|
str := v.Field(0)
|
||||||
enc.encode(reflect.ValueOf(byte(str.Len())), depth+1)
|
enc.encode(reflect.ValueOf(byte(str.Len())), depth)
|
||||||
b := make([]byte, str.Len()+1)
|
b := make([]byte, str.Len()+1)
|
||||||
copy(b, str.String())
|
copy(b, str.String())
|
||||||
b[len(b)-1] = 0
|
b[len(b)-1] = 0
|
||||||
@ -176,9 +203,6 @@ func (enc *encoder) encode(v reflect.Value, depth int) {
|
|||||||
case reflect.Map:
|
case reflect.Map:
|
||||||
// Maps are arrays of structures, so they actually increase the depth by
|
// Maps are arrays of structures, so they actually increase the depth by
|
||||||
// 2.
|
// 2.
|
||||||
if depth >= 63 {
|
|
||||||
panic(FormatError("input exceeds container depth limit"))
|
|
||||||
}
|
|
||||||
if !isKeyType(v.Type().Key()) {
|
if !isKeyType(v.Type().Key()) {
|
||||||
panic(InvalidTypeError{v.Type()})
|
panic(InvalidTypeError{v.Type()})
|
||||||
}
|
}
|
||||||
@ -189,12 +213,13 @@ func (enc *encoder) encode(v reflect.Value, depth int) {
|
|||||||
offset := enc.pos + n + enc.padding(n, 8)
|
offset := enc.pos + n + enc.padding(n, 8)
|
||||||
|
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
bufenc := newEncoderAtOffset(&buf, offset, enc.order)
|
bufenc := newEncoderAtOffset(&buf, offset, enc.order, enc.fds)
|
||||||
for _, k := range keys {
|
for _, k := range keys {
|
||||||
bufenc.align(8)
|
bufenc.align(8)
|
||||||
bufenc.encode(k, depth+2)
|
bufenc.encode(k, depth+2)
|
||||||
bufenc.encode(v.MapIndex(k), depth+2)
|
bufenc.encode(v.MapIndex(k), depth+2)
|
||||||
}
|
}
|
||||||
|
enc.fds = bufenc.fds
|
||||||
enc.encode(reflect.ValueOf(uint32(buf.Len())), depth)
|
enc.encode(reflect.ValueOf(uint32(buf.Len())), depth)
|
||||||
length := buf.Len()
|
length := buf.Len()
|
||||||
enc.align(8)
|
enc.align(8)
|
||||||
|
37
vendor/github.com/godbus/dbus/v5/export.go
generated
vendored
37
vendor/github.com/godbus/dbus/v5/export.go
generated
vendored
@ -26,6 +26,27 @@ var (
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func MakeNoObjectError(path ObjectPath) Error {
|
||||||
|
return Error{
|
||||||
|
"org.freedesktop.DBus.Error.NoSuchObject",
|
||||||
|
[]interface{}{fmt.Sprintf("No such object '%s'", string(path))},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func MakeUnknownMethodError(methodName string) Error {
|
||||||
|
return Error{
|
||||||
|
"org.freedesktop.DBus.Error.UnknownMethod",
|
||||||
|
[]interface{}{fmt.Sprintf("Unknown / invalid method '%s'", methodName)},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func MakeUnknownInterfaceError(ifaceName string) Error {
|
||||||
|
return Error{
|
||||||
|
"org.freedesktop.DBus.Error.UnknownInterface",
|
||||||
|
[]interface{}{fmt.Sprintf("Object does not implement the interface '%s'", ifaceName)},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func MakeFailedError(err error) *Error {
|
func MakeFailedError(err error) *Error {
|
||||||
return &Error{
|
return &Error{
|
||||||
"org.freedesktop.DBus.Error.Failed",
|
"org.freedesktop.DBus.Error.Failed",
|
||||||
@ -128,6 +149,11 @@ func (conn *Conn) handleCall(msg *Message) {
|
|||||||
ifaceName, _ := msg.Headers[FieldInterface].value.(string)
|
ifaceName, _ := msg.Headers[FieldInterface].value.(string)
|
||||||
sender, hasSender := msg.Headers[FieldSender].value.(string)
|
sender, hasSender := msg.Headers[FieldSender].value.(string)
|
||||||
serial := msg.serial
|
serial := msg.serial
|
||||||
|
|
||||||
|
if len(name) == 0 {
|
||||||
|
conn.sendError(ErrMsgUnknownMethod, sender, serial)
|
||||||
|
}
|
||||||
|
|
||||||
if ifaceName == "org.freedesktop.DBus.Peer" {
|
if ifaceName == "org.freedesktop.DBus.Peer" {
|
||||||
switch name {
|
switch name {
|
||||||
case "Ping":
|
case "Ping":
|
||||||
@ -135,29 +161,26 @@ func (conn *Conn) handleCall(msg *Message) {
|
|||||||
case "GetMachineId":
|
case "GetMachineId":
|
||||||
conn.sendReply(sender, serial, conn.uuid)
|
conn.sendReply(sender, serial, conn.uuid)
|
||||||
default:
|
default:
|
||||||
conn.sendError(ErrMsgUnknownMethod, sender, serial)
|
conn.sendError(MakeUnknownMethodError(name), sender, serial)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if len(name) == 0 {
|
|
||||||
conn.sendError(ErrMsgUnknownMethod, sender, serial)
|
|
||||||
}
|
|
||||||
|
|
||||||
object, ok := conn.handler.LookupObject(path)
|
object, ok := conn.handler.LookupObject(path)
|
||||||
if !ok {
|
if !ok {
|
||||||
conn.sendError(ErrMsgNoObject, sender, serial)
|
conn.sendError(MakeNoObjectError(path), sender, serial)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
iface, exists := object.LookupInterface(ifaceName)
|
iface, exists := object.LookupInterface(ifaceName)
|
||||||
if !exists {
|
if !exists {
|
||||||
conn.sendError(ErrMsgUnknownInterface, sender, serial)
|
conn.sendError(MakeUnknownInterfaceError(ifaceName), sender, serial)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
m, exists := iface.LookupMethod(name)
|
m, exists := iface.LookupMethod(name)
|
||||||
if !exists {
|
if !exists {
|
||||||
conn.sendError(ErrMsgUnknownMethod, sender, serial)
|
conn.sendError(MakeUnknownMethodError(name), sender, serial)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
args, err := conn.decodeArguments(m, sender, msg)
|
args, err := conn.decodeArguments(m, sender, msg)
|
||||||
|
73
vendor/github.com/godbus/dbus/v5/message.go
generated
vendored
73
vendor/github.com/godbus/dbus/v5/message.go
generated
vendored
@ -118,11 +118,7 @@ type header struct {
|
|||||||
Variant
|
Variant
|
||||||
}
|
}
|
||||||
|
|
||||||
// DecodeMessage tries to decode a single message in the D-Bus wire format
|
func DecodeMessageWithFDs(rd io.Reader, fds []int) (msg *Message, err error) {
|
||||||
// from the given reader. The byte order is figured out from the first byte.
|
|
||||||
// The possibly returned error can be an error of the underlying reader, an
|
|
||||||
// InvalidMessageError or a FormatError.
|
|
||||||
func DecodeMessage(rd io.Reader) (msg *Message, err error) {
|
|
||||||
var order binary.ByteOrder
|
var order binary.ByteOrder
|
||||||
var hlength, length uint32
|
var hlength, length uint32
|
||||||
var typ, flags, proto byte
|
var typ, flags, proto byte
|
||||||
@ -142,7 +138,7 @@ func DecodeMessage(rd io.Reader) (msg *Message, err error) {
|
|||||||
return nil, InvalidMessageError("invalid byte order")
|
return nil, InvalidMessageError("invalid byte order")
|
||||||
}
|
}
|
||||||
|
|
||||||
dec := newDecoder(rd, order)
|
dec := newDecoder(rd, order, fds)
|
||||||
dec.pos = 1
|
dec.pos = 1
|
||||||
|
|
||||||
msg = new(Message)
|
msg = new(Message)
|
||||||
@ -166,7 +162,7 @@ func DecodeMessage(rd io.Reader) (msg *Message, err error) {
|
|||||||
if hlength+length+16 > 1<<27 {
|
if hlength+length+16 > 1<<27 {
|
||||||
return nil, InvalidMessageError("message is too long")
|
return nil, InvalidMessageError("message is too long")
|
||||||
}
|
}
|
||||||
dec = newDecoder(io.MultiReader(bytes.NewBuffer(b), rd), order)
|
dec = newDecoder(io.MultiReader(bytes.NewBuffer(b), rd), order, fds)
|
||||||
dec.pos = 12
|
dec.pos = 12
|
||||||
vs, err = dec.Decode(Signature{"a(yv)"})
|
vs, err = dec.Decode(Signature{"a(yv)"})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -196,7 +192,7 @@ func DecodeMessage(rd io.Reader) (msg *Message, err error) {
|
|||||||
sig, _ := msg.Headers[FieldSignature].value.(Signature)
|
sig, _ := msg.Headers[FieldSignature].value.(Signature)
|
||||||
if sig.str != "" {
|
if sig.str != "" {
|
||||||
buf := bytes.NewBuffer(body)
|
buf := bytes.NewBuffer(body)
|
||||||
dec = newDecoder(buf, order)
|
dec = newDecoder(buf, order, fds)
|
||||||
vs, err := dec.Decode(sig)
|
vs, err := dec.Decode(sig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -207,12 +203,32 @@ func DecodeMessage(rd io.Reader) (msg *Message, err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// EncodeTo encodes and sends a message to the given writer. The byte order must
|
// DecodeMessage tries to decode a single message in the D-Bus wire format
|
||||||
// be either binary.LittleEndian or binary.BigEndian. If the message is not
|
// from the given reader. The byte order is figured out from the first byte.
|
||||||
// valid or an error occurs when writing, an error is returned.
|
// The possibly returned error can be an error of the underlying reader, an
|
||||||
func (msg *Message) EncodeTo(out io.Writer, order binary.ByteOrder) error {
|
// InvalidMessageError or a FormatError.
|
||||||
|
func DecodeMessage(rd io.Reader) (msg *Message, err error) {
|
||||||
|
return DecodeMessageWithFDs(rd, make([]int, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
type nullwriter struct{}
|
||||||
|
|
||||||
|
func (nullwriter) Write(p []byte) (cnt int, err error) {
|
||||||
|
return len(p), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (msg *Message) CountFds() (int, error) {
|
||||||
|
if len(msg.Body) == 0 {
|
||||||
|
return 0, nil
|
||||||
|
}
|
||||||
|
enc := newEncoder(nullwriter{}, nativeEndian, make([]int, 0))
|
||||||
|
err := enc.Encode(msg.Body...)
|
||||||
|
return len(enc.fds), err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (msg *Message) EncodeToWithFDs(out io.Writer, order binary.ByteOrder) (fds []int, err error) {
|
||||||
if err := msg.IsValid(); err != nil {
|
if err := msg.IsValid(); err != nil {
|
||||||
return err
|
return make([]int, 0), err
|
||||||
}
|
}
|
||||||
var vs [7]interface{}
|
var vs [7]interface{}
|
||||||
switch order {
|
switch order {
|
||||||
@ -221,12 +237,16 @@ func (msg *Message) EncodeTo(out io.Writer, order binary.ByteOrder) error {
|
|||||||
case binary.BigEndian:
|
case binary.BigEndian:
|
||||||
vs[0] = byte('B')
|
vs[0] = byte('B')
|
||||||
default:
|
default:
|
||||||
return errors.New("dbus: invalid byte order")
|
return make([]int, 0), errors.New("dbus: invalid byte order")
|
||||||
}
|
}
|
||||||
body := new(bytes.Buffer)
|
body := new(bytes.Buffer)
|
||||||
enc := newEncoder(body, order)
|
fds = make([]int, 0)
|
||||||
|
enc := newEncoder(body, order, fds)
|
||||||
if len(msg.Body) != 0 {
|
if len(msg.Body) != 0 {
|
||||||
enc.Encode(msg.Body...)
|
err = enc.Encode(msg.Body...)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
vs[1] = msg.Type
|
vs[1] = msg.Type
|
||||||
vs[2] = msg.Flags
|
vs[2] = msg.Flags
|
||||||
@ -239,17 +259,28 @@ func (msg *Message) EncodeTo(out io.Writer, order binary.ByteOrder) error {
|
|||||||
}
|
}
|
||||||
vs[6] = headers
|
vs[6] = headers
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
enc = newEncoder(&buf, order)
|
enc = newEncoder(&buf, order, enc.fds)
|
||||||
enc.Encode(vs[:]...)
|
err = enc.Encode(vs[:]...)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
enc.align(8)
|
enc.align(8)
|
||||||
body.WriteTo(&buf)
|
body.WriteTo(&buf)
|
||||||
if buf.Len() > 1<<27 {
|
if buf.Len() > 1<<27 {
|
||||||
return InvalidMessageError("message is too long")
|
return make([]int, 0), InvalidMessageError("message is too long")
|
||||||
}
|
}
|
||||||
if _, err := buf.WriteTo(out); err != nil {
|
if _, err := buf.WriteTo(out); err != nil {
|
||||||
return err
|
return make([]int, 0), err
|
||||||
}
|
}
|
||||||
return nil
|
return enc.fds, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// EncodeTo encodes and sends a message to the given writer. The byte order must
|
||||||
|
// be either binary.LittleEndian or binary.BigEndian. If the message is not
|
||||||
|
// valid or an error occurs when writing, an error is returned.
|
||||||
|
func (msg *Message) EncodeTo(out io.Writer, order binary.ByteOrder) (err error) {
|
||||||
|
_, err = msg.EncodeToWithFDs(out, order)
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsValid checks whether msg is a valid message and returns an
|
// IsValid checks whether msg is a valid message and returns an
|
||||||
|
66
vendor/github.com/godbus/dbus/v5/sig.go
generated
vendored
66
vendor/github.com/godbus/dbus/v5/sig.go
generated
vendored
@ -34,7 +34,7 @@ type Signature struct {
|
|||||||
func SignatureOf(vs ...interface{}) Signature {
|
func SignatureOf(vs ...interface{}) Signature {
|
||||||
var s string
|
var s string
|
||||||
for _, v := range vs {
|
for _, v := range vs {
|
||||||
s += getSignature(reflect.TypeOf(v))
|
s += getSignature(reflect.TypeOf(v), &depthCounter{})
|
||||||
}
|
}
|
||||||
return Signature{s}
|
return Signature{s}
|
||||||
}
|
}
|
||||||
@ -42,11 +42,19 @@ func SignatureOf(vs ...interface{}) Signature {
|
|||||||
// SignatureOfType returns the signature of the given type. It panics if the
|
// SignatureOfType returns the signature of the given type. It panics if the
|
||||||
// type is not representable in D-Bus.
|
// type is not representable in D-Bus.
|
||||||
func SignatureOfType(t reflect.Type) Signature {
|
func SignatureOfType(t reflect.Type) Signature {
|
||||||
return Signature{getSignature(t)}
|
return Signature{getSignature(t, &depthCounter{})}
|
||||||
}
|
}
|
||||||
|
|
||||||
// getSignature returns the signature of the given type and panics on unknown types.
|
// getSignature returns the signature of the given type and panics on unknown types.
|
||||||
func getSignature(t reflect.Type) string {
|
func getSignature(t reflect.Type, depth *depthCounter) (sig string) {
|
||||||
|
if !depth.Valid() {
|
||||||
|
panic("container nesting too deep")
|
||||||
|
}
|
||||||
|
defer func() {
|
||||||
|
if len(sig) > 255 {
|
||||||
|
panic("signature exceeds the length limitation")
|
||||||
|
}
|
||||||
|
}()
|
||||||
// handle simple types first
|
// handle simple types first
|
||||||
switch t.Kind() {
|
switch t.Kind() {
|
||||||
case reflect.Uint8:
|
case reflect.Uint8:
|
||||||
@ -74,7 +82,7 @@ func getSignature(t reflect.Type) string {
|
|||||||
case reflect.Float64:
|
case reflect.Float64:
|
||||||
return "d"
|
return "d"
|
||||||
case reflect.Ptr:
|
case reflect.Ptr:
|
||||||
return getSignature(t.Elem())
|
return getSignature(t.Elem(), depth)
|
||||||
case reflect.String:
|
case reflect.String:
|
||||||
if t == objectPathType {
|
if t == objectPathType {
|
||||||
return "o"
|
return "o"
|
||||||
@ -90,17 +98,20 @@ func getSignature(t reflect.Type) string {
|
|||||||
for i := 0; i < t.NumField(); i++ {
|
for i := 0; i < t.NumField(); i++ {
|
||||||
field := t.Field(i)
|
field := t.Field(i)
|
||||||
if field.PkgPath == "" && field.Tag.Get("dbus") != "-" {
|
if field.PkgPath == "" && field.Tag.Get("dbus") != "-" {
|
||||||
s += getSignature(t.Field(i).Type)
|
s += getSignature(t.Field(i).Type, depth.EnterStruct())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if len(s) == 0 {
|
||||||
|
panic("empty struct")
|
||||||
|
}
|
||||||
return "(" + s + ")"
|
return "(" + s + ")"
|
||||||
case reflect.Array, reflect.Slice:
|
case reflect.Array, reflect.Slice:
|
||||||
return "a" + getSignature(t.Elem())
|
return "a" + getSignature(t.Elem(), depth.EnterArray())
|
||||||
case reflect.Map:
|
case reflect.Map:
|
||||||
if !isKeyType(t.Key()) {
|
if !isKeyType(t.Key()) {
|
||||||
panic(InvalidTypeError{t})
|
panic(InvalidTypeError{t})
|
||||||
}
|
}
|
||||||
return "a{" + getSignature(t.Key()) + getSignature(t.Elem()) + "}"
|
return "a{" + getSignature(t.Key(), depth.EnterArray().EnterDictEntry()) + getSignature(t.Elem(), depth.EnterArray().EnterDictEntry()) + "}"
|
||||||
case reflect.Interface:
|
case reflect.Interface:
|
||||||
return "v"
|
return "v"
|
||||||
}
|
}
|
||||||
@ -118,7 +129,7 @@ func ParseSignature(s string) (sig Signature, err error) {
|
|||||||
}
|
}
|
||||||
sig.str = s
|
sig.str = s
|
||||||
for err == nil && len(s) != 0 {
|
for err == nil && len(s) != 0 {
|
||||||
err, s = validSingle(s, 0)
|
err, s = validSingle(s, &depthCounter{})
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
sig = Signature{""}
|
sig = Signature{""}
|
||||||
@ -144,7 +155,7 @@ func (s Signature) Empty() bool {
|
|||||||
|
|
||||||
// Single returns whether the signature represents a single, complete type.
|
// Single returns whether the signature represents a single, complete type.
|
||||||
func (s Signature) Single() bool {
|
func (s Signature) Single() bool {
|
||||||
err, r := validSingle(s.str, 0)
|
err, r := validSingle(s.str, &depthCounter{})
|
||||||
return err != nil && r == ""
|
return err != nil && r == ""
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -164,15 +175,38 @@ func (e SignatureError) Error() string {
|
|||||||
return fmt.Sprintf("dbus: invalid signature: %q (%s)", e.Sig, e.Reason)
|
return fmt.Sprintf("dbus: invalid signature: %q (%s)", e.Sig, e.Reason)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type depthCounter struct {
|
||||||
|
arrayDepth, structDepth, dictEntryDepth int
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cnt *depthCounter) Valid() bool {
|
||||||
|
return cnt.arrayDepth <= 32 && cnt.structDepth <= 32 && cnt.dictEntryDepth <= 32
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cnt depthCounter) EnterArray() *depthCounter {
|
||||||
|
cnt.arrayDepth++
|
||||||
|
return &cnt
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cnt depthCounter) EnterStruct() *depthCounter {
|
||||||
|
cnt.structDepth++
|
||||||
|
return &cnt
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cnt depthCounter) EnterDictEntry() *depthCounter {
|
||||||
|
cnt.dictEntryDepth++
|
||||||
|
return &cnt
|
||||||
|
}
|
||||||
|
|
||||||
// Try to read a single type from this string. If it was successful, err is nil
|
// Try to read a single type from this string. If it was successful, err is nil
|
||||||
// and rem is the remaining unparsed part. Otherwise, err is a non-nil
|
// and rem is the remaining unparsed part. Otherwise, err is a non-nil
|
||||||
// SignatureError and rem is "". depth is the current recursion depth which may
|
// SignatureError and rem is "". depth is the current recursion depth which may
|
||||||
// not be greater than 64 and should be given as 0 on the first call.
|
// not be greater than 64 and should be given as 0 on the first call.
|
||||||
func validSingle(s string, depth int) (err error, rem string) {
|
func validSingle(s string, depth *depthCounter) (err error, rem string) {
|
||||||
if s == "" {
|
if s == "" {
|
||||||
return SignatureError{Sig: s, Reason: "empty signature"}, ""
|
return SignatureError{Sig: s, Reason: "empty signature"}, ""
|
||||||
}
|
}
|
||||||
if depth > 64 {
|
if !depth.Valid() {
|
||||||
return SignatureError{Sig: s, Reason: "container nesting too deep"}, ""
|
return SignatureError{Sig: s, Reason: "container nesting too deep"}, ""
|
||||||
}
|
}
|
||||||
switch s[0] {
|
switch s[0] {
|
||||||
@ -187,10 +221,10 @@ func validSingle(s string, depth int) (err error, rem string) {
|
|||||||
i++
|
i++
|
||||||
rem = s[i+1:]
|
rem = s[i+1:]
|
||||||
s = s[2:i]
|
s = s[2:i]
|
||||||
if err, _ = validSingle(s[:1], depth+1); err != nil {
|
if err, _ = validSingle(s[:1], depth.EnterArray().EnterDictEntry()); err != nil {
|
||||||
return err, ""
|
return err, ""
|
||||||
}
|
}
|
||||||
err, nr := validSingle(s[1:], depth+1)
|
err, nr := validSingle(s[1:], depth.EnterArray().EnterDictEntry())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err, ""
|
return err, ""
|
||||||
}
|
}
|
||||||
@ -199,7 +233,7 @@ func validSingle(s string, depth int) (err error, rem string) {
|
|||||||
}
|
}
|
||||||
return nil, rem
|
return nil, rem
|
||||||
}
|
}
|
||||||
return validSingle(s[1:], depth+1)
|
return validSingle(s[1:], depth.EnterArray())
|
||||||
case '(':
|
case '(':
|
||||||
i := findMatching(s, '(', ')')
|
i := findMatching(s, '(', ')')
|
||||||
if i == -1 {
|
if i == -1 {
|
||||||
@ -208,7 +242,7 @@ func validSingle(s string, depth int) (err error, rem string) {
|
|||||||
rem = s[i+1:]
|
rem = s[i+1:]
|
||||||
s = s[1:i]
|
s = s[1:i]
|
||||||
for err == nil && s != "" {
|
for err == nil && s != "" {
|
||||||
err, s = validSingle(s, depth+1)
|
err, s = validSingle(s, depth.EnterStruct())
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
rem = ""
|
rem = ""
|
||||||
@ -236,7 +270,7 @@ func findMatching(s string, left, right rune) int {
|
|||||||
// typeFor returns the type of the given signature. It ignores any left over
|
// typeFor returns the type of the given signature. It ignores any left over
|
||||||
// characters and panics if s doesn't start with a valid type signature.
|
// characters and panics if s doesn't start with a valid type signature.
|
||||||
func typeFor(s string) (t reflect.Type) {
|
func typeFor(s string) (t reflect.Type) {
|
||||||
err, _ := validSingle(s, 0)
|
err, _ := validSingle(s, &depthCounter{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user