Vendor vfkit v0.5.1 and gopsutil v3.24.1

Signed-off-by: Matt Heon <mheon@redhat.com>
This commit is contained in:
Matt Heon
2024-02-21 14:53:40 -05:00
parent 70091d57e7
commit 2af73b83fe
48 changed files with 1160 additions and 937 deletions

18
go.mod
View File

@ -23,7 +23,7 @@ require (
github.com/coreos/go-systemd/v22 v22.5.1-0.20231103132048-7d375ecc2b09 github.com/coreos/go-systemd/v22 v22.5.1-0.20231103132048-7d375ecc2b09
github.com/coreos/stream-metadata-go v0.4.4 github.com/coreos/stream-metadata-go v0.4.4
github.com/crc-org/crc/v2 v2.32.0 github.com/crc-org/crc/v2 v2.32.0
github.com/crc-org/vfkit v0.5.0 github.com/crc-org/vfkit v0.5.1
github.com/cyphar/filepath-securejoin v0.2.4 github.com/cyphar/filepath-securejoin v0.2.4
github.com/digitalocean/go-qemu v0.0.0-20230711162256-2e3d0186973e github.com/digitalocean/go-qemu v0.0.0-20230711162256-2e3d0186973e
github.com/docker/distribution v2.8.3+incompatible github.com/docker/distribution v2.8.3+incompatible
@ -59,7 +59,7 @@ require (
github.com/opencontainers/selinux v1.11.0 github.com/opencontainers/selinux v1.11.0
github.com/openshift/imagebuilder v1.2.6-0.20231127234745-ef2a5fe47510 github.com/openshift/imagebuilder v1.2.6-0.20231127234745-ef2a5fe47510
github.com/rootless-containers/rootlesskit v1.1.1 github.com/rootless-containers/rootlesskit v1.1.1
github.com/shirou/gopsutil/v3 v3.23.12 github.com/shirou/gopsutil/v3 v3.24.1
github.com/sirupsen/logrus v1.9.3 github.com/sirupsen/logrus v1.9.3
github.com/spf13/cobra v1.8.0 github.com/spf13/cobra v1.8.0
github.com/spf13/pflag v1.0.5 github.com/spf13/pflag v1.0.5
@ -92,9 +92,9 @@ require (
github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d // indirect github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d // indirect
github.com/aead/serpent v0.0.0-20160714141033-fba169763ea6 // indirect github.com/aead/serpent v0.0.0-20160714141033-fba169763ea6 // indirect
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect
github.com/bytedance/sonic v1.10.1 // indirect github.com/bytedance/sonic v1.10.2 // indirect
github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d // indirect github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d // indirect
github.com/chenzhuoyu/iasm v0.9.0 // indirect github.com/chenzhuoyu/iasm v0.9.1 // indirect
github.com/chzyer/readline v1.5.1 // indirect github.com/chzyer/readline v1.5.1 // indirect
github.com/containerd/cgroups/v3 v3.0.3 // indirect github.com/containerd/cgroups/v3 v3.0.3 // indirect
github.com/containerd/containerd v1.7.13 // indirect github.com/containerd/containerd v1.7.13 // indirect
@ -115,7 +115,7 @@ require (
github.com/felixge/httpsnoop v1.0.4 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect
github.com/fsnotify/fsnotify v1.7.0 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect
github.com/fsouza/go-dockerclient v1.10.1 // indirect github.com/fsouza/go-dockerclient v1.10.1 // indirect
github.com/gabriel-vasile/mimetype v1.4.2 // indirect github.com/gabriel-vasile/mimetype v1.4.3 // indirect
github.com/gin-contrib/sse v0.1.0 // indirect github.com/gin-contrib/sse v0.1.0 // indirect
github.com/gin-gonic/gin v1.9.1 // indirect github.com/gin-gonic/gin v1.9.1 // indirect
github.com/go-jose/go-jose/v3 v3.0.1 // indirect github.com/go-jose/go-jose/v3 v3.0.1 // indirect
@ -134,7 +134,7 @@ require (
github.com/go-openapi/validate v0.22.1 // indirect github.com/go-openapi/validate v0.22.1 // indirect
github.com/go-playground/locales v0.14.1 // indirect github.com/go-playground/locales v0.14.1 // indirect
github.com/go-playground/universal-translator v0.18.1 // indirect github.com/go-playground/universal-translator v0.18.1 // indirect
github.com/go-playground/validator/v10 v10.15.5 // indirect github.com/go-playground/validator/v10 v10.17.0 // indirect
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect
github.com/goccy/go-json v0.10.2 // indirect github.com/goccy/go-json v0.10.2 // indirect
github.com/gogo/protobuf v1.3.2 // indirect github.com/gogo/protobuf v1.3.2 // indirect
@ -160,7 +160,7 @@ require (
github.com/mailru/easyjson v0.7.7 // indirect github.com/mailru/easyjson v0.7.7 // indirect
github.com/manifoldco/promptui v0.9.0 // indirect github.com/manifoldco/promptui v0.9.0 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.19 // indirect github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mattn/go-runewidth v0.0.15 // indirect github.com/mattn/go-runewidth v0.0.15 // indirect
github.com/mdlayher/socket v0.4.1 // indirect github.com/mdlayher/socket v0.4.1 // indirect
github.com/miekg/pkcs11 v1.1.1 // indirect github.com/miekg/pkcs11 v1.1.1 // indirect
@ -199,7 +199,7 @@ require (
github.com/tklauser/numcpus v0.6.1 // indirect github.com/tklauser/numcpus v0.6.1 // indirect
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
github.com/u-root/uio v0.0.0-20230305220412-3e8cd9d6bf63 // indirect github.com/u-root/uio v0.0.0-20230305220412-3e8cd9d6bf63 // indirect
github.com/ugorji/go/codec v1.2.11 // indirect github.com/ugorji/go/codec v1.2.12 // indirect
github.com/vbatts/tar-split v0.11.5 // indirect github.com/vbatts/tar-split v0.11.5 // indirect
github.com/vishvananda/netns v0.0.4 // indirect github.com/vishvananda/netns v0.0.4 // indirect
github.com/yusufpapurcu/wmi v1.2.3 // indirect github.com/yusufpapurcu/wmi v1.2.3 // indirect
@ -211,7 +211,7 @@ require (
go.opentelemetry.io/otel/metric v1.21.0 // indirect go.opentelemetry.io/otel/metric v1.21.0 // indirect
go.opentelemetry.io/otel/sdk v1.21.0 // indirect go.opentelemetry.io/otel/sdk v1.21.0 // indirect
go.opentelemetry.io/otel/trace v1.21.0 // indirect go.opentelemetry.io/otel/trace v1.21.0 // indirect
golang.org/x/arch v0.5.0 // indirect golang.org/x/arch v0.7.0 // indirect
golang.org/x/crypto v0.19.0 // indirect golang.org/x/crypto v0.19.0 // indirect
golang.org/x/mod v0.14.0 // indirect golang.org/x/mod v0.14.0 // indirect
golang.org/x/oauth2 v0.16.0 // indirect golang.org/x/oauth2 v0.16.0 // indirect

37
go.sum
View File

@ -31,8 +31,8 @@ github.com/buger/goterm v1.0.4 h1:Z9YvGmOih81P0FbVtEYTFF6YsSgxSUKEhf/f9bTMXbY=
github.com/buger/goterm v1.0.4/go.mod h1:HiFWV3xnkolgrBV3mY8m0X0Pumt4zg4QhbdOzQtB8tE= github.com/buger/goterm v1.0.4/go.mod h1:HiFWV3xnkolgrBV3mY8m0X0Pumt4zg4QhbdOzQtB8tE=
github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM= github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM=
github.com/bytedance/sonic v1.10.0-rc/go.mod h1:ElCzW+ufi8qKqNW0FY314xriJhyJhuoJ3gFZdAHF7NM= github.com/bytedance/sonic v1.10.0-rc/go.mod h1:ElCzW+ufi8qKqNW0FY314xriJhyJhuoJ3gFZdAHF7NM=
github.com/bytedance/sonic v1.10.1 h1:7a1wuFXL1cMy7a3f7/VFcEtriuXQnUBhtoVfOZiaysc= github.com/bytedance/sonic v1.10.2 h1:GQebETVBxYB7JGWJtLBi07OVzWwt+8dWA00gEVW2ZFE=
github.com/bytedance/sonic v1.10.1/go.mod h1:iZcSUejdk5aukTND/Eu/ivjQuEL0Cu9/rf50Hi0u/g4= github.com/bytedance/sonic v1.10.2/go.mod h1:iZcSUejdk5aukTND/Eu/ivjQuEL0Cu9/rf50Hi0u/g4=
github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM= github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
@ -44,8 +44,9 @@ github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk= github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk=
github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d h1:77cEq6EriyTZ0g/qfRdp61a3Uu/AWrgIq2s0ClJV1g0= github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d h1:77cEq6EriyTZ0g/qfRdp61a3Uu/AWrgIq2s0ClJV1g0=
github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d/go.mod h1:8EPpVsBuRksnlj1mLy4AWzRNQYxauNi62uWcE3to6eA= github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d/go.mod h1:8EPpVsBuRksnlj1mLy4AWzRNQYxauNi62uWcE3to6eA=
github.com/chenzhuoyu/iasm v0.9.0 h1:9fhXjVzq5hUy2gkhhgHl95zG2cEAhw9OSGs8toWWAwo=
github.com/chenzhuoyu/iasm v0.9.0/go.mod h1:Xjy2NpN3h7aUqeqM+woSuuvxmIe6+DDsiNLIrkAmYog= github.com/chenzhuoyu/iasm v0.9.0/go.mod h1:Xjy2NpN3h7aUqeqM+woSuuvxmIe6+DDsiNLIrkAmYog=
github.com/chenzhuoyu/iasm v0.9.1 h1:tUHQJXo3NhBqw6s33wkGn9SP3bvrWLdlVIJ3hQBL7P0=
github.com/chenzhuoyu/iasm v0.9.1/go.mod h1:Xjy2NpN3h7aUqeqM+woSuuvxmIe6+DDsiNLIrkAmYog=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/logex v1.2.1 h1:XHDu3E6q+gdHgsdTPH6ImJMIp436vR6MPtH8gP05QzM= github.com/chzyer/logex v1.2.1 h1:XHDu3E6q+gdHgsdTPH6ImJMIp436vR6MPtH8gP05QzM=
github.com/chzyer/logex v1.2.1/go.mod h1:JLbx6lG2kDbNRFnfkgvh4eRJRPX1QCoOIWomwysCBrQ= github.com/chzyer/logex v1.2.1/go.mod h1:JLbx6lG2kDbNRFnfkgvh4eRJRPX1QCoOIWomwysCBrQ=
@ -106,8 +107,8 @@ github.com/coreos/stream-metadata-go v0.4.4/go.mod h1:fMObQqQm8Ku91G04btKzEH3Asd
github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/crc-org/crc/v2 v2.32.0 h1:I/62j5KrID8ua1vgAUPOVTtzhcsCsHWdqqiIRHySLfQ= github.com/crc-org/crc/v2 v2.32.0 h1:I/62j5KrID8ua1vgAUPOVTtzhcsCsHWdqqiIRHySLfQ=
github.com/crc-org/crc/v2 v2.32.0/go.mod h1:Q2XJM3KkR/Gu+tBjeN77pk5P8DWYKdbxCSf+9l9MYcs= github.com/crc-org/crc/v2 v2.32.0/go.mod h1:Q2XJM3KkR/Gu+tBjeN77pk5P8DWYKdbxCSf+9l9MYcs=
github.com/crc-org/vfkit v0.5.0 h1:co7N/3h5Jl29VfhPIvbF2cSG2bC7vC4DxbBVeppGPY0= github.com/crc-org/vfkit v0.5.1 h1:r1zNf1g1bLbgu5BgIQodirvYaIGWJQ91eS/PIgNO6lo=
github.com/crc-org/vfkit v0.5.0/go.mod h1:OQiqOghCzdgkd/jRoVu4/lcfQSKje7XPVpfW1aO9YvE= github.com/crc-org/vfkit v0.5.1/go.mod h1:Hqi20zQcqXMk6JqvByvOidHYv+KzPx3G+cjkdGSWv60=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY=
github.com/cyberphone/json-canonicalization v0.0.0-20231217050601-ba74d44ecf5f h1:eHnXnuK47UlSTOQexbzxAZfekVz6i+LKRdj1CU5DPaM= github.com/cyberphone/json-canonicalization v0.0.0-20231217050601-ba74d44ecf5f h1:eHnXnuK47UlSTOQexbzxAZfekVz6i+LKRdj1CU5DPaM=
@ -155,8 +156,8 @@ github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nos
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
github.com/fsouza/go-dockerclient v1.10.1 h1:bSU5Wu2ARdub+iv9VtoDsN8yBUI0vgflmshbeQLKhvc= github.com/fsouza/go-dockerclient v1.10.1 h1:bSU5Wu2ARdub+iv9VtoDsN8yBUI0vgflmshbeQLKhvc=
github.com/fsouza/go-dockerclient v1.10.1/go.mod h1:dyzGriw6v3pK4O4O1u/X+vXxDDsrnLLkCqYkcLsDq2k= github.com/fsouza/go-dockerclient v1.10.1/go.mod h1:dyzGriw6v3pK4O4O1u/X+vXxDDsrnLLkCqYkcLsDq2k=
github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q7OhCmWKU= github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0=
github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA= github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk=
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg= github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg=
@ -214,8 +215,8 @@ github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/o
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
github.com/go-playground/validator/v10 v10.15.5 h1:LEBecTWb/1j5TNY1YYG2RcOUN3R7NLylN+x8TTueE24= github.com/go-playground/validator/v10 v10.17.0 h1:SmVVlfAOtlZncTxRuinDPomC2DkXJ4E5T9gDA0AIH74=
github.com/go-playground/validator/v10 v10.15.5/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU= github.com/go-playground/validator/v10 v10.17.0/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU=
github.com/go-rod/rod v0.114.5 h1:1x6oqnslwFVuXJbJifgxspJUd3O4ntaGhRLHt+4Er9c= github.com/go-rod/rod v0.114.5 h1:1x6oqnslwFVuXJbJifgxspJUd3O4ntaGhRLHt+4Er9c=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
@ -387,8 +388,8 @@ github.com/markbates/safe v1.0.1/go.mod h1:nAqgmRi7cY2nqMc92/bSEeQA+R4OheNU2T1kN
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U= github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U=
github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/mattn/go-shellwords v1.0.12 h1:M2zGm7EW6UQJvDeQxo4T51eKPurbeFbe8WtebGE2xrk= github.com/mattn/go-shellwords v1.0.12 h1:M2zGm7EW6UQJvDeQxo4T51eKPurbeFbe8WtebGE2xrk=
@ -509,8 +510,8 @@ github.com/secure-systems-lab/go-securesystemslib v0.8.0/go.mod h1:UH2VZVuJfCYR8
github.com/segmentio/ksuid v1.0.4 h1:sBo2BdShXjmcugAMwjugoGUdUV0pcxY5mW4xKRn3v4c= github.com/segmentio/ksuid v1.0.4 h1:sBo2BdShXjmcugAMwjugoGUdUV0pcxY5mW4xKRn3v4c=
github.com/segmentio/ksuid v1.0.4/go.mod h1:/XUiZBD3kVx5SmUOl55voK5yeAbBNNIed+2O73XgrPE= github.com/segmentio/ksuid v1.0.4/go.mod h1:/XUiZBD3kVx5SmUOl55voK5yeAbBNNIed+2O73XgrPE=
github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8= github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8=
github.com/shirou/gopsutil/v3 v3.23.12 h1:z90NtUkp3bMtmICZKpC4+WaknU1eXtp5vtbQ11DgpE4= github.com/shirou/gopsutil/v3 v3.24.1 h1:R3t6ondCEvmARp3wxODhXMTLC/klMa87h2PHUw5m7QI=
github.com/shirou/gopsutil/v3 v3.23.12/go.mod h1:1FrWgea594Jp7qmjHUUPlJDTPgcsb9mGnXDxavtikzM= github.com/shirou/gopsutil/v3 v3.24.1/go.mod h1:UU7a2MSBQa+kW1uuDq8DeEBS8kmrnQwsv2b5O513rwU=
github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM= github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM=
github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ= github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ=
github.com/shoenig/test v0.6.4 h1:kVTaSd7WLz5WZ2IaoM0RSzRsUD+m8wRR+5qvntpn4LU= github.com/shoenig/test v0.6.4 h1:kVTaSd7WLz5WZ2IaoM0RSzRsUD+m8wRR+5qvntpn4LU=
@ -570,8 +571,8 @@ github.com/u-root/gobusybox/src v0.0.0-20230806212452-e9366a5b9fdc h1:udgfN9Qy57
github.com/u-root/u-root v0.11.1-0.20230807200058-f87ad7ccb594 h1:1AIJqOtdEufYfGb3eRpdaqWONzBOpAwrg1fehbWg+Mg= github.com/u-root/u-root v0.11.1-0.20230807200058-f87ad7ccb594 h1:1AIJqOtdEufYfGb3eRpdaqWONzBOpAwrg1fehbWg+Mg=
github.com/u-root/uio v0.0.0-20230305220412-3e8cd9d6bf63 h1:YcojQL98T/OO+rybuzn2+5KrD5dBwXIvYBvQ2cD3Avg= github.com/u-root/uio v0.0.0-20230305220412-3e8cd9d6bf63 h1:YcojQL98T/OO+rybuzn2+5KrD5dBwXIvYBvQ2cD3Avg=
github.com/u-root/uio v0.0.0-20230305220412-3e8cd9d6bf63/go.mod h1:eLL9Nub3yfAho7qB0MzZizFhTU2QkLeoVsWdHtDW264= github.com/u-root/uio v0.0.0-20230305220412-3e8cd9d6bf63/go.mod h1:eLL9Nub3yfAho7qB0MzZizFhTU2QkLeoVsWdHtDW264=
github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU= github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE=
github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
github.com/ulikunitz/xz v0.5.11 h1:kpFauv27b6ynzBNT/Xy+1k+fK4WswhN/6PN5WhFAGw8= github.com/ulikunitz/xz v0.5.11 h1:kpFauv27b6ynzBNT/Xy+1k+fK4WswhN/6PN5WhFAGw8=
github.com/ulikunitz/xz v0.5.11/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= github.com/ulikunitz/xz v0.5.11/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
github.com/vbatts/tar-split v0.11.5 h1:3bHCTIheBm1qFTcgh9oPu+nNBtX+XJIupG/vacinCts= github.com/vbatts/tar-split v0.11.5 h1:3bHCTIheBm1qFTcgh9oPu+nNBtX+XJIupG/vacinCts=
@ -631,8 +632,8 @@ go.opentelemetry.io/otel/trace v1.21.0/go.mod h1:LGbsEB0f9LGjN+OZaQQ26sohbOmiMR+
go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lIVU/I= go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lIVU/I=
go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A= go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A=
golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
golang.org/x/arch v0.5.0 h1:jpGode6huXQxcskEIpOCvrU+tzo81b6+oFLUYXWtH/Y= golang.org/x/arch v0.7.0 h1:pskyeJh/3AmoQ8CPE95vxHLqp1G1GfGNXTmcl9NEKTc=
golang.org/x/arch v0.5.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= golang.org/x/arch v0.7.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190422162423-af44ce270edf/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= golang.org/x/crypto v0.0.0-20190422162423-af44ce270edf/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE=
@ -733,7 +734,7 @@ golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y= golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y=
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=

View File

@ -107,7 +107,7 @@ err := sonic.Unmarshal(output, &data)
``` ```
### Streaming IO ### Streaming IO
Sonic supports decoding json from `io.Reader` or encoding objects into `io.`Writer`, aims at handling multiple values as well as reducing memory consumption. Sonic supports decoding json from `io.Reader` or encoding objects into `io.Writer`, aims at handling multiple values as well as reducing memory consumption.
- encoder - encoder
```go ```go
var o1 = map[string]interface{}{ var o1 = map[string]interface{}{

View File

@ -420,9 +420,9 @@ func (self *_Assembler) call_go(fn obj.Addr) {
} }
func (self *_Assembler) callc(fn obj.Addr) { func (self *_Assembler) callc(fn obj.Addr) {
self.Emit("XCHGQ", _IP, _BP) self.save(_IP)
self.call(fn) self.call(fn)
self.Emit("XCHGQ", _IP, _BP) self.load(_IP)
} }
func (self *_Assembler) call_c(fn obj.Addr) { func (self *_Assembler) call_c(fn obj.Addr) {
@ -1164,7 +1164,7 @@ var (
var ( var (
_F_FieldMap_GetCaseInsensitive obj.Addr _F_FieldMap_GetCaseInsensitive obj.Addr
_Empty_Slice = make([]byte, 0) _Empty_Slice = []byte{}
_Zero_Base = int64(uintptr(((*rt.GoSlice)(unsafe.Pointer(&_Empty_Slice))).Ptr)) _Zero_Base = int64(uintptr(((*rt.GoSlice)(unsafe.Pointer(&_Empty_Slice))).Ptr))
) )
@ -1641,7 +1641,8 @@ func (self *_Assembler) _asm_OP_check_empty(p *_Instr) {
self.Emit("CMPB", jit.Sib(_IP, _IC, 1, 0), jit.Imm(int64(rbracket))) // CMPB (IP)(IC), ']' self.Emit("CMPB", jit.Sib(_IP, _IC, 1, 0), jit.Imm(int64(rbracket))) // CMPB (IP)(IC), ']'
self.Sjmp("JNE" , "_not_empty_array_{n}") // JNE _not_empty_array_{n} self.Sjmp("JNE" , "_not_empty_array_{n}") // JNE _not_empty_array_{n}
self.Emit("MOVQ", _AX, _IC) // MOVQ AX, IC self.Emit("MOVQ", _AX, _IC) // MOVQ AX, IC
self.StorePtr(_Zero_Base, jit.Ptr(_VP, 0), _AX) // MOVQ $zerobase, (VP) self.Emit("MOVQ", jit.Imm(_Zero_Base), _AX)
self.WritePtrAX(9, jit.Ptr(_VP, 0), false)
self.Emit("PXOR", _X0, _X0) // PXOR X0, X0 self.Emit("PXOR", _X0, _X0) // PXOR X0, X0
self.Emit("MOVOU", _X0, jit.Ptr(_VP, 8)) // MOVOU X0, 8(VP) self.Emit("MOVOU", _X0, jit.Ptr(_VP, 8)) // MOVOU X0, 8(VP)
self.Xjmp("JMP" , p.vi()) // JMP {p.vi()} self.Xjmp("JMP" , p.vi()) // JMP {p.vi()}

View File

@ -1651,7 +1651,8 @@ func (self *_Assembler) _asm_OP_check_empty(p *_Instr) {
self.Emit("CMPB", jit.Sib(_IP, _IC, 1, 0), jit.Imm(int64(rbracket))) // CMPB (IP)(IC), ']' self.Emit("CMPB", jit.Sib(_IP, _IC, 1, 0), jit.Imm(int64(rbracket))) // CMPB (IP)(IC), ']'
self.Sjmp("JNE" , "_not_empty_array_{n}") // JNE _not_empty_array_{n} self.Sjmp("JNE" , "_not_empty_array_{n}") // JNE _not_empty_array_{n}
self.Emit("MOVQ", _AX, _IC) // MOVQ AX, IC self.Emit("MOVQ", _AX, _IC) // MOVQ AX, IC
self.StorePtr(_Zero_Base, jit.Ptr(_VP, 0), _AX) // MOVQ $zerobase, (VP) self.Emit("MOVQ", jit.Imm(_Zero_Base), _AX)
self.WritePtrAX(9, jit.Ptr(_VP, 0), false)
self.Emit("PXOR" , _X0, _X0) // PXOR X0, X0 self.Emit("PXOR" , _X0, _X0) // PXOR X0, X0
self.Emit("MOVOU", _X0, jit.Ptr(_VP, 8)) // MOVOU X0, 8(VP) self.Emit("MOVOU", _X0, jit.Ptr(_VP, 8)) // MOVOU X0, 8(VP)
self.Xjmp("JMP" , p.vi()) // JMP {p.vi()} self.Xjmp("JMP" , p.vi()) // JMP {p.vi()}

View File

@ -527,6 +527,38 @@ func (self *_Compiler) compile(vt reflect.Type) (ret _Program, err error) {
return return
} }
func (self *_Compiler) checkMarshaler(p *_Program, vt reflect.Type) bool {
pt := reflect.PtrTo(vt)
/* check for `json.Unmarshaler` with pointer receiver */
if pt.Implements(jsonUnmarshalerType) {
p.rtt(_OP_unmarshal_p, pt)
return true
}
/* check for `json.Unmarshaler` */
if vt.Implements(jsonUnmarshalerType) {
p.add(_OP_lspace)
self.compileUnmarshalJson(p, vt)
return true
}
/* check for `encoding.TextMarshaler` with pointer receiver */
if pt.Implements(encodingTextUnmarshalerType) {
p.add(_OP_lspace)
self.compileUnmarshalTextPtr(p, pt)
return true
}
/* check for `encoding.TextUnmarshaler` */
if vt.Implements(encodingTextUnmarshalerType) {
p.add(_OP_lspace)
self.compileUnmarshalText(p, vt)
return true
}
return false
}
func (self *_Compiler) compileOne(p *_Program, sp int, vt reflect.Type) { func (self *_Compiler) compileOne(p *_Program, sp int, vt reflect.Type) {
/* check for recursive nesting */ /* check for recursive nesting */
ok := self.tab[vt] ok := self.tab[vt]
@ -535,32 +567,7 @@ func (self *_Compiler) compileOne(p *_Program, sp int, vt reflect.Type) {
return return
} }
pt := reflect.PtrTo(vt) if self.checkMarshaler(p, vt) {
/* check for `json.Unmarshaler` with pointer receiver */
if pt.Implements(jsonUnmarshalerType) {
p.rtt(_OP_unmarshal_p, pt)
return
}
/* check for `json.Unmarshaler` */
if vt.Implements(jsonUnmarshalerType) {
p.add(_OP_lspace)
self.compileUnmarshalJson(p, vt)
return
}
/* check for `encoding.TextMarshaler` with pointer receiver */
if pt.Implements(encodingTextUnmarshalerType) {
p.add(_OP_lspace)
self.compileUnmarshalTextPtr(p, pt)
return
}
/* check for `encoding.TextUnmarshaler` */
if vt.Implements(encodingTextUnmarshalerType) {
p.add(_OP_lspace)
self.compileUnmarshalText(p, vt)
return return
} }
@ -683,17 +690,9 @@ func (self *_Compiler) compilePtr(p *_Program, sp int, et reflect.Type) {
/* dereference all the way down */ /* dereference all the way down */
for et.Kind() == reflect.Ptr { for et.Kind() == reflect.Ptr {
if et.Implements(jsonUnmarshalerType) { if self.checkMarshaler(p, et) {
p.rtt(_OP_unmarshal_p, et)
return return
} }
if et.Implements(encodingTextUnmarshalerType) {
p.add(_OP_lspace)
self.compileUnmarshalTextPtr(p, et)
return
}
et = et.Elem() et = et.Elem()
p.rtt(_OP_deref, et) p.rtt(_OP_deref, et)
} }
@ -706,7 +705,7 @@ func (self *_Compiler) compilePtr(p *_Program, sp int, et reflect.Type) {
/* enter the recursion */ /* enter the recursion */
p.add(_OP_lspace) p.add(_OP_lspace)
self.tab[et] = true self.tab[et] = true
/* not inline the pointer type /* not inline the pointer type
* recursing the defined pointer type's elem will casue issue379. * recursing the defined pointer type's elem will casue issue379.
*/ */
@ -716,8 +715,12 @@ func (self *_Compiler) compilePtr(p *_Program, sp int, et reflect.Type) {
j := p.pc() j := p.pc()
p.add(_OP_goto) p.add(_OP_goto)
// set val pointer as nil
p.pin(i) p.pin(i)
p.add(_OP_nil_1) p.add(_OP_nil_1)
// nothing todo
p.pin(j) p.pin(j)
} }

View File

@ -119,9 +119,9 @@ func (self *_ValueDecoder) call_go(fn obj.Addr) {
} }
func (self *_ValueDecoder) callc(fn obj.Addr) { func (self *_ValueDecoder) callc(fn obj.Addr) {
self.Emit("XCHGQ", _IP, _BP) self.save(_IP)
self.call(fn) self.call(fn)
self.Emit("XCHGQ", _IP, _BP) self.load(_IP)
} }
func (self *_ValueDecoder) call_c(fn obj.Addr) { func (self *_ValueDecoder) call_c(fn obj.Addr) {

View File

@ -171,7 +171,7 @@ var (
) )
var ( var (
_REG_ffi = []obj.Addr{ _RP, _RL, _RC} _REG_ffi = []obj.Addr{ _RP, _RL, _RC, _SP_q}
_REG_b64 = []obj.Addr{_SP_p, _SP_q} _REG_b64 = []obj.Addr{_SP_p, _SP_q}
_REG_all = []obj.Addr{_ST, _SP_x, _SP_f, _SP_p, _SP_q, _RP, _RL, _RC} _REG_all = []obj.Addr{_ST, _SP_x, _SP_f, _SP_p, _SP_q, _RP, _RL, _RC}
@ -510,11 +510,9 @@ func (self *_Assembler) call_b64(pc obj.Addr) {
func (self *_Assembler) call_c(pc obj.Addr) { func (self *_Assembler) call_c(pc obj.Addr) {
self.Emit("XCHGQ", _SP_p, _BX) self.Emit("XCHGQ", _SP_p, _BX)
self.Emit("XCHGQ", _SP_q, _BP)
self.call(pc) // CALL $pc self.call(pc) // CALL $pc
self.xload(_REG_ffi...) // LOAD $REG_ffi self.xload(_REG_ffi...) // LOAD $REG_ffi
self.Emit("XCHGQ", _SP_p, _BX) self.Emit("XCHGQ", _SP_p, _BX)
self.Emit("XCHGQ", _SP_q, _BP)
} }
func (self *_Assembler) call_go(pc obj.Addr) { func (self *_Assembler) call_go(pc obj.Addr) {

View File

@ -72,18 +72,6 @@ func (self *BaseAssembler) NOPn(n int) {
} }
} }
func (self *BaseAssembler) StorePtr(ptr int64, to obj.Addr, tmp obj.Addr) {
if (to.Type != obj.TYPE_MEM) || (tmp.Type != obj.TYPE_REG) {
panic("must store imm to memory, tmp must be register")
}
if (ptr >> 32) != 0 {
self.Emit("MOVQ", Imm(ptr), tmp)
self.Emit("MOVQ", tmp, to)
} else {
self.Emit("MOVQ", Imm(ptr), to);
}
}
func (self *BaseAssembler) Byte(v ...byte) { func (self *BaseAssembler) Byte(v ...byte) {
for ; len(v) >= 8; v = v[8:] { self.From("QUAD", Imm(rt.Get64(v))) } for ; len(v) >= 8; v = v[8:] { self.From("QUAD", Imm(rt.Get64(v))) }
for ; len(v) >= 4; v = v[4:] { self.From("LONG", Imm(int64(rt.Get32(v)))) } for ; len(v) >= 4; v = v[4:] { self.From("LONG", Imm(int64(rt.Get32(v)))) }

View File

@ -17,12 +17,12 @@
package rt package rt
const ( const (
MinInt48 = -(1 << 47) MinInt48 int64 = -(1 << 47)
MaxInt48 = +(1 << 47) - 1 MaxInt48 int64 = +(1 << 47) - 1
) )
func PackInt(v int) uint64 { func PackInt(v int) uint64 {
if u := uint64(v); v < MinInt48 || v > MaxInt48 { if u := uint64(v); int64(v) < MinInt48 || int64(v) > MaxInt48 {
panic("int48 out of range") panic("int48 out of range")
} else { } else {
return ((u >> 63) << 47) | (u & 0x00007fffffffffff) return ((u >> 63) << 47) | (u & 0x00007fffffffffff)

View File

@ -1,13 +1,13 @@
package x86_64 package x86_64
import ( import (
`errors` "errors"
`fmt` "fmt"
`math` "math"
`reflect` "reflect"
`strconv` "strconv"
`strings` "strings"
`sync/atomic` "sync/atomic"
) )
// RelativeOffset represents an RIP-relative offset. // RelativeOffset represents an RIP-relative offset.
@ -15,496 +15,635 @@ type RelativeOffset int32
// String implements the fmt.Stringer interface. // String implements the fmt.Stringer interface.
func (self RelativeOffset) String() string { func (self RelativeOffset) String() string {
if self == 0 { if self == 0 {
return "(%rip)" return "(%rip)"
} else { } else {
return fmt.Sprintf("%d(%%rip)", self) return fmt.Sprintf("%d(%%rip)", self)
} }
} }
// RoundingControl represents a floating-point rounding option. // RoundingControl represents a floating-point rounding option.
type RoundingControl uint8 type RoundingControl uint8
const ( const (
// RN_SAE represents "Round Nearest", which is the default rounding option. // RN_SAE represents "Round Nearest", which is the default rounding option.
RN_SAE RoundingControl = iota RN_SAE RoundingControl = iota
// RD_SAE represents "Round Down". // RD_SAE represents "Round Down".
RD_SAE RD_SAE
// RU_SAE represents "Round Up". // RU_SAE represents "Round Up".
RU_SAE RU_SAE
// RZ_SAE represents "Round towards Zero". // RZ_SAE represents "Round towards Zero".
RZ_SAE RZ_SAE
) )
var _RC_NAMES = map[RoundingControl]string { var _RC_NAMES = map[RoundingControl]string{
RN_SAE: "rn-sae", RN_SAE: "rn-sae",
RD_SAE: "rd-sae", RD_SAE: "rd-sae",
RU_SAE: "ru-sae", RU_SAE: "ru-sae",
RZ_SAE: "rz-sae", RZ_SAE: "rz-sae",
} }
func (self RoundingControl) String() string { func (self RoundingControl) String() string {
if v, ok := _RC_NAMES[self]; ok { if v, ok := _RC_NAMES[self]; ok {
return v return v
} else { } else {
panic("invalid RoundingControl value") panic("invalid RoundingControl value")
} }
} }
// ExceptionControl represents the "Suppress All Exceptions" flag. // ExceptionControl represents the "Suppress All Exceptions" flag.
type ExceptionControl uint8 type ExceptionControl uint8
const ( const (
// SAE represents the flag "Suppress All Exceptions" for floating point operations. // SAE represents the flag "Suppress All Exceptions" for floating point operations.
SAE ExceptionControl = iota SAE ExceptionControl = iota
) )
func (ExceptionControl) String() string { func (ExceptionControl) String() string {
return "sae" return "sae"
} }
// AddressType indicates which kind of value that an Addressable object contains. // AddressType indicates which kind of value that an Addressable object contains.
type AddressType uint type AddressType uint
const ( const (
// None indicates the Addressable does not contain any addressable value. // None indicates the Addressable does not contain any addressable value.
None AddressType = iota None AddressType = iota
// Memory indicates the Addressable contains a memory address. // Memory indicates the Addressable contains a memory address.
Memory Memory
// Offset indicates the Addressable contains an RIP-relative offset. // Offset indicates the Addressable contains an RIP-relative offset.
Offset Offset
// Reference indicates the Addressable contains a label reference. // Reference indicates the Addressable contains a label reference.
Reference Reference
) )
// Disposable is a type of object that can be Free'd manually. // Disposable is a type of object that can be Free'd manually.
type Disposable interface { type Disposable interface {
Free() Free()
} }
// Label represents a location within the program. // Label represents a location within the program.
type Label struct { type Label struct {
refs int64 refs int64
Name string Name string
Dest *Instruction Dest *Instruction
} }
func (self *Label) offset(p uintptr, n int) RelativeOffset { func (self *Label) offset(p uintptr, n int) RelativeOffset {
if self.Dest == nil { if self.Dest == nil {
panic("unresolved label: " + self.Name) panic("unresolved label: " + self.Name)
} else { } else {
return RelativeOffset(self.Dest.pc - p - uintptr(n)) return RelativeOffset(self.Dest.pc - p - uintptr(n))
} }
} }
// Free decreases the reference count of a Label, if the // Free decreases the reference count of a Label, if the
// refcount drops to 0, the Label will be recycled. // refcount drops to 0, the Label will be recycled.
func (self *Label) Free() { func (self *Label) Free() {
if atomic.AddInt64(&self.refs, -1) == 0 { if atomic.AddInt64(&self.refs, -1) == 0 {
freeLabel(self) //freeLabel(self)
} }
} }
// String implements the fmt.Stringer interface. // String implements the fmt.Stringer interface.
func (self *Label) String() string { func (self *Label) String() string {
if self.Dest == nil { if self.Dest == nil {
return fmt.Sprintf("%s(%%rip)", self.Name) return fmt.Sprintf("%s(%%rip)", self.Name)
} else { } else {
return fmt.Sprintf("%s(%%rip)@%#x", self.Name, self.Dest.pc) return fmt.Sprintf("%s(%%rip)@%#x", self.Name, self.Dest.pc)
} }
} }
// Retain increases the reference count of a Label. // Retain increases the reference count of a Label.
func (self *Label) Retain() *Label { func (self *Label) Retain() *Label {
atomic.AddInt64(&self.refs, 1) atomic.AddInt64(&self.refs, 1)
return self return self
} }
// Evaluate implements the interface expr.Term. // Evaluate implements the interface expr.Term.
func (self *Label) Evaluate() (int64, error) { func (self *Label) Evaluate() (int64, error) {
if self.Dest != nil { if self.Dest != nil {
return int64(self.Dest.pc), nil return int64(self.Dest.pc), nil
} else { } else {
return 0, errors.New("unresolved label: " + self.Name) return 0, errors.New("unresolved label: " + self.Name)
} }
} }
// Addressable is a union to represent an addressable operand. // Addressable is a union to represent an addressable operand.
type Addressable struct { type Addressable struct {
Type AddressType Type AddressType
Memory MemoryAddress Memory MemoryAddress
Offset RelativeOffset Offset RelativeOffset
Reference *Label Reference *Label
} }
// String implements the fmt.Stringer interface. // String implements the fmt.Stringer interface.
func (self *Addressable) String() string { func (self *Addressable) String() string {
switch self.Type { switch self.Type {
case None : return "(not addressable)" case None:
case Memory : return self.Memory.String() return "(not addressable)"
case Offset : return self.Offset.String() case Memory:
case Reference : return self.Reference.String() return self.Memory.String()
default : return "(invalid addressable)" case Offset:
} return self.Offset.String()
case Reference:
return self.Reference.String()
default:
return "(invalid addressable)"
}
} }
// MemoryOperand represents a memory operand for an instruction. // MemoryOperand represents a memory operand for an instruction.
type MemoryOperand struct { type MemoryOperand struct {
refs int64 refs int64
Size int Size int
Addr Addressable Addr Addressable
Mask RegisterMask Mask RegisterMask
Masked bool Masked bool
Broadcast uint8 Broadcast uint8
} }
const ( const (
_Sizes = 0b10000000100010111 // bit-mask for valid sizes (0, 1, 2, 4, 8, 16) _Sizes = 0b10000000100010111 // bit-mask for valid sizes (0, 1, 2, 4, 8, 16)
) )
func (self *MemoryOperand) isVMX(evex bool) bool { func (self *MemoryOperand) isVMX(evex bool) bool {
return self.Addr.Type == Memory && self.Addr.Memory.isVMX(evex) return self.Addr.Type == Memory && self.Addr.Memory.isVMX(evex)
} }
func (self *MemoryOperand) isVMY(evex bool) bool { func (self *MemoryOperand) isVMY(evex bool) bool {
return self.Addr.Type == Memory && self.Addr.Memory.isVMY(evex) return self.Addr.Type == Memory && self.Addr.Memory.isVMY(evex)
} }
func (self *MemoryOperand) isVMZ() bool { func (self *MemoryOperand) isVMZ() bool {
return self.Addr.Type == Memory && self.Addr.Memory.isVMZ() return self.Addr.Type == Memory && self.Addr.Memory.isVMZ()
} }
func (self *MemoryOperand) isMem() bool { func (self *MemoryOperand) isMem() bool {
if (_Sizes & (1 << self.Broadcast)) == 0 { if (_Sizes & (1 << self.Broadcast)) == 0 {
return false return false
} else if self.Addr.Type == Memory { } else if self.Addr.Type == Memory {
return self.Addr.Memory.isMem() return self.Addr.Memory.isMem()
} else if self.Addr.Type == Offset { } else if self.Addr.Type == Offset {
return true return true
} else if self.Addr.Type == Reference { } else if self.Addr.Type == Reference {
return true return true
} else { } else {
return false return false
} }
} }
func (self *MemoryOperand) isSize(n int) bool { func (self *MemoryOperand) isSize(n int) bool {
return self.Size == 0 || self.Size == n return self.Size == 0 || self.Size == n
} }
func (self *MemoryOperand) isBroadcast(n int, b uint8) bool { func (self *MemoryOperand) isBroadcast(n int, b uint8) bool {
return self.Size == n && self.Broadcast == b return self.Size == n && self.Broadcast == b
} }
func (self *MemoryOperand) formatMask() string { func (self *MemoryOperand) formatMask() string {
if !self.Masked { if !self.Masked {
return "" return ""
} else { } else {
return self.Mask.String() return self.Mask.String()
} }
} }
func (self *MemoryOperand) formatBroadcast() string { func (self *MemoryOperand) formatBroadcast() string {
if self.Broadcast == 0 { if self.Broadcast == 0 {
return "" return ""
} else { } else {
return fmt.Sprintf("{1to%d}", self.Broadcast) return fmt.Sprintf("{1to%d}", self.Broadcast)
} }
} }
func (self *MemoryOperand) ensureAddrValid() { func (self *MemoryOperand) ensureAddrValid() {
switch self.Addr.Type { switch self.Addr.Type {
case None : break case None:
case Memory : self.Addr.Memory.EnsureValid() break
case Offset : break case Memory:
case Reference : break self.Addr.Memory.EnsureValid()
default : panic("invalid address type") case Offset:
} break
case Reference:
break
default:
panic("invalid address type")
}
} }
func (self *MemoryOperand) ensureSizeValid() { func (self *MemoryOperand) ensureSizeValid() {
if (_Sizes & (1 << self.Size)) == 0 { if (_Sizes & (1 << self.Size)) == 0 {
panic("invalid memory operand size") panic("invalid memory operand size")
} }
} }
func (self *MemoryOperand) ensureBroadcastValid() { func (self *MemoryOperand) ensureBroadcastValid() {
if (_Sizes & (1 << self.Broadcast)) == 0 { if (_Sizes & (1 << self.Broadcast)) == 0 {
panic("invalid memory operand broadcast") panic("invalid memory operand broadcast")
} }
} }
// Free decreases the reference count of a MemoryOperand, if the // Free decreases the reference count of a MemoryOperand, if the
// refcount drops to 0, the Label will be recycled. // refcount drops to 0, the Label will be recycled.
func (self *MemoryOperand) Free() { func (self *MemoryOperand) Free() {
if atomic.AddInt64(&self.refs, -1) == 0 { if atomic.AddInt64(&self.refs, -1) == 0 {
freeMemoryOperand(self) //freeMemoryOperand(self)
} }
} }
// String implements the fmt.Stringer interface. // String implements the fmt.Stringer interface.
func (self *MemoryOperand) String() string { func (self *MemoryOperand) String() string {
return self.Addr.String() + self.formatMask() + self.formatBroadcast() return self.Addr.String() + self.formatMask() + self.formatBroadcast()
} }
// Retain increases the reference count of a MemoryOperand. // Retain increases the reference count of a MemoryOperand.
func (self *MemoryOperand) Retain() *MemoryOperand { func (self *MemoryOperand) Retain() *MemoryOperand {
atomic.AddInt64(&self.refs, 1) atomic.AddInt64(&self.refs, 1)
return self return self
} }
// EnsureValid checks if the memory operand is valid, if not, it panics. // EnsureValid checks if the memory operand is valid, if not, it panics.
func (self *MemoryOperand) EnsureValid() { func (self *MemoryOperand) EnsureValid() {
self.ensureAddrValid() self.ensureAddrValid()
self.ensureSizeValid() self.ensureSizeValid()
self.ensureBroadcastValid() self.ensureBroadcastValid()
} }
// MemoryAddress represents a memory address. // MemoryAddress represents a memory address.
type MemoryAddress struct { type MemoryAddress struct {
Base Register Base Register
Index Register Index Register
Scale uint8 Scale uint8
Displacement int32 Displacement int32
} }
const ( const (
_Scales = 0b100010111 // bit-mask for valid scales (0, 1, 2, 4, 8) _Scales = 0b100010111 // bit-mask for valid scales (0, 1, 2, 4, 8)
) )
func (self *MemoryAddress) isVMX(evex bool) bool { func (self *MemoryAddress) isVMX(evex bool) bool {
return self.isMemBase() && (self.Index == nil || isXMM(self.Index) || (evex && isEVEXXMM(self.Index))) return self.isMemBase() && (self.Index == nil || isXMM(self.Index) || (evex && isEVEXXMM(self.Index)))
} }
func (self *MemoryAddress) isVMY(evex bool) bool { func (self *MemoryAddress) isVMY(evex bool) bool {
return self.isMemBase() && (self.Index == nil || isYMM(self.Index) || (evex && isEVEXYMM(self.Index))) return self.isMemBase() && (self.Index == nil || isYMM(self.Index) || (evex && isEVEXYMM(self.Index)))
} }
func (self *MemoryAddress) isVMZ() bool { func (self *MemoryAddress) isVMZ() bool {
return self.isMemBase() && (self.Index == nil || isZMM(self.Index)) return self.isMemBase() && (self.Index == nil || isZMM(self.Index))
} }
func (self *MemoryAddress) isMem() bool { func (self *MemoryAddress) isMem() bool {
return self.isMemBase() && (self.Index == nil || isReg64(self.Index)) return self.isMemBase() && (self.Index == nil || isReg64(self.Index))
} }
func (self *MemoryAddress) isMemBase() bool { func (self *MemoryAddress) isMemBase() bool {
return (self.Base == nil || isReg64(self.Base)) && // `Base` must be 64-bit if present return (self.Base == nil || isReg64(self.Base)) && // `Base` must be 64-bit if present
(self.Scale == 0) == (self.Index == nil) && // `Scale` and `Index` depends on each other (self.Scale == 0) == (self.Index == nil) && // `Scale` and `Index` depends on each other
(_Scales & (1 << self.Scale)) != 0 // `Scale` can only be 0, 1, 2, 4 or 8 (_Scales&(1<<self.Scale)) != 0 // `Scale` can only be 0, 1, 2, 4 or 8
} }
// String implements the fmt.Stringer interface. // String implements the fmt.Stringer interface.
func (self *MemoryAddress) String() string { func (self *MemoryAddress) String() string {
var dp int var dp int
var sb strings.Builder var sb strings.Builder
/* the displacement part */ /* the displacement part */
if dp = int(self.Displacement); dp != 0 { if dp = int(self.Displacement); dp != 0 {
sb.WriteString(strconv.Itoa(dp)) sb.WriteString(strconv.Itoa(dp))
} }
/* the base register */ /* the base register */
if sb.WriteByte('('); self.Base != nil { if sb.WriteByte('('); self.Base != nil {
sb.WriteByte('%') sb.WriteByte('%')
sb.WriteString(self.Base.String()) sb.WriteString(self.Base.String())
} }
/* index is optional */ /* index is optional */
if self.Index != nil { if self.Index != nil {
sb.WriteString(",%") sb.WriteString(",%")
sb.WriteString(self.Index.String()) sb.WriteString(self.Index.String())
/* scale is also optional */ /* scale is also optional */
if self.Scale >= 2 { if self.Scale >= 2 {
sb.WriteByte(',') sb.WriteByte(',')
sb.WriteString(strconv.Itoa(int(self.Scale))) sb.WriteString(strconv.Itoa(int(self.Scale)))
} }
} }
/* close the bracket */ /* close the bracket */
sb.WriteByte(')') sb.WriteByte(')')
return sb.String() return sb.String()
} }
// EnsureValid checks if the memory address is valid, if not, it panics. // EnsureValid checks if the memory address is valid, if not, it panics.
func (self *MemoryAddress) EnsureValid() { func (self *MemoryAddress) EnsureValid() {
if !self.isMemBase() || (self.Index != nil && !isIndexable(self.Index)) { if !self.isMemBase() || (self.Index != nil && !isIndexable(self.Index)) {
panic("not a valid memory address") panic("not a valid memory address")
} }
} }
// Ref constructs a memory reference to a label. // Ref constructs a memory reference to a label.
func Ref(ref *Label) (v *MemoryOperand) { func Ref(ref *Label) (v *MemoryOperand) {
v = CreateMemoryOperand() v = CreateMemoryOperand()
v.Addr.Type = Reference v.Addr.Type = Reference
v.Addr.Reference = ref v.Addr.Reference = ref
return return
} }
// Abs construct a simple memory address that represents absolute addressing. // Abs construct a simple memory address that represents absolute addressing.
func Abs(disp int32) *MemoryOperand { func Abs(disp int32) *MemoryOperand {
return Sib(nil, nil, 0, disp) return Sib(nil, nil, 0, disp)
} }
// Ptr constructs a simple memory operand with base and displacement. // Ptr constructs a simple memory operand with base and displacement.
func Ptr(base Register, disp int32) *MemoryOperand { func Ptr(base Register, disp int32) *MemoryOperand {
return Sib(base, nil, 0, disp) return Sib(base, nil, 0, disp)
} }
// Sib constructs a simple memory operand that represents a complete memory address. // Sib constructs a simple memory operand that represents a complete memory address.
func Sib(base Register, index Register, scale uint8, disp int32) (v *MemoryOperand) { func Sib(base Register, index Register, scale uint8, disp int32) (v *MemoryOperand) {
v = CreateMemoryOperand() v = CreateMemoryOperand()
v.Addr.Type = Memory v.Addr.Type = Memory
v.Addr.Memory.Base = base v.Addr.Memory.Base = base
v.Addr.Memory.Index = index v.Addr.Memory.Index = index
v.Addr.Memory.Scale = scale v.Addr.Memory.Scale = scale
v.Addr.Memory.Displacement = disp v.Addr.Memory.Displacement = disp
v.EnsureValid() v.EnsureValid()
return return
} }
/** Operand Matching Helpers **/ /** Operand Matching Helpers **/
const _IntMask = const _IntMask = (1 << reflect.Int) |
(1 << reflect.Int ) | (1 << reflect.Int8) |
(1 << reflect.Int8 ) | (1 << reflect.Int16) |
(1 << reflect.Int16 ) | (1 << reflect.Int32) |
(1 << reflect.Int32 ) | (1 << reflect.Int64) |
(1 << reflect.Int64 ) | (1 << reflect.Uint) |
(1 << reflect.Uint ) | (1 << reflect.Uint8) |
(1 << reflect.Uint8 ) | (1 << reflect.Uint16) |
(1 << reflect.Uint16 ) | (1 << reflect.Uint32) |
(1 << reflect.Uint32 ) | (1 << reflect.Uint64) |
(1 << reflect.Uint64 ) | (1 << reflect.Uintptr)
(1 << reflect.Uintptr)
func isInt(k reflect.Kind) bool { func isInt(k reflect.Kind) bool {
return (_IntMask & (1 << k)) != 0 return (_IntMask & (1 << k)) != 0
} }
func asInt64(v interface{}) (int64, bool) { func asInt64(v interface{}) (int64, bool) {
if isSpecial(v) { if isSpecial(v) {
return 0, false return 0, false
} else if x := efaceOf(v); isInt(x.kind()) { } else if x := efaceOf(v); isInt(x.kind()) {
return x.toInt64(), true return x.toInt64(), true
} else { } else {
return 0, false return 0, false
} }
} }
func inRange(v interface{}, low int64, high int64) bool { func inRange(v interface{}, low int64, high int64) bool {
x, ok := asInt64(v) x, ok := asInt64(v)
return ok && x >= low && x <= high return ok && x >= low && x <= high
} }
func isSpecial(v interface{}) bool { func isSpecial(v interface{}) bool {
switch v.(type) { switch v.(type) {
case Register8 : return true case Register8:
case Register16 : return true return true
case Register32 : return true case Register16:
case Register64 : return true return true
case KRegister : return true case Register32:
case MMRegister : return true return true
case XMMRegister : return true case Register64:
case YMMRegister : return true return true
case ZMMRegister : return true case KRegister:
case RelativeOffset : return true return true
case RoundingControl : return true case MMRegister:
case ExceptionControl : return true return true
default : return false case XMMRegister:
} return true
case YMMRegister:
return true
case ZMMRegister:
return true
case RelativeOffset:
return true
case RoundingControl:
return true
case ExceptionControl:
return true
default:
return false
}
} }
func isIndexable(v interface{}) bool { func isIndexable(v interface{}) bool {
return isZMM(v) || isReg64(v) || isEVEXXMM(v) || isEVEXYMM(v) return isZMM(v) || isReg64(v) || isEVEXXMM(v) || isEVEXYMM(v)
} }
func isImm4 (v interface{}) bool { return inRange(v, 0, 15) } func isImm4(v interface{}) bool { return inRange(v, 0, 15) }
func isImm8 (v interface{}) bool { return inRange(v, math.MinInt8, math.MaxUint8) } func isImm8(v interface{}) bool { return inRange(v, math.MinInt8, math.MaxUint8) }
func isImm16 (v interface{}) bool { return inRange(v, math.MinInt16, math.MaxUint16) } func isImm16(v interface{}) bool { return inRange(v, math.MinInt16, math.MaxUint16) }
func isImm32 (v interface{}) bool { return inRange(v, math.MinInt32, math.MaxUint32) } func isImm32(v interface{}) bool { return inRange(v, math.MinInt32, math.MaxUint32) }
func isImm64 (v interface{}) bool { _, r := asInt64(v) ; return r } func isImm64(v interface{}) bool { _, r := asInt64(v); return r }
func isConst1 (v interface{}) bool { x, r := asInt64(v) ; return r && x == 1 } func isConst1(v interface{}) bool { x, r := asInt64(v); return r && x == 1 }
func isConst3 (v interface{}) bool { x, r := asInt64(v) ; return r && x == 3 } func isConst3(v interface{}) bool { x, r := asInt64(v); return r && x == 3 }
func isRel8 (v interface{}) bool { x, r := v.(RelativeOffset) ; return r && x >= math.MinInt8 && x <= math.MaxInt8 } func isRel8(v interface{}) bool {
func isRel32 (v interface{}) bool { _, r := v.(RelativeOffset) ; return r } x, r := v.(RelativeOffset)
func isLabel (v interface{}) bool { _, r := v.(*Label) ; return r } return r && x >= math.MinInt8 && x <= math.MaxInt8
func isReg8 (v interface{}) bool { _, r := v.(Register8) ; return r } }
func isReg8REX (v interface{}) bool { x, r := v.(Register8) ; return r && (x & 0x80) == 0 && x >= SPL } func isRel32(v interface{}) bool { _, r := v.(RelativeOffset); return r }
func isReg16 (v interface{}) bool { _, r := v.(Register16) ; return r } func isLabel(v interface{}) bool { _, r := v.(*Label); return r }
func isReg32 (v interface{}) bool { _, r := v.(Register32) ; return r } func isReg8(v interface{}) bool { _, r := v.(Register8); return r }
func isReg64 (v interface{}) bool { _, r := v.(Register64) ; return r } func isReg8REX(v interface{}) bool {
func isMM (v interface{}) bool { _, r := v.(MMRegister) ; return r } x, r := v.(Register8)
func isXMM (v interface{}) bool { x, r := v.(XMMRegister) ; return r && x <= XMM15 } return r && (x&0x80) == 0 && x >= SPL
func isEVEXXMM (v interface{}) bool { _, r := v.(XMMRegister) ; return r } }
func isXMMk (v interface{}) bool { x, r := v.(MaskedRegister) ; return isXMM(v) || (r && isXMM(x.Reg) && !x.Mask.Z) } func isReg16(v interface{}) bool { _, r := v.(Register16); return r }
func isXMMkz (v interface{}) bool { x, r := v.(MaskedRegister) ; return isXMM(v) || (r && isXMM(x.Reg)) } func isReg32(v interface{}) bool { _, r := v.(Register32); return r }
func isYMM (v interface{}) bool { x, r := v.(YMMRegister) ; return r && x <= YMM15 } func isReg64(v interface{}) bool { _, r := v.(Register64); return r }
func isEVEXYMM (v interface{}) bool { _, r := v.(YMMRegister) ; return r } func isMM(v interface{}) bool { _, r := v.(MMRegister); return r }
func isYMMk (v interface{}) bool { x, r := v.(MaskedRegister) ; return isYMM(v) || (r && isYMM(x.Reg) && !x.Mask.Z) } func isXMM(v interface{}) bool { x, r := v.(XMMRegister); return r && x <= XMM15 }
func isYMMkz (v interface{}) bool { x, r := v.(MaskedRegister) ; return isYMM(v) || (r && isYMM(x.Reg)) } func isEVEXXMM(v interface{}) bool { _, r := v.(XMMRegister); return r }
func isZMM (v interface{}) bool { _, r := v.(ZMMRegister) ; return r } func isXMMk(v interface{}) bool {
func isZMMk (v interface{}) bool { x, r := v.(MaskedRegister) ; return isZMM(v) || (r && isZMM(x.Reg) && !x.Mask.Z) } x, r := v.(MaskedRegister)
func isZMMkz (v interface{}) bool { x, r := v.(MaskedRegister) ; return isZMM(v) || (r && isZMM(x.Reg)) } return isXMM(v) || (r && isXMM(x.Reg) && !x.Mask.Z)
func isK (v interface{}) bool { _, r := v.(KRegister) ; return r } }
func isKk (v interface{}) bool { x, r := v.(MaskedRegister) ; return isK(v) || (r && isK(x.Reg) && !x.Mask.Z) } func isXMMkz(v interface{}) bool {
func isM (v interface{}) bool { x, r := v.(*MemoryOperand) ; return r && x.isMem() && x.Broadcast == 0 && !x.Masked } x, r := v.(MaskedRegister)
func isMk (v interface{}) bool { x, r := v.(*MemoryOperand) ; return r && x.isMem() && x.Broadcast == 0 && !(x.Masked && x.Mask.Z) } return isXMM(v) || (r && isXMM(x.Reg))
func isMkz (v interface{}) bool { x, r := v.(*MemoryOperand) ; return r && x.isMem() && x.Broadcast == 0 } }
func isM8 (v interface{}) bool { x, r := v.(*MemoryOperand) ; return r && isM(v) && x.isSize(1) } func isYMM(v interface{}) bool { x, r := v.(YMMRegister); return r && x <= YMM15 }
func isM16 (v interface{}) bool { x, r := v.(*MemoryOperand) ; return r && isM(v) && x.isSize(2) } func isEVEXYMM(v interface{}) bool { _, r := v.(YMMRegister); return r }
func isM16kz (v interface{}) bool { x, r := v.(*MemoryOperand) ; return r && isMkz(v) && x.isSize(2) } func isYMMk(v interface{}) bool {
func isM32 (v interface{}) bool { x, r := v.(*MemoryOperand) ; return r && isM(v) && x.isSize(4) } x, r := v.(MaskedRegister)
func isM32k (v interface{}) bool { x, r := v.(*MemoryOperand) ; return r && isMk(v) && x.isSize(4) } return isYMM(v) || (r && isYMM(x.Reg) && !x.Mask.Z)
func isM32kz (v interface{}) bool { x, r := v.(*MemoryOperand) ; return r && isMkz(v) && x.isSize(4) } }
func isM64 (v interface{}) bool { x, r := v.(*MemoryOperand) ; return r && isM(v) && x.isSize(8) } func isYMMkz(v interface{}) bool {
func isM64k (v interface{}) bool { x, r := v.(*MemoryOperand) ; return r && isMk(v) && x.isSize(8) } x, r := v.(MaskedRegister)
func isM64kz (v interface{}) bool { x, r := v.(*MemoryOperand) ; return r && isMkz(v) && x.isSize(8) } return isYMM(v) || (r && isYMM(x.Reg))
func isM128 (v interface{}) bool { x, r := v.(*MemoryOperand) ; return r && isM(v) && x.isSize(16) } }
func isM128kz (v interface{}) bool { x, r := v.(*MemoryOperand) ; return r && isMkz(v) && x.isSize(16) } func isZMM(v interface{}) bool { _, r := v.(ZMMRegister); return r }
func isM256 (v interface{}) bool { x, r := v.(*MemoryOperand) ; return r && isM(v) && x.isSize(32) } func isZMMk(v interface{}) bool {
func isM256kz (v interface{}) bool { x, r := v.(*MemoryOperand) ; return r && isMkz(v) && x.isSize(32) } x, r := v.(MaskedRegister)
func isM512 (v interface{}) bool { x, r := v.(*MemoryOperand) ; return r && isM(v) && x.isSize(64) } return isZMM(v) || (r && isZMM(x.Reg) && !x.Mask.Z)
func isM512kz (v interface{}) bool { x, r := v.(*MemoryOperand) ; return r && isMkz(v) && x.isSize(64) } }
func isM64M32bcst (v interface{}) bool { x, r := v.(*MemoryOperand) ; return isM64(v) || (r && x.isBroadcast(4, 2)) } func isZMMkz(v interface{}) bool {
func isM128M32bcst (v interface{}) bool { x, r := v.(*MemoryOperand) ; return isM128(v) || (r && x.isBroadcast(4, 4)) } x, r := v.(MaskedRegister)
func isM256M32bcst (v interface{}) bool { x, r := v.(*MemoryOperand) ; return isM256(v) || (r && x.isBroadcast(4, 8)) } return isZMM(v) || (r && isZMM(x.Reg))
func isM512M32bcst (v interface{}) bool { x, r := v.(*MemoryOperand) ; return isM512(v) || (r && x.isBroadcast(4, 16)) } }
func isM128M64bcst (v interface{}) bool { x, r := v.(*MemoryOperand) ; return isM128(v) || (r && x.isBroadcast(8, 2)) } func isK(v interface{}) bool { _, r := v.(KRegister); return r }
func isM256M64bcst (v interface{}) bool { x, r := v.(*MemoryOperand) ; return isM256(v) || (r && x.isBroadcast(8, 4)) } func isKk(v interface{}) bool {
func isM512M64bcst (v interface{}) bool { x, r := v.(*MemoryOperand) ; return isM512(v) || (r && x.isBroadcast(8, 8)) } x, r := v.(MaskedRegister)
func isVMX (v interface{}) bool { x, r := v.(*MemoryOperand) ; return r && x.isVMX(false) && !x.Masked } return isK(v) || (r && isK(x.Reg) && !x.Mask.Z)
func isEVEXVMX (v interface{}) bool { x, r := v.(*MemoryOperand) ; return r && x.isVMX(true) && !x.Masked } }
func isVMXk (v interface{}) bool { x, r := v.(*MemoryOperand) ; return r && x.isVMX(true) } func isM(v interface{}) bool {
func isVMY (v interface{}) bool { x, r := v.(*MemoryOperand) ; return r && x.isVMY(false) && !x.Masked } x, r := v.(*MemoryOperand)
func isEVEXVMY (v interface{}) bool { x, r := v.(*MemoryOperand) ; return r && x.isVMY(true) && !x.Masked } return r && x.isMem() && x.Broadcast == 0 && !x.Masked
func isVMYk (v interface{}) bool { x, r := v.(*MemoryOperand) ; return r && x.isVMY(true) } }
func isVMZ (v interface{}) bool { x, r := v.(*MemoryOperand) ; return r && x.isVMZ() && !x.Masked } func isMk(v interface{}) bool {
func isVMZk (v interface{}) bool { x, r := v.(*MemoryOperand) ; return r && x.isVMZ() } x, r := v.(*MemoryOperand)
func isSAE (v interface{}) bool { _, r := v.(ExceptionControl) ; return r } return r && x.isMem() && x.Broadcast == 0 && !(x.Masked && x.Mask.Z)
func isER (v interface{}) bool { _, r := v.(RoundingControl) ; return r } }
func isMkz(v interface{}) bool {
x, r := v.(*MemoryOperand)
return r && x.isMem() && x.Broadcast == 0
}
func isM8(v interface{}) bool {
x, r := v.(*MemoryOperand)
return r && isM(v) && x.isSize(1)
}
func isM16(v interface{}) bool {
x, r := v.(*MemoryOperand)
return r && isM(v) && x.isSize(2)
}
func isM16kz(v interface{}) bool {
x, r := v.(*MemoryOperand)
return r && isMkz(v) && x.isSize(2)
}
func isM32(v interface{}) bool {
x, r := v.(*MemoryOperand)
return r && isM(v) && x.isSize(4)
}
func isM32k(v interface{}) bool {
x, r := v.(*MemoryOperand)
return r && isMk(v) && x.isSize(4)
}
func isM32kz(v interface{}) bool {
x, r := v.(*MemoryOperand)
return r && isMkz(v) && x.isSize(4)
}
func isM64(v interface{}) bool {
x, r := v.(*MemoryOperand)
return r && isM(v) && x.isSize(8)
}
func isM64k(v interface{}) bool {
x, r := v.(*MemoryOperand)
return r && isMk(v) && x.isSize(8)
}
func isM64kz(v interface{}) bool {
x, r := v.(*MemoryOperand)
return r && isMkz(v) && x.isSize(8)
}
func isM128(v interface{}) bool {
x, r := v.(*MemoryOperand)
return r && isM(v) && x.isSize(16)
}
func isM128kz(v interface{}) bool {
x, r := v.(*MemoryOperand)
return r && isMkz(v) && x.isSize(16)
}
func isM256(v interface{}) bool {
x, r := v.(*MemoryOperand)
return r && isM(v) && x.isSize(32)
}
func isM256kz(v interface{}) bool {
x, r := v.(*MemoryOperand)
return r && isMkz(v) && x.isSize(32)
}
func isM512(v interface{}) bool {
x, r := v.(*MemoryOperand)
return r && isM(v) && x.isSize(64)
}
func isM512kz(v interface{}) bool {
x, r := v.(*MemoryOperand)
return r && isMkz(v) && x.isSize(64)
}
func isM64M32bcst(v interface{}) bool {
x, r := v.(*MemoryOperand)
return isM64(v) || (r && x.isBroadcast(4, 2))
}
func isM128M32bcst(v interface{}) bool {
x, r := v.(*MemoryOperand)
return isM128(v) || (r && x.isBroadcast(4, 4))
}
func isM256M32bcst(v interface{}) bool {
x, r := v.(*MemoryOperand)
return isM256(v) || (r && x.isBroadcast(4, 8))
}
func isM512M32bcst(v interface{}) bool {
x, r := v.(*MemoryOperand)
return isM512(v) || (r && x.isBroadcast(4, 16))
}
func isM128M64bcst(v interface{}) bool {
x, r := v.(*MemoryOperand)
return isM128(v) || (r && x.isBroadcast(8, 2))
}
func isM256M64bcst(v interface{}) bool {
x, r := v.(*MemoryOperand)
return isM256(v) || (r && x.isBroadcast(8, 4))
}
func isM512M64bcst(v interface{}) bool {
x, r := v.(*MemoryOperand)
return isM512(v) || (r && x.isBroadcast(8, 8))
}
func isVMX(v interface{}) bool {
x, r := v.(*MemoryOperand)
return r && x.isVMX(false) && !x.Masked
}
func isEVEXVMX(v interface{}) bool {
x, r := v.(*MemoryOperand)
return r && x.isVMX(true) && !x.Masked
}
func isVMXk(v interface{}) bool { x, r := v.(*MemoryOperand); return r && x.isVMX(true) }
func isVMY(v interface{}) bool {
x, r := v.(*MemoryOperand)
return r && x.isVMY(false) && !x.Masked
}
func isEVEXVMY(v interface{}) bool {
x, r := v.(*MemoryOperand)
return r && x.isVMY(true) && !x.Masked
}
func isVMYk(v interface{}) bool { x, r := v.(*MemoryOperand); return r && x.isVMY(true) }
func isVMZ(v interface{}) bool {
x, r := v.(*MemoryOperand)
return r && x.isVMZ() && !x.Masked
}
func isVMZk(v interface{}) bool { x, r := v.(*MemoryOperand); return r && x.isVMZ() }
func isSAE(v interface{}) bool { _, r := v.(ExceptionControl); return r }
func isER(v interface{}) bool { _, r := v.(RoundingControl); return r }
func isImmExt(v interface{}, ext int, min int64, max int64) bool { func isImmExt(v interface{}, ext int, min int64, max int64) bool {
if x, ok := asInt64(v); !ok { if x, ok := asInt64(v); !ok {
return false return false
} else if m := int64(1) << (8 * ext); x < m && x >= m + min { } else if m := int64(1) << (8 * ext); x < m && x >= m+min {
return true return true
} else { } else {
return x <= max && x >= min return x <= max && x >= min
} }
} }
func isImm8Ext(v interface{}, ext int) bool { func isImm8Ext(v interface{}, ext int) bool {
return isImmExt(v, ext, math.MinInt8, math.MaxInt8) return isImmExt(v, ext, math.MinInt8, math.MaxInt8)
} }
func isImm32Ext(v interface{}, ext int) bool { func isImm32Ext(v interface{}, ext int) bool {
return isImmExt(v, ext, math.MinInt32, math.MaxInt32) return isImmExt(v, ext, math.MinInt32, math.MaxInt32)
} }

View File

@ -1,117 +1,38 @@
package x86_64 package x86_64
import (
`sync`
)
var (
labelPool sync.Pool
programPool sync.Pool
instructionPool sync.Pool
memoryOperandPool sync.Pool
)
func freeLabel(v *Label) {
labelPool.Put(v)
}
func clearLabel(p *Label) *Label {
*p = Label{}
return p
}
// CreateLabel creates a new Label, it may allocate a new one or grab one from a pool. // CreateLabel creates a new Label, it may allocate a new one or grab one from a pool.
func CreateLabel(name string) *Label { func CreateLabel(name string) *Label {
var p *Label p := new(Label)
var v interface{}
/* attempt to grab from the pool */ /* initialize the label */
if v = labelPool.Get(); v == nil { p.refs = 1
p = new(Label) p.Name = name
} else { return p
p = clearLabel(v.(*Label))
}
/* initialize the label */
p.refs = 1
p.Name = name
return p
} }
func newProgram(arch *Arch) *Program { func newProgram(arch *Arch) *Program {
var p *Program p := new(Program)
var v interface{}
/* attempt to grab from the pool */ /* initialize the program */
if v = programPool.Get(); v == nil { p.arch = arch
p = new(Program) return p
} else {
p = clearProgram(v.(*Program))
}
/* initialize the program */
p.arch = arch
return p
}
func freeProgram(p *Program) {
programPool.Put(p)
}
func clearProgram(p *Program) *Program {
*p = Program{}
return p
} }
func newInstruction(name string, argc int, argv Operands) *Instruction { func newInstruction(name string, argc int, argv Operands) *Instruction {
var v interface{} p := new(Instruction)
var p *Instruction
/* attempt to grab from the pool */ /* initialize the instruction */
if v = instructionPool.Get(); v == nil { p.name = name
p = new(Instruction) p.argc = argc
} else { p.argv = argv
p = clearInstruction(v.(*Instruction)) return p
}
/* initialize the instruction */
p.name = name
p.argc = argc
p.argv = argv
return p
}
func freeInstruction(v *Instruction) {
instructionPool.Put(v)
}
func clearInstruction(p *Instruction) *Instruction {
*p = Instruction { prefix: p.prefix[:0] }
return p
}
func freeMemoryOperand(m *MemoryOperand) {
memoryOperandPool.Put(m)
}
func clearMemoryOperand(m *MemoryOperand) *MemoryOperand {
*m = MemoryOperand{}
return m
} }
// CreateMemoryOperand creates a new MemoryOperand, it may allocate a new one or grab one from a pool. // CreateMemoryOperand creates a new MemoryOperand, it may allocate a new one or grab one from a pool.
func CreateMemoryOperand() *MemoryOperand { func CreateMemoryOperand() *MemoryOperand {
var v interface{} p := new(MemoryOperand)
var p *MemoryOperand
/* attempt to grab from the pool */ /* initialize the memory operand */
if v = memoryOperandPool.Get(); v == nil { p.refs = 1
p = new(MemoryOperand) return p
} else {
p = clearMemoryOperand(v.(*MemoryOperand))
}
/* initialize the memory operand */
p.refs = 1
return p
} }

View File

@ -1,127 +1,149 @@
package x86_64 package x86_64
import ( import (
`fmt` "fmt"
`math` "math"
`math/bits` "math/bits"
`github.com/chenzhuoyu/iasm/expr` "github.com/chenzhuoyu/iasm/expr"
) )
type ( type (
_PseudoType int _PseudoType int
_InstructionEncoder func(*Program, ...interface{}) *Instruction _InstructionEncoder func(*Program, ...interface{}) *Instruction
) )
const ( const (
_PseudoNop _PseudoType = iota + 1 _PseudoNop _PseudoType = iota + 1
_PseudoByte _PseudoByte
_PseudoWord _PseudoWord
_PseudoLong _PseudoLong
_PseudoQuad _PseudoQuad
_PseudoData _PseudoData
_PseudoAlign _PseudoAlign
) )
func (self _PseudoType) String() string { func (self _PseudoType) String() string {
switch self { switch self {
case _PseudoNop : return ".nop" case _PseudoNop:
case _PseudoByte : return ".byte" return ".nop"
case _PseudoWord : return ".word" case _PseudoByte:
case _PseudoLong : return ".long" return ".byte"
case _PseudoQuad : return ".quad" case _PseudoWord:
case _PseudoData : return ".data" return ".word"
case _PseudoAlign : return ".align" case _PseudoLong:
default : panic("unreachable") return ".long"
} case _PseudoQuad:
return ".quad"
case _PseudoData:
return ".data"
case _PseudoAlign:
return ".align"
default:
panic("unreachable")
}
} }
type _Pseudo struct { type _Pseudo struct {
kind _PseudoType kind _PseudoType
data []byte data []byte
uint uint64 uint uint64
expr *expr.Expr expr *expr.Expr
} }
func (self *_Pseudo) free() { func (self *_Pseudo) free() {
if self.expr != nil { if self.expr != nil {
self.expr.Free() self.expr.Free()
} }
} }
func (self *_Pseudo) encode(m *[]byte, pc uintptr) int { func (self *_Pseudo) encode(m *[]byte, pc uintptr) int {
switch self.kind { switch self.kind {
case _PseudoNop : return 0 case _PseudoNop:
case _PseudoByte : self.encodeByte(m) ; return 1 return 0
case _PseudoWord : self.encodeWord(m) ; return 2 case _PseudoByte:
case _PseudoLong : self.encodeLong(m) ; return 4 self.encodeByte(m)
case _PseudoQuad : self.encodeQuad(m) ; return 8 return 1
case _PseudoData : self.encodeData(m) ; return len(self.data) case _PseudoWord:
case _PseudoAlign : self.encodeAlign(m, pc) ; return self.alignSize(pc) self.encodeWord(m)
default : panic("invalid pseudo instruction") return 2
} case _PseudoLong:
self.encodeLong(m)
return 4
case _PseudoQuad:
self.encodeQuad(m)
return 8
case _PseudoData:
self.encodeData(m)
return len(self.data)
case _PseudoAlign:
self.encodeAlign(m, pc)
return self.alignSize(pc)
default:
panic("invalid pseudo instruction")
}
} }
func (self *_Pseudo) evalExpr(low int64, high int64) int64 { func (self *_Pseudo) evalExpr(low int64, high int64) int64 {
if v, err := self.expr.Evaluate(); err != nil { if v, err := self.expr.Evaluate(); err != nil {
panic(err) panic(err)
} else if v < low || v > high { } else if v < low || v > high {
panic(fmt.Sprintf("expression out of range [%d, %d]: %d", low, high, v)) panic(fmt.Sprintf("expression out of range [%d, %d]: %d", low, high, v))
} else { } else {
return v return v
} }
} }
func (self *_Pseudo) alignSize(pc uintptr) int { func (self *_Pseudo) alignSize(pc uintptr) int {
if !ispow2(self.uint) { if !ispow2(self.uint) {
panic(fmt.Sprintf("aligment should be a power of 2, not %d", self.uint)) panic(fmt.Sprintf("aligment should be a power of 2, not %d", self.uint))
} else { } else {
return align(int(pc), bits.TrailingZeros64(self.uint)) - int(pc) return align(int(pc), bits.TrailingZeros64(self.uint)) - int(pc)
} }
} }
func (self *_Pseudo) encodeData(m *[]byte) { func (self *_Pseudo) encodeData(m *[]byte) {
if m != nil { if m != nil {
*m = append(*m, self.data...) *m = append(*m, self.data...)
} }
} }
func (self *_Pseudo) encodeByte(m *[]byte) { func (self *_Pseudo) encodeByte(m *[]byte) {
if m != nil { if m != nil {
append8(m, byte(self.evalExpr(math.MinInt8, math.MaxUint8))) append8(m, byte(self.evalExpr(math.MinInt8, math.MaxUint8)))
} }
} }
func (self *_Pseudo) encodeWord(m *[]byte) { func (self *_Pseudo) encodeWord(m *[]byte) {
if m != nil { if m != nil {
append16(m, uint16(self.evalExpr(math.MinInt16, math.MaxUint16))) append16(m, uint16(self.evalExpr(math.MinInt16, math.MaxUint16)))
} }
} }
func (self *_Pseudo) encodeLong(m *[]byte) { func (self *_Pseudo) encodeLong(m *[]byte) {
if m != nil { if m != nil {
append32(m, uint32(self.evalExpr(math.MinInt32, math.MaxUint32))) append32(m, uint32(self.evalExpr(math.MinInt32, math.MaxUint32)))
} }
} }
func (self *_Pseudo) encodeQuad(m *[]byte) { func (self *_Pseudo) encodeQuad(m *[]byte) {
if m != nil { if m != nil {
if v, err := self.expr.Evaluate(); err != nil { if v, err := self.expr.Evaluate(); err != nil {
panic(err) panic(err)
} else { } else {
append64(m, uint64(v)) append64(m, uint64(v))
} }
} }
} }
func (self *_Pseudo) encodeAlign(m *[]byte, pc uintptr) { func (self *_Pseudo) encodeAlign(m *[]byte, pc uintptr) {
if m != nil { if m != nil {
if self.expr == nil { if self.expr == nil {
expandmm(m, self.alignSize(pc), 0) expandmm(m, self.alignSize(pc), 0)
} else { } else {
expandmm(m, self.alignSize(pc), byte(self.evalExpr(math.MinInt8, math.MaxUint8))) expandmm(m, self.alignSize(pc), byte(self.evalExpr(math.MinInt8, math.MaxUint8)))
} }
} }
} }
// Operands represents a sequence of operand required by an instruction. // Operands represents a sequence of operand required by an instruction.
@ -131,15 +153,15 @@ type Operands [_N_args]interface{}
type InstructionDomain uint8 type InstructionDomain uint8
const ( const (
DomainGeneric InstructionDomain = iota DomainGeneric InstructionDomain = iota
DomainMMXSSE DomainMMXSSE
DomainAVX DomainAVX
DomainFMA DomainFMA
DomainCrypto DomainCrypto
DomainMask DomainMask
DomainAMDSpecific DomainAMDSpecific
DomainMisc DomainMisc
DomainPseudo DomainPseudo
) )
type ( type (
@ -147,139 +169,139 @@ type (
) )
const ( const (
_B_none _BranchType = iota _B_none _BranchType = iota
_B_conditional _B_conditional
_B_unconditional _B_unconditional
) )
// Instruction represents an unencoded instruction. // Instruction represents an unencoded instruction.
type Instruction struct { type Instruction struct {
next *Instruction next *Instruction
pc uintptr pc uintptr
nb int nb int
len int len int
argc int argc int
name string name string
argv Operands argv Operands
forms [_N_forms]_Encoding forms [_N_forms]_Encoding
pseudo _Pseudo pseudo _Pseudo
branch _BranchType branch _BranchType
domain InstructionDomain domain InstructionDomain
prefix []byte prefix []byte
} }
func (self *Instruction) add(flags int, encoder func(m *_Encoding, v []interface{})) { func (self *Instruction) add(flags int, encoder func(m *_Encoding, v []interface{})) {
self.forms[self.len].flags = flags self.forms[self.len].flags = flags
self.forms[self.len].encoder = encoder self.forms[self.len].encoder = encoder
self.len++ self.len++
} }
func (self *Instruction) free() { func (self *Instruction) free() {
self.clear() self.clear()
self.pseudo.free() self.pseudo.free()
freeInstruction(self) //freeInstruction(self)
} }
func (self *Instruction) clear() { func (self *Instruction) clear() {
for i := 0; i < self.argc; i++ { for i := 0; i < self.argc; i++ {
if v, ok := self.argv[i].(Disposable); ok { if v, ok := self.argv[i].(Disposable); ok {
v.Free() v.Free()
} }
} }
} }
func (self *Instruction) check(e *_Encoding) bool { func (self *Instruction) check(e *_Encoding) bool {
if (e.flags & _F_rel1) != 0 { if (e.flags & _F_rel1) != 0 {
return isRel8(self.argv[0]) return isRel8(self.argv[0])
} else if (e.flags & _F_rel4) != 0 { } else if (e.flags & _F_rel4) != 0 {
return isRel32(self.argv[0]) || isLabel(self.argv[0]) return isRel32(self.argv[0]) || isLabel(self.argv[0])
} else { } else {
return true return true
} }
} }
func (self *Instruction) encode(m *[]byte) int { func (self *Instruction) encode(m *[]byte) int {
n := math.MaxInt64 n := math.MaxInt64
p := (*_Encoding)(nil) p := (*_Encoding)(nil)
/* encode prefixes if any */ /* encode prefixes if any */
if self.nb = len(self.prefix); m != nil { if self.nb = len(self.prefix); m != nil {
*m = append(*m, self.prefix...) *m = append(*m, self.prefix...)
} }
/* check for pseudo-instructions */ /* check for pseudo-instructions */
if self.pseudo.kind != 0 { if self.pseudo.kind != 0 {
self.nb += self.pseudo.encode(m, self.pc) self.nb += self.pseudo.encode(m, self.pc)
return self.nb return self.nb
} }
/* find the shortest encoding */ /* find the shortest encoding */
for i := 0; i < self.len; i++ { for i := 0; i < self.len; i++ {
if e := &self.forms[i]; self.check(e) { if e := &self.forms[i]; self.check(e) {
if v := e.encode(self.argv[:self.argc]); v < n { if v := e.encode(self.argv[:self.argc]); v < n {
n = v n = v
p = e p = e
} }
} }
} }
/* add to buffer if needed */ /* add to buffer if needed */
if m != nil { if m != nil {
*m = append(*m, p.bytes[:n]...) *m = append(*m, p.bytes[:n]...)
} }
/* update the instruction length */ /* update the instruction length */
self.nb += n self.nb += n
return self.nb return self.nb
} }
/** Instruction Prefixes **/ /** Instruction Prefixes **/
const ( const (
_P_cs = 0x2e _P_cs = 0x2e
_P_ds = 0x3e _P_ds = 0x3e
_P_es = 0x26 _P_es = 0x26
_P_fs = 0x64 _P_fs = 0x64
_P_gs = 0x65 _P_gs = 0x65
_P_ss = 0x36 _P_ss = 0x36
_P_lock = 0xf0 _P_lock = 0xf0
) )
// CS overrides the memory operation of this instruction to CS. // CS overrides the memory operation of this instruction to CS.
func (self *Instruction) CS() *Instruction { func (self *Instruction) CS() *Instruction {
self.prefix = append(self.prefix, _P_cs) self.prefix = append(self.prefix, _P_cs)
return self return self
} }
// DS overrides the memory operation of this instruction to DS, // DS overrides the memory operation of this instruction to DS,
// this is the default section for most instructions if not specified. // this is the default section for most instructions if not specified.
func (self *Instruction) DS() *Instruction { func (self *Instruction) DS() *Instruction {
self.prefix = append(self.prefix, _P_ds) self.prefix = append(self.prefix, _P_ds)
return self return self
} }
// ES overrides the memory operation of this instruction to ES. // ES overrides the memory operation of this instruction to ES.
func (self *Instruction) ES() *Instruction { func (self *Instruction) ES() *Instruction {
self.prefix = append(self.prefix, _P_es) self.prefix = append(self.prefix, _P_es)
return self return self
} }
// FS overrides the memory operation of this instruction to FS. // FS overrides the memory operation of this instruction to FS.
func (self *Instruction) FS() *Instruction { func (self *Instruction) FS() *Instruction {
self.prefix = append(self.prefix, _P_fs) self.prefix = append(self.prefix, _P_fs)
return self return self
} }
// GS overrides the memory operation of this instruction to GS. // GS overrides the memory operation of this instruction to GS.
func (self *Instruction) GS() *Instruction { func (self *Instruction) GS() *Instruction {
self.prefix = append(self.prefix, _P_gs) self.prefix = append(self.prefix, _P_gs)
return self return self
} }
// SS overrides the memory operation of this instruction to SS. // SS overrides the memory operation of this instruction to SS.
func (self *Instruction) SS() *Instruction { func (self *Instruction) SS() *Instruction {
self.prefix = append(self.prefix, _P_ss) self.prefix = append(self.prefix, _P_ss)
return self return self
} }
// LOCK causes the processor's LOCK# signal to be asserted during execution of // LOCK causes the processor's LOCK# signal to be asserted during execution of
@ -287,128 +309,132 @@ func (self *Instruction) SS() *Instruction {
// In a multiprocessor environment, the LOCK# signal insures that the processor // In a multiprocessor environment, the LOCK# signal insures that the processor
// has exclusive use of any shared memory while the signal is asserted. // has exclusive use of any shared memory while the signal is asserted.
func (self *Instruction) LOCK() *Instruction { func (self *Instruction) LOCK() *Instruction {
self.prefix = append(self.prefix, _P_lock) self.prefix = append(self.prefix, _P_lock)
return self return self
} }
/** Basic Instruction Properties **/ /** Basic Instruction Properties **/
// Name returns the instruction name. // Name returns the instruction name.
func (self *Instruction) Name() string { func (self *Instruction) Name() string {
return self.name return self.name
} }
// Domain returns the domain of this instruction. // Domain returns the domain of this instruction.
func (self *Instruction) Domain() InstructionDomain { func (self *Instruction) Domain() InstructionDomain {
return self.domain return self.domain
} }
// Operands returns the operands of this instruction. // Operands returns the operands of this instruction.
func (self *Instruction) Operands() []interface{} { func (self *Instruction) Operands() []interface{} {
return self.argv[:self.argc] return self.argv[:self.argc]
} }
// Program represents a sequence of instructions. // Program represents a sequence of instructions.
type Program struct { type Program struct {
arch *Arch arch *Arch
head *Instruction head *Instruction
tail *Instruction tail *Instruction
} }
const ( const (
_N_near = 2 // near-branch (-128 ~ +127) takes 2 bytes to encode _N_near = 2 // near-branch (-128 ~ +127) takes 2 bytes to encode
_N_far_cond = 6 // conditional far-branch takes 6 bytes to encode _N_far_cond = 6 // conditional far-branch takes 6 bytes to encode
_N_far_uncond = 5 // unconditional far-branch takes 5 bytes to encode _N_far_uncond = 5 // unconditional far-branch takes 5 bytes to encode
) )
func (self *Program) clear() { func (self *Program) clear() {
for p, q := self.head, self.head; p != nil; p = q { for p, q := self.head, self.head; p != nil; p = q {
q = p.next q = p.next
p.free() p.free()
} }
} }
func (self *Program) alloc(name string, argc int, argv Operands) *Instruction { func (self *Program) alloc(name string, argc int, argv Operands) *Instruction {
p := self.tail p := self.tail
q := newInstruction(name, argc, argv) q := newInstruction(name, argc, argv)
/* attach to tail if any */ /* attach to tail if any */
if p != nil { if p != nil {
p.next = q p.next = q
} else { } else {
self.head = q self.head = q
} }
/* set the new tail */ /* set the new tail */
self.tail = q self.tail = q
return q return q
} }
func (self *Program) pseudo(kind _PseudoType) (p *Instruction) { func (self *Program) pseudo(kind _PseudoType) (p *Instruction) {
p = self.alloc(kind.String(), 0, Operands{}) p = self.alloc(kind.String(), 0, Operands{})
p.domain = DomainPseudo p.domain = DomainPseudo
p.pseudo.kind = kind p.pseudo.kind = kind
return return
} }
func (self *Program) require(isa ISA) { func (self *Program) require(isa ISA) {
if !self.arch.HasISA(isa) { if !self.arch.HasISA(isa) {
panic("ISA '" + isa.String() + "' was not enabled") panic("ISA '" + isa.String() + "' was not enabled")
} }
} }
func (self *Program) branchSize(p *Instruction) int { func (self *Program) branchSize(p *Instruction) int {
switch p.branch { switch p.branch {
case _B_none : panic("p is not a branch") case _B_none:
case _B_conditional : return _N_far_cond panic("p is not a branch")
case _B_unconditional : return _N_far_uncond case _B_conditional:
default : panic("invalid instruction") return _N_far_cond
} case _B_unconditional:
return _N_far_uncond
default:
panic("invalid instruction")
}
} }
/** Pseudo-Instructions **/ /** Pseudo-Instructions **/
// Byte is a pseudo-instruction to add raw byte to the assembled code. // Byte is a pseudo-instruction to add raw byte to the assembled code.
func (self *Program) Byte(v *expr.Expr) (p *Instruction) { func (self *Program) Byte(v *expr.Expr) (p *Instruction) {
p = self.pseudo(_PseudoByte) p = self.pseudo(_PseudoByte)
p.pseudo.expr = v p.pseudo.expr = v
return return
} }
// Word is a pseudo-instruction to add raw uint16 as little-endian to the assembled code. // Word is a pseudo-instruction to add raw uint16 as little-endian to the assembled code.
func (self *Program) Word(v *expr.Expr) (p *Instruction) { func (self *Program) Word(v *expr.Expr) (p *Instruction) {
p = self.pseudo(_PseudoWord) p = self.pseudo(_PseudoWord)
p.pseudo.expr = v p.pseudo.expr = v
return return
} }
// Long is a pseudo-instruction to add raw uint32 as little-endian to the assembled code. // Long is a pseudo-instruction to add raw uint32 as little-endian to the assembled code.
func (self *Program) Long(v *expr.Expr) (p *Instruction) { func (self *Program) Long(v *expr.Expr) (p *Instruction) {
p = self.pseudo(_PseudoLong) p = self.pseudo(_PseudoLong)
p.pseudo.expr = v p.pseudo.expr = v
return return
} }
// Quad is a pseudo-instruction to add raw uint64 as little-endian to the assembled code. // Quad is a pseudo-instruction to add raw uint64 as little-endian to the assembled code.
func (self *Program) Quad(v *expr.Expr) (p *Instruction) { func (self *Program) Quad(v *expr.Expr) (p *Instruction) {
p = self.pseudo(_PseudoQuad) p = self.pseudo(_PseudoQuad)
p.pseudo.expr = v p.pseudo.expr = v
return return
} }
// Data is a pseudo-instruction to add raw bytes to the assembled code. // Data is a pseudo-instruction to add raw bytes to the assembled code.
func (self *Program) Data(v []byte) (p *Instruction) { func (self *Program) Data(v []byte) (p *Instruction) {
p = self.pseudo(_PseudoData) p = self.pseudo(_PseudoData)
p.pseudo.data = v p.pseudo.data = v
return return
} }
// Align is a pseudo-instruction to ensure the PC is aligned to a certain value. // Align is a pseudo-instruction to ensure the PC is aligned to a certain value.
func (self *Program) Align(align uint64, padding *expr.Expr) (p *Instruction) { func (self *Program) Align(align uint64, padding *expr.Expr) (p *Instruction) {
p = self.pseudo(_PseudoAlign) p = self.pseudo(_PseudoAlign)
p.pseudo.uint = align p.pseudo.uint = align
p.pseudo.expr = padding p.pseudo.expr = padding
return return
} }
/** Program Assembler **/ /** Program Assembler **/
@ -417,126 +443,126 @@ func (self *Program) Align(align uint64, padding *expr.Expr) (p *Instruction) {
// Any operation performed after Free is undefined behavior. // Any operation performed after Free is undefined behavior.
// //
// NOTE: This also frees all the instructions, labels, memory // NOTE: This also frees all the instructions, labels, memory
// operands and expressions associated with this program.
// //
// operands and expressions associated with this program.
func (self *Program) Free() { func (self *Program) Free() {
self.clear() self.clear()
freeProgram(self) //freeProgram(self)
} }
// Link pins a label at the current position. // Link pins a label at the current position.
func (self *Program) Link(p *Label) { func (self *Program) Link(p *Label) {
if p.Dest != nil { if p.Dest != nil {
panic("lable was alreay linked") panic("lable was alreay linked")
} else { } else {
p.Dest = self.pseudo(_PseudoNop) p.Dest = self.pseudo(_PseudoNop)
} }
} }
// Assemble assembles and links the entire program into machine code. // Assemble assembles and links the entire program into machine code.
func (self *Program) Assemble(pc uintptr) (ret []byte) { func (self *Program) Assemble(pc uintptr) (ret []byte) {
orig := pc orig := pc
next := true next := true
offs := uintptr(0) offs := uintptr(0)
/* Pass 0: PC-precompute, assume all labeled branches are far-branches. */ /* Pass 0: PC-precompute, assume all labeled branches are far-branches. */
for p := self.head; p != nil; p = p.next { for p := self.head; p != nil; p = p.next {
if p.pc = pc; !isLabel(p.argv[0]) || p.branch == _B_none { if p.pc = pc; !isLabel(p.argv[0]) || p.branch == _B_none {
pc += uintptr(p.encode(nil)) pc += uintptr(p.encode(nil))
} else { } else {
pc += uintptr(self.branchSize(p)) pc += uintptr(self.branchSize(p))
} }
} }
/* allocate space for the machine code */ /* allocate space for the machine code */
nb := int(pc - orig) nb := int(pc - orig)
ret = make([]byte, 0, nb) ret = make([]byte, 0, nb)
/* Pass 1: adjust all the jumps */ /* Pass 1: adjust all the jumps */
for next { for next {
next = false next = false
offs = uintptr(0) offs = uintptr(0)
/* scan all the branches */ /* scan all the branches */
for p := self.head; p != nil; p = p.next { for p := self.head; p != nil; p = p.next {
var ok bool var ok bool
var lb *Label var lb *Label
/* re-calculate the alignment here */ /* re-calculate the alignment here */
if nb = p.nb; p.pseudo.kind == _PseudoAlign { if nb = p.nb; p.pseudo.kind == _PseudoAlign {
p.pc -= offs p.pc -= offs
offs += uintptr(nb - p.encode(nil)) offs += uintptr(nb - p.encode(nil))
continue continue
} }
/* adjust the program counter */ /* adjust the program counter */
p.pc -= offs p.pc -= offs
lb, ok = p.argv[0].(*Label) lb, ok = p.argv[0].(*Label)
/* only care about labeled far-branches */ /* only care about labeled far-branches */
if !ok || p.nb == _N_near || p.branch == _B_none { if !ok || p.nb == _N_near || p.branch == _B_none {
continue continue
} }
/* calculate the jump offset */ /* calculate the jump offset */
size := self.branchSize(p) size := self.branchSize(p)
diff := lb.offset(p.pc, size) diff := lb.offset(p.pc, size)
/* too far to be a near jump */ /* too far to be a near jump */
if diff > 127 || diff < -128 { if diff > 127 || diff < -128 {
p.nb = size p.nb = size
continue continue
} }
/* a far jump becomes a near jump, calculate /* a far jump becomes a near jump, calculate
* the PC adjustment value and assemble again */ * the PC adjustment value and assemble again */
next = true next = true
p.nb = _N_near p.nb = _N_near
offs += uintptr(size - _N_near) offs += uintptr(size - _N_near)
} }
} }
/* Pass 3: link all the cross-references */ /* Pass 3: link all the cross-references */
for p := self.head; p != nil; p = p.next { for p := self.head; p != nil; p = p.next {
for i := 0; i < p.argc; i++ { for i := 0; i < p.argc; i++ {
var ok bool var ok bool
var lb *Label var lb *Label
var op *MemoryOperand var op *MemoryOperand
/* resolve labels */ /* resolve labels */
if lb, ok = p.argv[i].(*Label); ok { if lb, ok = p.argv[i].(*Label); ok {
p.argv[i] = lb.offset(p.pc, p.nb) p.argv[i] = lb.offset(p.pc, p.nb)
continue continue
} }
/* check for memory operands */ /* check for memory operands */
if op, ok = p.argv[i].(*MemoryOperand); !ok { if op, ok = p.argv[i].(*MemoryOperand); !ok {
continue continue
} }
/* check for label references */ /* check for label references */
if op.Addr.Type != Reference { if op.Addr.Type != Reference {
continue continue
} }
/* replace the label with the real offset */ /* replace the label with the real offset */
op.Addr.Type = Offset op.Addr.Type = Offset
op.Addr.Offset = op.Addr.Reference.offset(p.pc, p.nb) op.Addr.Offset = op.Addr.Reference.offset(p.pc, p.nb)
} }
} }
/* Pass 4: actually encode all the instructions */ /* Pass 4: actually encode all the instructions */
for p := self.head; p != nil; p = p.next { for p := self.head; p != nil; p = p.next {
p.encode(&ret) p.encode(&ret)
} }
/* all done */ /* all done */
return ret return ret
} }
// AssembleAndFree is like Assemble, but it frees the Program after assembling. // AssembleAndFree is like Assemble, but it frees the Program after assembling.
func (self *Program) AssembleAndFree(pc uintptr) (ret []byte) { func (self *Program) AssembleAndFree(pc uintptr) (ret []byte) {
ret = self.Assemble(pc) ret = self.Assemble(pc)
self.Free() self.Free()
return return
} }

View File

@ -52,7 +52,7 @@ func (bootloader *LinuxBootloader) FromOptions(options []option) error {
case "initrd": case "initrd":
bootloader.InitrdPath = option.value bootloader.InitrdPath = option.value
default: default:
return fmt.Errorf("Unknown option for linux bootloaders: %s", option.key) return fmt.Errorf("unknown option for linux bootloaders: %s", option.key)
} }
} }
return nil return nil
@ -61,17 +61,17 @@ func (bootloader *LinuxBootloader) FromOptions(options []option) error {
func (bootloader *LinuxBootloader) ToCmdLine() ([]string, error) { func (bootloader *LinuxBootloader) ToCmdLine() ([]string, error) {
args := []string{} args := []string{}
if bootloader.VmlinuzPath == "" { if bootloader.VmlinuzPath == "" {
return nil, fmt.Errorf("Missing kernel path") return nil, fmt.Errorf("missing kernel path")
} }
args = append(args, "--kernel", bootloader.VmlinuzPath) args = append(args, "--kernel", bootloader.VmlinuzPath)
if bootloader.InitrdPath == "" { if bootloader.InitrdPath == "" {
return nil, fmt.Errorf("Missing initrd path") return nil, fmt.Errorf("missing initrd path")
} }
args = append(args, "--initrd", bootloader.InitrdPath) args = append(args, "--initrd", bootloader.InitrdPath)
if bootloader.KernelCmdLine == "" { if bootloader.KernelCmdLine == "" {
return nil, fmt.Errorf("Missing kernel command line") return nil, fmt.Errorf("missing kernel command line")
} }
args = append(args, "--kernel-cmdline", bootloader.KernelCmdLine) args = append(args, "--kernel-cmdline", bootloader.KernelCmdLine)
@ -95,11 +95,11 @@ func (bootloader *EFIBootloader) FromOptions(options []option) error {
bootloader.EFIVariableStorePath = option.value bootloader.EFIVariableStorePath = option.value
case "create": case "create":
if option.value != "" { if option.value != "" {
return fmt.Errorf("Unexpected value for EFI bootloader 'create' option: %s", option.value) return fmt.Errorf("unexpected value for EFI bootloader 'create' option: %s", option.value)
} }
bootloader.CreateVariableStore = true bootloader.CreateVariableStore = true
default: default:
return fmt.Errorf("Unknown option for EFI bootloaders: %s", option.key) return fmt.Errorf("unknown option for EFI bootloaders: %s", option.key)
} }
} }
return nil return nil
@ -107,7 +107,7 @@ func (bootloader *EFIBootloader) FromOptions(options []option) error {
func (bootloader *EFIBootloader) ToCmdLine() ([]string, error) { func (bootloader *EFIBootloader) ToCmdLine() ([]string, error) {
if bootloader.EFIVariableStorePath == "" { if bootloader.EFIVariableStorePath == "" {
return nil, fmt.Errorf("Missing EFI store path") return nil, fmt.Errorf("missing EFI store path")
} }
builder := strings.Builder{} builder := strings.Builder{}

View File

@ -189,12 +189,12 @@ func (ts *TimeSync) FromOptions(options []option) error {
} }
ts.VsockPort = uint(vsockPort) ts.VsockPort = uint(vsockPort)
default: default:
return fmt.Errorf("Unknown option for timesync parameter: %s", option.key) return fmt.Errorf("unknown option for timesync parameter: %s", option.key)
} }
} }
if ts.VsockPort == 0 { if ts.VsockPort == 0 {
return fmt.Errorf("Missing 'vsockPort' option for timesync parameter") return fmt.Errorf("missing 'vsockPort' option for timesync parameter")
} }
return nil return nil

View File

@ -193,7 +193,7 @@ func (dev *VirtioSerial) validate() error {
return fmt.Errorf("'logFilePath' and 'stdio' cannot be set at the same time") return fmt.Errorf("'logFilePath' and 'stdio' cannot be set at the same time")
} }
if dev.LogFile == "" && !dev.UsesStdio { if dev.LogFile == "" && !dev.UsesStdio {
return fmt.Errorf("One of 'logFilePath' or 'stdio' must be set") return fmt.Errorf("one of 'logFilePath' or 'stdio' must be set")
} }
return nil return nil
@ -217,11 +217,11 @@ func (dev *VirtioSerial) FromOptions(options []option) error {
dev.LogFile = option.value dev.LogFile = option.value
case "stdio": case "stdio":
if option.value != "" { if option.value != "" {
return fmt.Errorf("Unexpected value for virtio-serial 'stdio' option: %s", option.value) return fmt.Errorf("unexpected value for virtio-serial 'stdio' option: %s", option.value)
} }
dev.UsesStdio = true dev.UsesStdio = true
default: default:
return fmt.Errorf("Unknown option for virtio-serial devices: %s", option.key) return fmt.Errorf("unknown option for virtio-serial devices: %s", option.key)
} }
} }
@ -244,7 +244,7 @@ func VirtioInputNew(inputType string) (VirtioDevice, error) {
func (dev *VirtioInput) validate() error { func (dev *VirtioInput) validate() error {
if dev.InputType != VirtioInputPointingDevice && dev.InputType != VirtioInputKeyboardDevice { if dev.InputType != VirtioInputPointingDevice && dev.InputType != VirtioInputKeyboardDevice {
return fmt.Errorf("Unknown option for virtio-input devices: %s", dev.InputType) return fmt.Errorf("unknown option for virtio-input devices: %s", dev.InputType)
} }
return nil return nil
@ -263,11 +263,11 @@ func (dev *VirtioInput) FromOptions(options []option) error {
switch option.key { switch option.key {
case VirtioInputPointingDevice, VirtioInputKeyboardDevice: case VirtioInputPointingDevice, VirtioInputKeyboardDevice:
if option.value != "" { if option.value != "" {
return fmt.Errorf(fmt.Sprintf("Unexpected value for virtio-input %s option: %s", option.key, option.value)) return fmt.Errorf(fmt.Sprintf("unexpected value for virtio-input %s option: %s", option.key, option.value))
} }
dev.InputType = option.key dev.InputType = option.key
default: default:
return fmt.Errorf("Unknown option for virtio-input devices: %s", option.key) return fmt.Errorf("unknown option for virtio-input devices: %s", option.key)
} }
} }
return dev.validate() return dev.validate()
@ -288,7 +288,7 @@ func VirtioGPUNew() (VirtioDevice, error) {
func (dev *VirtioGPU) validate() error { func (dev *VirtioGPU) validate() error {
if dev.Height < 1 || dev.Width < 1 { if dev.Height < 1 || dev.Width < 1 {
return fmt.Errorf("Invalid dimensions for virtio-gpu device resolution: %dx%d", dev.Width, dev.Height) return fmt.Errorf("invalid dimensions for virtio-gpu device resolution: %dx%d", dev.Width, dev.Height)
} }
return nil return nil
@ -320,7 +320,7 @@ func (dev *VirtioGPU) FromOptions(options []option) error {
dev.Width = width dev.Width = width
default: default:
return fmt.Errorf("Unknown option for virtio-gpu devices: %s", option.key) return fmt.Errorf("unknown option for virtio-gpu devices: %s", option.key)
} }
} }
@ -376,7 +376,7 @@ func (dev *VirtioNet) validate() error {
return fmt.Errorf("'fd' and 'unixSocketPath' cannot be set at the same time") return fmt.Errorf("'fd' and 'unixSocketPath' cannot be set at the same time")
} }
if !dev.Nat && dev.Socket == nil && dev.UnixSocketPath == "" { if !dev.Nat && dev.Socket == nil && dev.UnixSocketPath == "" {
return fmt.Errorf("One of 'nat' or 'fd' or 'unixSocketPath' must be set") return fmt.Errorf("one of 'nat' or 'fd' or 'unixSocketPath' must be set")
} }
return nil return nil
@ -410,7 +410,7 @@ func (dev *VirtioNet) FromOptions(options []option) error {
switch option.key { switch option.key {
case "nat": case "nat":
if option.value != "" { if option.value != "" {
return fmt.Errorf("Unexpected value for virtio-net 'nat' option: %s", option.value) return fmt.Errorf("unexpected value for virtio-net 'nat' option: %s", option.value)
} }
dev.Nat = true dev.Nat = true
case "mac": case "mac":
@ -428,7 +428,7 @@ func (dev *VirtioNet) FromOptions(options []option) error {
case "unixSocketPath": case "unixSocketPath":
dev.UnixSocketPath = option.value dev.UnixSocketPath = option.value
default: default:
return fmt.Errorf("Unknown option for virtio-net devices: %s", option.key) return fmt.Errorf("unknown option for virtio-net devices: %s", option.key)
} }
} }
@ -447,7 +447,7 @@ func (dev *VirtioRng) ToCmdLine() ([]string, error) {
func (dev *VirtioRng) FromOptions(options []option) error { func (dev *VirtioRng) FromOptions(options []option) error {
if len(options) != 0 { if len(options) != 0 {
return fmt.Errorf("Unknown options for virtio-rng devices: %s", options) return fmt.Errorf("unknown options for virtio-rng devices: %s", options)
} }
return nil return nil
} }
@ -494,7 +494,7 @@ func (dev *VirtioBlk) ToCmdLine() ([]string, error) {
return []string{}, err return []string{}, err
} }
if len(cmdLine) != 2 { if len(cmdLine) != 2 {
return []string{}, fmt.Errorf("Unexpected storage config commandline") return []string{}, fmt.Errorf("unexpected storage config commandline")
} }
if dev.DeviceIdentifier != "" { if dev.DeviceIdentifier != "" {
cmdLine[1] = fmt.Sprintf("%s,deviceId=%s", cmdLine[1], dev.DeviceIdentifier) cmdLine[1] = fmt.Sprintf("%s,deviceId=%s", cmdLine[1], dev.DeviceIdentifier)
@ -546,7 +546,7 @@ func (dev *VirtioVsock) FromOptions(options []option) error {
case "connect": case "connect":
dev.Listen = false dev.Listen = false
default: default:
return fmt.Errorf("Unknown option for virtio-vsock devices: %s", option.key) return fmt.Errorf("unknown option for virtio-vsock devices: %s", option.key)
} }
} }
return nil return nil
@ -583,7 +583,7 @@ func (dev *VirtioFs) FromOptions(options []option) error {
case "mountTag": case "mountTag":
dev.MountTag = option.value dev.MountTag = option.value
default: default:
return fmt.Errorf("Unknown option for virtio-fs devices: %s", option.key) return fmt.Errorf("unknown option for virtio-fs devices: %s", option.key)
} }
} }
return nil return nil
@ -623,7 +623,7 @@ func (dev *RosettaShare) FromOptions(options []option) error {
case "install": case "install":
dev.InstallRosetta = true dev.InstallRosetta = true
default: default:
return fmt.Errorf("Unknown option for rosetta share: %s", option.key) return fmt.Errorf("unknown option for rosetta share: %s", option.key)
} }
} }
return nil return nil
@ -670,7 +670,7 @@ func (config *StorageConfig) FromOptions(options []option) error {
case "path": case "path":
config.ImagePath = option.value config.ImagePath = option.value
default: default:
return fmt.Errorf("Unknown option for %s devices: %s", config.DevName, option.key) return fmt.Errorf("unknown option for %s devices: %s", config.DevName, option.key)
} }
} }
return nil return nil

View File

@ -10,9 +10,6 @@
</h6> </h6>
<p align="center"> <p align="center">
<a href="https://travis-ci.org/gabriel-vasile/mimetype">
<img alt="Build Status" src="https://travis-ci.org/gabriel-vasile/mimetype.svg?branch=master">
</a>
<a href="https://pkg.go.dev/github.com/gabriel-vasile/mimetype"> <a href="https://pkg.go.dev/github.com/gabriel-vasile/mimetype">
<img alt="Go Reference" src="https://pkg.go.dev/badge/github.com/gabriel-vasile/mimetype.svg"> <img alt="Go Reference" src="https://pkg.go.dev/badge/github.com/gabriel-vasile/mimetype.svg">
</a> </a>

View File

@ -150,32 +150,34 @@ func Marc(raw []byte, limit uint32) bool {
} }
// Glb matches a glTF model format file. // Glb matches a glTF model format file.
// GLB is the binary file format representation of 3D models save in // GLB is the binary file format representation of 3D models saved in
// the GL transmission Format (glTF). // the GL transmission Format (glTF).
// see more: https://docs.fileformat.com/3d/glb/ // GLB uses little endian and its header structure is as follows:
// https://www.iana.org/assignments/media-types/model/gltf-binary
// GLB file format is based on little endian and its header structure
// show below:
// //
// <-- 12-byte header --> // <-- 12-byte header -->
// | magic | version | length | // | magic | version | length |
// | (uint32) | (uint32) | (uint32) | // | (uint32) | (uint32) | (uint32) |
// | \x67\x6C\x54\x46 | \x01\x00\x00\x00 | ... | // | \x67\x6C\x54\x46 | \x01\x00\x00\x00 | ... |
// | g l T F | 1 | ... | // | g l T F | 1 | ... |
//
// Visit [glTF specification] and [IANA glTF entry] for more details.
//
// [glTF specification]: https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html
// [IANA glTF entry]: https://www.iana.org/assignments/media-types/model/gltf-binary
var Glb = prefix([]byte("\x67\x6C\x54\x46\x02\x00\x00\x00"), var Glb = prefix([]byte("\x67\x6C\x54\x46\x02\x00\x00\x00"),
[]byte("\x67\x6C\x54\x46\x01\x00\x00\x00")) []byte("\x67\x6C\x54\x46\x01\x00\x00\x00"))
// TzIf matches a Time Zone Information Format (TZif) file. // TzIf matches a Time Zone Information Format (TZif) file.
// See more: https://tools.ietf.org/id/draft-murchison-tzdist-tzif-00.html#rfc.section.3 // See more: https://tools.ietf.org/id/draft-murchison-tzdist-tzif-00.html#rfc.section.3
// Its header structure is shown below: // Its header structure is shown below:
// +---------------+---+ // +---------------+---+
// | magic (4) | <-+-- version (1) // | magic (4) | <-+-- version (1)
// +---------------+---+---------------------------------------+ // +---------------+---+---------------------------------------+
// | [unused - reserved for future use] (15) | // | [unused - reserved for future use] (15) |
// +---------------+---------------+---------------+-----------+ // +---------------+---------------+---------------+-----------+
// | isutccnt (4) | isstdcnt (4) | leapcnt (4) | // | isutccnt (4) | isstdcnt (4) | leapcnt (4) |
// +---------------+---------------+---------------+ // +---------------+---------------+---------------+
// | timecnt (4) | typecnt (4) | charcnt (4) | // | timecnt (4) | typecnt (4) | charcnt (4) |
func TzIf(raw []byte, limit uint32) bool { func TzIf(raw []byte, limit uint32) bool {
// File is at least 44 bytes (header size). // File is at least 44 bytes (header size).
if len(raw) < 44 { if len(raw) < 44 {

View File

@ -177,7 +177,9 @@ func newXMLSig(localName, xmlns string) xmlSig {
// and, optionally, followed by the arguments for the interpreter. // and, optionally, followed by the arguments for the interpreter.
// //
// Ex: // Ex:
// #! /usr/bin/env php //
// #! /usr/bin/env php
//
// /usr/bin/env is the interpreter, php is the first and only argument. // /usr/bin/env is the interpreter, php is the first and only argument.
func shebang(sigs ...[]byte) Detector { func shebang(sigs ...[]byte) Detector {
return func(raw []byte, limit uint32) bool { return func(raw []byte, limit uint32) bool {

View File

@ -3,6 +3,7 @@ package magic
import ( import (
"bytes" "bytes"
"encoding/csv" "encoding/csv"
"errors"
"io" "io"
) )
@ -19,12 +20,23 @@ func Tsv(raw []byte, limit uint32) bool {
func sv(in []byte, comma rune, limit uint32) bool { func sv(in []byte, comma rune, limit uint32) bool {
r := csv.NewReader(dropLastLine(in, limit)) r := csv.NewReader(dropLastLine(in, limit))
r.Comma = comma r.Comma = comma
r.TrimLeadingSpace = true r.ReuseRecord = true
r.LazyQuotes = true r.LazyQuotes = true
r.Comment = '#' r.Comment = '#'
lines, err := r.ReadAll() lines := 0
return err == nil && r.FieldsPerRecord > 1 && len(lines) > 1 for {
_, err := r.Read()
if errors.Is(err, io.EOF) {
break
}
if err != nil {
return false
}
lines++
}
return r.FieldsPerRecord > 1 && lines > 1
} }
// dropLastLine drops the last incomplete line from b. // dropLastLine drops the last incomplete line from b.

View File

@ -39,7 +39,8 @@ func Detect(in []byte) *MIME {
// //
// DetectReader assumes the reader offset is at the start. If the input is an // DetectReader assumes the reader offset is at the start. If the input is an
// io.ReadSeeker you previously read from, it should be rewinded before detection: // io.ReadSeeker you previously read from, it should be rewinded before detection:
// reader.Seek(0, io.SeekStart) //
// reader.Seek(0, io.SeekStart)
func DetectReader(r io.Reader) (*MIME, error) { func DetectReader(r io.Reader) (*MIME, error) {
var in []byte var in []byte
var err error var err error

View File

@ -1,4 +1,4 @@
## 172 Supported MIME types ## 173 Supported MIME types
This file is automatically generated when running tests. Do not edit manually. This file is automatically generated when running tests. Do not edit manually.
Extension | MIME type | Aliases Extension | MIME type | Aliases

View File

@ -1,7 +1,7 @@
Package validator Package validator
================= =================
<img align="right" src="logo.png">[![Join the chat at https://gitter.im/go-playground/validator](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/go-playground/validator?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) <img align="right" src="logo.png">[![Join the chat at https://gitter.im/go-playground/validator](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/go-playground/validator?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
![Project status](https://img.shields.io/badge/version-10.15.4-green.svg) ![Project status](https://img.shields.io/badge/version-10.17.0-green.svg)
[![Build Status](https://travis-ci.org/go-playground/validator.svg?branch=master)](https://travis-ci.org/go-playground/validator) [![Build Status](https://travis-ci.org/go-playground/validator.svg?branch=master)](https://travis-ci.org/go-playground/validator)
[![Coverage Status](https://coveralls.io/repos/go-playground/validator/badge.svg?branch=master&service=github)](https://coveralls.io/github/go-playground/validator?branch=master) [![Coverage Status](https://coveralls.io/repos/go-playground/validator/badge.svg?branch=master&service=github)](https://coveralls.io/github/go-playground/validator?branch=master)
[![Go Report Card](https://goreportcard.com/badge/github.com/go-playground/validator)](https://goreportcard.com/report/github.com/go-playground/validator) [![Go Report Card](https://goreportcard.com/badge/github.com/go-playground/validator)](https://goreportcard.com/report/github.com/go-playground/validator)
@ -178,6 +178,7 @@ validate := validator.New(validator.WithRequiredStructEnabled())
| isbn | International Standard Book Number | | isbn | International Standard Book Number |
| isbn10 | International Standard Book Number 10 | | isbn10 | International Standard Book Number 10 |
| isbn13 | International Standard Book Number 13 | | isbn13 | International Standard Book Number 13 |
| issn | International Standard Serial Number |
| iso3166_1_alpha2 | Two-letter country code (ISO 3166-1 alpha-2) | | iso3166_1_alpha2 | Two-letter country code (ISO 3166-1 alpha-2) |
| iso3166_1_alpha3 | Three-letter country code (ISO 3166-1 alpha-3) | | iso3166_1_alpha3 | Three-letter country code (ISO 3166-1 alpha-3) |
| iso3166_1_alpha_numeric | Numeric country code (ISO 3166-1 numeric) | | iso3166_1_alpha_numeric | Numeric country code (ISO 3166-1 numeric) |

View File

@ -51,6 +51,7 @@ var (
endKeysTag: {}, endKeysTag: {},
structOnlyTag: {}, structOnlyTag: {},
omitempty: {}, omitempty: {},
omitnil: {},
skipValidationTag: {}, skipValidationTag: {},
utf8HexComma: {}, utf8HexComma: {},
utf8Pipe: {}, utf8Pipe: {},
@ -149,6 +150,7 @@ var (
"isbn": isISBN, "isbn": isISBN,
"isbn10": isISBN10, "isbn10": isISBN10,
"isbn13": isISBN13, "isbn13": isISBN13,
"issn": isISSN,
"eth_addr": isEthereumAddress, "eth_addr": isEthereumAddress,
"eth_addr_checksum": isEthereumAddressChecksum, "eth_addr_checksum": isEthereumAddressChecksum,
"btc_addr": isBitcoinAddress, "btc_addr": isBitcoinAddress,
@ -508,47 +510,47 @@ func isASCII(fl FieldLevel) bool {
// isUUID5 is the validation function for validating if the field's value is a valid v5 UUID. // isUUID5 is the validation function for validating if the field's value is a valid v5 UUID.
func isUUID5(fl FieldLevel) bool { func isUUID5(fl FieldLevel) bool {
return uUID5Regex.MatchString(fl.Field().String()) return fieldMatchesRegexByStringerValOrString(uUID5Regex, fl)
} }
// isUUID4 is the validation function for validating if the field's value is a valid v4 UUID. // isUUID4 is the validation function for validating if the field's value is a valid v4 UUID.
func isUUID4(fl FieldLevel) bool { func isUUID4(fl FieldLevel) bool {
return uUID4Regex.MatchString(fl.Field().String()) return fieldMatchesRegexByStringerValOrString(uUID4Regex, fl)
} }
// isUUID3 is the validation function for validating if the field's value is a valid v3 UUID. // isUUID3 is the validation function for validating if the field's value is a valid v3 UUID.
func isUUID3(fl FieldLevel) bool { func isUUID3(fl FieldLevel) bool {
return uUID3Regex.MatchString(fl.Field().String()) return fieldMatchesRegexByStringerValOrString(uUID3Regex, fl)
} }
// isUUID is the validation function for validating if the field's value is a valid UUID of any version. // isUUID is the validation function for validating if the field's value is a valid UUID of any version.
func isUUID(fl FieldLevel) bool { func isUUID(fl FieldLevel) bool {
return uUIDRegex.MatchString(fl.Field().String()) return fieldMatchesRegexByStringerValOrString(uUIDRegex, fl)
} }
// isUUID5RFC4122 is the validation function for validating if the field's value is a valid RFC4122 v5 UUID. // isUUID5RFC4122 is the validation function for validating if the field's value is a valid RFC4122 v5 UUID.
func isUUID5RFC4122(fl FieldLevel) bool { func isUUID5RFC4122(fl FieldLevel) bool {
return uUID5RFC4122Regex.MatchString(fl.Field().String()) return fieldMatchesRegexByStringerValOrString(uUID5RFC4122Regex, fl)
} }
// isUUID4RFC4122 is the validation function for validating if the field's value is a valid RFC4122 v4 UUID. // isUUID4RFC4122 is the validation function for validating if the field's value is a valid RFC4122 v4 UUID.
func isUUID4RFC4122(fl FieldLevel) bool { func isUUID4RFC4122(fl FieldLevel) bool {
return uUID4RFC4122Regex.MatchString(fl.Field().String()) return fieldMatchesRegexByStringerValOrString(uUID4RFC4122Regex, fl)
} }
// isUUID3RFC4122 is the validation function for validating if the field's value is a valid RFC4122 v3 UUID. // isUUID3RFC4122 is the validation function for validating if the field's value is a valid RFC4122 v3 UUID.
func isUUID3RFC4122(fl FieldLevel) bool { func isUUID3RFC4122(fl FieldLevel) bool {
return uUID3RFC4122Regex.MatchString(fl.Field().String()) return fieldMatchesRegexByStringerValOrString(uUID3RFC4122Regex, fl)
} }
// isUUIDRFC4122 is the validation function for validating if the field's value is a valid RFC4122 UUID of any version. // isUUIDRFC4122 is the validation function for validating if the field's value is a valid RFC4122 UUID of any version.
func isUUIDRFC4122(fl FieldLevel) bool { func isUUIDRFC4122(fl FieldLevel) bool {
return uUIDRFC4122Regex.MatchString(fl.Field().String()) return fieldMatchesRegexByStringerValOrString(uUIDRFC4122Regex, fl)
} }
// isULID is the validation function for validating if the field's value is a valid ULID. // isULID is the validation function for validating if the field's value is a valid ULID.
func isULID(fl FieldLevel) bool { func isULID(fl FieldLevel) bool {
return uLIDRegex.MatchString(fl.Field().String()) return fieldMatchesRegexByStringerValOrString(uLIDRegex, fl)
} }
// isMD4 is the validation function for validating if the field's value is a valid MD4. // isMD4 is the validation function for validating if the field's value is a valid MD4.
@ -650,6 +652,32 @@ func isISBN10(fl FieldLevel) bool {
return checksum%11 == 0 return checksum%11 == 0
} }
// isISSN is the validation function for validating if the field's value is a valid ISSN.
func isISSN(fl FieldLevel) bool {
s := fl.Field().String()
if !iSSNRegex.MatchString(s) {
return false
}
s = strings.ReplaceAll(s, "-", "")
pos := 8
checksum := 0
for i := 0; i < 7; i++ {
checksum += pos * int(s[i]-'0')
pos--
}
if s[7] == 'X' {
checksum += 10
} else {
checksum += int(s[7] - '0')
}
return checksum%11 == 0
}
// isEthereumAddress is the validation function for validating if the field's value is a valid Ethereum address. // isEthereumAddress is the validation function for validating if the field's value is a valid Ethereum address.
func isEthereumAddress(fl FieldLevel) bool { func isEthereumAddress(fl FieldLevel) bool {
address := fl.Field().String() address := fl.Field().String()
@ -1413,6 +1441,15 @@ func isURI(fl FieldLevel) bool {
panic(fmt.Sprintf("Bad field type %T", field.Interface())) panic(fmt.Sprintf("Bad field type %T", field.Interface()))
} }
// isFileURL is the helper function for validating if the `path` valid file URL as per RFC8089
func isFileURL(path string) bool {
if !strings.HasPrefix(path, "file:/") {
return false
}
_, err := url.ParseRequestURI(path)
return err == nil
}
// isURL is the validation function for validating if the current field's value is a valid URL. // isURL is the validation function for validating if the current field's value is a valid URL.
func isURL(fl FieldLevel) bool { func isURL(fl FieldLevel) bool {
field := fl.Field() field := fl.Field()
@ -1420,12 +1457,16 @@ func isURL(fl FieldLevel) bool {
switch field.Kind() { switch field.Kind() {
case reflect.String: case reflect.String:
s := field.String() s := strings.ToLower(field.String())
if len(s) == 0 { if len(s) == 0 {
return false return false
} }
if isFileURL(s) {
return true
}
url, err := url.Parse(s) url, err := url.Parse(s)
if err != nil || url.Scheme == "" { if err != nil || url.Scheme == "" {
return false return false

View File

@ -20,6 +20,7 @@ const (
typeOr typeOr
typeKeys typeKeys
typeEndKeys typeEndKeys
typeOmitNil
) )
const ( const (
@ -252,6 +253,10 @@ func (v *Validate) parseFieldTagsRecursive(tag string, fieldName string, alias s
current.typeof = typeOmitEmpty current.typeof = typeOmitEmpty
continue continue
case omitnil:
current.typeof = typeOmitNil
continue
case structOnlyTag: case structOnlyTag:
current.typeof = typeStructOnly current.typeof = typeStructOnly
continue continue

View File

@ -194,6 +194,13 @@ such as min or max won't run, but if a value is set validation will run.
Usage: omitempty Usage: omitempty
# Omit Nil
Allows to skip the validation if the value is nil (same as omitempty, but
only for the nil-values).
Usage: omitnil
# Dive # Dive
This tells the validator to dive into a slice, array or map and validate that This tells the validator to dive into a slice, array or map and validate that

View File

@ -257,15 +257,19 @@ func (fe *fieldError) Error() string {
// NOTE: if no registered translation can be found, it returns the original // NOTE: if no registered translation can be found, it returns the original
// untranslated error message. // untranslated error message.
func (fe *fieldError) Translate(ut ut.Translator) string { func (fe *fieldError) Translate(ut ut.Translator) string {
var fn TranslationFunc
m, ok := fe.v.transTagFunc[ut] m, ok := fe.v.transTagFunc[ut]
if !ok { if !ok {
return fe.Error() return fe.Error()
} }
fn, ok := m[fe.tag] fn, ok = m[fe.tag]
if !ok { if !ok {
return fe.Error() fn, ok = m[fe.actualTag]
if !ok {
return fe.Error()
}
} }
return fn(ut, fe) return fn(ut, fe)

View File

@ -22,6 +22,7 @@ const (
base64RawURLRegexString = "^(?:[A-Za-z0-9-_]{4})*(?:[A-Za-z0-9-_]{2,4})$" base64RawURLRegexString = "^(?:[A-Za-z0-9-_]{4})*(?:[A-Za-z0-9-_]{2,4})$"
iSBN10RegexString = "^(?:[0-9]{9}X|[0-9]{10})$" iSBN10RegexString = "^(?:[0-9]{9}X|[0-9]{10})$"
iSBN13RegexString = "^(?:(?:97(?:8|9))[0-9]{10})$" iSBN13RegexString = "^(?:(?:97(?:8|9))[0-9]{10})$"
iSSNRegexString = "^(?:[0-9]{4}-[0-9]{3}[0-9X])$"
uUID3RegexString = "^[0-9a-f]{8}-[0-9a-f]{4}-3[0-9a-f]{3}-[0-9a-f]{4}-[0-9a-f]{12}$" uUID3RegexString = "^[0-9a-f]{8}-[0-9a-f]{4}-3[0-9a-f]{3}-[0-9a-f]{4}-[0-9a-f]{12}$"
uUID4RegexString = "^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$" uUID4RegexString = "^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$"
uUID5RegexString = "^[0-9a-f]{8}-[0-9a-f]{4}-5[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$" uUID5RegexString = "^[0-9a-f]{8}-[0-9a-f]{4}-5[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$"
@ -93,6 +94,7 @@ var (
base64RawURLRegex = regexp.MustCompile(base64RawURLRegexString) base64RawURLRegex = regexp.MustCompile(base64RawURLRegexString)
iSBN10Regex = regexp.MustCompile(iSBN10RegexString) iSBN10Regex = regexp.MustCompile(iSBN10RegexString)
iSBN13Regex = regexp.MustCompile(iSBN13RegexString) iSBN13Regex = regexp.MustCompile(iSBN13RegexString)
iSSNRegex = regexp.MustCompile(iSSNRegexString)
uUID3Regex = regexp.MustCompile(uUID3RegexString) uUID3Regex = regexp.MustCompile(uUID3RegexString)
uUID4Regex = regexp.MustCompile(uUID4RegexString) uUID4Regex = regexp.MustCompile(uUID4RegexString)
uUID5Regex = regexp.MustCompile(uUID5RegexString) uUID5Regex = regexp.MustCompile(uUID5RegexString)

View File

@ -1,7 +1,9 @@
package validator package validator
import ( import (
"fmt"
"reflect" "reflect"
"regexp"
"strconv" "strconv"
"strings" "strings"
"time" "time"
@ -292,3 +294,18 @@ func panicIf(err error) {
panic(err.Error()) panic(err.Error())
} }
} }
// Checks if field value matches regex. If fl.Field can be cast to Stringer, it uses the Stringer interfaces
// String() return value. Otherwise, it uses fl.Field's String() value.
func fieldMatchesRegexByStringerValOrString(regex *regexp.Regexp, fl FieldLevel) bool {
switch fl.Field().Kind() {
case reflect.String:
return regex.MatchString(fl.Field().String())
default:
if stringer, ok := fl.Field().Interface().(fmt.Stringer); ok {
return regex.MatchString(stringer.String())
} else {
return regex.MatchString(fl.Field().String())
}
}
}

View File

@ -112,6 +112,10 @@ func (v *validate) traverseField(ctx context.Context, parent reflect.Value, curr
return return
} }
if ct.typeof == typeOmitNil && (kind != reflect.Invalid && current.IsNil()) {
return
}
if ct.hasTag { if ct.hasTag {
if kind == reflect.Invalid { if kind == reflect.Invalid {
v.str1 = string(append(ns, cf.altName...)) v.str1 = string(append(ns, cf.altName...))
@ -233,6 +237,26 @@ OUTER:
ct = ct.next ct = ct.next
continue continue
case typeOmitNil:
v.slflParent = parent
v.flField = current
v.cf = cf
v.ct = ct
switch field := v.Field(); field.Kind() {
case reflect.Slice, reflect.Map, reflect.Ptr, reflect.Interface, reflect.Chan, reflect.Func:
if field.IsNil() {
return
}
default:
if v.fldIsPointer && field.Interface() == nil {
return
}
}
ct = ct.next
continue
case typeEndKeys: case typeEndKeys:
return return

View File

@ -22,6 +22,7 @@ const (
structOnlyTag = "structonly" structOnlyTag = "structonly"
noStructLevelTag = "nostructlevel" noStructLevelTag = "nostructlevel"
omitempty = "omitempty" omitempty = "omitempty"
omitnil = "omitnil"
isdefault = "isdefault" isdefault = "isdefault"
requiredWithoutAllTag = "required_without_all" requiredWithoutAllTag = "required_without_all"
requiredWithoutTag = "required_without" requiredWithoutTag = "required_without"

View File

@ -1,6 +1,7 @@
//go:build (darwin || freebsd || openbsd || netbsd || dragonfly || hurd) && !appengine //go:build (darwin || freebsd || openbsd || netbsd || dragonfly || hurd) && !appengine && !tinygo
// +build darwin freebsd openbsd netbsd dragonfly hurd // +build darwin freebsd openbsd netbsd dragonfly hurd
// +build !appengine // +build !appengine
// +build !tinygo
package isatty package isatty

View File

@ -1,5 +1,6 @@
//go:build appengine || js || nacl || wasm //go:build (appengine || js || nacl || tinygo || wasm) && !windows
// +build appengine js nacl wasm // +build appengine js nacl tinygo wasm
// +build !windows
package isatty package isatty

View File

@ -1,6 +1,7 @@
//go:build (linux || aix || zos) && !appengine //go:build (linux || aix || zos) && !appengine && !tinygo
// +build linux aix zos // +build linux aix zos
// +build !appengine // +build !appengine
// +build !tinygo
package isatty package isatty

View File

@ -343,7 +343,7 @@ func PathExistsWithContents(filename string) bool {
if err != nil { if err != nil {
return false return false
} }
return info.Size() > 4 // at least 4 bytes return info.Size() > 4 && !info.IsDir() // at least 4 bytes
} }
// GetEnvWithContext retrieves the environment variable key. If it does not exist it returns the default. // GetEnvWithContext retrieves the environment variable key. If it does not exist it returns the default.

View File

@ -12,10 +12,14 @@ import (
"strconv" "strconv"
"strings" "strings"
"sync" "sync"
"sync/atomic"
"syscall" "syscall"
"time" "time"
) )
// cachedBootTime must be accessed via atomic.Load/StoreUint64
var cachedBootTime uint64
func DoSysctrl(mib string) ([]string, error) { func DoSysctrl(mib string) ([]string, error) {
cmd := exec.Command("sysctl", "-n", mib) cmd := exec.Command("sysctl", "-n", mib)
cmd.Env = getSysctrlEnv(os.Environ()) cmd.Env = getSysctrlEnv(os.Environ())
@ -56,7 +60,14 @@ func NumProcsWithContext(ctx context.Context) (uint64, error) {
return cnt, nil return cnt, nil
} }
func BootTimeWithContext(ctx context.Context) (uint64, error) { func BootTimeWithContext(ctx context.Context, enableCache bool) (uint64, error) {
if enableCache {
t := atomic.LoadUint64(&cachedBootTime)
if t != 0 {
return t, nil
}
}
system, role, err := VirtualizationWithContext(ctx) system, role, err := VirtualizationWithContext(ctx)
if err != nil { if err != nil {
return 0, err return 0, err
@ -72,7 +83,13 @@ func BootTimeWithContext(ctx context.Context) (uint64, error) {
} }
if useStatFile { if useStatFile {
return readBootTimeStat(ctx) t, err := readBootTimeStat(ctx)
if err != nil {
return 0, err
}
if enableCache {
atomic.StoreUint64(&cachedBootTime, t)
}
} }
filename := HostProcWithContext(ctx, "uptime") filename := HostProcWithContext(ctx, "uptime")
@ -90,6 +107,11 @@ func BootTimeWithContext(ctx context.Context) (uint64, error) {
} }
currentTime := float64(time.Now().UnixNano()) / float64(time.Second) currentTime := float64(time.Now().UnixNano()) / float64(time.Second)
t := currentTime - b t := currentTime - b
if enableCache {
atomic.StoreUint64(&cachedBootTime, uint64(t))
}
return uint64(t), nil return uint64(t), nil
} }
@ -307,7 +329,7 @@ func GetOSReleaseWithContext(ctx context.Context) (platform string, version stri
switch field[0] { switch field[0] {
case "ID": // use ID for lowercase case "ID": // use ID for lowercase
platform = trimQuotes(field[1]) platform = trimQuotes(field[1])
case "VERSION": case "VERSION_ID":
version = trimQuotes(field[1]) version = trimQuotes(field[1])
} }
} }

View File

@ -171,6 +171,13 @@ func (p NumCtxSwitchesStat) String() string {
return string(s) return string(s)
} }
var enableBootTimeCache bool
// EnableBootTimeCache change cache behavior of BootTime. If true, cache BootTime value. Default is false.
func EnableBootTimeCache(enable bool) {
enableBootTimeCache = enable
}
// Pids returns a slice of process ID list which are running now. // Pids returns a slice of process ID list which are running now.
func Pids() ([]int32, error) { func Pids() ([]int32, error) {
return PidsWithContext(context.Background()) return PidsWithContext(context.Background())

View File

@ -1071,7 +1071,7 @@ func (p *Process) fillFromTIDStatWithContext(ctx context.Context, tid int32) (ui
Iowait: iotime / float64(clockTicks), Iowait: iotime / float64(clockTicks),
} }
bootTime, _ := common.BootTimeWithContext(ctx) bootTime, _ := common.BootTimeWithContext(ctx, enableBootTimeCache)
t, err := strconv.ParseUint(fields[22], 10, 64) t, err := strconv.ParseUint(fields[22], 10, 64)
if err != nil { if err != nil {
return 0, 0, nil, 0, 0, 0, nil, err return 0, 0, nil, 0, 0, 0, nil, err

View File

@ -253,7 +253,7 @@ func pidsWithContext(ctx context.Context) ([]int32, error) {
if err := windows.EnumProcesses(ps, &read); err != nil { if err := windows.EnumProcesses(ps, &read); err != nil {
return nil, err return nil, err
} }
if uint32(len(ps)) == read { // ps buffer was too small to host every results, retry with a bigger one if uint32(len(ps)) == read/dwordSize { // ps buffer was too small to host every results, retry with a bigger one
psSize += 1024 psSize += 1024
continue continue
} }

View File

@ -123,6 +123,11 @@ type cborEncDriver struct {
encDriverNoopContainerWriter encDriverNoopContainerWriter
h *CborHandle h *CborHandle
// scratch buffer for: encode time, numbers, etc
//
// RFC3339Nano uses 35 chars: 2006-01-02T15:04:05.999999999Z07:00
b [40]byte
e Encoder e Encoder
} }
@ -204,7 +209,7 @@ func (e *cborEncDriver) EncodeTime(t time.Time) {
e.EncodeNil() e.EncodeNil()
} else if e.h.TimeRFC3339 { } else if e.h.TimeRFC3339 {
e.encUint(0, cborBaseTag) e.encUint(0, cborBaseTag)
e.encStringBytesS(cborBaseString, t.Format(time.RFC3339Nano)) e.encStringBytesS(cborBaseString, stringView(fmtTime(t, time.RFC3339Nano, e.b[:0])))
} else { } else {
e.encUint(1, cborBaseTag) e.encUint(1, cborBaseTag)
t = t.UTC().Round(time.Microsecond) t = t.UTC().Round(time.Microsecond)
@ -427,12 +432,13 @@ func (d *cborDecDriver) decLen() int {
return int(d.decUint()) return int(d.decUint())
} }
func (d *cborDecDriver) decAppendIndefiniteBytes(bs []byte) []byte { func (d *cborDecDriver) decAppendIndefiniteBytes(bs []byte, major byte) []byte {
d.bdRead = false d.bdRead = false
for !d.CheckBreak() { for !d.CheckBreak() {
if major := d.bd >> 5; major != cborMajorBytes && major != cborMajorString { chunkMajor := d.bd >> 5
d.d.errorf("invalid indefinite string/bytes %x (%s); got major %v, expected %v or %v", if chunkMajor != major {
d.bd, cbordesc(d.bd), major, cborMajorBytes, cborMajorString) d.d.errorf("malformed indefinite string/bytes %x (%s); contains chunk with major type %v, expected %v",
d.bd, cbordesc(d.bd), chunkMajor, major)
} }
n := uint(d.decLen()) n := uint(d.decLen())
oldLen := uint(len(bs)) oldLen := uint(len(bs))
@ -445,6 +451,9 @@ func (d *cborDecDriver) decAppendIndefiniteBytes(bs []byte) []byte {
bs = bs[:newLen] bs = bs[:newLen]
} }
d.d.decRd.readb(bs[oldLen:newLen]) d.d.decRd.readb(bs[oldLen:newLen])
if d.h.ValidateUnicode && major == cborMajorString && !utf8.Valid(bs[oldLen:newLen]) {
d.d.errorf("indefinite-length text string contains chunk that is not a valid utf-8 sequence: 0x%x", bs[oldLen:newLen])
}
d.bdRead = false d.bdRead = false
} }
d.bdRead = false d.bdRead = false
@ -580,9 +589,9 @@ func (d *cborDecDriver) DecodeBytes(bs []byte) (bsOut []byte) {
d.bdRead = false d.bdRead = false
if bs == nil { if bs == nil {
d.d.decByteState = decByteStateReuseBuf d.d.decByteState = decByteStateReuseBuf
return d.decAppendIndefiniteBytes(d.d.b[:0]) return d.decAppendIndefiniteBytes(d.d.b[:0], d.bd>>5)
} }
return d.decAppendIndefiniteBytes(bs[:0]) return d.decAppendIndefiniteBytes(bs[:0], d.bd>>5)
} }
if d.bd == cborBdIndefiniteArray { if d.bd == cborBdIndefiniteArray {
d.bdRead = false d.bdRead = false

View File

@ -1399,6 +1399,10 @@ func NewDecoderString(s string, h Handle) *Decoder {
return NewDecoderBytes(bytesView(s), h) return NewDecoderBytes(bytesView(s), h)
} }
func (d *Decoder) HandleName() string {
return d.hh.Name()
}
func (d *Decoder) r() *decRd { func (d *Decoder) r() *decRd {
return &d.decRd return &d.decRd
} }
@ -1580,14 +1584,9 @@ func (d *Decoder) MustDecode(v interface{}) {
d.calls-- d.calls--
} }
// Release releases shared (pooled) resources. // Release is a no-op.
// //
// It is important to call Release() when done with a Decoder, so those resources // Deprecated: Pooled resources are not used with a Decoder.
// are released instantly for use by subsequently created Decoders.
//
// By default, Release() is automatically called unless the option ExplicitRelease is set.
//
// Deprecated: Release is a no-op as pooled resources are not used with an Decoder.
// This method is kept for compatibility reasons only. // This method is kept for compatibility reasons only.
func (d *Decoder) Release() { func (d *Decoder) Release() {
} }

View File

@ -984,6 +984,10 @@ func NewEncoderBytes(out *[]byte, h Handle) *Encoder {
return e return e
} }
func (e *Encoder) HandleName() string {
return e.hh.Name()
}
func (e *Encoder) init(h Handle) { func (e *Encoder) init(h Handle) {
initHandle(h) initHandle(h)
e.err = errEncoderNotInitialized e.err = errEncoderNotInitialized
@ -1150,12 +1154,9 @@ func (e *Encoder) MustEncode(v interface{}) {
} }
} }
// Release releases shared (pooled) resources. // Release is a no-op.
// //
// It is important to call Release() when done with an Encoder, so those resources // Deprecated: Pooled resources are not used with an Encoder.
// are released instantly for use by subsequently created Encoders.
//
// Deprecated: Release is a no-op as pooled resources are not used with an Encoder.
// This method is kept for compatibility reasons only. // This method is kept for compatibility reasons only.
func (e *Encoder) Release() { func (e *Encoder) Release() {
} }

View File

@ -8,7 +8,7 @@ package codec
import ( import (
"bytes" "bytes"
"encoding/base64" "encoding/base32"
"errors" "errors"
"fmt" "fmt"
"go/format" "go/format"
@ -190,7 +190,11 @@ var (
errGenExpectArrayOrMap = errors.New("unexpected type - expecting array/map/slice") errGenExpectArrayOrMap = errors.New("unexpected type - expecting array/map/slice")
errGenUnexpectedTypeFastpath = errors.New("fast-path: unexpected type - requires map or slice") errGenUnexpectedTypeFastpath = errors.New("fast-path: unexpected type - requires map or slice")
genBase64enc = base64.NewEncoding("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789__") // don't use base64, only 63 characters allowed in valid go identifiers
// ie ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_
//
// don't use numbers, as a valid go identifer must start with a letter.
genTypenameEnc = base32.NewEncoding("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdef")
genQNameRegex = regexp.MustCompile(`[A-Za-z_.]+`) genQNameRegex = regexp.MustCompile(`[A-Za-z_.]+`)
) )
@ -2303,8 +2307,6 @@ func genMethodNameT(t reflect.Type, tRef reflect.Type) (n string) {
} }
} else { } else {
// best way to get the package name inclusive // best way to get the package name inclusive
// return ptrPfx + strings.Replace(tstr, ".", "_", 1000)
// return ptrPfx + genBase64enc.EncodeToString([]byte(tstr))
if t.Name() != "" && genQNameRegex.MatchString(tstr) { if t.Name() != "" && genQNameRegex.MatchString(tstr) {
return ptrPfx + strings.Replace(tstr, ".", "_", 1000) return ptrPfx + strings.Replace(tstr, ".", "_", 1000)
} else { } else {
@ -2315,12 +2317,12 @@ func genMethodNameT(t reflect.Type, tRef reflect.Type) (n string) {
} }
} }
// genCustomNameForType base64encodes the t.String() value in such a way // genCustomNameForType base32 encodes the t.String() value in such a way
// that it can be used within a function name. // that it can be used within a function name.
func genCustomTypeName(tstr string) string { func genCustomTypeName(tstr string) string {
len2 := genBase64enc.EncodedLen(len(tstr)) len2 := genTypenameEnc.EncodedLen(len(tstr))
bufx := make([]byte, len2) bufx := make([]byte, len2)
genBase64enc.Encode(bufx, []byte(tstr)) genTypenameEnc.Encode(bufx, []byte(tstr))
for i := len2 - 1; i >= 0; i-- { for i := len2 - 1; i >= 0; i-- {
if bufx[i] == '=' { if bufx[i] == '=' {
len2-- len2--

View File

@ -110,8 +110,7 @@ package codec
// //
// ------------------------------------------ // ------------------------------------------
// Bounds Checking // Bounds Checking
// - Allow bytesDecReader to incur "bounds check error", and // - Allow bytesDecReader to incur "bounds check error", and recover that as an io error.
// recover that as an io.EOF.
// This allows the bounds check branch to always be taken by the branch predictor, // This allows the bounds check branch to always be taken by the branch predictor,
// giving better performance (in theory), while ensuring that the code is shorter. // giving better performance (in theory), while ensuring that the code is shorter.
// //
@ -857,26 +856,10 @@ type BasicHandle struct {
// Once a Handle has been initialized (used), do not modify this option. It will be ignored. // Once a Handle has been initialized (used), do not modify this option. It will be ignored.
TimeNotBuiltin bool TimeNotBuiltin bool
// ExplicitRelease configures whether Release() is implicitly called after an encode or // ExplicitRelease is ignored and has no effect.
// decode call.
// //
// If you will hold onto an Encoder or Decoder for re-use, by calling Reset(...) // Deprecated: Pools are only used for long-lived objects shared across goroutines.
// on it or calling (Must)Encode repeatedly into a given []byte or io.Writer, // It is maintained for backward compatibility.
// then you do not want it to be implicitly closed after each Encode/Decode call.
// Doing so will unnecessarily return resources to the shared pool, only for you to
// grab them right after again to do another Encode/Decode call.
//
// Instead, you configure ExplicitRelease=true, and you explicitly call Release() when
// you are truly done.
//
// As an alternative, you can explicitly set a finalizer - so its resources
// are returned to the shared pool before it is garbage-collected. Do it as below:
// runtime.SetFinalizer(e, (*Encoder).Release)
// runtime.SetFinalizer(d, (*Decoder).Release)
//
// Deprecated: This is not longer used as pools are only used for long-lived objects
// which are shared across goroutines.
// Setting this value has no effect. It is maintained for backward compatibility.
ExplicitRelease bool ExplicitRelease bool
// ---- cache line // ---- cache line
@ -2489,7 +2472,7 @@ func panicValToErr(h errDecorator, v interface{}, err *error) {
case runtime.Error: case runtime.Error:
d, dok := h.(*Decoder) d, dok := h.(*Decoder)
if dok && d.bytes && isSliceBoundsError(xerr.Error()) { if dok && d.bytes && isSliceBoundsError(xerr.Error()) {
*err = io.EOF *err = io.ErrUnexpectedEOF
} else { } else {
h.wrapErr(xerr, err) h.wrapErr(xerr, err)
} }
@ -2803,7 +2786,7 @@ func freelistCapacity(length int) (capacity int) {
// bytesFreelist is a list of byte buffers, sorted by cap. // bytesFreelist is a list of byte buffers, sorted by cap.
// //
// In anecdotal testing (running go test -tsd 1..6), we couldn't get // In anecdotal testing (running go test -tsd 1..6), we couldn't get
// the length ofthe list > 4 at any time. So we believe a linear search // the length of the list > 4 at any time. So we believe a linear search
// without bounds checking is sufficient. // without bounds checking is sufficient.
// //
// Typical usage model: // Typical usage model:
@ -2821,7 +2804,7 @@ func freelistCapacity(length int) (capacity int) {
// v1 := v0 // v1 := v0
// ... use v1 ... // ... use v1 ...
// blist.put(v1) // blist.put(v1)
// if byteSliceAddr(v0) != byteSliceAddr(v1) { // if !byteSliceSameData(v0, v1) {
// blist.put(v0) // blist.put(v0)
// } // }
type bytesFreelist [][]byte type bytesFreelist [][]byte

View File

@ -1301,6 +1301,9 @@ func (d *jsonDecDriver) DecodeNaked() {
// Note also that the float values for NaN, +Inf or -Inf are encoded as null, // Note also that the float values for NaN, +Inf or -Inf are encoded as null,
// as suggested by NOTE 4 of the ECMA-262 ECMAScript Language Specification 5.1 edition. // as suggested by NOTE 4 of the ECMA-262 ECMAScript Language Specification 5.1 edition.
// see http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf . // see http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf .
//
// Note the following behaviour differences vs std-library encoding/json package:
// - struct field names matched in case-sensitive manner
type JsonHandle struct { type JsonHandle struct {
textEncodingType textEncodingType
BasicHandle BasicHandle

View File

@ -1174,7 +1174,7 @@ func (c *msgpackSpecRpcCodec) ReadRequestBody(body interface{}) error {
func (c *msgpackSpecRpcCodec) parseCustomHeader(expectTypeByte byte, msgid *uint64, methodOrError *string) (err error) { func (c *msgpackSpecRpcCodec) parseCustomHeader(expectTypeByte byte, msgid *uint64, methodOrError *string) (err error) {
if cls := c.cls.load(); cls.closed { if cls := c.cls.load(); cls.closed {
return io.EOF return io.ErrUnexpectedEOF
} }
// We read the response header by hand // We read the response header by hand

View File

@ -350,9 +350,9 @@ func (z *ioDecReader) unreadn1() {
// bytesDecReader is a decReader that reads off a byte slice with zero copying // bytesDecReader is a decReader that reads off a byte slice with zero copying
// //
// Note: we do not try to convert index'ing out of bounds to an io.EOF. // Note: we do not try to convert index'ing out of bounds to an io error.
// instead, we let it bubble up to the exported Encode/Decode method // instead, we let it bubble up to the exported Encode/Decode method
// and recover it as an io.EOF. // and recover it as an io error.
// //
// Every function here MUST defensively check bounds either explicitly // Every function here MUST defensively check bounds either explicitly
// or via a bounds check. // or via a bounds check.

20
vendor/modules.txt vendored
View File

@ -63,7 +63,7 @@ github.com/blang/semver/v4
# github.com/buger/goterm v1.0.4 # github.com/buger/goterm v1.0.4
## explicit; go 1.15 ## explicit; go 1.15
github.com/buger/goterm github.com/buger/goterm
# github.com/bytedance/sonic v1.10.1 # github.com/bytedance/sonic v1.10.2
## explicit; go 1.16 ## explicit; go 1.16
github.com/bytedance/sonic github.com/bytedance/sonic
github.com/bytedance/sonic/ast github.com/bytedance/sonic/ast
@ -97,7 +97,7 @@ github.com/checkpoint-restore/go-criu/v7/stats
# github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d # github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d
## explicit; go 1.16 ## explicit; go 1.16
github.com/chenzhuoyu/base64x github.com/chenzhuoyu/base64x
# github.com/chenzhuoyu/iasm v0.9.0 # github.com/chenzhuoyu/iasm v0.9.1
## explicit; go 1.16 ## explicit; go 1.16
github.com/chenzhuoyu/iasm/expr github.com/chenzhuoyu/iasm/expr
github.com/chenzhuoyu/iasm/x86_64 github.com/chenzhuoyu/iasm/x86_64
@ -429,7 +429,7 @@ github.com/coreos/stream-metadata-go/stream/rhcos
## explicit; go 1.20 ## explicit; go 1.20
github.com/crc-org/crc/v2/pkg/crc/logging github.com/crc-org/crc/v2/pkg/crc/logging
github.com/crc-org/crc/v2/pkg/os github.com/crc-org/crc/v2/pkg/os
# github.com/crc-org/vfkit v0.5.0 # github.com/crc-org/vfkit v0.5.1
## explicit; go 1.18 ## explicit; go 1.18
github.com/crc-org/vfkit/pkg/cmdline github.com/crc-org/vfkit/pkg/cmdline
github.com/crc-org/vfkit/pkg/config github.com/crc-org/vfkit/pkg/config
@ -531,7 +531,7 @@ github.com/fsnotify/fsnotify
# github.com/fsouza/go-dockerclient v1.10.1 # github.com/fsouza/go-dockerclient v1.10.1
## explicit; go 1.20 ## explicit; go 1.20
github.com/fsouza/go-dockerclient github.com/fsouza/go-dockerclient
# github.com/gabriel-vasile/mimetype v1.4.2 # github.com/gabriel-vasile/mimetype v1.4.3
## explicit; go 1.20 ## explicit; go 1.20
github.com/gabriel-vasile/mimetype github.com/gabriel-vasile/mimetype
github.com/gabriel-vasile/mimetype/internal/charset github.com/gabriel-vasile/mimetype/internal/charset
@ -615,7 +615,7 @@ github.com/go-playground/locales/currency
# github.com/go-playground/universal-translator v0.18.1 # github.com/go-playground/universal-translator v0.18.1
## explicit; go 1.18 ## explicit; go 1.18
github.com/go-playground/universal-translator github.com/go-playground/universal-translator
# github.com/go-playground/validator/v10 v10.15.5 # github.com/go-playground/validator/v10 v10.17.0
## explicit; go 1.18 ## explicit; go 1.18
github.com/go-playground/validator/v10 github.com/go-playground/validator/v10
# github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 # github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572
@ -770,7 +770,7 @@ github.com/manifoldco/promptui/screenbuf
# github.com/mattn/go-colorable v0.1.13 # github.com/mattn/go-colorable v0.1.13
## explicit; go 1.15 ## explicit; go 1.15
github.com/mattn/go-colorable github.com/mattn/go-colorable
# github.com/mattn/go-isatty v0.0.19 # github.com/mattn/go-isatty v0.0.20
## explicit; go 1.15 ## explicit; go 1.15
github.com/mattn/go-isatty github.com/mattn/go-isatty
# github.com/mattn/go-runewidth v0.0.15 # github.com/mattn/go-runewidth v0.0.15
@ -974,7 +974,7 @@ github.com/secure-systems-lab/go-securesystemslib/encrypted
# github.com/segmentio/ksuid v1.0.4 # github.com/segmentio/ksuid v1.0.4
## explicit; go 1.12 ## explicit; go 1.12
github.com/segmentio/ksuid github.com/segmentio/ksuid
# github.com/shirou/gopsutil/v3 v3.23.12 # github.com/shirou/gopsutil/v3 v3.24.1
## explicit; go 1.15 ## explicit; go 1.15
github.com/shirou/gopsutil/v3/common github.com/shirou/gopsutil/v3/common
github.com/shirou/gopsutil/v3/cpu github.com/shirou/gopsutil/v3/cpu
@ -1067,7 +1067,7 @@ github.com/twitchyliquid64/golang-asm/unsafeheader
# github.com/u-root/uio v0.0.0-20230305220412-3e8cd9d6bf63 # github.com/u-root/uio v0.0.0-20230305220412-3e8cd9d6bf63
## explicit; go 1.16 ## explicit; go 1.16
github.com/u-root/uio/ulog github.com/u-root/uio/ulog
# github.com/ugorji/go/codec v1.2.11 # github.com/ugorji/go/codec v1.2.12
## explicit; go 1.11 ## explicit; go 1.11
github.com/ugorji/go/codec github.com/ugorji/go/codec
# github.com/ulikunitz/xz v0.5.11 # github.com/ulikunitz/xz v0.5.11
@ -1147,8 +1147,8 @@ go.opentelemetry.io/otel/metric/embedded
## explicit; go 1.20 ## explicit; go 1.20
go.opentelemetry.io/otel/trace go.opentelemetry.io/otel/trace
go.opentelemetry.io/otel/trace/embedded go.opentelemetry.io/otel/trace/embedded
# golang.org/x/arch v0.5.0 # golang.org/x/arch v0.7.0
## explicit; go 1.17 ## explicit; go 1.18
golang.org/x/arch/x86/x86asm golang.org/x/arch/x86/x86asm
# golang.org/x/crypto v0.19.0 # golang.org/x/crypto v0.19.0
## explicit; go 1.18 ## explicit; go 1.18