mirror of
https://github.com/kata-containers/kata-containers.git
synced 2025-04-29 12:14:48 +00:00
runtime: update runc dependency to 1.0.1
Dependabot brought to us attention that we were still vendoring the runc code which was affected by CVE-2021-30465. Although the vulnerability doesn't seem to affect kata-containers, we better keep our dependencies up-to-date anyways. With this in mind, let's bump our runc dependency to the latest release. Fixes: #2309 Signed-off-by: Fabiano Fidêncio <fidencio@redhat.com>
This commit is contained in:
parent
3160f0102d
commit
b5293c5214
@ -26,16 +26,16 @@ require (
|
||||
github.com/intel-go/cpuid v0.0.0-20210602155658-5747e5cec0d9
|
||||
github.com/kata-containers/govmm v0.0.0-20210722115311-0173713ea912
|
||||
github.com/mdlayher/vsock v0.0.0-20191108225356-d9c65923cb8f
|
||||
github.com/opencontainers/runc v1.0.0-rc93
|
||||
github.com/opencontainers/runtime-spec v1.0.3-0.20200929063507-e6143ca7d51d
|
||||
github.com/opencontainers/selinux v1.8.0
|
||||
github.com/opencontainers/runc v1.0.1
|
||||
github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417
|
||||
github.com/opencontainers/selinux v1.8.2
|
||||
github.com/pkg/errors v0.9.1
|
||||
github.com/prometheus/client_golang v1.7.1
|
||||
github.com/prometheus/client_model v0.2.0
|
||||
github.com/prometheus/common v0.10.0
|
||||
github.com/prometheus/procfs v0.6.0
|
||||
github.com/safchain/ethtool v0.0.0-20190326074333-42ed695e3de8
|
||||
github.com/sirupsen/logrus v1.7.0
|
||||
github.com/sirupsen/logrus v1.8.1
|
||||
github.com/smartystreets/goconvey v1.6.4 // indirect
|
||||
github.com/stretchr/testify v1.6.1
|
||||
github.com/urfave/cli v1.22.2
|
||||
@ -46,7 +46,7 @@ require (
|
||||
go.opentelemetry.io/otel/sdk v0.15.0
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110
|
||||
golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43
|
||||
golang.org/x/sys v0.0.0-20210324051608-47abb6519492
|
||||
golang.org/x/sys v0.0.0-20210426230700-d19ff857e887
|
||||
google.golang.org/grpc v1.33.2
|
||||
k8s.io/apimachinery v0.20.6
|
||||
)
|
||||
|
@ -95,6 +95,8 @@ 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/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
|
||||
github.com/bitly/go-simplejson v0.5.0/go.mod h1:cXHtHw4XUPsvGaxgjIAn8PhEWG9NfngEKAMDJEczWVA=
|
||||
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.1.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
|
||||
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=
|
||||
@ -111,16 +113,18 @@ github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
|
||||
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
|
||||
github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY=
|
||||
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/checkpoint-restore/go-criu/v4 v4.1.0 h1:WW2B2uxx9KWF6bGlHqhm8Okiafwwx7Y2kcpn8lCpjgo=
|
||||
github.com/checkpoint-restore/go-criu/v4 v4.1.0/go.mod h1:xUQBLp4RLc5zJtWY++yjOoMoB5lihDt7fai+75m+rGw=
|
||||
github.com/checkpoint-restore/go-criu/v5 v5.0.0 h1:TW8f/UvntYoVDMN1K2HlT82qH1rb0sOjpGw3m6Ym+i4=
|
||||
github.com/checkpoint-restore/go-criu/v5 v5.0.0/go.mod h1:cfwC0EG7HMUenopBsUf9d89JlCLQIfgVcNsNN0t6T2M=
|
||||
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/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
||||
github.com/cilium/ebpf v0.0.0-20200110133405-4032b1d8aae3/go.mod h1:MA5e5Lr8slmEg9bt0VpxxWqJlO4iwu3FBdHUzV7wQVg=
|
||||
github.com/cilium/ebpf v0.0.0-20200702112145-1c8d4c9ef775/go.mod h1:7cR51M8ViRLIdUjrmSXlK9pkrsDlLHbO8jiB8X8JnOc=
|
||||
github.com/cilium/ebpf v0.2.0/go.mod h1:To2CFviqOWL/M0gIMsvSMlqe7em/l1ALkX1PyjrX2Qs=
|
||||
github.com/cilium/ebpf v0.4.0 h1:QlHdikaxALkqWasW8hAC1mfR0jdmvbfaBdBPFmRSglA=
|
||||
github.com/cilium/ebpf v0.4.0/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs=
|
||||
github.com/cilium/ebpf v0.6.2 h1:iHsfF/t4aW4heW2YKfeHrVPGdtYTL4C4KocpM8KTSnI=
|
||||
github.com/cilium/ebpf v0.6.2/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
||||
github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8=
|
||||
@ -229,8 +233,9 @@ github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7
|
||||
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e h1:Wf6HqHfScWJN9/ZjdUKyjop4mf3Qdd+1TvvltAvM3m8=
|
||||
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
||||
github.com/coreos/go-systemd/v22 v22.0.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk=
|
||||
github.com/coreos/go-systemd/v22 v22.1.0 h1:kq/SbG2BCKLkDKkjQf5OWwKWUKj1lgs3lFI4PxnR5lg=
|
||||
github.com/coreos/go-systemd/v22 v22.1.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk=
|
||||
github.com/coreos/go-systemd/v22 v22.3.2 h1:D9/bQk5vlXQFZ6Kwuu6zaiXJ9oTPe68++AzAJc1DzSI=
|
||||
github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
|
||||
github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
|
||||
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||
@ -348,8 +353,9 @@ github.com/godbus/dbus v0.0.0-20151105175453-c7fdd8b5cd55/go.mod h1:/YcGZj5zSblf
|
||||
github.com/godbus/dbus v0.0.0-20180201030542-885f9cc04c9c/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw=
|
||||
github.com/godbus/dbus v0.0.0-20190422162347-ade71ed3457e h1:BWhy2j3IXJhjCbC68FptL43tDKIq8FladmaTs3Xs7Z8=
|
||||
github.com/godbus/dbus v0.0.0-20190422162347-ade71ed3457e/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4=
|
||||
github.com/godbus/dbus/v5 v5.0.3 h1:ZqHaoEF7TBzh4jzPmqVhE/5A1z9of6orkAe5uHoAeME=
|
||||
github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||
github.com/godbus/dbus/v5 v5.0.4 h1:9349emZab16e7zQvpmsbtjc18ykshndd8y2PG3sgJbA=
|
||||
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||
github.com/gogo/googleapis v1.2.0/go.mod h1:Njal3psf3qN6dwBtQfUmBZh2ybovJ0tlu3o/AC7HYjU=
|
||||
github.com/gogo/googleapis v1.4.0 h1:zgVt4UpGxcqVOw97aRGxT4svlcmdK35fynLNctY32zI=
|
||||
github.com/gogo/googleapis v1.4.0/go.mod h1:5YRNX2z1oM5gXdAkurHa942MDgEJyk02w4OecKY87+c=
|
||||
@ -387,8 +393,9 @@ github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:W
|
||||
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
|
||||
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
|
||||
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||
github.com/golang/protobuf v1.4.3 h1:JjCZWpVbqXDqFVmTfYWEVTMIYrL/NPdPSCHPJ0T/raM=
|
||||
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||
github.com/golang/protobuf v1.5.0 h1:LUVKkCeviFUMKqHa4tXIIij/lbhnMbP7Fn5wKdKkRh4=
|
||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||
@ -399,8 +406,9 @@ github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
|
||||
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.4 h1:L8R9j+yAqZuZjsqh/z+F1NCffTKKLShY6zXTItVIZ8M=
|
||||
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
|
||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/gofuzz v1.1.0 h1:Hsa8mG0dQ46ij8Sl2AYJDUv1oA9/d6Vk+3LG99Oe02g=
|
||||
github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
@ -559,18 +567,21 @@ github.com/opencontainers/runc v0.0.0-20190115041553-12f6a991201f/go.mod h1:qT5X
|
||||
github.com/opencontainers/runc v0.1.1/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
|
||||
github.com/opencontainers/runc v1.0.0-rc8.0.20190926000215-3e425f80a8c9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
|
||||
github.com/opencontainers/runc v1.0.0-rc9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
|
||||
github.com/opencontainers/runc v1.0.0-rc93 h1:x2UMpOOVf3kQ8arv/EsDGwim8PTNqzL1/EYDr/+scOM=
|
||||
github.com/opencontainers/runc v1.0.0-rc93/go.mod h1:3NOsor4w32B2tC0Zbl8Knk4Wg84SM2ImC1fxBuqJ/H0=
|
||||
github.com/opencontainers/runc v1.0.1 h1:G18PGckGdAm3yVQRWDVQ1rLSLntiniKJ0cNRT2Tm5gs=
|
||||
github.com/opencontainers/runc v1.0.1/go.mod h1:aTaHFFwQXuA71CiyxOdFFIorAoemI04suvGRQFzWTD0=
|
||||
github.com/opencontainers/runtime-spec v0.1.2-0.20190507144316-5b71a03e2700/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
||||
github.com/opencontainers/runtime-spec v1.0.1/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
||||
github.com/opencontainers/runtime-spec v1.0.2-0.20190207185410-29686dbc5559/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
||||
github.com/opencontainers/runtime-spec v1.0.2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
||||
github.com/opencontainers/runtime-spec v1.0.3-0.20200929063507-e6143ca7d51d h1:pNa8metDkwZjb9g4T8s+krQ+HRgZAkqnXml+wNir/+s=
|
||||
github.com/opencontainers/runtime-spec v1.0.3-0.20200929063507-e6143ca7d51d/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
||||
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-tools v0.0.0-20181011054405-1d69bd0f9c39/go.mod h1:r3f7wjNzSs2extwzU3Y+6pKfobzPh+kKFJ3ofN+3nfs=
|
||||
github.com/opencontainers/selinux v1.6.0/go.mod h1:VVGKuOLlE7v4PJyT6h7mNWvq1rzqiriPsEqVhc+svHE=
|
||||
github.com/opencontainers/selinux v1.8.0 h1:+77ba4ar4jsCbL1GLbFL8fFM57w6suPfSS9PDLDY7KM=
|
||||
github.com/opencontainers/selinux v1.8.0/go.mod h1:RScLhm78qiWa2gbVCcGkC7tCGdgk3ogry1nUQF8Evvo=
|
||||
github.com/opencontainers/selinux v1.8.2 h1:c4ca10UMgRcvZ6h0K4HtS15UaVSBEaE+iln2LVpAuGc=
|
||||
github.com/opencontainers/selinux v1.8.2/go.mod h1:MUIHuUEvKB1wtJjQdOyYRgOnLD2xAPP8dBsCoU0KuF8=
|
||||
github.com/pborman/uuid v1.2.0 h1:J7Q5mO4ysT1dv8hyrUGHb9+ooztCXu1D8MY8DZYsu3g=
|
||||
github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
|
||||
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
||||
@ -635,8 +646,9 @@ github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPx
|
||||
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
|
||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
|
||||
github.com/sirupsen/logrus v1.7.0 h1:ShrD1U9pZB12TX0cVy0DtePoCH97K8EtX+mg7ZARUtM=
|
||||
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
||||
github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE=
|
||||
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM=
|
||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
||||
github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
||||
@ -691,7 +703,6 @@ github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17
|
||||
github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae h1:4hwBBUfQCFe3Cym0ZtKyq7L16eZUtYKs+BaHDN6mAns=
|
||||
github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0=
|
||||
github.com/willf/bitset v1.1.11-0.20200630133818-d5bec3311243/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4=
|
||||
github.com/willf/bitset v1.1.11 h1:N7Z7E9UvjW+sGsEl7k/SJrvY2reP1A07MrGuCjIOjRE=
|
||||
github.com/willf/bitset v1.1.11/go.mod h1:83CECat5yLh5zVOf4P1ErAgKA5UDvKtgyUABdr3+MjI=
|
||||
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
|
||||
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ=
|
||||
@ -896,8 +907,9 @@ golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201202213521-69691e467435/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210324051608-47abb6519492 h1:Paq34FxTluEPvVyayQqMPgHm+vTOrIifmcYxFBx9TLg=
|
||||
golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210426230700-d19ff857e887 h1:dXfMednGJh/SUUFjTLsWJz3P+TQt9qnR11GgeI3vWKs=
|
||||
golang.org/x/sys v0.0.0-20210426230700-d19ff857e887/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
@ -1018,8 +1030,10 @@ google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miE
|
||||
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
|
||||
google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c=
|
||||
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
|
||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||
google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk=
|
||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U=
|
||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
|
@ -2,10 +2,9 @@
|
||||
|
||||
*Go language library to map between non-negative integers and boolean values*
|
||||
|
||||
[](https://github.com/willf/bitset/actions?query=workflow%3ATest)
|
||||
[](https://coveralls.io/github/willf/bitset?branch=master)
|
||||
[](https://github.com/willf/bitset/actions?query=workflow%3ATest)
|
||||
[](https://goreportcard.com/report/github.com/willf/bitset)
|
||||
[](https://pkg.go.dev/github.com/willf/bitset?tab=doc)
|
||||
[](https://pkg.go.dev/github.com/bits-and-blooms/bitset?tab=doc)
|
||||
|
||||
|
||||
## Description
|
||||
@ -30,7 +29,7 @@ import (
|
||||
"fmt"
|
||||
"math/rand"
|
||||
|
||||
"github.com/willf/bitset"
|
||||
"github.com/bits-and-blooms/bitset"
|
||||
)
|
||||
|
||||
func main() {
|
||||
@ -63,7 +62,7 @@ func main() {
|
||||
|
||||
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/willf/bitset?tab=doc
|
||||
Package documentation is at: https://pkg.go.dev/github.com/bits-and-blooms/bitset?tab=doc
|
||||
|
||||
## Memory Usage
|
||||
|
||||
@ -78,7 +77,7 @@ It is possible that a later version will match the `math/bits` return signature
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
go get github.com/willf/bitset
|
||||
go get github.com/bits-and-blooms/bitset
|
||||
```
|
||||
|
||||
## Contributing
|
@ -209,6 +209,27 @@ func (b *BitSet) Flip(i uint) *BitSet {
|
||||
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.
|
||||
@ -519,7 +540,7 @@ func (b *BitSet) Copy(c *BitSet) (count uint) {
|
||||
}
|
||||
|
||||
// Count (number of set bits).
|
||||
// Also known as "popcount" or "popularity count".
|
||||
// Also known as "popcount" or "population count".
|
||||
func (b *BitSet) Count() uint {
|
||||
if b != nil && b.set != nil {
|
||||
return uint(popcntSlice(b.set))
|
3
src/runtime/vendor/github.com/bits-and-blooms/bitset/go.mod
generated
vendored
Normal file
3
src/runtime/vendor/github.com/bits-and-blooms/bitset/go.mod
generated
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
module github.com/bits-and-blooms/bitset
|
||||
|
||||
go 1.14
|
28
src/runtime/vendor/github.com/checkpoint-restore/go-criu/v4/.travis.yml
generated
vendored
28
src/runtime/vendor/github.com/checkpoint-restore/go-criu/v4/.travis.yml
generated
vendored
@ -1,28 +0,0 @@
|
||||
language: go
|
||||
dist: bionic
|
||||
os:
|
||||
- linux
|
||||
go:
|
||||
- "1.14.x"
|
||||
- "1.13.x"
|
||||
- tip
|
||||
env:
|
||||
# Run the tests with CRIU master and criu-dev
|
||||
- CRIU_BRANCH="master"
|
||||
- CRIU_BRANCH="criu-dev"
|
||||
install:
|
||||
- sudo apt-get update
|
||||
- sudo apt-get install -y libprotobuf-dev libprotobuf-c0-dev protobuf-c-compiler protobuf-compiler python-protobuf libnl-3-dev libnet-dev libcap-dev
|
||||
- make install.tools
|
||||
- go get github.com/checkpoint-restore/go-criu
|
||||
- git clone --single-branch -b ${CRIU_BRANCH} https://github.com/checkpoint-restore/criu.git
|
||||
- cd criu; make
|
||||
- sudo install -D -m 755 criu/criu /usr/sbin/
|
||||
- cd ..
|
||||
script:
|
||||
# This builds the code without running the tests.
|
||||
- make lint build phaul test/test test/phaul test/piggie
|
||||
# Run actual test as root as it uses CRIU.
|
||||
- sudo make test phaul-test
|
||||
# This builds crit-go
|
||||
- make -C crit-go/magic-gen lint build magicgen test
|
60
src/runtime/vendor/github.com/checkpoint-restore/go-criu/v4/Makefile
generated
vendored
60
src/runtime/vendor/github.com/checkpoint-restore/go-criu/v4/Makefile
generated
vendored
@ -1,60 +0,0 @@
|
||||
GO ?= go
|
||||
CC ?= gcc
|
||||
ifeq ($(GOPATH),)
|
||||
export GOPATH := $(shell $(GO) env GOPATH)
|
||||
endif
|
||||
FIRST_GOPATH := $(firstword $(subst :, ,$(GOPATH)))
|
||||
GOBIN := $(shell $(GO) env GOBIN)
|
||||
ifeq ($(GOBIN),)
|
||||
GOBIN := $(FIRST_GOPATH)/bin
|
||||
endif
|
||||
|
||||
all: build test phaul phaul-test
|
||||
|
||||
lint:
|
||||
@golint -set_exit_status . test phaul
|
||||
build:
|
||||
@$(GO) build -v
|
||||
|
||||
test/piggie: test/piggie.c
|
||||
@$(CC) $^ -o $@
|
||||
|
||||
test/test: test/main.go
|
||||
@$(GO) build -v -o test/test test/main.go
|
||||
|
||||
test: test/test test/piggie
|
||||
mkdir -p image
|
||||
test/piggie
|
||||
test/test dump `pidof piggie` image
|
||||
test/test restore image
|
||||
pkill -9 piggie || :
|
||||
|
||||
phaul:
|
||||
@cd phaul; go build -v
|
||||
|
||||
test/phaul: test/phaul-main.go
|
||||
@$(GO) build -v -o test/phaul test/phaul-main.go
|
||||
|
||||
phaul-test: test/phaul test/piggie
|
||||
rm -rf image
|
||||
test/piggie
|
||||
test/phaul `pidof piggie`
|
||||
pkill -9 piggie || :
|
||||
|
||||
clean:
|
||||
@rm -f test/test test/piggie test/phaul
|
||||
@rm -rf image
|
||||
@rm -f rpc/rpc.proto
|
||||
|
||||
install.tools:
|
||||
if [ ! -x "$(GOBIN)/golint" ]; then \
|
||||
$(GO) get -u golang.org/x/lint/golint; \
|
||||
fi
|
||||
|
||||
rpc/rpc.proto:
|
||||
curl -s https://raw.githubusercontent.com/checkpoint-restore/criu/master/images/rpc.proto -o $@
|
||||
|
||||
rpc/rpc.pb.go: rpc/rpc.proto
|
||||
protoc --go_out=. $^
|
||||
|
||||
.PHONY: build test clean lint phaul
|
5
src/runtime/vendor/github.com/checkpoint-restore/go-criu/v4/go.mod
generated
vendored
5
src/runtime/vendor/github.com/checkpoint-restore/go-criu/v4/go.mod
generated
vendored
@ -1,5 +0,0 @@
|
||||
module github.com/checkpoint-restore/go-criu/v4
|
||||
|
||||
go 1.13
|
||||
|
||||
require github.com/golang/protobuf v1.3.5
|
2
src/runtime/vendor/github.com/checkpoint-restore/go-criu/v4/go.sum
generated
vendored
2
src/runtime/vendor/github.com/checkpoint-restore/go-criu/v4/go.sum
generated
vendored
@ -1,2 +0,0 @@
|
||||
github.com/golang/protobuf v1.3.5 h1:F768QJ1E9tib+q5Sc8MkdJi1RxLTbRcTf8LJV56aRls=
|
||||
github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk=
|
1667
src/runtime/vendor/github.com/checkpoint-restore/go-criu/v4/rpc/rpc.pb.go
generated
vendored
1667
src/runtime/vendor/github.com/checkpoint-restore/go-criu/v4/rpc/rpc.pb.go
generated
vendored
File diff suppressed because it is too large
Load Diff
@ -1,5 +1,6 @@
|
||||
test/test
|
||||
test/piggie
|
||||
test/piggie/piggie
|
||||
test/phaul
|
||||
image
|
||||
rpc/rpc.proto
|
||||
stats/stats.proto
|
12
src/runtime/vendor/github.com/checkpoint-restore/go-criu/v5/.golangci.yml
generated
vendored
Normal file
12
src/runtime/vendor/github.com/checkpoint-restore/go-criu/v5/.golangci.yml
generated
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
run:
|
||||
skip_dirs:
|
||||
- rpc
|
||||
- stats
|
||||
|
||||
linters:
|
||||
disable-all: false
|
||||
presets:
|
||||
- bugs
|
||||
- performance
|
||||
- unused
|
||||
- format
|
57
src/runtime/vendor/github.com/checkpoint-restore/go-criu/v5/Makefile
generated
vendored
Normal file
57
src/runtime/vendor/github.com/checkpoint-restore/go-criu/v5/Makefile
generated
vendored
Normal file
@ -0,0 +1,57 @@
|
||||
GO ?= go
|
||||
CC ?= gcc
|
||||
|
||||
all: build test phaul-test
|
||||
|
||||
lint:
|
||||
golangci-lint run ./...
|
||||
|
||||
build:
|
||||
$(GO) build -v ./...
|
||||
|
||||
TEST_BINARIES := test/test test/piggie/piggie test/phaul/phaul
|
||||
test-bin: $(TEST_BINARIES)
|
||||
|
||||
test/piggie/piggie: test/piggie/piggie.c
|
||||
$(CC) $^ -o $@
|
||||
|
||||
test/test: test/*.go
|
||||
$(GO) build -v -o $@ $^
|
||||
|
||||
test: $(TEST_BINARIES)
|
||||
mkdir -p image
|
||||
PID=$$(test/piggie/piggie) && { \
|
||||
test/test dump $$PID image && \
|
||||
test/test restore image; \
|
||||
pkill -9 piggie; \
|
||||
}
|
||||
rm -rf image
|
||||
|
||||
test/phaul/phaul: test/phaul/*.go
|
||||
$(GO) build -v -o $@ $^
|
||||
|
||||
phaul-test: $(TEST_BINARIES)
|
||||
rm -rf image
|
||||
PID=$$(test/piggie/piggie) && { \
|
||||
test/phaul/phaul $$PID; \
|
||||
pkill -9 piggie; \
|
||||
}
|
||||
|
||||
clean:
|
||||
@rm -f $(TEST_BINARIES)
|
||||
@rm -rf image
|
||||
@rm -f rpc/rpc.proto stats/stats.proto
|
||||
|
||||
rpc/rpc.proto:
|
||||
curl -sSL https://raw.githubusercontent.com/checkpoint-restore/criu/master/images/rpc.proto -o $@
|
||||
|
||||
stats/stats.proto:
|
||||
curl -sSL https://raw.githubusercontent.com/checkpoint-restore/criu/master/images/stats.proto -o $@
|
||||
|
||||
rpc/rpc.pb.go: rpc/rpc.proto
|
||||
protoc --go_out=. $^
|
||||
|
||||
stats/stats.pb.go: stats/stats.proto
|
||||
protoc --go_out=. $^
|
||||
|
||||
.PHONY: build test phaul-test test-bin clean lint
|
@ -1,8 +1,10 @@
|
||||
[](https://travis-ci.org/checkpoint-restore/go-criu)
|
||||
[](https://github.com/checkpoint-restore/go-criu/actions?query=workflow%3Aci)
|
||||
[](https://github.com/checkpoint-restore/go-criu/actions?query=workflow%3Averify)
|
||||
[](https://pkg.go.dev/github.com/checkpoint-restore/go-criu)
|
||||
|
||||
## go-criu -- Go bindings for [CRIU](https://criu.org/)
|
||||
## go-criu -- Go bindings for CRIU
|
||||
|
||||
This repository provides Go bindings for CRIU. The code is based on the Go based PHaul
|
||||
This repository provides Go bindings for [CRIU](https://criu.org/). The code is based on the Go-based PHaul
|
||||
implementation from the CRIU repository. For easier inclusion into other Go projects the
|
||||
CRIU Go bindings have been moved to this repository.
|
||||
|
||||
@ -10,13 +12,26 @@ The Go bindings provide an easy way to use the CRIU RPC calls from Go without th
|
||||
to set up all the infrastructure to make the actual RPC connection to CRIU.
|
||||
|
||||
The following example would print the version of CRIU:
|
||||
```
|
||||
```go
|
||||
import (
|
||||
"log"
|
||||
|
||||
"github.com/checkpoint/restore/go-criu/v5"
|
||||
)
|
||||
|
||||
func main() {
|
||||
c := criu.MakeCriu()
|
||||
version, err := c.GetCriuVersion()
|
||||
fmt.Println(version)
|
||||
if err != nil {
|
||||
log.Fatalln(err)
|
||||
}
|
||||
log.Println(version)
|
||||
}
|
||||
```
|
||||
|
||||
or to just check if at least a certain CRIU version is installed:
|
||||
```
|
||||
|
||||
```go
|
||||
c := criu.MakeCriu()
|
||||
result, err := c.IsCriuAtLeast(31100)
|
||||
```
|
||||
@ -31,7 +46,12 @@ As go-criu is imported in other projects and as Go modules are expected
|
||||
to follow Semantic Versioning go-criu will also follow Semantic Versioning
|
||||
starting with the 4.0.0 release.
|
||||
|
||||
4.0.0 is based on CRIU 3.14
|
||||
The following table shows the relation between go-criu and criu versions:
|
||||
|
||||
| Major version | Latest release | CRIU version |
|
||||
| -------------- | -------------- | ------------ |
|
||||
| v5 | 5.0.0 | 3.15 |
|
||||
| v4 | 4.1.0 | 3.14 |
|
||||
|
||||
## How to contribute
|
||||
|
9
src/runtime/vendor/github.com/checkpoint-restore/go-criu/v5/go.mod
generated
vendored
Normal file
9
src/runtime/vendor/github.com/checkpoint-restore/go-criu/v5/go.mod
generated
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
module github.com/checkpoint-restore/go-criu/v5
|
||||
|
||||
go 1.13
|
||||
|
||||
require (
|
||||
github.com/golang/protobuf v1.4.3
|
||||
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c
|
||||
google.golang.org/protobuf v1.23.0
|
||||
)
|
22
src/runtime/vendor/github.com/checkpoint-restore/go-criu/v5/go.sum
generated
vendored
Normal file
22
src/runtime/vendor/github.com/checkpoint-restore/go-criu/v5/go.sum
generated
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
|
||||
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
|
||||
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
|
||||
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/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/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||
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=
|
@ -8,8 +8,8 @@ import (
|
||||
"strconv"
|
||||
"syscall"
|
||||
|
||||
"github.com/checkpoint-restore/go-criu/v4/rpc"
|
||||
"github.com/golang/protobuf/proto"
|
||||
"github.com/checkpoint-restore/go-criu/v5/rpc"
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
// Criu struct
|
||||
@ -45,6 +45,7 @@ func (c *Criu) Prepare() error {
|
||||
defer srv.Close()
|
||||
|
||||
args := []string{"swrk", strconv.Itoa(fds[1])}
|
||||
// #nosec G204
|
||||
cmd := exec.Command(c.swrkPath, args...)
|
||||
|
||||
err = cmd.Start()
|
||||
@ -64,7 +65,7 @@ func (c *Criu) Cleanup() {
|
||||
if c.swrkCmd != nil {
|
||||
c.swrkSk.Close()
|
||||
c.swrkSk = nil
|
||||
c.swrkCmd.Wait()
|
||||
_ = c.swrkCmd.Wait()
|
||||
c.swrkCmd = nil
|
||||
}
|
||||
}
|
||||
@ -187,28 +188,28 @@ func (c *Criu) doSwrkWithResp(reqType rpc.CriuReqType, opts *rpc.CriuOpts, nfy N
|
||||
}
|
||||
|
||||
// Dump dumps a process
|
||||
func (c *Criu) Dump(opts rpc.CriuOpts, nfy Notify) error {
|
||||
return c.doSwrk(rpc.CriuReqType_DUMP, &opts, nfy)
|
||||
func (c *Criu) Dump(opts *rpc.CriuOpts, nfy Notify) error {
|
||||
return c.doSwrk(rpc.CriuReqType_DUMP, opts, nfy)
|
||||
}
|
||||
|
||||
// Restore restores a process
|
||||
func (c *Criu) Restore(opts rpc.CriuOpts, nfy Notify) error {
|
||||
return c.doSwrk(rpc.CriuReqType_RESTORE, &opts, nfy)
|
||||
func (c *Criu) Restore(opts *rpc.CriuOpts, nfy Notify) error {
|
||||
return c.doSwrk(rpc.CriuReqType_RESTORE, opts, nfy)
|
||||
}
|
||||
|
||||
// PreDump does a pre-dump
|
||||
func (c *Criu) PreDump(opts rpc.CriuOpts, nfy Notify) error {
|
||||
return c.doSwrk(rpc.CriuReqType_PRE_DUMP, &opts, nfy)
|
||||
func (c *Criu) PreDump(opts *rpc.CriuOpts, nfy Notify) error {
|
||||
return c.doSwrk(rpc.CriuReqType_PRE_DUMP, opts, nfy)
|
||||
}
|
||||
|
||||
// StartPageServer starts the page server
|
||||
func (c *Criu) StartPageServer(opts rpc.CriuOpts) error {
|
||||
return c.doSwrk(rpc.CriuReqType_PAGE_SERVER, &opts, nil)
|
||||
func (c *Criu) StartPageServer(opts *rpc.CriuOpts) error {
|
||||
return c.doSwrk(rpc.CriuReqType_PAGE_SERVER, opts, nil)
|
||||
}
|
||||
|
||||
// StartPageServerChld starts the page server and returns PID and port
|
||||
func (c *Criu) StartPageServerChld(opts rpc.CriuOpts) (int, int, error) {
|
||||
resp, err := c.doSwrkWithResp(rpc.CriuReqType_PAGE_SERVER_CHLD, &opts, nil)
|
||||
func (c *Criu) StartPageServerChld(opts *rpc.CriuOpts) (int, int, error) {
|
||||
resp, err := c.doSwrkWithResp(rpc.CriuReqType_PAGE_SERVER_CHLD, opts, nil)
|
||||
if err != nil {
|
||||
return 0, 0, err
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
package criu
|
||||
|
||||
//Notify interface
|
||||
// Notify interface
|
||||
type Notify interface {
|
||||
PreDump() error
|
||||
PostDump() error
|
||||
@ -14,8 +14,7 @@ type Notify interface {
|
||||
}
|
||||
|
||||
// NoNotify struct
|
||||
type NoNotify struct {
|
||||
}
|
||||
type NoNotify struct{}
|
||||
|
||||
// PreDump NoNotify
|
||||
func (c NoNotify) PreDump() error {
|
2208
src/runtime/vendor/github.com/checkpoint-restore/go-criu/v5/rpc/rpc.pb.go
generated
vendored
Normal file
2208
src/runtime/vendor/github.com/checkpoint-restore/go-criu/v5/rpc/rpc.pb.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
29
src/runtime/vendor/github.com/cilium/ebpf/.golangci.yaml
generated
vendored
Normal file
29
src/runtime/vendor/github.com/cilium/ebpf/.golangci.yaml
generated
vendored
Normal file
@ -0,0 +1,29 @@
|
||||
---
|
||||
issues:
|
||||
exclude-rules:
|
||||
# syscall param structs will have unused fields in Go code.
|
||||
- path: syscall.*.go
|
||||
linters:
|
||||
- structcheck
|
||||
|
||||
linters:
|
||||
disable-all: true
|
||||
enable:
|
||||
- deadcode
|
||||
- errcheck
|
||||
- goimports
|
||||
- gosimple
|
||||
- govet
|
||||
- ineffassign
|
||||
- misspell
|
||||
- staticcheck
|
||||
- structcheck
|
||||
- typecheck
|
||||
- unused
|
||||
- varcheck
|
||||
|
||||
# Could be enabled later:
|
||||
# - gocyclo
|
||||
# - prealloc
|
||||
# - maligned
|
||||
# - gosec
|
21
src/runtime/vendor/github.com/cilium/ebpf/CONTRIBUTING.md
generated
vendored
21
src/runtime/vendor/github.com/cilium/ebpf/CONTRIBUTING.md
generated
vendored
@ -18,6 +18,23 @@ reason about the proposed changes.
|
||||
## Running the tests
|
||||
|
||||
Many of the tests require privileges to set resource limits and load eBPF code.
|
||||
The easiest way to obtain these is to run the tests with `sudo`:
|
||||
The easiest way to obtain these is to run the tests with `sudo`.
|
||||
|
||||
To test the current package with your local kernel you can simply run:
|
||||
```
|
||||
go test -exec sudo ./...
|
||||
```
|
||||
|
||||
To test the current package with a different kernel version you can use the [run-tests.sh](run-tests.sh) script.
|
||||
It requires [virtme](https://github.com/amluto/virtme) and qemu to be installed.
|
||||
|
||||
Examples:
|
||||
|
||||
```bash
|
||||
# Run all tests on a 5.4 kernel
|
||||
./run-tests.sh 5.4
|
||||
|
||||
# Run a subset of tests:
|
||||
./run-tests.sh 5.4 go test ./link
|
||||
```
|
||||
|
||||
sudo go test ./...
|
7
src/runtime/vendor/github.com/cilium/ebpf/Makefile
generated
vendored
7
src/runtime/vendor/github.com/cilium/ebpf/Makefile
generated
vendored
@ -1,7 +1,7 @@
|
||||
# The development version of clang is distributed as the 'clang' binary,
|
||||
# while stable/released versions have a version number attached.
|
||||
# Pin the default clang to a stable version.
|
||||
CLANG ?= clang-11
|
||||
CLANG ?= clang-12
|
||||
CFLAGS := -target bpf -O2 -g -Wall -Werror $(CFLAGS)
|
||||
|
||||
# Obtain an absolute path to the directory of the Makefile.
|
||||
@ -17,7 +17,7 @@ VERSION := $(shell cat ${REPODIR}/testdata/docker/VERSION)
|
||||
TARGETS := \
|
||||
testdata/loader-clang-7 \
|
||||
testdata/loader-clang-9 \
|
||||
testdata/loader-clang-11 \
|
||||
testdata/loader-$(CLANG) \
|
||||
testdata/invalid_map \
|
||||
testdata/raw_tracepoint \
|
||||
testdata/invalid_map_static \
|
||||
@ -33,6 +33,7 @@ TARGETS := \
|
||||
docker-all:
|
||||
docker run --rm --user "${UIDGID}" \
|
||||
-v "${REPODIR}":/ebpf -w /ebpf --env MAKEFLAGS \
|
||||
--env CFLAGS="-fdebug-prefix-map=/ebpf=." \
|
||||
"${IMAGE}:${VERSION}" \
|
||||
make all
|
||||
|
||||
@ -47,6 +48,8 @@ clean:
|
||||
-$(RM) internal/btf/testdata/*.elf
|
||||
|
||||
all: $(addsuffix -el.elf,$(TARGETS)) $(addsuffix -eb.elf,$(TARGETS))
|
||||
ln -srf testdata/loader-$(CLANG)-el.elf testdata/loader-el.elf
|
||||
ln -srf testdata/loader-$(CLANG)-eb.elf testdata/loader-eb.elf
|
||||
|
||||
testdata/loader-%-el.elf: testdata/loader.c
|
||||
$* $(CFLAGS) -mlittle-endian -c $< -o $@
|
||||
|
10
src/runtime/vendor/github.com/cilium/ebpf/README.md
generated
vendored
10
src/runtime/vendor/github.com/cilium/ebpf/README.md
generated
vendored
@ -13,7 +13,7 @@ be used in long running processes.
|
||||
* [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
|
||||
embedding eBPF in Go
|
||||
compiling and embedding eBPF programs in Go code
|
||||
|
||||
The library is maintained by [Cloudflare](https://www.cloudflare.com) and
|
||||
[Cilium](https://www.cilium.io). Feel free to
|
||||
@ -25,6 +25,14 @@ The library is maintained by [Cloudflare](https://www.cloudflare.com) and
|
||||
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
|
||||
|
||||
A small collection of Go and eBPF programs that serve as examples for building
|
||||
your own tools can be found under [examples/](examples/).
|
||||
|
||||
Contributions are highly encouraged, as they highlight certain use cases of
|
||||
eBPF and the library, and help shape the future of the project.
|
||||
|
||||
## Requirements
|
||||
|
||||
* A version of Go that is [supported by
|
||||
|
54
src/runtime/vendor/github.com/cilium/ebpf/asm/func.go
generated
vendored
54
src/runtime/vendor/github.com/cilium/ebpf/asm/func.go
generated
vendored
@ -7,7 +7,7 @@ type BuiltinFunc int32
|
||||
|
||||
// eBPF built-in functions
|
||||
//
|
||||
// You can renegerate this list using the following gawk script:
|
||||
// You can regenerate this list using the following gawk script:
|
||||
//
|
||||
// /FN\(.+\),/ {
|
||||
// match($1, /\((.+)\)/, r)
|
||||
@ -132,6 +132,58 @@ const (
|
||||
FnSkStorageDelete
|
||||
FnSendSignal
|
||||
FnTcpGenSyncookie
|
||||
FnSkbOutput
|
||||
FnProbeReadUser
|
||||
FnProbeReadKernel
|
||||
FnProbeReadUserStr
|
||||
FnProbeReadKernelStr
|
||||
FnTcpSendAck
|
||||
FnSendSignalThread
|
||||
FnJiffies64
|
||||
FnReadBranchRecords
|
||||
FnGetNsCurrentPidTgid
|
||||
FnXdpOutput
|
||||
FnGetNetnsCookie
|
||||
FnGetCurrentAncestorCgroupId
|
||||
FnSkAssign
|
||||
FnKtimeGetBootNs
|
||||
FnSeqPrintf
|
||||
FnSeqWrite
|
||||
FnSkCgroupId
|
||||
FnSkAncestorCgroupId
|
||||
FnRingbufOutput
|
||||
FnRingbufReserve
|
||||
FnRingbufSubmit
|
||||
FnRingbufDiscard
|
||||
FnRingbufQuery
|
||||
FnCsumLevel
|
||||
FnSkcToTcp6Sock
|
||||
FnSkcToTcpSock
|
||||
FnSkcToTcpTimewaitSock
|
||||
FnSkcToTcpRequestSock
|
||||
FnSkcToUdp6Sock
|
||||
FnGetTaskStack
|
||||
FnLoadHdrOpt
|
||||
FnStoreHdrOpt
|
||||
FnReserveHdrOpt
|
||||
FnInodeStorageGet
|
||||
FnInodeStorageDelete
|
||||
FnDPath
|
||||
FnCopyFromUser
|
||||
FnSnprintfBtf
|
||||
FnSeqPrintfBtf
|
||||
FnSkbCgroupClassid
|
||||
FnRedirectNeigh
|
||||
FnPerCpuPtr
|
||||
FnThisCpuPtr
|
||||
FnRedirectPeer
|
||||
FnTaskStorageGet
|
||||
FnTaskStorageDelete
|
||||
FnGetCurrentTaskBtf
|
||||
FnBprmOptsSet
|
||||
FnKtimeGetCoarseNs
|
||||
FnImaInodeHash
|
||||
FnSockFromFile
|
||||
)
|
||||
|
||||
// Call emits a function call.
|
||||
|
56
src/runtime/vendor/github.com/cilium/ebpf/asm/func_string.go
generated
vendored
56
src/runtime/vendor/github.com/cilium/ebpf/asm/func_string.go
generated
vendored
@ -119,11 +119,63 @@ func _() {
|
||||
_ = x[FnSkStorageDelete-108]
|
||||
_ = x[FnSendSignal-109]
|
||||
_ = x[FnTcpGenSyncookie-110]
|
||||
_ = x[FnSkbOutput-111]
|
||||
_ = x[FnProbeReadUser-112]
|
||||
_ = x[FnProbeReadKernel-113]
|
||||
_ = x[FnProbeReadUserStr-114]
|
||||
_ = x[FnProbeReadKernelStr-115]
|
||||
_ = x[FnTcpSendAck-116]
|
||||
_ = x[FnSendSignalThread-117]
|
||||
_ = x[FnJiffies64-118]
|
||||
_ = x[FnReadBranchRecords-119]
|
||||
_ = x[FnGetNsCurrentPidTgid-120]
|
||||
_ = x[FnXdpOutput-121]
|
||||
_ = x[FnGetNetnsCookie-122]
|
||||
_ = x[FnGetCurrentAncestorCgroupId-123]
|
||||
_ = x[FnSkAssign-124]
|
||||
_ = x[FnKtimeGetBootNs-125]
|
||||
_ = x[FnSeqPrintf-126]
|
||||
_ = x[FnSeqWrite-127]
|
||||
_ = x[FnSkCgroupId-128]
|
||||
_ = x[FnSkAncestorCgroupId-129]
|
||||
_ = x[FnRingbufOutput-130]
|
||||
_ = x[FnRingbufReserve-131]
|
||||
_ = x[FnRingbufSubmit-132]
|
||||
_ = x[FnRingbufDiscard-133]
|
||||
_ = x[FnRingbufQuery-134]
|
||||
_ = x[FnCsumLevel-135]
|
||||
_ = x[FnSkcToTcp6Sock-136]
|
||||
_ = x[FnSkcToTcpSock-137]
|
||||
_ = x[FnSkcToTcpTimewaitSock-138]
|
||||
_ = x[FnSkcToTcpRequestSock-139]
|
||||
_ = x[FnSkcToUdp6Sock-140]
|
||||
_ = x[FnGetTaskStack-141]
|
||||
_ = x[FnLoadHdrOpt-142]
|
||||
_ = x[FnStoreHdrOpt-143]
|
||||
_ = x[FnReserveHdrOpt-144]
|
||||
_ = x[FnInodeStorageGet-145]
|
||||
_ = x[FnInodeStorageDelete-146]
|
||||
_ = x[FnDPath-147]
|
||||
_ = x[FnCopyFromUser-148]
|
||||
_ = x[FnSnprintfBtf-149]
|
||||
_ = x[FnSeqPrintfBtf-150]
|
||||
_ = x[FnSkbCgroupClassid-151]
|
||||
_ = x[FnRedirectNeigh-152]
|
||||
_ = x[FnPerCpuPtr-153]
|
||||
_ = x[FnThisCpuPtr-154]
|
||||
_ = x[FnRedirectPeer-155]
|
||||
_ = x[FnTaskStorageGet-156]
|
||||
_ = x[FnTaskStorageDelete-157]
|
||||
_ = x[FnGetCurrentTaskBtf-158]
|
||||
_ = x[FnBprmOptsSet-159]
|
||||
_ = x[FnKtimeGetCoarseNs-160]
|
||||
_ = x[FnImaInodeHash-161]
|
||||
_ = x[FnSockFromFile-162]
|
||||
}
|
||||
|
||||
const _BuiltinFunc_name = "FnUnspecFnMapLookupElemFnMapUpdateElemFnMapDeleteElemFnProbeReadFnKtimeGetNsFnTracePrintkFnGetPrandomU32FnGetSmpProcessorIdFnSkbStoreBytesFnL3CsumReplaceFnL4CsumReplaceFnTailCallFnCloneRedirectFnGetCurrentPidTgidFnGetCurrentUidGidFnGetCurrentCommFnGetCgroupClassidFnSkbVlanPushFnSkbVlanPopFnSkbGetTunnelKeyFnSkbSetTunnelKeyFnPerfEventReadFnRedirectFnGetRouteRealmFnPerfEventOutputFnSkbLoadBytesFnGetStackidFnCsumDiffFnSkbGetTunnelOptFnSkbSetTunnelOptFnSkbChangeProtoFnSkbChangeTypeFnSkbUnderCgroupFnGetHashRecalcFnGetCurrentTaskFnProbeWriteUserFnCurrentTaskUnderCgroupFnSkbChangeTailFnSkbPullDataFnCsumUpdateFnSetHashInvalidFnGetNumaNodeIdFnSkbChangeHeadFnXdpAdjustHeadFnProbeReadStrFnGetSocketCookieFnGetSocketUidFnSetHashFnSetsockoptFnSkbAdjustRoomFnRedirectMapFnSkRedirectMapFnSockMapUpdateFnXdpAdjustMetaFnPerfEventReadValueFnPerfProgReadValueFnGetsockoptFnOverrideReturnFnSockOpsCbFlagsSetFnMsgRedirectMapFnMsgApplyBytesFnMsgCorkBytesFnMsgPullDataFnBindFnXdpAdjustTailFnSkbGetXfrmStateFnGetStackFnSkbLoadBytesRelativeFnFibLookupFnSockHashUpdateFnMsgRedirectHashFnSkRedirectHashFnLwtPushEncapFnLwtSeg6StoreBytesFnLwtSeg6AdjustSrhFnLwtSeg6ActionFnRcRepeatFnRcKeydownFnSkbCgroupIdFnGetCurrentCgroupIdFnGetLocalStorageFnSkSelectReuseportFnSkbAncestorCgroupIdFnSkLookupTcpFnSkLookupUdpFnSkReleaseFnMapPushElemFnMapPopElemFnMapPeekElemFnMsgPushDataFnMsgPopDataFnRcPointerRelFnSpinLockFnSpinUnlockFnSkFullsockFnTcpSockFnSkbEcnSetCeFnGetListenerSockFnSkcLookupTcpFnTcpCheckSyncookieFnSysctlGetNameFnSysctlGetCurrentValueFnSysctlGetNewValueFnSysctlSetNewValueFnStrtolFnStrtoulFnSkStorageGetFnSkStorageDeleteFnSendSignalFnTcpGenSyncookie"
|
||||
const _BuiltinFunc_name = "FnUnspecFnMapLookupElemFnMapUpdateElemFnMapDeleteElemFnProbeReadFnKtimeGetNsFnTracePrintkFnGetPrandomU32FnGetSmpProcessorIdFnSkbStoreBytesFnL3CsumReplaceFnL4CsumReplaceFnTailCallFnCloneRedirectFnGetCurrentPidTgidFnGetCurrentUidGidFnGetCurrentCommFnGetCgroupClassidFnSkbVlanPushFnSkbVlanPopFnSkbGetTunnelKeyFnSkbSetTunnelKeyFnPerfEventReadFnRedirectFnGetRouteRealmFnPerfEventOutputFnSkbLoadBytesFnGetStackidFnCsumDiffFnSkbGetTunnelOptFnSkbSetTunnelOptFnSkbChangeProtoFnSkbChangeTypeFnSkbUnderCgroupFnGetHashRecalcFnGetCurrentTaskFnProbeWriteUserFnCurrentTaskUnderCgroupFnSkbChangeTailFnSkbPullDataFnCsumUpdateFnSetHashInvalidFnGetNumaNodeIdFnSkbChangeHeadFnXdpAdjustHeadFnProbeReadStrFnGetSocketCookieFnGetSocketUidFnSetHashFnSetsockoptFnSkbAdjustRoomFnRedirectMapFnSkRedirectMapFnSockMapUpdateFnXdpAdjustMetaFnPerfEventReadValueFnPerfProgReadValueFnGetsockoptFnOverrideReturnFnSockOpsCbFlagsSetFnMsgRedirectMapFnMsgApplyBytesFnMsgCorkBytesFnMsgPullDataFnBindFnXdpAdjustTailFnSkbGetXfrmStateFnGetStackFnSkbLoadBytesRelativeFnFibLookupFnSockHashUpdateFnMsgRedirectHashFnSkRedirectHashFnLwtPushEncapFnLwtSeg6StoreBytesFnLwtSeg6AdjustSrhFnLwtSeg6ActionFnRcRepeatFnRcKeydownFnSkbCgroupIdFnGetCurrentCgroupIdFnGetLocalStorageFnSkSelectReuseportFnSkbAncestorCgroupIdFnSkLookupTcpFnSkLookupUdpFnSkReleaseFnMapPushElemFnMapPopElemFnMapPeekElemFnMsgPushDataFnMsgPopDataFnRcPointerRelFnSpinLockFnSpinUnlockFnSkFullsockFnTcpSockFnSkbEcnSetCeFnGetListenerSockFnSkcLookupTcpFnTcpCheckSyncookieFnSysctlGetNameFnSysctlGetCurrentValueFnSysctlGetNewValueFnSysctlSetNewValueFnStrtolFnStrtoulFnSkStorageGetFnSkStorageDeleteFnSendSignalFnTcpGenSyncookieFnSkbOutputFnProbeReadUserFnProbeReadKernelFnProbeReadUserStrFnProbeReadKernelStrFnTcpSendAckFnSendSignalThreadFnJiffies64FnReadBranchRecordsFnGetNsCurrentPidTgidFnXdpOutputFnGetNetnsCookieFnGetCurrentAncestorCgroupIdFnSkAssignFnKtimeGetBootNsFnSeqPrintfFnSeqWriteFnSkCgroupIdFnSkAncestorCgroupIdFnRingbufOutputFnRingbufReserveFnRingbufSubmitFnRingbufDiscardFnRingbufQueryFnCsumLevelFnSkcToTcp6SockFnSkcToTcpSockFnSkcToTcpTimewaitSockFnSkcToTcpRequestSockFnSkcToUdp6SockFnGetTaskStackFnLoadHdrOptFnStoreHdrOptFnReserveHdrOptFnInodeStorageGetFnInodeStorageDeleteFnDPathFnCopyFromUserFnSnprintfBtfFnSeqPrintfBtfFnSkbCgroupClassidFnRedirectNeighFnPerCpuPtrFnThisCpuPtrFnRedirectPeerFnTaskStorageGetFnTaskStorageDeleteFnGetCurrentTaskBtfFnBprmOptsSetFnKtimeGetCoarseNsFnImaInodeHashFnSockFromFile"
|
||||
|
||||
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}
|
||||
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}
|
||||
|
||||
func (i BuiltinFunc) String() string {
|
||||
if i < 0 || i >= BuiltinFunc(len(_BuiltinFunc_index)-1) {
|
||||
|
36
src/runtime/vendor/github.com/cilium/ebpf/asm/instruction.go
generated
vendored
36
src/runtime/vendor/github.com/cilium/ebpf/asm/instruction.go
generated
vendored
@ -57,7 +57,7 @@ func (ins *Instruction) Unmarshal(r io.Reader, bo binary.ByteOrder) (uint64, err
|
||||
return 0, fmt.Errorf("can't unmarshal registers: %s", err)
|
||||
}
|
||||
|
||||
if !bi.OpCode.isDWordLoad() {
|
||||
if !bi.OpCode.IsDWordLoad() {
|
||||
return InstructionSize, nil
|
||||
}
|
||||
|
||||
@ -80,7 +80,7 @@ func (ins Instruction) Marshal(w io.Writer, bo binary.ByteOrder) (uint64, error)
|
||||
return 0, errors.New("invalid opcode")
|
||||
}
|
||||
|
||||
isDWordLoad := ins.OpCode.isDWordLoad()
|
||||
isDWordLoad := ins.OpCode.IsDWordLoad()
|
||||
|
||||
cons := int32(ins.Constant)
|
||||
if isDWordLoad {
|
||||
@ -123,7 +123,7 @@ func (ins Instruction) Marshal(w io.Writer, bo binary.ByteOrder) (uint64, error)
|
||||
//
|
||||
// Returns an error if the instruction doesn't load a map.
|
||||
func (ins *Instruction) RewriteMapPtr(fd int) error {
|
||||
if !ins.OpCode.isDWordLoad() {
|
||||
if !ins.OpCode.IsDWordLoad() {
|
||||
return fmt.Errorf("%s is not a 64 bit load", ins.OpCode)
|
||||
}
|
||||
|
||||
@ -138,15 +138,19 @@ func (ins *Instruction) RewriteMapPtr(fd int) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ins *Instruction) mapPtr() uint32 {
|
||||
return uint32(uint64(ins.Constant) & math.MaxUint32)
|
||||
// MapPtr returns the map fd for this instruction.
|
||||
//
|
||||
// The result is undefined if the instruction is not a load from a map,
|
||||
// see IsLoadFromMap.
|
||||
func (ins *Instruction) MapPtr() int {
|
||||
return int(int32(uint64(ins.Constant) & math.MaxUint32))
|
||||
}
|
||||
|
||||
// RewriteMapOffset changes the offset of a direct load from a map.
|
||||
//
|
||||
// Returns an error if the instruction is not a direct load.
|
||||
func (ins *Instruction) RewriteMapOffset(offset uint32) error {
|
||||
if !ins.OpCode.isDWordLoad() {
|
||||
if !ins.OpCode.IsDWordLoad() {
|
||||
return fmt.Errorf("%s is not a 64 bit load", ins.OpCode)
|
||||
}
|
||||
|
||||
@ -163,10 +167,10 @@ func (ins *Instruction) mapOffset() uint32 {
|
||||
return uint32(uint64(ins.Constant) >> 32)
|
||||
}
|
||||
|
||||
// isLoadFromMap returns true if the instruction loads from a map.
|
||||
// IsLoadFromMap returns true if the instruction loads from a map.
|
||||
//
|
||||
// This covers both loading the map pointer and direct map value loads.
|
||||
func (ins *Instruction) isLoadFromMap() bool {
|
||||
func (ins *Instruction) IsLoadFromMap() bool {
|
||||
return ins.OpCode == LoadImmOp(DWord) && (ins.Src == PseudoMapFD || ins.Src == PseudoMapValue)
|
||||
}
|
||||
|
||||
@ -177,6 +181,12 @@ func (ins *Instruction) IsFunctionCall() bool {
|
||||
return ins.OpCode.JumpOp() == Call && ins.Src == PseudoCall
|
||||
}
|
||||
|
||||
// IsConstantLoad returns true if the instruction loads a constant of the
|
||||
// given size.
|
||||
func (ins *Instruction) IsConstantLoad(size Size) bool {
|
||||
return ins.OpCode == LoadImmOp(size) && ins.Src == R0 && ins.Offset == 0
|
||||
}
|
||||
|
||||
// Format implements fmt.Formatter.
|
||||
func (ins Instruction) Format(f fmt.State, c rune) {
|
||||
if c != 'v' {
|
||||
@ -197,8 +207,8 @@ func (ins Instruction) Format(f fmt.State, c rune) {
|
||||
return
|
||||
}
|
||||
|
||||
if ins.isLoadFromMap() {
|
||||
fd := int32(ins.mapPtr())
|
||||
if ins.IsLoadFromMap() {
|
||||
fd := ins.MapPtr()
|
||||
switch ins.Src {
|
||||
case PseudoMapFD:
|
||||
fmt.Fprintf(f, "LoadMapPtr dst: %s fd: %d", ins.Dst, fd)
|
||||
@ -337,7 +347,7 @@ func (insns Instructions) ReferenceOffsets() map[string][]int {
|
||||
// You can control indentation of symbols by
|
||||
// specifying a width. Setting a precision controls the indentation of
|
||||
// instructions.
|
||||
// The default character is a tab, which can be overriden by specifying
|
||||
// The default character is a tab, which can be overridden by specifying
|
||||
// the ' ' space flag.
|
||||
func (insns Instructions) Format(f fmt.State, c rune) {
|
||||
if c != 's' && c != 'v' {
|
||||
@ -382,8 +392,6 @@ func (insns Instructions) Format(f fmt.State, c rune) {
|
||||
}
|
||||
fmt.Fprintf(f, "%s%*d: %v\n", indent, offsetWidth, iter.Offset, iter.Ins)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// Marshal encodes a BPF program into the kernel format.
|
||||
@ -405,7 +413,7 @@ func (insns Instructions) Marshal(w io.Writer, bo binary.ByteOrder) error {
|
||||
func (insns Instructions) Tag(bo binary.ByteOrder) (string, error) {
|
||||
h := sha1.New()
|
||||
for i, ins := range insns {
|
||||
if ins.isLoadFromMap() {
|
||||
if ins.IsLoadFromMap() {
|
||||
ins.Constant = 0
|
||||
}
|
||||
_, err := ins.Marshal(h, bo)
|
||||
|
2
src/runtime/vendor/github.com/cilium/ebpf/asm/load_store.go
generated
vendored
2
src/runtime/vendor/github.com/cilium/ebpf/asm/load_store.go
generated
vendored
@ -111,7 +111,7 @@ func LoadMapPtr(dst Register, fd int) Instruction {
|
||||
OpCode: LoadImmOp(DWord),
|
||||
Dst: dst,
|
||||
Src: PseudoMapFD,
|
||||
Constant: int64(fd),
|
||||
Constant: int64(uint32(fd)),
|
||||
}
|
||||
}
|
||||
|
||||
|
4
src/runtime/vendor/github.com/cilium/ebpf/asm/opcode.go
generated
vendored
4
src/runtime/vendor/github.com/cilium/ebpf/asm/opcode.go
generated
vendored
@ -69,13 +69,13 @@ const InvalidOpCode OpCode = 0xff
|
||||
// rawInstructions returns the number of BPF instructions required
|
||||
// to encode this opcode.
|
||||
func (op OpCode) rawInstructions() int {
|
||||
if op.isDWordLoad() {
|
||||
if op.IsDWordLoad() {
|
||||
return 2
|
||||
}
|
||||
return 1
|
||||
}
|
||||
|
||||
func (op OpCode) isDWordLoad() bool {
|
||||
func (op OpCode) IsDWordLoad() bool {
|
||||
return op == LoadImmOp(DWord)
|
||||
}
|
||||
|
||||
|
59
src/runtime/vendor/github.com/cilium/ebpf/collection.go
generated
vendored
59
src/runtime/vendor/github.com/cilium/ebpf/collection.go
generated
vendored
@ -3,6 +3,7 @@ package ebpf
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"math"
|
||||
"reflect"
|
||||
"strings"
|
||||
@ -89,8 +90,8 @@ func (cs *CollectionSpec) RewriteMaps(maps map[string]*Map) error {
|
||||
//
|
||||
// The constant must be defined like so in the C program:
|
||||
//
|
||||
// static volatile const type foobar;
|
||||
// static volatile const type foobar = default;
|
||||
// volatile const type foobar;
|
||||
// volatile const type foobar = default;
|
||||
//
|
||||
// Replacement values must be of the same length as the C sizeof(type).
|
||||
// If necessary, they are marshalled according to the same rules as
|
||||
@ -269,11 +270,21 @@ func NewCollectionWithOptions(spec *CollectionSpec, opts CollectionOptions) (*Co
|
||||
}, nil
|
||||
}
|
||||
|
||||
type btfHandleCache map[*btf.Spec]*btf.Handle
|
||||
type handleCache struct {
|
||||
btfHandles map[*btf.Spec]*btf.Handle
|
||||
btfSpecs map[io.ReaderAt]*btf.Spec
|
||||
}
|
||||
|
||||
func (btfs btfHandleCache) load(spec *btf.Spec) (*btf.Handle, error) {
|
||||
if btfs[spec] != nil {
|
||||
return btfs[spec], nil
|
||||
func newHandleCache() *handleCache {
|
||||
return &handleCache{
|
||||
btfHandles: make(map[*btf.Spec]*btf.Handle),
|
||||
btfSpecs: make(map[io.ReaderAt]*btf.Spec),
|
||||
}
|
||||
}
|
||||
|
||||
func (hc handleCache) btfHandle(spec *btf.Spec) (*btf.Handle, error) {
|
||||
if hc.btfHandles[spec] != nil {
|
||||
return hc.btfHandles[spec], nil
|
||||
}
|
||||
|
||||
handle, err := btf.NewHandle(spec)
|
||||
@ -281,14 +292,30 @@ func (btfs btfHandleCache) load(spec *btf.Spec) (*btf.Handle, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
btfs[spec] = handle
|
||||
hc.btfHandles[spec] = handle
|
||||
return handle, nil
|
||||
}
|
||||
|
||||
func (btfs btfHandleCache) close() {
|
||||
for _, handle := range btfs {
|
||||
func (hc handleCache) btfSpec(rd io.ReaderAt) (*btf.Spec, error) {
|
||||
if hc.btfSpecs[rd] != nil {
|
||||
return hc.btfSpecs[rd], nil
|
||||
}
|
||||
|
||||
spec, err := btf.LoadSpecFromReader(rd)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
hc.btfSpecs[rd] = spec
|
||||
return spec, nil
|
||||
}
|
||||
|
||||
func (hc handleCache) close() {
|
||||
for _, handle := range hc.btfHandles {
|
||||
handle.Close()
|
||||
}
|
||||
hc.btfHandles = nil
|
||||
hc.btfSpecs = nil
|
||||
}
|
||||
|
||||
func lazyLoadCollection(coll *CollectionSpec, opts *CollectionOptions) (
|
||||
@ -300,12 +327,12 @@ func lazyLoadCollection(coll *CollectionSpec, opts *CollectionOptions) (
|
||||
var (
|
||||
maps = make(map[string]*Map)
|
||||
progs = make(map[string]*Program)
|
||||
btfs = make(btfHandleCache)
|
||||
handles = newHandleCache()
|
||||
skipMapsAndProgs = false
|
||||
)
|
||||
|
||||
cleanup = func() {
|
||||
btfs.close()
|
||||
handles.close()
|
||||
|
||||
if skipMapsAndProgs {
|
||||
return
|
||||
@ -335,7 +362,7 @@ func lazyLoadCollection(coll *CollectionSpec, opts *CollectionOptions) (
|
||||
return nil, fmt.Errorf("missing map %s", mapName)
|
||||
}
|
||||
|
||||
m, err := newMapWithOptions(mapSpec, opts.Maps, btfs)
|
||||
m, err := newMapWithOptions(mapSpec, opts.Maps, handles)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("map %s: %w", mapName, err)
|
||||
}
|
||||
@ -360,7 +387,7 @@ func lazyLoadCollection(coll *CollectionSpec, opts *CollectionOptions) (
|
||||
for i := range progSpec.Instructions {
|
||||
ins := &progSpec.Instructions[i]
|
||||
|
||||
if ins.OpCode != asm.LoadImmOp(asm.DWord) || ins.Reference == "" {
|
||||
if !ins.IsLoadFromMap() || ins.Reference == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
@ -372,7 +399,7 @@ func lazyLoadCollection(coll *CollectionSpec, opts *CollectionOptions) (
|
||||
|
||||
m, err := loadMap(ins.Reference)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("program %s: %s", progName, err)
|
||||
return nil, fmt.Errorf("program %s: %w", progName, err)
|
||||
}
|
||||
|
||||
fd := m.FD()
|
||||
@ -384,7 +411,7 @@ func lazyLoadCollection(coll *CollectionSpec, opts *CollectionOptions) (
|
||||
}
|
||||
}
|
||||
|
||||
prog, err := newProgramWithOptions(progSpec, opts.Programs, btfs)
|
||||
prog, err := newProgramWithOptions(progSpec, opts.Programs, handles)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("program %s: %w", progName, err)
|
||||
}
|
||||
@ -534,7 +561,7 @@ func assignValues(to interface{}, valueOf func(reflect.Type, string) (reflect.Va
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return fmt.Errorf("field %s: %s", field.Name, err)
|
||||
return fmt.Errorf("field %s: %w", field.Name, err)
|
||||
}
|
||||
}
|
||||
|
||||
|
181
src/runtime/vendor/github.com/cilium/ebpf/elf_reader.go
generated
vendored
181
src/runtime/vendor/github.com/cilium/ebpf/elf_reader.go
generated
vendored
@ -96,7 +96,7 @@ func LoadCollectionSpecFromReader(rd io.ReaderAt) (*CollectionSpec, error) {
|
||||
}
|
||||
|
||||
btfSpec, err := btf.LoadSpecFromReader(rd)
|
||||
if err != nil {
|
||||
if err != nil && !errors.Is(err, btf.ErrNotFound) {
|
||||
return nil, fmt.Errorf("load BTF: %w", err)
|
||||
}
|
||||
|
||||
@ -159,7 +159,7 @@ func LoadCollectionSpecFromReader(rd io.ReaderAt) (*CollectionSpec, error) {
|
||||
}
|
||||
|
||||
if target.Flags&elf.SHF_STRINGS > 0 {
|
||||
return nil, fmt.Errorf("section %q: string %q is not stack allocated: %w", section.Name, rel.Name, ErrNotSupported)
|
||||
return nil, fmt.Errorf("section %q: string is not stack allocated: %w", section.Name, ErrNotSupported)
|
||||
}
|
||||
|
||||
target.references++
|
||||
@ -272,11 +272,12 @@ func (ec *elfCode) loadPrograms() (map[string]*ProgramSpec, error) {
|
||||
return nil, fmt.Errorf("program %s: %w", funcSym.Name, err)
|
||||
}
|
||||
|
||||
progType, attachType, attachTo := getProgType(sec.Name)
|
||||
progType, attachType, progFlags, attachTo := getProgType(sec.Name)
|
||||
|
||||
spec := &ProgramSpec{
|
||||
Name: funcSym.Name,
|
||||
Type: progType,
|
||||
Flags: progFlags,
|
||||
AttachType: attachType,
|
||||
AttachTo: attachTo,
|
||||
License: ec.license,
|
||||
@ -373,17 +374,25 @@ func (ec *elfCode) relocateInstruction(ins *asm.Instruction, rel elf.Symbol) err
|
||||
}
|
||||
|
||||
case dataSection:
|
||||
var offset uint32
|
||||
switch typ {
|
||||
case elf.STT_SECTION:
|
||||
if bind != elf.STB_LOCAL {
|
||||
return fmt.Errorf("direct load: %s: unsupported relocation %s", name, bind)
|
||||
}
|
||||
|
||||
// This is really a reference to a static symbol, which clang doesn't
|
||||
// emit a symbol table entry for. Instead it encodes the offset in
|
||||
// the instruction itself.
|
||||
offset = uint32(uint64(ins.Constant))
|
||||
|
||||
case elf.STT_OBJECT:
|
||||
if bind != elf.STB_GLOBAL {
|
||||
return fmt.Errorf("direct load: %s: unsupported relocation %s", name, bind)
|
||||
}
|
||||
|
||||
offset = uint32(rel.Value)
|
||||
|
||||
default:
|
||||
return fmt.Errorf("incorrect relocation type %v for direct map load", typ)
|
||||
}
|
||||
@ -393,10 +402,8 @@ func (ec *elfCode) relocateInstruction(ins *asm.Instruction, rel elf.Symbol) err
|
||||
// it's not clear how to encode that into Instruction.
|
||||
name = target.Name
|
||||
|
||||
// For some reason, clang encodes the offset of the symbol its
|
||||
// section in the first basic BPF instruction, while the kernel
|
||||
// expects it in the second one.
|
||||
ins.Constant <<= 32
|
||||
// The kernel expects the offset in the second basic BPF instruction.
|
||||
ins.Constant = int64(uint64(offset) << 32)
|
||||
ins.Src = asm.PseudoMapValue
|
||||
|
||||
// Mark the instruction as needing an update when creating the
|
||||
@ -490,33 +497,38 @@ func (ec *elfCode) loadMaps(maps map[string]*MapSpec) error {
|
||||
return fmt.Errorf("section %s: missing symbol for map at offset %d", sec.Name, offset)
|
||||
}
|
||||
|
||||
if maps[mapSym.Name] != nil {
|
||||
mapName := mapSym.Name
|
||||
if maps[mapName] != nil {
|
||||
return fmt.Errorf("section %v: map %v already exists", sec.Name, mapSym)
|
||||
}
|
||||
|
||||
lr := io.LimitReader(r, int64(size))
|
||||
|
||||
spec := MapSpec{
|
||||
Name: SanitizeName(mapSym.Name, -1),
|
||||
Name: SanitizeName(mapName, -1),
|
||||
}
|
||||
switch {
|
||||
case binary.Read(lr, ec.ByteOrder, &spec.Type) != nil:
|
||||
return fmt.Errorf("map %v: missing type", mapSym)
|
||||
return fmt.Errorf("map %s: missing type", mapName)
|
||||
case binary.Read(lr, ec.ByteOrder, &spec.KeySize) != nil:
|
||||
return fmt.Errorf("map %v: missing key size", mapSym)
|
||||
return fmt.Errorf("map %s: missing key size", mapName)
|
||||
case binary.Read(lr, ec.ByteOrder, &spec.ValueSize) != nil:
|
||||
return fmt.Errorf("map %v: missing value size", mapSym)
|
||||
return fmt.Errorf("map %s: missing value size", mapName)
|
||||
case binary.Read(lr, ec.ByteOrder, &spec.MaxEntries) != nil:
|
||||
return fmt.Errorf("map %v: missing max entries", mapSym)
|
||||
return fmt.Errorf("map %s: missing max entries", mapName)
|
||||
case binary.Read(lr, ec.ByteOrder, &spec.Flags) != nil:
|
||||
return fmt.Errorf("map %v: missing flags", mapSym)
|
||||
return fmt.Errorf("map %s: missing flags", mapName)
|
||||
}
|
||||
|
||||
if _, err := io.Copy(internal.DiscardZeroes{}, lr); err != nil {
|
||||
return fmt.Errorf("map %v: unknown and non-zero fields in definition", mapSym)
|
||||
return fmt.Errorf("map %s: unknown and non-zero fields in definition", mapName)
|
||||
}
|
||||
|
||||
maps[mapSym.Name] = &spec
|
||||
if err := spec.clampPerfEventArraySize(); err != nil {
|
||||
return fmt.Errorf("map %s: %w", mapName, err)
|
||||
}
|
||||
|
||||
maps[mapName] = &spec
|
||||
}
|
||||
}
|
||||
|
||||
@ -533,28 +545,25 @@ func (ec *elfCode) loadBTFMaps(maps map[string]*MapSpec) error {
|
||||
return fmt.Errorf("missing BTF")
|
||||
}
|
||||
|
||||
if len(sec.symbols) == 0 {
|
||||
return fmt.Errorf("section %v: no symbols", sec.Name)
|
||||
}
|
||||
|
||||
_, err := io.Copy(internal.DiscardZeroes{}, bufio.NewReader(sec.Open()))
|
||||
if err != nil {
|
||||
return fmt.Errorf("section %v: initializing BTF map definitions: %w", sec.Name, internal.ErrNotSupported)
|
||||
}
|
||||
|
||||
for _, sym := range sec.symbols {
|
||||
name := sym.Name
|
||||
if maps[name] != nil {
|
||||
return fmt.Errorf("section %v: map %v already exists", sec.Name, sym)
|
||||
}
|
||||
var ds btf.Datasec
|
||||
if err := ec.btf.FindType(sec.Name, &ds); err != nil {
|
||||
return fmt.Errorf("cannot find section '%s' in BTF: %w", sec.Name, err)
|
||||
}
|
||||
|
||||
// A global Var is created by declaring a struct with a 'structure variable',
|
||||
// as is common in eBPF C to declare eBPF maps. For example,
|
||||
// `struct { ... } map_name ...;` emits a global variable `map_name`
|
||||
// with the type of said struct (which can be anonymous).
|
||||
var v btf.Var
|
||||
if err := ec.btf.FindType(name, &v); err != nil {
|
||||
return fmt.Errorf("cannot find global variable '%s' in BTF: %w", name, err)
|
||||
for _, vs := range ds.Vars {
|
||||
v, ok := vs.Type.(*btf.Var)
|
||||
if !ok {
|
||||
return fmt.Errorf("section %v: unexpected type %s", sec.Name, vs.Type)
|
||||
}
|
||||
name := string(v.Name)
|
||||
|
||||
if maps[name] != nil {
|
||||
return fmt.Errorf("section %v: map %s already exists", sec.Name, name)
|
||||
}
|
||||
|
||||
mapStruct, ok := v.Type.(*btf.Struct)
|
||||
@ -567,6 +576,10 @@ func (ec *elfCode) loadBTFMaps(maps map[string]*MapSpec) error {
|
||||
return fmt.Errorf("map %v: %w", name, err)
|
||||
}
|
||||
|
||||
if err := mapSpec.clampPerfEventArraySize(); err != nil {
|
||||
return fmt.Errorf("map %v: %w", name, err)
|
||||
}
|
||||
|
||||
maps[name] = mapSpec
|
||||
}
|
||||
}
|
||||
@ -834,56 +847,66 @@ func (ec *elfCode) loadDataSections(maps map[string]*MapSpec) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func getProgType(sectionName string) (ProgramType, AttachType, string) {
|
||||
func getProgType(sectionName string) (ProgramType, AttachType, uint32, string) {
|
||||
types := map[string]struct {
|
||||
progType ProgramType
|
||||
attachType AttachType
|
||||
progFlags uint32
|
||||
}{
|
||||
// From https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/tools/lib/bpf/libbpf.c
|
||||
"socket": {SocketFilter, AttachNone},
|
||||
"seccomp": {SocketFilter, AttachNone},
|
||||
"kprobe/": {Kprobe, AttachNone},
|
||||
"uprobe/": {Kprobe, AttachNone},
|
||||
"kretprobe/": {Kprobe, AttachNone},
|
||||
"uretprobe/": {Kprobe, AttachNone},
|
||||
"tracepoint/": {TracePoint, AttachNone},
|
||||
"raw_tracepoint/": {RawTracepoint, AttachNone},
|
||||
"xdp": {XDP, AttachNone},
|
||||
"perf_event": {PerfEvent, AttachNone},
|
||||
"lwt_in": {LWTIn, AttachNone},
|
||||
"lwt_out": {LWTOut, AttachNone},
|
||||
"lwt_xmit": {LWTXmit, AttachNone},
|
||||
"lwt_seg6local": {LWTSeg6Local, AttachNone},
|
||||
"sockops": {SockOps, AttachCGroupSockOps},
|
||||
"sk_skb/stream_parser": {SkSKB, AttachSkSKBStreamParser},
|
||||
"sk_skb/stream_verdict": {SkSKB, AttachSkSKBStreamParser},
|
||||
"sk_msg": {SkMsg, AttachSkSKBStreamVerdict},
|
||||
"lirc_mode2": {LircMode2, AttachLircMode2},
|
||||
"flow_dissector": {FlowDissector, AttachFlowDissector},
|
||||
"iter/": {Tracing, AttachTraceIter},
|
||||
"sk_lookup/": {SkLookup, AttachSkLookup},
|
||||
"lsm/": {LSM, AttachLSMMac},
|
||||
"socket": {SocketFilter, AttachNone, 0},
|
||||
"seccomp": {SocketFilter, AttachNone, 0},
|
||||
"kprobe/": {Kprobe, AttachNone, 0},
|
||||
"uprobe/": {Kprobe, AttachNone, 0},
|
||||
"kretprobe/": {Kprobe, AttachNone, 0},
|
||||
"uretprobe/": {Kprobe, AttachNone, 0},
|
||||
"tracepoint/": {TracePoint, AttachNone, 0},
|
||||
"raw_tracepoint/": {RawTracepoint, AttachNone, 0},
|
||||
"raw_tp/": {RawTracepoint, AttachNone, 0},
|
||||
"tp_btf/": {Tracing, AttachTraceRawTp, 0},
|
||||
"xdp": {XDP, AttachNone, 0},
|
||||
"perf_event": {PerfEvent, AttachNone, 0},
|
||||
"lwt_in": {LWTIn, AttachNone, 0},
|
||||
"lwt_out": {LWTOut, AttachNone, 0},
|
||||
"lwt_xmit": {LWTXmit, AttachNone, 0},
|
||||
"lwt_seg6local": {LWTSeg6Local, AttachNone, 0},
|
||||
"sockops": {SockOps, AttachCGroupSockOps, 0},
|
||||
"sk_skb/stream_parser": {SkSKB, AttachSkSKBStreamParser, 0},
|
||||
"sk_skb/stream_verdict": {SkSKB, AttachSkSKBStreamParser, 0},
|
||||
"sk_msg": {SkMsg, AttachSkSKBStreamVerdict, 0},
|
||||
"lirc_mode2": {LircMode2, AttachLircMode2, 0},
|
||||
"flow_dissector": {FlowDissector, AttachFlowDissector, 0},
|
||||
"iter/": {Tracing, AttachTraceIter, 0},
|
||||
"fentry/": {Tracing, AttachTraceFEntry, 0},
|
||||
"fmod_ret/": {Tracing, AttachModifyReturn, 0},
|
||||
"fexit/": {Tracing, AttachTraceFExit, 0},
|
||||
"fentry.s/": {Tracing, AttachTraceFEntry, unix.BPF_F_SLEEPABLE},
|
||||
"fmod_ret.s/": {Tracing, AttachModifyReturn, unix.BPF_F_SLEEPABLE},
|
||||
"fexit.s/": {Tracing, AttachTraceFExit, unix.BPF_F_SLEEPABLE},
|
||||
"sk_lookup/": {SkLookup, AttachSkLookup, 0},
|
||||
"lsm/": {LSM, AttachLSMMac, 0},
|
||||
"lsm.s/": {LSM, AttachLSMMac, unix.BPF_F_SLEEPABLE},
|
||||
|
||||
"cgroup_skb/ingress": {CGroupSKB, AttachCGroupInetIngress},
|
||||
"cgroup_skb/egress": {CGroupSKB, AttachCGroupInetEgress},
|
||||
"cgroup/dev": {CGroupDevice, AttachCGroupDevice},
|
||||
"cgroup/skb": {CGroupSKB, AttachNone},
|
||||
"cgroup/sock": {CGroupSock, AttachCGroupInetSockCreate},
|
||||
"cgroup/post_bind4": {CGroupSock, AttachCGroupInet4PostBind},
|
||||
"cgroup/post_bind6": {CGroupSock, AttachCGroupInet6PostBind},
|
||||
"cgroup/bind4": {CGroupSockAddr, AttachCGroupInet4Bind},
|
||||
"cgroup/bind6": {CGroupSockAddr, AttachCGroupInet6Bind},
|
||||
"cgroup/connect4": {CGroupSockAddr, AttachCGroupInet4Connect},
|
||||
"cgroup/connect6": {CGroupSockAddr, AttachCGroupInet6Connect},
|
||||
"cgroup/sendmsg4": {CGroupSockAddr, AttachCGroupUDP4Sendmsg},
|
||||
"cgroup/sendmsg6": {CGroupSockAddr, AttachCGroupUDP6Sendmsg},
|
||||
"cgroup/recvmsg4": {CGroupSockAddr, AttachCGroupUDP4Recvmsg},
|
||||
"cgroup/recvmsg6": {CGroupSockAddr, AttachCGroupUDP6Recvmsg},
|
||||
"cgroup/sysctl": {CGroupSysctl, AttachCGroupSysctl},
|
||||
"cgroup/getsockopt": {CGroupSockopt, AttachCGroupGetsockopt},
|
||||
"cgroup/setsockopt": {CGroupSockopt, AttachCGroupSetsockopt},
|
||||
"classifier": {SchedCLS, AttachNone},
|
||||
"action": {SchedACT, AttachNone},
|
||||
"cgroup_skb/ingress": {CGroupSKB, AttachCGroupInetIngress, 0},
|
||||
"cgroup_skb/egress": {CGroupSKB, AttachCGroupInetEgress, 0},
|
||||
"cgroup/dev": {CGroupDevice, AttachCGroupDevice, 0},
|
||||
"cgroup/skb": {CGroupSKB, AttachNone, 0},
|
||||
"cgroup/sock": {CGroupSock, AttachCGroupInetSockCreate, 0},
|
||||
"cgroup/post_bind4": {CGroupSock, AttachCGroupInet4PostBind, 0},
|
||||
"cgroup/post_bind6": {CGroupSock, AttachCGroupInet6PostBind, 0},
|
||||
"cgroup/bind4": {CGroupSockAddr, AttachCGroupInet4Bind, 0},
|
||||
"cgroup/bind6": {CGroupSockAddr, AttachCGroupInet6Bind, 0},
|
||||
"cgroup/connect4": {CGroupSockAddr, AttachCGroupInet4Connect, 0},
|
||||
"cgroup/connect6": {CGroupSockAddr, AttachCGroupInet6Connect, 0},
|
||||
"cgroup/sendmsg4": {CGroupSockAddr, AttachCGroupUDP4Sendmsg, 0},
|
||||
"cgroup/sendmsg6": {CGroupSockAddr, AttachCGroupUDP6Sendmsg, 0},
|
||||
"cgroup/recvmsg4": {CGroupSockAddr, AttachCGroupUDP4Recvmsg, 0},
|
||||
"cgroup/recvmsg6": {CGroupSockAddr, AttachCGroupUDP6Recvmsg, 0},
|
||||
"cgroup/sysctl": {CGroupSysctl, AttachCGroupSysctl, 0},
|
||||
"cgroup/getsockopt": {CGroupSockopt, AttachCGroupGetsockopt, 0},
|
||||
"cgroup/setsockopt": {CGroupSockopt, AttachCGroupSetsockopt, 0},
|
||||
"classifier": {SchedCLS, AttachNone, 0},
|
||||
"action": {SchedACT, AttachNone, 0},
|
||||
}
|
||||
|
||||
for prefix, t := range types {
|
||||
@ -892,13 +915,13 @@ func getProgType(sectionName string) (ProgramType, AttachType, string) {
|
||||
}
|
||||
|
||||
if !strings.HasSuffix(prefix, "/") {
|
||||
return t.progType, t.attachType, ""
|
||||
return t.progType, t.attachType, t.progFlags, ""
|
||||
}
|
||||
|
||||
return t.progType, t.attachType, sectionName[len(prefix):]
|
||||
return t.progType, t.attachType, t.progFlags, sectionName[len(prefix):]
|
||||
}
|
||||
|
||||
return UnspecifiedProgram, AttachNone, ""
|
||||
return UnspecifiedProgram, AttachNone, 0, ""
|
||||
}
|
||||
|
||||
func (ec *elfCode) loadRelocations(sec *elf.Section, symbols []elf.Symbol) (map[uint64]elf.Symbol, error) {
|
||||
|
32
src/runtime/vendor/github.com/cilium/ebpf/internal/btf/btf.go
generated
vendored
32
src/runtime/vendor/github.com/cilium/ebpf/internal/btf/btf.go
generated
vendored
@ -35,7 +35,7 @@ type Spec struct {
|
||||
namedTypes map[string][]namedType
|
||||
funcInfos map[string]extInfo
|
||||
lineInfos map[string]extInfo
|
||||
coreRelos map[string]bpfCoreRelos
|
||||
coreRelos map[string]coreRelos
|
||||
byteOrder binary.ByteOrder
|
||||
}
|
||||
|
||||
@ -53,7 +53,7 @@ type btfHeader struct {
|
||||
|
||||
// LoadSpecFromReader reads BTF sections from an ELF.
|
||||
//
|
||||
// Returns a nil Spec and no error if no BTF was present.
|
||||
// Returns ErrNotFound if the reader contains no BTF.
|
||||
func LoadSpecFromReader(rd io.ReaderAt) (*Spec, error) {
|
||||
file, err := internal.NewSafeELFFile(rd)
|
||||
if err != nil {
|
||||
@ -67,7 +67,7 @@ func LoadSpecFromReader(rd io.ReaderAt) (*Spec, error) {
|
||||
}
|
||||
|
||||
if btfSection == nil {
|
||||
return nil, nil
|
||||
return nil, fmt.Errorf("btf: %w", ErrNotFound)
|
||||
}
|
||||
|
||||
symbols, err := file.Symbols()
|
||||
@ -377,7 +377,7 @@ func (s *Spec) marshal(opts marshalOpts) ([]byte, error) {
|
||||
for _, raw := range s.rawTypes {
|
||||
switch {
|
||||
case opts.StripFuncLinkage && raw.Kind() == kindFunc:
|
||||
raw.SetLinkage(linkageStatic)
|
||||
raw.SetLinkage(StaticFunc)
|
||||
}
|
||||
|
||||
if err := raw.Marshal(&buf, opts.ByteOrder); err != nil {
|
||||
@ -438,13 +438,13 @@ func (s *Spec) Program(name string, length uint64) (*Program, error) {
|
||||
|
||||
funcInfos, funcOK := s.funcInfos[name]
|
||||
lineInfos, lineOK := s.lineInfos[name]
|
||||
coreRelos, coreOK := s.coreRelos[name]
|
||||
relos, coreOK := s.coreRelos[name]
|
||||
|
||||
if !funcOK && !lineOK && !coreOK {
|
||||
return nil, fmt.Errorf("no extended BTF info for section %s", name)
|
||||
}
|
||||
|
||||
return &Program{s, length, funcInfos, lineInfos, coreRelos}, nil
|
||||
return &Program{s, length, funcInfos, lineInfos, relos}, nil
|
||||
}
|
||||
|
||||
// Datasec returns the BTF required to create maps which represent data sections.
|
||||
@ -491,7 +491,8 @@ func (s *Spec) FindType(name string, typ Type) error {
|
||||
return fmt.Errorf("type %s: %w", name, ErrNotFound)
|
||||
}
|
||||
|
||||
value := reflect.Indirect(reflect.ValueOf(copyType(candidate)))
|
||||
cpy, _ := copyType(candidate, nil)
|
||||
value := reflect.Indirect(reflect.ValueOf(cpy))
|
||||
reflect.Indirect(reflect.ValueOf(typ)).Set(value)
|
||||
return nil
|
||||
}
|
||||
@ -606,7 +607,7 @@ type Program struct {
|
||||
spec *Spec
|
||||
length uint64
|
||||
funcInfos, lineInfos extInfo
|
||||
coreRelos bpfCoreRelos
|
||||
coreRelos coreRelos
|
||||
}
|
||||
|
||||
// ProgramSpec returns the Spec needed for loading function and line infos into the kernel.
|
||||
@ -665,16 +666,23 @@ func ProgramLineInfos(s *Program) (recordSize uint32, bytes []byte, err error) {
|
||||
return s.lineInfos.recordSize, bytes, nil
|
||||
}
|
||||
|
||||
// ProgramRelocations returns the CO-RE relocations required to adjust the
|
||||
// program to the target.
|
||||
// ProgramFixups 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
|
||||
// of package ebpf.
|
||||
func ProgramRelocations(s *Program, target *Spec) (map[uint64]Relocation, error) {
|
||||
func ProgramFixups(s *Program, target *Spec) (COREFixups, error) {
|
||||
if len(s.coreRelos) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
if target == nil {
|
||||
var err error
|
||||
target, err = LoadKernelSpec()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return coreRelocate(s.spec, target, s.coreRelos)
|
||||
}
|
||||
|
||||
@ -771,7 +779,7 @@ var haveFuncLinkage = internal.FeatureTest("BTF func linkage", "5.6", func() err
|
||||
types.Func.SetKind(kindFunc)
|
||||
types.Func.SizeType = 1 // aka FuncProto
|
||||
types.Func.NameOff = 1
|
||||
types.Func.SetLinkage(linkageGlobal)
|
||||
types.Func.SetLinkage(GlobalFunc)
|
||||
|
||||
btf := marshalBTF(&types, strings, internal.NativeEndian)
|
||||
|
||||
|
27
src/runtime/vendor/github.com/cilium/ebpf/internal/btf/btf_types.go
generated
vendored
27
src/runtime/vendor/github.com/cilium/ebpf/internal/btf/btf_types.go
generated
vendored
@ -6,6 +6,8 @@ import (
|
||||
"io"
|
||||
)
|
||||
|
||||
//go:generate stringer -linecomment -output=btf_types_string.go -type=FuncLinkage,VarLinkage
|
||||
|
||||
// btfKind describes a Type.
|
||||
type btfKind uint8
|
||||
|
||||
@ -31,12 +33,23 @@ const (
|
||||
kindDatasec
|
||||
)
|
||||
|
||||
type btfFuncLinkage uint8
|
||||
// FuncLinkage describes BTF function linkage metadata.
|
||||
type FuncLinkage int
|
||||
|
||||
// Equivalent of enum btf_func_linkage.
|
||||
const (
|
||||
StaticFunc FuncLinkage = iota // static
|
||||
GlobalFunc // global
|
||||
ExternFunc // extern
|
||||
)
|
||||
|
||||
// VarLinkage describes BTF variable linkage metadata.
|
||||
type VarLinkage int
|
||||
|
||||
const (
|
||||
linkageStatic btfFuncLinkage = iota
|
||||
linkageGlobal
|
||||
linkageExtern
|
||||
StaticVar VarLinkage = iota // static
|
||||
GlobalVar // global
|
||||
ExternVar // extern
|
||||
)
|
||||
|
||||
const (
|
||||
@ -142,11 +155,11 @@ func (bt *btfType) KindFlag() bool {
|
||||
return bt.info(btfTypeKindFlagMask, btfTypeKindFlagShift) == 1
|
||||
}
|
||||
|
||||
func (bt *btfType) Linkage() btfFuncLinkage {
|
||||
return btfFuncLinkage(bt.info(btfTypeVlenMask, btfTypeVlenShift))
|
||||
func (bt *btfType) Linkage() FuncLinkage {
|
||||
return FuncLinkage(bt.info(btfTypeVlenMask, btfTypeVlenShift))
|
||||
}
|
||||
|
||||
func (bt *btfType) SetLinkage(linkage btfFuncLinkage) {
|
||||
func (bt *btfType) SetLinkage(linkage FuncLinkage) {
|
||||
bt.setInfo(uint32(linkage), btfTypeVlenMask, btfTypeVlenShift)
|
||||
}
|
||||
|
||||
|
44
src/runtime/vendor/github.com/cilium/ebpf/internal/btf/btf_types_string.go
generated
vendored
Normal file
44
src/runtime/vendor/github.com/cilium/ebpf/internal/btf/btf_types_string.go
generated
vendored
Normal file
@ -0,0 +1,44 @@
|
||||
// Code generated by "stringer -linecomment -output=btf_types_string.go -type=FuncLinkage,VarLinkage"; DO NOT EDIT.
|
||||
|
||||
package btf
|
||||
|
||||
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[StaticFunc-0]
|
||||
_ = x[GlobalFunc-1]
|
||||
_ = x[ExternFunc-2]
|
||||
}
|
||||
|
||||
const _FuncLinkage_name = "staticglobalextern"
|
||||
|
||||
var _FuncLinkage_index = [...]uint8{0, 6, 12, 18}
|
||||
|
||||
func (i FuncLinkage) String() string {
|
||||
if i < 0 || i >= FuncLinkage(len(_FuncLinkage_index)-1) {
|
||||
return "FuncLinkage(" + strconv.FormatInt(int64(i), 10) + ")"
|
||||
}
|
||||
return _FuncLinkage_name[_FuncLinkage_index[i]:_FuncLinkage_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[StaticVar-0]
|
||||
_ = x[GlobalVar-1]
|
||||
_ = x[ExternVar-2]
|
||||
}
|
||||
|
||||
const _VarLinkage_name = "staticglobalextern"
|
||||
|
||||
var _VarLinkage_index = [...]uint8{0, 6, 12, 18}
|
||||
|
||||
func (i VarLinkage) String() string {
|
||||
if i < 0 || i >= VarLinkage(len(_VarLinkage_index)-1) {
|
||||
return "VarLinkage(" + strconv.FormatInt(int64(i), 10) + ")"
|
||||
}
|
||||
return _VarLinkage_name[_VarLinkage_index[i]:_VarLinkage_index[i+1]]
|
||||
}
|
795
src/runtime/vendor/github.com/cilium/ebpf/internal/btf/core.go
generated
vendored
795
src/runtime/vendor/github.com/cilium/ebpf/internal/btf/core.go
generated
vendored
@ -3,43 +3,160 @@ package btf
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"math"
|
||||
"reflect"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/cilium/ebpf/asm"
|
||||
)
|
||||
|
||||
// Code in this file is derived from libbpf, which is available under a BSD
|
||||
// 2-Clause license.
|
||||
|
||||
// Relocation describes a CO-RE relocation.
|
||||
type Relocation struct {
|
||||
Current uint32
|
||||
New uint32
|
||||
// COREFixup is the result of computing a CO-RE relocation for a target.
|
||||
type COREFixup struct {
|
||||
Kind COREKind
|
||||
Local uint32
|
||||
Target uint32
|
||||
Poison bool
|
||||
}
|
||||
|
||||
func (r Relocation) equal(other Relocation) bool {
|
||||
return r.Current == other.Current && r.New == other.New
|
||||
func (f COREFixup) equal(other COREFixup) bool {
|
||||
return f.Local == other.Local && f.Target == other.Target
|
||||
}
|
||||
|
||||
// coreReloKind is the type of CO-RE relocation
|
||||
type coreReloKind uint32
|
||||
func (f COREFixup) String() string {
|
||||
if f.Poison {
|
||||
return fmt.Sprintf("%s=poison", f.Kind)
|
||||
}
|
||||
return fmt.Sprintf("%s=%d->%d", f.Kind, f.Local, f.Target)
|
||||
}
|
||||
|
||||
func (f COREFixup) apply(ins *asm.Instruction) error {
|
||||
if f.Poison {
|
||||
return errors.New("can't poison individual instruction")
|
||||
}
|
||||
|
||||
switch class := ins.OpCode.Class(); class {
|
||||
case asm.LdXClass, asm.StClass, asm.StXClass:
|
||||
if want := int16(f.Local); want != ins.Offset {
|
||||
return fmt.Errorf("invalid offset %d, expected %d", ins.Offset, want)
|
||||
}
|
||||
|
||||
if f.Target > math.MaxInt16 {
|
||||
return fmt.Errorf("offset %d exceeds MaxInt16", f.Target)
|
||||
}
|
||||
|
||||
ins.Offset = int16(f.Target)
|
||||
|
||||
case asm.LdClass:
|
||||
if !ins.IsConstantLoad(asm.DWord) {
|
||||
return fmt.Errorf("not a dword-sized immediate load")
|
||||
}
|
||||
|
||||
if want := int64(f.Local); want != ins.Constant {
|
||||
return fmt.Errorf("invalid immediate %d, expected %d", ins.Constant, want)
|
||||
}
|
||||
|
||||
ins.Constant = int64(f.Target)
|
||||
|
||||
case asm.ALUClass:
|
||||
if ins.OpCode.ALUOp() == asm.Swap {
|
||||
return fmt.Errorf("relocation against swap")
|
||||
}
|
||||
|
||||
fallthrough
|
||||
|
||||
case asm.ALU64Class:
|
||||
if src := ins.OpCode.Source(); src != asm.ImmSource {
|
||||
return fmt.Errorf("invalid source %s", src)
|
||||
}
|
||||
|
||||
if want := int64(f.Local); want != ins.Constant {
|
||||
return fmt.Errorf("invalid immediate %d, expected %d", ins.Constant, want)
|
||||
}
|
||||
|
||||
if f.Target > math.MaxInt32 {
|
||||
return fmt.Errorf("immediate %d exceeds MaxInt32", f.Target)
|
||||
}
|
||||
|
||||
ins.Constant = int64(f.Target)
|
||||
|
||||
default:
|
||||
return fmt.Errorf("invalid class %s", class)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f COREFixup) isNonExistant() bool {
|
||||
return f.Kind.checksForExistence() && f.Target == 0
|
||||
}
|
||||
|
||||
type COREFixups map[uint64]COREFixup
|
||||
|
||||
// Apply a set of CO-RE relocations to a BPF program.
|
||||
func (fs COREFixups) Apply(insns asm.Instructions) (asm.Instructions, error) {
|
||||
if len(fs) == 0 {
|
||||
cpy := make(asm.Instructions, len(insns))
|
||||
copy(cpy, insns)
|
||||
return insns, nil
|
||||
}
|
||||
|
||||
cpy := make(asm.Instructions, 0, len(insns))
|
||||
iter := insns.Iterate()
|
||||
for iter.Next() {
|
||||
fixup, ok := fs[iter.Offset.Bytes()]
|
||||
if !ok {
|
||||
cpy = append(cpy, *iter.Ins)
|
||||
continue
|
||||
}
|
||||
|
||||
ins := *iter.Ins
|
||||
if fixup.Poison {
|
||||
const badRelo = asm.BuiltinFunc(0xbad2310)
|
||||
|
||||
cpy = append(cpy, badRelo.Call())
|
||||
if ins.OpCode.IsDWordLoad() {
|
||||
// 64 bit constant loads occupy two raw bpf instructions, so
|
||||
// we need to add another instruction as padding.
|
||||
cpy = append(cpy, badRelo.Call())
|
||||
}
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
if err := fixup.apply(&ins); err != nil {
|
||||
return nil, fmt.Errorf("instruction %d, offset %d: %s: %w", iter.Index, iter.Offset.Bytes(), fixup.Kind, err)
|
||||
}
|
||||
|
||||
cpy = append(cpy, ins)
|
||||
}
|
||||
|
||||
return cpy, nil
|
||||
}
|
||||
|
||||
// COREKind is the type of CO-RE relocation
|
||||
type COREKind uint32
|
||||
|
||||
const (
|
||||
reloFieldByteOffset coreReloKind = iota /* field byte offset */
|
||||
reloFieldByteSize /* field size in bytes */
|
||||
reloFieldExists /* field existence in target kernel */
|
||||
reloFieldSigned /* field signedness (0 - unsigned, 1 - signed) */
|
||||
reloFieldLShiftU64 /* bitfield-specific left bitshift */
|
||||
reloFieldRShiftU64 /* bitfield-specific right bitshift */
|
||||
reloTypeIDLocal /* type ID in local BPF object */
|
||||
reloTypeIDTarget /* type ID in target kernel */
|
||||
reloTypeExists /* type existence in target kernel */
|
||||
reloTypeSize /* type size in bytes */
|
||||
reloEnumvalExists /* enum value existence in target kernel */
|
||||
reloEnumvalValue /* enum value integer value */
|
||||
reloFieldByteOffset COREKind = iota /* field byte offset */
|
||||
reloFieldByteSize /* field size in bytes */
|
||||
reloFieldExists /* field existence in target kernel */
|
||||
reloFieldSigned /* field signedness (0 - unsigned, 1 - signed) */
|
||||
reloFieldLShiftU64 /* bitfield-specific left bitshift */
|
||||
reloFieldRShiftU64 /* bitfield-specific right bitshift */
|
||||
reloTypeIDLocal /* type ID in local BPF object */
|
||||
reloTypeIDTarget /* type ID in target kernel */
|
||||
reloTypeExists /* type existence in target kernel */
|
||||
reloTypeSize /* type size in bytes */
|
||||
reloEnumvalExists /* enum value existence in target kernel */
|
||||
reloEnumvalValue /* enum value integer value */
|
||||
)
|
||||
|
||||
func (k coreReloKind) String() string {
|
||||
func (k COREKind) String() string {
|
||||
switch k {
|
||||
case reloFieldByteOffset:
|
||||
return "byte_off"
|
||||
@ -70,103 +187,249 @@ func (k coreReloKind) String() string {
|
||||
}
|
||||
}
|
||||
|
||||
func coreRelocate(local, target *Spec, coreRelos bpfCoreRelos) (map[uint64]Relocation, error) {
|
||||
if target == nil {
|
||||
var err error
|
||||
target, err = loadKernelSpec()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
func (k COREKind) checksForExistence() bool {
|
||||
return k == reloEnumvalExists || k == reloTypeExists || k == reloFieldExists
|
||||
}
|
||||
|
||||
func coreRelocate(local, target *Spec, relos coreRelos) (COREFixups, error) {
|
||||
if local.byteOrder != target.byteOrder {
|
||||
return nil, fmt.Errorf("can't relocate %s against %s", local.byteOrder, target.byteOrder)
|
||||
}
|
||||
|
||||
relocations := make(map[uint64]Relocation, len(coreRelos))
|
||||
for _, relo := range coreRelos {
|
||||
accessorStr, err := local.strings.Lookup(relo.AccessStrOff)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var ids []TypeID
|
||||
relosByID := make(map[TypeID]coreRelos)
|
||||
result := make(COREFixups, len(relos))
|
||||
for _, relo := range relos {
|
||||
if relo.kind == reloTypeIDLocal {
|
||||
// Filtering out reloTypeIDLocal here makes our lives a lot easier
|
||||
// down the line, since it doesn't have a target at all.
|
||||
if len(relo.accessor) > 1 || relo.accessor[0] != 0 {
|
||||
return nil, fmt.Errorf("%s: unexpected accessor %v", relo.kind, relo.accessor)
|
||||
}
|
||||
|
||||
accessor, err := parseCoreAccessor(accessorStr)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("accessor %q: %s", accessorStr, err)
|
||||
}
|
||||
|
||||
if int(relo.TypeID) >= len(local.types) {
|
||||
return nil, fmt.Errorf("invalid type id %d", relo.TypeID)
|
||||
}
|
||||
|
||||
typ := local.types[relo.TypeID]
|
||||
|
||||
if relo.ReloKind == reloTypeIDLocal {
|
||||
relocations[uint64(relo.InsnOff)] = Relocation{
|
||||
uint32(typ.ID()),
|
||||
uint32(typ.ID()),
|
||||
result[uint64(relo.insnOff)] = COREFixup{
|
||||
relo.kind,
|
||||
uint32(relo.typeID),
|
||||
uint32(relo.typeID),
|
||||
false,
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
named, ok := typ.(namedType)
|
||||
if !ok || named.name() == "" {
|
||||
return nil, fmt.Errorf("relocate anonymous type %s: %w", typ.String(), ErrNotSupported)
|
||||
relos, ok := relosByID[relo.typeID]
|
||||
if !ok {
|
||||
ids = append(ids, relo.typeID)
|
||||
}
|
||||
|
||||
name := essentialName(named.name())
|
||||
res, err := coreCalculateRelocation(typ, target.namedTypes[name], relo.ReloKind, accessor)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("relocate %s: %w", name, err)
|
||||
}
|
||||
|
||||
relocations[uint64(relo.InsnOff)] = res
|
||||
relosByID[relo.typeID] = append(relos, relo)
|
||||
}
|
||||
|
||||
return relocations, nil
|
||||
// Ensure we work on relocations in a deterministic order.
|
||||
sort.Slice(ids, func(i, j int) bool {
|
||||
return ids[i] < ids[j]
|
||||
})
|
||||
|
||||
for _, id := range ids {
|
||||
if int(id) >= len(local.types) {
|
||||
return nil, fmt.Errorf("invalid type id %d", id)
|
||||
}
|
||||
|
||||
localType := local.types[id]
|
||||
named, ok := localType.(namedType)
|
||||
if !ok || named.name() == "" {
|
||||
return nil, fmt.Errorf("relocate unnamed or anonymous type %s: %w", localType, ErrNotSupported)
|
||||
}
|
||||
|
||||
relos := relosByID[id]
|
||||
targets := target.namedTypes[named.essentialName()]
|
||||
fixups, err := coreCalculateFixups(localType, targets, relos)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("relocate %s: %w", localType, err)
|
||||
}
|
||||
|
||||
for i, relo := range relos {
|
||||
result[uint64(relo.insnOff)] = fixups[i]
|
||||
}
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
var errAmbiguousRelocation = errors.New("ambiguous relocation")
|
||||
var errImpossibleRelocation = errors.New("impossible relocation")
|
||||
|
||||
// coreCalculateFixups calculates the fixups for the given relocations using
|
||||
// the "best" target.
|
||||
//
|
||||
// The best target is determined by scoring: the less poisoning we have to do
|
||||
// the better the target is.
|
||||
func coreCalculateFixups(local Type, targets []namedType, relos coreRelos) ([]COREFixup, error) {
|
||||
localID := local.ID()
|
||||
local, err := copyType(local, skipQualifierAndTypedef)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
bestScore := len(relos)
|
||||
var bestFixups []COREFixup
|
||||
for i := range targets {
|
||||
targetID := targets[i].ID()
|
||||
target, err := copyType(targets[i], skipQualifierAndTypedef)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
score := 0 // lower is better
|
||||
fixups := make([]COREFixup, 0, len(relos))
|
||||
for _, relo := range relos {
|
||||
fixup, err := coreCalculateFixup(local, localID, target, targetID, relo)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("target %s: %w", target, err)
|
||||
}
|
||||
if fixup.Poison || fixup.isNonExistant() {
|
||||
score++
|
||||
}
|
||||
fixups = append(fixups, fixup)
|
||||
}
|
||||
|
||||
if score > bestScore {
|
||||
// We have a better target already, ignore this one.
|
||||
continue
|
||||
}
|
||||
|
||||
if score < bestScore {
|
||||
// This is the best target yet, use it.
|
||||
bestScore = score
|
||||
bestFixups = fixups
|
||||
continue
|
||||
}
|
||||
|
||||
// Some other target has the same score as the current one. Make sure
|
||||
// the fixups agree with each other.
|
||||
for i, fixup := range bestFixups {
|
||||
if !fixup.equal(fixups[i]) {
|
||||
return nil, fmt.Errorf("%s: multiple types match: %w", fixup.Kind, errAmbiguousRelocation)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if bestFixups == nil {
|
||||
// Nothing at all matched, probably because there are no suitable
|
||||
// targets at all. Poison everything!
|
||||
bestFixups = make([]COREFixup, len(relos))
|
||||
for i, relo := range relos {
|
||||
bestFixups[i] = COREFixup{Kind: relo.kind, Poison: true}
|
||||
}
|
||||
}
|
||||
|
||||
return bestFixups, nil
|
||||
}
|
||||
|
||||
// coreCalculateFixup calculates the fixup for a single local type, target type
|
||||
// and relocation.
|
||||
func coreCalculateFixup(local Type, localID TypeID, target Type, targetID TypeID, relo coreRelo) (COREFixup, error) {
|
||||
fixup := func(local, target uint32) (COREFixup, error) {
|
||||
return COREFixup{relo.kind, local, target, false}, nil
|
||||
}
|
||||
poison := func() (COREFixup, error) {
|
||||
if relo.kind.checksForExistence() {
|
||||
return fixup(1, 0)
|
||||
}
|
||||
return COREFixup{relo.kind, 0, 0, true}, nil
|
||||
}
|
||||
zero := COREFixup{}
|
||||
|
||||
switch relo.kind {
|
||||
case reloTypeIDTarget, reloTypeSize, reloTypeExists:
|
||||
if len(relo.accessor) > 1 || relo.accessor[0] != 0 {
|
||||
return zero, fmt.Errorf("%s: unexpected accessor %v", relo.kind, relo.accessor)
|
||||
}
|
||||
|
||||
err := coreAreTypesCompatible(local, target)
|
||||
if errors.Is(err, errImpossibleRelocation) {
|
||||
return poison()
|
||||
}
|
||||
if err != nil {
|
||||
return zero, fmt.Errorf("relocation %s: %w", relo.kind, err)
|
||||
}
|
||||
|
||||
switch relo.kind {
|
||||
case reloTypeExists:
|
||||
return fixup(1, 1)
|
||||
|
||||
func coreCalculateRelocation(local Type, targets []namedType, kind coreReloKind, localAccessor coreAccessor) (Relocation, error) {
|
||||
var relos []Relocation
|
||||
var matches []Type
|
||||
for _, target := range targets {
|
||||
switch kind {
|
||||
case reloTypeIDTarget:
|
||||
if localAccessor[0] != 0 {
|
||||
return Relocation{}, fmt.Errorf("%s: unexpected non-zero accessor", kind)
|
||||
return fixup(uint32(localID), uint32(targetID))
|
||||
|
||||
case reloTypeSize:
|
||||
localSize, err := Sizeof(local)
|
||||
if err != nil {
|
||||
return zero, err
|
||||
}
|
||||
|
||||
if compat, err := coreAreTypesCompatible(local, target); err != nil {
|
||||
return Relocation{}, fmt.Errorf("%s: %s", kind, err)
|
||||
} else if !compat {
|
||||
continue
|
||||
targetSize, err := Sizeof(target)
|
||||
if err != nil {
|
||||
return zero, err
|
||||
}
|
||||
|
||||
relos = append(relos, Relocation{uint32(target.ID()), uint32(target.ID())})
|
||||
|
||||
default:
|
||||
return Relocation{}, fmt.Errorf("relocation %s: %w", kind, ErrNotSupported)
|
||||
return fixup(uint32(localSize), uint32(targetSize))
|
||||
}
|
||||
matches = append(matches, target)
|
||||
}
|
||||
|
||||
if len(relos) == 0 {
|
||||
// TODO: Add switch for existence checks like reloEnumvalExists here.
|
||||
case reloEnumvalValue, reloEnumvalExists:
|
||||
localValue, targetValue, err := coreFindEnumValue(local, relo.accessor, target)
|
||||
if errors.Is(err, errImpossibleRelocation) {
|
||||
return poison()
|
||||
}
|
||||
if err != nil {
|
||||
return zero, fmt.Errorf("relocation %s: %w", relo.kind, err)
|
||||
}
|
||||
|
||||
// TODO: This might have to be poisoned.
|
||||
return Relocation{}, fmt.Errorf("no relocation found, tried %v", targets)
|
||||
}
|
||||
switch relo.kind {
|
||||
case reloEnumvalExists:
|
||||
return fixup(1, 1)
|
||||
|
||||
case reloEnumvalValue:
|
||||
return fixup(uint32(localValue.Value), uint32(targetValue.Value))
|
||||
}
|
||||
|
||||
case reloFieldByteOffset, reloFieldByteSize, reloFieldExists:
|
||||
if _, ok := target.(*Fwd); ok {
|
||||
// We can't relocate fields using a forward declaration, so
|
||||
// skip it. If a non-forward declaration is present in the BTF
|
||||
// we'll find it in one of the other iterations.
|
||||
return poison()
|
||||
}
|
||||
|
||||
localField, targetField, err := coreFindField(local, relo.accessor, target)
|
||||
if errors.Is(err, errImpossibleRelocation) {
|
||||
return poison()
|
||||
}
|
||||
if err != nil {
|
||||
return zero, fmt.Errorf("target %s: %w", target, err)
|
||||
}
|
||||
|
||||
switch relo.kind {
|
||||
case reloFieldExists:
|
||||
return fixup(1, 1)
|
||||
|
||||
case reloFieldByteOffset:
|
||||
return fixup(localField.offset/8, targetField.offset/8)
|
||||
|
||||
case reloFieldByteSize:
|
||||
localSize, err := Sizeof(localField.Type)
|
||||
if err != nil {
|
||||
return zero, err
|
||||
}
|
||||
|
||||
targetSize, err := Sizeof(targetField.Type)
|
||||
if err != nil {
|
||||
return zero, err
|
||||
}
|
||||
|
||||
return fixup(uint32(localSize), uint32(targetSize))
|
||||
|
||||
relo := relos[0]
|
||||
for _, altRelo := range relos[1:] {
|
||||
if !altRelo.equal(relo) {
|
||||
return Relocation{}, fmt.Errorf("multiple types %v match: %w", matches, errAmbiguousRelocation)
|
||||
}
|
||||
}
|
||||
|
||||
return relo, nil
|
||||
return zero, fmt.Errorf("relocation %s: %w", relo.kind, ErrNotSupported)
|
||||
}
|
||||
|
||||
/* coreAccessor contains a path through a struct. It contains at least one index.
|
||||
@ -219,6 +482,240 @@ func parseCoreAccessor(accessor string) (coreAccessor, error) {
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (ca coreAccessor) String() string {
|
||||
strs := make([]string, 0, len(ca))
|
||||
for _, i := range ca {
|
||||
strs = append(strs, strconv.Itoa(i))
|
||||
}
|
||||
return strings.Join(strs, ":")
|
||||
}
|
||||
|
||||
func (ca coreAccessor) enumValue(t Type) (*EnumValue, error) {
|
||||
e, ok := t.(*Enum)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("not an enum: %s", t)
|
||||
}
|
||||
|
||||
if len(ca) > 1 {
|
||||
return nil, fmt.Errorf("invalid accessor %s for enum", ca)
|
||||
}
|
||||
|
||||
i := ca[0]
|
||||
if i >= len(e.Values) {
|
||||
return nil, fmt.Errorf("invalid index %d for %s", i, e)
|
||||
}
|
||||
|
||||
return &e.Values[i], nil
|
||||
}
|
||||
|
||||
type coreField struct {
|
||||
Type Type
|
||||
offset uint32
|
||||
}
|
||||
|
||||
func adjustOffset(base uint32, t Type, n int) (uint32, error) {
|
||||
size, err := Sizeof(t)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return base + (uint32(n) * uint32(size) * 8), nil
|
||||
}
|
||||
|
||||
// coreFindField descends into the local type using the accessor and tries to
|
||||
// find an equivalent field in target at each step.
|
||||
//
|
||||
// Returns the field and the offset of the field from the start of
|
||||
// target in bits.
|
||||
func coreFindField(local Type, localAcc coreAccessor, target Type) (_, _ coreField, _ error) {
|
||||
// The first index is used to offset a pointer of the base type like
|
||||
// when accessing an array.
|
||||
localOffset, err := adjustOffset(0, local, localAcc[0])
|
||||
if err != nil {
|
||||
return coreField{}, coreField{}, err
|
||||
}
|
||||
|
||||
targetOffset, err := adjustOffset(0, target, localAcc[0])
|
||||
if err != nil {
|
||||
return coreField{}, coreField{}, err
|
||||
}
|
||||
|
||||
if err := coreAreMembersCompatible(local, target); err != nil {
|
||||
return coreField{}, coreField{}, fmt.Errorf("fields: %w", err)
|
||||
}
|
||||
|
||||
var localMaybeFlex, targetMaybeFlex bool
|
||||
for _, acc := range localAcc[1:] {
|
||||
switch localType := local.(type) {
|
||||
case composite:
|
||||
// For composite types acc is used to find the field in the local type,
|
||||
// and then we try to find a field in target with the same name.
|
||||
localMembers := localType.members()
|
||||
if acc >= len(localMembers) {
|
||||
return coreField{}, coreField{}, fmt.Errorf("invalid accessor %d for %s", acc, local)
|
||||
}
|
||||
|
||||
localMember := localMembers[acc]
|
||||
if localMember.Name == "" {
|
||||
_, ok := localMember.Type.(composite)
|
||||
if !ok {
|
||||
return coreField{}, coreField{}, fmt.Errorf("unnamed field with type %s: %s", localMember.Type, ErrNotSupported)
|
||||
}
|
||||
|
||||
// This is an anonymous struct or union, ignore it.
|
||||
local = localMember.Type
|
||||
localOffset += localMember.Offset
|
||||
localMaybeFlex = false
|
||||
continue
|
||||
}
|
||||
|
||||
targetType, ok := target.(composite)
|
||||
if !ok {
|
||||
return coreField{}, coreField{}, fmt.Errorf("target not composite: %w", errImpossibleRelocation)
|
||||
}
|
||||
|
||||
targetMember, last, err := coreFindMember(targetType, localMember.Name)
|
||||
if err != nil {
|
||||
return coreField{}, coreField{}, err
|
||||
}
|
||||
|
||||
if targetMember.BitfieldSize > 0 {
|
||||
return coreField{}, coreField{}, fmt.Errorf("field %q is a bitfield: %w", targetMember.Name, ErrNotSupported)
|
||||
}
|
||||
|
||||
local = localMember.Type
|
||||
localMaybeFlex = acc == len(localMembers)-1
|
||||
localOffset += localMember.Offset
|
||||
target = targetMember.Type
|
||||
targetMaybeFlex = last
|
||||
targetOffset += targetMember.Offset
|
||||
|
||||
case *Array:
|
||||
// For arrays, acc is the index in the target.
|
||||
targetType, ok := target.(*Array)
|
||||
if !ok {
|
||||
return coreField{}, coreField{}, fmt.Errorf("target not array: %w", errImpossibleRelocation)
|
||||
}
|
||||
|
||||
if localType.Nelems == 0 && !localMaybeFlex {
|
||||
return coreField{}, coreField{}, fmt.Errorf("local type has invalid flexible array")
|
||||
}
|
||||
if targetType.Nelems == 0 && !targetMaybeFlex {
|
||||
return coreField{}, coreField{}, fmt.Errorf("target type has invalid flexible array")
|
||||
}
|
||||
|
||||
if localType.Nelems > 0 && acc >= int(localType.Nelems) {
|
||||
return coreField{}, coreField{}, fmt.Errorf("invalid access of %s at index %d", localType, acc)
|
||||
}
|
||||
if targetType.Nelems > 0 && acc >= int(targetType.Nelems) {
|
||||
return coreField{}, coreField{}, fmt.Errorf("out of bounds access of target: %w", errImpossibleRelocation)
|
||||
}
|
||||
|
||||
local = localType.Type
|
||||
localMaybeFlex = false
|
||||
localOffset, err = adjustOffset(localOffset, local, acc)
|
||||
if err != nil {
|
||||
return coreField{}, coreField{}, err
|
||||
}
|
||||
|
||||
target = targetType.Type
|
||||
targetMaybeFlex = false
|
||||
targetOffset, err = adjustOffset(targetOffset, target, acc)
|
||||
if err != nil {
|
||||
return coreField{}, coreField{}, err
|
||||
}
|
||||
|
||||
default:
|
||||
return coreField{}, coreField{}, fmt.Errorf("relocate field of %T: %w", localType, ErrNotSupported)
|
||||
}
|
||||
|
||||
if err := coreAreMembersCompatible(local, target); err != nil {
|
||||
return coreField{}, coreField{}, err
|
||||
}
|
||||
}
|
||||
|
||||
return coreField{local, localOffset}, coreField{target, targetOffset}, nil
|
||||
}
|
||||
|
||||
// coreFindMember finds a member in a composite type while handling anonymous
|
||||
// structs and unions.
|
||||
func coreFindMember(typ composite, name Name) (Member, bool, error) {
|
||||
if name == "" {
|
||||
return Member{}, false, errors.New("can't search for anonymous member")
|
||||
}
|
||||
|
||||
type offsetTarget struct {
|
||||
composite
|
||||
offset uint32
|
||||
}
|
||||
|
||||
targets := []offsetTarget{{typ, 0}}
|
||||
visited := make(map[composite]bool)
|
||||
|
||||
for i := 0; i < len(targets); i++ {
|
||||
target := targets[i]
|
||||
|
||||
// Only visit targets once to prevent infinite recursion.
|
||||
if visited[target] {
|
||||
continue
|
||||
}
|
||||
if len(visited) >= maxTypeDepth {
|
||||
// This check is different than libbpf, which restricts the entire
|
||||
// path to BPF_CORE_SPEC_MAX_LEN items.
|
||||
return Member{}, false, fmt.Errorf("type is nested too deep")
|
||||
}
|
||||
visited[target] = true
|
||||
|
||||
members := target.members()
|
||||
for j, member := range members {
|
||||
if member.Name == name {
|
||||
// NB: This is safe because member is a copy.
|
||||
member.Offset += target.offset
|
||||
return member, j == len(members)-1, nil
|
||||
}
|
||||
|
||||
// The names don't match, but this member could be an anonymous struct
|
||||
// or union.
|
||||
if member.Name != "" {
|
||||
continue
|
||||
}
|
||||
|
||||
comp, ok := member.Type.(composite)
|
||||
if !ok {
|
||||
return Member{}, false, fmt.Errorf("anonymous non-composite type %T not allowed", member.Type)
|
||||
}
|
||||
|
||||
targets = append(targets, offsetTarget{comp, target.offset + member.Offset})
|
||||
}
|
||||
}
|
||||
|
||||
return Member{}, false, fmt.Errorf("no matching member: %w", errImpossibleRelocation)
|
||||
}
|
||||
|
||||
// coreFindEnumValue follows localAcc to find the equivalent enum value in target.
|
||||
func coreFindEnumValue(local Type, localAcc coreAccessor, target Type) (localValue, targetValue *EnumValue, _ error) {
|
||||
localValue, err := localAcc.enumValue(local)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
targetEnum, ok := target.(*Enum)
|
||||
if !ok {
|
||||
return nil, nil, errImpossibleRelocation
|
||||
}
|
||||
|
||||
localName := localValue.Name.essentialName()
|
||||
for i, targetValue := range targetEnum.Values {
|
||||
if targetValue.Name.essentialName() != localName {
|
||||
continue
|
||||
}
|
||||
|
||||
return localValue, &targetEnum.Values[i], nil
|
||||
}
|
||||
|
||||
return nil, nil, errImpossibleRelocation
|
||||
}
|
||||
|
||||
/* The comment below is from bpf_core_types_are_compat in libbpf.c:
|
||||
*
|
||||
* Check local and target types for compatibility. This check is used for
|
||||
@ -239,8 +736,10 @@ func parseCoreAccessor(accessor string) (coreAccessor, error) {
|
||||
* number of input args and compatible return and argument types.
|
||||
* These rules are not set in stone and probably will be adjusted as we get
|
||||
* more experience with using BPF CO-RE relocations.
|
||||
*
|
||||
* Returns errImpossibleRelocation if types are not compatible.
|
||||
*/
|
||||
func coreAreTypesCompatible(localType Type, targetType Type) (bool, error) {
|
||||
func coreAreTypesCompatible(localType Type, targetType Type) error {
|
||||
var (
|
||||
localTs, targetTs typeDeque
|
||||
l, t = &localType, &targetType
|
||||
@ -249,14 +748,14 @@ func coreAreTypesCompatible(localType Type, targetType Type) (bool, error) {
|
||||
|
||||
for ; l != nil && t != nil; l, t = localTs.shift(), targetTs.shift() {
|
||||
if depth >= maxTypeDepth {
|
||||
return false, errors.New("types are nested too deep")
|
||||
return errors.New("types are nested too deep")
|
||||
}
|
||||
|
||||
localType = skipQualifierAndTypedef(*l)
|
||||
targetType = skipQualifierAndTypedef(*t)
|
||||
localType = *l
|
||||
targetType = *t
|
||||
|
||||
if reflect.TypeOf(localType) != reflect.TypeOf(targetType) {
|
||||
return false, nil
|
||||
return fmt.Errorf("type mismatch: %w", errImpossibleRelocation)
|
||||
}
|
||||
|
||||
switch lv := (localType).(type) {
|
||||
@ -266,7 +765,7 @@ func coreAreTypesCompatible(localType Type, targetType Type) (bool, error) {
|
||||
case *Int:
|
||||
tv := targetType.(*Int)
|
||||
if lv.isBitfield() || tv.isBitfield() {
|
||||
return false, nil
|
||||
return fmt.Errorf("bitfield: %w", errImpossibleRelocation)
|
||||
}
|
||||
|
||||
case *Pointer, *Array:
|
||||
@ -277,7 +776,7 @@ func coreAreTypesCompatible(localType Type, targetType Type) (bool, error) {
|
||||
case *FuncProto:
|
||||
tv := targetType.(*FuncProto)
|
||||
if len(lv.Params) != len(tv.Params) {
|
||||
return false, nil
|
||||
return fmt.Errorf("function param mismatch: %w", errImpossibleRelocation)
|
||||
}
|
||||
|
||||
depth++
|
||||
@ -285,22 +784,24 @@ func coreAreTypesCompatible(localType Type, targetType Type) (bool, error) {
|
||||
targetType.walk(&targetTs)
|
||||
|
||||
default:
|
||||
return false, fmt.Errorf("unsupported type %T", localType)
|
||||
return fmt.Errorf("unsupported type %T", localType)
|
||||
}
|
||||
}
|
||||
|
||||
if l != nil {
|
||||
return false, fmt.Errorf("dangling local type %T", *l)
|
||||
return fmt.Errorf("dangling local type %T", *l)
|
||||
}
|
||||
|
||||
if t != nil {
|
||||
return false, fmt.Errorf("dangling target type %T", *t)
|
||||
return fmt.Errorf("dangling target type %T", *t)
|
||||
}
|
||||
|
||||
return true, nil
|
||||
return nil
|
||||
}
|
||||
|
||||
/* The comment below is from bpf_core_fields_are_compat in libbpf.c:
|
||||
/* coreAreMembersCompatible checks two types for field-based relocation compatibility.
|
||||
*
|
||||
* The comment below is from bpf_core_fields_are_compat in libbpf.c:
|
||||
*
|
||||
* Check two types for compatibility for the purpose of field access
|
||||
* relocation. const/volatile/restrict and typedefs are skipped to ensure we
|
||||
@ -314,65 +815,63 @@ func coreAreTypesCompatible(localType Type, targetType Type) (bool, error) {
|
||||
* - for INT, size and signedness are ignored;
|
||||
* - for ARRAY, dimensionality is ignored, element types are checked for
|
||||
* compatibility recursively;
|
||||
* [ NB: coreAreMembersCompatible doesn't recurse, this check is done
|
||||
* by coreFindField. ]
|
||||
* - everything else shouldn't be ever a target of relocation.
|
||||
* These rules are not set in stone and probably will be adjusted as we get
|
||||
* more experience with using BPF CO-RE relocations.
|
||||
*
|
||||
* Returns errImpossibleRelocation if the members are not compatible.
|
||||
*/
|
||||
func coreAreMembersCompatible(localType Type, targetType Type) (bool, error) {
|
||||
doNamesMatch := func(a, b string) bool {
|
||||
func coreAreMembersCompatible(localType Type, targetType Type) error {
|
||||
doNamesMatch := func(a, b string) error {
|
||||
if a == "" || b == "" {
|
||||
// allow anonymous and named type to match
|
||||
return true
|
||||
return nil
|
||||
}
|
||||
|
||||
return essentialName(a) == essentialName(b)
|
||||
if essentialName(a) == essentialName(b) {
|
||||
return nil
|
||||
}
|
||||
|
||||
return fmt.Errorf("names don't match: %w", errImpossibleRelocation)
|
||||
}
|
||||
|
||||
for depth := 0; depth <= maxTypeDepth; depth++ {
|
||||
localType = skipQualifierAndTypedef(localType)
|
||||
targetType = skipQualifierAndTypedef(targetType)
|
||||
|
||||
_, lok := localType.(composite)
|
||||
_, tok := targetType.(composite)
|
||||
if lok && tok {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
if reflect.TypeOf(localType) != reflect.TypeOf(targetType) {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
switch lv := localType.(type) {
|
||||
case *Pointer:
|
||||
return true, nil
|
||||
|
||||
case *Enum:
|
||||
tv := targetType.(*Enum)
|
||||
return doNamesMatch(lv.name(), tv.name()), nil
|
||||
|
||||
case *Fwd:
|
||||
tv := targetType.(*Fwd)
|
||||
return doNamesMatch(lv.name(), tv.name()), nil
|
||||
|
||||
case *Int:
|
||||
tv := targetType.(*Int)
|
||||
return !lv.isBitfield() && !tv.isBitfield(), nil
|
||||
|
||||
case *Array:
|
||||
tv := targetType.(*Array)
|
||||
|
||||
localType = lv.Type
|
||||
targetType = tv.Type
|
||||
|
||||
default:
|
||||
return false, fmt.Errorf("unsupported type %T", localType)
|
||||
}
|
||||
_, lok := localType.(composite)
|
||||
_, tok := targetType.(composite)
|
||||
if lok && tok {
|
||||
return nil
|
||||
}
|
||||
|
||||
return false, errors.New("types are nested too deep")
|
||||
if reflect.TypeOf(localType) != reflect.TypeOf(targetType) {
|
||||
return fmt.Errorf("type mismatch: %w", errImpossibleRelocation)
|
||||
}
|
||||
|
||||
switch lv := localType.(type) {
|
||||
case *Array, *Pointer:
|
||||
return nil
|
||||
|
||||
case *Enum:
|
||||
tv := targetType.(*Enum)
|
||||
return doNamesMatch(lv.name(), tv.name())
|
||||
|
||||
case *Fwd:
|
||||
tv := targetType.(*Fwd)
|
||||
return doNamesMatch(lv.name(), tv.name())
|
||||
|
||||
case *Int:
|
||||
tv := targetType.(*Int)
|
||||
if lv.isBitfield() || tv.isBitfield() {
|
||||
return fmt.Errorf("bitfield: %w", errImpossibleRelocation)
|
||||
}
|
||||
return nil
|
||||
|
||||
default:
|
||||
return fmt.Errorf("type %s: %w", localType, ErrNotSupported)
|
||||
}
|
||||
}
|
||||
|
||||
func skipQualifierAndTypedef(typ Type) Type {
|
||||
func skipQualifierAndTypedef(typ Type) (Type, error) {
|
||||
result := typ
|
||||
for depth := 0; depth <= maxTypeDepth; depth++ {
|
||||
switch v := (result).(type) {
|
||||
@ -381,8 +880,8 @@ func skipQualifierAndTypedef(typ Type) Type {
|
||||
case *Typedef:
|
||||
result = v.Type
|
||||
default:
|
||||
return result
|
||||
return result, nil
|
||||
}
|
||||
}
|
||||
return typ
|
||||
return nil, errors.New("exceeded type depth")
|
||||
}
|
||||
|
46
src/runtime/vendor/github.com/cilium/ebpf/internal/btf/ext_info.go
generated
vendored
46
src/runtime/vendor/github.com/cilium/ebpf/internal/btf/ext_info.go
generated
vendored
@ -30,7 +30,7 @@ type btfExtCoreHeader struct {
|
||||
CoreReloLen uint32
|
||||
}
|
||||
|
||||
func parseExtInfos(r io.ReadSeeker, bo binary.ByteOrder, strings stringTable) (funcInfo, lineInfo map[string]extInfo, coreRelos map[string]bpfCoreRelos, err error) {
|
||||
func parseExtInfos(r io.ReadSeeker, bo binary.ByteOrder, strings stringTable) (funcInfo, lineInfo map[string]extInfo, relos map[string]coreRelos, err error) {
|
||||
var header btfExtHeader
|
||||
var coreHeader btfExtCoreHeader
|
||||
if err := binary.Read(r, bo, &header); err != nil {
|
||||
@ -94,13 +94,13 @@ func parseExtInfos(r io.ReadSeeker, bo binary.ByteOrder, strings stringTable) (f
|
||||
return nil, nil, nil, fmt.Errorf("can't seek to CO-RE relocation section: %v", err)
|
||||
}
|
||||
|
||||
coreRelos, err = parseExtInfoRelos(io.LimitReader(r, int64(coreHeader.CoreReloLen)), bo, strings)
|
||||
relos, err = parseExtInfoRelos(io.LimitReader(r, int64(coreHeader.CoreReloLen)), bo, strings)
|
||||
if err != nil {
|
||||
return nil, nil, nil, fmt.Errorf("CO-RE relocation info: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
return funcInfo, lineInfo, coreRelos, nil
|
||||
return funcInfo, lineInfo, relos, nil
|
||||
}
|
||||
|
||||
type btfExtInfoSec struct {
|
||||
@ -208,18 +208,25 @@ type bpfCoreRelo struct {
|
||||
InsnOff uint32
|
||||
TypeID TypeID
|
||||
AccessStrOff uint32
|
||||
ReloKind coreReloKind
|
||||
Kind COREKind
|
||||
}
|
||||
|
||||
type bpfCoreRelos []bpfCoreRelo
|
||||
type coreRelo struct {
|
||||
insnOff uint32
|
||||
typeID TypeID
|
||||
accessor coreAccessor
|
||||
kind COREKind
|
||||
}
|
||||
|
||||
type coreRelos []coreRelo
|
||||
|
||||
// append two slices of extInfoRelo to each other. The InsnOff of b are adjusted
|
||||
// by offset.
|
||||
func (r bpfCoreRelos) append(other bpfCoreRelos, offset uint64) bpfCoreRelos {
|
||||
result := make([]bpfCoreRelo, 0, len(r)+len(other))
|
||||
func (r coreRelos) append(other coreRelos, offset uint64) coreRelos {
|
||||
result := make([]coreRelo, 0, len(r)+len(other))
|
||||
result = append(result, r...)
|
||||
for _, relo := range other {
|
||||
relo.InsnOff += uint32(offset)
|
||||
relo.insnOff += uint32(offset)
|
||||
result = append(result, relo)
|
||||
}
|
||||
return result
|
||||
@ -227,7 +234,7 @@ func (r bpfCoreRelos) append(other bpfCoreRelos, offset uint64) bpfCoreRelos {
|
||||
|
||||
var extInfoReloSize = binary.Size(bpfCoreRelo{})
|
||||
|
||||
func parseExtInfoRelos(r io.Reader, bo binary.ByteOrder, strings stringTable) (map[string]bpfCoreRelos, error) {
|
||||
func parseExtInfoRelos(r io.Reader, bo binary.ByteOrder, strings stringTable) (map[string]coreRelos, error) {
|
||||
var recordSize uint32
|
||||
if err := binary.Read(r, bo, &recordSize); err != nil {
|
||||
return nil, fmt.Errorf("read record size: %v", err)
|
||||
@ -237,14 +244,14 @@ func parseExtInfoRelos(r io.Reader, bo binary.ByteOrder, strings stringTable) (m
|
||||
return nil, fmt.Errorf("expected record size %d, got %d", extInfoReloSize, recordSize)
|
||||
}
|
||||
|
||||
result := make(map[string]bpfCoreRelos)
|
||||
result := make(map[string]coreRelos)
|
||||
for {
|
||||
secName, infoHeader, err := parseExtInfoHeader(r, bo, strings)
|
||||
if errors.Is(err, io.EOF) {
|
||||
return result, nil
|
||||
}
|
||||
|
||||
var relos []bpfCoreRelo
|
||||
var relos coreRelos
|
||||
for i := uint32(0); i < infoHeader.NumInfo; i++ {
|
||||
var relo bpfCoreRelo
|
||||
if err := binary.Read(r, bo, &relo); err != nil {
|
||||
@ -255,7 +262,22 @@ func parseExtInfoRelos(r io.Reader, bo binary.ByteOrder, strings stringTable) (m
|
||||
return nil, fmt.Errorf("section %v: offset %v is not aligned with instruction size", secName, relo.InsnOff)
|
||||
}
|
||||
|
||||
relos = append(relos, relo)
|
||||
accessorStr, err := strings.Lookup(relo.AccessStrOff)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
accessor, err := parseCoreAccessor(accessorStr)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("accessor %q: %s", accessorStr, err)
|
||||
}
|
||||
|
||||
relos = append(relos, coreRelo{
|
||||
relo.InsnOff,
|
||||
relo.TypeID,
|
||||
accessor,
|
||||
relo.Kind,
|
||||
})
|
||||
}
|
||||
|
||||
result[secName] = relos
|
||||
|
62
src/runtime/vendor/github.com/cilium/ebpf/internal/btf/types.go
generated
vendored
62
src/runtime/vendor/github.com/cilium/ebpf/internal/btf/types.go
generated
vendored
@ -1,7 +1,6 @@
|
||||
package btf
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"math"
|
||||
"strings"
|
||||
@ -37,6 +36,7 @@ type Type interface {
|
||||
type namedType interface {
|
||||
Type
|
||||
name() string
|
||||
essentialName() string
|
||||
}
|
||||
|
||||
// Name identifies a type.
|
||||
@ -48,6 +48,10 @@ func (n Name) name() string {
|
||||
return string(n)
|
||||
}
|
||||
|
||||
func (n Name) essentialName() string {
|
||||
return essentialName(string(n))
|
||||
}
|
||||
|
||||
// Void is the unit type of BTF.
|
||||
type Void struct{}
|
||||
|
||||
@ -174,8 +178,7 @@ func (s *Struct) walk(tdq *typeDeque) {
|
||||
|
||||
func (s *Struct) copy() Type {
|
||||
cpy := *s
|
||||
cpy.Members = make([]Member, len(s.Members))
|
||||
copy(cpy.Members, s.Members)
|
||||
cpy.Members = copyMembers(s.Members)
|
||||
return &cpy
|
||||
}
|
||||
|
||||
@ -206,8 +209,7 @@ func (u *Union) walk(tdq *typeDeque) {
|
||||
|
||||
func (u *Union) copy() Type {
|
||||
cpy := *u
|
||||
cpy.Members = make([]Member, len(u.Members))
|
||||
copy(cpy.Members, u.Members)
|
||||
cpy.Members = copyMembers(u.Members)
|
||||
return &cpy
|
||||
}
|
||||
|
||||
@ -215,6 +217,12 @@ func (u *Union) members() []Member {
|
||||
return u.Members
|
||||
}
|
||||
|
||||
func copyMembers(orig []Member) []Member {
|
||||
cpy := make([]Member, len(orig))
|
||||
copy(cpy, orig)
|
||||
return cpy
|
||||
}
|
||||
|
||||
type composite interface {
|
||||
members() []Member
|
||||
}
|
||||
@ -372,11 +380,12 @@ func (r *Restrict) copy() Type {
|
||||
type Func struct {
|
||||
TypeID
|
||||
Name
|
||||
Type Type
|
||||
Type Type
|
||||
Linkage FuncLinkage
|
||||
}
|
||||
|
||||
func (f *Func) String() string {
|
||||
return fmt.Sprintf("func#%d[%q proto=#%d]", f.TypeID, 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) walk(tdq *typeDeque) { tdq.push(&f.Type) }
|
||||
@ -425,12 +434,12 @@ type FuncParam struct {
|
||||
type Var struct {
|
||||
TypeID
|
||||
Name
|
||||
Type Type
|
||||
Type Type
|
||||
Linkage VarLinkage
|
||||
}
|
||||
|
||||
func (v *Var) String() string {
|
||||
// TODO: Linkage
|
||||
return fmt.Sprintf("var#%d[%q]", v.TypeID, v.Name)
|
||||
return fmt.Sprintf("var#%d[%s %q]", v.TypeID, v.Linkage, v.Name)
|
||||
}
|
||||
|
||||
func (v *Var) walk(tdq *typeDeque) { tdq.push(&v.Type) }
|
||||
@ -511,7 +520,7 @@ func Sizeof(typ Type) (int, error) {
|
||||
switch v := typ.(type) {
|
||||
case *Array:
|
||||
if n > 0 && int64(v.Nelems) > math.MaxInt64/n {
|
||||
return 0, errors.New("overflow")
|
||||
return 0, fmt.Errorf("type %s: overflow", typ)
|
||||
}
|
||||
|
||||
// Arrays may be of zero length, which allows
|
||||
@ -532,28 +541,30 @@ func Sizeof(typ Type) (int, error) {
|
||||
continue
|
||||
|
||||
default:
|
||||
return 0, fmt.Errorf("unrecognized type %T", typ)
|
||||
return 0, fmt.Errorf("unsized type %T", typ)
|
||||
}
|
||||
|
||||
if n > 0 && elem > math.MaxInt64/n {
|
||||
return 0, errors.New("overflow")
|
||||
return 0, fmt.Errorf("type %s: overflow", typ)
|
||||
}
|
||||
|
||||
size := n * elem
|
||||
if int64(int(size)) != size {
|
||||
return 0, errors.New("overflow")
|
||||
return 0, fmt.Errorf("type %s: overflow", typ)
|
||||
}
|
||||
|
||||
return int(size), nil
|
||||
}
|
||||
|
||||
return 0, errors.New("exceeded type depth")
|
||||
return 0, fmt.Errorf("type %s: exceeded type depth", typ)
|
||||
}
|
||||
|
||||
// copy a Type recursively.
|
||||
//
|
||||
// typ may form a cycle.
|
||||
func copyType(typ Type) Type {
|
||||
//
|
||||
// Returns any errors from transform verbatim.
|
||||
func copyType(typ Type, transform func(Type) (Type, error)) (Type, error) {
|
||||
var (
|
||||
copies = make(map[Type]Type)
|
||||
work typeDeque
|
||||
@ -566,7 +577,17 @@ func copyType(typ Type) Type {
|
||||
continue
|
||||
}
|
||||
|
||||
cpy := (*t).copy()
|
||||
var cpy Type
|
||||
if transform != nil {
|
||||
tf, err := transform(*t)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("copy %s: %w", typ, err)
|
||||
}
|
||||
cpy = tf.copy()
|
||||
} else {
|
||||
cpy = (*t).copy()
|
||||
}
|
||||
|
||||
copies[*t] = cpy
|
||||
*t = cpy
|
||||
|
||||
@ -574,7 +595,7 @@ func copyType(typ Type) Type {
|
||||
cpy.walk(&work)
|
||||
}
|
||||
|
||||
return typ
|
||||
return typ, nil
|
||||
}
|
||||
|
||||
// typeDeque keeps track of pointers to types which still
|
||||
@ -783,7 +804,7 @@ func inflateRawTypes(rawTypes []rawType, rawStrings stringTable) (types []Type,
|
||||
typ = restrict
|
||||
|
||||
case kindFunc:
|
||||
fn := &Func{id, name, nil}
|
||||
fn := &Func{id, name, nil, raw.Linkage()}
|
||||
fixup(raw.Type(), kindFuncProto, &fn.Type)
|
||||
typ = fn
|
||||
|
||||
@ -808,7 +829,8 @@ func inflateRawTypes(rawTypes []rawType, rawStrings stringTable) (types []Type,
|
||||
typ = fp
|
||||
|
||||
case kindVar:
|
||||
v := &Var{id, name, nil}
|
||||
variable := raw.data.(*btfVariable)
|
||||
v := &Var{id, name, nil, VarLinkage(variable.Linkage)}
|
||||
fixup(raw.Type(), kindUnknown, &v.Type)
|
||||
typ = v
|
||||
|
||||
|
16
src/runtime/vendor/github.com/cilium/ebpf/internal/elf.go
generated
vendored
16
src/runtime/vendor/github.com/cilium/ebpf/internal/elf.go
generated
vendored
@ -50,3 +50,19 @@ func (se *SafeELFFile) Symbols() (syms []elf.Symbol, err error) {
|
||||
syms, err = se.File.Symbols()
|
||||
return
|
||||
}
|
||||
|
||||
// DynamicSymbols is the safe version of elf.File.DynamicSymbols.
|
||||
func (se *SafeELFFile) DynamicSymbols() (syms []elf.Symbol, err error) {
|
||||
defer func() {
|
||||
r := recover()
|
||||
if r == nil {
|
||||
return
|
||||
}
|
||||
|
||||
syms = nil
|
||||
err = fmt.Errorf("reading ELF dynamic symbols panicked: %s", r)
|
||||
}()
|
||||
|
||||
syms, err = se.File.DynamicSymbols()
|
||||
return
|
||||
}
|
||||
|
5
src/runtime/vendor/github.com/cilium/ebpf/internal/endian.go
generated
vendored
5
src/runtime/vendor/github.com/cilium/ebpf/internal/endian.go
generated
vendored
@ -9,11 +9,16 @@ import (
|
||||
// depending on the host's endianness.
|
||||
var NativeEndian binary.ByteOrder
|
||||
|
||||
// Clang is set to either "el" or "eb" depending on the host's endianness.
|
||||
var ClangEndian string
|
||||
|
||||
func init() {
|
||||
if isBigEndian() {
|
||||
NativeEndian = binary.BigEndian
|
||||
ClangEndian = "eb"
|
||||
} else {
|
||||
NativeEndian = binary.LittleEndian
|
||||
ClangEndian = "el"
|
||||
}
|
||||
}
|
||||
|
||||
|
4
src/runtime/vendor/github.com/cilium/ebpf/internal/errors.go
generated
vendored
4
src/runtime/vendor/github.com/cilium/ebpf/internal/errors.go
generated
vendored
@ -29,6 +29,10 @@ type VerifierError struct {
|
||||
log string
|
||||
}
|
||||
|
||||
func (le *VerifierError) Unwrap() error {
|
||||
return le.cause
|
||||
}
|
||||
|
||||
func (le *VerifierError) Error() string {
|
||||
if le.log == "" {
|
||||
return le.cause.Error()
|
||||
|
38
src/runtime/vendor/github.com/cilium/ebpf/internal/feature.go
generated
vendored
38
src/runtime/vendor/github.com/cilium/ebpf/internal/feature.go
generated
vendored
@ -98,41 +98,3 @@ func FeatureTest(name, version string, fn FeatureTestFn) func() error {
|
||||
return ft.result
|
||||
}
|
||||
}
|
||||
|
||||
// A Version in the form Major.Minor.Patch.
|
||||
type Version [3]uint16
|
||||
|
||||
// NewVersion creates a version from a string like "Major.Minor.Patch".
|
||||
//
|
||||
// Patch is optional.
|
||||
func NewVersion(ver string) (Version, error) {
|
||||
var major, minor, patch uint16
|
||||
n, _ := fmt.Sscanf(ver, "%d.%d.%d", &major, &minor, &patch)
|
||||
if n < 2 {
|
||||
return Version{}, fmt.Errorf("invalid version: %s", ver)
|
||||
}
|
||||
return Version{major, minor, patch}, nil
|
||||
}
|
||||
|
||||
func (v Version) String() string {
|
||||
if v[2] == 0 {
|
||||
return fmt.Sprintf("v%d.%d", v[0], v[1])
|
||||
}
|
||||
return fmt.Sprintf("v%d.%d.%d", v[0], v[1], v[2])
|
||||
}
|
||||
|
||||
// Less returns true if the version is less than another version.
|
||||
func (v Version) Less(other Version) bool {
|
||||
for i, a := range v {
|
||||
if a == other[i] {
|
||||
continue
|
||||
}
|
||||
return a < other[i]
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Unspecified returns true if the version is all zero.
|
||||
func (v Version) Unspecified() bool {
|
||||
return v[0] == 0 && v[1] == 0 && v[2] == 0
|
||||
}
|
||||
|
@ -1,36 +1,38 @@
|
||||
package ebpf
|
||||
package internal
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/cilium/ebpf/internal"
|
||||
"github.com/cilium/ebpf/internal/unix"
|
||||
)
|
||||
|
||||
func pin(currentPath, newPath string, fd *internal.FD) error {
|
||||
func Pin(currentPath, newPath string, fd *FD) error {
|
||||
if newPath == "" {
|
||||
return errors.New("given pinning path cannot be empty")
|
||||
}
|
||||
if currentPath == "" {
|
||||
return internal.BPFObjPin(newPath, fd)
|
||||
}
|
||||
if currentPath == newPath {
|
||||
return nil
|
||||
}
|
||||
if currentPath == "" {
|
||||
return BPFObjPin(newPath, fd)
|
||||
}
|
||||
var err error
|
||||
// Object is now moved to the new pinning path.
|
||||
if err = os.Rename(currentPath, newPath); err == nil {
|
||||
// Renameat2 is used instead of os.Rename to disallow the new path replacing
|
||||
// an existing path.
|
||||
if err = unix.Renameat2(unix.AT_FDCWD, currentPath, unix.AT_FDCWD, newPath, unix.RENAME_NOREPLACE); err == nil {
|
||||
// Object is now moved to the new pinning path.
|
||||
return nil
|
||||
}
|
||||
if !os.IsNotExist(err) {
|
||||
return fmt.Errorf("unable to move pinned object to new path %v: %w", newPath, err)
|
||||
}
|
||||
// Internal state not in sync with the file system so let's fix it.
|
||||
return internal.BPFObjPin(newPath, fd)
|
||||
return BPFObjPin(newPath, fd)
|
||||
}
|
||||
|
||||
func unpin(pinnedPath string) error {
|
||||
func Unpin(pinnedPath string) error {
|
||||
if pinnedPath == "" {
|
||||
return nil
|
||||
}
|
15
src/runtime/vendor/github.com/cilium/ebpf/internal/ptr.go
generated
vendored
15
src/runtime/vendor/github.com/cilium/ebpf/internal/ptr.go
generated
vendored
@ -1,6 +1,10 @@
|
||||
package internal
|
||||
|
||||
import "unsafe"
|
||||
import (
|
||||
"unsafe"
|
||||
|
||||
"github.com/cilium/ebpf/internal/unix"
|
||||
)
|
||||
|
||||
// NewPointer creates a 64-bit pointer from an unsafe Pointer.
|
||||
func NewPointer(ptr unsafe.Pointer) Pointer {
|
||||
@ -18,13 +22,10 @@ func NewSlicePointer(buf []byte) Pointer {
|
||||
|
||||
// NewStringPointer creates a 64-bit pointer from a string.
|
||||
func NewStringPointer(str string) Pointer {
|
||||
if str == "" {
|
||||
p, err := unix.BytePtrFromString(str)
|
||||
if err != nil {
|
||||
return Pointer{}
|
||||
}
|
||||
|
||||
// The kernel expects strings to be zero terminated
|
||||
buf := make([]byte, len(str)+1)
|
||||
copy(buf, str)
|
||||
|
||||
return Pointer{ptr: unsafe.Pointer(&buf[0])}
|
||||
return Pointer{ptr: unsafe.Pointer(p)}
|
||||
}
|
||||
|
72
src/runtime/vendor/github.com/cilium/ebpf/internal/syscall.go
generated
vendored
72
src/runtime/vendor/github.com/cilium/ebpf/internal/syscall.go
generated
vendored
@ -4,6 +4,7 @@ import (
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
|
||||
"github.com/cilium/ebpf/internal/unix"
|
||||
@ -61,7 +62,7 @@ func BPF(cmd BPFCmd, attr unsafe.Pointer, size uintptr) (uintptr, error) {
|
||||
|
||||
var err error
|
||||
if errNo != 0 {
|
||||
err = errNo
|
||||
err = wrappedErrno{errNo}
|
||||
}
|
||||
|
||||
return r1, err
|
||||
@ -140,9 +141,10 @@ func BPFObjPin(fileName string, fd *FD) error {
|
||||
}
|
||||
|
||||
// BPFObjGet wraps BPF_OBJ_GET.
|
||||
func BPFObjGet(fileName string) (*FD, error) {
|
||||
func BPFObjGet(fileName string, flags uint32) (*FD, error) {
|
||||
attr := bpfObjAttr{
|
||||
fileName: NewStringPointer(fileName),
|
||||
fileName: NewStringPointer(fileName),
|
||||
fileFlags: flags,
|
||||
}
|
||||
ptr, err := BPF(BPF_OBJ_GET, unsafe.Pointer(&attr), unsafe.Sizeof(attr))
|
||||
if err != nil {
|
||||
@ -177,3 +179,67 @@ func BPFObjGetInfoByFD(fd *FD, info unsafe.Pointer, size uintptr) error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// BPFObjName is a null-terminated string made up of
|
||||
// 'A-Za-z0-9_' characters.
|
||||
type BPFObjName [unix.BPF_OBJ_NAME_LEN]byte
|
||||
|
||||
// NewBPFObjName truncates the result if it is too long.
|
||||
func NewBPFObjName(name string) BPFObjName {
|
||||
var result BPFObjName
|
||||
copy(result[:unix.BPF_OBJ_NAME_LEN-1], name)
|
||||
return result
|
||||
}
|
||||
|
||||
type BPFMapCreateAttr struct {
|
||||
MapType uint32
|
||||
KeySize uint32
|
||||
ValueSize uint32
|
||||
MaxEntries uint32
|
||||
Flags uint32
|
||||
InnerMapFd uint32 // since 4.12 56f668dfe00d
|
||||
NumaNode uint32 // since 4.14 96eabe7a40aa
|
||||
MapName BPFObjName // since 4.15 ad5b177bd73f
|
||||
MapIfIndex uint32
|
||||
BTFFd uint32
|
||||
BTFKeyTypeID uint32
|
||||
BTFValueTypeID uint32
|
||||
}
|
||||
|
||||
func BPFMapCreate(attr *BPFMapCreateAttr) (*FD, error) {
|
||||
fd, err := BPF(BPF_MAP_CREATE, unsafe.Pointer(attr), unsafe.Sizeof(*attr))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return NewFD(uint32(fd)), nil
|
||||
}
|
||||
|
||||
// wrappedErrno wraps syscall.Errno to prevent direct comparisons with
|
||||
// syscall.E* or unix.E* constants.
|
||||
//
|
||||
// You should never export an error of this type.
|
||||
type wrappedErrno struct {
|
||||
syscall.Errno
|
||||
}
|
||||
|
||||
func (we wrappedErrno) Unwrap() error {
|
||||
return we.Errno
|
||||
}
|
||||
|
||||
type syscallError struct {
|
||||
error
|
||||
errno syscall.Errno
|
||||
}
|
||||
|
||||
func SyscallError(err error, errno syscall.Errno) error {
|
||||
return &syscallError{err, errno}
|
||||
}
|
||||
|
||||
func (se *syscallError) Is(target error) bool {
|
||||
return target == se.error
|
||||
}
|
||||
|
||||
func (se *syscallError) Unwrap() error {
|
||||
return se.errno
|
||||
}
|
||||
|
34
src/runtime/vendor/github.com/cilium/ebpf/internal/unix/types_linux.go
generated
vendored
34
src/runtime/vendor/github.com/cilium/ebpf/internal/unix/types_linux.go
generated
vendored
@ -26,8 +26,13 @@ const (
|
||||
EBADF = linux.EBADF
|
||||
BPF_F_NO_PREALLOC = linux.BPF_F_NO_PREALLOC
|
||||
BPF_F_NUMA_NODE = linux.BPF_F_NUMA_NODE
|
||||
BPF_F_RDONLY = linux.BPF_F_RDONLY
|
||||
BPF_F_WRONLY = linux.BPF_F_WRONLY
|
||||
BPF_F_RDONLY_PROG = linux.BPF_F_RDONLY_PROG
|
||||
BPF_F_WRONLY_PROG = linux.BPF_F_WRONLY_PROG
|
||||
BPF_F_SLEEPABLE = linux.BPF_F_SLEEPABLE
|
||||
BPF_F_MMAPABLE = linux.BPF_F_MMAPABLE
|
||||
BPF_F_INNER_MAP = linux.BPF_F_INNER_MAP
|
||||
BPF_OBJ_NAME_LEN = linux.BPF_OBJ_NAME_LEN
|
||||
BPF_TAG_SIZE = linux.BPF_TAG_SIZE
|
||||
SYS_BPF = linux.SYS_BPF
|
||||
@ -39,14 +44,23 @@ const (
|
||||
PROT_READ = linux.PROT_READ
|
||||
PROT_WRITE = linux.PROT_WRITE
|
||||
MAP_SHARED = linux.MAP_SHARED
|
||||
PERF_ATTR_SIZE_VER1 = linux.PERF_ATTR_SIZE_VER1
|
||||
PERF_TYPE_SOFTWARE = linux.PERF_TYPE_SOFTWARE
|
||||
PERF_TYPE_TRACEPOINT = linux.PERF_TYPE_TRACEPOINT
|
||||
PERF_COUNT_SW_BPF_OUTPUT = linux.PERF_COUNT_SW_BPF_OUTPUT
|
||||
PERF_EVENT_IOC_DISABLE = linux.PERF_EVENT_IOC_DISABLE
|
||||
PERF_EVENT_IOC_ENABLE = linux.PERF_EVENT_IOC_ENABLE
|
||||
PERF_EVENT_IOC_SET_BPF = linux.PERF_EVENT_IOC_SET_BPF
|
||||
PerfBitWatermark = linux.PerfBitWatermark
|
||||
PERF_SAMPLE_RAW = linux.PERF_SAMPLE_RAW
|
||||
PERF_FLAG_FD_CLOEXEC = linux.PERF_FLAG_FD_CLOEXEC
|
||||
RLIM_INFINITY = linux.RLIM_INFINITY
|
||||
RLIMIT_MEMLOCK = linux.RLIMIT_MEMLOCK
|
||||
BPF_STATS_RUN_TIME = linux.BPF_STATS_RUN_TIME
|
||||
PERF_RECORD_LOST = linux.PERF_RECORD_LOST
|
||||
PERF_RECORD_SAMPLE = linux.PERF_RECORD_SAMPLE
|
||||
AT_FDCWD = linux.AT_FDCWD
|
||||
RENAME_NOREPLACE = linux.RENAME_NOREPLACE
|
||||
)
|
||||
|
||||
// Statfs_t is a wrapper
|
||||
@ -70,6 +84,11 @@ func FcntlInt(fd uintptr, cmd, arg int) (int, error) {
|
||||
return linux.FcntlInt(fd, cmd, arg)
|
||||
}
|
||||
|
||||
// IoctlSetInt is a wrapper
|
||||
func IoctlSetInt(fd int, req uint, value int) error {
|
||||
return linux.IoctlSetInt(fd, req, value)
|
||||
}
|
||||
|
||||
// Statfs is a wrapper
|
||||
func Statfs(path string, buf *Statfs_t) (err error) {
|
||||
return linux.Statfs(path, buf)
|
||||
@ -157,6 +176,21 @@ func Tgkill(tgid int, tid int, sig syscall.Signal) (err error) {
|
||||
return linux.Tgkill(tgid, tid, sig)
|
||||
}
|
||||
|
||||
// BytePtrFromString is a wrapper
|
||||
func BytePtrFromString(s string) (*byte, error) {
|
||||
return linux.BytePtrFromString(s)
|
||||
}
|
||||
|
||||
// ByteSliceToString is a wrapper
|
||||
func ByteSliceToString(s []byte) string {
|
||||
return linux.ByteSliceToString(s)
|
||||
}
|
||||
|
||||
// Renameat2 is a wrapper
|
||||
func Renameat2(olddirfd int, oldpath string, newdirfd int, newpath string, flags uint) error {
|
||||
return linux.Renameat2(olddirfd, oldpath, newdirfd, newpath, flags)
|
||||
}
|
||||
|
||||
func KernelRelease() (string, error) {
|
||||
var uname Utsname
|
||||
err := Uname(&uname)
|
||||
|
35
src/runtime/vendor/github.com/cilium/ebpf/internal/unix/types_other.go
generated
vendored
35
src/runtime/vendor/github.com/cilium/ebpf/internal/unix/types_other.go
generated
vendored
@ -26,8 +26,13 @@ const (
|
||||
|
||||
BPF_F_NO_PREALLOC = 0
|
||||
BPF_F_NUMA_NODE = 0
|
||||
BPF_F_RDONLY = 0
|
||||
BPF_F_WRONLY = 0
|
||||
BPF_F_RDONLY_PROG = 0
|
||||
BPF_F_WRONLY_PROG = 0
|
||||
BPF_F_SLEEPABLE = 0
|
||||
BPF_F_MMAPABLE = 0
|
||||
BPF_F_INNER_MAP = 0
|
||||
BPF_OBJ_NAME_LEN = 0x10
|
||||
BPF_TAG_SIZE = 0x8
|
||||
SYS_BPF = 321
|
||||
@ -40,14 +45,23 @@ const (
|
||||
PROT_READ = 0x1
|
||||
PROT_WRITE = 0x2
|
||||
MAP_SHARED = 0x1
|
||||
PERF_ATTR_SIZE_VER1 = 0
|
||||
PERF_TYPE_SOFTWARE = 0x1
|
||||
PERF_TYPE_TRACEPOINT = 0
|
||||
PERF_COUNT_SW_BPF_OUTPUT = 0xa
|
||||
PERF_EVENT_IOC_DISABLE = 0
|
||||
PERF_EVENT_IOC_ENABLE = 0
|
||||
PERF_EVENT_IOC_SET_BPF = 0
|
||||
PerfBitWatermark = 0x4000
|
||||
PERF_SAMPLE_RAW = 0x400
|
||||
PERF_FLAG_FD_CLOEXEC = 0x8
|
||||
RLIM_INFINITY = 0x7fffffffffffffff
|
||||
RLIMIT_MEMLOCK = 8
|
||||
BPF_STATS_RUN_TIME = 0
|
||||
PERF_RECORD_LOST = 2
|
||||
PERF_RECORD_SAMPLE = 9
|
||||
AT_FDCWD = -0x2
|
||||
RENAME_NOREPLACE = 0x1
|
||||
)
|
||||
|
||||
// Statfs_t is a wrapper
|
||||
@ -87,6 +101,11 @@ func FcntlInt(fd uintptr, cmd, arg int) (int, error) {
|
||||
return -1, errNonLinux
|
||||
}
|
||||
|
||||
// IoctlSetInt is a wrapper
|
||||
func IoctlSetInt(fd int, req uint, value int) error {
|
||||
return errNonLinux
|
||||
}
|
||||
|
||||
// Statfs is a wrapper
|
||||
func Statfs(path string, buf *Statfs_t) error {
|
||||
return errNonLinux
|
||||
@ -201,6 +220,7 @@ func PerfEventOpen(attr *PerfEventAttr, pid int, cpu int, groupFd int, flags int
|
||||
// Utsname is a wrapper
|
||||
type Utsname struct {
|
||||
Release [65]byte
|
||||
Version [65]byte
|
||||
}
|
||||
|
||||
// Uname is a wrapper
|
||||
@ -223,6 +243,21 @@ func Tgkill(tgid int, tid int, sig syscall.Signal) (err error) {
|
||||
return errNonLinux
|
||||
}
|
||||
|
||||
// BytePtrFromString is a wrapper
|
||||
func BytePtrFromString(s string) (*byte, error) {
|
||||
return nil, errNonLinux
|
||||
}
|
||||
|
||||
// ByteSliceToString is a wrapper
|
||||
func ByteSliceToString(s []byte) string {
|
||||
return ""
|
||||
}
|
||||
|
||||
// Renameat2 is a wrapper
|
||||
func Renameat2(olddirfd int, oldpath string, newdirfd int, newpath string, flags uint) error {
|
||||
return errNonLinux
|
||||
}
|
||||
|
||||
func KernelRelease() (string, error) {
|
||||
return "", errNonLinux
|
||||
}
|
||||
|
163
src/runtime/vendor/github.com/cilium/ebpf/internal/version.go
generated
vendored
Normal file
163
src/runtime/vendor/github.com/cilium/ebpf/internal/version.go
generated
vendored
Normal file
@ -0,0 +1,163 @@
|
||||
package internal
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"regexp"
|
||||
"sync"
|
||||
|
||||
"github.com/cilium/ebpf/internal/unix"
|
||||
)
|
||||
|
||||
const (
|
||||
// Version constant used in ELF binaries indicating that the loader needs to
|
||||
// substitute the eBPF program's version with the value of the kernel's
|
||||
// KERNEL_VERSION compile-time macro. Used for compatibility with BCC, gobpf
|
||||
// and RedSift.
|
||||
MagicKernelVersion = 0xFFFFFFFE
|
||||
)
|
||||
|
||||
var (
|
||||
// Match between one and three decimals separated by dots, with the last
|
||||
// segment (patch level) being optional on some kernels.
|
||||
// The x.y.z string must appear at the start of a string or right after
|
||||
// whitespace to prevent sequences like 'x.y.z-a.b.c' from matching 'a.b.c'.
|
||||
rgxKernelVersion = regexp.MustCompile(`(?:\A|\s)\d{1,3}\.\d{1,3}(?:\.\d{1,3})?`)
|
||||
|
||||
kernelVersion = struct {
|
||||
once sync.Once
|
||||
version Version
|
||||
err error
|
||||
}{}
|
||||
)
|
||||
|
||||
// A Version in the form Major.Minor.Patch.
|
||||
type Version [3]uint16
|
||||
|
||||
// NewVersion creates a version from a string like "Major.Minor.Patch".
|
||||
//
|
||||
// Patch is optional.
|
||||
func NewVersion(ver string) (Version, error) {
|
||||
var major, minor, patch uint16
|
||||
n, _ := fmt.Sscanf(ver, "%d.%d.%d", &major, &minor, &patch)
|
||||
if n < 2 {
|
||||
return Version{}, fmt.Errorf("invalid version: %s", ver)
|
||||
}
|
||||
return Version{major, minor, patch}, nil
|
||||
}
|
||||
|
||||
func (v Version) String() string {
|
||||
if v[2] == 0 {
|
||||
return fmt.Sprintf("v%d.%d", v[0], v[1])
|
||||
}
|
||||
return fmt.Sprintf("v%d.%d.%d", v[0], v[1], v[2])
|
||||
}
|
||||
|
||||
// Less returns true if the version is less than another version.
|
||||
func (v Version) Less(other Version) bool {
|
||||
for i, a := range v {
|
||||
if a == other[i] {
|
||||
continue
|
||||
}
|
||||
return a < other[i]
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Unspecified returns true if the version is all zero.
|
||||
func (v Version) Unspecified() bool {
|
||||
return v[0] == 0 && v[1] == 0 && v[2] == 0
|
||||
}
|
||||
|
||||
// Kernel implements the kernel's KERNEL_VERSION macro from linux/version.h.
|
||||
// It represents the kernel version and patch level as a single value.
|
||||
func (v Version) Kernel() uint32 {
|
||||
|
||||
// Kernels 4.4 and 4.9 have their SUBLEVEL clamped to 255 to avoid
|
||||
// overflowing into PATCHLEVEL.
|
||||
// See kernel commit 9b82f13e7ef3 ("kbuild: clamp SUBLEVEL to 255").
|
||||
s := v[2]
|
||||
if s > 255 {
|
||||
s = 255
|
||||
}
|
||||
|
||||
// Truncate members to uint8 to prevent them from spilling over into
|
||||
// each other when overflowing 8 bits.
|
||||
return uint32(uint8(v[0]))<<16 | uint32(uint8(v[1]))<<8 | uint32(uint8(s))
|
||||
}
|
||||
|
||||
// KernelVersion returns the version of the currently running kernel.
|
||||
func KernelVersion() (Version, error) {
|
||||
kernelVersion.once.Do(func() {
|
||||
kernelVersion.version, kernelVersion.err = detectKernelVersion()
|
||||
})
|
||||
|
||||
if kernelVersion.err != nil {
|
||||
return Version{}, kernelVersion.err
|
||||
}
|
||||
return kernelVersion.version, nil
|
||||
}
|
||||
|
||||
// detectKernelVersion returns the version of the running kernel. It scans the
|
||||
// following sources in order: /proc/version_signature, uname -v, uname -r.
|
||||
// In each of those locations, the last-appearing x.y(.z) value is selected
|
||||
// for parsing. The first location that yields a usable version number is
|
||||
// returned.
|
||||
func detectKernelVersion() (Version, error) {
|
||||
|
||||
// Try reading /proc/version_signature for Ubuntu compatibility.
|
||||
// Example format: Ubuntu 4.15.0-91.92-generic 4.15.18
|
||||
// This method exists in the kernel itself, see d18acd15c
|
||||
// ("perf tools: Fix kernel version error in ubuntu").
|
||||
if pvs, err := ioutil.ReadFile("/proc/version_signature"); err == nil {
|
||||
// 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
|
||||
// through any other method.
|
||||
v, err := findKernelVersion(string(pvs))
|
||||
if err != nil {
|
||||
return Version{}, err
|
||||
}
|
||||
return v, nil
|
||||
}
|
||||
|
||||
var uname unix.Utsname
|
||||
if err := unix.Uname(&uname); err != nil {
|
||||
return Version{}, fmt.Errorf("calling uname: %w", err)
|
||||
}
|
||||
|
||||
// Debian puts the version including the patch level in uname.Version.
|
||||
// It is not an error if there's no version number in uname.Version,
|
||||
// as most distributions don't use it. Parsing can continue on uname.Release.
|
||||
// Example format: #1 SMP Debian 4.19.37-5+deb10u2 (2019-08-08)
|
||||
if v, err := findKernelVersion(unix.ByteSliceToString(uname.Version[:])); err == nil {
|
||||
return v, nil
|
||||
}
|
||||
|
||||
// Most other distributions have the full kernel version including patch
|
||||
// level in uname.Release.
|
||||
// Example format: 4.19.0-5-amd64, 5.5.10-arch1-1
|
||||
v, err := findKernelVersion(unix.ByteSliceToString(uname.Release[:]))
|
||||
if err != nil {
|
||||
return Version{}, err
|
||||
}
|
||||
|
||||
return v, nil
|
||||
}
|
||||
|
||||
// findKernelVersion matches s against rgxKernelVersion and parses the result
|
||||
// into a Version. If s contains multiple matches, the last entry is selected.
|
||||
func findKernelVersion(s string) (Version, error) {
|
||||
m := rgxKernelVersion.FindAllString(s, -1)
|
||||
if m == nil {
|
||||
return Version{}, fmt.Errorf("no kernel version in string: %s", s)
|
||||
}
|
||||
// Pick the last match of the string in case there are multiple.
|
||||
s = m[len(m)-1]
|
||||
|
||||
v, err := NewVersion(s)
|
||||
if err != nil {
|
||||
return Version{}, fmt.Errorf("parsing version string %s: %w", s, err)
|
||||
}
|
||||
|
||||
return v, nil
|
||||
}
|
171
src/runtime/vendor/github.com/cilium/ebpf/link/cgroup.go
generated
vendored
Normal file
171
src/runtime/vendor/github.com/cilium/ebpf/link/cgroup.go
generated
vendored
Normal file
@ -0,0 +1,171 @@
|
||||
package link
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/cilium/ebpf"
|
||||
)
|
||||
|
||||
type cgroupAttachFlags uint32
|
||||
|
||||
// cgroup attach flags
|
||||
const (
|
||||
flagAllowOverride cgroupAttachFlags = 1 << iota
|
||||
flagAllowMulti
|
||||
flagReplace
|
||||
)
|
||||
|
||||
type CgroupOptions struct {
|
||||
// Path to a cgroupv2 folder.
|
||||
Path string
|
||||
// One of the AttachCgroup* constants
|
||||
Attach ebpf.AttachType
|
||||
// Program must be of type CGroup*, and the attach type must match Attach.
|
||||
Program *ebpf.Program
|
||||
}
|
||||
|
||||
// AttachCgroup links a BPF program to a cgroup.
|
||||
func AttachCgroup(opts CgroupOptions) (Link, error) {
|
||||
cgroup, err := os.Open(opts.Path)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("can't open cgroup: %s", err)
|
||||
}
|
||||
|
||||
clone, err := opts.Program.Clone()
|
||||
if err != nil {
|
||||
cgroup.Close()
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var cg Link
|
||||
cg, err = newLinkCgroup(cgroup, opts.Attach, clone)
|
||||
if errors.Is(err, ErrNotSupported) {
|
||||
cg, err = newProgAttachCgroup(cgroup, opts.Attach, clone, flagAllowMulti)
|
||||
}
|
||||
if errors.Is(err, ErrNotSupported) {
|
||||
cg, err = newProgAttachCgroup(cgroup, opts.Attach, clone, flagAllowOverride)
|
||||
}
|
||||
if err != nil {
|
||||
cgroup.Close()
|
||||
clone.Close()
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return cg, nil
|
||||
}
|
||||
|
||||
// LoadPinnedCgroup loads a pinned cgroup from a bpffs.
|
||||
func LoadPinnedCgroup(fileName string, opts *ebpf.LoadPinOptions) (Link, error) {
|
||||
link, err := LoadPinnedRawLink(fileName, CgroupType, opts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &linkCgroup{*link}, nil
|
||||
}
|
||||
|
||||
type progAttachCgroup struct {
|
||||
cgroup *os.File
|
||||
current *ebpf.Program
|
||||
attachType ebpf.AttachType
|
||||
flags cgroupAttachFlags
|
||||
}
|
||||
|
||||
var _ Link = (*progAttachCgroup)(nil)
|
||||
|
||||
func (cg *progAttachCgroup) isLink() {}
|
||||
|
||||
func newProgAttachCgroup(cgroup *os.File, attach ebpf.AttachType, prog *ebpf.Program, flags cgroupAttachFlags) (*progAttachCgroup, error) {
|
||||
if flags&flagAllowMulti > 0 {
|
||||
if err := haveProgAttachReplace(); err != nil {
|
||||
return nil, fmt.Errorf("can't support multiple programs: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
err := RawAttachProgram(RawAttachProgramOptions{
|
||||
Target: int(cgroup.Fd()),
|
||||
Program: prog,
|
||||
Flags: uint32(flags),
|
||||
Attach: attach,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cgroup: %w", err)
|
||||
}
|
||||
|
||||
return &progAttachCgroup{cgroup, prog, attach, flags}, nil
|
||||
}
|
||||
|
||||
func (cg *progAttachCgroup) Close() error {
|
||||
defer cg.cgroup.Close()
|
||||
defer cg.current.Close()
|
||||
|
||||
err := RawDetachProgram(RawDetachProgramOptions{
|
||||
Target: int(cg.cgroup.Fd()),
|
||||
Program: cg.current,
|
||||
Attach: cg.attachType,
|
||||
})
|
||||
if err != nil {
|
||||
return fmt.Errorf("close cgroup: %s", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cg *progAttachCgroup) Update(prog *ebpf.Program) error {
|
||||
new, err := prog.Clone()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
args := RawAttachProgramOptions{
|
||||
Target: int(cg.cgroup.Fd()),
|
||||
Program: prog,
|
||||
Attach: cg.attachType,
|
||||
Flags: uint32(cg.flags),
|
||||
}
|
||||
|
||||
if cg.flags&flagAllowMulti > 0 {
|
||||
// Atomically replacing multiple programs requires at least
|
||||
// 5.5 (commit 7dd68b3279f17921 "bpf: Support replacing cgroup-bpf
|
||||
// program in MULTI mode")
|
||||
args.Flags |= uint32(flagReplace)
|
||||
args.Replace = cg.current
|
||||
}
|
||||
|
||||
if err := RawAttachProgram(args); err != nil {
|
||||
new.Close()
|
||||
return fmt.Errorf("can't update cgroup: %s", err)
|
||||
}
|
||||
|
||||
cg.current.Close()
|
||||
cg.current = new
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cg *progAttachCgroup) Pin(string) error {
|
||||
return fmt.Errorf("can't pin cgroup: %w", ErrNotSupported)
|
||||
}
|
||||
|
||||
func (cg *progAttachCgroup) Unpin() error {
|
||||
return fmt.Errorf("can't pin cgroup: %w", ErrNotSupported)
|
||||
}
|
||||
|
||||
type linkCgroup struct {
|
||||
RawLink
|
||||
}
|
||||
|
||||
var _ Link = (*linkCgroup)(nil)
|
||||
|
||||
func newLinkCgroup(cgroup *os.File, attach ebpf.AttachType, prog *ebpf.Program) (*linkCgroup, error) {
|
||||
link, err := AttachRawLink(RawLinkOptions{
|
||||
Target: int(cgroup.Fd()),
|
||||
Program: prog,
|
||||
Attach: attach,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &linkCgroup{*link}, err
|
||||
}
|
2
src/runtime/vendor/github.com/cilium/ebpf/link/doc.go
generated
vendored
Normal file
2
src/runtime/vendor/github.com/cilium/ebpf/link/doc.go
generated
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
// Package link allows attaching eBPF programs to various kernel hooks.
|
||||
package link
|
100
src/runtime/vendor/github.com/cilium/ebpf/link/iter.go
generated
vendored
Normal file
100
src/runtime/vendor/github.com/cilium/ebpf/link/iter.go
generated
vendored
Normal file
@ -0,0 +1,100 @@
|
||||
package link
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"unsafe"
|
||||
|
||||
"github.com/cilium/ebpf"
|
||||
"github.com/cilium/ebpf/internal"
|
||||
)
|
||||
|
||||
type IterOptions struct {
|
||||
// Program must be of type Tracing with attach type
|
||||
// AttachTraceIter. The kind of iterator to attach to is
|
||||
// determined at load time via the AttachTo field.
|
||||
//
|
||||
// AttachTo requires the kernel to include BTF of itself,
|
||||
// and it to be compiled with a recent pahole (>= 1.16).
|
||||
Program *ebpf.Program
|
||||
|
||||
// Map specifies the target map for bpf_map_elem and sockmap iterators.
|
||||
// It may be nil.
|
||||
Map *ebpf.Map
|
||||
}
|
||||
|
||||
// AttachIter attaches a BPF seq_file iterator.
|
||||
func AttachIter(opts IterOptions) (*Iter, error) {
|
||||
if err := haveBPFLink(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
progFd := opts.Program.FD()
|
||||
if progFd < 0 {
|
||||
return nil, fmt.Errorf("invalid program: %s", internal.ErrClosedFd)
|
||||
}
|
||||
|
||||
var info bpfIterLinkInfoMap
|
||||
if opts.Map != nil {
|
||||
mapFd := opts.Map.FD()
|
||||
if mapFd < 0 {
|
||||
return nil, fmt.Errorf("invalid map: %w", internal.ErrClosedFd)
|
||||
}
|
||||
info.map_fd = uint32(mapFd)
|
||||
}
|
||||
|
||||
attr := bpfLinkCreateIterAttr{
|
||||
prog_fd: uint32(progFd),
|
||||
attach_type: ebpf.AttachTraceIter,
|
||||
iter_info: internal.NewPointer(unsafe.Pointer(&info)),
|
||||
iter_info_len: uint32(unsafe.Sizeof(info)),
|
||||
}
|
||||
|
||||
fd, err := bpfLinkCreateIter(&attr)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("can't link iterator: %w", err)
|
||||
}
|
||||
|
||||
return &Iter{RawLink{fd, ""}}, err
|
||||
}
|
||||
|
||||
// LoadPinnedIter loads a pinned iterator from a bpffs.
|
||||
func LoadPinnedIter(fileName string, opts *ebpf.LoadPinOptions) (*Iter, error) {
|
||||
link, err := LoadPinnedRawLink(fileName, IterType, opts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &Iter{*link}, err
|
||||
}
|
||||
|
||||
// Iter represents an attached bpf_iter.
|
||||
type Iter struct {
|
||||
RawLink
|
||||
}
|
||||
|
||||
// Open creates a new instance of the iterator.
|
||||
//
|
||||
// Reading from the returned reader triggers the BPF program.
|
||||
func (it *Iter) Open() (io.ReadCloser, error) {
|
||||
linkFd, err := it.fd.Value()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
attr := &bpfIterCreateAttr{
|
||||
linkFd: linkFd,
|
||||
}
|
||||
|
||||
fd, err := bpfIterCreate(attr)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("can't create iterator: %w", err)
|
||||
}
|
||||
|
||||
return fd.File("bpf_iter"), nil
|
||||
}
|
||||
|
||||
// union bpf_iter_link_info.map
|
||||
type bpfIterLinkInfoMap struct {
|
||||
map_fd uint32
|
||||
}
|
438
src/runtime/vendor/github.com/cilium/ebpf/link/kprobe.go
generated
vendored
Normal file
438
src/runtime/vendor/github.com/cilium/ebpf/link/kprobe.go
generated
vendored
Normal file
@ -0,0 +1,438 @@
|
||||
package link
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/rand"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"sync"
|
||||
"unsafe"
|
||||
|
||||
"github.com/cilium/ebpf"
|
||||
"github.com/cilium/ebpf/internal"
|
||||
"github.com/cilium/ebpf/internal/unix"
|
||||
)
|
||||
|
||||
var (
|
||||
kprobeEventsPath = filepath.Join(tracefsPath, "kprobe_events")
|
||||
|
||||
kprobeRetprobeBit = struct {
|
||||
once sync.Once
|
||||
value uint64
|
||||
err error
|
||||
}{}
|
||||
)
|
||||
|
||||
type probeType uint8
|
||||
|
||||
const (
|
||||
kprobeType probeType = iota
|
||||
uprobeType
|
||||
)
|
||||
|
||||
func (pt probeType) String() string {
|
||||
if pt == kprobeType {
|
||||
return "kprobe"
|
||||
}
|
||||
return "uprobe"
|
||||
}
|
||||
|
||||
func (pt probeType) EventsPath() string {
|
||||
if pt == kprobeType {
|
||||
return kprobeEventsPath
|
||||
}
|
||||
return uprobeEventsPath
|
||||
}
|
||||
|
||||
func (pt probeType) PerfEventType(ret bool) perfEventType {
|
||||
if pt == kprobeType {
|
||||
if ret {
|
||||
return kretprobeEvent
|
||||
}
|
||||
return kprobeEvent
|
||||
}
|
||||
if ret {
|
||||
return uretprobeEvent
|
||||
}
|
||||
return uprobeEvent
|
||||
}
|
||||
|
||||
func (pt probeType) RetprobeBit() (uint64, error) {
|
||||
if pt == kprobeType {
|
||||
return kretprobeBit()
|
||||
}
|
||||
return uretprobeBit()
|
||||
}
|
||||
|
||||
// Kprobe attaches the given eBPF program to a perf event that fires when the
|
||||
// given kernel symbol starts executing. See /proc/kallsyms for available
|
||||
// symbols. For example, printk():
|
||||
//
|
||||
// Kprobe("printk", prog)
|
||||
//
|
||||
// The resulting Link must be Closed during program shutdown to avoid leaking
|
||||
// system resources.
|
||||
func Kprobe(symbol string, prog *ebpf.Program) (Link, error) {
|
||||
k, err := kprobe(symbol, prog, false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = k.attach(prog)
|
||||
if err != nil {
|
||||
k.Close()
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return k, nil
|
||||
}
|
||||
|
||||
// Kretprobe attaches the given eBPF program to a perf event that fires right
|
||||
// before the given kernel symbol exits, with the function stack left intact.
|
||||
// See /proc/kallsyms for available symbols. For example, printk():
|
||||
//
|
||||
// Kretprobe("printk", prog)
|
||||
//
|
||||
// The resulting Link must be Closed during program shutdown to avoid leaking
|
||||
// system resources.
|
||||
func Kretprobe(symbol string, prog *ebpf.Program) (Link, error) {
|
||||
k, err := kprobe(symbol, prog, true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = k.attach(prog)
|
||||
if err != nil {
|
||||
k.Close()
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return k, nil
|
||||
}
|
||||
|
||||
// kprobe opens a perf event on the given symbol and attaches prog to it.
|
||||
// If ret is true, create a kretprobe.
|
||||
func kprobe(symbol string, prog *ebpf.Program, ret bool) (*perfEvent, error) {
|
||||
if symbol == "" {
|
||||
return nil, fmt.Errorf("symbol name cannot be empty: %w", errInvalidInput)
|
||||
}
|
||||
if prog == nil {
|
||||
return nil, fmt.Errorf("prog cannot be nil: %w", errInvalidInput)
|
||||
}
|
||||
if !rgxTraceEvent.MatchString(symbol) {
|
||||
return nil, fmt.Errorf("symbol '%s' must be alphanumeric or underscore: %w", symbol, errInvalidInput)
|
||||
}
|
||||
if prog.Type() != ebpf.Kprobe {
|
||||
return nil, fmt.Errorf("eBPF program type %s is not a Kprobe: %w", prog.Type(), errInvalidInput)
|
||||
}
|
||||
|
||||
// Use kprobe PMU if the kernel has it available.
|
||||
tp, err := pmuKprobe(platformPrefix(symbol), ret)
|
||||
if errors.Is(err, os.ErrNotExist) {
|
||||
tp, err = pmuKprobe(symbol, ret)
|
||||
}
|
||||
if err == nil {
|
||||
return tp, nil
|
||||
}
|
||||
if err != nil && !errors.Is(err, ErrNotSupported) {
|
||||
return nil, fmt.Errorf("creating perf_kprobe PMU: %w", err)
|
||||
}
|
||||
|
||||
// Use tracefs if kprobe PMU is missing.
|
||||
tp, err = tracefsKprobe(platformPrefix(symbol), ret)
|
||||
if errors.Is(err, os.ErrNotExist) {
|
||||
tp, err = tracefsKprobe(symbol, ret)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("creating trace event '%s' in tracefs: %w", symbol, err)
|
||||
}
|
||||
|
||||
return tp, nil
|
||||
}
|
||||
|
||||
// pmuKprobe opens a perf event based on the kprobe PMU.
|
||||
// Returns os.ErrNotExist if the given symbol does not exist in the kernel.
|
||||
func pmuKprobe(symbol string, ret bool) (*perfEvent, error) {
|
||||
return pmuProbe(kprobeType, symbol, "", 0, ret)
|
||||
}
|
||||
|
||||
// pmuProbe opens a perf event based on a Performance Monitoring Unit.
|
||||
//
|
||||
// Requires at least a 4.17 kernel.
|
||||
// e12f03d7031a "perf/core: Implement the 'perf_kprobe' PMU"
|
||||
// 33ea4b24277b "perf/core: Implement the 'perf_uprobe' 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) {
|
||||
// Getting the PMU type will fail if the kernel doesn't support
|
||||
// the perf_[k,u]probe PMU.
|
||||
et, err := getPMUEventType(typ)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var config uint64
|
||||
if ret {
|
||||
bit, err := typ.RetprobeBit()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
config |= 1 << bit
|
||||
}
|
||||
|
||||
var (
|
||||
attr unix.PerfEventAttr
|
||||
sp unsafe.Pointer
|
||||
)
|
||||
switch typ {
|
||||
case kprobeType:
|
||||
// Create a pointer to a NUL-terminated string for the kernel.
|
||||
sp, err := unsafeStringPtr(symbol)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
attr = unix.PerfEventAttr{
|
||||
Type: uint32(et), // PMU event type read from sysfs
|
||||
Ext1: uint64(uintptr(sp)), // Kernel symbol to trace
|
||||
Config: config, // Retprobe flag
|
||||
}
|
||||
case uprobeType:
|
||||
sp, err := unsafeStringPtr(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
attr = unix.PerfEventAttr{
|
||||
// The minimum size required for PMU uprobes is PERF_ATTR_SIZE_VER1,
|
||||
// since it added the config2 (Ext2) field. The Size field controls the
|
||||
// size of the internal buffer the kernel allocates for reading the
|
||||
// perf_event_attr argument from userspace.
|
||||
Size: unix.PERF_ATTR_SIZE_VER1,
|
||||
Type: uint32(et), // PMU event type read from sysfs
|
||||
Ext1: uint64(uintptr(sp)), // Uprobe path
|
||||
Ext2: offset, // Uprobe offset
|
||||
Config: config, // Retprobe flag
|
||||
}
|
||||
}
|
||||
|
||||
fd, err := unix.PerfEventOpen(&attr, perfAllThreads, 0, -1, unix.PERF_FLAG_FD_CLOEXEC)
|
||||
|
||||
// Since commit 97c753e62e6c, ENOENT is correctly returned instead of EINVAL
|
||||
// when trying to create a kretprobe for a missing symbol. Make sure ENOENT
|
||||
// is returned to the caller.
|
||||
if errors.Is(err, os.ErrNotExist) || errors.Is(err, unix.EINVAL) {
|
||||
return nil, fmt.Errorf("symbol '%s' not found: %w", symbol, os.ErrNotExist)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("opening perf event: %w", err)
|
||||
}
|
||||
|
||||
// Ensure the string pointer is not collected before PerfEventOpen returns.
|
||||
runtime.KeepAlive(sp)
|
||||
|
||||
// Kernel has perf_[k,u]probe PMU available, initialize perf event.
|
||||
return &perfEvent{
|
||||
fd: internal.NewFD(uint32(fd)),
|
||||
pmuID: et,
|
||||
name: symbol,
|
||||
typ: typ.PerfEventType(ret),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// tracefsKprobe creates a Kprobe tracefs entry.
|
||||
func tracefsKprobe(symbol string, ret bool) (*perfEvent, error) {
|
||||
return tracefsProbe(kprobeType, symbol, "", 0, ret)
|
||||
}
|
||||
|
||||
// tracefsProbe creates a trace event by writing an entry to <tracefs>/[k,u]probe_events.
|
||||
// A new trace event group name is generated on every call to support creating
|
||||
// multiple trace events for the same kernel or userspace symbol.
|
||||
// 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.
|
||||
// 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) {
|
||||
// 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
|
||||
// multiple kprobe trace events with the same name.
|
||||
group, err := randomGroup("ebpf")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("randomizing group name: %w", err)
|
||||
}
|
||||
|
||||
// Before attempting to create a trace event through tracefs,
|
||||
// check if an event with the same group and name already exists.
|
||||
// Kernels 4.x and earlier don't return os.ErrExist on writing a duplicate
|
||||
// entry, so we need to rely on reads for detecting uniqueness.
|
||||
_, err = getTraceEventID(group, symbol)
|
||||
if err == nil {
|
||||
return nil, fmt.Errorf("trace event already exists: %s/%s", group, symbol)
|
||||
}
|
||||
if err != nil && !errors.Is(err, os.ErrNotExist) {
|
||||
return nil, fmt.Errorf("checking trace event %s/%s: %w", group, symbol, err)
|
||||
}
|
||||
|
||||
// Create the [k,u]probe trace event using tracefs.
|
||||
if err := createTraceFSProbeEvent(typ, group, symbol, path, offset, ret); err != nil {
|
||||
return nil, fmt.Errorf("creating probe entry on tracefs: %w", err)
|
||||
}
|
||||
|
||||
// Get the newly-created trace event's id.
|
||||
tid, err := getTraceEventID(group, symbol)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("getting trace event id: %w", err)
|
||||
}
|
||||
|
||||
// Kprobes are ephemeral tracepoints and share the same perf event type.
|
||||
fd, err := openTracepointPerfEvent(tid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &perfEvent{
|
||||
fd: fd,
|
||||
group: group,
|
||||
name: symbol,
|
||||
tracefsID: tid,
|
||||
typ: typ.PerfEventType(ret),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// createTraceFSProbeEvent creates a new ephemeral trace event by writing to
|
||||
// <tracefs>/[k,u]probe_events. Returns os.ErrNotExist if symbol is not a valid
|
||||
// kernel symbol, or if it is not traceable with kprobes. Returns os.ErrExist
|
||||
// if a probe with the same group and symbol already exists.
|
||||
func createTraceFSProbeEvent(typ probeType, group, symbol, path string, offset uint64, ret bool) error {
|
||||
// Open the kprobe_events file in tracefs.
|
||||
f, err := os.OpenFile(typ.EventsPath(), os.O_APPEND|os.O_WRONLY, 0666)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error opening '%s': %w", typ.EventsPath(), err)
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
var pe string
|
||||
switch typ {
|
||||
case kprobeType:
|
||||
// The kprobe_events syntax is as follows (see Documentation/trace/kprobetrace.txt):
|
||||
// p[:[GRP/]EVENT] [MOD:]SYM[+offs]|MEMADDR [FETCHARGS] : Set a probe
|
||||
// r[MAXACTIVE][:[GRP/]EVENT] [MOD:]SYM[+0] [FETCHARGS] : Set a return probe
|
||||
// -:[GRP/]EVENT : Clear a probe
|
||||
//
|
||||
// Some examples:
|
||||
// r:ebpf_1234/r_my_kretprobe nf_conntrack_destroy
|
||||
// p:ebpf_5678/p_my_kprobe __x64_sys_execve
|
||||
//
|
||||
// Leaving the kretprobe's MAXACTIVE set to 0 (or absent) will make the
|
||||
// kernel default to NR_CPUS. This is desired in most eBPF cases since
|
||||
// subsampling or rate limiting logic can be more accurately implemented in
|
||||
// the eBPF program itself.
|
||||
// See Documentation/kprobes.txt for more details.
|
||||
pe = fmt.Sprintf("%s:%s/%s %s", probePrefix(ret), group, symbol, symbol)
|
||||
case uprobeType:
|
||||
// The uprobe_events syntax is as follows:
|
||||
// p[:[GRP/]EVENT] PATH:OFFSET [FETCHARGS] : Set a probe
|
||||
// r[:[GRP/]EVENT] PATH:OFFSET [FETCHARGS] : Set a return probe
|
||||
// -:[GRP/]EVENT : Clear a probe
|
||||
//
|
||||
// Some examples:
|
||||
// r:ebpf_1234/readline /bin/bash:0x12345
|
||||
// p:ebpf_5678/main_mySymbol /bin/mybin:0x12345
|
||||
//
|
||||
// See Documentation/trace/uprobetracer.txt for more details.
|
||||
pathOffset := uprobePathOffset(path, offset)
|
||||
pe = fmt.Sprintf("%s:%s/%s %s", probePrefix(ret), group, symbol, pathOffset)
|
||||
}
|
||||
_, err = f.WriteString(pe)
|
||||
// Since commit 97c753e62e6c, ENOENT is correctly returned instead of EINVAL
|
||||
// when trying to create a kretprobe for a missing symbol. Make sure ENOENT
|
||||
// is returned to the caller.
|
||||
if errors.Is(err, os.ErrNotExist) || errors.Is(err, unix.EINVAL) {
|
||||
return fmt.Errorf("symbol %s not found: %w", symbol, os.ErrNotExist)
|
||||
}
|
||||
if err != nil {
|
||||
return fmt.Errorf("writing '%s' to '%s': %w", pe, typ.EventsPath(), err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// closeTraceFSProbeEvent removes the [k,u]probe with the given type, group and symbol
|
||||
// from <tracefs>/[k,u]probe_events.
|
||||
func closeTraceFSProbeEvent(typ probeType, group, symbol string) error {
|
||||
f, err := os.OpenFile(typ.EventsPath(), os.O_APPEND|os.O_WRONLY, 0666)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error opening %s: %w", typ.EventsPath(), err)
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
// See [k,u]probe_events syntax above. The probe type does not need to be specified
|
||||
// for removals.
|
||||
pe := fmt.Sprintf("-:%s/%s", group, symbol)
|
||||
if _, err = f.WriteString(pe); err != nil {
|
||||
return fmt.Errorf("writing '%s' to '%s': %w", pe, typ.EventsPath(), err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// randomGroup generates a pseudorandom string for use as a tracefs group name.
|
||||
// Returns an error when the output string would exceed 63 characters (kernel
|
||||
// limitation), when rand.Read() fails or when prefix contains characters not
|
||||
// allowed by rgxTraceEvent.
|
||||
func randomGroup(prefix string) (string, error) {
|
||||
if !rgxTraceEvent.MatchString(prefix) {
|
||||
return "", fmt.Errorf("prefix '%s' must be alphanumeric or underscore: %w", prefix, errInvalidInput)
|
||||
}
|
||||
|
||||
b := make([]byte, 8)
|
||||
if _, err := rand.Read(b); err != nil {
|
||||
return "", fmt.Errorf("reading random bytes: %w", err)
|
||||
}
|
||||
|
||||
group := fmt.Sprintf("%s_%x", prefix, b)
|
||||
if len(group) > 63 {
|
||||
return "", fmt.Errorf("group name '%s' cannot be longer than 63 characters: %w", group, errInvalidInput)
|
||||
}
|
||||
|
||||
return group, nil
|
||||
}
|
||||
|
||||
func probePrefix(ret bool) string {
|
||||
if ret {
|
||||
return "r"
|
||||
}
|
||||
return "p"
|
||||
}
|
||||
|
||||
// determineRetprobeBit reads a Performance Monitoring Unit's retprobe bit
|
||||
// from /sys/bus/event_source/devices/<pmu>/format/retprobe.
|
||||
func determineRetprobeBit(typ probeType) (uint64, error) {
|
||||
p := filepath.Join("/sys/bus/event_source/devices/", typ.String(), "/format/retprobe")
|
||||
|
||||
data, err := ioutil.ReadFile(p)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
var rp uint64
|
||||
n, err := fmt.Sscanf(string(bytes.TrimSpace(data)), "config:%d", &rp)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("parse retprobe bit: %w", err)
|
||||
}
|
||||
if n != 1 {
|
||||
return 0, fmt.Errorf("parse retprobe bit: expected 1 item, got %d", n)
|
||||
}
|
||||
|
||||
return rp, nil
|
||||
}
|
||||
|
||||
func kretprobeBit() (uint64, error) {
|
||||
kprobeRetprobeBit.once.Do(func() {
|
||||
kprobeRetprobeBit.value, kprobeRetprobeBit.err = determineRetprobeBit(kprobeType)
|
||||
})
|
||||
return kprobeRetprobeBit.value, kprobeRetprobeBit.err
|
||||
}
|
229
src/runtime/vendor/github.com/cilium/ebpf/link/link.go
generated
vendored
Normal file
229
src/runtime/vendor/github.com/cilium/ebpf/link/link.go
generated
vendored
Normal file
@ -0,0 +1,229 @@
|
||||
package link
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"unsafe"
|
||||
|
||||
"github.com/cilium/ebpf"
|
||||
"github.com/cilium/ebpf/internal"
|
||||
)
|
||||
|
||||
var ErrNotSupported = internal.ErrNotSupported
|
||||
|
||||
// Link represents a Program attached to a BPF hook.
|
||||
type Link interface {
|
||||
// Replace the current program with a new program.
|
||||
//
|
||||
// Passing a nil program is an error. May return an error wrapping ErrNotSupported.
|
||||
Update(*ebpf.Program) error
|
||||
|
||||
// Persist a link by pinning it into a bpffs.
|
||||
//
|
||||
// May return an error wrapping ErrNotSupported.
|
||||
Pin(string) error
|
||||
|
||||
// Undo a previous call to Pin.
|
||||
//
|
||||
// May return an error wrapping ErrNotSupported.
|
||||
Unpin() error
|
||||
|
||||
// Close frees resources.
|
||||
//
|
||||
// The link will be broken unless it has been pinned. A link
|
||||
// may continue past the lifetime of the process if Close is
|
||||
// not called.
|
||||
Close() error
|
||||
|
||||
// Prevent external users from implementing this interface.
|
||||
isLink()
|
||||
}
|
||||
|
||||
// ID uniquely identifies a BPF link.
|
||||
type ID uint32
|
||||
|
||||
// RawLinkOptions control the creation of a raw link.
|
||||
type RawLinkOptions struct {
|
||||
// File descriptor to attach to. This differs for each attach type.
|
||||
Target int
|
||||
// Program to attach.
|
||||
Program *ebpf.Program
|
||||
// Attach must match the attach type of Program.
|
||||
Attach ebpf.AttachType
|
||||
}
|
||||
|
||||
// RawLinkInfo contains metadata on a link.
|
||||
type RawLinkInfo struct {
|
||||
Type Type
|
||||
ID ID
|
||||
Program ebpf.ProgramID
|
||||
}
|
||||
|
||||
// RawLink is the low-level API to bpf_link.
|
||||
//
|
||||
// You should consider using the higher level interfaces in this
|
||||
// package instead.
|
||||
type RawLink struct {
|
||||
fd *internal.FD
|
||||
pinnedPath string
|
||||
}
|
||||
|
||||
// AttachRawLink creates a raw link.
|
||||
func AttachRawLink(opts RawLinkOptions) (*RawLink, error) {
|
||||
if err := haveBPFLink(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if opts.Target < 0 {
|
||||
return nil, fmt.Errorf("invalid target: %s", internal.ErrClosedFd)
|
||||
}
|
||||
|
||||
progFd := opts.Program.FD()
|
||||
if progFd < 0 {
|
||||
return nil, fmt.Errorf("invalid program: %s", internal.ErrClosedFd)
|
||||
}
|
||||
|
||||
attr := bpfLinkCreateAttr{
|
||||
targetFd: uint32(opts.Target),
|
||||
progFd: uint32(progFd),
|
||||
attachType: opts.Attach,
|
||||
}
|
||||
fd, err := bpfLinkCreate(&attr)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("can't create link: %s", err)
|
||||
}
|
||||
|
||||
return &RawLink{fd, ""}, nil
|
||||
}
|
||||
|
||||
// LoadPinnedRawLink loads a persisted link from a bpffs.
|
||||
//
|
||||
// Returns an error if the pinned link type doesn't match linkType. Pass
|
||||
// UnspecifiedType to disable this behaviour.
|
||||
func LoadPinnedRawLink(fileName string, linkType Type, opts *ebpf.LoadPinOptions) (*RawLink, error) {
|
||||
fd, err := internal.BPFObjGet(fileName, opts.Marshal())
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("load pinned link: %w", err)
|
||||
}
|
||||
|
||||
link := &RawLink{fd, fileName}
|
||||
if linkType == UnspecifiedType {
|
||||
return link, nil
|
||||
}
|
||||
|
||||
info, err := link.Info()
|
||||
if err != nil {
|
||||
link.Close()
|
||||
return nil, fmt.Errorf("get pinned link info: %s", err)
|
||||
}
|
||||
|
||||
if info.Type != linkType {
|
||||
link.Close()
|
||||
return nil, fmt.Errorf("link type %v doesn't match %v", info.Type, linkType)
|
||||
}
|
||||
|
||||
return link, nil
|
||||
}
|
||||
|
||||
func (l *RawLink) isLink() {}
|
||||
|
||||
// FD returns the raw file descriptor.
|
||||
func (l *RawLink) FD() int {
|
||||
fd, err := l.fd.Value()
|
||||
if err != nil {
|
||||
return -1
|
||||
}
|
||||
return int(fd)
|
||||
}
|
||||
|
||||
// Close breaks the link.
|
||||
//
|
||||
// Use Pin if you want to make the link persistent.
|
||||
func (l *RawLink) Close() error {
|
||||
return l.fd.Close()
|
||||
}
|
||||
|
||||
// Pin persists a link past the lifetime of the process.
|
||||
//
|
||||
// Calling Close on a pinned Link will not break the link
|
||||
// until the pin is removed.
|
||||
func (l *RawLink) Pin(fileName string) error {
|
||||
if err := internal.Pin(l.pinnedPath, fileName, l.fd); err != nil {
|
||||
return err
|
||||
}
|
||||
l.pinnedPath = fileName
|
||||
return nil
|
||||
}
|
||||
|
||||
// Unpin implements the Link interface.
|
||||
func (l *RawLink) Unpin() error {
|
||||
if err := internal.Unpin(l.pinnedPath); err != nil {
|
||||
return err
|
||||
}
|
||||
l.pinnedPath = ""
|
||||
return nil
|
||||
}
|
||||
|
||||
// Update implements the Link interface.
|
||||
func (l *RawLink) Update(new *ebpf.Program) error {
|
||||
return l.UpdateArgs(RawLinkUpdateOptions{
|
||||
New: new,
|
||||
})
|
||||
}
|
||||
|
||||
// RawLinkUpdateOptions control the behaviour of RawLink.UpdateArgs.
|
||||
type RawLinkUpdateOptions struct {
|
||||
New *ebpf.Program
|
||||
Old *ebpf.Program
|
||||
Flags uint32
|
||||
}
|
||||
|
||||
// UpdateArgs updates a link based on args.
|
||||
func (l *RawLink) UpdateArgs(opts RawLinkUpdateOptions) error {
|
||||
newFd := opts.New.FD()
|
||||
if newFd < 0 {
|
||||
return fmt.Errorf("invalid program: %s", internal.ErrClosedFd)
|
||||
}
|
||||
|
||||
var oldFd int
|
||||
if opts.Old != nil {
|
||||
oldFd = opts.Old.FD()
|
||||
if oldFd < 0 {
|
||||
return fmt.Errorf("invalid replacement program: %s", internal.ErrClosedFd)
|
||||
}
|
||||
}
|
||||
|
||||
linkFd, err := l.fd.Value()
|
||||
if err != nil {
|
||||
return fmt.Errorf("can't update link: %s", err)
|
||||
}
|
||||
|
||||
attr := bpfLinkUpdateAttr{
|
||||
linkFd: linkFd,
|
||||
newProgFd: uint32(newFd),
|
||||
oldProgFd: uint32(oldFd),
|
||||
flags: opts.Flags,
|
||||
}
|
||||
return bpfLinkUpdate(&attr)
|
||||
}
|
||||
|
||||
// struct bpf_link_info
|
||||
type bpfLinkInfo struct {
|
||||
typ uint32
|
||||
id uint32
|
||||
prog_id uint32
|
||||
}
|
||||
|
||||
// Info returns metadata about the link.
|
||||
func (l *RawLink) Info() (*RawLinkInfo, error) {
|
||||
var info bpfLinkInfo
|
||||
err := internal.BPFObjGetInfoByFD(l.fd, unsafe.Pointer(&info), unsafe.Sizeof(info))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("link info: %s", err)
|
||||
}
|
||||
|
||||
return &RawLinkInfo{
|
||||
Type(info.typ),
|
||||
ID(info.id),
|
||||
ebpf.ProgramID(info.prog_id),
|
||||
}, nil
|
||||
}
|
60
src/runtime/vendor/github.com/cilium/ebpf/link/netns.go
generated
vendored
Normal file
60
src/runtime/vendor/github.com/cilium/ebpf/link/netns.go
generated
vendored
Normal file
@ -0,0 +1,60 @@
|
||||
package link
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/cilium/ebpf"
|
||||
)
|
||||
|
||||
// NetNsInfo contains metadata about a network namespace link.
|
||||
type NetNsInfo struct {
|
||||
RawLinkInfo
|
||||
}
|
||||
|
||||
// NetNsLink is a program attached to a network namespace.
|
||||
type NetNsLink struct {
|
||||
*RawLink
|
||||
}
|
||||
|
||||
// AttachNetNs attaches a program to a network namespace.
|
||||
func AttachNetNs(ns int, prog *ebpf.Program) (*NetNsLink, error) {
|
||||
var attach ebpf.AttachType
|
||||
switch t := prog.Type(); t {
|
||||
case ebpf.FlowDissector:
|
||||
attach = ebpf.AttachFlowDissector
|
||||
case ebpf.SkLookup:
|
||||
attach = ebpf.AttachSkLookup
|
||||
default:
|
||||
return nil, fmt.Errorf("can't attach %v to network namespace", t)
|
||||
}
|
||||
|
||||
link, err := AttachRawLink(RawLinkOptions{
|
||||
Target: ns,
|
||||
Program: prog,
|
||||
Attach: attach,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &NetNsLink{link}, nil
|
||||
}
|
||||
|
||||
// LoadPinnedNetNs loads a network namespace link from bpffs.
|
||||
func LoadPinnedNetNs(fileName string, opts *ebpf.LoadPinOptions) (*NetNsLink, error) {
|
||||
link, err := LoadPinnedRawLink(fileName, NetNsType, opts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &NetNsLink{link}, nil
|
||||
}
|
||||
|
||||
// Info returns information about the link.
|
||||
func (nns *NetNsLink) Info() (*NetNsInfo, error) {
|
||||
info, err := nns.RawLink.Info()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &NetNsInfo{*info}, nil
|
||||
}
|
273
src/runtime/vendor/github.com/cilium/ebpf/link/perf_event.go
generated
vendored
Normal file
273
src/runtime/vendor/github.com/cilium/ebpf/link/perf_event.go
generated
vendored
Normal file
@ -0,0 +1,273 @@
|
||||
package link
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
"unsafe"
|
||||
|
||||
"github.com/cilium/ebpf"
|
||||
"github.com/cilium/ebpf/internal"
|
||||
"github.com/cilium/ebpf/internal/unix"
|
||||
)
|
||||
|
||||
// Getting the terminology right is usually the hardest part. For posterity and
|
||||
// for staying sane during implementation:
|
||||
//
|
||||
// - trace event: Representation of a kernel runtime hook. Filesystem entries
|
||||
// under <tracefs>/events. Can be tracepoints (static), kprobes or uprobes.
|
||||
// Can be instantiated into perf events (see below).
|
||||
// - tracepoint: A predetermined hook point in the kernel. Exposed as trace
|
||||
// events in (sub)directories under <tracefs>/events. Cannot be closed or
|
||||
// removed, they are static.
|
||||
// - k(ret)probe: Ephemeral trace events based on entry or exit points of
|
||||
// exported kernel symbols. kprobe-based (tracefs) trace events can be
|
||||
// created system-wide by writing to the <tracefs>/kprobe_events file, or
|
||||
// they can be scoped to the current process by creating PMU perf events.
|
||||
// - u(ret)probe: Ephemeral trace events based on user provides ELF binaries
|
||||
// and offsets. uprobe-based (tracefs) trace events can be
|
||||
// created system-wide by writing to the <tracefs>/uprobe_events file, or
|
||||
// they can be scoped to the current process by creating PMU perf events.
|
||||
// - perf event: An object instantiated based on an existing trace event or
|
||||
// kernel symbol. Referred to by fd in userspace.
|
||||
// Exactly one eBPF program can be attached to a perf event. Multiple perf
|
||||
// events can be created from a single trace event. Closing a perf event
|
||||
// stops any further invocations of the attached eBPF program.
|
||||
|
||||
var (
|
||||
tracefsPath = "/sys/kernel/debug/tracing"
|
||||
|
||||
// Trace event groups, names and kernel symbols must adhere to this set
|
||||
// of characters. Non-empty, first character must not be a number, all
|
||||
// characters must be alphanumeric or underscore.
|
||||
rgxTraceEvent = regexp.MustCompile("^[a-zA-Z_][0-9a-zA-Z_]*$")
|
||||
|
||||
errInvalidInput = errors.New("invalid input")
|
||||
)
|
||||
|
||||
const (
|
||||
perfAllThreads = -1
|
||||
)
|
||||
|
||||
type perfEventType uint8
|
||||
|
||||
const (
|
||||
tracepointEvent perfEventType = iota
|
||||
kprobeEvent
|
||||
kretprobeEvent
|
||||
uprobeEvent
|
||||
uretprobeEvent
|
||||
)
|
||||
|
||||
// A perfEvent represents a perf event kernel object. Exactly one eBPF program
|
||||
// can be attached to it. It is created based on a tracefs trace event or a
|
||||
// Performance Monitoring Unit (PMU).
|
||||
type perfEvent struct {
|
||||
|
||||
// Group and name of the tracepoint/kprobe/uprobe.
|
||||
group string
|
||||
name string
|
||||
|
||||
// PMU event ID read from sysfs. Valid IDs are non-zero.
|
||||
pmuID uint64
|
||||
// ID of the trace event read from tracefs. Valid IDs are non-zero.
|
||||
tracefsID uint64
|
||||
|
||||
// The event type determines the types of programs that can be attached.
|
||||
typ perfEventType
|
||||
|
||||
fd *internal.FD
|
||||
}
|
||||
|
||||
func (pe *perfEvent) isLink() {}
|
||||
|
||||
func (pe *perfEvent) Pin(string) error {
|
||||
return fmt.Errorf("pin perf event: %w", ErrNotSupported)
|
||||
}
|
||||
|
||||
func (pe *perfEvent) Unpin() error {
|
||||
return fmt.Errorf("unpin perf event: %w", ErrNotSupported)
|
||||
}
|
||||
|
||||
// Since 4.15 (e87c6bc3852b "bpf: permit multiple bpf attachments for a single perf event"),
|
||||
// calling PERF_EVENT_IOC_SET_BPF appends the given program to a prog_array
|
||||
// owned by the perf event, which means multiple programs can be attached
|
||||
// simultaneously.
|
||||
//
|
||||
// Before 4.15, calling PERF_EVENT_IOC_SET_BPF more than once on a perf event
|
||||
// returns EEXIST.
|
||||
//
|
||||
// Detaching a program from a perf event is currently not possible, so a
|
||||
// program replacement mechanism cannot be implemented for perf events.
|
||||
func (pe *perfEvent) Update(prog *ebpf.Program) error {
|
||||
return fmt.Errorf("can't replace eBPF program in perf event: %w", ErrNotSupported)
|
||||
}
|
||||
|
||||
func (pe *perfEvent) Close() error {
|
||||
if pe.fd == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
pfd, err := pe.fd.Value()
|
||||
if err != nil {
|
||||
return fmt.Errorf("getting perf event fd: %w", err)
|
||||
}
|
||||
|
||||
err = unix.IoctlSetInt(int(pfd), unix.PERF_EVENT_IOC_DISABLE, 0)
|
||||
if err != nil {
|
||||
return fmt.Errorf("disabling perf event: %w", err)
|
||||
}
|
||||
|
||||
err = pe.fd.Close()
|
||||
if err != nil {
|
||||
return fmt.Errorf("closing perf event fd: %w", err)
|
||||
}
|
||||
|
||||
switch pe.typ {
|
||||
case kprobeEvent, kretprobeEvent:
|
||||
// Clean up kprobe tracefs entry.
|
||||
if pe.tracefsID != 0 {
|
||||
return closeTraceFSProbeEvent(kprobeType, pe.group, pe.name)
|
||||
}
|
||||
case uprobeEvent, uretprobeEvent:
|
||||
// Clean up uprobe tracefs entry.
|
||||
if pe.tracefsID != 0 {
|
||||
return closeTraceFSProbeEvent(uprobeType, pe.group, pe.name)
|
||||
}
|
||||
case tracepointEvent:
|
||||
// Tracepoint trace events don't hold any extra resources.
|
||||
return nil
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// attach the given eBPF prog to the perf event stored in pe.
|
||||
// pe must contain a valid perf event fd.
|
||||
// prog's type must match the program type stored in pe.
|
||||
func (pe *perfEvent) attach(prog *ebpf.Program) error {
|
||||
if prog == nil {
|
||||
return errors.New("cannot attach a nil program")
|
||||
}
|
||||
if pe.fd == nil {
|
||||
return errors.New("cannot attach to nil perf event")
|
||||
}
|
||||
if prog.FD() < 0 {
|
||||
return fmt.Errorf("invalid program: %w", internal.ErrClosedFd)
|
||||
}
|
||||
switch pe.typ {
|
||||
case kprobeEvent, kretprobeEvent, uprobeEvent, uretprobeEvent:
|
||||
if t := prog.Type(); t != ebpf.Kprobe {
|
||||
return fmt.Errorf("invalid program type (expected %s): %s", ebpf.Kprobe, t)
|
||||
}
|
||||
case tracepointEvent:
|
||||
if t := prog.Type(); t != ebpf.TracePoint {
|
||||
return fmt.Errorf("invalid program type (expected %s): %s", ebpf.TracePoint, t)
|
||||
}
|
||||
default:
|
||||
return fmt.Errorf("unknown perf event type: %d", pe.typ)
|
||||
}
|
||||
|
||||
// The ioctl below will fail when the fd is invalid.
|
||||
kfd, _ := pe.fd.Value()
|
||||
|
||||
// Assign the eBPF program to the perf event.
|
||||
err := unix.IoctlSetInt(int(kfd), unix.PERF_EVENT_IOC_SET_BPF, prog.FD())
|
||||
if err != nil {
|
||||
return fmt.Errorf("setting perf event bpf program: %w", err)
|
||||
}
|
||||
|
||||
// PERF_EVENT_IOC_ENABLE and _DISABLE ignore their given values.
|
||||
if err := unix.IoctlSetInt(int(kfd), unix.PERF_EVENT_IOC_ENABLE, 0); err != nil {
|
||||
return fmt.Errorf("enable perf event: %s", err)
|
||||
}
|
||||
|
||||
// Close the perf event when its reference is lost to avoid leaking system resources.
|
||||
runtime.SetFinalizer(pe, (*perfEvent).Close)
|
||||
return nil
|
||||
}
|
||||
|
||||
// unsafeStringPtr returns an unsafe.Pointer to a NUL-terminated copy of str.
|
||||
func unsafeStringPtr(str string) (unsafe.Pointer, error) {
|
||||
p, err := unix.BytePtrFromString(str)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return unsafe.Pointer(p), nil
|
||||
}
|
||||
|
||||
// getTraceEventID reads a trace event's ID from tracefs given its group and name.
|
||||
// group and name must be alphanumeric or underscore, as required by the kernel.
|
||||
func getTraceEventID(group, name string) (uint64, error) {
|
||||
tid, err := uint64FromFile(tracefsPath, "events", group, name, "id")
|
||||
if errors.Is(err, os.ErrNotExist) {
|
||||
return 0, fmt.Errorf("trace event %s/%s: %w", group, name, os.ErrNotExist)
|
||||
}
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("reading trace event ID of %s/%s: %w", group, name, err)
|
||||
}
|
||||
|
||||
return tid, nil
|
||||
}
|
||||
|
||||
// getPMUEventType reads a Performance Monitoring Unit's type (numeric identifier)
|
||||
// from /sys/bus/event_source/devices/<pmu>/type.
|
||||
//
|
||||
// Returns ErrNotSupported if the pmu type is not supported.
|
||||
func getPMUEventType(typ probeType) (uint64, error) {
|
||||
et, err := uint64FromFile("/sys/bus/event_source/devices", typ.String(), "type")
|
||||
if errors.Is(err, os.ErrNotExist) {
|
||||
return 0, fmt.Errorf("pmu type %s: %w", typ, ErrNotSupported)
|
||||
}
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("reading pmu type %s: %w", typ, err)
|
||||
}
|
||||
|
||||
return et, nil
|
||||
}
|
||||
|
||||
// openTracepointPerfEvent opens a tracepoint-type perf event. System-wide
|
||||
// [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.
|
||||
func openTracepointPerfEvent(tid uint64) (*internal.FD, error) {
|
||||
attr := unix.PerfEventAttr{
|
||||
Type: unix.PERF_TYPE_TRACEPOINT,
|
||||
Config: tid,
|
||||
Sample_type: unix.PERF_SAMPLE_RAW,
|
||||
Sample: 1,
|
||||
Wakeup: 1,
|
||||
}
|
||||
|
||||
fd, err := unix.PerfEventOpen(&attr, perfAllThreads, 0, -1, unix.PERF_FLAG_FD_CLOEXEC)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("opening tracepoint perf event: %w", err)
|
||||
}
|
||||
|
||||
return internal.NewFD(uint32(fd)), nil
|
||||
}
|
||||
|
||||
// uint64FromFile reads a uint64 from a file. All elements of path are sanitized
|
||||
// and joined onto base. Returns error if base no longer prefixes the path after
|
||||
// joining all components.
|
||||
func uint64FromFile(base string, path ...string) (uint64, error) {
|
||||
l := filepath.Join(path...)
|
||||
p := filepath.Join(base, l)
|
||||
if !strings.HasPrefix(p, base) {
|
||||
return 0, fmt.Errorf("path '%s' attempts to escape base path '%s': %w", l, base, errInvalidInput)
|
||||
}
|
||||
|
||||
data, err := ioutil.ReadFile(p)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("reading file %s: %w", p, err)
|
||||
}
|
||||
|
||||
et := bytes.TrimSpace(data)
|
||||
return strconv.ParseUint(string(et), 10, 64)
|
||||
}
|
25
src/runtime/vendor/github.com/cilium/ebpf/link/platform.go
generated
vendored
Normal file
25
src/runtime/vendor/github.com/cilium/ebpf/link/platform.go
generated
vendored
Normal file
@ -0,0 +1,25 @@
|
||||
package link
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"runtime"
|
||||
)
|
||||
|
||||
func platformPrefix(symbol string) string {
|
||||
|
||||
prefix := runtime.GOARCH
|
||||
|
||||
// per https://github.com/golang/go/blob/master/src/go/build/syslist.go
|
||||
switch prefix {
|
||||
case "386":
|
||||
prefix = "ia32"
|
||||
case "amd64", "amd64p32":
|
||||
prefix = "x64"
|
||||
case "arm64", "arm64be":
|
||||
prefix = "arm64"
|
||||
default:
|
||||
return symbol
|
||||
}
|
||||
|
||||
return fmt.Sprintf("__%s_%s", prefix, symbol)
|
||||
}
|
76
src/runtime/vendor/github.com/cilium/ebpf/link/program.go
generated
vendored
Normal file
76
src/runtime/vendor/github.com/cilium/ebpf/link/program.go
generated
vendored
Normal file
@ -0,0 +1,76 @@
|
||||
package link
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/cilium/ebpf"
|
||||
"github.com/cilium/ebpf/internal"
|
||||
)
|
||||
|
||||
type RawAttachProgramOptions struct {
|
||||
// File descriptor to attach to. This differs for each attach type.
|
||||
Target int
|
||||
// Program to attach.
|
||||
Program *ebpf.Program
|
||||
// Program to replace (cgroups).
|
||||
Replace *ebpf.Program
|
||||
// Attach must match the attach type of Program (and Replace).
|
||||
Attach ebpf.AttachType
|
||||
// Flags control the attach behaviour. This differs for each attach type.
|
||||
Flags uint32
|
||||
}
|
||||
|
||||
// RawAttachProgram is a low level wrapper around BPF_PROG_ATTACH.
|
||||
//
|
||||
// You should use one of the higher level abstractions available in this
|
||||
// package if possible.
|
||||
func RawAttachProgram(opts RawAttachProgramOptions) error {
|
||||
if err := haveProgAttach(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var replaceFd uint32
|
||||
if opts.Replace != nil {
|
||||
replaceFd = uint32(opts.Replace.FD())
|
||||
}
|
||||
|
||||
attr := internal.BPFProgAttachAttr{
|
||||
TargetFd: uint32(opts.Target),
|
||||
AttachBpfFd: uint32(opts.Program.FD()),
|
||||
ReplaceBpfFd: replaceFd,
|
||||
AttachType: uint32(opts.Attach),
|
||||
AttachFlags: uint32(opts.Flags),
|
||||
}
|
||||
|
||||
if err := internal.BPFProgAttach(&attr); err != nil {
|
||||
return fmt.Errorf("can't attach program: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type RawDetachProgramOptions struct {
|
||||
Target int
|
||||
Program *ebpf.Program
|
||||
Attach ebpf.AttachType
|
||||
}
|
||||
|
||||
// RawDetachProgram is a low level wrapper around BPF_PROG_DETACH.
|
||||
//
|
||||
// You should use one of the higher level abstractions available in this
|
||||
// package if possible.
|
||||
func RawDetachProgram(opts RawDetachProgramOptions) error {
|
||||
if err := haveProgAttach(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
attr := internal.BPFProgDetachAttr{
|
||||
TargetFd: uint32(opts.Target),
|
||||
AttachBpfFd: uint32(opts.Program.FD()),
|
||||
AttachType: uint32(opts.Attach),
|
||||
}
|
||||
if err := internal.BPFProgDetach(&attr); err != nil {
|
||||
return fmt.Errorf("can't detach program: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
61
src/runtime/vendor/github.com/cilium/ebpf/link/raw_tracepoint.go
generated
vendored
Normal file
61
src/runtime/vendor/github.com/cilium/ebpf/link/raw_tracepoint.go
generated
vendored
Normal file
@ -0,0 +1,61 @@
|
||||
package link
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/cilium/ebpf"
|
||||
"github.com/cilium/ebpf/internal"
|
||||
)
|
||||
|
||||
type RawTracepointOptions struct {
|
||||
// Tracepoint name.
|
||||
Name string
|
||||
// Program must be of type RawTracepoint*
|
||||
Program *ebpf.Program
|
||||
}
|
||||
|
||||
// AttachRawTracepoint links a BPF program to a raw_tracepoint.
|
||||
//
|
||||
// Requires at least Linux 4.17.
|
||||
func AttachRawTracepoint(opts RawTracepointOptions) (Link, error) {
|
||||
if t := opts.Program.Type(); t != ebpf.RawTracepoint && t != ebpf.RawTracepointWritable {
|
||||
return nil, fmt.Errorf("invalid program type %s, expected RawTracepoint(Writable)", t)
|
||||
}
|
||||
if opts.Program.FD() < 0 {
|
||||
return nil, fmt.Errorf("invalid program: %w", internal.ErrClosedFd)
|
||||
}
|
||||
|
||||
fd, err := bpfRawTracepointOpen(&bpfRawTracepointOpenAttr{
|
||||
name: internal.NewStringPointer(opts.Name),
|
||||
fd: uint32(opts.Program.FD()),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &progAttachRawTracepoint{fd: fd}, nil
|
||||
}
|
||||
|
||||
type progAttachRawTracepoint struct {
|
||||
fd *internal.FD
|
||||
}
|
||||
|
||||
var _ Link = (*progAttachRawTracepoint)(nil)
|
||||
|
||||
func (rt *progAttachRawTracepoint) isLink() {}
|
||||
|
||||
func (rt *progAttachRawTracepoint) Close() error {
|
||||
return rt.fd.Close()
|
||||
}
|
||||
|
||||
func (rt *progAttachRawTracepoint) Update(_ *ebpf.Program) error {
|
||||
return fmt.Errorf("can't update raw_tracepoint: %w", ErrNotSupported)
|
||||
}
|
||||
|
||||
func (rt *progAttachRawTracepoint) Pin(_ string) error {
|
||||
return fmt.Errorf("can't pin raw_tracepoint: %w", ErrNotSupported)
|
||||
}
|
||||
|
||||
func (rt *progAttachRawTracepoint) Unpin() error {
|
||||
return fmt.Errorf("unpin raw_tracepoint: %w", ErrNotSupported)
|
||||
}
|
190
src/runtime/vendor/github.com/cilium/ebpf/link/syscalls.go
generated
vendored
Normal file
190
src/runtime/vendor/github.com/cilium/ebpf/link/syscalls.go
generated
vendored
Normal file
@ -0,0 +1,190 @@
|
||||
package link
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"unsafe"
|
||||
|
||||
"github.com/cilium/ebpf"
|
||||
"github.com/cilium/ebpf/asm"
|
||||
"github.com/cilium/ebpf/internal"
|
||||
"github.com/cilium/ebpf/internal/unix"
|
||||
)
|
||||
|
||||
// Type is the kind of link.
|
||||
type Type uint32
|
||||
|
||||
// Valid link types.
|
||||
//
|
||||
// Equivalent to enum bpf_link_type.
|
||||
const (
|
||||
UnspecifiedType Type = iota
|
||||
RawTracepointType
|
||||
TracingType
|
||||
CgroupType
|
||||
IterType
|
||||
NetNsType
|
||||
XDPType
|
||||
)
|
||||
|
||||
var haveProgAttach = internal.FeatureTest("BPF_PROG_ATTACH", "4.10", func() error {
|
||||
prog, err := ebpf.NewProgram(&ebpf.ProgramSpec{
|
||||
Type: ebpf.CGroupSKB,
|
||||
AttachType: ebpf.AttachCGroupInetIngress,
|
||||
License: "MIT",
|
||||
Instructions: asm.Instructions{
|
||||
asm.Mov.Imm(asm.R0, 0),
|
||||
asm.Return(),
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
return internal.ErrNotSupported
|
||||
}
|
||||
|
||||
// BPF_PROG_ATTACH was introduced at the same time as CGgroupSKB,
|
||||
// so being able to load the program is enough to infer that we
|
||||
// have the syscall.
|
||||
prog.Close()
|
||||
return nil
|
||||
})
|
||||
|
||||
var haveProgAttachReplace = internal.FeatureTest("BPF_PROG_ATTACH atomic replacement", "5.5", func() error {
|
||||
if err := haveProgAttach(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
prog, err := ebpf.NewProgram(&ebpf.ProgramSpec{
|
||||
Type: ebpf.CGroupSKB,
|
||||
AttachType: ebpf.AttachCGroupInetIngress,
|
||||
License: "MIT",
|
||||
Instructions: asm.Instructions{
|
||||
asm.Mov.Imm(asm.R0, 0),
|
||||
asm.Return(),
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
return internal.ErrNotSupported
|
||||
}
|
||||
defer prog.Close()
|
||||
|
||||
// We know that we have BPF_PROG_ATTACH since we can load CGroupSKB programs.
|
||||
// If passing BPF_F_REPLACE gives us EINVAL we know that the feature isn't
|
||||
// present.
|
||||
attr := internal.BPFProgAttachAttr{
|
||||
// We rely on this being checked after attachFlags.
|
||||
TargetFd: ^uint32(0),
|
||||
AttachBpfFd: uint32(prog.FD()),
|
||||
AttachType: uint32(ebpf.AttachCGroupInetIngress),
|
||||
AttachFlags: uint32(flagReplace),
|
||||
}
|
||||
|
||||
err = internal.BPFProgAttach(&attr)
|
||||
if errors.Is(err, unix.EINVAL) {
|
||||
return internal.ErrNotSupported
|
||||
}
|
||||
if errors.Is(err, unix.EBADF) {
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
})
|
||||
|
||||
type bpfLinkCreateAttr struct {
|
||||
progFd uint32
|
||||
targetFd uint32
|
||||
attachType ebpf.AttachType
|
||||
flags uint32
|
||||
}
|
||||
|
||||
func bpfLinkCreate(attr *bpfLinkCreateAttr) (*internal.FD, error) {
|
||||
ptr, err := internal.BPF(internal.BPF_LINK_CREATE, unsafe.Pointer(attr), unsafe.Sizeof(*attr))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return internal.NewFD(uint32(ptr)), nil
|
||||
}
|
||||
|
||||
type bpfLinkCreateIterAttr struct {
|
||||
prog_fd uint32
|
||||
target_fd uint32
|
||||
attach_type ebpf.AttachType
|
||||
flags uint32
|
||||
iter_info internal.Pointer
|
||||
iter_info_len uint32
|
||||
}
|
||||
|
||||
func bpfLinkCreateIter(attr *bpfLinkCreateIterAttr) (*internal.FD, error) {
|
||||
ptr, err := internal.BPF(internal.BPF_LINK_CREATE, unsafe.Pointer(attr), unsafe.Sizeof(*attr))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return internal.NewFD(uint32(ptr)), nil
|
||||
}
|
||||
|
||||
type bpfLinkUpdateAttr struct {
|
||||
linkFd uint32
|
||||
newProgFd uint32
|
||||
flags uint32
|
||||
oldProgFd uint32
|
||||
}
|
||||
|
||||
func bpfLinkUpdate(attr *bpfLinkUpdateAttr) error {
|
||||
_, err := internal.BPF(internal.BPF_LINK_UPDATE, unsafe.Pointer(attr), unsafe.Sizeof(*attr))
|
||||
return err
|
||||
}
|
||||
|
||||
var haveBPFLink = internal.FeatureTest("bpf_link", "5.7", func() error {
|
||||
prog, err := ebpf.NewProgram(&ebpf.ProgramSpec{
|
||||
Type: ebpf.CGroupSKB,
|
||||
AttachType: ebpf.AttachCGroupInetIngress,
|
||||
License: "MIT",
|
||||
Instructions: asm.Instructions{
|
||||
asm.Mov.Imm(asm.R0, 0),
|
||||
asm.Return(),
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
return internal.ErrNotSupported
|
||||
}
|
||||
defer prog.Close()
|
||||
|
||||
attr := bpfLinkCreateAttr{
|
||||
// This is a hopefully invalid file descriptor, which triggers EBADF.
|
||||
targetFd: ^uint32(0),
|
||||
progFd: uint32(prog.FD()),
|
||||
attachType: ebpf.AttachCGroupInetIngress,
|
||||
}
|
||||
_, err = bpfLinkCreate(&attr)
|
||||
if errors.Is(err, unix.EINVAL) {
|
||||
return internal.ErrNotSupported
|
||||
}
|
||||
if errors.Is(err, unix.EBADF) {
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
})
|
||||
|
||||
type bpfIterCreateAttr struct {
|
||||
linkFd uint32
|
||||
flags uint32
|
||||
}
|
||||
|
||||
func bpfIterCreate(attr *bpfIterCreateAttr) (*internal.FD, error) {
|
||||
ptr, err := internal.BPF(internal.BPF_ITER_CREATE, unsafe.Pointer(attr), unsafe.Sizeof(*attr))
|
||||
if err == nil {
|
||||
return internal.NewFD(uint32(ptr)), nil
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
type bpfRawTracepointOpenAttr struct {
|
||||
name internal.Pointer
|
||||
fd uint32
|
||||
_ uint32
|
||||
}
|
||||
|
||||
func bpfRawTracepointOpen(attr *bpfRawTracepointOpenAttr) (*internal.FD, error) {
|
||||
ptr, err := internal.BPF(internal.BPF_RAW_TRACEPOINT_OPEN, unsafe.Pointer(attr), unsafe.Sizeof(*attr))
|
||||
if err == nil {
|
||||
return internal.NewFD(uint32(ptr)), nil
|
||||
}
|
||||
return nil, err
|
||||
}
|
56
src/runtime/vendor/github.com/cilium/ebpf/link/tracepoint.go
generated
vendored
Normal file
56
src/runtime/vendor/github.com/cilium/ebpf/link/tracepoint.go
generated
vendored
Normal file
@ -0,0 +1,56 @@
|
||||
package link
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/cilium/ebpf"
|
||||
)
|
||||
|
||||
// Tracepoint attaches the given eBPF program to the tracepoint with the given
|
||||
// group and name. See /sys/kernel/debug/tracing/events to find available
|
||||
// tracepoints. The top-level directory is the group, the event's subdirectory
|
||||
// is the name. Example:
|
||||
//
|
||||
// Tracepoint("syscalls", "sys_enter_fork", prog)
|
||||
//
|
||||
// Note that attaching eBPF programs to syscalls (sys_enter_*/sys_exit_*) is
|
||||
// only possible as of kernel 4.14 (commit cf5f5ce).
|
||||
func Tracepoint(group, name string, prog *ebpf.Program) (Link, error) {
|
||||
if group == "" || name == "" {
|
||||
return nil, fmt.Errorf("group and name cannot be empty: %w", errInvalidInput)
|
||||
}
|
||||
if prog == nil {
|
||||
return nil, fmt.Errorf("prog cannot be nil: %w", errInvalidInput)
|
||||
}
|
||||
if !rgxTraceEvent.MatchString(group) || !rgxTraceEvent.MatchString(name) {
|
||||
return nil, fmt.Errorf("group and name '%s/%s' must be alphanumeric or underscore: %w", group, name, errInvalidInput)
|
||||
}
|
||||
if prog.Type() != ebpf.TracePoint {
|
||||
return nil, fmt.Errorf("eBPF program type %s is not a Tracepoint: %w", prog.Type(), errInvalidInput)
|
||||
}
|
||||
|
||||
tid, err := getTraceEventID(group, name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
fd, err := openTracepointPerfEvent(tid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
pe := &perfEvent{
|
||||
fd: fd,
|
||||
tracefsID: tid,
|
||||
group: group,
|
||||
name: name,
|
||||
typ: tracepointEvent,
|
||||
}
|
||||
|
||||
if err := pe.attach(prog); err != nil {
|
||||
pe.Close()
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return pe, nil
|
||||
}
|
237
src/runtime/vendor/github.com/cilium/ebpf/link/uprobe.go
generated
vendored
Normal file
237
src/runtime/vendor/github.com/cilium/ebpf/link/uprobe.go
generated
vendored
Normal file
@ -0,0 +1,237 @@
|
||||
package link
|
||||
|
||||
import (
|
||||
"debug/elf"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"sync"
|
||||
|
||||
"github.com/cilium/ebpf"
|
||||
"github.com/cilium/ebpf/internal"
|
||||
)
|
||||
|
||||
var (
|
||||
uprobeEventsPath = filepath.Join(tracefsPath, "uprobe_events")
|
||||
|
||||
// rgxUprobeSymbol is used to strip invalid characters from the uprobe symbol
|
||||
// as they are not allowed to be used as the EVENT token in tracefs.
|
||||
rgxUprobeSymbol = regexp.MustCompile("[^a-zA-Z0-9]+")
|
||||
|
||||
uprobeRetprobeBit = struct {
|
||||
once sync.Once
|
||||
value uint64
|
||||
err error
|
||||
}{}
|
||||
)
|
||||
|
||||
// Executable defines an executable program on the filesystem.
|
||||
type Executable struct {
|
||||
// Path of the executable on the filesystem.
|
||||
path string
|
||||
// Parsed ELF symbols and dynamic symbols.
|
||||
symbols map[string]elf.Symbol
|
||||
}
|
||||
|
||||
// UprobeOptions defines additional parameters that will be used
|
||||
// when loading Uprobes.
|
||||
type UprobeOptions struct {
|
||||
// Symbol offset. Must be provided in case of external symbols (shared libs).
|
||||
// If set, overrides the offset eventually parsed from the executable.
|
||||
Offset uint64
|
||||
}
|
||||
|
||||
// To open a new Executable, use:
|
||||
//
|
||||
// OpenExecutable("/bin/bash")
|
||||
//
|
||||
// The returned value can then be used to open Uprobe(s).
|
||||
func OpenExecutable(path string) (*Executable, error) {
|
||||
if path == "" {
|
||||
return nil, fmt.Errorf("path cannot be empty")
|
||||
}
|
||||
|
||||
f, err := os.Open(path)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("open file '%s': %w", path, err)
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
se, err := internal.NewSafeELFFile(f)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("parse ELF file: %w", err)
|
||||
}
|
||||
|
||||
var ex = Executable{
|
||||
path: path,
|
||||
symbols: make(map[string]elf.Symbol),
|
||||
}
|
||||
if err := ex.addSymbols(se.Symbols); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := ex.addSymbols(se.DynamicSymbols); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &ex, nil
|
||||
}
|
||||
|
||||
func (ex *Executable) addSymbols(f func() ([]elf.Symbol, error)) error {
|
||||
// elf.Symbols and elf.DynamicSymbols return ErrNoSymbols if the section is not found.
|
||||
syms, err := f()
|
||||
if err != nil && !errors.Is(err, elf.ErrNoSymbols) {
|
||||
return err
|
||||
}
|
||||
for _, s := range syms {
|
||||
if elf.ST_TYPE(s.Info) != elf.STT_FUNC {
|
||||
// Symbol not associated with a function or other executable code.
|
||||
continue
|
||||
}
|
||||
ex.symbols[s.Name] = s
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ex *Executable) symbol(symbol string) (*elf.Symbol, error) {
|
||||
if s, ok := ex.symbols[symbol]; ok {
|
||||
return &s, nil
|
||||
}
|
||||
return nil, fmt.Errorf("symbol %s not found", symbol)
|
||||
}
|
||||
|
||||
// Uprobe attaches the given eBPF program to a perf event that fires when the
|
||||
// given symbol starts executing in the given Executable.
|
||||
// For example, /bin/bash::main():
|
||||
//
|
||||
// ex, _ = OpenExecutable("/bin/bash")
|
||||
// ex.Uprobe("main", prog, nil)
|
||||
//
|
||||
// When using symbols which belongs to shared libraries,
|
||||
// an offset must be provided via options:
|
||||
//
|
||||
// ex.Uprobe("main", prog, &UprobeOptions{Offset: 0x123})
|
||||
//
|
||||
// The resulting Link must be Closed during 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) {
|
||||
u, err := ex.uprobe(symbol, prog, opts, false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = u.attach(prog)
|
||||
if err != nil {
|
||||
u.Close()
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return u, nil
|
||||
}
|
||||
|
||||
// Uretprobe attaches the given eBPF program to a perf event that fires right
|
||||
// before the given symbol exits. For example, /bin/bash::main():
|
||||
//
|
||||
// ex, _ = OpenExecutable("/bin/bash")
|
||||
// ex.Uretprobe("main", prog, nil)
|
||||
//
|
||||
// When using symbols which belongs to shared libraries,
|
||||
// an offset must be provided via options:
|
||||
//
|
||||
// ex.Uretprobe("main", prog, &UprobeOptions{Offset: 0x123})
|
||||
//
|
||||
// The resulting Link must be Closed during 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) {
|
||||
u, err := ex.uprobe(symbol, prog, opts, true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = u.attach(prog)
|
||||
if err != nil {
|
||||
u.Close()
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return u, nil
|
||||
}
|
||||
|
||||
// uprobe opens a perf event for the given binary/symbol and attaches prog to it.
|
||||
// If ret is true, create a uretprobe.
|
||||
func (ex *Executable) uprobe(symbol string, prog *ebpf.Program, opts *UprobeOptions, ret bool) (*perfEvent, error) {
|
||||
if prog == nil {
|
||||
return nil, fmt.Errorf("prog cannot be nil: %w", errInvalidInput)
|
||||
}
|
||||
if prog.Type() != ebpf.Kprobe {
|
||||
return nil, fmt.Errorf("eBPF program type %s is not Kprobe: %w", prog.Type(), errInvalidInput)
|
||||
}
|
||||
|
||||
var offset uint64
|
||||
if opts != nil && opts.Offset != 0 {
|
||||
offset = opts.Offset
|
||||
} else {
|
||||
sym, err := ex.symbol(symbol)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("symbol '%s' not found: %w", symbol, err)
|
||||
}
|
||||
|
||||
// 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.
|
||||
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.
|
||||
tp, err := pmuUprobe(symbol, ex.path, offset, ret)
|
||||
if err == nil {
|
||||
return tp, nil
|
||||
}
|
||||
if err != nil && !errors.Is(err, ErrNotSupported) {
|
||||
return nil, fmt.Errorf("creating perf_uprobe PMU: %w", err)
|
||||
}
|
||||
|
||||
// Use tracefs if uprobe PMU is missing.
|
||||
tp, err = tracefsUprobe(uprobeSanitizedSymbol(symbol), ex.path, offset, ret)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("creating trace event '%s:%s' in tracefs: %w", ex.path, symbol, err)
|
||||
}
|
||||
|
||||
return tp, nil
|
||||
}
|
||||
|
||||
// pmuUprobe opens a perf event based on the uprobe PMU.
|
||||
func pmuUprobe(symbol, path string, offset uint64, ret bool) (*perfEvent, error) {
|
||||
return pmuProbe(uprobeType, symbol, path, offset, ret)
|
||||
}
|
||||
|
||||
// tracefsUprobe creates a Uprobe tracefs entry.
|
||||
func tracefsUprobe(symbol, path string, offset uint64, ret bool) (*perfEvent, error) {
|
||||
return tracefsProbe(uprobeType, symbol, path, offset, ret)
|
||||
}
|
||||
|
||||
// uprobeSanitizedSymbol replaces every invalid characted for the tracefs api with an underscore.
|
||||
func uprobeSanitizedSymbol(symbol string) string {
|
||||
return rgxUprobeSymbol.ReplaceAllString(symbol, "_")
|
||||
}
|
||||
|
||||
// uprobePathOffset creates the PATH:OFFSET token for the tracefs api.
|
||||
func uprobePathOffset(path string, offset uint64) string {
|
||||
return fmt.Sprintf("%s:%#x", path, offset)
|
||||
}
|
||||
|
||||
func uretprobeBit() (uint64, error) {
|
||||
uprobeRetprobeBit.once.Do(func() {
|
||||
uprobeRetprobeBit.value, uprobeRetprobeBit.err = determineRetprobeBit(uprobeType)
|
||||
})
|
||||
return uprobeRetprobeBit.value, uprobeRetprobeBit.err
|
||||
}
|
11
src/runtime/vendor/github.com/cilium/ebpf/linker.go
generated
vendored
11
src/runtime/vendor/github.com/cilium/ebpf/linker.go
generated
vendored
@ -108,12 +108,16 @@ func fixupJumpsAndCalls(insns asm.Instructions) error {
|
||||
offset := iter.Offset
|
||||
ins := iter.Ins
|
||||
|
||||
if ins.Reference == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
switch {
|
||||
case ins.IsFunctionCall() && ins.Constant == -1:
|
||||
// Rewrite bpf to bpf call
|
||||
callOffset, ok := symbolOffsets[ins.Reference]
|
||||
if !ok {
|
||||
return fmt.Errorf("instruction %d: reference to missing symbol %q", i, ins.Reference)
|
||||
return fmt.Errorf("call at %d: reference to missing symbol %q", i, ins.Reference)
|
||||
}
|
||||
|
||||
ins.Constant = int64(callOffset - offset - 1)
|
||||
@ -122,10 +126,13 @@ func fixupJumpsAndCalls(insns asm.Instructions) error {
|
||||
// Rewrite jump to label
|
||||
jumpOffset, ok := symbolOffsets[ins.Reference]
|
||||
if !ok {
|
||||
return fmt.Errorf("instruction %d: reference to missing symbol %q", i, ins.Reference)
|
||||
return fmt.Errorf("jump at %d: reference to missing symbol %q", i, ins.Reference)
|
||||
}
|
||||
|
||||
ins.Offset = int16(jumpOffset - offset - 1)
|
||||
|
||||
case ins.IsLoadFromMap() && ins.MapPtr() == -1:
|
||||
return fmt.Errorf("map %s: %w", ins.Reference, errUnsatisfiedReference)
|
||||
}
|
||||
}
|
||||
|
||||
|
138
src/runtime/vendor/github.com/cilium/ebpf/map.go
generated
vendored
138
src/runtime/vendor/github.com/cilium/ebpf/map.go
generated
vendored
@ -18,6 +18,7 @@ var (
|
||||
ErrKeyNotExist = errors.New("key does not exist")
|
||||
ErrKeyExist = errors.New("key already exists")
|
||||
ErrIterationAborted = errors.New("iteration aborted")
|
||||
ErrMapIncompatible = errors.New("map's spec is incompatible with pinned map")
|
||||
)
|
||||
|
||||
// MapOptions control loading a map into the kernel.
|
||||
@ -25,7 +26,8 @@ type MapOptions struct {
|
||||
// The base path to pin maps in if requested via PinByName.
|
||||
// Existing maps will be re-used if they are compatible, otherwise an
|
||||
// error is returned.
|
||||
PinPath string
|
||||
PinPath string
|
||||
LoadPinOptions LoadPinOptions
|
||||
}
|
||||
|
||||
// MapID represents the unique ID of an eBPF map
|
||||
@ -40,7 +42,10 @@ type MapSpec struct {
|
||||
KeySize uint32
|
||||
ValueSize uint32
|
||||
MaxEntries uint32
|
||||
Flags uint32
|
||||
|
||||
// Flags is passed to the kernel and specifies additional map
|
||||
// creation attributes.
|
||||
Flags uint32
|
||||
|
||||
// Automatically pin and load a map from MapOptions.PinPath.
|
||||
// Generates an error if an existing pinned map is incompatible with the MapSpec.
|
||||
@ -83,6 +88,23 @@ func (ms *MapSpec) Copy() *MapSpec {
|
||||
return &cpy
|
||||
}
|
||||
|
||||
func (ms *MapSpec) clampPerfEventArraySize() error {
|
||||
if ms.Type != PerfEventArray {
|
||||
return nil
|
||||
}
|
||||
|
||||
n, err := internal.PossibleCPUs()
|
||||
if err != nil {
|
||||
return fmt.Errorf("perf event array: %w", err)
|
||||
}
|
||||
|
||||
if n := uint32(n); ms.MaxEntries > n {
|
||||
ms.MaxEntries = n
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// MapKV is used to initialize the contents of a Map.
|
||||
type MapKV struct {
|
||||
Key interface{}
|
||||
@ -92,19 +114,19 @@ type MapKV struct {
|
||||
func (ms *MapSpec) checkCompatibility(m *Map) error {
|
||||
switch {
|
||||
case m.typ != ms.Type:
|
||||
return fmt.Errorf("expected type %v, got %v", ms.Type, m.typ)
|
||||
return fmt.Errorf("expected type %v, got %v: %w", ms.Type, m.typ, ErrMapIncompatible)
|
||||
|
||||
case m.keySize != ms.KeySize:
|
||||
return fmt.Errorf("expected key size %v, got %v", ms.KeySize, m.keySize)
|
||||
return fmt.Errorf("expected key size %v, got %v: %w", ms.KeySize, m.keySize, ErrMapIncompatible)
|
||||
|
||||
case m.valueSize != ms.ValueSize:
|
||||
return fmt.Errorf("expected value size %v, got %v", ms.ValueSize, m.valueSize)
|
||||
return fmt.Errorf("expected value size %v, got %v: %w", ms.ValueSize, m.valueSize, ErrMapIncompatible)
|
||||
|
||||
case m.maxEntries != ms.MaxEntries:
|
||||
return fmt.Errorf("expected max entries %v, got %v", ms.MaxEntries, m.maxEntries)
|
||||
return fmt.Errorf("expected max entries %v, got %v: %w", ms.MaxEntries, m.maxEntries, ErrMapIncompatible)
|
||||
|
||||
case m.flags != ms.Flags:
|
||||
return fmt.Errorf("expected flags %v, got %v", ms.Flags, m.flags)
|
||||
return fmt.Errorf("expected flags %v, got %v: %w", ms.Flags, m.flags, ErrMapIncompatible)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@ -167,31 +189,40 @@ func NewMap(spec *MapSpec) (*Map, error) {
|
||||
// The caller is responsible for ensuring the process' rlimit is set
|
||||
// sufficiently high for locking memory during map creation. This can be done
|
||||
// by calling unix.Setrlimit with unix.RLIMIT_MEMLOCK prior to calling NewMapWithOptions.
|
||||
//
|
||||
// May return an error wrapping ErrMapIncompatible.
|
||||
func NewMapWithOptions(spec *MapSpec, opts MapOptions) (*Map, error) {
|
||||
btfs := make(btfHandleCache)
|
||||
defer btfs.close()
|
||||
handles := newHandleCache()
|
||||
defer handles.close()
|
||||
|
||||
return newMapWithOptions(spec, opts, btfs)
|
||||
return newMapWithOptions(spec, opts, handles)
|
||||
}
|
||||
|
||||
func newMapWithOptions(spec *MapSpec, opts MapOptions, btfs btfHandleCache) (*Map, error) {
|
||||
func newMapWithOptions(spec *MapSpec, opts MapOptions, handles *handleCache) (_ *Map, err error) {
|
||||
closeOnError := func(c io.Closer) {
|
||||
if err != nil {
|
||||
c.Close()
|
||||
}
|
||||
}
|
||||
|
||||
switch spec.Pinning {
|
||||
case PinByName:
|
||||
if spec.Name == "" || opts.PinPath == "" {
|
||||
return nil, fmt.Errorf("pin by name: missing Name or PinPath")
|
||||
}
|
||||
|
||||
m, err := LoadPinnedMap(filepath.Join(opts.PinPath, spec.Name))
|
||||
path := filepath.Join(opts.PinPath, spec.Name)
|
||||
m, err := LoadPinnedMap(path, &opts.LoadPinOptions)
|
||||
if errors.Is(err, unix.ENOENT) {
|
||||
break
|
||||
}
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("load pinned map: %s", err)
|
||||
return nil, fmt.Errorf("load pinned map: %w", err)
|
||||
}
|
||||
defer closeOnError(m)
|
||||
|
||||
if err := spec.checkCompatibility(m); err != nil {
|
||||
m.Close()
|
||||
return nil, fmt.Errorf("use pinned map %s: %s", spec.Name, err)
|
||||
return nil, fmt.Errorf("use pinned map %s: %w", spec.Name, err)
|
||||
}
|
||||
|
||||
return m, nil
|
||||
@ -200,7 +231,7 @@ func newMapWithOptions(spec *MapSpec, opts MapOptions, btfs btfHandleCache) (*Ma
|
||||
// Nothing to do here
|
||||
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported pin type %d", int(spec.Pinning))
|
||||
return nil, fmt.Errorf("pin type %d: %w", int(spec.Pinning), ErrNotSupported)
|
||||
}
|
||||
|
||||
var innerFd *internal.FD
|
||||
@ -213,7 +244,7 @@ func newMapWithOptions(spec *MapSpec, opts MapOptions, btfs btfHandleCache) (*Ma
|
||||
return nil, errors.New("inner maps cannot be pinned")
|
||||
}
|
||||
|
||||
template, err := createMap(spec.InnerMap, nil, opts, btfs)
|
||||
template, err := createMap(spec.InnerMap, nil, opts, handles)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -222,14 +253,15 @@ func newMapWithOptions(spec *MapSpec, opts MapOptions, btfs btfHandleCache) (*Ma
|
||||
innerFd = template.fd
|
||||
}
|
||||
|
||||
m, err := createMap(spec, innerFd, opts, btfs)
|
||||
m, err := createMap(spec, innerFd, opts, handles)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer closeOnError(m)
|
||||
|
||||
if spec.Pinning == PinByName {
|
||||
if err := m.Pin(filepath.Join(opts.PinPath, spec.Name)); err != nil {
|
||||
m.Close()
|
||||
path := filepath.Join(opts.PinPath, spec.Name)
|
||||
if err := m.Pin(path); err != nil {
|
||||
return nil, fmt.Errorf("pin map: %s", err)
|
||||
}
|
||||
}
|
||||
@ -237,7 +269,7 @@ func newMapWithOptions(spec *MapSpec, opts MapOptions, btfs btfHandleCache) (*Ma
|
||||
return m, nil
|
||||
}
|
||||
|
||||
func createMap(spec *MapSpec, inner *internal.FD, opts MapOptions, btfs btfHandleCache) (_ *Map, err error) {
|
||||
func createMap(spec *MapSpec, inner *internal.FD, opts MapOptions, handles *handleCache) (_ *Map, err error) {
|
||||
closeOnError := func(closer io.Closer) {
|
||||
if err != nil {
|
||||
closer.Close()
|
||||
@ -284,44 +316,54 @@ func createMap(spec *MapSpec, inner *internal.FD, opts MapOptions, btfs btfHandl
|
||||
return nil, fmt.Errorf("map create: %w", err)
|
||||
}
|
||||
}
|
||||
if spec.Flags&unix.BPF_F_MMAPABLE > 0 {
|
||||
if err := haveMmapableMaps(); err != nil {
|
||||
return nil, fmt.Errorf("map create: %w", err)
|
||||
}
|
||||
}
|
||||
if spec.Flags&unix.BPF_F_INNER_MAP > 0 {
|
||||
if err := haveInnerMaps(); err != nil {
|
||||
return nil, fmt.Errorf("map create: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
attr := bpfMapCreateAttr{
|
||||
mapType: spec.Type,
|
||||
keySize: spec.KeySize,
|
||||
valueSize: spec.ValueSize,
|
||||
maxEntries: spec.MaxEntries,
|
||||
flags: spec.Flags,
|
||||
numaNode: spec.NumaNode,
|
||||
attr := internal.BPFMapCreateAttr{
|
||||
MapType: uint32(spec.Type),
|
||||
KeySize: spec.KeySize,
|
||||
ValueSize: spec.ValueSize,
|
||||
MaxEntries: spec.MaxEntries,
|
||||
Flags: spec.Flags,
|
||||
NumaNode: spec.NumaNode,
|
||||
}
|
||||
|
||||
if inner != nil {
|
||||
var err error
|
||||
attr.innerMapFd, err = inner.Value()
|
||||
attr.InnerMapFd, err = inner.Value()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("map create: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
if haveObjName() == nil {
|
||||
attr.mapName = newBPFObjName(spec.Name)
|
||||
attr.MapName = internal.NewBPFObjName(spec.Name)
|
||||
}
|
||||
|
||||
var btfDisabled bool
|
||||
if spec.BTF != nil {
|
||||
handle, err := btfs.load(btf.MapSpec(spec.BTF))
|
||||
handle, err := handles.btfHandle(btf.MapSpec(spec.BTF))
|
||||
btfDisabled = errors.Is(err, btf.ErrNotSupported)
|
||||
if err != nil && !btfDisabled {
|
||||
return nil, fmt.Errorf("load BTF: %w", err)
|
||||
}
|
||||
|
||||
if handle != nil {
|
||||
attr.btfFd = uint32(handle.FD())
|
||||
attr.btfKeyTypeID = btf.MapKey(spec.BTF).ID()
|
||||
attr.btfValueTypeID = btf.MapValue(spec.BTF).ID()
|
||||
attr.BTFFd = uint32(handle.FD())
|
||||
attr.BTFKeyTypeID = uint32(btf.MapKey(spec.BTF).ID())
|
||||
attr.BTFValueTypeID = uint32(btf.MapValue(spec.BTF).ID())
|
||||
}
|
||||
}
|
||||
|
||||
fd, err := bpfMapCreate(&attr)
|
||||
fd, err := internal.BPFMapCreate(&attr)
|
||||
if err != nil {
|
||||
if errors.Is(err, unix.EPERM) {
|
||||
return nil, fmt.Errorf("map create: RLIMIT_MEMLOCK may be too low: %w", err)
|
||||
@ -805,12 +847,13 @@ func (m *Map) Clone() (*Map, error) {
|
||||
// Pin persists the map on the BPF virtual file system past the lifetime of
|
||||
// the process that created it .
|
||||
//
|
||||
// Calling Pin on a previously pinned map will override the path.
|
||||
// Calling Pin on a previously pinned map will overwrite the path, except when
|
||||
// the new path already exists. Re-pinning across filesystems is not supported.
|
||||
// You can Clone a map to pin it to a different path.
|
||||
//
|
||||
// This requires bpffs to be mounted above fileName. See https://docs.cilium.io/en/k8s-doc/admin/#admin-mount-bpffs
|
||||
func (m *Map) Pin(fileName string) error {
|
||||
if err := pin(m.pinnedPath, fileName, m.fd); err != nil {
|
||||
if err := internal.Pin(m.pinnedPath, fileName, m.fd); err != nil {
|
||||
return err
|
||||
}
|
||||
m.pinnedPath = fileName
|
||||
@ -823,7 +866,7 @@ func (m *Map) Pin(fileName string) error {
|
||||
//
|
||||
// Unpinning an unpinned Map returns nil.
|
||||
func (m *Map) Unpin() error {
|
||||
if err := unpin(m.pinnedPath); err != nil {
|
||||
if err := internal.Unpin(m.pinnedPath); err != nil {
|
||||
return err
|
||||
}
|
||||
m.pinnedPath = ""
|
||||
@ -832,10 +875,7 @@ func (m *Map) Unpin() error {
|
||||
|
||||
// IsPinned returns true if the map has a non-empty pinned path.
|
||||
func (m *Map) IsPinned() bool {
|
||||
if m.pinnedPath == "" {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
return m.pinnedPath != ""
|
||||
}
|
||||
|
||||
// Freeze prevents a map to be modified from user space.
|
||||
@ -937,7 +977,9 @@ func (m *Map) unmarshalValue(value interface{}, buf []byte) error {
|
||||
return err
|
||||
}
|
||||
|
||||
(*value).Close()
|
||||
// The caller might close the map externally, so ignore errors.
|
||||
_ = (*value).Close()
|
||||
|
||||
*value = other
|
||||
return nil
|
||||
|
||||
@ -957,7 +999,9 @@ func (m *Map) unmarshalValue(value interface{}, buf []byte) error {
|
||||
return err
|
||||
}
|
||||
|
||||
(*value).Close()
|
||||
// The caller might close the program externally, so ignore errors.
|
||||
_ = (*value).Close()
|
||||
|
||||
*value = other
|
||||
return nil
|
||||
|
||||
@ -971,9 +1015,9 @@ func (m *Map) unmarshalValue(value interface{}, buf []byte) error {
|
||||
return unmarshalBytes(value, buf)
|
||||
}
|
||||
|
||||
// LoadPinnedMap load a Map from a BPF file.
|
||||
func LoadPinnedMap(fileName string) (*Map, error) {
|
||||
fd, err := internal.BPFObjGet(fileName)
|
||||
// LoadPinnedMap loads a Map from a BPF file.
|
||||
func LoadPinnedMap(fileName string, opts *LoadPinOptions) (*Map, error) {
|
||||
fd, err := internal.BPFObjGet(fileName, opts.Marshal())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
4
src/runtime/vendor/github.com/cilium/ebpf/marshalers.go
generated
vendored
4
src/runtime/vendor/github.com/cilium/ebpf/marshalers.go
generated
vendored
@ -84,7 +84,9 @@ func makeBuffer(dst interface{}, length int) (internal.Pointer, []byte) {
|
||||
func unmarshalBytes(data interface{}, buf []byte) error {
|
||||
switch value := data.(type) {
|
||||
case unsafe.Pointer:
|
||||
sh := &reflect.SliceHeader{
|
||||
// This could be solved in Go 1.17 by unsafe.Slice instead. (https://github.com/golang/go/issues/19367)
|
||||
// We could opt for removing unsafe.Pointer support in the lib as well.
|
||||
sh := &reflect.SliceHeader{ //nolint:govet
|
||||
Data: uintptr(value),
|
||||
Len: len(buf),
|
||||
Cap: len(buf),
|
||||
|
190
src/runtime/vendor/github.com/cilium/ebpf/prog.go
generated
vendored
190
src/runtime/vendor/github.com/cilium/ebpf/prog.go
generated
vendored
@ -5,6 +5,7 @@ import (
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"math"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
@ -19,6 +20,8 @@ import (
|
||||
// ErrNotSupported is returned whenever the kernel doesn't support a feature.
|
||||
var ErrNotSupported = internal.ErrNotSupported
|
||||
|
||||
var errUnsatisfiedReference = errors.New("unsatisfied reference")
|
||||
|
||||
// ProgramID represents the unique ID of an eBPF program.
|
||||
type ProgramID uint32
|
||||
|
||||
@ -41,6 +44,12 @@ type ProgramOptions struct {
|
||||
// Controls the output buffer size for the verifier. Defaults to
|
||||
// DefaultVerifierLogSize.
|
||||
LogSize int
|
||||
// An ELF containing the target BTF for this program. It is used both to
|
||||
// find the correct function to trace and to apply CO-RE relocations.
|
||||
// This is useful in environments where the kernel BTF is not available
|
||||
// (containers) or where it is in a non-standard location. Defaults to
|
||||
// use the kernel BTF from a well-known location.
|
||||
TargetBTF io.ReaderAt
|
||||
}
|
||||
|
||||
// ProgramSpec defines a Program.
|
||||
@ -55,16 +64,19 @@ type ProgramSpec struct {
|
||||
// depends on Type and AttachType.
|
||||
AttachTo string
|
||||
Instructions asm.Instructions
|
||||
|
||||
// Flags is passed to the kernel and specifies additional program
|
||||
// load attributes.
|
||||
Flags uint32
|
||||
// License of the program. Some helpers are only available if
|
||||
// the license is deemed compatible with the GPL.
|
||||
//
|
||||
// See https://www.kernel.org/doc/html/latest/process/license-rules.html#id1
|
||||
License string
|
||||
|
||||
// Version used by tracing programs.
|
||||
// Version used by Kprobe programs.
|
||||
//
|
||||
// Deprecated: superseded by BTF.
|
||||
// Deprecated on kernels 5.0 and later. Leave empty to let the library
|
||||
// detect this value automatically.
|
||||
KernelVersion uint32
|
||||
|
||||
// The BTF associated with this program. Changing Instructions
|
||||
@ -122,62 +134,68 @@ func NewProgram(spec *ProgramSpec) (*Program, error) {
|
||||
// Loading a program for the first time will perform
|
||||
// feature detection by loading small, temporary programs.
|
||||
func NewProgramWithOptions(spec *ProgramSpec, opts ProgramOptions) (*Program, error) {
|
||||
btfs := make(btfHandleCache)
|
||||
defer btfs.close()
|
||||
handles := newHandleCache()
|
||||
defer handles.close()
|
||||
|
||||
return newProgramWithOptions(spec, opts, btfs)
|
||||
prog, err := newProgramWithOptions(spec, opts, handles)
|
||||
if errors.Is(err, errUnsatisfiedReference) {
|
||||
return nil, fmt.Errorf("cannot load program without loading its whole collection: %w", err)
|
||||
}
|
||||
return prog, err
|
||||
}
|
||||
|
||||
func newProgramWithOptions(spec *ProgramSpec, opts ProgramOptions, btfs btfHandleCache) (*Program, error) {
|
||||
func newProgramWithOptions(spec *ProgramSpec, opts ProgramOptions, handles *handleCache) (*Program, error) {
|
||||
if len(spec.Instructions) == 0 {
|
||||
return nil, errors.New("Instructions cannot be empty")
|
||||
}
|
||||
|
||||
if len(spec.License) == 0 {
|
||||
return nil, errors.New("License cannot be empty")
|
||||
}
|
||||
|
||||
if spec.ByteOrder != nil && spec.ByteOrder != internal.NativeEndian {
|
||||
return nil, fmt.Errorf("can't load %s program on %s", spec.ByteOrder, internal.NativeEndian)
|
||||
}
|
||||
|
||||
insns := make(asm.Instructions, len(spec.Instructions))
|
||||
copy(insns, spec.Instructions)
|
||||
|
||||
if err := fixupJumpsAndCalls(insns); err != nil {
|
||||
return nil, err
|
||||
// Kernels before 5.0 (6c4fc209fcf9 "bpf: remove useless version check for prog load")
|
||||
// require the version field to be set to the value of the KERNEL_VERSION
|
||||
// macro for kprobe-type programs.
|
||||
// Overwrite Kprobe program version if set to zero or the magic version constant.
|
||||
kv := spec.KernelVersion
|
||||
if spec.Type == Kprobe && (kv == 0 || kv == internal.MagicKernelVersion) {
|
||||
v, err := internal.KernelVersion()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("detecting kernel version: %w", err)
|
||||
}
|
||||
kv = v.Kernel()
|
||||
}
|
||||
|
||||
buf := bytes.NewBuffer(make([]byte, 0, len(spec.Instructions)*asm.InstructionSize))
|
||||
err := insns.Marshal(buf, internal.NativeEndian)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
bytecode := buf.Bytes()
|
||||
insCount := uint32(len(bytecode) / asm.InstructionSize)
|
||||
attr := &bpfProgLoadAttr{
|
||||
progType: spec.Type,
|
||||
progFlags: spec.Flags,
|
||||
expectedAttachType: spec.AttachType,
|
||||
insCount: insCount,
|
||||
instructions: internal.NewSlicePointer(bytecode),
|
||||
license: internal.NewStringPointer(spec.License),
|
||||
kernelVersion: spec.KernelVersion,
|
||||
kernelVersion: kv,
|
||||
}
|
||||
|
||||
if haveObjName() == nil {
|
||||
attr.progName = newBPFObjName(spec.Name)
|
||||
attr.progName = internal.NewBPFObjName(spec.Name)
|
||||
}
|
||||
|
||||
var err error
|
||||
var targetBTF *btf.Spec
|
||||
if opts.TargetBTF != nil {
|
||||
targetBTF, err = handles.btfSpec(opts.TargetBTF)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("load target BTF: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
var btfDisabled bool
|
||||
var core btf.COREFixups
|
||||
if spec.BTF != nil {
|
||||
if relos, err := btf.ProgramRelocations(spec.BTF, nil); err != nil {
|
||||
return nil, fmt.Errorf("CO-RE relocations: %s", err)
|
||||
} else if len(relos) > 0 {
|
||||
return nil, fmt.Errorf("applying CO-RE relocations: %w", ErrNotSupported)
|
||||
core, err = btf.ProgramFixups(spec.BTF, targetBTF)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("CO-RE relocations: %w", err)
|
||||
}
|
||||
|
||||
handle, err := btfs.load(btf.ProgramSpec(spec.BTF))
|
||||
handle, err := handles.btfHandle(btf.ProgramSpec(spec.BTF))
|
||||
btfDisabled = errors.Is(err, btf.ErrNotSupported)
|
||||
if err != nil && !btfDisabled {
|
||||
return nil, fmt.Errorf("load BTF: %w", err)
|
||||
@ -204,8 +222,27 @@ func newProgramWithOptions(spec *ProgramSpec, opts ProgramOptions, btfs btfHandl
|
||||
}
|
||||
}
|
||||
|
||||
insns, err := core.Apply(spec.Instructions)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("CO-RE fixup: %w", err)
|
||||
}
|
||||
|
||||
if err := fixupJumpsAndCalls(insns); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
buf := bytes.NewBuffer(make([]byte, 0, len(spec.Instructions)*asm.InstructionSize))
|
||||
err = insns.Marshal(buf, internal.NativeEndian)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
bytecode := buf.Bytes()
|
||||
attr.instructions = internal.NewSlicePointer(bytecode)
|
||||
attr.insCount = uint32(len(bytecode) / asm.InstructionSize)
|
||||
|
||||
if spec.AttachTo != "" {
|
||||
target, err := resolveBTFType(spec.AttachTo, spec.Type, spec.AttachType)
|
||||
target, err := resolveBTFType(targetBTF, spec.AttachTo, spec.Type, spec.AttachType)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -233,7 +270,7 @@ func newProgramWithOptions(spec *ProgramSpec, opts ProgramOptions, btfs btfHandl
|
||||
}
|
||||
|
||||
logErr := err
|
||||
if opts.LogLevel == 0 {
|
||||
if opts.LogLevel == 0 && opts.LogSize >= 0 {
|
||||
// Re-run with the verifier enabled to get better error messages.
|
||||
logBuf = make([]byte, logSize)
|
||||
attr.logLevel = 1
|
||||
@ -345,9 +382,12 @@ func (p *Program) Clone() (*Program, error) {
|
||||
// Pin persists the Program on the BPF virtual file system past the lifetime of
|
||||
// the process that created it
|
||||
//
|
||||
// Calling Pin on a previously pinned program will overwrite the path, except when
|
||||
// the new path already exists. Re-pinning across filesystems is not supported.
|
||||
//
|
||||
// This requires bpffs to be mounted above fileName. See https://docs.cilium.io/en/k8s-doc/admin/#admin-mount-bpffs
|
||||
func (p *Program) Pin(fileName string) error {
|
||||
if err := pin(p.pinnedPath, fileName, p.fd); err != nil {
|
||||
if err := internal.Pin(p.pinnedPath, fileName, p.fd); err != nil {
|
||||
return err
|
||||
}
|
||||
p.pinnedPath = fileName
|
||||
@ -360,7 +400,7 @@ func (p *Program) Pin(fileName string) error {
|
||||
//
|
||||
// Unpinning an unpinned Program returns nil.
|
||||
func (p *Program) Unpin() error {
|
||||
if err := unpin(p.pinnedPath); err != nil {
|
||||
if err := internal.Unpin(p.pinnedPath); err != nil {
|
||||
return err
|
||||
}
|
||||
p.pinnedPath = ""
|
||||
@ -369,10 +409,7 @@ func (p *Program) Unpin() error {
|
||||
|
||||
// IsPinned returns true if the Program has a non-empty pinned path.
|
||||
func (p *Program) IsPinned() bool {
|
||||
if p.pinnedPath == "" {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
return p.pinnedPath != ""
|
||||
}
|
||||
|
||||
// Close unloads the program from the kernel.
|
||||
@ -597,8 +634,8 @@ func (p *Program) Detach(fd int, typ AttachType, flags AttachFlags) error {
|
||||
// LoadPinnedProgram loads a Program from a BPF file.
|
||||
//
|
||||
// Requires at least Linux 4.11.
|
||||
func LoadPinnedProgram(fileName string) (*Program, error) {
|
||||
fd, err := internal.BPFObjGet(fileName)
|
||||
func LoadPinnedProgram(fileName string, opts *LoadPinOptions) (*Program, error) {
|
||||
fd, err := internal.BPFObjGet(fileName, opts.Marshal())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -609,7 +646,7 @@ func LoadPinnedProgram(fileName string) (*Program, error) {
|
||||
return nil, fmt.Errorf("info for %s: %w", fileName, err)
|
||||
}
|
||||
|
||||
return &Program{"", fd, filepath.Base(fileName), "", info.Type}, nil
|
||||
return &Program{"", fd, filepath.Base(fileName), fileName, info.Type}, nil
|
||||
}
|
||||
|
||||
// SanitizeName replaces all invalid characters in name with replacement.
|
||||
@ -647,52 +684,45 @@ func (p *Program) ID() (ProgramID, error) {
|
||||
return ProgramID(info.id), nil
|
||||
}
|
||||
|
||||
func findKernelType(name string, typ btf.Type) error {
|
||||
kernel, err := btf.LoadKernelSpec()
|
||||
if err != nil {
|
||||
return fmt.Errorf("can't load kernel spec: %w", err)
|
||||
}
|
||||
|
||||
return kernel.FindType(name, typ)
|
||||
}
|
||||
|
||||
func resolveBTFType(name string, progType ProgramType, attachType AttachType) (btf.Type, error) {
|
||||
func resolveBTFType(kernel *btf.Spec, name string, progType ProgramType, attachType AttachType) (btf.Type, error) {
|
||||
type match struct {
|
||||
p ProgramType
|
||||
a AttachType
|
||||
}
|
||||
|
||||
target := match{progType, attachType}
|
||||
switch target {
|
||||
var target btf.Type
|
||||
var typeName, featureName string
|
||||
switch (match{progType, attachType}) {
|
||||
case match{LSM, AttachLSMMac}:
|
||||
var target btf.Func
|
||||
err := findKernelType("bpf_lsm_"+name, &target)
|
||||
if errors.Is(err, btf.ErrNotFound) {
|
||||
return nil, &internal.UnsupportedFeatureError{
|
||||
Name: name + " LSM hook",
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("resolve BTF for LSM hook %s: %w", name, err)
|
||||
}
|
||||
|
||||
return &target, nil
|
||||
target = new(btf.Func)
|
||||
typeName = "bpf_lsm_" + name
|
||||
featureName = name + " LSM hook"
|
||||
|
||||
case match{Tracing, AttachTraceIter}:
|
||||
var target btf.Func
|
||||
err := findKernelType("bpf_iter_"+name, &target)
|
||||
if errors.Is(err, btf.ErrNotFound) {
|
||||
return nil, &internal.UnsupportedFeatureError{
|
||||
Name: name + " iterator",
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("resolve BTF for iterator %s: %w", name, err)
|
||||
}
|
||||
|
||||
return &target, nil
|
||||
target = new(btf.Func)
|
||||
typeName = "bpf_iter_" + name
|
||||
featureName = name + " iterator"
|
||||
|
||||
default:
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
if kernel == nil {
|
||||
var err error
|
||||
kernel, err = btf.LoadKernelSpec()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("load kernel spec: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
err := kernel.FindType(typeName, target)
|
||||
if errors.Is(err, btf.ErrNotFound) {
|
||||
return nil, &internal.UnsupportedFeatureError{
|
||||
Name: featureName,
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("resolve BTF for %s: %w", featureName, err)
|
||||
}
|
||||
return target, nil
|
||||
}
|
||||
|
126
src/runtime/vendor/github.com/cilium/ebpf/run-tests.sh
generated
vendored
126
src/runtime/vendor/github.com/cilium/ebpf/run-tests.sh
generated
vendored
@ -1,55 +1,95 @@
|
||||
#!/bin/bash
|
||||
# Test the current package under a different kernel.
|
||||
# Requires virtme and qemu to be installed.
|
||||
# Examples:
|
||||
# Run all tests on a 5.4 kernel
|
||||
# $ ./run-tests.sh 5.4
|
||||
# Run a subset of tests:
|
||||
# $ ./run-tests.sh 5.4 go test ./link
|
||||
|
||||
set -eu
|
||||
set -o pipefail
|
||||
set -euo pipefail
|
||||
|
||||
if [[ "${1:-}" = "--in-vm" ]]; then
|
||||
script="$(realpath "$0")"
|
||||
readonly script
|
||||
|
||||
# This script is a bit like a Matryoshka doll since it keeps re-executing itself
|
||||
# in various different contexts:
|
||||
#
|
||||
# 1. invoked by the user like run-tests.sh 5.4
|
||||
# 2. invoked by go test like run-tests.sh --exec-vm
|
||||
# 3. invoked by init in the vm like run-tests.sh --exec-test
|
||||
#
|
||||
# This allows us to use all available CPU on the host machine to compile our
|
||||
# code, and then only use the VM to execute the test. This is because the VM
|
||||
# is usually slower at compiling than the host.
|
||||
if [[ "${1:-}" = "--exec-vm" ]]; then
|
||||
shift
|
||||
|
||||
input="$1"
|
||||
shift
|
||||
|
||||
# Use sudo if /dev/kvm isn't accessible by the current user.
|
||||
sudo=""
|
||||
if [[ ! -r /dev/kvm || ! -w /dev/kvm ]]; then
|
||||
sudo="sudo"
|
||||
fi
|
||||
readonly sudo
|
||||
|
||||
testdir="$(dirname "$1")"
|
||||
output="$(mktemp -d)"
|
||||
printf -v cmd "%q " "$@"
|
||||
|
||||
if [[ "$(stat -c '%t:%T' -L /proc/$$/fd/0)" == "1:3" ]]; then
|
||||
# stdin is /dev/null, which doesn't play well with qemu. Use a fifo as a
|
||||
# blocking substitute.
|
||||
mkfifo "${output}/fake-stdin"
|
||||
# Open for reading and writing to avoid blocking.
|
||||
exec 0<> "${output}/fake-stdin"
|
||||
rm "${output}/fake-stdin"
|
||||
fi
|
||||
|
||||
$sudo virtme-run --kimg "${input}/bzImage" --memory 768M --pwd \
|
||||
--rwdir="${testdir}=${testdir}" \
|
||||
--rodir=/run/input="${input}" \
|
||||
--rwdir=/run/output="${output}" \
|
||||
--script-sh "PATH=\"$PATH\" \"$script\" --exec-test $cmd" \
|
||||
--qemu-opts -smp 2 # need at least two CPUs for some tests
|
||||
|
||||
if [[ ! -e "${output}/success" ]]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
$sudo rm -r "$output"
|
||||
exit 0
|
||||
elif [[ "${1:-}" = "--exec-test" ]]; then
|
||||
shift
|
||||
|
||||
mount -t bpf bpf /sys/fs/bpf
|
||||
export CGO_ENABLED=0
|
||||
export GOFLAGS=-mod=readonly
|
||||
export GOPATH=/run/go-path
|
||||
export GOPROXY=file:///run/go-path/pkg/mod/cache/download
|
||||
export GOSUMDB=off
|
||||
export GOCACHE=/run/go-cache
|
||||
mount -t tracefs tracefs /sys/kernel/debug/tracing
|
||||
|
||||
if [[ -d "/run/input/bpf" ]]; then
|
||||
export KERNEL_SELFTESTS="/run/input/bpf"
|
||||
fi
|
||||
|
||||
readonly output="${1}"
|
||||
shift
|
||||
|
||||
echo Running tests...
|
||||
go test -v -coverpkg=./... -coverprofile="$output/coverage.txt" -count 1 ./...
|
||||
touch "$output/success"
|
||||
dmesg -C
|
||||
if ! "$@"; then
|
||||
dmesg
|
||||
exit 1
|
||||
fi
|
||||
touch "/run/output/success"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Pull all dependencies, so that we can run tests without the
|
||||
# vm having network access.
|
||||
go mod download
|
||||
|
||||
# Use sudo if /dev/kvm isn't accessible by the current user.
|
||||
sudo=""
|
||||
if [[ ! -r /dev/kvm || ! -w /dev/kvm ]]; then
|
||||
sudo="sudo"
|
||||
fi
|
||||
readonly sudo
|
||||
|
||||
readonly kernel_version="${1:-}"
|
||||
if [[ -z "${kernel_version}" ]]; then
|
||||
echo "Expecting kernel version as first argument"
|
||||
exit 1
|
||||
fi
|
||||
shift
|
||||
|
||||
readonly kernel="linux-${kernel_version}.bz"
|
||||
readonly selftests="linux-${kernel_version}-selftests-bpf.bz"
|
||||
readonly input="$(mktemp -d)"
|
||||
readonly output="$(mktemp -d)"
|
||||
readonly tmp_dir="${TMPDIR:-/tmp}"
|
||||
readonly branch="${BRANCH:-master}"
|
||||
|
||||
@ -59,6 +99,7 @@ fetch() {
|
||||
}
|
||||
|
||||
fetch "${kernel}"
|
||||
cp "${tmp_dir}/${kernel}" "${input}/bzImage"
|
||||
|
||||
if fetch "${selftests}"; then
|
||||
mkdir "${input}/bpf"
|
||||
@ -67,25 +108,16 @@ else
|
||||
echo "No selftests found, disabling"
|
||||
fi
|
||||
|
||||
echo Testing on "${kernel_version}"
|
||||
$sudo virtme-run --kimg "${tmp_dir}/${kernel}" --memory 512M --pwd \
|
||||
--rw \
|
||||
--rwdir=/run/input="${input}" \
|
||||
--rwdir=/run/output="${output}" \
|
||||
--rodir=/run/go-path="$(go env GOPATH)" \
|
||||
--rwdir=/run/go-cache="$(go env GOCACHE)" \
|
||||
--script-sh "PATH=\"$PATH\" $(realpath "$0") --in-vm /run/output" \
|
||||
--qemu-opts -smp 2 # need at least two CPUs for some tests
|
||||
|
||||
if [[ ! -e "${output}/success" ]]; then
|
||||
echo "Test failed on ${kernel_version}"
|
||||
exit 1
|
||||
else
|
||||
echo "Test successful on ${kernel_version}"
|
||||
if [[ -v COVERALLS_TOKEN ]]; then
|
||||
goveralls -coverprofile="${output}/coverage.txt" -service=semaphore -repotoken "$COVERALLS_TOKEN"
|
||||
fi
|
||||
args=(-v -short -coverpkg=./... -coverprofile=coverage.out -count 1 ./...)
|
||||
if (( $# > 0 )); then
|
||||
args=("$@")
|
||||
fi
|
||||
|
||||
$sudo rm -r "${input}"
|
||||
$sudo rm -r "${output}"
|
||||
export GOFLAGS=-mod=readonly
|
||||
export CGO_ENABLED=0
|
||||
|
||||
echo Testing on "${kernel_version}"
|
||||
go test -exec "$script --exec-vm $input" "${args[@]}"
|
||||
echo "Test successful on ${kernel_version}"
|
||||
|
||||
rm -r "${input}"
|
||||
|
183
src/runtime/vendor/github.com/cilium/ebpf/syscalls.go
generated
vendored
183
src/runtime/vendor/github.com/cilium/ebpf/syscalls.go
generated
vendored
@ -3,6 +3,7 @@ package ebpf
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"unsafe"
|
||||
|
||||
"github.com/cilium/ebpf/internal"
|
||||
@ -10,19 +11,10 @@ import (
|
||||
"github.com/cilium/ebpf/internal/unix"
|
||||
)
|
||||
|
||||
// Generic errors returned by BPF syscalls.
|
||||
var ErrNotExist = errors.New("requested object does not exist")
|
||||
|
||||
// bpfObjName is a null-terminated string made up of
|
||||
// 'A-Za-z0-9_' characters.
|
||||
type bpfObjName [unix.BPF_OBJ_NAME_LEN]byte
|
||||
|
||||
// newBPFObjName truncates the result if it is too long.
|
||||
func newBPFObjName(name string) bpfObjName {
|
||||
var result bpfObjName
|
||||
copy(result[:unix.BPF_OBJ_NAME_LEN-1], name)
|
||||
return result
|
||||
}
|
||||
// ErrNotExist is returned when loading a non-existing map or program.
|
||||
//
|
||||
// Deprecated: use os.ErrNotExist instead.
|
||||
var ErrNotExist = os.ErrNotExist
|
||||
|
||||
// invalidBPFObjNameChar returns true if char may not appear in
|
||||
// a BPF object name.
|
||||
@ -45,21 +37,6 @@ func invalidBPFObjNameChar(char rune) bool {
|
||||
}
|
||||
}
|
||||
|
||||
type bpfMapCreateAttr struct {
|
||||
mapType MapType
|
||||
keySize uint32
|
||||
valueSize uint32
|
||||
maxEntries uint32
|
||||
flags uint32
|
||||
innerMapFd uint32 // since 4.12 56f668dfe00d
|
||||
numaNode uint32 // since 4.14 96eabe7a40aa
|
||||
mapName bpfObjName // since 4.15 ad5b177bd73f
|
||||
mapIfIndex uint32
|
||||
btfFd uint32
|
||||
btfKeyTypeID btf.TypeID
|
||||
btfValueTypeID btf.TypeID
|
||||
}
|
||||
|
||||
type bpfMapOpAttr struct {
|
||||
mapFd uint32
|
||||
padding uint32
|
||||
@ -86,10 +63,10 @@ type bpfMapInfo struct {
|
||||
value_size uint32
|
||||
max_entries uint32
|
||||
map_flags uint32
|
||||
name bpfObjName // since 4.15 ad5b177bd73f
|
||||
ifindex uint32 // since 4.16 52775b33bb50
|
||||
btf_vmlinux_value_type_id uint32 // since 5.6 85d33df357b6
|
||||
netns_dev uint64 // since 4.16 52775b33bb50
|
||||
name internal.BPFObjName // since 4.15 ad5b177bd73f
|
||||
ifindex uint32 // since 4.16 52775b33bb50
|
||||
btf_vmlinux_value_type_id uint32 // since 5.6 85d33df357b6
|
||||
netns_dev uint64 // since 4.16 52775b33bb50
|
||||
netns_ino uint64
|
||||
btf_id uint32 // since 4.18 78958fca7ead
|
||||
btf_key_type_id uint32 // since 4.18 9b2cf328b2ec
|
||||
@ -104,11 +81,11 @@ type bpfProgLoadAttr struct {
|
||||
logLevel uint32
|
||||
logSize uint32
|
||||
logBuf internal.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 AttachType // since 4.17 5e43f899b03a
|
||||
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
|
||||
@ -132,7 +109,7 @@ type bpfProgInfo struct {
|
||||
created_by_uid uint32
|
||||
nr_map_ids uint32
|
||||
map_ids internal.Pointer
|
||||
name bpfObjName // since 4.15 067cae47771c
|
||||
name internal.BPFObjName // since 4.15 067cae47771c
|
||||
ifindex uint32
|
||||
gpl_compatible uint32
|
||||
netns_dev uint64
|
||||
@ -188,7 +165,7 @@ func bpfProgLoad(attr *bpfProgLoadAttr) (*internal.FD, error) {
|
||||
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 err == unix.EAGAIN {
|
||||
if errors.Is(err, unix.EAGAIN) {
|
||||
continue
|
||||
}
|
||||
|
||||
@ -205,23 +182,14 @@ func bpfProgTestRun(attr *bpfProgTestRunAttr) error {
|
||||
return err
|
||||
}
|
||||
|
||||
func bpfMapCreate(attr *bpfMapCreateAttr) (*internal.FD, error) {
|
||||
fd, err := internal.BPF(internal.BPF_MAP_CREATE, unsafe.Pointer(attr), unsafe.Sizeof(*attr))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return internal.NewFD(uint32(fd)), nil
|
||||
}
|
||||
|
||||
var haveNestedMaps = internal.FeatureTest("nested maps", "4.12", func() error {
|
||||
_, err := bpfMapCreate(&bpfMapCreateAttr{
|
||||
mapType: ArrayOfMaps,
|
||||
keySize: 4,
|
||||
valueSize: 4,
|
||||
maxEntries: 1,
|
||||
_, err := internal.BPFMapCreate(&internal.BPFMapCreateAttr{
|
||||
MapType: uint32(ArrayOfMaps),
|
||||
KeySize: 4,
|
||||
ValueSize: 4,
|
||||
MaxEntries: 1,
|
||||
// Invalid file descriptor.
|
||||
innerMapFd: ^uint32(0),
|
||||
InnerMapFd: ^uint32(0),
|
||||
})
|
||||
if errors.Is(err, unix.EINVAL) {
|
||||
return internal.ErrNotSupported
|
||||
@ -235,12 +203,44 @@ var haveNestedMaps = internal.FeatureTest("nested maps", "4.12", func() error {
|
||||
var haveMapMutabilityModifiers = internal.FeatureTest("read- and write-only maps", "5.2", func() error {
|
||||
// This checks BPF_F_RDONLY_PROG and BPF_F_WRONLY_PROG. Since
|
||||
// BPF_MAP_FREEZE appeared in 5.2 as well we don't do a separate check.
|
||||
m, err := bpfMapCreate(&bpfMapCreateAttr{
|
||||
mapType: Array,
|
||||
keySize: 4,
|
||||
valueSize: 4,
|
||||
maxEntries: 1,
|
||||
flags: unix.BPF_F_RDONLY_PROG,
|
||||
m, err := internal.BPFMapCreate(&internal.BPFMapCreateAttr{
|
||||
MapType: uint32(Array),
|
||||
KeySize: 4,
|
||||
ValueSize: 4,
|
||||
MaxEntries: 1,
|
||||
Flags: unix.BPF_F_RDONLY_PROG,
|
||||
})
|
||||
if err != nil {
|
||||
return internal.ErrNotSupported
|
||||
}
|
||||
_ = m.Close()
|
||||
return nil
|
||||
})
|
||||
|
||||
var haveMmapableMaps = internal.FeatureTest("mmapable maps", "5.5", func() error {
|
||||
// This checks BPF_F_MMAPABLE, which appeared in 5.5 for array maps.
|
||||
m, err := internal.BPFMapCreate(&internal.BPFMapCreateAttr{
|
||||
MapType: uint32(Array),
|
||||
KeySize: 4,
|
||||
ValueSize: 4,
|
||||
MaxEntries: 1,
|
||||
Flags: unix.BPF_F_MMAPABLE,
|
||||
})
|
||||
if err != nil {
|
||||
return internal.ErrNotSupported
|
||||
}
|
||||
_ = m.Close()
|
||||
return nil
|
||||
})
|
||||
|
||||
var haveInnerMaps = internal.FeatureTest("inner maps", "5.10", func() error {
|
||||
// This checks BPF_F_INNER_MAP, which appeared in 5.10.
|
||||
m, err := internal.BPFMapCreate(&internal.BPFMapCreateAttr{
|
||||
MapType: uint32(Array),
|
||||
KeySize: 4,
|
||||
ValueSize: 4,
|
||||
MaxEntries: 1,
|
||||
Flags: unix.BPF_F_INNER_MAP,
|
||||
})
|
||||
if err != nil {
|
||||
return internal.ErrNotSupported
|
||||
@ -329,7 +329,7 @@ func objGetNextID(cmd internal.BPFCmd, start uint32) (uint32, error) {
|
||||
startID: start,
|
||||
}
|
||||
_, err := internal.BPF(cmd, unsafe.Pointer(&attr), unsafe.Sizeof(attr))
|
||||
return attr.nextID, wrapObjError(err)
|
||||
return attr.nextID, err
|
||||
}
|
||||
|
||||
func bpfMapBatch(cmd internal.BPFCmd, m *internal.FD, inBatch, outBatch, keys, values internal.Pointer, count uint32, opts *BatchOptions) (uint32, error) {
|
||||
@ -355,35 +355,24 @@ func bpfMapBatch(cmd internal.BPFCmd, m *internal.FD, inBatch, outBatch, keys, v
|
||||
return attr.count, wrapMapError(err)
|
||||
}
|
||||
|
||||
func wrapObjError(err error) error {
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
if errors.Is(err, unix.ENOENT) {
|
||||
return fmt.Errorf("%w", ErrNotExist)
|
||||
}
|
||||
|
||||
return errors.New(err.Error())
|
||||
}
|
||||
|
||||
func wrapMapError(err error) error {
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
if errors.Is(err, unix.ENOENT) {
|
||||
return ErrKeyNotExist
|
||||
return internal.SyscallError(ErrKeyNotExist, unix.ENOENT)
|
||||
}
|
||||
|
||||
if errors.Is(err, unix.EEXIST) {
|
||||
return ErrKeyExist
|
||||
return internal.SyscallError(ErrKeyExist, unix.EEXIST)
|
||||
}
|
||||
|
||||
if errors.Is(err, unix.ENOTSUPP) {
|
||||
return ErrNotSupported
|
||||
return internal.SyscallError(ErrNotSupported, unix.ENOTSUPP)
|
||||
}
|
||||
|
||||
return errors.New(err.Error())
|
||||
return err
|
||||
}
|
||||
|
||||
func bpfMapFreeze(m *internal.FD) error {
|
||||
@ -417,15 +406,15 @@ func bpfGetMapInfoByFD(fd *internal.FD) (*bpfMapInfo, error) {
|
||||
}
|
||||
|
||||
var haveObjName = internal.FeatureTest("object names", "4.15", func() error {
|
||||
attr := bpfMapCreateAttr{
|
||||
mapType: Array,
|
||||
keySize: 4,
|
||||
valueSize: 4,
|
||||
maxEntries: 1,
|
||||
mapName: newBPFObjName("feature_test"),
|
||||
attr := internal.BPFMapCreateAttr{
|
||||
MapType: uint32(Array),
|
||||
KeySize: 4,
|
||||
ValueSize: 4,
|
||||
MaxEntries: 1,
|
||||
MapName: internal.NewBPFObjName("feature_test"),
|
||||
}
|
||||
|
||||
fd, err := bpfMapCreate(&attr)
|
||||
fd, err := internal.BPFMapCreate(&attr)
|
||||
if err != nil {
|
||||
return internal.ErrNotSupported
|
||||
}
|
||||
@ -439,15 +428,15 @@ var objNameAllowsDot = internal.FeatureTest("dot in object names", "5.2", func()
|
||||
return err
|
||||
}
|
||||
|
||||
attr := bpfMapCreateAttr{
|
||||
mapType: Array,
|
||||
keySize: 4,
|
||||
valueSize: 4,
|
||||
maxEntries: 1,
|
||||
mapName: newBPFObjName(".test"),
|
||||
attr := internal.BPFMapCreateAttr{
|
||||
MapType: uint32(Array),
|
||||
KeySize: 4,
|
||||
ValueSize: 4,
|
||||
MaxEntries: 1,
|
||||
MapName: internal.NewBPFObjName(".test"),
|
||||
}
|
||||
|
||||
fd, err := bpfMapCreate(&attr)
|
||||
fd, err := internal.BPFMapCreate(&attr)
|
||||
if err != nil {
|
||||
return internal.ErrNotSupported
|
||||
}
|
||||
@ -458,14 +447,14 @@ var objNameAllowsDot = internal.FeatureTest("dot in object names", "5.2", func()
|
||||
|
||||
var haveBatchAPI = internal.FeatureTest("map batch api", "5.6", func() error {
|
||||
var maxEntries uint32 = 2
|
||||
attr := bpfMapCreateAttr{
|
||||
mapType: Hash,
|
||||
keySize: 4,
|
||||
valueSize: 4,
|
||||
maxEntries: maxEntries,
|
||||
attr := internal.BPFMapCreateAttr{
|
||||
MapType: uint32(Hash),
|
||||
KeySize: 4,
|
||||
ValueSize: 4,
|
||||
MaxEntries: maxEntries,
|
||||
}
|
||||
|
||||
fd, err := bpfMapCreate(&attr)
|
||||
fd, err := internal.BPFMapCreate(&attr)
|
||||
if err != nil {
|
||||
return internal.ErrNotSupported
|
||||
}
|
||||
@ -487,5 +476,5 @@ func bpfObjGetFDByID(cmd internal.BPFCmd, id uint32) (*internal.FD, error) {
|
||||
id: id,
|
||||
}
|
||||
ptr, err := internal.BPF(cmd, unsafe.Pointer(&attr), unsafe.Sizeof(attr))
|
||||
return internal.NewFD(uint32(ptr)), wrapObjError(err)
|
||||
return internal.NewFD(uint32(ptr)), err
|
||||
}
|
||||
|
35
src/runtime/vendor/github.com/cilium/ebpf/types.go
generated
vendored
35
src/runtime/vendor/github.com/cilium/ebpf/types.go
generated
vendored
@ -1,5 +1,9 @@
|
||||
package ebpf
|
||||
|
||||
import (
|
||||
"github.com/cilium/ebpf/internal/unix"
|
||||
)
|
||||
|
||||
//go:generate stringer -output types_string.go -type=MapType,ProgramType,AttachType,PinType
|
||||
|
||||
// MapType indicates the type map structure
|
||||
@ -81,6 +85,10 @@ const (
|
||||
SkStorage
|
||||
// DevMapHash - Hash-based indexing scheme for references to network devices.
|
||||
DevMapHash
|
||||
StructOpts
|
||||
RingBuf
|
||||
InodeStorage
|
||||
TaskStorage
|
||||
)
|
||||
|
||||
// hasPerCPUValue returns true if the Map stores a value per CPU.
|
||||
@ -202,6 +210,33 @@ const (
|
||||
PinByName
|
||||
)
|
||||
|
||||
// LoadPinOptions control how a pinned object is loaded.
|
||||
type LoadPinOptions struct {
|
||||
// Request a read-only or write-only object. The default is a read-write
|
||||
// object. Only one of the flags may be set.
|
||||
ReadOnly bool
|
||||
WriteOnly bool
|
||||
|
||||
// Raw flags for the syscall. Other fields of this struct take precedence.
|
||||
Flags uint32
|
||||
}
|
||||
|
||||
// Marshal returns a value suitable for BPF_OBJ_GET syscall file_flags parameter.
|
||||
func (lpo *LoadPinOptions) Marshal() uint32 {
|
||||
if lpo == nil {
|
||||
return 0
|
||||
}
|
||||
|
||||
flags := lpo.Flags
|
||||
if lpo.ReadOnly {
|
||||
flags |= unix.BPF_F_RDONLY
|
||||
}
|
||||
if lpo.WriteOnly {
|
||||
flags |= unix.BPF_F_WRONLY
|
||||
}
|
||||
return flags
|
||||
}
|
||||
|
||||
// BatchOptions batch map operations options
|
||||
//
|
||||
// Mirrors libbpf struct bpf_map_batch_opts
|
||||
|
8
src/runtime/vendor/github.com/cilium/ebpf/types_string.go
generated
vendored
8
src/runtime/vendor/github.com/cilium/ebpf/types_string.go
generated
vendored
@ -34,11 +34,15 @@ func _() {
|
||||
_ = x[Stack-23]
|
||||
_ = x[SkStorage-24]
|
||||
_ = x[DevMapHash-25]
|
||||
_ = x[StructOpts-26]
|
||||
_ = x[RingBuf-27]
|
||||
_ = x[InodeStorage-28]
|
||||
_ = x[TaskStorage-29]
|
||||
}
|
||||
|
||||
const _MapType_name = "UnspecifiedMapHashArrayProgramArrayPerfEventArrayPerCPUHashPerCPUArrayStackTraceCGroupArrayLRUHashLRUCPUHashLPMTrieArrayOfMapsHashOfMapsDevMapSockMapCPUMapXSKMapSockHashCGroupStorageReusePortSockArrayPerCPUCGroupStorageQueueStackSkStorageDevMapHash"
|
||||
const _MapType_name = "UnspecifiedMapHashArrayProgramArrayPerfEventArrayPerCPUHashPerCPUArrayStackTraceCGroupArrayLRUHashLRUCPUHashLPMTrieArrayOfMapsHashOfMapsDevMapSockMapCPUMapXSKMapSockHashCGroupStorageReusePortSockArrayPerCPUCGroupStorageQueueStackSkStorageDevMapHashStructOptsRingBufInodeStorageTaskStorage"
|
||||
|
||||
var _MapType_index = [...]uint8{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}
|
||||
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}
|
||||
|
||||
func (i MapType) String() string {
|
||||
if i >= MapType(len(_MapType_index)-1) {
|
||||
|
61
src/runtime/vendor/github.com/coreos/go-systemd/v22/dbus/dbus.go
generated
vendored
61
src/runtime/vendor/github.com/coreos/go-systemd/v22/dbus/dbus.go
generated
vendored
@ -16,6 +16,7 @@
|
||||
package dbus
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"os"
|
||||
@ -110,46 +111,66 @@ type Conn struct {
|
||||
}
|
||||
}
|
||||
|
||||
// New establishes a connection to any available bus and authenticates.
|
||||
// Callers should call Close() when done with the connection.
|
||||
// Deprecated: use NewWithContext instead.
|
||||
func New() (*Conn, error) {
|
||||
conn, err := NewSystemConnection()
|
||||
return NewWithContext(context.Background())
|
||||
}
|
||||
|
||||
// NewWithContext establishes a connection to any available bus and authenticates.
|
||||
// Callers should call Close() when done with the connection.
|
||||
func NewWithContext(ctx context.Context) (*Conn, error) {
|
||||
conn, err := NewSystemConnectionContext(ctx)
|
||||
if err != nil && os.Geteuid() == 0 {
|
||||
return NewSystemdConnection()
|
||||
return NewSystemdConnectionContext(ctx)
|
||||
}
|
||||
return conn, err
|
||||
}
|
||||
|
||||
// NewSystemConnection establishes a connection to the system bus and authenticates.
|
||||
// Callers should call Close() when done with the connection
|
||||
// Deprecated: use NewSystemConnectionContext instead.
|
||||
func NewSystemConnection() (*Conn, error) {
|
||||
return NewSystemConnectionContext(context.Background())
|
||||
}
|
||||
|
||||
// NewSystemConnectionContext establishes a connection to the system bus and authenticates.
|
||||
// Callers should call Close() when done with the connection.
|
||||
func NewSystemConnectionContext(ctx context.Context) (*Conn, error) {
|
||||
return NewConnection(func() (*dbus.Conn, error) {
|
||||
return dbusAuthHelloConnection(dbus.SystemBusPrivate)
|
||||
return dbusAuthHelloConnection(ctx, dbus.SystemBusPrivate)
|
||||
})
|
||||
}
|
||||
|
||||
// NewUserConnection establishes a connection to the session bus and
|
||||
// Deprecated: use NewUserConnectionContext instead.
|
||||
func NewUserConnection() (*Conn, error) {
|
||||
return NewUserConnectionContext(context.Background())
|
||||
}
|
||||
|
||||
// NewUserConnectionContext establishes a connection to the session bus and
|
||||
// authenticates. This can be used to connect to systemd user instances.
|
||||
// Callers should call Close() when done with the connection.
|
||||
func NewUserConnection() (*Conn, error) {
|
||||
func NewUserConnectionContext(ctx context.Context) (*Conn, error) {
|
||||
return NewConnection(func() (*dbus.Conn, error) {
|
||||
return dbusAuthHelloConnection(dbus.SessionBusPrivate)
|
||||
return dbusAuthHelloConnection(ctx, dbus.SessionBusPrivate)
|
||||
})
|
||||
}
|
||||
|
||||
// NewSystemdConnection establishes a private, direct connection to systemd.
|
||||
// Deprecated: use NewSystemdConnectionContext instead.
|
||||
func NewSystemdConnection() (*Conn, error) {
|
||||
return NewSystemdConnectionContext(context.Background())
|
||||
}
|
||||
|
||||
// NewSystemdConnectionContext establishes a private, direct connection to systemd.
|
||||
// This can be used for communicating with systemd without a dbus daemon.
|
||||
// Callers should call Close() when done with the connection.
|
||||
func NewSystemdConnection() (*Conn, error) {
|
||||
func NewSystemdConnectionContext(ctx context.Context) (*Conn, error) {
|
||||
return NewConnection(func() (*dbus.Conn, error) {
|
||||
// We skip Hello when talking directly to systemd.
|
||||
return dbusAuthConnection(func(opts ...dbus.ConnOption) (*dbus.Conn, error) {
|
||||
return dbus.Dial("unix:path=/run/systemd/private")
|
||||
return dbusAuthConnection(ctx, func(opts ...dbus.ConnOption) (*dbus.Conn, error) {
|
||||
return dbus.Dial("unix:path=/run/systemd/private", opts...)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// Close closes an established connection
|
||||
// Close closes an established connection.
|
||||
func (c *Conn) Close() {
|
||||
c.sysconn.Close()
|
||||
c.sigconn.Close()
|
||||
@ -192,7 +213,7 @@ func NewConnection(dialBus func() (*dbus.Conn, error)) (*Conn, error) {
|
||||
|
||||
// GetManagerProperty returns the value of a property on the org.freedesktop.systemd1.Manager
|
||||
// interface. The value is returned in its string representation, as defined at
|
||||
// https://developer.gnome.org/glib/unstable/gvariant-text.html
|
||||
// https://developer.gnome.org/glib/unstable/gvariant-text.html.
|
||||
func (c *Conn) GetManagerProperty(prop string) (string, error) {
|
||||
variant, err := c.sysobj.GetProperty("org.freedesktop.systemd1.Manager." + prop)
|
||||
if err != nil {
|
||||
@ -201,8 +222,8 @@ func (c *Conn) GetManagerProperty(prop string) (string, error) {
|
||||
return variant.String(), nil
|
||||
}
|
||||
|
||||
func dbusAuthConnection(createBus func(opts ...dbus.ConnOption) (*dbus.Conn, error)) (*dbus.Conn, error) {
|
||||
conn, err := createBus()
|
||||
func dbusAuthConnection(ctx context.Context, createBus func(opts ...dbus.ConnOption) (*dbus.Conn, error)) (*dbus.Conn, error) {
|
||||
conn, err := createBus(dbus.WithContext(ctx))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -221,8 +242,8 @@ func dbusAuthConnection(createBus func(opts ...dbus.ConnOption) (*dbus.Conn, err
|
||||
return conn, nil
|
||||
}
|
||||
|
||||
func dbusAuthHelloConnection(createBus func(opts ...dbus.ConnOption) (*dbus.Conn, error)) (*dbus.Conn, error) {
|
||||
conn, err := dbusAuthConnection(createBus)
|
||||
func dbusAuthHelloConnection(ctx context.Context, createBus func(opts ...dbus.ConnOption) (*dbus.Conn, error)) (*dbus.Conn, error) {
|
||||
conn, err := dbusAuthConnection(ctx, createBus)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
452
src/runtime/vendor/github.com/coreos/go-systemd/v22/dbus/methods.go
generated
vendored
452
src/runtime/vendor/github.com/coreos/go-systemd/v22/dbus/methods.go
generated
vendored
@ -15,6 +15,7 @@
|
||||
package dbus
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"path"
|
||||
@ -23,6 +24,18 @@ import (
|
||||
"github.com/godbus/dbus/v5"
|
||||
)
|
||||
|
||||
// Who can be used to specify which process to kill in the unit via the KillUnitWithTarget API
|
||||
type Who string
|
||||
|
||||
const (
|
||||
// All sends the signal to all processes in the unit
|
||||
All Who = "all"
|
||||
// Main sends the signal to the main process of the unit
|
||||
Main Who = "main"
|
||||
// Control sends the signal to the control process of the unit
|
||||
Control Who = "control"
|
||||
)
|
||||
|
||||
func (c *Conn) jobComplete(signal *dbus.Signal) {
|
||||
var id uint32
|
||||
var job dbus.ObjectPath
|
||||
@ -38,14 +51,14 @@ func (c *Conn) jobComplete(signal *dbus.Signal) {
|
||||
c.jobListener.Unlock()
|
||||
}
|
||||
|
||||
func (c *Conn) startJob(ch chan<- string, job string, args ...interface{}) (int, error) {
|
||||
func (c *Conn) startJob(ctx context.Context, ch chan<- string, job string, args ...interface{}) (int, error) {
|
||||
if ch != nil {
|
||||
c.jobListener.Lock()
|
||||
defer c.jobListener.Unlock()
|
||||
}
|
||||
|
||||
var p dbus.ObjectPath
|
||||
err := c.sysobj.Call(job, 0, args...).Store(&p)
|
||||
err := c.sysobj.CallWithContext(ctx, job, 0, args...).Store(&p)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
@ -60,7 +73,12 @@ func (c *Conn) startJob(ch chan<- string, job string, args ...interface{}) (int,
|
||||
return jobID, nil
|
||||
}
|
||||
|
||||
// StartUnit enqueues a start job and depending jobs, if any (unless otherwise
|
||||
// Deprecated: use StartUnitContext instead.
|
||||
func (c *Conn) StartUnit(name string, mode string, ch chan<- string) (int, error) {
|
||||
return c.StartUnitContext(context.Background(), name, mode, ch)
|
||||
}
|
||||
|
||||
// StartUnitContext enqueues a start job and depending jobs, if any (unless otherwise
|
||||
// specified by the mode string).
|
||||
//
|
||||
// Takes the unit to activate, plus a mode string. The mode needs to be one of
|
||||
@ -90,72 +108,130 @@ func (c *Conn) startJob(ch chan<- string, job string, args ...interface{}) (int,
|
||||
// should not be considered authoritative.
|
||||
//
|
||||
// If an error does occur, it will be returned to the user alongside a job ID of 0.
|
||||
func (c *Conn) StartUnit(name string, mode string, ch chan<- string) (int, error) {
|
||||
return c.startJob(ch, "org.freedesktop.systemd1.Manager.StartUnit", name, mode)
|
||||
func (c *Conn) StartUnitContext(ctx context.Context, name string, mode string, ch chan<- string) (int, error) {
|
||||
return c.startJob(ctx, ch, "org.freedesktop.systemd1.Manager.StartUnit", name, mode)
|
||||
}
|
||||
|
||||
// StopUnit is similar to StartUnit but stops the specified unit rather
|
||||
// than starting it.
|
||||
// Deprecated: use StopUnitContext instead.
|
||||
func (c *Conn) StopUnit(name string, mode string, ch chan<- string) (int, error) {
|
||||
return c.startJob(ch, "org.freedesktop.systemd1.Manager.StopUnit", name, mode)
|
||||
return c.StopUnitContext(context.Background(), name, mode, ch)
|
||||
}
|
||||
|
||||
// ReloadUnit reloads a unit. Reloading is done only if the unit is already running and fails otherwise.
|
||||
// StopUnitContext is similar to StartUnitContext, but stops the specified unit
|
||||
// rather than starting it.
|
||||
func (c *Conn) StopUnitContext(ctx context.Context, name string, mode string, ch chan<- string) (int, error) {
|
||||
return c.startJob(ctx, ch, "org.freedesktop.systemd1.Manager.StopUnit", name, mode)
|
||||
}
|
||||
|
||||
// Deprecated: use ReloadUnitContext instead.
|
||||
func (c *Conn) ReloadUnit(name string, mode string, ch chan<- string) (int, error) {
|
||||
return c.startJob(ch, "org.freedesktop.systemd1.Manager.ReloadUnit", name, mode)
|
||||
return c.ReloadUnitContext(context.Background(), name, mode, ch)
|
||||
}
|
||||
|
||||
// RestartUnit restarts a service. If a service is restarted that isn't
|
||||
// running it will be started.
|
||||
// ReloadUnitContext reloads a unit. Reloading is done only if the unit
|
||||
// is already running, and fails otherwise.
|
||||
func (c *Conn) ReloadUnitContext(ctx context.Context, name string, mode string, ch chan<- string) (int, error) {
|
||||
return c.startJob(ctx, ch, "org.freedesktop.systemd1.Manager.ReloadUnit", name, mode)
|
||||
}
|
||||
|
||||
// Deprecated: use RestartUnitContext instead.
|
||||
func (c *Conn) RestartUnit(name string, mode string, ch chan<- string) (int, error) {
|
||||
return c.startJob(ch, "org.freedesktop.systemd1.Manager.RestartUnit", name, mode)
|
||||
return c.RestartUnitContext(context.Background(), name, mode, ch)
|
||||
}
|
||||
|
||||
// TryRestartUnit is like RestartUnit, except that a service that isn't running
|
||||
// is not affected by the restart.
|
||||
// RestartUnitContext restarts a service. If a service is restarted that isn't
|
||||
// running it will be started.
|
||||
func (c *Conn) RestartUnitContext(ctx context.Context, name string, mode string, ch chan<- string) (int, error) {
|
||||
return c.startJob(ctx, ch, "org.freedesktop.systemd1.Manager.RestartUnit", name, mode)
|
||||
}
|
||||
|
||||
// Deprecated: use TryRestartUnitContext instead.
|
||||
func (c *Conn) TryRestartUnit(name string, mode string, ch chan<- string) (int, error) {
|
||||
return c.startJob(ch, "org.freedesktop.systemd1.Manager.TryRestartUnit", name, mode)
|
||||
return c.TryRestartUnitContext(context.Background(), name, mode, ch)
|
||||
}
|
||||
|
||||
// ReloadOrRestartUnit attempts a reload if the unit supports it and use a restart
|
||||
// otherwise.
|
||||
// TryRestartUnitContext is like RestartUnitContext, except that a service that
|
||||
// isn't running is not affected by the restart.
|
||||
func (c *Conn) TryRestartUnitContext(ctx context.Context, name string, mode string, ch chan<- string) (int, error) {
|
||||
return c.startJob(ctx, ch, "org.freedesktop.systemd1.Manager.TryRestartUnit", name, mode)
|
||||
}
|
||||
|
||||
// Deprecated: use ReloadOrRestartUnitContext instead.
|
||||
func (c *Conn) ReloadOrRestartUnit(name string, mode string, ch chan<- string) (int, error) {
|
||||
return c.startJob(ch, "org.freedesktop.systemd1.Manager.ReloadOrRestartUnit", name, mode)
|
||||
return c.ReloadOrRestartUnitContext(context.Background(), name, mode, ch)
|
||||
}
|
||||
|
||||
// ReloadOrTryRestartUnit attempts a reload if the unit supports it and use a "Try"
|
||||
// flavored restart otherwise.
|
||||
// ReloadOrRestartUnitContext attempts a reload if the unit supports it and use
|
||||
// a restart otherwise.
|
||||
func (c *Conn) ReloadOrRestartUnitContext(ctx context.Context, name string, mode string, ch chan<- string) (int, error) {
|
||||
return c.startJob(ctx, ch, "org.freedesktop.systemd1.Manager.ReloadOrRestartUnit", name, mode)
|
||||
}
|
||||
|
||||
// Deprecated: use ReloadOrTryRestartUnitContext instead.
|
||||
func (c *Conn) ReloadOrTryRestartUnit(name string, mode string, ch chan<- string) (int, error) {
|
||||
return c.startJob(ch, "org.freedesktop.systemd1.Manager.ReloadOrTryRestartUnit", name, mode)
|
||||
return c.ReloadOrTryRestartUnitContext(context.Background(), name, mode, ch)
|
||||
}
|
||||
|
||||
// StartTransientUnit() may be used to create and start a transient unit, which
|
||||
// ReloadOrTryRestartUnitContext attempts a reload if the unit supports it,
|
||||
// and use a "Try" flavored restart otherwise.
|
||||
func (c *Conn) ReloadOrTryRestartUnitContext(ctx context.Context, name string, mode string, ch chan<- string) (int, error) {
|
||||
return c.startJob(ctx, ch, "org.freedesktop.systemd1.Manager.ReloadOrTryRestartUnit", name, mode)
|
||||
}
|
||||
|
||||
// Deprecated: use StartTransientUnitContext instead.
|
||||
func (c *Conn) StartTransientUnit(name string, mode string, properties []Property, ch chan<- string) (int, error) {
|
||||
return c.StartTransientUnitContext(context.Background(), name, mode, properties, ch)
|
||||
}
|
||||
|
||||
// StartTransientUnitContext may be used to create and start a transient unit, which
|
||||
// will be released as soon as it is not running or referenced anymore or the
|
||||
// system is rebooted. name is the unit name including suffix, and must be
|
||||
// unique. mode is the same as in StartUnit(), properties contains properties
|
||||
// unique. mode is the same as in StartUnitContext, properties contains properties
|
||||
// of the unit.
|
||||
func (c *Conn) StartTransientUnit(name string, mode string, properties []Property, ch chan<- string) (int, error) {
|
||||
return c.startJob(ch, "org.freedesktop.systemd1.Manager.StartTransientUnit", name, mode, properties, make([]PropertyCollection, 0))
|
||||
func (c *Conn) StartTransientUnitContext(ctx context.Context, name string, mode string, properties []Property, ch chan<- string) (int, error) {
|
||||
return c.startJob(ctx, ch, "org.freedesktop.systemd1.Manager.StartTransientUnit", name, mode, properties, make([]PropertyCollection, 0))
|
||||
}
|
||||
|
||||
// KillUnit takes the unit name and a UNIX signal number to send. All of the unit's
|
||||
// processes are killed.
|
||||
// Deprecated: use KillUnitContext instead.
|
||||
func (c *Conn) KillUnit(name string, signal int32) {
|
||||
c.sysobj.Call("org.freedesktop.systemd1.Manager.KillUnit", 0, name, "all", signal).Store()
|
||||
c.KillUnitContext(context.Background(), name, signal)
|
||||
}
|
||||
|
||||
// ResetFailedUnit resets the "failed" state of a specific unit.
|
||||
// KillUnitContext takes the unit name and a UNIX signal number to send.
|
||||
// All of the unit's processes are killed.
|
||||
func (c *Conn) KillUnitContext(ctx context.Context, name string, signal int32) {
|
||||
c.KillUnitWithTarget(ctx, name, All, signal)
|
||||
}
|
||||
|
||||
// KillUnitWithTarget is like KillUnitContext, but allows you to specify which
|
||||
// process in the unit to send the signal to.
|
||||
func (c *Conn) KillUnitWithTarget(ctx context.Context, name string, target Who, signal int32) error {
|
||||
return c.sysobj.CallWithContext(ctx, "org.freedesktop.systemd1.Manager.KillUnit", 0, name, string(target), signal).Store()
|
||||
}
|
||||
|
||||
// Deprecated: use ResetFailedUnitContext instead.
|
||||
func (c *Conn) ResetFailedUnit(name string) error {
|
||||
return c.sysobj.Call("org.freedesktop.systemd1.Manager.ResetFailedUnit", 0, name).Store()
|
||||
return c.ResetFailedUnitContext(context.Background(), name)
|
||||
}
|
||||
|
||||
// SystemState returns the systemd state. Equivalent to `systemctl is-system-running`.
|
||||
// ResetFailedUnitContext resets the "failed" state of a specific unit.
|
||||
func (c *Conn) ResetFailedUnitContext(ctx context.Context, name string) error {
|
||||
return c.sysobj.CallWithContext(ctx, "org.freedesktop.systemd1.Manager.ResetFailedUnit", 0, name).Store()
|
||||
}
|
||||
|
||||
// Deprecated: use SystemStateContext instead.
|
||||
func (c *Conn) SystemState() (*Property, error) {
|
||||
return c.SystemStateContext(context.Background())
|
||||
}
|
||||
|
||||
// SystemStateContext returns the systemd state. Equivalent to
|
||||
// systemctl is-system-running.
|
||||
func (c *Conn) SystemStateContext(ctx context.Context) (*Property, error) {
|
||||
var err error
|
||||
var prop dbus.Variant
|
||||
|
||||
obj := c.sysconn.Object("org.freedesktop.systemd1", "/org/freedesktop/systemd1")
|
||||
err = obj.Call("org.freedesktop.DBus.Properties.Get", 0, "org.freedesktop.systemd1.Manager", "SystemState").Store(&prop)
|
||||
err = obj.CallWithContext(ctx, "org.freedesktop.DBus.Properties.Get", 0, "org.freedesktop.systemd1.Manager", "SystemState").Store(&prop)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -163,8 +239,8 @@ func (c *Conn) SystemState() (*Property, error) {
|
||||
return &Property{Name: "SystemState", Value: prop}, nil
|
||||
}
|
||||
|
||||
// getProperties takes the unit path and returns all of its dbus object properties, for the given dbus interface
|
||||
func (c *Conn) getProperties(path dbus.ObjectPath, dbusInterface string) (map[string]interface{}, error) {
|
||||
// getProperties takes the unit path and returns all of its dbus object properties, for the given dbus interface.
|
||||
func (c *Conn) getProperties(ctx context.Context, path dbus.ObjectPath, dbusInterface string) (map[string]interface{}, error) {
|
||||
var err error
|
||||
var props map[string]dbus.Variant
|
||||
|
||||
@ -173,7 +249,7 @@ func (c *Conn) getProperties(path dbus.ObjectPath, dbusInterface string) (map[st
|
||||
}
|
||||
|
||||
obj := c.sysconn.Object("org.freedesktop.systemd1", path)
|
||||
err = obj.Call("org.freedesktop.DBus.Properties.GetAll", 0, dbusInterface).Store(&props)
|
||||
err = obj.CallWithContext(ctx, "org.freedesktop.DBus.Properties.GetAll", 0, dbusInterface).Store(&props)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -186,24 +262,42 @@ func (c *Conn) getProperties(path dbus.ObjectPath, dbusInterface string) (map[st
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// GetUnitProperties takes the (unescaped) unit name and returns all of its dbus object properties.
|
||||
// Deprecated: use GetUnitPropertiesContext instead.
|
||||
func (c *Conn) GetUnitProperties(unit string) (map[string]interface{}, error) {
|
||||
path := unitPath(unit)
|
||||
return c.getProperties(path, "org.freedesktop.systemd1.Unit")
|
||||
return c.GetUnitPropertiesContext(context.Background(), unit)
|
||||
}
|
||||
|
||||
// GetUnitPathProperties takes the (escaped) unit path and returns all of its dbus object properties.
|
||||
// GetUnitPropertiesContext takes the (unescaped) unit name and returns all of
|
||||
// its dbus object properties.
|
||||
func (c *Conn) GetUnitPropertiesContext(ctx context.Context, unit string) (map[string]interface{}, error) {
|
||||
path := unitPath(unit)
|
||||
return c.getProperties(ctx, path, "org.freedesktop.systemd1.Unit")
|
||||
}
|
||||
|
||||
// Deprecated: use GetUnitPathPropertiesContext instead.
|
||||
func (c *Conn) GetUnitPathProperties(path dbus.ObjectPath) (map[string]interface{}, error) {
|
||||
return c.getProperties(path, "org.freedesktop.systemd1.Unit")
|
||||
return c.GetUnitPathPropertiesContext(context.Background(), path)
|
||||
}
|
||||
|
||||
// GetAllProperties takes the (unescaped) unit name and returns all of its dbus object properties.
|
||||
// GetUnitPathPropertiesContext takes the (escaped) unit path and returns all
|
||||
// of its dbus object properties.
|
||||
func (c *Conn) GetUnitPathPropertiesContext(ctx context.Context, path dbus.ObjectPath) (map[string]interface{}, error) {
|
||||
return c.getProperties(ctx, path, "org.freedesktop.systemd1.Unit")
|
||||
}
|
||||
|
||||
// Deprecated: use GetAllPropertiesContext instead.
|
||||
func (c *Conn) GetAllProperties(unit string) (map[string]interface{}, error) {
|
||||
path := unitPath(unit)
|
||||
return c.getProperties(path, "")
|
||||
return c.GetAllPropertiesContext(context.Background(), unit)
|
||||
}
|
||||
|
||||
func (c *Conn) getProperty(unit string, dbusInterface string, propertyName string) (*Property, error) {
|
||||
// GetAllPropertiesContext takes the (unescaped) unit name and returns all of
|
||||
// its dbus object properties.
|
||||
func (c *Conn) GetAllPropertiesContext(ctx context.Context, unit string) (map[string]interface{}, error) {
|
||||
path := unitPath(unit)
|
||||
return c.getProperties(ctx, path, "")
|
||||
}
|
||||
|
||||
func (c *Conn) getProperty(ctx context.Context, unit string, dbusInterface string, propertyName string) (*Property, error) {
|
||||
var err error
|
||||
var prop dbus.Variant
|
||||
|
||||
@ -213,7 +307,7 @@ func (c *Conn) getProperty(unit string, dbusInterface string, propertyName strin
|
||||
}
|
||||
|
||||
obj := c.sysconn.Object("org.freedesktop.systemd1", path)
|
||||
err = obj.Call("org.freedesktop.DBus.Properties.Get", 0, dbusInterface, propertyName).Store(&prop)
|
||||
err = obj.CallWithContext(ctx, "org.freedesktop.DBus.Properties.Get", 0, dbusInterface, propertyName).Store(&prop)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -221,36 +315,65 @@ func (c *Conn) getProperty(unit string, dbusInterface string, propertyName strin
|
||||
return &Property{Name: propertyName, Value: prop}, nil
|
||||
}
|
||||
|
||||
// Deprecated: use GetUnitPropertyContext instead.
|
||||
func (c *Conn) GetUnitProperty(unit string, propertyName string) (*Property, error) {
|
||||
return c.getProperty(unit, "org.freedesktop.systemd1.Unit", propertyName)
|
||||
return c.GetUnitPropertyContext(context.Background(), unit, propertyName)
|
||||
}
|
||||
|
||||
// GetServiceProperty returns property for given service name and property name
|
||||
// GetUnitPropertyContext takes an (unescaped) unit name, and a property name,
|
||||
// and returns the property value.
|
||||
func (c *Conn) GetUnitPropertyContext(ctx context.Context, unit string, propertyName string) (*Property, error) {
|
||||
return c.getProperty(ctx, unit, "org.freedesktop.systemd1.Unit", propertyName)
|
||||
}
|
||||
|
||||
// Deprecated: use GetServicePropertyContext instead.
|
||||
func (c *Conn) GetServiceProperty(service string, propertyName string) (*Property, error) {
|
||||
return c.getProperty(service, "org.freedesktop.systemd1.Service", propertyName)
|
||||
return c.GetServicePropertyContext(context.Background(), service, propertyName)
|
||||
}
|
||||
|
||||
// GetUnitTypeProperties returns the extra properties for a unit, specific to the unit type.
|
||||
// Valid values for unitType: Service, Socket, Target, Device, Mount, Automount, Snapshot, Timer, Swap, Path, Slice, Scope
|
||||
// return "dbus.Error: Unknown interface" if the unitType is not the correct type of the unit
|
||||
// GetServiceProperty returns property for given service name and property name.
|
||||
func (c *Conn) GetServicePropertyContext(ctx context.Context, service string, propertyName string) (*Property, error) {
|
||||
return c.getProperty(ctx, service, "org.freedesktop.systemd1.Service", propertyName)
|
||||
}
|
||||
|
||||
// Deprecated: use GetUnitTypePropertiesContext instead.
|
||||
func (c *Conn) GetUnitTypeProperties(unit string, unitType string) (map[string]interface{}, error) {
|
||||
path := unitPath(unit)
|
||||
return c.getProperties(path, "org.freedesktop.systemd1."+unitType)
|
||||
return c.GetUnitTypePropertiesContext(context.Background(), unit, unitType)
|
||||
}
|
||||
|
||||
// SetUnitProperties() may be used to modify certain unit properties at runtime.
|
||||
// GetUnitTypePropertiesContext returns the extra properties for a unit, specific to the unit type.
|
||||
// Valid values for unitType: Service, Socket, Target, Device, Mount, Automount, Snapshot, Timer, Swap, Path, Slice, Scope.
|
||||
// Returns "dbus.Error: Unknown interface" error if the unitType is not the correct type of the unit.
|
||||
func (c *Conn) GetUnitTypePropertiesContext(ctx context.Context, unit string, unitType string) (map[string]interface{}, error) {
|
||||
path := unitPath(unit)
|
||||
return c.getProperties(ctx, path, "org.freedesktop.systemd1."+unitType)
|
||||
}
|
||||
|
||||
// Deprecated: use SetUnitPropertiesContext instead.
|
||||
func (c *Conn) SetUnitProperties(name string, runtime bool, properties ...Property) error {
|
||||
return c.SetUnitPropertiesContext(context.Background(), name, runtime, properties...)
|
||||
}
|
||||
|
||||
// SetUnitPropertiesContext may be used to modify certain unit properties at runtime.
|
||||
// Not all properties may be changed at runtime, but many resource management
|
||||
// settings (primarily those in systemd.cgroup(5)) may. The changes are applied
|
||||
// instantly, and stored on disk for future boots, unless runtime is true, in which
|
||||
// case the settings only apply until the next reboot. name is the name of the unit
|
||||
// to modify. properties are the settings to set, encoded as an array of property
|
||||
// name and value pairs.
|
||||
func (c *Conn) SetUnitProperties(name string, runtime bool, properties ...Property) error {
|
||||
return c.sysobj.Call("org.freedesktop.systemd1.Manager.SetUnitProperties", 0, name, runtime, properties).Store()
|
||||
func (c *Conn) SetUnitPropertiesContext(ctx context.Context, name string, runtime bool, properties ...Property) error {
|
||||
return c.sysobj.CallWithContext(ctx, "org.freedesktop.systemd1.Manager.SetUnitProperties", 0, name, runtime, properties).Store()
|
||||
}
|
||||
|
||||
// Deprecated: use GetUnitTypePropertyContext instead.
|
||||
func (c *Conn) GetUnitTypeProperty(unit string, unitType string, propertyName string) (*Property, error) {
|
||||
return c.getProperty(unit, "org.freedesktop.systemd1."+unitType, propertyName)
|
||||
return c.GetUnitTypePropertyContext(context.Background(), unit, unitType, propertyName)
|
||||
}
|
||||
|
||||
// GetUnitTypePropertyContext takes a property name, a unit name, and a unit type,
|
||||
// and returns a property value. For valid values of unitType, see GetUnitTypePropertiesContext.
|
||||
func (c *Conn) GetUnitTypePropertyContext(ctx context.Context, unit string, unitType string, propertyName string) (*Property, error) {
|
||||
return c.getProperty(ctx, unit, "org.freedesktop.systemd1."+unitType, propertyName)
|
||||
}
|
||||
|
||||
type UnitStatus struct {
|
||||
@ -294,36 +417,57 @@ func (c *Conn) listUnitsInternal(f storeFunc) ([]UnitStatus, error) {
|
||||
return status, nil
|
||||
}
|
||||
|
||||
// ListUnits returns an array with all currently loaded units. Note that
|
||||
// Deprecated: use ListUnitsContext instead.
|
||||
func (c *Conn) ListUnits() ([]UnitStatus, error) {
|
||||
return c.ListUnitsContext(context.Background())
|
||||
}
|
||||
|
||||
// ListUnitsContext returns an array with all currently loaded units. Note that
|
||||
// units may be known by multiple names at the same time, and hence there might
|
||||
// be more unit names loaded than actual units behind them.
|
||||
// Also note that a unit is only loaded if it is active and/or enabled.
|
||||
// Units that are both disabled and inactive will thus not be returned.
|
||||
func (c *Conn) ListUnits() ([]UnitStatus, error) {
|
||||
return c.listUnitsInternal(c.sysobj.Call("org.freedesktop.systemd1.Manager.ListUnits", 0).Store)
|
||||
func (c *Conn) ListUnitsContext(ctx context.Context) ([]UnitStatus, error) {
|
||||
return c.listUnitsInternal(c.sysobj.CallWithContext(ctx, "org.freedesktop.systemd1.Manager.ListUnits", 0).Store)
|
||||
}
|
||||
|
||||
// ListUnitsFiltered returns an array with units filtered by state.
|
||||
// It takes a list of units' statuses to filter.
|
||||
// Deprecated: use ListUnitsFilteredContext instead.
|
||||
func (c *Conn) ListUnitsFiltered(states []string) ([]UnitStatus, error) {
|
||||
return c.listUnitsInternal(c.sysobj.Call("org.freedesktop.systemd1.Manager.ListUnitsFiltered", 0, states).Store)
|
||||
return c.ListUnitsFilteredContext(context.Background(), states)
|
||||
}
|
||||
|
||||
// ListUnitsByPatterns returns an array with units.
|
||||
// ListUnitsFilteredContext returns an array with units filtered by state.
|
||||
// It takes a list of units' statuses to filter.
|
||||
func (c *Conn) ListUnitsFilteredContext(ctx context.Context, states []string) ([]UnitStatus, error) {
|
||||
return c.listUnitsInternal(c.sysobj.CallWithContext(ctx, "org.freedesktop.systemd1.Manager.ListUnitsFiltered", 0, states).Store)
|
||||
}
|
||||
|
||||
// Deprecated: use ListUnitsByPatternsContext instead.
|
||||
func (c *Conn) ListUnitsByPatterns(states []string, patterns []string) ([]UnitStatus, error) {
|
||||
return c.ListUnitsByPatternsContext(context.Background(), states, patterns)
|
||||
}
|
||||
|
||||
// ListUnitsByPatternsContext returns an array with units.
|
||||
// It takes a list of units' statuses and names to filter.
|
||||
// Note that units may be known by multiple names at the same time,
|
||||
// and hence there might be more unit names loaded than actual units behind them.
|
||||
func (c *Conn) ListUnitsByPatterns(states []string, patterns []string) ([]UnitStatus, error) {
|
||||
return c.listUnitsInternal(c.sysobj.Call("org.freedesktop.systemd1.Manager.ListUnitsByPatterns", 0, states, patterns).Store)
|
||||
func (c *Conn) ListUnitsByPatternsContext(ctx context.Context, states []string, patterns []string) ([]UnitStatus, error) {
|
||||
return c.listUnitsInternal(c.sysobj.CallWithContext(ctx, "org.freedesktop.systemd1.Manager.ListUnitsByPatterns", 0, states, patterns).Store)
|
||||
}
|
||||
|
||||
// ListUnitsByNames returns an array with units. It takes a list of units'
|
||||
// names and returns an UnitStatus array. Comparing to ListUnitsByPatterns
|
||||
// Deprecated: use ListUnitsByNamesContext instead.
|
||||
func (c *Conn) ListUnitsByNames(units []string) ([]UnitStatus, error) {
|
||||
return c.ListUnitsByNamesContext(context.Background(), units)
|
||||
}
|
||||
|
||||
// ListUnitsByNamesContext returns an array with units. It takes a list of units'
|
||||
// names and returns an UnitStatus array. Comparing to ListUnitsByPatternsContext
|
||||
// method, this method returns statuses even for inactive or non-existing
|
||||
// units. Input array should contain exact unit names, but not patterns.
|
||||
// Note: Requires systemd v230 or higher
|
||||
func (c *Conn) ListUnitsByNames(units []string) ([]UnitStatus, error) {
|
||||
return c.listUnitsInternal(c.sysobj.Call("org.freedesktop.systemd1.Manager.ListUnitsByNames", 0, units).Store)
|
||||
//
|
||||
// Requires systemd v230 or higher.
|
||||
func (c *Conn) ListUnitsByNamesContext(ctx context.Context, units []string) ([]UnitStatus, error) {
|
||||
return c.listUnitsInternal(c.sysobj.CallWithContext(ctx, "org.freedesktop.systemd1.Manager.ListUnitsByNames", 0, units).Store)
|
||||
}
|
||||
|
||||
type UnitFile struct {
|
||||
@ -357,25 +501,43 @@ func (c *Conn) listUnitFilesInternal(f storeFunc) ([]UnitFile, error) {
|
||||
return files, nil
|
||||
}
|
||||
|
||||
// ListUnitFiles returns an array of all available units on disk.
|
||||
// Deprecated: use ListUnitFilesContext instead.
|
||||
func (c *Conn) ListUnitFiles() ([]UnitFile, error) {
|
||||
return c.listUnitFilesInternal(c.sysobj.Call("org.freedesktop.systemd1.Manager.ListUnitFiles", 0).Store)
|
||||
return c.ListUnitFilesContext(context.Background())
|
||||
}
|
||||
|
||||
// ListUnitFilesByPatterns returns an array of all available units on disk matched the patterns.
|
||||
// ListUnitFiles returns an array of all available units on disk.
|
||||
func (c *Conn) ListUnitFilesContext(ctx context.Context) ([]UnitFile, error) {
|
||||
return c.listUnitFilesInternal(c.sysobj.CallWithContext(ctx, "org.freedesktop.systemd1.Manager.ListUnitFiles", 0).Store)
|
||||
}
|
||||
|
||||
// Deprecated: use ListUnitFilesByPatternsContext instead.
|
||||
func (c *Conn) ListUnitFilesByPatterns(states []string, patterns []string) ([]UnitFile, error) {
|
||||
return c.listUnitFilesInternal(c.sysobj.Call("org.freedesktop.systemd1.Manager.ListUnitFilesByPatterns", 0, states, patterns).Store)
|
||||
return c.ListUnitFilesByPatternsContext(context.Background(), states, patterns)
|
||||
}
|
||||
|
||||
// ListUnitFilesByPatternsContext returns an array of all available units on disk matched the patterns.
|
||||
func (c *Conn) ListUnitFilesByPatternsContext(ctx context.Context, states []string, patterns []string) ([]UnitFile, error) {
|
||||
return c.listUnitFilesInternal(c.sysobj.CallWithContext(ctx, "org.freedesktop.systemd1.Manager.ListUnitFilesByPatterns", 0, states, patterns).Store)
|
||||
}
|
||||
|
||||
type LinkUnitFileChange EnableUnitFileChange
|
||||
|
||||
// LinkUnitFiles() links unit files (that are located outside of the
|
||||
// Deprecated: use LinkUnitFilesContext instead.
|
||||
func (c *Conn) LinkUnitFiles(files []string, runtime bool, force bool) ([]LinkUnitFileChange, error) {
|
||||
return c.LinkUnitFilesContext(context.Background(), files, runtime, force)
|
||||
}
|
||||
|
||||
// LinkUnitFilesContext links unit files (that are located outside of the
|
||||
// usual unit search paths) into the unit search path.
|
||||
//
|
||||
// It takes a list of absolute paths to unit files to link and two
|
||||
// booleans. The first boolean controls whether the unit shall be
|
||||
// booleans.
|
||||
//
|
||||
// The first boolean controls whether the unit shall be
|
||||
// enabled for runtime only (true, /run), or persistently (false,
|
||||
// /etc).
|
||||
//
|
||||
// The second controls whether symlinks pointing to other units shall
|
||||
// be replaced if necessary.
|
||||
//
|
||||
@ -383,9 +545,9 @@ type LinkUnitFileChange EnableUnitFileChange
|
||||
// structures with three strings: the type of the change (one of symlink
|
||||
// or unlink), the file name of the symlink and the destination of the
|
||||
// symlink.
|
||||
func (c *Conn) LinkUnitFiles(files []string, runtime bool, force bool) ([]LinkUnitFileChange, error) {
|
||||
func (c *Conn) LinkUnitFilesContext(ctx context.Context, files []string, runtime bool, force bool) ([]LinkUnitFileChange, error) {
|
||||
result := make([][]interface{}, 0)
|
||||
err := c.sysobj.Call("org.freedesktop.systemd1.Manager.LinkUnitFiles", 0, files, runtime, force).Store(&result)
|
||||
err := c.sysobj.CallWithContext(ctx, "org.freedesktop.systemd1.Manager.LinkUnitFiles", 0, files, runtime, force).Store(&result)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -409,8 +571,13 @@ func (c *Conn) LinkUnitFiles(files []string, runtime bool, force bool) ([]LinkUn
|
||||
return changes, nil
|
||||
}
|
||||
|
||||
// EnableUnitFiles() may be used to enable one or more units in the system (by
|
||||
// creating symlinks to them in /etc or /run).
|
||||
// Deprecated: use EnableUnitFilesContext instead.
|
||||
func (c *Conn) EnableUnitFiles(files []string, runtime bool, force bool) (bool, []EnableUnitFileChange, error) {
|
||||
return c.EnableUnitFilesContext(context.Background(), files, runtime, force)
|
||||
}
|
||||
|
||||
// EnableUnitFilesContext may be used to enable one or more units in the system
|
||||
// (by creating symlinks to them in /etc or /run).
|
||||
//
|
||||
// It takes a list of unit files to enable (either just file names or full
|
||||
// absolute paths if the unit files are residing outside the usual unit
|
||||
@ -425,11 +592,11 @@ func (c *Conn) LinkUnitFiles(files []string, runtime bool, force bool) ([]LinkUn
|
||||
// structures with three strings: the type of the change (one of symlink
|
||||
// or unlink), the file name of the symlink and the destination of the
|
||||
// symlink.
|
||||
func (c *Conn) EnableUnitFiles(files []string, runtime bool, force bool) (bool, []EnableUnitFileChange, error) {
|
||||
func (c *Conn) EnableUnitFilesContext(ctx context.Context, files []string, runtime bool, force bool) (bool, []EnableUnitFileChange, error) {
|
||||
var carries_install_info bool
|
||||
|
||||
result := make([][]interface{}, 0)
|
||||
err := c.sysobj.Call("org.freedesktop.systemd1.Manager.EnableUnitFiles", 0, files, runtime, force).Store(&carries_install_info, &result)
|
||||
err := c.sysobj.CallWithContext(ctx, "org.freedesktop.systemd1.Manager.EnableUnitFiles", 0, files, runtime, force).Store(&carries_install_info, &result)
|
||||
if err != nil {
|
||||
return false, nil, err
|
||||
}
|
||||
@ -459,8 +626,13 @@ type EnableUnitFileChange struct {
|
||||
Destination string // Destination of the symlink
|
||||
}
|
||||
|
||||
// DisableUnitFiles() may be used to disable one or more units in the system (by
|
||||
// removing symlinks to them from /etc or /run).
|
||||
// Deprecated: use DisableUnitFilesContext instead.
|
||||
func (c *Conn) DisableUnitFiles(files []string, runtime bool) ([]DisableUnitFileChange, error) {
|
||||
return c.DisableUnitFilesContext(context.Background(), files, runtime)
|
||||
}
|
||||
|
||||
// DisableUnitFilesContext may be used to disable one or more units in the
|
||||
// system (by removing symlinks to them from /etc or /run).
|
||||
//
|
||||
// It takes a list of unit files to disable (either just file names or full
|
||||
// absolute paths if the unit files are residing outside the usual unit
|
||||
@ -471,9 +643,9 @@ type EnableUnitFileChange struct {
|
||||
// consists of structures with three strings: the type of the change (one of
|
||||
// symlink or unlink), the file name of the symlink and the destination of the
|
||||
// symlink.
|
||||
func (c *Conn) DisableUnitFiles(files []string, runtime bool) ([]DisableUnitFileChange, error) {
|
||||
func (c *Conn) DisableUnitFilesContext(ctx context.Context, files []string, runtime bool) ([]DisableUnitFileChange, error) {
|
||||
result := make([][]interface{}, 0)
|
||||
err := c.sysobj.Call("org.freedesktop.systemd1.Manager.DisableUnitFiles", 0, files, runtime).Store(&result)
|
||||
err := c.sysobj.CallWithContext(ctx, "org.freedesktop.systemd1.Manager.DisableUnitFiles", 0, files, runtime).Store(&result)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -503,18 +675,23 @@ type DisableUnitFileChange struct {
|
||||
Destination string // Destination of the symlink
|
||||
}
|
||||
|
||||
// MaskUnitFiles masks one or more units in the system
|
||||
//
|
||||
// It takes three arguments:
|
||||
// * list of units to mask (either just file names or full
|
||||
// absolute paths if the unit files are residing outside
|
||||
// the usual unit search paths)
|
||||
// * runtime to specify whether the unit was enabled for runtime
|
||||
// only (true, /run/systemd/..), or persistently (false, /etc/systemd/..)
|
||||
// * force flag
|
||||
// Deprecated: use MaskUnitFilesContext instead.
|
||||
func (c *Conn) MaskUnitFiles(files []string, runtime bool, force bool) ([]MaskUnitFileChange, error) {
|
||||
return c.MaskUnitFilesContext(context.Background(), files, runtime, force)
|
||||
}
|
||||
|
||||
// MaskUnitFilesContext masks one or more units in the system.
|
||||
//
|
||||
// The files argument contains a list of units to mask (either just file names
|
||||
// or full absolute paths if the unit files are residing outside the usual unit
|
||||
// search paths).
|
||||
//
|
||||
// The runtime argument is used to specify whether the unit was enabled for
|
||||
// runtime only (true, /run/systemd/..), or persistently (false,
|
||||
// /etc/systemd/..).
|
||||
func (c *Conn) MaskUnitFilesContext(ctx context.Context, files []string, runtime bool, force bool) ([]MaskUnitFileChange, error) {
|
||||
result := make([][]interface{}, 0)
|
||||
err := c.sysobj.Call("org.freedesktop.systemd1.Manager.MaskUnitFiles", 0, files, runtime, force).Store(&result)
|
||||
err := c.sysobj.CallWithContext(ctx, "org.freedesktop.systemd1.Manager.MaskUnitFiles", 0, files, runtime, force).Store(&result)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -544,17 +721,21 @@ type MaskUnitFileChange struct {
|
||||
Destination string // Destination of the symlink
|
||||
}
|
||||
|
||||
// UnmaskUnitFiles unmasks one or more units in the system
|
||||
//
|
||||
// It takes two arguments:
|
||||
// * list of unit files to mask (either just file names or full
|
||||
// absolute paths if the unit files are residing outside
|
||||
// the usual unit search paths)
|
||||
// * runtime to specify whether the unit was enabled for runtime
|
||||
// only (true, /run/systemd/..), or persistently (false, /etc/systemd/..)
|
||||
// Deprecated: use UnmaskUnitFilesContext instead.
|
||||
func (c *Conn) UnmaskUnitFiles(files []string, runtime bool) ([]UnmaskUnitFileChange, error) {
|
||||
return c.UnmaskUnitFilesContext(context.Background(), files, runtime)
|
||||
}
|
||||
|
||||
// UnmaskUnitFilesContext unmasks one or more units in the system.
|
||||
//
|
||||
// It takes the list of unit files to mask (either just file names or full
|
||||
// absolute paths if the unit files are residing outside the usual unit search
|
||||
// paths), and a boolean runtime flag to specify whether the unit was enabled
|
||||
// for runtime only (true, /run/systemd/..), or persistently (false,
|
||||
// /etc/systemd/..).
|
||||
func (c *Conn) UnmaskUnitFilesContext(ctx context.Context, files []string, runtime bool) ([]UnmaskUnitFileChange, error) {
|
||||
result := make([][]interface{}, 0)
|
||||
err := c.sysobj.Call("org.freedesktop.systemd1.Manager.UnmaskUnitFiles", 0, files, runtime).Store(&result)
|
||||
err := c.sysobj.CallWithContext(ctx, "org.freedesktop.systemd1.Manager.UnmaskUnitFiles", 0, files, runtime).Store(&result)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -584,17 +765,66 @@ type UnmaskUnitFileChange struct {
|
||||
Destination string // Destination of the symlink
|
||||
}
|
||||
|
||||
// Reload instructs systemd to scan for and reload unit files. This is
|
||||
// equivalent to a 'systemctl daemon-reload'.
|
||||
// Deprecated: use ReloadContext instead.
|
||||
func (c *Conn) Reload() error {
|
||||
return c.sysobj.Call("org.freedesktop.systemd1.Manager.Reload", 0).Store()
|
||||
return c.ReloadContext(context.Background())
|
||||
}
|
||||
|
||||
// ReloadContext instructs systemd to scan for and reload unit files. This is
|
||||
// an equivalent to systemctl daemon-reload.
|
||||
func (c *Conn) ReloadContext(ctx context.Context) error {
|
||||
return c.sysobj.CallWithContext(ctx, "org.freedesktop.systemd1.Manager.Reload", 0).Store()
|
||||
}
|
||||
|
||||
func unitPath(name string) dbus.ObjectPath {
|
||||
return dbus.ObjectPath("/org/freedesktop/systemd1/unit/" + PathBusEscape(name))
|
||||
}
|
||||
|
||||
// unitName returns the unescaped base element of the supplied escaped path
|
||||
// unitName returns the unescaped base element of the supplied escaped path.
|
||||
func unitName(dpath dbus.ObjectPath) string {
|
||||
return pathBusUnescape(path.Base(string(dpath)))
|
||||
}
|
||||
|
||||
// JobStatus holds a currently queued job definition.
|
||||
type JobStatus struct {
|
||||
Id uint32 // The numeric job id
|
||||
Unit string // The primary unit name for this job
|
||||
JobType string // The job type as string
|
||||
Status string // The job state as string
|
||||
JobPath dbus.ObjectPath // The job object path
|
||||
UnitPath dbus.ObjectPath // The unit object path
|
||||
}
|
||||
|
||||
// Deprecated: use ListJobsContext instead.
|
||||
func (c *Conn) ListJobs() ([]JobStatus, error) {
|
||||
return c.ListJobsContext(context.Background())
|
||||
}
|
||||
|
||||
// ListJobsContext returns an array with all currently queued jobs.
|
||||
func (c *Conn) ListJobsContext(ctx context.Context) ([]JobStatus, error) {
|
||||
return c.listJobsInternal(ctx)
|
||||
}
|
||||
|
||||
func (c *Conn) listJobsInternal(ctx context.Context) ([]JobStatus, error) {
|
||||
result := make([][]interface{}, 0)
|
||||
if err := c.sysobj.CallWithContext(ctx, "org.freedesktop.systemd1.Manager.ListJobs", 0).Store(&result); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resultInterface := make([]interface{}, len(result))
|
||||
for i := range result {
|
||||
resultInterface[i] = result[i]
|
||||
}
|
||||
|
||||
status := make([]JobStatus, len(result))
|
||||
statusInterface := make([]interface{}, len(status))
|
||||
for i := range status {
|
||||
statusInterface[i] = &status[i]
|
||||
}
|
||||
|
||||
if err := dbus.Store(resultInterface, statusInterface...); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return status, nil
|
||||
}
|
||||
|
50
src/runtime/vendor/github.com/godbus/dbus/v5/.travis.yml
generated
vendored
50
src/runtime/vendor/github.com/godbus/dbus/v5/.travis.yml
generated
vendored
@ -1,50 +0,0 @@
|
||||
dist: bionic
|
||||
language: go
|
||||
go_import_path: github.com/godbus/dbus
|
||||
|
||||
go:
|
||||
- 1.11.x
|
||||
- 1.12.x
|
||||
- 1.13.x
|
||||
- tip
|
||||
|
||||
matrix:
|
||||
fast_finish: true
|
||||
allow_failures:
|
||||
- go: tip
|
||||
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- dbus
|
||||
- dbus-x11
|
||||
|
||||
before_install:
|
||||
- export GO111MODULE=on
|
||||
|
||||
script:
|
||||
- go test -v -race -mod=readonly ./... # Run all the tests with the race detector enabled
|
||||
- go vet ./... # go vet is the official Go static analyzer
|
||||
|
||||
jobs:
|
||||
include:
|
||||
# The build matrix doesn't cover build stages, so manually expand
|
||||
# the jobs with anchors
|
||||
- &multiarch
|
||||
stage: "Multiarch Test"
|
||||
go: 1.11.x
|
||||
env: TARGETS="386 arm arm64 ppc64le"
|
||||
before_install:
|
||||
- docker run --rm --privileged multiarch/qemu-user-static --reset -p yes
|
||||
script:
|
||||
- |
|
||||
set -e
|
||||
for target in $TARGETS; do
|
||||
printf "\e[1mRunning test suite under ${target}.\e[0m\n"
|
||||
GOARCH="$target" go test -v ./...
|
||||
printf "\n\n"
|
||||
done
|
||||
- <<: *multiarch
|
||||
go: 1.12.x
|
||||
- <<: *multiarch
|
||||
go: 1.13.x
|
4
src/runtime/vendor/github.com/godbus/dbus/v5/README.markdown
generated
vendored
4
src/runtime/vendor/github.com/godbus/dbus/v5/README.markdown
generated
vendored
@ -1,4 +1,4 @@
|
||||
[](https://travis-ci.org/godbus/dbus)
|
||||

|
||||
|
||||
dbus
|
||||
----
|
||||
@ -32,6 +32,8 @@ gives a short overview over the basic usage.
|
||||
#### Projects using godbus
|
||||
- [notify](https://github.com/esiqveland/notify) provides desktop notifications over dbus into a library.
|
||||
- [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".
|
||||
|
||||
Please note that the API is considered unstable for now and may change without
|
||||
further notice.
|
||||
|
2
src/runtime/vendor/github.com/godbus/dbus/v5/auth.go
generated
vendored
2
src/runtime/vendor/github.com/godbus/dbus/v5/auth.go
generated
vendored
@ -37,7 +37,7 @@ const (
|
||||
|
||||
// Auth defines the behaviour of an authentication mechanism.
|
||||
type Auth interface {
|
||||
// Return the name of the mechnism, the argument to the first AUTH command
|
||||
// Return the name of the mechanism, the argument to the first AUTH command
|
||||
// and the next status.
|
||||
FirstData() (name, resp []byte, status AuthStatus)
|
||||
|
||||
|
9
src/runtime/vendor/github.com/godbus/dbus/v5/call.go
generated
vendored
9
src/runtime/vendor/github.com/godbus/dbus/v5/call.go
generated
vendored
@ -24,6 +24,15 @@ type Call struct {
|
||||
// Holds the response once the call is done.
|
||||
Body []interface{}
|
||||
|
||||
// ResponseSequence stores the sequence number of the DBus message containing
|
||||
// the call response (or error). This can be compared to the sequence number
|
||||
// of other call responses and signals on this connection to determine their
|
||||
// relative ordering on the underlying DBus connection.
|
||||
// For errors, ResponseSequence is populated only if the error came from a
|
||||
// DBusMessage that was received or if there was an error receiving. In case of
|
||||
// failure to make the call, ResponseSequence will be NoSequence.
|
||||
ResponseSequence Sequence
|
||||
|
||||
// tracks context and canceler
|
||||
ctx context.Context
|
||||
ctxCanceler context.CancelFunc
|
||||
|
159
src/runtime/vendor/github.com/godbus/dbus/v5/conn.go
generated
vendored
159
src/runtime/vendor/github.com/godbus/dbus/v5/conn.go
generated
vendored
@ -45,6 +45,7 @@ type Conn struct {
|
||||
serialGen SerialGenerator
|
||||
inInt Interceptor
|
||||
outInt Interceptor
|
||||
auth []Auth
|
||||
|
||||
names *nameTracker
|
||||
calls *callTracker
|
||||
@ -59,7 +60,8 @@ type Conn struct {
|
||||
func SessionBus() (conn *Conn, err error) {
|
||||
sessionBusLck.Lock()
|
||||
defer sessionBusLck.Unlock()
|
||||
if sessionBus != nil {
|
||||
if sessionBus != nil &&
|
||||
sessionBus.Connected() {
|
||||
return sessionBus, nil
|
||||
}
|
||||
defer func() {
|
||||
@ -67,19 +69,7 @@ func SessionBus() (conn *Conn, err error) {
|
||||
sessionBus = conn
|
||||
}
|
||||
}()
|
||||
conn, err = SessionBusPrivate()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if err = conn.Auth(nil); err != nil {
|
||||
conn.Close()
|
||||
conn = nil
|
||||
return
|
||||
}
|
||||
if err = conn.Hello(); err != nil {
|
||||
conn.Close()
|
||||
conn = nil
|
||||
}
|
||||
conn, err = ConnectSessionBus()
|
||||
return
|
||||
}
|
||||
|
||||
@ -116,7 +106,8 @@ func SessionBusPrivateHandler(handler Handler, signalHandler SignalHandler) (*Co
|
||||
func SystemBus() (conn *Conn, err error) {
|
||||
systemBusLck.Lock()
|
||||
defer systemBusLck.Unlock()
|
||||
if systemBus != nil {
|
||||
if systemBus != nil &&
|
||||
systemBus.Connected() {
|
||||
return systemBus, nil
|
||||
}
|
||||
defer func() {
|
||||
@ -124,20 +115,42 @@ func SystemBus() (conn *Conn, err error) {
|
||||
systemBus = conn
|
||||
}
|
||||
}()
|
||||
conn, err = SystemBusPrivate()
|
||||
conn, err = ConnectSystemBus()
|
||||
return
|
||||
}
|
||||
|
||||
// ConnectSessionBus connects to the session bus.
|
||||
func ConnectSessionBus(opts ...ConnOption) (*Conn, error) {
|
||||
address, err := getSessionBusAddress()
|
||||
if err != nil {
|
||||
return
|
||||
return nil, err
|
||||
}
|
||||
if err = conn.Auth(nil); err != nil {
|
||||
conn.Close()
|
||||
conn = nil
|
||||
return
|
||||
return Connect(address, opts...)
|
||||
}
|
||||
|
||||
// ConnectSystemBus connects to the system bus.
|
||||
func ConnectSystemBus(opts ...ConnOption) (*Conn, error) {
|
||||
return Connect(getSystemBusPlatformAddress(), opts...)
|
||||
}
|
||||
|
||||
// Connect connects to the given address.
|
||||
//
|
||||
// Returned connection is ready to use and doesn't require calling
|
||||
// Auth and Hello methods to make it usable.
|
||||
func Connect(address string, opts ...ConnOption) (*Conn, error) {
|
||||
conn, err := Dial(address, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err = conn.Auth(conn.auth); err != nil {
|
||||
_ = conn.Close()
|
||||
return nil, err
|
||||
}
|
||||
if err = conn.Hello(); err != nil {
|
||||
conn.Close()
|
||||
conn = nil
|
||||
_ = conn.Close()
|
||||
return nil, err
|
||||
}
|
||||
return
|
||||
return conn, nil
|
||||
}
|
||||
|
||||
// SystemBusPrivate returns a new private connection to the system bus.
|
||||
@ -197,6 +210,14 @@ func WithSerialGenerator(gen SerialGenerator) ConnOption {
|
||||
}
|
||||
}
|
||||
|
||||
// WithAuth sets authentication methods for the auth conversation.
|
||||
func WithAuth(methods ...Auth) ConnOption {
|
||||
return func(conn *Conn) error {
|
||||
conn.auth = methods
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// Interceptor intercepts incoming and outgoing messages.
|
||||
type Interceptor func(msg *Message)
|
||||
|
||||
@ -309,6 +330,11 @@ func (conn *Conn) Context() context.Context {
|
||||
return conn.ctx
|
||||
}
|
||||
|
||||
// Connected returns whether conn is connected
|
||||
func (conn *Conn) Connected() bool {
|
||||
return conn.ctx.Err() == nil
|
||||
}
|
||||
|
||||
// Eavesdrop causes conn to send all incoming messages to the given channel
|
||||
// without further processing. Method replies, errors and signals will not be
|
||||
// sent to the appropriate channels and method calls will not be handled. If nil
|
||||
@ -342,8 +368,9 @@ func (conn *Conn) Hello() error {
|
||||
}
|
||||
|
||||
// inWorker runs in an own goroutine, reading incoming messages from the
|
||||
// transport and dispatching them appropiately.
|
||||
// transport and dispatching them appropriately.
|
||||
func (conn *Conn) inWorker() {
|
||||
sequenceGen := newSequenceGenerator()
|
||||
for {
|
||||
msg, err := conn.ReadMessage()
|
||||
if err != nil {
|
||||
@ -352,7 +379,7 @@ func (conn *Conn) inWorker() {
|
||||
// anything but to shut down all stuff and returns errors to all
|
||||
// pending replies.
|
||||
conn.Close()
|
||||
conn.calls.finalizeAllWithError(err)
|
||||
conn.calls.finalizeAllWithError(sequenceGen, err)
|
||||
return
|
||||
}
|
||||
// invalid messages are ignored
|
||||
@ -381,13 +408,14 @@ func (conn *Conn) inWorker() {
|
||||
if conn.inInt != nil {
|
||||
conn.inInt(msg)
|
||||
}
|
||||
sequence := sequenceGen.next()
|
||||
switch msg.Type {
|
||||
case TypeError:
|
||||
conn.serialGen.RetireSerial(conn.calls.handleDBusError(msg))
|
||||
conn.serialGen.RetireSerial(conn.calls.handleDBusError(sequence, msg))
|
||||
case TypeMethodReply:
|
||||
conn.serialGen.RetireSerial(conn.calls.handleReply(msg))
|
||||
conn.serialGen.RetireSerial(conn.calls.handleReply(sequence, msg))
|
||||
case TypeSignal:
|
||||
conn.handleSignal(msg)
|
||||
conn.handleSignal(sequence, msg)
|
||||
case TypeMethodCall:
|
||||
go conn.handleCall(msg)
|
||||
}
|
||||
@ -395,7 +423,7 @@ func (conn *Conn) inWorker() {
|
||||
}
|
||||
}
|
||||
|
||||
func (conn *Conn) handleSignal(msg *Message) {
|
||||
func (conn *Conn) handleSignal(sequence Sequence, msg *Message) {
|
||||
iface := msg.Headers[FieldInterface].value.(string)
|
||||
member := msg.Headers[FieldMember].value.(string)
|
||||
// as per http://dbus.freedesktop.org/doc/dbus-specification.html ,
|
||||
@ -421,10 +449,11 @@ func (conn *Conn) handleSignal(msg *Message) {
|
||||
}
|
||||
}
|
||||
signal := &Signal{
|
||||
Sender: sender,
|
||||
Path: msg.Headers[FieldPath].value.(ObjectPath),
|
||||
Name: iface + "." + member,
|
||||
Body: msg.Body,
|
||||
Sender: sender,
|
||||
Path: msg.Headers[FieldPath].value.(ObjectPath),
|
||||
Name: iface + "." + member,
|
||||
Body: msg.Body,
|
||||
Sequence: sequence,
|
||||
}
|
||||
conn.signalHandler.DeliverSignal(iface, member, signal)
|
||||
}
|
||||
@ -442,6 +471,9 @@ func (conn *Conn) Object(dest string, path ObjectPath) BusObject {
|
||||
}
|
||||
|
||||
func (conn *Conn) sendMessageAndIfClosed(msg *Message, ifClosed func()) {
|
||||
if msg.serial == 0 {
|
||||
msg.serial = conn.getSerial()
|
||||
}
|
||||
if conn.outInt != nil {
|
||||
conn.outInt(msg)
|
||||
}
|
||||
@ -473,16 +505,16 @@ func (conn *Conn) send(ctx context.Context, msg *Message, ch chan *Call) *Call {
|
||||
if ctx == nil {
|
||||
panic("nil context")
|
||||
}
|
||||
if ch == nil {
|
||||
ch = make(chan *Call, 1)
|
||||
} else if cap(ch) == 0 {
|
||||
panic("dbus: unbuffered channel passed to (*Conn).Send")
|
||||
}
|
||||
|
||||
var call *Call
|
||||
ctx, canceler := context.WithCancel(ctx)
|
||||
msg.serial = conn.getSerial()
|
||||
if msg.Type == TypeMethodCall && msg.Flags&FlagNoReplyExpected == 0 {
|
||||
if ch == nil {
|
||||
ch = make(chan *Call, 5)
|
||||
} else if cap(ch) == 0 {
|
||||
panic("dbus: unbuffered channel passed to (*Conn).Send")
|
||||
}
|
||||
call = new(Call)
|
||||
call.Destination, _ = msg.Headers[FieldDestination].value.(string)
|
||||
call.Path, _ = msg.Headers[FieldPath].value.(ObjectPath)
|
||||
@ -504,7 +536,8 @@ func (conn *Conn) send(ctx context.Context, msg *Message, ch chan *Call) *Call {
|
||||
})
|
||||
} else {
|
||||
canceler()
|
||||
call = &Call{Err: nil}
|
||||
call = &Call{Err: nil, Done: ch}
|
||||
ch <- call
|
||||
conn.sendMessageAndIfClosed(msg, func() {
|
||||
call = &Call{Err: ErrClosed}
|
||||
})
|
||||
@ -529,7 +562,6 @@ func (conn *Conn) sendError(err error, dest string, serial uint32) {
|
||||
}
|
||||
msg := new(Message)
|
||||
msg.Type = TypeError
|
||||
msg.serial = conn.getSerial()
|
||||
msg.Headers = make(map[HeaderField]Variant)
|
||||
if dest != "" {
|
||||
msg.Headers[FieldDestination] = MakeVariant(dest)
|
||||
@ -548,7 +580,6 @@ func (conn *Conn) sendError(err error, dest string, serial uint32) {
|
||||
func (conn *Conn) sendReply(dest string, serial uint32, values ...interface{}) {
|
||||
msg := new(Message)
|
||||
msg.Type = TypeMethodReply
|
||||
msg.serial = conn.getSerial()
|
||||
msg.Headers = make(map[HeaderField]Variant)
|
||||
if dest != "" {
|
||||
msg.Headers[FieldDestination] = MakeVariant(dest)
|
||||
@ -564,8 +595,14 @@ func (conn *Conn) sendReply(dest string, serial uint32, values ...interface{}) {
|
||||
// AddMatchSignal registers the given match rule to receive broadcast
|
||||
// signals based on their contents.
|
||||
func (conn *Conn) AddMatchSignal(options ...MatchOption) error {
|
||||
return conn.AddMatchSignalContext(context.Background(), options...)
|
||||
}
|
||||
|
||||
// AddMatchSignalContext acts like AddMatchSignal but takes a context.
|
||||
func (conn *Conn) AddMatchSignalContext(ctx context.Context, options ...MatchOption) error {
|
||||
options = append([]MatchOption{withMatchType("signal")}, options...)
|
||||
return conn.busObj.Call(
|
||||
return conn.busObj.CallWithContext(
|
||||
ctx,
|
||||
"org.freedesktop.DBus.AddMatch", 0,
|
||||
formatMatchOptions(options),
|
||||
).Store()
|
||||
@ -573,8 +610,14 @@ func (conn *Conn) AddMatchSignal(options ...MatchOption) error {
|
||||
|
||||
// RemoveMatchSignal removes the first rule that matches previously registered with AddMatchSignal.
|
||||
func (conn *Conn) RemoveMatchSignal(options ...MatchOption) error {
|
||||
return conn.RemoveMatchSignalContext(context.Background(), options...)
|
||||
}
|
||||
|
||||
// RemoveMatchSignalContext acts like RemoveMatchSignal but takes a context.
|
||||
func (conn *Conn) RemoveMatchSignalContext(ctx context.Context, options ...MatchOption) error {
|
||||
options = append([]MatchOption{withMatchType("signal")}, options...)
|
||||
return conn.busObj.Call(
|
||||
return conn.busObj.CallWithContext(
|
||||
ctx,
|
||||
"org.freedesktop.DBus.RemoveMatch", 0,
|
||||
formatMatchOptions(options),
|
||||
).Store()
|
||||
@ -639,10 +682,11 @@ func (e Error) Error() string {
|
||||
// Signal represents a D-Bus message of type Signal. The name member is given in
|
||||
// "interface.member" notation, e.g. org.freedesktop.D-Bus.NameLost.
|
||||
type Signal struct {
|
||||
Sender string
|
||||
Path ObjectPath
|
||||
Name string
|
||||
Body []interface{}
|
||||
Sender string
|
||||
Path ObjectPath
|
||||
Name string
|
||||
Body []interface{}
|
||||
Sequence Sequence
|
||||
}
|
||||
|
||||
// transport is a D-Bus transport.
|
||||
@ -825,25 +869,25 @@ func (tracker *callTracker) track(sn uint32, call *Call) {
|
||||
tracker.lck.Unlock()
|
||||
}
|
||||
|
||||
func (tracker *callTracker) handleReply(msg *Message) uint32 {
|
||||
func (tracker *callTracker) handleReply(sequence Sequence, msg *Message) uint32 {
|
||||
serial := msg.Headers[FieldReplySerial].value.(uint32)
|
||||
tracker.lck.RLock()
|
||||
_, ok := tracker.calls[serial]
|
||||
tracker.lck.RUnlock()
|
||||
if ok {
|
||||
tracker.finalizeWithBody(serial, msg.Body)
|
||||
tracker.finalizeWithBody(serial, sequence, msg.Body)
|
||||
}
|
||||
return serial
|
||||
}
|
||||
|
||||
func (tracker *callTracker) handleDBusError(msg *Message) uint32 {
|
||||
func (tracker *callTracker) handleDBusError(sequence Sequence, msg *Message) uint32 {
|
||||
serial := msg.Headers[FieldReplySerial].value.(uint32)
|
||||
tracker.lck.RLock()
|
||||
_, ok := tracker.calls[serial]
|
||||
tracker.lck.RUnlock()
|
||||
if ok {
|
||||
name, _ := msg.Headers[FieldErrorName].value.(string)
|
||||
tracker.finalizeWithError(serial, Error{name, msg.Body})
|
||||
tracker.finalizeWithError(serial, sequence, Error{name, msg.Body})
|
||||
}
|
||||
return serial
|
||||
}
|
||||
@ -856,7 +900,7 @@ func (tracker *callTracker) handleSendError(msg *Message, err error) {
|
||||
_, ok := tracker.calls[msg.serial]
|
||||
tracker.lck.RUnlock()
|
||||
if ok {
|
||||
tracker.finalizeWithError(msg.serial, err)
|
||||
tracker.finalizeWithError(msg.serial, NoSequence, err)
|
||||
}
|
||||
}
|
||||
|
||||
@ -871,7 +915,7 @@ func (tracker *callTracker) finalize(sn uint32) {
|
||||
}
|
||||
}
|
||||
|
||||
func (tracker *callTracker) finalizeWithBody(sn uint32, body []interface{}) {
|
||||
func (tracker *callTracker) finalizeWithBody(sn uint32, sequence Sequence, body []interface{}) {
|
||||
tracker.lck.Lock()
|
||||
c, ok := tracker.calls[sn]
|
||||
if ok {
|
||||
@ -880,11 +924,12 @@ func (tracker *callTracker) finalizeWithBody(sn uint32, body []interface{}) {
|
||||
tracker.lck.Unlock()
|
||||
if ok {
|
||||
c.Body = body
|
||||
c.ResponseSequence = sequence
|
||||
c.done()
|
||||
}
|
||||
}
|
||||
|
||||
func (tracker *callTracker) finalizeWithError(sn uint32, err error) {
|
||||
func (tracker *callTracker) finalizeWithError(sn uint32, sequence Sequence, err error) {
|
||||
tracker.lck.Lock()
|
||||
c, ok := tracker.calls[sn]
|
||||
if ok {
|
||||
@ -893,11 +938,12 @@ func (tracker *callTracker) finalizeWithError(sn uint32, err error) {
|
||||
tracker.lck.Unlock()
|
||||
if ok {
|
||||
c.Err = err
|
||||
c.ResponseSequence = sequence
|
||||
c.done()
|
||||
}
|
||||
}
|
||||
|
||||
func (tracker *callTracker) finalizeAllWithError(err error) {
|
||||
func (tracker *callTracker) finalizeAllWithError(sequenceGen *sequenceGenerator, err error) {
|
||||
tracker.lck.Lock()
|
||||
closedCalls := make([]*Call, 0, len(tracker.calls))
|
||||
for sn := range tracker.calls {
|
||||
@ -907,6 +953,7 @@ func (tracker *callTracker) finalizeAllWithError(err error) {
|
||||
tracker.lck.Unlock()
|
||||
for _, call := range closedCalls {
|
||||
call.Err = err
|
||||
call.ResponseSequence = sequenceGen.next()
|
||||
call.done()
|
||||
}
|
||||
}
|
||||
|
4
src/runtime/vendor/github.com/godbus/dbus/v5/dbus.go
generated
vendored
4
src/runtime/vendor/github.com/godbus/dbus/v5/dbus.go
generated
vendored
@ -28,6 +28,7 @@ var (
|
||||
interfaceType = reflect.TypeOf((*interface{})(nil)).Elem()
|
||||
unixFDType = reflect.TypeOf(UnixFD(0))
|
||||
unixFDIndexType = reflect.TypeOf(UnixFDIndex(0))
|
||||
errType = reflect.TypeOf((*error)(nil)).Elem()
|
||||
)
|
||||
|
||||
// An InvalidTypeError signals that a value which cannot be represented in the
|
||||
@ -63,6 +64,9 @@ func storeInterfaces(src, dest interface{}) error {
|
||||
|
||||
func store(dest, src reflect.Value) error {
|
||||
if dest.Kind() == reflect.Ptr {
|
||||
if dest.IsNil() {
|
||||
dest.Set(reflect.New(dest.Type().Elem()))
|
||||
}
|
||||
return store(dest.Elem(), src)
|
||||
}
|
||||
switch src.Kind() {
|
||||
|
22
src/runtime/vendor/github.com/godbus/dbus/v5/default_handler.go
generated
vendored
22
src/runtime/vendor/github.com/godbus/dbus/v5/default_handler.go
generated
vendored
@ -126,14 +126,28 @@ func (m exportedMethod) Call(args ...interface{}) ([]interface{}, error) {
|
||||
}
|
||||
|
||||
ret := m.Value.Call(params)
|
||||
|
||||
err := ret[t.NumOut()-1].Interface().(*Error)
|
||||
ret = ret[:t.NumOut()-1]
|
||||
var err error
|
||||
nilErr := false // The reflection will find almost-nils, let's only pass back clean ones!
|
||||
if t.NumOut() > 0 {
|
||||
if e, ok := ret[t.NumOut()-1].Interface().(*Error); ok { // godbus *Error
|
||||
nilErr = ret[t.NumOut()-1].IsNil()
|
||||
ret = ret[:t.NumOut()-1]
|
||||
err = e
|
||||
} else if ret[t.NumOut()-1].Type().Implements(errType) { // Go error
|
||||
i := ret[t.NumOut()-1].Interface()
|
||||
if i == nil {
|
||||
nilErr = ret[t.NumOut()-1].IsNil()
|
||||
} else {
|
||||
err = i.(error)
|
||||
}
|
||||
ret = ret[:t.NumOut()-1]
|
||||
}
|
||||
}
|
||||
out := make([]interface{}, len(ret))
|
||||
for i, val := range ret {
|
||||
out[i] = val.Interface()
|
||||
}
|
||||
if err == nil {
|
||||
if nilErr || err == nil {
|
||||
//concrete type to interface nil is a special case
|
||||
return out, nil
|
||||
}
|
||||
|
61
src/runtime/vendor/github.com/godbus/dbus/v5/export.go
generated
vendored
61
src/runtime/vendor/github.com/godbus/dbus/v5/export.go
generated
vendored
@ -69,6 +69,22 @@ func getMethods(in interface{}, mapping map[string]string) map[string]reflect.Va
|
||||
return methods
|
||||
}
|
||||
|
||||
func getAllMethods(in interface{}, mapping map[string]string) map[string]reflect.Value {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
methods := make(map[string]reflect.Value)
|
||||
val := reflect.ValueOf(in)
|
||||
typ := val.Type()
|
||||
for i := 0; i < typ.NumMethod(); i++ {
|
||||
methtype := typ.Method(i)
|
||||
method := val.Method(i)
|
||||
// map names while building table
|
||||
methods[computeMethodName(methtype.Name, mapping)] = method
|
||||
}
|
||||
return methods
|
||||
}
|
||||
|
||||
func standardMethodArgumentDecode(m Method, sender string, msg *Message, body []interface{}) ([]interface{}, error) {
|
||||
pointers := make([]interface{}, m.NumArguments())
|
||||
decode := make([]interface{}, 0, len(body))
|
||||
@ -159,7 +175,6 @@ func (conn *Conn) handleCall(msg *Message) {
|
||||
if msg.Flags&FlagNoReplyExpected == 0 {
|
||||
reply := new(Message)
|
||||
reply.Type = TypeMethodReply
|
||||
reply.serial = conn.getSerial()
|
||||
reply.Headers = make(map[HeaderField]Variant)
|
||||
if hasSender {
|
||||
reply.Headers[FieldDestination] = msg.Headers[FieldSender]
|
||||
@ -195,7 +210,6 @@ func (conn *Conn) Emit(path ObjectPath, name string, values ...interface{}) erro
|
||||
}
|
||||
msg := new(Message)
|
||||
msg.Type = TypeSignal
|
||||
msg.serial = conn.getSerial()
|
||||
msg.Headers = make(map[HeaderField]Variant)
|
||||
msg.Headers[FieldInterface] = MakeVariant(iface)
|
||||
msg.Headers[FieldMember] = MakeVariant(member)
|
||||
@ -247,6 +261,18 @@ func (conn *Conn) Export(v interface{}, path ObjectPath, iface string) error {
|
||||
return conn.ExportWithMap(v, nil, path, iface)
|
||||
}
|
||||
|
||||
// ExportAll registers all exported methods defined by the given object on
|
||||
// the message bus.
|
||||
//
|
||||
// Unlike Export there is no requirement to have the last parameter as type
|
||||
// *Error. If you want to be able to return error then you can append an error
|
||||
// type parameter to your method signature. If the error returned is not nil,
|
||||
// it is sent back to the caller as an error. Otherwise, a method reply is
|
||||
// sent with the other return values as its body.
|
||||
func (conn *Conn) ExportAll(v interface{}, path ObjectPath, iface string) error {
|
||||
return conn.export(getAllMethods(v, nil), path, iface, false)
|
||||
}
|
||||
|
||||
// ExportWithMap works exactly like Export but provides the ability to remap
|
||||
// method names (e.g. export a lower-case method).
|
||||
//
|
||||
@ -299,19 +325,22 @@ func (conn *Conn) ExportSubtreeMethodTable(methods map[string]interface{}, path
|
||||
}
|
||||
|
||||
func (conn *Conn) exportMethodTable(methods map[string]interface{}, path ObjectPath, iface string, includeSubtree bool) error {
|
||||
out := make(map[string]reflect.Value)
|
||||
for name, method := range methods {
|
||||
rval := reflect.ValueOf(method)
|
||||
if rval.Kind() != reflect.Func {
|
||||
continue
|
||||
var out map[string]reflect.Value
|
||||
if methods != nil {
|
||||
out = make(map[string]reflect.Value)
|
||||
for name, method := range methods {
|
||||
rval := reflect.ValueOf(method)
|
||||
if rval.Kind() != reflect.Func {
|
||||
continue
|
||||
}
|
||||
t := rval.Type()
|
||||
// only track valid methods must return *Error as last arg
|
||||
if t.NumOut() == 0 ||
|
||||
t.Out(t.NumOut()-1) != reflect.TypeOf(&ErrMsgInvalidArg) {
|
||||
continue
|
||||
}
|
||||
out[name] = rval
|
||||
}
|
||||
t := rval.Type()
|
||||
// only track valid methods must return *Error as last arg
|
||||
if t.NumOut() == 0 ||
|
||||
t.Out(t.NumOut()-1) != reflect.TypeOf(&ErrMsgInvalidArg) {
|
||||
continue
|
||||
}
|
||||
out[name] = rval
|
||||
}
|
||||
return conn.export(out, path, iface, includeSubtree)
|
||||
}
|
||||
@ -327,12 +356,12 @@ func (conn *Conn) unexport(h *defaultHandler, path ObjectPath, iface string) err
|
||||
return nil
|
||||
}
|
||||
|
||||
// exportWithMap is the worker function for all exports/registrations.
|
||||
// export is the worker function for all exports/registrations.
|
||||
func (conn *Conn) export(methods map[string]reflect.Value, path ObjectPath, iface string, includeSubtree bool) error {
|
||||
h, ok := conn.handler.(*defaultHandler)
|
||||
if !ok {
|
||||
return fmt.Errorf(
|
||||
`dbus: export only allowed on the default hander handler have %T"`,
|
||||
`dbus: export only allowed on the default handler. Received: %T"`,
|
||||
conn.handler)
|
||||
}
|
||||
|
||||
|
27
src/runtime/vendor/github.com/godbus/dbus/v5/match.go
generated
vendored
27
src/runtime/vendor/github.com/godbus/dbus/v5/match.go
generated
vendored
@ -1,6 +1,7 @@
|
||||
package dbus
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
@ -60,3 +61,29 @@ func WithMatchPathNamespace(namespace ObjectPath) MatchOption {
|
||||
func WithMatchDestination(destination string) MatchOption {
|
||||
return WithMatchOption("destination", destination)
|
||||
}
|
||||
|
||||
// WithMatchArg sets argN match option, range of N is 0 to 63.
|
||||
func WithMatchArg(argIdx int, value string) MatchOption {
|
||||
if argIdx < 0 || argIdx > 63 {
|
||||
panic("range of argument index is 0 to 63")
|
||||
}
|
||||
return WithMatchOption("arg"+strconv.Itoa(argIdx), value)
|
||||
}
|
||||
|
||||
// WithMatchArgPath sets argN path match option, range of N is 0 to 63.
|
||||
func WithMatchArgPath(argIdx int, path string) MatchOption {
|
||||
if argIdx < 0 || argIdx > 63 {
|
||||
panic("range of argument index is 0 to 63")
|
||||
}
|
||||
return WithMatchOption("arg"+strconv.Itoa(argIdx)+"path", path)
|
||||
}
|
||||
|
||||
// WithMatchArg0Namespace sets arg0namespace match option.
|
||||
func WithMatchArg0Namespace(arg0Namespace string) MatchOption {
|
||||
return WithMatchOption("arg0namespace", arg0Namespace)
|
||||
}
|
||||
|
||||
// WithMatchEavesdrop sets eavesdrop match option.
|
||||
func WithMatchEavesdrop(eavesdrop bool) MatchOption {
|
||||
return WithMatchOption("eavesdrop", strconv.FormatBool(eavesdrop))
|
||||
}
|
||||
|
65
src/runtime/vendor/github.com/godbus/dbus/v5/object.go
generated
vendored
65
src/runtime/vendor/github.com/godbus/dbus/v5/object.go
generated
vendored
@ -16,6 +16,7 @@ type BusObject interface {
|
||||
AddMatchSignal(iface, member string, options ...MatchOption) *Call
|
||||
RemoveMatchSignal(iface, member string, options ...MatchOption) *Call
|
||||
GetProperty(p string) (Variant, error)
|
||||
StoreProperty(p string, value interface{}) error
|
||||
SetProperty(p string, v interface{}) error
|
||||
Destination() string
|
||||
Path() ObjectPath
|
||||
@ -109,7 +110,6 @@ func (o *Object) createCall(ctx context.Context, method string, flags Flags, ch
|
||||
method = method[i+1:]
|
||||
msg := new(Message)
|
||||
msg.Type = TypeMethodCall
|
||||
msg.serial = o.conn.getSerial()
|
||||
msg.Flags = flags & (FlagNoAutoStart | FlagNoReplyExpected)
|
||||
msg.Headers = make(map[HeaderField]Variant)
|
||||
msg.Headers[FieldPath] = MakeVariant(o.path)
|
||||
@ -122,68 +122,31 @@ func (o *Object) createCall(ctx context.Context, method string, flags Flags, ch
|
||||
if len(args) > 0 {
|
||||
msg.Headers[FieldSignature] = MakeVariant(SignatureOf(args...))
|
||||
}
|
||||
if msg.Flags&FlagNoReplyExpected == 0 {
|
||||
if ch == nil {
|
||||
ch = make(chan *Call, 1)
|
||||
} else if cap(ch) == 0 {
|
||||
panic("dbus: unbuffered channel passed to (*Object).Go")
|
||||
}
|
||||
ctx, cancel := context.WithCancel(ctx)
|
||||
call := &Call{
|
||||
Destination: o.dest,
|
||||
Path: o.path,
|
||||
Method: method,
|
||||
Args: args,
|
||||
Done: ch,
|
||||
ctxCanceler: cancel,
|
||||
ctx: ctx,
|
||||
}
|
||||
o.conn.calls.track(msg.serial, call)
|
||||
o.conn.sendMessageAndIfClosed(msg, func() {
|
||||
o.conn.calls.handleSendError(msg, ErrClosed)
|
||||
cancel()
|
||||
})
|
||||
go func() {
|
||||
<-ctx.Done()
|
||||
o.conn.calls.handleSendError(msg, ctx.Err())
|
||||
}()
|
||||
|
||||
return call
|
||||
}
|
||||
done := make(chan *Call, 1)
|
||||
call := &Call{
|
||||
Err: nil,
|
||||
Done: done,
|
||||
}
|
||||
defer func() {
|
||||
call.Done <- call
|
||||
close(done)
|
||||
}()
|
||||
o.conn.sendMessageAndIfClosed(msg, func() {
|
||||
call.Err = ErrClosed
|
||||
})
|
||||
return call
|
||||
return o.conn.SendWithContext(ctx, msg, ch)
|
||||
}
|
||||
|
||||
// GetProperty calls org.freedesktop.DBus.Properties.Get on the given
|
||||
// object. The property name must be given in interface.member notation.
|
||||
func (o *Object) GetProperty(p string) (Variant, error) {
|
||||
var result Variant
|
||||
err := o.StoreProperty(p, &result)
|
||||
return result, err
|
||||
}
|
||||
|
||||
// StoreProperty calls org.freedesktop.DBus.Properties.Get on the given
|
||||
// object. The property name must be given in interface.member notation.
|
||||
// It stores the returned property into the provided value.
|
||||
func (o *Object) StoreProperty(p string, value interface{}) error {
|
||||
idx := strings.LastIndex(p, ".")
|
||||
if idx == -1 || idx+1 == len(p) {
|
||||
return Variant{}, errors.New("dbus: invalid property " + p)
|
||||
return errors.New("dbus: invalid property " + p)
|
||||
}
|
||||
|
||||
iface := p[:idx]
|
||||
prop := p[idx+1:]
|
||||
|
||||
result := Variant{}
|
||||
err := o.Call("org.freedesktop.DBus.Properties.Get", 0, iface, prop).Store(&result)
|
||||
|
||||
if err != nil {
|
||||
return Variant{}, err
|
||||
}
|
||||
|
||||
return result, nil
|
||||
return o.Call("org.freedesktop.DBus.Properties.Get", 0, iface, prop).
|
||||
Store(value)
|
||||
}
|
||||
|
||||
// SetProperty calls org.freedesktop.DBus.Properties.Set on the given
|
||||
|
24
src/runtime/vendor/github.com/godbus/dbus/v5/sequence.go
generated
vendored
Normal file
24
src/runtime/vendor/github.com/godbus/dbus/v5/sequence.go
generated
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
package dbus
|
||||
|
||||
// Sequence represents the value of a monotonically increasing counter.
|
||||
type Sequence uint64
|
||||
|
||||
const (
|
||||
// NoSequence indicates the absence of a sequence value.
|
||||
NoSequence Sequence = 0
|
||||
)
|
||||
|
||||
// sequenceGenerator represents a monotonically increasing counter.
|
||||
type sequenceGenerator struct {
|
||||
nextSequence Sequence
|
||||
}
|
||||
|
||||
func (generator *sequenceGenerator) next() Sequence {
|
||||
result := generator.nextSequence
|
||||
generator.nextSequence++
|
||||
return result
|
||||
}
|
||||
|
||||
func newSequenceGenerator() *sequenceGenerator {
|
||||
return &sequenceGenerator{nextSequence: 1}
|
||||
}
|
125
src/runtime/vendor/github.com/godbus/dbus/v5/sequential_handler.go
generated
vendored
Normal file
125
src/runtime/vendor/github.com/godbus/dbus/v5/sequential_handler.go
generated
vendored
Normal file
@ -0,0 +1,125 @@
|
||||
package dbus
|
||||
|
||||
import (
|
||||
"sync"
|
||||
)
|
||||
|
||||
// NewSequentialSignalHandler returns an instance of a new
|
||||
// signal handler that guarantees sequential processing of signals. It is a
|
||||
// guarantee of this signal handler that signals will be written to
|
||||
// channels in the order they are received on the DBus connection.
|
||||
func NewSequentialSignalHandler() SignalHandler {
|
||||
return &sequentialSignalHandler{}
|
||||
}
|
||||
|
||||
type sequentialSignalHandler struct {
|
||||
mu sync.RWMutex
|
||||
closed bool
|
||||
signals []*sequentialSignalChannelData
|
||||
}
|
||||
|
||||
func (sh *sequentialSignalHandler) DeliverSignal(intf, name string, signal *Signal) {
|
||||
sh.mu.RLock()
|
||||
defer sh.mu.RUnlock()
|
||||
if sh.closed {
|
||||
return
|
||||
}
|
||||
for _, scd := range sh.signals {
|
||||
scd.deliver(signal)
|
||||
}
|
||||
}
|
||||
|
||||
func (sh *sequentialSignalHandler) Terminate() {
|
||||
sh.mu.Lock()
|
||||
defer sh.mu.Unlock()
|
||||
if sh.closed {
|
||||
return
|
||||
}
|
||||
|
||||
for _, scd := range sh.signals {
|
||||
scd.close()
|
||||
close(scd.ch)
|
||||
}
|
||||
sh.closed = true
|
||||
sh.signals = nil
|
||||
}
|
||||
|
||||
func (sh *sequentialSignalHandler) AddSignal(ch chan<- *Signal) {
|
||||
sh.mu.Lock()
|
||||
defer sh.mu.Unlock()
|
||||
if sh.closed {
|
||||
return
|
||||
}
|
||||
sh.signals = append(sh.signals, newSequentialSignalChannelData(ch))
|
||||
}
|
||||
|
||||
func (sh *sequentialSignalHandler) RemoveSignal(ch chan<- *Signal) {
|
||||
sh.mu.Lock()
|
||||
defer sh.mu.Unlock()
|
||||
if sh.closed {
|
||||
return
|
||||
}
|
||||
for i := len(sh.signals) - 1; i >= 0; i-- {
|
||||
if ch == sh.signals[i].ch {
|
||||
sh.signals[i].close()
|
||||
copy(sh.signals[i:], sh.signals[i+1:])
|
||||
sh.signals[len(sh.signals)-1] = nil
|
||||
sh.signals = sh.signals[:len(sh.signals)-1]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type sequentialSignalChannelData struct {
|
||||
ch chan<- *Signal
|
||||
in chan *Signal
|
||||
done chan struct{}
|
||||
}
|
||||
|
||||
func newSequentialSignalChannelData(ch chan<- *Signal) *sequentialSignalChannelData {
|
||||
scd := &sequentialSignalChannelData{
|
||||
ch: ch,
|
||||
in: make(chan *Signal),
|
||||
done: make(chan struct{}),
|
||||
}
|
||||
go scd.bufferSignals()
|
||||
return scd
|
||||
}
|
||||
|
||||
func (scd *sequentialSignalChannelData) bufferSignals() {
|
||||
defer close(scd.done)
|
||||
|
||||
// Ensure that signals are delivered to scd.ch in the same
|
||||
// order they are received from scd.in.
|
||||
var queue []*Signal
|
||||
for {
|
||||
if len(queue) == 0 {
|
||||
signal, ok := <- scd.in
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
queue = append(queue, signal)
|
||||
}
|
||||
select {
|
||||
case scd.ch <- queue[0]:
|
||||
copy(queue, queue[1:])
|
||||
queue[len(queue)-1] = nil
|
||||
queue = queue[:len(queue)-1]
|
||||
case signal, ok := <-scd.in:
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
queue = append(queue, signal)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (scd *sequentialSignalChannelData) deliver(signal *Signal) {
|
||||
scd.in <- signal
|
||||
}
|
||||
|
||||
func (scd *sequentialSignalChannelData) close() {
|
||||
close(scd.in)
|
||||
// Ensure that bufferSignals() has exited and won't attempt
|
||||
// any future sends on scd.ch
|
||||
<-scd.done
|
||||
}
|
2
src/runtime/vendor/github.com/godbus/dbus/v5/sig.go
generated
vendored
2
src/runtime/vendor/github.com/godbus/dbus/v5/sig.go
generated
vendored
@ -137,7 +137,7 @@ func ParseSignatureMust(s string) Signature {
|
||||
return sig
|
||||
}
|
||||
|
||||
// Empty retruns whether the signature is the empty signature.
|
||||
// Empty returns whether the signature is the empty signature.
|
||||
func (s Signature) Empty() bool {
|
||||
return s.str == ""
|
||||
}
|
||||
|
1
src/runtime/vendor/github.com/godbus/dbus/v5/transport_unixcred_freebsd.go
generated
vendored
1
src/runtime/vendor/github.com/godbus/dbus/v5/transport_unixcred_freebsd.go
generated
vendored
@ -10,6 +10,7 @@ package dbus
|
||||
/*
|
||||
const int sizeofPtr = sizeof(void*);
|
||||
#define _WANT_UCRED
|
||||
#include <sys/types.h>
|
||||
#include <sys/ucred.h>
|
||||
*/
|
||||
import "C"
|
||||
|
6
src/runtime/vendor/github.com/godbus/dbus/v5/variant.go
generated
vendored
6
src/runtime/vendor/github.com/godbus/dbus/v5/variant.go
generated
vendored
@ -142,3 +142,9 @@ func (v Variant) String() string {
|
||||
func (v Variant) Value() interface{} {
|
||||
return v.value
|
||||
}
|
||||
|
||||
// Store converts the variant into a native go type using the same
|
||||
// mechanism as the "Store" function.
|
||||
func (v Variant) Store(value interface{}) error {
|
||||
return storeInterfaces(v.value, value)
|
||||
}
|
||||
|
10
src/runtime/vendor/github.com/golang/protobuf/proto/registry.go
generated
vendored
10
src/runtime/vendor/github.com/golang/protobuf/proto/registry.go
generated
vendored
@ -13,6 +13,7 @@ import (
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"google.golang.org/protobuf/reflect/protodesc"
|
||||
"google.golang.org/protobuf/reflect/protoreflect"
|
||||
"google.golang.org/protobuf/reflect/protoregistry"
|
||||
"google.golang.org/protobuf/runtime/protoimpl"
|
||||
@ -62,14 +63,7 @@ func FileDescriptor(s filePath) fileDescGZIP {
|
||||
// Find the descriptor in the v2 registry.
|
||||
var b []byte
|
||||
if fd, _ := protoregistry.GlobalFiles.FindFileByPath(s); fd != nil {
|
||||
if fd, ok := fd.(interface{ ProtoLegacyRawDesc() []byte }); ok {
|
||||
b = fd.ProtoLegacyRawDesc()
|
||||
} else {
|
||||
// TODO: Use protodesc.ToFileDescriptorProto to construct
|
||||
// a descriptorpb.FileDescriptorProto and marshal it.
|
||||
// However, doing so causes the proto package to have a dependency
|
||||
// on descriptorpb, leading to cyclic dependency issues.
|
||||
}
|
||||
b, _ = Marshal(protodesc.ToFileDescriptorProto(fd))
|
||||
}
|
||||
|
||||
// Locally cache the raw descriptor form for the file.
|
||||
|
14
src/runtime/vendor/github.com/golang/protobuf/ptypes/any.go
generated
vendored
14
src/runtime/vendor/github.com/golang/protobuf/ptypes/any.go
generated
vendored
@ -19,6 +19,8 @@ const urlPrefix = "type.googleapis.com/"
|
||||
|
||||
// AnyMessageName returns the message name contained in an anypb.Any message.
|
||||
// Most type assertions should use the Is function instead.
|
||||
//
|
||||
// Deprecated: Call the any.MessageName method instead.
|
||||
func AnyMessageName(any *anypb.Any) (string, error) {
|
||||
name, err := anyMessageName(any)
|
||||
return string(name), err
|
||||
@ -38,6 +40,8 @@ func anyMessageName(any *anypb.Any) (protoreflect.FullName, error) {
|
||||
}
|
||||
|
||||
// MarshalAny marshals the given message m into an anypb.Any message.
|
||||
//
|
||||
// Deprecated: Call the anypb.New function instead.
|
||||
func MarshalAny(m proto.Message) (*anypb.Any, error) {
|
||||
switch dm := m.(type) {
|
||||
case DynamicAny:
|
||||
@ -58,6 +62,9 @@ func MarshalAny(m proto.Message) (*anypb.Any, error) {
|
||||
// Empty returns a new message of the type specified in an anypb.Any message.
|
||||
// It returns protoregistry.NotFound if the corresponding message type could not
|
||||
// be resolved in the global registry.
|
||||
//
|
||||
// Deprecated: Use protoregistry.GlobalTypes.FindMessageByName instead
|
||||
// to resolve the message name and create a new instance of it.
|
||||
func Empty(any *anypb.Any) (proto.Message, error) {
|
||||
name, err := anyMessageName(any)
|
||||
if err != nil {
|
||||
@ -76,6 +83,8 @@ func Empty(any *anypb.Any) (proto.Message, error) {
|
||||
//
|
||||
// The target message m may be a *DynamicAny message. If the underlying message
|
||||
// type could not be resolved, then this returns protoregistry.NotFound.
|
||||
//
|
||||
// Deprecated: Call the any.UnmarshalTo method instead.
|
||||
func UnmarshalAny(any *anypb.Any, m proto.Message) error {
|
||||
if dm, ok := m.(*DynamicAny); ok {
|
||||
if dm.Message == nil {
|
||||
@ -100,6 +109,8 @@ func UnmarshalAny(any *anypb.Any, m proto.Message) error {
|
||||
}
|
||||
|
||||
// Is reports whether the Any message contains a message of the specified type.
|
||||
//
|
||||
// Deprecated: Call the any.MessageIs method instead.
|
||||
func Is(any *anypb.Any, m proto.Message) bool {
|
||||
if any == nil || m == nil {
|
||||
return false
|
||||
@ -119,6 +130,9 @@ func Is(any *anypb.Any, m proto.Message) bool {
|
||||
// var x ptypes.DynamicAny
|
||||
// if err := ptypes.UnmarshalAny(a, &x); err != nil { ... }
|
||||
// fmt.Printf("unmarshaled message: %v", x.Message)
|
||||
//
|
||||
// Deprecated: Use the any.UnmarshalNew method instead to unmarshal
|
||||
// the any message contents into a new instance of the underlying message.
|
||||
type DynamicAny struct{ proto.Message }
|
||||
|
||||
func (m DynamicAny) String() string {
|
||||
|
4
src/runtime/vendor/github.com/golang/protobuf/ptypes/doc.go
generated
vendored
4
src/runtime/vendor/github.com/golang/protobuf/ptypes/doc.go
generated
vendored
@ -3,4 +3,8 @@
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Package ptypes provides functionality for interacting with well-known types.
|
||||
//
|
||||
// Deprecated: Well-known types have specialized functionality directly
|
||||
// injected into the generated packages for each message type.
|
||||
// See the deprecation notice for each function for the suggested alternative.
|
||||
package ptypes
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user