pkg/proc: use gore to obtain info from stripped binaries (#3577)
This patch switches from using a forked version of one of the libraries of goretk/gore to using the module directly. This is possible now that certain functionality has been exposed / fixed within that module making it usable for Delve.
This commit is contained in:
parent
08eced2f1f
commit
6e8e1cee9b
@ -13,18 +13,18 @@ Tests skipped by each supported backend:
|
|||||||
* 1 broken - cgo stacktraces
|
* 1 broken - cgo stacktraces
|
||||||
* darwin/lldb skipped = 1
|
* darwin/lldb skipped = 1
|
||||||
* 1 upstream issue
|
* 1 upstream issue
|
||||||
* freebsd skipped = 9
|
* freebsd skipped = 10
|
||||||
* 2 flaky
|
* 2 flaky
|
||||||
* 2 follow exec not implemented on freebsd
|
* 2 follow exec not implemented on freebsd
|
||||||
* 4 not implemented
|
* 4 not implemented
|
||||||
* 1 not working on freebsd
|
* 2 not working on freebsd
|
||||||
* linux/386 skipped = 1
|
* linux/386 skipped = 2
|
||||||
* 1 not working on linux/386
|
* 2 not working on linux/386
|
||||||
* linux/386/pie skipped = 1
|
* linux/386/pie skipped = 1
|
||||||
* 1 broken
|
* 1 broken
|
||||||
* linux/ppc64le skipped = 2
|
* linux/ppc64le skipped = 3
|
||||||
* 1 broken - cgo stacktraces
|
* 1 broken - cgo stacktraces
|
||||||
* 1 not working on linux/ppc64le when -gcflags=-N -l is passed
|
* 2 not working on linux/ppc64le when -gcflags=-N -l is passed
|
||||||
* linux/ppc64le/native skipped = 1
|
* linux/ppc64le/native skipped = 1
|
||||||
* 1 broken in linux ppc64le
|
* 1 broken in linux ppc64le
|
||||||
* linux/ppc64le/native/pie skipped = 3
|
* linux/ppc64le/native/pie skipped = 3
|
||||||
@ -35,9 +35,9 @@ Tests skipped by each supported backend:
|
|||||||
* 6 broken
|
* 6 broken
|
||||||
* 1 broken - global variable symbolication
|
* 1 broken - global variable symbolication
|
||||||
* 4 not implemented
|
* 4 not implemented
|
||||||
* windows skipped = 5
|
* windows skipped = 6
|
||||||
* 1 broken
|
* 1 broken
|
||||||
* 1 not working on windows
|
* 2 not working on windows
|
||||||
* 3 see https://github.com/go-delve/delve/issues/2768
|
* 3 see https://github.com/go-delve/delve/issues/2768
|
||||||
* windows/arm64 skipped = 5
|
* windows/arm64 skipped = 5
|
||||||
* 3 broken
|
* 3 broken
|
||||||
|
|||||||
5
go.mod
5
go.mod
@ -9,6 +9,7 @@ require (
|
|||||||
github.com/derekparker/trie v0.0.0-20230829180723-39f4de51ef7d
|
github.com/derekparker/trie v0.0.0-20230829180723-39f4de51ef7d
|
||||||
github.com/go-delve/liner v1.2.3-0.20220127212407-d32d89dd2a5d
|
github.com/go-delve/liner v1.2.3-0.20220127212407-d32d89dd2a5d
|
||||||
github.com/google/go-dap v0.11.0
|
github.com/google/go-dap v0.11.0
|
||||||
|
github.com/goretk/gore v0.11.3
|
||||||
github.com/hashicorp/golang-lru v1.0.2
|
github.com/hashicorp/golang-lru v1.0.2
|
||||||
github.com/mattn/go-colorable v0.1.13
|
github.com/mattn/go-colorable v0.1.13
|
||||||
github.com/mattn/go-isatty v0.0.20
|
github.com/mattn/go-isatty v0.0.20
|
||||||
@ -16,7 +17,7 @@ require (
|
|||||||
github.com/spf13/cobra v1.7.0
|
github.com/spf13/cobra v1.7.0
|
||||||
github.com/spf13/pflag v1.0.5
|
github.com/spf13/pflag v1.0.5
|
||||||
go.starlark.net v0.0.0-20231101134539-556fd59b42f6
|
go.starlark.net v0.0.0-20231101134539-556fd59b42f6
|
||||||
golang.org/x/arch v0.5.0
|
golang.org/x/arch v0.6.0
|
||||||
golang.org/x/sys v0.13.0
|
golang.org/x/sys v0.13.0
|
||||||
golang.org/x/tools v0.14.0
|
golang.org/x/tools v0.14.0
|
||||||
gopkg.in/yaml.v2 v2.4.0
|
gopkg.in/yaml.v2 v2.4.0
|
||||||
@ -29,6 +30,6 @@ require (
|
|||||||
github.com/rivo/uniseg v0.2.0 // indirect
|
github.com/rivo/uniseg v0.2.0 // indirect
|
||||||
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||||
golang.org/x/exp v0.0.0-20230224173230-c95f2b4c22f2 // indirect
|
golang.org/x/exp v0.0.0-20230224173230-c95f2b4c22f2 // indirect
|
||||||
golang.org/x/mod v0.13.0 // indirect
|
golang.org/x/mod v0.14.0 // indirect
|
||||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
)
|
)
|
||||||
|
|||||||
131
go.sum
131
go.sum
@ -1,17 +1,9 @@
|
|||||||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
|
||||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
|
||||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
|
||||||
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
|
||||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
|
||||||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
|
||||||
github.com/cilium/ebpf v0.11.0 h1:V8gS/bTCCjX9uUnkUFUpPsksM8n1lXBAvHcpiFk1X2Y=
|
github.com/cilium/ebpf v0.11.0 h1:V8gS/bTCCjX9uUnkUFUpPsksM8n1lXBAvHcpiFk1X2Y=
|
||||||
github.com/cilium/ebpf v0.11.0/go.mod h1:WE7CZAnqOL2RouJ4f1uyNhqr2P4CCvXFIqdRDUgWsVs=
|
github.com/cilium/ebpf v0.11.0/go.mod h1:WE7CZAnqOL2RouJ4f1uyNhqr2P4CCvXFIqdRDUgWsVs=
|
||||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
|
||||||
github.com/cosiner/argv v0.1.0 h1:BVDiEL32lwHukgJKP87btEPenzrrHUjajs/8yzaqcXg=
|
github.com/cosiner/argv v0.1.0 h1:BVDiEL32lwHukgJKP87btEPenzrrHUjajs/8yzaqcXg=
|
||||||
github.com/cosiner/argv v0.1.0/go.mod h1:EusR6TucWKX+zFgtdUsKT2Cvg45K5rtpCcWz4hK06d8=
|
github.com/cosiner/argv v0.1.0/go.mod h1:EusR6TucWKX+zFgtdUsKT2Cvg45K5rtpCcWz4hK06d8=
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w=
|
github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w=
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
|
||||||
github.com/creack/pty v1.1.20 h1:VIPb/a2s17qNeQgDnkfZC35RScx+blkKF8GV68n80J4=
|
github.com/creack/pty v1.1.20 h1:VIPb/a2s17qNeQgDnkfZC35RScx+blkKF8GV68n80J4=
|
||||||
github.com/creack/pty v1.1.20/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4=
|
github.com/creack/pty v1.1.20/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4=
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
@ -19,33 +11,16 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
|
|||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/derekparker/trie v0.0.0-20230829180723-39f4de51ef7d h1:hUWoLdw5kvo2xCsqlsIBMvWUc1QCSsCYD2J2+Fg6YoU=
|
github.com/derekparker/trie v0.0.0-20230829180723-39f4de51ef7d h1:hUWoLdw5kvo2xCsqlsIBMvWUc1QCSsCYD2J2+Fg6YoU=
|
||||||
github.com/derekparker/trie v0.0.0-20230829180723-39f4de51ef7d/go.mod h1:C7Es+DLenIpPc9J6IYw4jrK0h7S9bKj4DNl8+KxGEXU=
|
github.com/derekparker/trie v0.0.0-20230829180723-39f4de51ef7d/go.mod h1:C7Es+DLenIpPc9J6IYw4jrK0h7S9bKj4DNl8+KxGEXU=
|
||||||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
|
||||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
|
||||||
github.com/frankban/quicktest v1.14.5 h1:dfYrrRyLtiqT9GyKXgdh+k4inNeTvmGbuSgZ3lx3GhA=
|
github.com/frankban/quicktest v1.14.5 h1:dfYrrRyLtiqT9GyKXgdh+k4inNeTvmGbuSgZ3lx3GhA=
|
||||||
github.com/frankban/quicktest v1.14.5/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
|
github.com/frankban/quicktest v1.14.5/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
|
||||||
github.com/go-delve/liner v1.2.3-0.20220127212407-d32d89dd2a5d h1:pxjSLshkZJGLVm0wv20f/H0oTWiq/egkoJQ2ja6LEvo=
|
github.com/go-delve/liner v1.2.3-0.20220127212407-d32d89dd2a5d h1:pxjSLshkZJGLVm0wv20f/H0oTWiq/egkoJQ2ja6LEvo=
|
||||||
github.com/go-delve/liner v1.2.3-0.20220127212407-d32d89dd2a5d/go.mod h1:biJCRbqp51wS+I92HMqn5H8/A0PAhxn2vyOT+JqhiGI=
|
github.com/go-delve/liner v1.2.3-0.20220127212407-d32d89dd2a5d/go.mod h1:biJCRbqp51wS+I92HMqn5H8/A0PAhxn2vyOT+JqhiGI=
|
||||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
|
||||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
|
||||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
|
||||||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
|
||||||
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
|
|
||||||
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
|
|
||||||
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
|
|
||||||
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
|
|
||||||
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
|
|
||||||
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
|
|
||||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
|
||||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
|
||||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
|
||||||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
|
||||||
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
|
||||||
github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
|
||||||
github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
|
||||||
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
||||||
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||||
github.com/google/go-dap v0.11.0 h1:SpAZJL41rOOvd85PuLCCLE1dteTQOyKNnn0H3DBHywo=
|
github.com/google/go-dap v0.11.0 h1:SpAZJL41rOOvd85PuLCCLE1dteTQOyKNnn0H3DBHywo=
|
||||||
github.com/google/go-dap v0.11.0/go.mod h1:HAeyoSd2WIfTfg+0GRXcFrb+RnojAtGNh+k+XTIxJDE=
|
github.com/google/go-dap v0.11.0/go.mod h1:HAeyoSd2WIfTfg+0GRXcFrb+RnojAtGNh+k+XTIxJDE=
|
||||||
|
github.com/goretk/gore v0.11.3 h1:Igk+aBl3sVEp0j6paNMaNs9hXeqC5GO9YHDqVBqiWiA=
|
||||||
|
github.com/goretk/gore v0.11.3/go.mod h1:MMkaJmF/reDsujtnLvSJBFdA5b/aZXcVKfKmMjLR+qo=
|
||||||
github.com/hashicorp/golang-lru v1.0.2 h1:dV3g9Z/unq5DpblPpw+Oqcv4dU/1omnb4Ok8iPY6p1c=
|
github.com/hashicorp/golang-lru v1.0.2 h1:dV3g9Z/unq5DpblPpw+Oqcv4dU/1omnb4Ok8iPY6p1c=
|
||||||
github.com/hashicorp/golang-lru v1.0.2/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
|
github.com/hashicorp/golang-lru v1.0.2/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
|
||||||
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
|
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
|
||||||
@ -62,10 +37,8 @@ github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D
|
|||||||
github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
|
github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
|
||||||
github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU=
|
github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU=
|
||||||
github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||||
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
|
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
|
||||||
github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
|
github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
|
||||||
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||||
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
|
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
|
||||||
@ -79,112 +52,27 @@ github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRM
|
|||||||
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
|
||||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
||||||
|
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||||
go.starlark.net v0.0.0-20231101134539-556fd59b42f6 h1:+eC0F/k4aBLC4szgOcjd7bDTEnpxADJyWJE0yowgM3E=
|
go.starlark.net v0.0.0-20231101134539-556fd59b42f6 h1:+eC0F/k4aBLC4szgOcjd7bDTEnpxADJyWJE0yowgM3E=
|
||||||
go.starlark.net v0.0.0-20231101134539-556fd59b42f6/go.mod h1:LcLNIzVOMp4oV+uusnpk+VU+SzXaJakUuBjoCSWH5dM=
|
go.starlark.net v0.0.0-20231101134539-556fd59b42f6/go.mod h1:LcLNIzVOMp4oV+uusnpk+VU+SzXaJakUuBjoCSWH5dM=
|
||||||
golang.org/x/arch v0.5.0 h1:jpGode6huXQxcskEIpOCvrU+tzo81b6+oFLUYXWtH/Y=
|
golang.org/x/arch v0.6.0 h1:S0JTfE48HbRj80+4tbvZDYsJ3tGv6BUU3XxyZ7CirAc=
|
||||||
golang.org/x/arch v0.5.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
|
golang.org/x/arch v0.6.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys=
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
|
||||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
|
||||||
golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw=
|
|
||||||
golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
|
|
||||||
golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
|
|
||||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
|
||||||
golang.org/x/exp v0.0.0-20230224173230-c95f2b4c22f2 h1:Jvc7gsqn21cJHCmAWx0LiimpP18LZmUxkT5Mp7EZ1mI=
|
golang.org/x/exp v0.0.0-20230224173230-c95f2b4c22f2 h1:Jvc7gsqn21cJHCmAWx0LiimpP18LZmUxkT5Mp7EZ1mI=
|
||||||
golang.org/x/exp v0.0.0-20230224173230-c95f2b4c22f2/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc=
|
golang.org/x/exp v0.0.0-20230224173230-c95f2b4c22f2/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc=
|
||||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0=
|
||||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||||
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
|
||||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
|
||||||
golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI=
|
|
||||||
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
|
||||||
golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
|
||||||
golang.org/x/mod v0.13.0 h1:I/DsJXRlw/8l/0c24sM9yb0T4z9liZTduXvdAWYiysY=
|
|
||||||
golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
|
||||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
|
||||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
|
||||||
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
|
||||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
|
||||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
|
||||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
|
||||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
|
||||||
golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco=
|
|
||||||
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
|
||||||
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
|
||||||
golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
|
|
||||||
golang.org/x/net v0.16.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
|
|
||||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
|
||||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
|
||||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
|
||||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
|
||||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
|
||||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
|
||||||
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
|
|
||||||
golang.org/x/sync v0.4.0 h1:zxkM55ReGkDlKSM+Fu41A+zmbZuaPVbGMzvvdUPznYQ=
|
golang.org/x/sync v0.4.0 h1:zxkM55ReGkDlKSM+Fu41A+zmbZuaPVbGMzvvdUPznYQ=
|
||||||
golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
|
golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
|
||||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
|
||||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
||||||
golang.org/x/sys v0.0.0-20211117180635-dee7805ff2e1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20211117180635-dee7805ff2e1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
||||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
||||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
||||||
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.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
||||||
golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
|
golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
|
||||||
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
|
||||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
|
||||||
golang.org/x/term v0.0.0-20220526004731-065cf7ba2467/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
|
||||||
golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
|
||||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
|
||||||
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
|
|
||||||
golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU=
|
|
||||||
golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U=
|
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
|
||||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
|
||||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
|
||||||
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
|
||||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
|
||||||
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
|
||||||
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
|
||||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
|
||||||
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
|
||||||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
|
||||||
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
|
||||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
|
||||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
|
||||||
golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA=
|
|
||||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
|
||||||
golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
|
|
||||||
golang.org/x/tools v0.14.0 h1:jvNa2pY0M4r62jkRQ6RwEZZyPcymeL9XZMLBbV7U2nc=
|
golang.org/x/tools v0.14.0 h1:jvNa2pY0M4r62jkRQ6RwEZZyPcymeL9XZMLBbV7U2nc=
|
||||||
golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg=
|
golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg=
|
||||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
|
||||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
|
||||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
|
||||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
|
||||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
|
||||||
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
|
||||||
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
|
|
||||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
|
||||||
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
|
||||||
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
|
||||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
|
||||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
|
||||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
|
||||||
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
|
|
||||||
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
|
|
||||||
google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
|
||||||
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
|
||||||
google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c=
|
google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c=
|
||||||
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
|
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||||
@ -194,6 +82,3 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
|||||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
|
||||||
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
|
||||||
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
|
|
||||||
|
|||||||
BIN
inlinestripped
Executable file
BIN
inlinestripped
Executable file
Binary file not shown.
@ -9,6 +9,7 @@ package gosym
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"debug/elf"
|
"debug/elf"
|
||||||
|
"debug/macho"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
@ -150,6 +151,15 @@ func ProgContaining(elfFile *elf.File, addr uint64) *elf.Prog {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func SegmentContaining(exe *macho.File, addr uint64) *macho.Segment {
|
||||||
|
for _, l := range exe.Loads {
|
||||||
|
if s, ok := l.(*macho.Segment); ok && s.Addr <= addr && addr < s.Addr+s.Filesz {
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// An Obj represents a collection of functions in a symbol table.
|
// An Obj represents a collection of functions in a symbol table.
|
||||||
//
|
//
|
||||||
// The exact method of division of a binary into separate Objs is an internal detail
|
// The exact method of division of a binary into separate Objs is an internal detail
|
||||||
|
|||||||
@ -1,86 +0,0 @@
|
|||||||
// This package implements the parsing and usage of the moduledata
|
|
||||||
// structs from a binary.
|
|
||||||
// This code is mostly taken and adapted from https://github.com/goretk/gore.
|
|
||||||
package moduledata
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"debug/elf"
|
|
||||||
"encoding/binary"
|
|
||||||
"errors"
|
|
||||||
)
|
|
||||||
|
|
||||||
// GetGoFuncValue is used to acquire the value of the
|
|
||||||
// "go:func.*" symbol in stripped binaries.
|
|
||||||
// TODO(derekparker) support Mach-O, PE.
|
|
||||||
func GetGoFuncValue(f *elf.File, pclntabAddr uint64) (uint64, error) {
|
|
||||||
s := f.Section(".noptrdata")
|
|
||||||
if s == nil {
|
|
||||||
return 0, errors.New("unable to find .noptrdata section")
|
|
||||||
}
|
|
||||||
data, err := s.Data()
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
buf := new(bytes.Buffer)
|
|
||||||
err = binary.Write(buf, binary.LittleEndian, &pclntabAddr)
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
off := bytes.Index(data, buf.Bytes()[:8])
|
|
||||||
|
|
||||||
var md moduledata2064
|
|
||||||
err = binary.Read(bytes.NewReader(data[off:off+0x340]), f.ByteOrder, &md)
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
return md.GoFunc, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type moduledata2064 struct {
|
|
||||||
PcHeader uint64
|
|
||||||
Funcnametab, Funcnametablen, Funcnametabcap uint64
|
|
||||||
Cutab, Cutablen, Cutabcap uint64
|
|
||||||
Filetab, Filetablen, Filetabcap uint64
|
|
||||||
Pctab, Pctablen, Pctabcap uint64
|
|
||||||
Pclntable, Pclntablelen, Pclntablecap uint64
|
|
||||||
Ftab, Ftablen, Ftabcap uint64
|
|
||||||
Findfunctab uint64
|
|
||||||
Minpc, Maxpc uint64
|
|
||||||
|
|
||||||
Text, Etext uint64
|
|
||||||
Noptrdata, Enoptrdata uint64
|
|
||||||
Data, Edata uint64
|
|
||||||
Bss, Ebss uint64
|
|
||||||
Noptrbss, Enoptrbss uint64
|
|
||||||
Covctrs, Ecovctrs uint64
|
|
||||||
End, Gcdata, Gcbss uint64
|
|
||||||
Types, Etypes uint64
|
|
||||||
RData uint64
|
|
||||||
GoFunc uint64
|
|
||||||
|
|
||||||
Textsectmap, Textsectmaplen, Textsectmapcap uint64
|
|
||||||
Typelinks, Typelinkslen, Typelinkscap uint64 // offsets from types
|
|
||||||
Itablinks, Itablinkslen, Itablinkscap uint64
|
|
||||||
|
|
||||||
Ptab, Ptablen, Ptabcap uint64
|
|
||||||
|
|
||||||
Pluginpath, Pluginpathlen uint64
|
|
||||||
Pkghashes, Pkghasheslen, Pkghashescap uint64
|
|
||||||
|
|
||||||
Modulename, Modulenamelen uint64
|
|
||||||
Modulehashes, Modulehasheslen, Modulehashescap uint64
|
|
||||||
|
|
||||||
/* These fields we are not planning to use so skipping the parsing of them.
|
|
||||||
|
|
||||||
hasmain uint8 // 1 if module contains the main function, 0 otherwise
|
|
||||||
|
|
||||||
gcdatamask, gcbssmask bitvector
|
|
||||||
|
|
||||||
typemap map[typeOff]*_type // offset to *_rtype in previous module
|
|
||||||
|
|
||||||
bad bool // module failed to load and should be ignored
|
|
||||||
|
|
||||||
next *moduledata
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
@ -1,67 +0,0 @@
|
|||||||
package moduledata
|
|
||||||
|
|
||||||
import (
|
|
||||||
"debug/elf"
|
|
||||||
"github.com/go-delve/delve/pkg/goversion"
|
|
||||||
"os"
|
|
||||||
"os/exec"
|
|
||||||
"runtime"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestGetGoFuncValue(t *testing.T) {
|
|
||||||
if runtime.GOOS != "linux" || runtime.GOARCH != "amd64" {
|
|
||||||
t.Skipf("skipping since not linux/amd64")
|
|
||||||
}
|
|
||||||
if !goversion.VersionAfterOrEqual(runtime.Version(), 1, 20) {
|
|
||||||
t.Skip("temporarily disabled on Go versions < 1.20")
|
|
||||||
}
|
|
||||||
bin := "getgofuncvaltestbin"
|
|
||||||
|
|
||||||
err := exec.Command("go", "build", "-o", bin, "../../../_fixtures/traceprog.go").Run()
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
defer func(name string) {
|
|
||||||
err := os.Remove(name)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
}(bin)
|
|
||||||
|
|
||||||
file, err := elf.Open(bin)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
s := file.Section(".gopclntab")
|
|
||||||
|
|
||||||
goFuncValue, err := GetGoFuncValue(file, s.Addr)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
goFuncSymValue := getGoFuncSymValue(file, t)
|
|
||||||
if goFuncSymValue == 0 {
|
|
||||||
t.Fatal("unable to find value for go:func.* symbol")
|
|
||||||
}
|
|
||||||
|
|
||||||
t.Logf("gofuncVal: %#v goFuncSymValue: %#v\n", goFuncValue, goFuncSymValue)
|
|
||||||
|
|
||||||
if goFuncValue != goFuncSymValue {
|
|
||||||
t.Fatalf("expected goFuncValue %#v to equal goFuncSymValue %#v", goFuncValue, goFuncSymValue)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func getGoFuncSymValue(f *elf.File, t *testing.T) uint64 {
|
|
||||||
syms, err := f.Symbols()
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
for i := range syms {
|
|
||||||
if syms[i].Name == "go:func.*" {
|
|
||||||
return syms[i].Value
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
@ -31,9 +31,9 @@ import (
|
|||||||
"github.com/go-delve/delve/pkg/dwarf/reader"
|
"github.com/go-delve/delve/pkg/dwarf/reader"
|
||||||
"github.com/go-delve/delve/pkg/goversion"
|
"github.com/go-delve/delve/pkg/goversion"
|
||||||
"github.com/go-delve/delve/pkg/internal/gosym"
|
"github.com/go-delve/delve/pkg/internal/gosym"
|
||||||
"github.com/go-delve/delve/pkg/internal/moduledata"
|
|
||||||
"github.com/go-delve/delve/pkg/logflags"
|
"github.com/go-delve/delve/pkg/logflags"
|
||||||
"github.com/go-delve/delve/pkg/proc/debuginfod"
|
"github.com/go-delve/delve/pkg/proc/debuginfod"
|
||||||
|
"github.com/goretk/gore"
|
||||||
"github.com/hashicorp/golang-lru/simplelru"
|
"github.com/hashicorp/golang-lru/simplelru"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -1458,21 +1458,25 @@ func loadBinaryInfoElf(bi *BinaryInfo, image *Image, path string, addr uint64, w
|
|||||||
}
|
}
|
||||||
cu := &compileUnit{}
|
cu := &compileUnit{}
|
||||||
cu.image = image
|
cu.image = image
|
||||||
symTable, pcLnTabAddr, err := readPcLnTableElf(elfFile, path)
|
symTable, _, err := readPcLnTableElf(elfFile, path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("could not read debug info (%v) and could not read go symbol table (%v)", dwerr, err)
|
return fmt.Errorf("could not read debug info (%v) and could not read go symbol table (%v)", dwerr, err)
|
||||||
}
|
}
|
||||||
image.symTable = symTable
|
image.symTable = symTable
|
||||||
goFuncVal, err := moduledata.GetGoFuncValue(elfFile, pcLnTabAddr)
|
gorefile, err := gore.Open(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
prog := gosym.ProgContaining(elfFile, goFuncVal)
|
md, err := gorefile.Moduledata()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
prog := gosym.ProgContaining(elfFile, md.GoFuncValue())
|
||||||
inlFuncs := make(map[string]*Function)
|
inlFuncs := make(map[string]*Function)
|
||||||
for _, f := range image.symTable.Funcs {
|
for _, f := range image.symTable.Funcs {
|
||||||
fnEntry := f.Entry + image.StaticBase
|
fnEntry := f.Entry + image.StaticBase
|
||||||
if prog != nil {
|
if prog != nil {
|
||||||
inlCalls, err := image.symTable.GetInlineTree(&f, goFuncVal, prog.Vaddr, prog.ReaderAt)
|
inlCalls, err := image.symTable.GetInlineTree(&f, md.GoFuncValue(), prog.Vaddr, prog.ReaderAt)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -1867,15 +1871,53 @@ func loadBinaryInfoMacho(bi *BinaryInfo, image *Image, path string, entryPoint u
|
|||||||
return fmt.Errorf("could not read debug info (%v) and could not read go symbol table (%v)", dwerr, err)
|
return fmt.Errorf("could not read debug info (%v) and could not read go symbol table (%v)", dwerr, err)
|
||||||
}
|
}
|
||||||
image.symTable = symTable
|
image.symTable = symTable
|
||||||
for _, f := range image.symTable.Funcs {
|
|
||||||
cu := &compileUnit{}
|
cu := &compileUnit{}
|
||||||
cu.image = image
|
cu.image = image
|
||||||
fn := Function{Name: f.Name, Entry: f.Entry + image.StaticBase, End: f.End + image.StaticBase, cu: cu}
|
gorefile, err := gore.Open(path)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
md, err := gorefile.Moduledata()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
seg := gosym.SegmentContaining(exe, md.GoFuncValue())
|
||||||
|
inlFuncs := make(map[string]*Function)
|
||||||
|
for _, f := range image.symTable.Funcs {
|
||||||
|
fnEntry := f.Entry + image.StaticBase
|
||||||
|
if seg != nil {
|
||||||
|
inlCalls, err := image.symTable.GetInlineTree(&f, md.GoFuncValue(), seg.Addr, seg.ReaderAt)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
for _, inlfn := range inlCalls {
|
||||||
|
newInlinedCall := InlinedCall{cu: cu, LowPC: fnEntry + uint64(inlfn.ParentPC)}
|
||||||
|
if fn, ok := inlFuncs[inlfn.Name]; ok {
|
||||||
|
fn.InlinedCalls = append(fn.InlinedCalls, newInlinedCall)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
inlFuncs[inlfn.Name] = &Function{
|
||||||
|
Name: inlfn.Name,
|
||||||
|
Entry: 0, End: 0,
|
||||||
|
cu: cu,
|
||||||
|
InlinedCalls: []InlinedCall{
|
||||||
|
newInlinedCall,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn := Function{Name: f.Name, Entry: fnEntry, End: f.End + image.StaticBase, cu: cu}
|
||||||
bi.Functions = append(bi.Functions, fn)
|
bi.Functions = append(bi.Functions, fn)
|
||||||
}
|
}
|
||||||
|
for i := range inlFuncs {
|
||||||
|
bi.Functions = append(bi.Functions, *inlFuncs[i])
|
||||||
|
}
|
||||||
|
sort.Sort(functionsDebugInfoByEntry(bi.Functions))
|
||||||
for f := range image.symTable.Files {
|
for f := range image.symTable.Files {
|
||||||
bi.Sources = append(bi.Sources, f)
|
bi.Sources = append(bi.Sources, f)
|
||||||
}
|
}
|
||||||
|
sort.Strings(bi.Sources)
|
||||||
|
bi.Sources = uniq(bi.Sources)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
debugInfoBytes, err := godwarf.GetDebugSectionMacho(exe, "info")
|
debugInfoBytes, err := godwarf.GetDebugSectionMacho(exe, "info")
|
||||||
|
|||||||
@ -3204,12 +3204,15 @@ func TestDebugStripped(t *testing.T) {
|
|||||||
|
|
||||||
func TestDebugStripped2(t *testing.T) {
|
func TestDebugStripped2(t *testing.T) {
|
||||||
// Currently only implemented for Linux ELF executables.
|
// Currently only implemented for Linux ELF executables.
|
||||||
// TODO(derekparker): Add support for Mach-O and PE.
|
// TODO(derekparker): Add support for PE.
|
||||||
skipUnlessOn(t, "linux/amd64 only", "linux", "amd64")
|
skipOn(t, "not working on windows", "windows")
|
||||||
|
skipOn(t, "not working on freebsd", "freebsd")
|
||||||
|
skipOn(t, "not working on linux/386", "linux", "386")
|
||||||
|
skipOn(t, "not working on linux/ppc64le when -gcflags=-N -l is passed", "linux", "ppc64le")
|
||||||
if !goversion.VersionAfterOrEqual(runtime.Version(), 1, 20) {
|
if !goversion.VersionAfterOrEqual(runtime.Version(), 1, 20) {
|
||||||
t.Skip("temporarily disabled on Go versions < 1.20")
|
t.Skip("temporarily disabled on Go versions < 1.20")
|
||||||
}
|
}
|
||||||
withTestProcessArgs("inlinestripped", t, "", []string{}, protest.EnableInlining|protest.LinkStrip, func(p *proc.Target, grp *proc.TargetGroup, f protest.Fixture) {
|
withTestProcessArgs("inlinestripped", t, "", []string{}, protest.EnableInlining|protest.LinkStrip|protest.LinkDisableDWARF, func(p *proc.Target, grp *proc.TargetGroup, f protest.Fixture) {
|
||||||
setFunctionBreakpointAll(p, t, "fmt.Println")
|
setFunctionBreakpointAll(p, t, "fmt.Println")
|
||||||
|
|
||||||
for i, line := range []int{12, 13, 14} {
|
for i, line := range []int{12, 13, 14} {
|
||||||
|
|||||||
15
vendor/github.com/goretk/gore/.gitignore
generated
vendored
Normal file
15
vendor/github.com/goretk/gore/.gitignore
generated
vendored
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
# Binaries for programs and plugins
|
||||||
|
*.exe
|
||||||
|
*.exe~
|
||||||
|
*.dll
|
||||||
|
*.so
|
||||||
|
*.dylib
|
||||||
|
|
||||||
|
# Test binary, build with `go test -c`
|
||||||
|
*.test
|
||||||
|
|
||||||
|
# Output of the go coverage tool, specifically when used with LiteIDE
|
||||||
|
*.out
|
||||||
|
*.swp
|
||||||
|
|
||||||
|
.vscode/*
|
||||||
3
vendor/github.com/goretk/gore/.gitmodules
generated
vendored
Normal file
3
vendor/github.com/goretk/gore/.gitmodules
generated
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
[submodule "testdata/gold"]
|
||||||
|
path = testdata/gold
|
||||||
|
url = https://github.com/goretk/testdata.git
|
||||||
27
vendor/github.com/goretk/gore/CONTRIBUTING.md
generated
vendored
Normal file
27
vendor/github.com/goretk/gore/CONTRIBUTING.md
generated
vendored
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
# Want to contribute?
|
||||||
|
|
||||||
|
We welcome tickets, pull requests, feature suggestions.
|
||||||
|
|
||||||
|
When developing, please try to comply to the general code style that we try to
|
||||||
|
maintain across the project. When introducing new features or fixing
|
||||||
|
significant bugs, please provide tests and also include some concise
|
||||||
|
information.
|
||||||
|
|
||||||
|
## Test resources
|
||||||
|
|
||||||
|
A lot of tests in the library requires test resources. Due to the total size of
|
||||||
|
these files, they are not included with the source code. The `testdata` folder
|
||||||
|
contains a helper script that can be used to build them. For building the
|
||||||
|
resources locally `docker` is used. They are also stored in a separate repo that
|
||||||
|
can be accessed by running: `git submodule update --init --recursive`
|
||||||
|
|
||||||
|
Build missing resources:
|
||||||
|
```
|
||||||
|
./testdata/helper.sh build
|
||||||
|
```
|
||||||
|
|
||||||
|
## Download the latest Go compiler release information
|
||||||
|
|
||||||
|
```
|
||||||
|
go generate
|
||||||
|
```
|
||||||
661
vendor/github.com/goretk/gore/LICENSE
generated
vendored
Normal file
661
vendor/github.com/goretk/gore/LICENSE
generated
vendored
Normal file
@ -0,0 +1,661 @@
|
|||||||
|
GNU AFFERO GENERAL PUBLIC LICENSE
|
||||||
|
Version 3, 19 November 2007
|
||||||
|
|
||||||
|
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
||||||
|
Everyone is permitted to copy and distribute verbatim copies
|
||||||
|
of this license document, but changing it is not allowed.
|
||||||
|
|
||||||
|
Preamble
|
||||||
|
|
||||||
|
The GNU Affero General Public License is a free, copyleft license for
|
||||||
|
software and other kinds of works, specifically designed to ensure
|
||||||
|
cooperation with the community in the case of network server software.
|
||||||
|
|
||||||
|
The licenses for most software and other practical works are designed
|
||||||
|
to take away your freedom to share and change the works. By contrast,
|
||||||
|
our General Public Licenses are intended to guarantee your freedom to
|
||||||
|
share and change all versions of a program--to make sure it remains free
|
||||||
|
software for all its users.
|
||||||
|
|
||||||
|
When we speak of free software, we are referring to freedom, not
|
||||||
|
price. Our General Public Licenses are designed to make sure that you
|
||||||
|
have the freedom to distribute copies of free software (and charge for
|
||||||
|
them if you wish), that you receive source code or can get it if you
|
||||||
|
want it, that you can change the software or use pieces of it in new
|
||||||
|
free programs, and that you know you can do these things.
|
||||||
|
|
||||||
|
Developers that use our General Public Licenses protect your rights
|
||||||
|
with two steps: (1) assert copyright on the software, and (2) offer
|
||||||
|
you this License which gives you legal permission to copy, distribute
|
||||||
|
and/or modify the software.
|
||||||
|
|
||||||
|
A secondary benefit of defending all users' freedom is that
|
||||||
|
improvements made in alternate versions of the program, if they
|
||||||
|
receive widespread use, become available for other developers to
|
||||||
|
incorporate. Many developers of free software are heartened and
|
||||||
|
encouraged by the resulting cooperation. However, in the case of
|
||||||
|
software used on network servers, this result may fail to come about.
|
||||||
|
The GNU General Public License permits making a modified version and
|
||||||
|
letting the public access it on a server without ever releasing its
|
||||||
|
source code to the public.
|
||||||
|
|
||||||
|
The GNU Affero General Public License is designed specifically to
|
||||||
|
ensure that, in such cases, the modified source code becomes available
|
||||||
|
to the community. It requires the operator of a network server to
|
||||||
|
provide the source code of the modified version running there to the
|
||||||
|
users of that server. Therefore, public use of a modified version, on
|
||||||
|
a publicly accessible server, gives the public access to the source
|
||||||
|
code of the modified version.
|
||||||
|
|
||||||
|
An older license, called the Affero General Public License and
|
||||||
|
published by Affero, was designed to accomplish similar goals. This is
|
||||||
|
a different license, not a version of the Affero GPL, but Affero has
|
||||||
|
released a new version of the Affero GPL which permits relicensing under
|
||||||
|
this license.
|
||||||
|
|
||||||
|
The precise terms and conditions for copying, distribution and
|
||||||
|
modification follow.
|
||||||
|
|
||||||
|
TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
0. Definitions.
|
||||||
|
|
||||||
|
"This License" refers to version 3 of the GNU Affero General Public License.
|
||||||
|
|
||||||
|
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||||
|
works, such as semiconductor masks.
|
||||||
|
|
||||||
|
"The Program" refers to any copyrightable work licensed under this
|
||||||
|
License. Each licensee is addressed as "you". "Licensees" and
|
||||||
|
"recipients" may be individuals or organizations.
|
||||||
|
|
||||||
|
To "modify" a work means to copy from or adapt all or part of the work
|
||||||
|
in a fashion requiring copyright permission, other than the making of an
|
||||||
|
exact copy. The resulting work is called a "modified version" of the
|
||||||
|
earlier work or a work "based on" the earlier work.
|
||||||
|
|
||||||
|
A "covered work" means either the unmodified Program or a work based
|
||||||
|
on the Program.
|
||||||
|
|
||||||
|
To "propagate" a work means to do anything with it that, without
|
||||||
|
permission, would make you directly or secondarily liable for
|
||||||
|
infringement under applicable copyright law, except executing it on a
|
||||||
|
computer or modifying a private copy. Propagation includes copying,
|
||||||
|
distribution (with or without modification), making available to the
|
||||||
|
public, and in some countries other activities as well.
|
||||||
|
|
||||||
|
To "convey" a work means any kind of propagation that enables other
|
||||||
|
parties to make or receive copies. Mere interaction with a user through
|
||||||
|
a computer network, with no transfer of a copy, is not conveying.
|
||||||
|
|
||||||
|
An interactive user interface displays "Appropriate Legal Notices"
|
||||||
|
to the extent that it includes a convenient and prominently visible
|
||||||
|
feature that (1) displays an appropriate copyright notice, and (2)
|
||||||
|
tells the user that there is no warranty for the work (except to the
|
||||||
|
extent that warranties are provided), that licensees may convey the
|
||||||
|
work under this License, and how to view a copy of this License. If
|
||||||
|
the interface presents a list of user commands or options, such as a
|
||||||
|
menu, a prominent item in the list meets this criterion.
|
||||||
|
|
||||||
|
1. Source Code.
|
||||||
|
|
||||||
|
The "source code" for a work means the preferred form of the work
|
||||||
|
for making modifications to it. "Object code" means any non-source
|
||||||
|
form of a work.
|
||||||
|
|
||||||
|
A "Standard Interface" means an interface that either is an official
|
||||||
|
standard defined by a recognized standards body, or, in the case of
|
||||||
|
interfaces specified for a particular programming language, one that
|
||||||
|
is widely used among developers working in that language.
|
||||||
|
|
||||||
|
The "System Libraries" of an executable work include anything, other
|
||||||
|
than the work as a whole, that (a) is included in the normal form of
|
||||||
|
packaging a Major Component, but which is not part of that Major
|
||||||
|
Component, and (b) serves only to enable use of the work with that
|
||||||
|
Major Component, or to implement a Standard Interface for which an
|
||||||
|
implementation is available to the public in source code form. A
|
||||||
|
"Major Component", in this context, means a major essential component
|
||||||
|
(kernel, window system, and so on) of the specific operating system
|
||||||
|
(if any) on which the executable work runs, or a compiler used to
|
||||||
|
produce the work, or an object code interpreter used to run it.
|
||||||
|
|
||||||
|
The "Corresponding Source" for a work in object code form means all
|
||||||
|
the source code needed to generate, install, and (for an executable
|
||||||
|
work) run the object code and to modify the work, including scripts to
|
||||||
|
control those activities. However, it does not include the work's
|
||||||
|
System Libraries, or general-purpose tools or generally available free
|
||||||
|
programs which are used unmodified in performing those activities but
|
||||||
|
which are not part of the work. For example, Corresponding Source
|
||||||
|
includes interface definition files associated with source files for
|
||||||
|
the work, and the source code for shared libraries and dynamically
|
||||||
|
linked subprograms that the work is specifically designed to require,
|
||||||
|
such as by intimate data communication or control flow between those
|
||||||
|
subprograms and other parts of the work.
|
||||||
|
|
||||||
|
The Corresponding Source need not include anything that users
|
||||||
|
can regenerate automatically from other parts of the Corresponding
|
||||||
|
Source.
|
||||||
|
|
||||||
|
The Corresponding Source for a work in source code form is that
|
||||||
|
same work.
|
||||||
|
|
||||||
|
2. Basic Permissions.
|
||||||
|
|
||||||
|
All rights granted under this License are granted for the term of
|
||||||
|
copyright on the Program, and are irrevocable provided the stated
|
||||||
|
conditions are met. This License explicitly affirms your unlimited
|
||||||
|
permission to run the unmodified Program. The output from running a
|
||||||
|
covered work is covered by this License only if the output, given its
|
||||||
|
content, constitutes a covered work. This License acknowledges your
|
||||||
|
rights of fair use or other equivalent, as provided by copyright law.
|
||||||
|
|
||||||
|
You may make, run and propagate covered works that you do not
|
||||||
|
convey, without conditions so long as your license otherwise remains
|
||||||
|
in force. You may convey covered works to others for the sole purpose
|
||||||
|
of having them make modifications exclusively for you, or provide you
|
||||||
|
with facilities for running those works, provided that you comply with
|
||||||
|
the terms of this License in conveying all material for which you do
|
||||||
|
not control copyright. Those thus making or running the covered works
|
||||||
|
for you must do so exclusively on your behalf, under your direction
|
||||||
|
and control, on terms that prohibit them from making any copies of
|
||||||
|
your copyrighted material outside their relationship with you.
|
||||||
|
|
||||||
|
Conveying under any other circumstances is permitted solely under
|
||||||
|
the conditions stated below. Sublicensing is not allowed; section 10
|
||||||
|
makes it unnecessary.
|
||||||
|
|
||||||
|
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||||
|
|
||||||
|
No covered work shall be deemed part of an effective technological
|
||||||
|
measure under any applicable law fulfilling obligations under article
|
||||||
|
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||||
|
similar laws prohibiting or restricting circumvention of such
|
||||||
|
measures.
|
||||||
|
|
||||||
|
When you convey a covered work, you waive any legal power to forbid
|
||||||
|
circumvention of technological measures to the extent such circumvention
|
||||||
|
is effected by exercising rights under this License with respect to
|
||||||
|
the covered work, and you disclaim any intention to limit operation or
|
||||||
|
modification of the work as a means of enforcing, against the work's
|
||||||
|
users, your or third parties' legal rights to forbid circumvention of
|
||||||
|
technological measures.
|
||||||
|
|
||||||
|
4. Conveying Verbatim Copies.
|
||||||
|
|
||||||
|
You may convey verbatim copies of the Program's source code as you
|
||||||
|
receive it, in any medium, provided that you conspicuously and
|
||||||
|
appropriately publish on each copy an appropriate copyright notice;
|
||||||
|
keep intact all notices stating that this License and any
|
||||||
|
non-permissive terms added in accord with section 7 apply to the code;
|
||||||
|
keep intact all notices of the absence of any warranty; and give all
|
||||||
|
recipients a copy of this License along with the Program.
|
||||||
|
|
||||||
|
You may charge any price or no price for each copy that you convey,
|
||||||
|
and you may offer support or warranty protection for a fee.
|
||||||
|
|
||||||
|
5. Conveying Modified Source Versions.
|
||||||
|
|
||||||
|
You may convey a work based on the Program, or the modifications to
|
||||||
|
produce it from the Program, in the form of source code under the
|
||||||
|
terms of section 4, provided that you also meet all of these conditions:
|
||||||
|
|
||||||
|
a) The work must carry prominent notices stating that you modified
|
||||||
|
it, and giving a relevant date.
|
||||||
|
|
||||||
|
b) The work must carry prominent notices stating that it is
|
||||||
|
released under this License and any conditions added under section
|
||||||
|
7. This requirement modifies the requirement in section 4 to
|
||||||
|
"keep intact all notices".
|
||||||
|
|
||||||
|
c) You must license the entire work, as a whole, under this
|
||||||
|
License to anyone who comes into possession of a copy. This
|
||||||
|
License will therefore apply, along with any applicable section 7
|
||||||
|
additional terms, to the whole of the work, and all its parts,
|
||||||
|
regardless of how they are packaged. This License gives no
|
||||||
|
permission to license the work in any other way, but it does not
|
||||||
|
invalidate such permission if you have separately received it.
|
||||||
|
|
||||||
|
d) If the work has interactive user interfaces, each must display
|
||||||
|
Appropriate Legal Notices; however, if the Program has interactive
|
||||||
|
interfaces that do not display Appropriate Legal Notices, your
|
||||||
|
work need not make them do so.
|
||||||
|
|
||||||
|
A compilation of a covered work with other separate and independent
|
||||||
|
works, which are not by their nature extensions of the covered work,
|
||||||
|
and which are not combined with it such as to form a larger program,
|
||||||
|
in or on a volume of a storage or distribution medium, is called an
|
||||||
|
"aggregate" if the compilation and its resulting copyright are not
|
||||||
|
used to limit the access or legal rights of the compilation's users
|
||||||
|
beyond what the individual works permit. Inclusion of a covered work
|
||||||
|
in an aggregate does not cause this License to apply to the other
|
||||||
|
parts of the aggregate.
|
||||||
|
|
||||||
|
6. Conveying Non-Source Forms.
|
||||||
|
|
||||||
|
You may convey a covered work in object code form under the terms
|
||||||
|
of sections 4 and 5, provided that you also convey the
|
||||||
|
machine-readable Corresponding Source under the terms of this License,
|
||||||
|
in one of these ways:
|
||||||
|
|
||||||
|
a) Convey the object code in, or embodied in, a physical product
|
||||||
|
(including a physical distribution medium), accompanied by the
|
||||||
|
Corresponding Source fixed on a durable physical medium
|
||||||
|
customarily used for software interchange.
|
||||||
|
|
||||||
|
b) Convey the object code in, or embodied in, a physical product
|
||||||
|
(including a physical distribution medium), accompanied by a
|
||||||
|
written offer, valid for at least three years and valid for as
|
||||||
|
long as you offer spare parts or customer support for that product
|
||||||
|
model, to give anyone who possesses the object code either (1) a
|
||||||
|
copy of the Corresponding Source for all the software in the
|
||||||
|
product that is covered by this License, on a durable physical
|
||||||
|
medium customarily used for software interchange, for a price no
|
||||||
|
more than your reasonable cost of physically performing this
|
||||||
|
conveying of source, or (2) access to copy the
|
||||||
|
Corresponding Source from a network server at no charge.
|
||||||
|
|
||||||
|
c) Convey individual copies of the object code with a copy of the
|
||||||
|
written offer to provide the Corresponding Source. This
|
||||||
|
alternative is allowed only occasionally and noncommercially, and
|
||||||
|
only if you received the object code with such an offer, in accord
|
||||||
|
with subsection 6b.
|
||||||
|
|
||||||
|
d) Convey the object code by offering access from a designated
|
||||||
|
place (gratis or for a charge), and offer equivalent access to the
|
||||||
|
Corresponding Source in the same way through the same place at no
|
||||||
|
further charge. You need not require recipients to copy the
|
||||||
|
Corresponding Source along with the object code. If the place to
|
||||||
|
copy the object code is a network server, the Corresponding Source
|
||||||
|
may be on a different server (operated by you or a third party)
|
||||||
|
that supports equivalent copying facilities, provided you maintain
|
||||||
|
clear directions next to the object code saying where to find the
|
||||||
|
Corresponding Source. Regardless of what server hosts the
|
||||||
|
Corresponding Source, you remain obligated to ensure that it is
|
||||||
|
available for as long as needed to satisfy these requirements.
|
||||||
|
|
||||||
|
e) Convey the object code using peer-to-peer transmission, provided
|
||||||
|
you inform other peers where the object code and Corresponding
|
||||||
|
Source of the work are being offered to the general public at no
|
||||||
|
charge under subsection 6d.
|
||||||
|
|
||||||
|
A separable portion of the object code, whose source code is excluded
|
||||||
|
from the Corresponding Source as a System Library, need not be
|
||||||
|
included in conveying the object code work.
|
||||||
|
|
||||||
|
A "User Product" is either (1) a "consumer product", which means any
|
||||||
|
tangible personal property which is normally used for personal, family,
|
||||||
|
or household purposes, or (2) anything designed or sold for incorporation
|
||||||
|
into a dwelling. In determining whether a product is a consumer product,
|
||||||
|
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||||
|
product received by a particular user, "normally used" refers to a
|
||||||
|
typical or common use of that class of product, regardless of the status
|
||||||
|
of the particular user or of the way in which the particular user
|
||||||
|
actually uses, or expects or is expected to use, the product. A product
|
||||||
|
is a consumer product regardless of whether the product has substantial
|
||||||
|
commercial, industrial or non-consumer uses, unless such uses represent
|
||||||
|
the only significant mode of use of the product.
|
||||||
|
|
||||||
|
"Installation Information" for a User Product means any methods,
|
||||||
|
procedures, authorization keys, or other information required to install
|
||||||
|
and execute modified versions of a covered work in that User Product from
|
||||||
|
a modified version of its Corresponding Source. The information must
|
||||||
|
suffice to ensure that the continued functioning of the modified object
|
||||||
|
code is in no case prevented or interfered with solely because
|
||||||
|
modification has been made.
|
||||||
|
|
||||||
|
If you convey an object code work under this section in, or with, or
|
||||||
|
specifically for use in, a User Product, and the conveying occurs as
|
||||||
|
part of a transaction in which the right of possession and use of the
|
||||||
|
User Product is transferred to the recipient in perpetuity or for a
|
||||||
|
fixed term (regardless of how the transaction is characterized), the
|
||||||
|
Corresponding Source conveyed under this section must be accompanied
|
||||||
|
by the Installation Information. But this requirement does not apply
|
||||||
|
if neither you nor any third party retains the ability to install
|
||||||
|
modified object code on the User Product (for example, the work has
|
||||||
|
been installed in ROM).
|
||||||
|
|
||||||
|
The requirement to provide Installation Information does not include a
|
||||||
|
requirement to continue to provide support service, warranty, or updates
|
||||||
|
for a work that has been modified or installed by the recipient, or for
|
||||||
|
the User Product in which it has been modified or installed. Access to a
|
||||||
|
network may be denied when the modification itself materially and
|
||||||
|
adversely affects the operation of the network or violates the rules and
|
||||||
|
protocols for communication across the network.
|
||||||
|
|
||||||
|
Corresponding Source conveyed, and Installation Information provided,
|
||||||
|
in accord with this section must be in a format that is publicly
|
||||||
|
documented (and with an implementation available to the public in
|
||||||
|
source code form), and must require no special password or key for
|
||||||
|
unpacking, reading or copying.
|
||||||
|
|
||||||
|
7. Additional Terms.
|
||||||
|
|
||||||
|
"Additional permissions" are terms that supplement the terms of this
|
||||||
|
License by making exceptions from one or more of its conditions.
|
||||||
|
Additional permissions that are applicable to the entire Program shall
|
||||||
|
be treated as though they were included in this License, to the extent
|
||||||
|
that they are valid under applicable law. If additional permissions
|
||||||
|
apply only to part of the Program, that part may be used separately
|
||||||
|
under those permissions, but the entire Program remains governed by
|
||||||
|
this License without regard to the additional permissions.
|
||||||
|
|
||||||
|
When you convey a copy of a covered work, you may at your option
|
||||||
|
remove any additional permissions from that copy, or from any part of
|
||||||
|
it. (Additional permissions may be written to require their own
|
||||||
|
removal in certain cases when you modify the work.) You may place
|
||||||
|
additional permissions on material, added by you to a covered work,
|
||||||
|
for which you have or can give appropriate copyright permission.
|
||||||
|
|
||||||
|
Notwithstanding any other provision of this License, for material you
|
||||||
|
add to a covered work, you may (if authorized by the copyright holders of
|
||||||
|
that material) supplement the terms of this License with terms:
|
||||||
|
|
||||||
|
a) Disclaiming warranty or limiting liability differently from the
|
||||||
|
terms of sections 15 and 16 of this License; or
|
||||||
|
|
||||||
|
b) Requiring preservation of specified reasonable legal notices or
|
||||||
|
author attributions in that material or in the Appropriate Legal
|
||||||
|
Notices displayed by works containing it; or
|
||||||
|
|
||||||
|
c) Prohibiting misrepresentation of the origin of that material, or
|
||||||
|
requiring that modified versions of such material be marked in
|
||||||
|
reasonable ways as different from the original version; or
|
||||||
|
|
||||||
|
d) Limiting the use for publicity purposes of names of licensors or
|
||||||
|
authors of the material; or
|
||||||
|
|
||||||
|
e) Declining to grant rights under trademark law for use of some
|
||||||
|
trade names, trademarks, or service marks; or
|
||||||
|
|
||||||
|
f) Requiring indemnification of licensors and authors of that
|
||||||
|
material by anyone who conveys the material (or modified versions of
|
||||||
|
it) with contractual assumptions of liability to the recipient, for
|
||||||
|
any liability that these contractual assumptions directly impose on
|
||||||
|
those licensors and authors.
|
||||||
|
|
||||||
|
All other non-permissive additional terms are considered "further
|
||||||
|
restrictions" within the meaning of section 10. If the Program as you
|
||||||
|
received it, or any part of it, contains a notice stating that it is
|
||||||
|
governed by this License along with a term that is a further
|
||||||
|
restriction, you may remove that term. If a license document contains
|
||||||
|
a further restriction but permits relicensing or conveying under this
|
||||||
|
License, you may add to a covered work material governed by the terms
|
||||||
|
of that license document, provided that the further restriction does
|
||||||
|
not survive such relicensing or conveying.
|
||||||
|
|
||||||
|
If you add terms to a covered work in accord with this section, you
|
||||||
|
must place, in the relevant source files, a statement of the
|
||||||
|
additional terms that apply to those files, or a notice indicating
|
||||||
|
where to find the applicable terms.
|
||||||
|
|
||||||
|
Additional terms, permissive or non-permissive, may be stated in the
|
||||||
|
form of a separately written license, or stated as exceptions;
|
||||||
|
the above requirements apply either way.
|
||||||
|
|
||||||
|
8. Termination.
|
||||||
|
|
||||||
|
You may not propagate or modify a covered work except as expressly
|
||||||
|
provided under this License. Any attempt otherwise to propagate or
|
||||||
|
modify it is void, and will automatically terminate your rights under
|
||||||
|
this License (including any patent licenses granted under the third
|
||||||
|
paragraph of section 11).
|
||||||
|
|
||||||
|
However, if you cease all violation of this License, then your
|
||||||
|
license from a particular copyright holder is reinstated (a)
|
||||||
|
provisionally, unless and until the copyright holder explicitly and
|
||||||
|
finally terminates your license, and (b) permanently, if the copyright
|
||||||
|
holder fails to notify you of the violation by some reasonable means
|
||||||
|
prior to 60 days after the cessation.
|
||||||
|
|
||||||
|
Moreover, your license from a particular copyright holder is
|
||||||
|
reinstated permanently if the copyright holder notifies you of the
|
||||||
|
violation by some reasonable means, this is the first time you have
|
||||||
|
received notice of violation of this License (for any work) from that
|
||||||
|
copyright holder, and you cure the violation prior to 30 days after
|
||||||
|
your receipt of the notice.
|
||||||
|
|
||||||
|
Termination of your rights under this section does not terminate the
|
||||||
|
licenses of parties who have received copies or rights from you under
|
||||||
|
this License. If your rights have been terminated and not permanently
|
||||||
|
reinstated, you do not qualify to receive new licenses for the same
|
||||||
|
material under section 10.
|
||||||
|
|
||||||
|
9. Acceptance Not Required for Having Copies.
|
||||||
|
|
||||||
|
You are not required to accept this License in order to receive or
|
||||||
|
run a copy of the Program. Ancillary propagation of a covered work
|
||||||
|
occurring solely as a consequence of using peer-to-peer transmission
|
||||||
|
to receive a copy likewise does not require acceptance. However,
|
||||||
|
nothing other than this License grants you permission to propagate or
|
||||||
|
modify any covered work. These actions infringe copyright if you do
|
||||||
|
not accept this License. Therefore, by modifying or propagating a
|
||||||
|
covered work, you indicate your acceptance of this License to do so.
|
||||||
|
|
||||||
|
10. Automatic Licensing of Downstream Recipients.
|
||||||
|
|
||||||
|
Each time you convey a covered work, the recipient automatically
|
||||||
|
receives a license from the original licensors, to run, modify and
|
||||||
|
propagate that work, subject to this License. You are not responsible
|
||||||
|
for enforcing compliance by third parties with this License.
|
||||||
|
|
||||||
|
An "entity transaction" is a transaction transferring control of an
|
||||||
|
organization, or substantially all assets of one, or subdividing an
|
||||||
|
organization, or merging organizations. If propagation of a covered
|
||||||
|
work results from an entity transaction, each party to that
|
||||||
|
transaction who receives a copy of the work also receives whatever
|
||||||
|
licenses to the work the party's predecessor in interest had or could
|
||||||
|
give under the previous paragraph, plus a right to possession of the
|
||||||
|
Corresponding Source of the work from the predecessor in interest, if
|
||||||
|
the predecessor has it or can get it with reasonable efforts.
|
||||||
|
|
||||||
|
You may not impose any further restrictions on the exercise of the
|
||||||
|
rights granted or affirmed under this License. For example, you may
|
||||||
|
not impose a license fee, royalty, or other charge for exercise of
|
||||||
|
rights granted under this License, and you may not initiate litigation
|
||||||
|
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||||
|
any patent claim is infringed by making, using, selling, offering for
|
||||||
|
sale, or importing the Program or any portion of it.
|
||||||
|
|
||||||
|
11. Patents.
|
||||||
|
|
||||||
|
A "contributor" is a copyright holder who authorizes use under this
|
||||||
|
License of the Program or a work on which the Program is based. The
|
||||||
|
work thus licensed is called the contributor's "contributor version".
|
||||||
|
|
||||||
|
A contributor's "essential patent claims" are all patent claims
|
||||||
|
owned or controlled by the contributor, whether already acquired or
|
||||||
|
hereafter acquired, that would be infringed by some manner, permitted
|
||||||
|
by this License, of making, using, or selling its contributor version,
|
||||||
|
but do not include claims that would be infringed only as a
|
||||||
|
consequence of further modification of the contributor version. For
|
||||||
|
purposes of this definition, "control" includes the right to grant
|
||||||
|
patent sublicenses in a manner consistent with the requirements of
|
||||||
|
this License.
|
||||||
|
|
||||||
|
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||||
|
patent license under the contributor's essential patent claims, to
|
||||||
|
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||||
|
propagate the contents of its contributor version.
|
||||||
|
|
||||||
|
In the following three paragraphs, a "patent license" is any express
|
||||||
|
agreement or commitment, however denominated, not to enforce a patent
|
||||||
|
(such as an express permission to practice a patent or covenant not to
|
||||||
|
sue for patent infringement). To "grant" such a patent license to a
|
||||||
|
party means to make such an agreement or commitment not to enforce a
|
||||||
|
patent against the party.
|
||||||
|
|
||||||
|
If you convey a covered work, knowingly relying on a patent license,
|
||||||
|
and the Corresponding Source of the work is not available for anyone
|
||||||
|
to copy, free of charge and under the terms of this License, through a
|
||||||
|
publicly available network server or other readily accessible means,
|
||||||
|
then you must either (1) cause the Corresponding Source to be so
|
||||||
|
available, or (2) arrange to deprive yourself of the benefit of the
|
||||||
|
patent license for this particular work, or (3) arrange, in a manner
|
||||||
|
consistent with the requirements of this License, to extend the patent
|
||||||
|
license to downstream recipients. "Knowingly relying" means you have
|
||||||
|
actual knowledge that, but for the patent license, your conveying the
|
||||||
|
covered work in a country, or your recipient's use of the covered work
|
||||||
|
in a country, would infringe one or more identifiable patents in that
|
||||||
|
country that you have reason to believe are valid.
|
||||||
|
|
||||||
|
If, pursuant to or in connection with a single transaction or
|
||||||
|
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||||
|
covered work, and grant a patent license to some of the parties
|
||||||
|
receiving the covered work authorizing them to use, propagate, modify
|
||||||
|
or convey a specific copy of the covered work, then the patent license
|
||||||
|
you grant is automatically extended to all recipients of the covered
|
||||||
|
work and works based on it.
|
||||||
|
|
||||||
|
A patent license is "discriminatory" if it does not include within
|
||||||
|
the scope of its coverage, prohibits the exercise of, or is
|
||||||
|
conditioned on the non-exercise of one or more of the rights that are
|
||||||
|
specifically granted under this License. You may not convey a covered
|
||||||
|
work if you are a party to an arrangement with a third party that is
|
||||||
|
in the business of distributing software, under which you make payment
|
||||||
|
to the third party based on the extent of your activity of conveying
|
||||||
|
the work, and under which the third party grants, to any of the
|
||||||
|
parties who would receive the covered work from you, a discriminatory
|
||||||
|
patent license (a) in connection with copies of the covered work
|
||||||
|
conveyed by you (or copies made from those copies), or (b) primarily
|
||||||
|
for and in connection with specific products or compilations that
|
||||||
|
contain the covered work, unless you entered into that arrangement,
|
||||||
|
or that patent license was granted, prior to 28 March 2007.
|
||||||
|
|
||||||
|
Nothing in this License shall be construed as excluding or limiting
|
||||||
|
any implied license or other defenses to infringement that may
|
||||||
|
otherwise be available to you under applicable patent law.
|
||||||
|
|
||||||
|
12. No Surrender of Others' Freedom.
|
||||||
|
|
||||||
|
If conditions are imposed on you (whether by court order, agreement or
|
||||||
|
otherwise) that contradict the conditions of this License, they do not
|
||||||
|
excuse you from the conditions of this License. If you cannot convey a
|
||||||
|
covered work so as to satisfy simultaneously your obligations under this
|
||||||
|
License and any other pertinent obligations, then as a consequence you may
|
||||||
|
not convey it at all. For example, if you agree to terms that obligate you
|
||||||
|
to collect a royalty for further conveying from those to whom you convey
|
||||||
|
the Program, the only way you could satisfy both those terms and this
|
||||||
|
License would be to refrain entirely from conveying the Program.
|
||||||
|
|
||||||
|
13. Remote Network Interaction; Use with the GNU General Public License.
|
||||||
|
|
||||||
|
Notwithstanding any other provision of this License, if you modify the
|
||||||
|
Program, your modified version must prominently offer all users
|
||||||
|
interacting with it remotely through a computer network (if your version
|
||||||
|
supports such interaction) an opportunity to receive the Corresponding
|
||||||
|
Source of your version by providing access to the Corresponding Source
|
||||||
|
from a network server at no charge, through some standard or customary
|
||||||
|
means of facilitating copying of software. This Corresponding Source
|
||||||
|
shall include the Corresponding Source for any work covered by version 3
|
||||||
|
of the GNU General Public License that is incorporated pursuant to the
|
||||||
|
following paragraph.
|
||||||
|
|
||||||
|
Notwithstanding any other provision of this License, you have
|
||||||
|
permission to link or combine any covered work with a work licensed
|
||||||
|
under version 3 of the GNU General Public License into a single
|
||||||
|
combined work, and to convey the resulting work. The terms of this
|
||||||
|
License will continue to apply to the part which is the covered work,
|
||||||
|
but the work with which it is combined will remain governed by version
|
||||||
|
3 of the GNU General Public License.
|
||||||
|
|
||||||
|
14. Revised Versions of this License.
|
||||||
|
|
||||||
|
The Free Software Foundation may publish revised and/or new versions of
|
||||||
|
the GNU Affero General Public License from time to time. Such new versions
|
||||||
|
will be similar in spirit to the present version, but may differ in detail to
|
||||||
|
address new problems or concerns.
|
||||||
|
|
||||||
|
Each version is given a distinguishing version number. If the
|
||||||
|
Program specifies that a certain numbered version of the GNU Affero General
|
||||||
|
Public License "or any later version" applies to it, you have the
|
||||||
|
option of following the terms and conditions either of that numbered
|
||||||
|
version or of any later version published by the Free Software
|
||||||
|
Foundation. If the Program does not specify a version number of the
|
||||||
|
GNU Affero General Public License, you may choose any version ever published
|
||||||
|
by the Free Software Foundation.
|
||||||
|
|
||||||
|
If the Program specifies that a proxy can decide which future
|
||||||
|
versions of the GNU Affero General Public License can be used, that proxy's
|
||||||
|
public statement of acceptance of a version permanently authorizes you
|
||||||
|
to choose that version for the Program.
|
||||||
|
|
||||||
|
Later license versions may give you additional or different
|
||||||
|
permissions. However, no additional obligations are imposed on any
|
||||||
|
author or copyright holder as a result of your choosing to follow a
|
||||||
|
later version.
|
||||||
|
|
||||||
|
15. Disclaimer of Warranty.
|
||||||
|
|
||||||
|
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
||||||
|
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
||||||
|
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
||||||
|
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
||||||
|
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
||||||
|
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||||
|
|
||||||
|
16. Limitation of Liability.
|
||||||
|
|
||||||
|
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||||
|
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||||
|
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||||
|
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
||||||
|
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
||||||
|
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
||||||
|
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
||||||
|
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
||||||
|
SUCH DAMAGES.
|
||||||
|
|
||||||
|
17. Interpretation of Sections 15 and 16.
|
||||||
|
|
||||||
|
If the disclaimer of warranty and limitation of liability provided
|
||||||
|
above cannot be given local legal effect according to their terms,
|
||||||
|
reviewing courts shall apply local law that most closely approximates
|
||||||
|
an absolute waiver of all civil liability in connection with the
|
||||||
|
Program, unless a warranty or assumption of liability accompanies a
|
||||||
|
copy of the Program in return for a fee.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
How to Apply These Terms to Your New Programs
|
||||||
|
|
||||||
|
If you develop a new program, and you want it to be of the greatest
|
||||||
|
possible use to the public, the best way to achieve this is to make it
|
||||||
|
free software which everyone can redistribute and change under these terms.
|
||||||
|
|
||||||
|
To do so, attach the following notices to the program. It is safest
|
||||||
|
to attach them to the start of each source file to most effectively
|
||||||
|
state the exclusion of warranty; and each file should have at least
|
||||||
|
the "copyright" line and a pointer to where the full notice is found.
|
||||||
|
|
||||||
|
<one line to give the program's name and a brief idea of what it does.>
|
||||||
|
Copyright (C) <year> <name of author>
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Affero General Public License as published
|
||||||
|
by the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Affero General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Affero General Public License
|
||||||
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
Also add information on how to contact you by electronic and paper mail.
|
||||||
|
|
||||||
|
If your software can interact with users remotely through a computer
|
||||||
|
network, you should also make sure that it provides a way for users to
|
||||||
|
get its source. For example, if your program is a web application, its
|
||||||
|
interface could display a "Source" link that leads users to an archive
|
||||||
|
of the code. There are many ways you could offer source, and different
|
||||||
|
solutions will be better for different programs; see section 13 for the
|
||||||
|
specific requirements.
|
||||||
|
|
||||||
|
You should also get your employer (if you work as a programmer) or school,
|
||||||
|
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||||
|
For more information on this, and how to apply and follow the GNU AGPL, see
|
||||||
|
<https://www.gnu.org/licenses/>.
|
||||||
68
vendor/github.com/goretk/gore/README.md
generated
vendored
Normal file
68
vendor/github.com/goretk/gore/README.md
generated
vendored
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
[](https://github.com/goretk/gore/actions/workflows/go.yml)
|
||||||
|

|
||||||
|
[](https://codecov.io/gh/goretk/gore)
|
||||||
|
[](https://goreportcard.com/report/github.com/goretk/gore)
|
||||||
|
[](https://pkg.go.dev/github.com/goretk/gore)
|
||||||
|
# GoRE - Package gore is a library for analyzing Go binaries
|
||||||
|
|
||||||
|
## How to use
|
||||||
|
|
||||||
|
1. Use `go get` to download the library.
|
||||||
|
2. Import it into your project.
|
||||||
|
3. Write a new cool tool.
|
||||||
|
|
||||||
|
For an example use case, please checkout [redress](https://github.com/goretk/redress).
|
||||||
|
|
||||||
|
### Sample code
|
||||||
|
|
||||||
|
Extract the main package, child packages, and sibling packages:
|
||||||
|
```go
|
||||||
|
f, err := gore.Open(fileStr)
|
||||||
|
pkgs, err := f.GetPackages()
|
||||||
|
```
|
||||||
|
|
||||||
|
Extract all the types in the binary:
|
||||||
|
```go
|
||||||
|
f, err := gore.Open(fileStr)
|
||||||
|
typs, err := f.GetTypes()
|
||||||
|
```
|
||||||
|
|
||||||
|
## Update get new Go release information
|
||||||
|
|
||||||
|
Instead of downloading new release of the library to get detection
|
||||||
|
for new Go releases, it is possible to do a local pull.
|
||||||
|
|
||||||
|
Run `go generate` and new compiler releases will be generated from
|
||||||
|
the git tags.
|
||||||
|
|
||||||
|
## Functionality
|
||||||
|
|
||||||
|
### Go compiler
|
||||||
|
|
||||||
|
The library has functionality for guessing the compiler version
|
||||||
|
used. It searches the binary for the identifiable string left
|
||||||
|
by the compiler. It is not perfect, so functionality for assuming
|
||||||
|
a specific version is also provided. The version strings used are
|
||||||
|
identical to the identifiers. For example version "1.10.1" is
|
||||||
|
represented as "go1.10.1" and version "1.10" is represented as
|
||||||
|
"go1.10"
|
||||||
|
|
||||||
|
### Function recovery
|
||||||
|
|
||||||
|
Function information is recovered from the pclntab. Information
|
||||||
|
that is recovered includes: function start and end location in
|
||||||
|
the text section, source file. The library also tries to estimate
|
||||||
|
the first and last line number in the source file for the function.
|
||||||
|
The methods recovered includes the receiver. All functions and
|
||||||
|
methods belong to a package. The library tries to classify the
|
||||||
|
type of package. If it is a standard library package, 3rd-party
|
||||||
|
package, or part of the main application. If it unable to classify
|
||||||
|
the package, it is classified as unknown.
|
||||||
|
|
||||||
|
### Type recovery
|
||||||
|
|
||||||
|
The types in the binary are parsed from the "typelink" list. Not
|
||||||
|
all versions of Go are supported equally. Versions 1.7 and later
|
||||||
|
are fully supported. Versions 1.5 and 1.6 are partially supported.
|
||||||
|
Version prior to 1.5 are not supported at all at the moment.
|
||||||
|
|
||||||
72
vendor/github.com/goretk/gore/buildid.go
generated
vendored
Normal file
72
vendor/github.com/goretk/gore/buildid.go
generated
vendored
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
// This file is part of GoRE.
|
||||||
|
//
|
||||||
|
// Copyright (C) 2019-2021 GoRE Authors
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU Affero General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Affero General Public License
|
||||||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
package gore
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/binary"
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
goNoteNameELF = []byte("Go\x00\x00")
|
||||||
|
goNoteRawStart = []byte("\xff Go build ID: \"")
|
||||||
|
goNoteRawEnd = []byte("\"\n \xff")
|
||||||
|
)
|
||||||
|
|
||||||
|
func parseBuildIDFromElf(data []byte, byteOrder binary.ByteOrder) (string, error) {
|
||||||
|
r := bytes.NewReader(data)
|
||||||
|
var nameLen uint32
|
||||||
|
var idLen uint32
|
||||||
|
var tag uint32
|
||||||
|
err := binary.Read(r, byteOrder, &nameLen)
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("error when reading the BuildID name length: %w", err)
|
||||||
|
}
|
||||||
|
err = binary.Read(r, byteOrder, &idLen)
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("error when reading the BuildID ID length: %w", err)
|
||||||
|
}
|
||||||
|
err = binary.Read(r, byteOrder, &tag)
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("error when reading the BuildID tag: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if tag != uint32(4) {
|
||||||
|
return "", fmt.Errorf("build ID does not match expected value. 0x%x parsed", tag)
|
||||||
|
}
|
||||||
|
|
||||||
|
noteName := data[12 : 12+int(nameLen)]
|
||||||
|
if !bytes.Equal(noteName, goNoteNameELF) {
|
||||||
|
return "", fmt.Errorf("note name not as expected")
|
||||||
|
}
|
||||||
|
return string(data[16 : 16+int(idLen)]), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseBuildIDFromRaw(data []byte) (string, error) {
|
||||||
|
idx := bytes.Index(data, goNoteRawStart)
|
||||||
|
if idx < 0 {
|
||||||
|
// No Build ID
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
end := bytes.Index(data, goNoteRawEnd)
|
||||||
|
if end < 0 {
|
||||||
|
return "", fmt.Errorf("malformed Build ID")
|
||||||
|
}
|
||||||
|
return string(data[idx+len(goNoteRawStart) : end]), nil
|
||||||
|
}
|
||||||
65
vendor/github.com/goretk/gore/doc.go
generated
vendored
Normal file
65
vendor/github.com/goretk/gore/doc.go
generated
vendored
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
// This file is part of GoRE.
|
||||||
|
//
|
||||||
|
// Copyright (C) 2019-2021 GoRE Authors
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU Affero General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Affero General Public License
|
||||||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
/*
|
||||||
|
Package gore is a library for analyzing Go binaries.
|
||||||
|
|
||||||
|
Only little endian architectures are supported.
|
||||||
|
|
||||||
|
Go compiler
|
||||||
|
|
||||||
|
The library has functionality for guessing the compiler version
|
||||||
|
used. It searches the binary for the identifiable string left
|
||||||
|
by the compiler. It is not perfect, so functionality for assuming
|
||||||
|
a specific version is also provided. The version strings used are
|
||||||
|
identical to the identifiers. For example version "1.10.1" is
|
||||||
|
represented as "go1.10.1" and version "1.10" is represented as
|
||||||
|
"go1.10"
|
||||||
|
|
||||||
|
Function recovery
|
||||||
|
|
||||||
|
Function information is recovered from the pclntab. Information
|
||||||
|
that is recovered includes: function start and end location in
|
||||||
|
the text section, source file. The library also tries to estimate
|
||||||
|
the first and last line number in the source file for the function.
|
||||||
|
The methods recovered includes the receiver. All functions and
|
||||||
|
methods belong to a package. The library tries to classify the
|
||||||
|
type of package. If it is a standard library package, 3rd-party
|
||||||
|
package, or part of the main application. If it unable to classify
|
||||||
|
the package, it is classified as unknown.
|
||||||
|
|
||||||
|
Type recovery
|
||||||
|
|
||||||
|
The types in the binary are parsed from the "typelink" list. Not
|
||||||
|
all versions of Go are supported equally. Versions 1.7 and later
|
||||||
|
are fully supported. Versions 1.5 and 1.6 are partially supported.
|
||||||
|
Version prior to 1.5 are not supported at all at the moment.
|
||||||
|
|
||||||
|
Example code
|
||||||
|
|
||||||
|
Extract the main package, child packages, and sibling packages:
|
||||||
|
|
||||||
|
f, err := gore.Open(fileStr)
|
||||||
|
pkgs, err := f.GetPackages()
|
||||||
|
|
||||||
|
Extract all the types in the binary:
|
||||||
|
|
||||||
|
f, err := gore.Open(fileStr)
|
||||||
|
typs, err := f.GetTypes()
|
||||||
|
|
||||||
|
*/
|
||||||
|
package gore
|
||||||
169
vendor/github.com/goretk/gore/elf.go
generated
vendored
Normal file
169
vendor/github.com/goretk/gore/elf.go
generated
vendored
Normal file
@ -0,0 +1,169 @@
|
|||||||
|
// This file is part of GoRE.
|
||||||
|
//
|
||||||
|
// Copyright (C) 2019-2021 GoRE Authors
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU Affero General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Affero General Public License
|
||||||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
package gore
|
||||||
|
|
||||||
|
import (
|
||||||
|
"debug/elf"
|
||||||
|
"debug/gosym"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
func openELF(fp string) (*elfFile, error) {
|
||||||
|
osFile, err := os.Open(fp)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("error when opening the ELF file: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
f, err := elf.NewFile(osFile)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("error when parsing the ELF file: %w", err)
|
||||||
|
}
|
||||||
|
return &elfFile{file: f, osFile: osFile}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type elfFile struct {
|
||||||
|
file *elf.File
|
||||||
|
osFile *os.File
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *elfFile) getFile() *os.File {
|
||||||
|
return e.osFile
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *elfFile) getPCLNTab() (*gosym.Table, error) {
|
||||||
|
pclnSection := e.file.Section(".gopclntab")
|
||||||
|
if pclnSection == nil {
|
||||||
|
// No section found. Check if the PIE section exist instead.
|
||||||
|
pclnSection = e.file.Section(".data.rel.ro.gopclntab")
|
||||||
|
}
|
||||||
|
if pclnSection == nil {
|
||||||
|
return nil, fmt.Errorf("no gopclntab section found")
|
||||||
|
}
|
||||||
|
|
||||||
|
pclndat, err := pclnSection.Data()
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("could not get the data for the pclntab: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
pcln := gosym.NewLineTable(pclndat, e.file.Section(".text").Addr)
|
||||||
|
return gosym.NewTable(make([]byte, 0), pcln)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *elfFile) Close() error {
|
||||||
|
err := e.file.Close()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return e.osFile.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *elfFile) getRData() ([]byte, error) {
|
||||||
|
section := e.file.Section(".rodata")
|
||||||
|
if section == nil {
|
||||||
|
return nil, ErrSectionDoesNotExist
|
||||||
|
}
|
||||||
|
return section.Data()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *elfFile) getCodeSection() ([]byte, error) {
|
||||||
|
section := e.file.Section(".text")
|
||||||
|
if section == nil {
|
||||||
|
return nil, ErrSectionDoesNotExist
|
||||||
|
}
|
||||||
|
return section.Data()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *elfFile) getPCLNTABData() (uint64, []byte, error) {
|
||||||
|
start, data, err := e.getSectionData(".gopclntab")
|
||||||
|
if err == ErrSectionDoesNotExist {
|
||||||
|
// Try PIE location
|
||||||
|
return e.getSectionData(".data.rel.ro.gopclntab")
|
||||||
|
}
|
||||||
|
return start, data, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *elfFile) moduledataSection() string {
|
||||||
|
return ".noptrdata"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *elfFile) getSectionDataFromOffset(off uint64) (uint64, []byte, error) {
|
||||||
|
for _, section := range e.file.Sections {
|
||||||
|
if section.Offset == 0 {
|
||||||
|
// Only exist in memory
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if section.Addr <= off && off < (section.Addr+section.Size) {
|
||||||
|
data, err := section.Data()
|
||||||
|
return section.Addr, data, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0, nil, ErrSectionDoesNotExist
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *elfFile) getSectionData(name string) (uint64, []byte, error) {
|
||||||
|
section := e.file.Section(name)
|
||||||
|
if section == nil {
|
||||||
|
return 0, nil, ErrSectionDoesNotExist
|
||||||
|
}
|
||||||
|
data, err := section.Data()
|
||||||
|
return section.Addr, data, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *elfFile) getFileInfo() *FileInfo {
|
||||||
|
var wordSize int
|
||||||
|
class := e.file.FileHeader.Class
|
||||||
|
if class == elf.ELFCLASS32 {
|
||||||
|
wordSize = intSize32
|
||||||
|
}
|
||||||
|
if class == elf.ELFCLASS64 {
|
||||||
|
wordSize = intSize64
|
||||||
|
}
|
||||||
|
|
||||||
|
var arch string
|
||||||
|
switch e.file.Machine {
|
||||||
|
case elf.EM_386:
|
||||||
|
arch = Arch386
|
||||||
|
case elf.EM_MIPS:
|
||||||
|
arch = ArchMIPS
|
||||||
|
case elf.EM_X86_64:
|
||||||
|
arch = ArchAMD64
|
||||||
|
case elf.EM_ARM:
|
||||||
|
arch = ArchARM
|
||||||
|
}
|
||||||
|
|
||||||
|
return &FileInfo{
|
||||||
|
ByteOrder: e.file.FileHeader.ByteOrder,
|
||||||
|
OS: e.file.Machine.String(),
|
||||||
|
WordSize: wordSize,
|
||||||
|
Arch: arch,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *elfFile) getBuildID() (string, error) {
|
||||||
|
_, data, err := e.getSectionData(".note.go.buildid")
|
||||||
|
// If the note section does not exist, we just ignore the build id.
|
||||||
|
if err == ErrSectionDoesNotExist {
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("error when getting note section: %w", err)
|
||||||
|
}
|
||||||
|
return parseBuildIDFromElf(data, e.file.ByteOrder)
|
||||||
|
}
|
||||||
38
vendor/github.com/goretk/gore/error.go
generated
vendored
Normal file
38
vendor/github.com/goretk/gore/error.go
generated
vendored
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
// This file is part of GoRE.
|
||||||
|
//
|
||||||
|
// Copyright (C) 2019-2021 GoRE Authors
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU Affero General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Affero General Public License
|
||||||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
package gore
|
||||||
|
|
||||||
|
import "errors"
|
||||||
|
|
||||||
|
var (
|
||||||
|
// ErrNotEnoughBytesRead is returned if read call returned less bytes than what is needed.
|
||||||
|
ErrNotEnoughBytesRead = errors.New("not enough bytes read")
|
||||||
|
// ErrUnsupportedFile is returned if the file process is unsupported.
|
||||||
|
ErrUnsupportedFile = errors.New("unsupported file")
|
||||||
|
// ErrSectionDoesNotExist is returned when accessing a section that does not exist.
|
||||||
|
ErrSectionDoesNotExist = errors.New("section does not exist")
|
||||||
|
// ErrNoGoVersionFound is returned if no goversion was found in the binary.
|
||||||
|
ErrNoGoVersionFound = errors.New("no goversion found")
|
||||||
|
// ErrNoPCLNTab is returned if no PCLN table can be located.
|
||||||
|
ErrNoPCLNTab = errors.New("no pclntab located")
|
||||||
|
// ErrInvalidGoVersion is returned if the go version set for the file is either invalid
|
||||||
|
// or does not match a known version by the library.
|
||||||
|
ErrInvalidGoVersion = errors.New("invalid go version")
|
||||||
|
// ErrNoGoRootFound is returned if no goroot was found in the binary.
|
||||||
|
ErrNoGoRootFound = errors.New("no goroot found")
|
||||||
|
)
|
||||||
397
vendor/github.com/goretk/gore/file.go
generated
vendored
Normal file
397
vendor/github.com/goretk/gore/file.go
generated
vendored
Normal file
@ -0,0 +1,397 @@
|
|||||||
|
// This file is part of GoRE.
|
||||||
|
//
|
||||||
|
// Copyright (C) 2019-2021 GoRE Authors
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU Affero General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Affero General Public License
|
||||||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
package gore
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"debug/gosym"
|
||||||
|
"encoding/binary"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"sort"
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
elfMagic = []byte{0x7f, 0x45, 0x4c, 0x46}
|
||||||
|
peMagic = []byte{0x4d, 0x5a}
|
||||||
|
maxMagicBufLen = 4
|
||||||
|
machoMagic1 = []byte{0xfe, 0xed, 0xfa, 0xce}
|
||||||
|
machoMagic2 = []byte{0xfe, 0xed, 0xfa, 0xcf}
|
||||||
|
machoMagic3 = []byte{0xce, 0xfa, 0xed, 0xfe}
|
||||||
|
machoMagic4 = []byte{0xcf, 0xfa, 0xed, 0xfe}
|
||||||
|
)
|
||||||
|
|
||||||
|
// Open opens a file and returns a handler to the file.
|
||||||
|
func Open(filePath string) (*GoFile, error) {
|
||||||
|
f, err := os.Open(filePath)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = f.Seek(0, 0)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
buf := make([]byte, maxMagicBufLen)
|
||||||
|
n, err := f.Read(buf)
|
||||||
|
f.Close()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if n < maxMagicBufLen {
|
||||||
|
return nil, ErrNotEnoughBytesRead
|
||||||
|
}
|
||||||
|
gofile := new(GoFile)
|
||||||
|
if fileMagicMatch(buf, elfMagic) {
|
||||||
|
elf, err := openELF(filePath)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
gofile.fh = elf
|
||||||
|
} else if fileMagicMatch(buf, peMagic) {
|
||||||
|
pe, err := openPE(filePath)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
gofile.fh = pe
|
||||||
|
} else if fileMagicMatch(buf, machoMagic1) || fileMagicMatch(buf, machoMagic2) || fileMagicMatch(buf, machoMagic3) || fileMagicMatch(buf, machoMagic4) {
|
||||||
|
macho, err := openMachO(filePath)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
gofile.fh = macho
|
||||||
|
} else {
|
||||||
|
return nil, ErrUnsupportedFile
|
||||||
|
}
|
||||||
|
gofile.FileInfo = gofile.fh.getFileInfo()
|
||||||
|
|
||||||
|
// If the ID has been removed or tampered with, this will fail. If we can't
|
||||||
|
// get a build ID, we skip it.
|
||||||
|
buildID, err := gofile.fh.getBuildID()
|
||||||
|
if err == nil {
|
||||||
|
gofile.BuildID = buildID
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try to extract build information.
|
||||||
|
if bi, err := gofile.extractBuildInfo(); err == nil {
|
||||||
|
// This error is a minor failure, it just means we don't have
|
||||||
|
// this information. So if fails we just ignores it.
|
||||||
|
gofile.BuildInfo = bi
|
||||||
|
if bi.Compiler != nil {
|
||||||
|
gofile.FileInfo.goversion = bi.Compiler
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return gofile, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GoFile is a structure representing a go binary file.
|
||||||
|
type GoFile struct {
|
||||||
|
// BuildInfo holds the data from the buildinf structure. This can be nil
|
||||||
|
// because it's not always available.
|
||||||
|
BuildInfo *BuildInfo
|
||||||
|
// FileInfo holds information about the file.
|
||||||
|
FileInfo *FileInfo
|
||||||
|
// BuildID is the Go build ID hash extracted from the binary.
|
||||||
|
BuildID string
|
||||||
|
fh fileHandler
|
||||||
|
stdPkgs []*Package
|
||||||
|
generated []*Package
|
||||||
|
pkgs []*Package
|
||||||
|
vendors []*Package
|
||||||
|
unknown []*Package
|
||||||
|
pclntab *gosym.Table
|
||||||
|
initPackages sync.Once
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *GoFile) init() error {
|
||||||
|
var returnVal error
|
||||||
|
f.initPackages.Do(func() {
|
||||||
|
tab, err := f.PCLNTab()
|
||||||
|
if err != nil {
|
||||||
|
returnVal = err
|
||||||
|
return
|
||||||
|
}
|
||||||
|
f.pclntab = tab
|
||||||
|
returnVal = f.enumPackages()
|
||||||
|
})
|
||||||
|
return returnVal
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetCompilerVersion returns the Go compiler version of the compiler
|
||||||
|
// that was used to compile the binary.
|
||||||
|
func (f *GoFile) GetCompilerVersion() (*GoVersion, error) {
|
||||||
|
return findGoCompilerVersion(f)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SourceInfo returns the source code filename, starting line number
|
||||||
|
// and ending line number for the function.
|
||||||
|
func (f *GoFile) SourceInfo(fn *Function) (string, int, int) {
|
||||||
|
srcFile, _, _ := f.pclntab.PCToLine(fn.Offset)
|
||||||
|
start, end := findSourceLines(fn.Offset, fn.End, f.pclntab)
|
||||||
|
return srcFile, start, end
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetGoRoot returns the Go Root path
|
||||||
|
// that was used to compile the binary.
|
||||||
|
func (f *GoFile) GetGoRoot() (string, error) {
|
||||||
|
err := f.init()
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return findGoRootPath(f)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetGoVersion sets the assumed compiler version that was used. This
|
||||||
|
// can be used to force a version if gore is not able to determine the
|
||||||
|
// compiler version used. The version string must match one of the strings
|
||||||
|
// normally extracted from the binary. For example to set the version to
|
||||||
|
// go 1.12.0, use "go1.12". For 1.7.2, use "go1.7.2".
|
||||||
|
// If an incorrect version string or version not known to the library,
|
||||||
|
// ErrInvalidGoVersion is returned.
|
||||||
|
func (f *GoFile) SetGoVersion(version string) error {
|
||||||
|
gv := ResolveGoVersion(version)
|
||||||
|
if gv == nil {
|
||||||
|
return ErrInvalidGoVersion
|
||||||
|
}
|
||||||
|
f.FileInfo.goversion = gv
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetPackages returns the go packages that has been classified as part of the main
|
||||||
|
// project.
|
||||||
|
func (f *GoFile) GetPackages() ([]*Package, error) {
|
||||||
|
err := f.init()
|
||||||
|
return f.pkgs, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetVendors returns the 3rd party packages used by the binary.
|
||||||
|
func (f *GoFile) GetVendors() ([]*Package, error) {
|
||||||
|
err := f.init()
|
||||||
|
return f.vendors, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetSTDLib returns the standard library packages used by the binary.
|
||||||
|
func (f *GoFile) GetSTDLib() ([]*Package, error) {
|
||||||
|
err := f.init()
|
||||||
|
return f.stdPkgs, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetGeneratedPackages returns the compiler generated packages used by the binary.
|
||||||
|
func (f *GoFile) GetGeneratedPackages() ([]*Package, error) {
|
||||||
|
err := f.init()
|
||||||
|
return f.generated, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetUnknown returns unclassified packages used by the binary. This is a catch all
|
||||||
|
// category when the classification could not be determined.
|
||||||
|
func (f *GoFile) GetUnknown() ([]*Package, error) {
|
||||||
|
err := f.init()
|
||||||
|
return f.unknown, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *GoFile) enumPackages() error {
|
||||||
|
tab := f.pclntab
|
||||||
|
packages := make(map[string]*Package)
|
||||||
|
allPackages := sort.StringSlice{}
|
||||||
|
|
||||||
|
for _, n := range tab.Funcs {
|
||||||
|
needFilepath := false
|
||||||
|
|
||||||
|
p, ok := packages[n.PackageName()]
|
||||||
|
if !ok {
|
||||||
|
p = &Package{
|
||||||
|
Filepath: filepath.Dir(n.BaseName()),
|
||||||
|
Functions: make([]*Function, 0),
|
||||||
|
Methods: make([]*Method, 0),
|
||||||
|
}
|
||||||
|
packages[n.PackageName()] = p
|
||||||
|
allPackages = append(allPackages, n.PackageName())
|
||||||
|
needFilepath = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if n.ReceiverName() != "" {
|
||||||
|
m := &Method{
|
||||||
|
Function: &Function{
|
||||||
|
Name: n.BaseName(),
|
||||||
|
Offset: n.Entry,
|
||||||
|
End: n.End,
|
||||||
|
PackageName: n.PackageName(),
|
||||||
|
},
|
||||||
|
Receiver: n.ReceiverName(),
|
||||||
|
}
|
||||||
|
|
||||||
|
p.Methods = append(p.Methods, m)
|
||||||
|
|
||||||
|
if !ok && needFilepath {
|
||||||
|
fp, _, _ := tab.PCToLine(m.Offset)
|
||||||
|
p.Filepath = filepath.Dir(fp)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
f := &Function{
|
||||||
|
Name: n.BaseName(),
|
||||||
|
Offset: n.Entry,
|
||||||
|
End: n.End,
|
||||||
|
PackageName: n.PackageName(),
|
||||||
|
}
|
||||||
|
p.Functions = append(p.Functions, f)
|
||||||
|
|
||||||
|
if !ok && needFilepath {
|
||||||
|
fp, _, _ := tab.PCToLine(f.Offset)
|
||||||
|
p.Filepath = filepath.Dir(fp)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
allPackages.Sort()
|
||||||
|
|
||||||
|
var classifier PackageClassifier
|
||||||
|
|
||||||
|
if f.BuildInfo != nil && f.BuildInfo.ModInfo != nil {
|
||||||
|
classifier = NewModPackageClassifier(f.BuildInfo.ModInfo)
|
||||||
|
} else {
|
||||||
|
mainPkg, ok := packages["main"]
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("no main package found")
|
||||||
|
}
|
||||||
|
|
||||||
|
classifier = NewPathPackageClassifier(mainPkg.Filepath)
|
||||||
|
}
|
||||||
|
|
||||||
|
for n, p := range packages {
|
||||||
|
p.Name = n
|
||||||
|
class := classifier.Classify(p)
|
||||||
|
switch class {
|
||||||
|
case ClassSTD:
|
||||||
|
f.stdPkgs = append(f.stdPkgs, p)
|
||||||
|
case ClassVendor:
|
||||||
|
f.vendors = append(f.vendors, p)
|
||||||
|
case ClassMain:
|
||||||
|
f.pkgs = append(f.pkgs, p)
|
||||||
|
case ClassUnknown:
|
||||||
|
f.unknown = append(f.unknown, p)
|
||||||
|
case ClassGenerated:
|
||||||
|
f.generated = append(f.generated, p)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close releases the file handler.
|
||||||
|
func (f *GoFile) Close() error {
|
||||||
|
return f.fh.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
// PCLNTab returns the PCLN table.
|
||||||
|
func (f *GoFile) PCLNTab() (*gosym.Table, error) {
|
||||||
|
return f.fh.getPCLNTab()
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetTypes returns a map of all types found in the binary file.
|
||||||
|
func (f *GoFile) GetTypes() ([]*GoType, error) {
|
||||||
|
if f.FileInfo.goversion == nil {
|
||||||
|
ver, err := f.GetCompilerVersion()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
f.FileInfo.goversion = ver
|
||||||
|
}
|
||||||
|
t, err := getTypes(f.FileInfo, f.fh)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if err = f.init(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return sortTypes(t), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bytes returns a slice of raw bytes with the length in the file from the address.
|
||||||
|
func (f *GoFile) Bytes(address uint64, length uint64) ([]byte, error) {
|
||||||
|
base, section, err := f.fh.getSectionDataFromOffset(address)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if address+length-base > uint64(len(section)) {
|
||||||
|
return nil, errors.New("length out of bounds")
|
||||||
|
}
|
||||||
|
|
||||||
|
return section[address-base : address+length-base], nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func sortTypes(types map[uint64]*GoType) []*GoType {
|
||||||
|
sortedList := make([]*GoType, len(types))
|
||||||
|
|
||||||
|
i := 0
|
||||||
|
for _, typ := range types {
|
||||||
|
sortedList[i] = typ
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
sort.Slice(sortedList, func(i, j int) bool {
|
||||||
|
if sortedList[i].PackagePath == sortedList[j].PackagePath {
|
||||||
|
return sortedList[i].Name < sortedList[j].Name
|
||||||
|
}
|
||||||
|
return sortedList[i].PackagePath < sortedList[j].PackagePath
|
||||||
|
})
|
||||||
|
return sortedList
|
||||||
|
}
|
||||||
|
|
||||||
|
type fileHandler interface {
|
||||||
|
io.Closer
|
||||||
|
getPCLNTab() (*gosym.Table, error)
|
||||||
|
getRData() ([]byte, error)
|
||||||
|
getCodeSection() ([]byte, error)
|
||||||
|
getSectionDataFromOffset(uint64) (uint64, []byte, error)
|
||||||
|
getSectionData(string) (uint64, []byte, error)
|
||||||
|
getFileInfo() *FileInfo
|
||||||
|
getPCLNTABData() (uint64, []byte, error)
|
||||||
|
moduledataSection() string
|
||||||
|
getBuildID() (string, error)
|
||||||
|
getFile() *os.File
|
||||||
|
}
|
||||||
|
|
||||||
|
func fileMagicMatch(buf, magic []byte) bool {
|
||||||
|
return bytes.HasPrefix(buf, magic)
|
||||||
|
}
|
||||||
|
|
||||||
|
// FileInfo holds information about the file.
|
||||||
|
type FileInfo struct {
|
||||||
|
// Arch is the architecture the binary is compiled for.
|
||||||
|
Arch string
|
||||||
|
// OS is the operating system the binary is compiled for.
|
||||||
|
OS string
|
||||||
|
// ByteOrder is the byte order.
|
||||||
|
ByteOrder binary.ByteOrder
|
||||||
|
// WordSize is the natural integer size used by the file.
|
||||||
|
WordSize int
|
||||||
|
goversion *GoVersion
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
ArchAMD64 = "amd64"
|
||||||
|
ArchARM = "arm"
|
||||||
|
ArchARM64 = "arm64"
|
||||||
|
Arch386 = "i386"
|
||||||
|
ArchMIPS = "mips"
|
||||||
|
)
|
||||||
142
vendor/github.com/goretk/gore/function.go
generated
vendored
Normal file
142
vendor/github.com/goretk/gore/function.go
generated
vendored
Normal file
@ -0,0 +1,142 @@
|
|||||||
|
// This file is part of GoRE.
|
||||||
|
//
|
||||||
|
// Copyright (C) 2019-2021 GoRE Authors
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU Affero General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Affero General Public License
|
||||||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
package gore
|
||||||
|
|
||||||
|
import (
|
||||||
|
"debug/gosym"
|
||||||
|
"fmt"
|
||||||
|
"sort"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Function is a representation of a Go function.
|
||||||
|
type Function struct {
|
||||||
|
// Name is the extracted function name.
|
||||||
|
Name string `json:"name"`
|
||||||
|
// Offset is the starting location for the subroutine in the binary.
|
||||||
|
Offset uint64 `json:"offset"`
|
||||||
|
// End is the end location for the subroutine in the binary.
|
||||||
|
End uint64 `json:"end"`
|
||||||
|
// PackageName is the name of the Go package the function belongs to.
|
||||||
|
PackageName string `json:"packageName"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// String returns a string representation of the function.
|
||||||
|
func (f *Function) String() string {
|
||||||
|
return f.Name
|
||||||
|
}
|
||||||
|
|
||||||
|
// Method is a representation of a Go method.
|
||||||
|
type Method struct {
|
||||||
|
// Receiver is the name of the method receiver.
|
||||||
|
Receiver string `json:"receiver"`
|
||||||
|
*Function
|
||||||
|
}
|
||||||
|
|
||||||
|
// String returns a string summary of the function.
|
||||||
|
func (m *Method) String() string {
|
||||||
|
return fmt.Sprintf("%s%s", m.Receiver, m.Name)
|
||||||
|
}
|
||||||
|
|
||||||
|
// FileEntry is a representation of an entry in a source code file. This can for example be
|
||||||
|
// a function or a method.
|
||||||
|
type FileEntry struct {
|
||||||
|
// Name of the function or method.
|
||||||
|
Name string
|
||||||
|
// Start is the source line where the code starts.
|
||||||
|
Start int
|
||||||
|
// End is the source line where the code ends.
|
||||||
|
End int
|
||||||
|
}
|
||||||
|
|
||||||
|
// String returns a string representation of the entry.
|
||||||
|
func (f FileEntry) String() string {
|
||||||
|
return fmt.Sprintf("%s Lines: %d to %d (%d)", f.Name, f.Start, f.End, f.End-f.Start)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SourceFile is a representation of a source code file.
|
||||||
|
type SourceFile struct {
|
||||||
|
// Name of the file.
|
||||||
|
Name string
|
||||||
|
// Prefix that should be added to each line.
|
||||||
|
Prefix string
|
||||||
|
// Postfix that should be added to each line.
|
||||||
|
Postfix string
|
||||||
|
entries []FileEntry
|
||||||
|
}
|
||||||
|
|
||||||
|
// String produces a string representation of a source code file.
|
||||||
|
// The multi-line string has this format:
|
||||||
|
// File: simple.go
|
||||||
|
// main Lines: 5 to 8 (3)
|
||||||
|
// setup Lines: 9 to 11 (2)
|
||||||
|
// The prefix and postfix string is added to each line.
|
||||||
|
func (s *SourceFile) String() string {
|
||||||
|
sort.Slice(s.entries, func(i, j int) bool {
|
||||||
|
return s.entries[i].Start < s.entries[j].Start
|
||||||
|
})
|
||||||
|
|
||||||
|
numlines := len(s.entries) + 1
|
||||||
|
lines := make([]string, numlines)
|
||||||
|
lines[0] = fmt.Sprintf("%sFile: %s%s", s.Prefix, s.Name, s.Postfix)
|
||||||
|
|
||||||
|
// Entry lines
|
||||||
|
for i, e := range s.entries {
|
||||||
|
lines[i+1] = fmt.Sprintf("\t%s%s%s", s.Prefix, e, s.Postfix)
|
||||||
|
}
|
||||||
|
return strings.Join(lines, "\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
// findSourceLines walks from the entry of the function to the end and looks for the
|
||||||
|
// final source code line number. This function is pretty expensive to execute.
|
||||||
|
func findSourceLines(entry, end uint64, tab *gosym.Table) (int, int) {
|
||||||
|
// We don't need the Func returned since we are operating within the same function.
|
||||||
|
file, srcStart, _ := tab.PCToLine(entry)
|
||||||
|
|
||||||
|
// We walk from entry to end and check the source code line number. If it's greater
|
||||||
|
// then the current value, we set it as the new value. If the file is different, we
|
||||||
|
// have entered an inlined function. In this case we skip it. There is a possibility
|
||||||
|
// that we enter an inlined function that's defined in the same file. There is no way
|
||||||
|
// for us to tell this is the case.
|
||||||
|
srcEnd := srcStart
|
||||||
|
|
||||||
|
// We take a shortcut and only check every 4 bytes. This isn't perfect, but it speeds
|
||||||
|
// up the processes.
|
||||||
|
for i := entry; i <= end; i = i + 4 {
|
||||||
|
f, l, _ := tab.PCToLine(i)
|
||||||
|
|
||||||
|
// If this line is a different file, it's an inlined function so just continue.
|
||||||
|
if f != file {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the current line is less than the starting source line, we have entered
|
||||||
|
// an inline function defined before this function.
|
||||||
|
if l < srcStart {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the current line is greater, we assume it being closer to the end of the
|
||||||
|
// function definition. So we take it as the current srcEnd value.
|
||||||
|
if l > srcEnd {
|
||||||
|
srcEnd = l
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return srcStart, srcEnd
|
||||||
|
}
|
||||||
364
vendor/github.com/goretk/gore/goroot.go
generated
vendored
Normal file
364
vendor/github.com/goretk/gore/goroot.go
generated
vendored
Normal file
@ -0,0 +1,364 @@
|
|||||||
|
// This file is part of GoRE.
|
||||||
|
//
|
||||||
|
// Copyright (C) 2019-2021 GoRE Authors
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU Affero General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Affero General Public License
|
||||||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
package gore
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"reflect"
|
||||||
|
"strings"
|
||||||
|
"unicode/utf8"
|
||||||
|
|
||||||
|
"golang.org/x/arch/x86/x86asm"
|
||||||
|
)
|
||||||
|
|
||||||
|
func tryFromGOROOT(f *GoFile) (string, error) {
|
||||||
|
// Check for non supported architectures.
|
||||||
|
if f.FileInfo.Arch != Arch386 && f.FileInfo.Arch != ArchAMD64 {
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
|
||||||
|
is32 := false
|
||||||
|
if f.FileInfo.Arch == Arch386 {
|
||||||
|
is32 = true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find runtime.GOROOT function.
|
||||||
|
var fcn *Function
|
||||||
|
std, err := f.GetSTDLib()
|
||||||
|
if err != nil {
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
|
||||||
|
pkgLoop:
|
||||||
|
for _, v := range std {
|
||||||
|
if v.Name != "runtime" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
for _, vv := range v.Functions {
|
||||||
|
if vv.Name != "GOROOT" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
fcn = vv
|
||||||
|
break pkgLoop
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the functions was found
|
||||||
|
if fcn == nil {
|
||||||
|
// If we can't find the function there is nothing to do.
|
||||||
|
return "", ErrNoGoRootFound
|
||||||
|
}
|
||||||
|
// Get the raw hex.
|
||||||
|
buf, err := f.Bytes(fcn.Offset, fcn.End-fcn.Offset)
|
||||||
|
if err != nil {
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
s := 0
|
||||||
|
mode := f.FileInfo.WordSize * 8
|
||||||
|
|
||||||
|
for s < len(buf) {
|
||||||
|
inst, err := x86asm.Decode(buf[s:], mode)
|
||||||
|
if err != nil {
|
||||||
|
// If we fail to decode the instruction, something is wrong so
|
||||||
|
// bailout.
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update next instruction location.
|
||||||
|
s = s + inst.Len
|
||||||
|
|
||||||
|
// Check if it's a "mov" instruction.
|
||||||
|
if inst.Op != x86asm.MOV {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if inst.Args[0] != x86asm.RAX && inst.Args[0] != x86asm.EAX {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
arg := inst.Args[1].(x86asm.Mem)
|
||||||
|
|
||||||
|
// First assume that the address is a direct addressing.
|
||||||
|
addr := arg.Disp
|
||||||
|
if arg.Base == x86asm.EIP || arg.Base == x86asm.RIP {
|
||||||
|
// If the addressing is based on the instruction pointer, fix the address.
|
||||||
|
addr = addr + int64(fcn.Offset) + int64(s)
|
||||||
|
} else if arg.Base == 0 && arg.Disp > 0 {
|
||||||
|
// In order to support x32 direct addressing
|
||||||
|
} else {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// If the addressing is based on the stack pointer, this is not the right
|
||||||
|
// instruction.
|
||||||
|
if arg.Base == x86asm.ESP || arg.Base == x86asm.RSP {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// Resolve the pointer to the string. If we get no data, this is not the
|
||||||
|
// right instruction.
|
||||||
|
b, _ := f.Bytes(uint64(addr), uint64(0x20))
|
||||||
|
if b == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
r := bytes.NewReader(b)
|
||||||
|
ptr, err := readUIntTo64(r, f.FileInfo.ByteOrder, is32)
|
||||||
|
if err != nil {
|
||||||
|
// Probably not the right instruction, so go to next.
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
l, err := readUIntTo64(r, f.FileInfo.ByteOrder, is32)
|
||||||
|
if err != nil {
|
||||||
|
// Probably not the right instruction, so go to next.
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
bstr, _ := f.Bytes(ptr, l)
|
||||||
|
if bstr == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
ver := string(bstr)
|
||||||
|
if !utf8.ValidString(ver) {
|
||||||
|
return "", ErrNoGoRootFound
|
||||||
|
}
|
||||||
|
return ver, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// for go version vary from 1.5 to 1.9
|
||||||
|
s = 0
|
||||||
|
var insts []x86asm.Inst
|
||||||
|
for s < len(buf) {
|
||||||
|
inst, err := x86asm.Decode(buf[s:], mode)
|
||||||
|
if err != nil {
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
s = s + inst.Len
|
||||||
|
insts = append(insts, inst)
|
||||||
|
}
|
||||||
|
var length, addr uint64
|
||||||
|
// Look up the address from the end of the assembly instruction
|
||||||
|
for i := len(insts) - 1; i >= 0; i-- {
|
||||||
|
inst := insts[i]
|
||||||
|
|
||||||
|
if inst.Op == x86asm.MOV && length == 0 {
|
||||||
|
switch v := inst.Args[1].(type) {
|
||||||
|
case x86asm.Imm:
|
||||||
|
length = uint64(v)
|
||||||
|
continue
|
||||||
|
default:
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (inst.Op == x86asm.LEA || inst.Op == x86asm.MOV) && addr == 0 {
|
||||||
|
switch v := inst.Args[1].(type) {
|
||||||
|
case x86asm.Mem:
|
||||||
|
arg := v
|
||||||
|
if arg.Base == x86asm.ESP || arg.Base == x86asm.RSP {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
addr = uint64(arg.Disp)
|
||||||
|
if arg.Base == x86asm.EIP || arg.Base == x86asm.RIP {
|
||||||
|
// If the addressing is based on the instruction pointer, fix the address.
|
||||||
|
s = 0
|
||||||
|
for i2, inst2 := range insts {
|
||||||
|
if i2 > i {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
s += inst2.Len
|
||||||
|
}
|
||||||
|
addr = addr + fcn.Offset + uint64(s)
|
||||||
|
} else if arg.Base == 0 && arg.Disp > 0 {
|
||||||
|
// In order to support x32 direct addressing
|
||||||
|
} else {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
case x86asm.Imm:
|
||||||
|
addr = uint64(v)
|
||||||
|
default:
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if length > 0 && addr > 0 {
|
||||||
|
bstr, _ := f.Bytes(addr, length)
|
||||||
|
if bstr == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
ver := string(bstr)
|
||||||
|
if !utf8.ValidString(ver) {
|
||||||
|
return "", ErrNoGoRootFound
|
||||||
|
}
|
||||||
|
return ver, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "", ErrNoGoRootFound
|
||||||
|
}
|
||||||
|
|
||||||
|
func tryFromTimeInit(f *GoFile) (string, error) {
|
||||||
|
// Check for non supported architectures.
|
||||||
|
if f.FileInfo.Arch != Arch386 && f.FileInfo.Arch != ArchAMD64 {
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
|
||||||
|
is32 := false
|
||||||
|
if f.FileInfo.Arch == Arch386 {
|
||||||
|
is32 = true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find time.init function.
|
||||||
|
var fcn *Function
|
||||||
|
std, err := f.GetSTDLib()
|
||||||
|
if err != nil {
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
|
||||||
|
pkgLoop:
|
||||||
|
for _, v := range std {
|
||||||
|
if v.Name != "time" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
for _, vv := range v.Functions {
|
||||||
|
if vv.Name != "init" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
fcn = vv
|
||||||
|
break pkgLoop
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the functions was found
|
||||||
|
if fcn == nil {
|
||||||
|
// If we can't find the function there is nothing to do.
|
||||||
|
return "", ErrNoGoRootFound
|
||||||
|
}
|
||||||
|
// Get the raw hex.
|
||||||
|
buf, err := f.Bytes(fcn.Offset, fcn.End-fcn.Offset)
|
||||||
|
if err != nil {
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
s := 0
|
||||||
|
mode := f.FileInfo.WordSize * 8
|
||||||
|
|
||||||
|
for s < len(buf) {
|
||||||
|
inst, err := x86asm.Decode(buf[s:], mode)
|
||||||
|
if err != nil {
|
||||||
|
// If we fail to decode the instruction, something is wrong so
|
||||||
|
// bailout.
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update next instruction location.
|
||||||
|
s = s + inst.Len
|
||||||
|
|
||||||
|
// Check if it's a "mov" instruction.
|
||||||
|
if inst.Op != x86asm.MOV {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if inst.Args[0] != x86asm.RAX && inst.Args[0] != x86asm.ECX {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
kindof := reflect.TypeOf(inst.Args[1])
|
||||||
|
if kindof.String() != "x86asm.Mem" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
arg := inst.Args[1].(x86asm.Mem)
|
||||||
|
|
||||||
|
// First assume that the address is a direct addressing.
|
||||||
|
addr := arg.Disp
|
||||||
|
if arg.Base == x86asm.EIP || arg.Base == x86asm.RIP {
|
||||||
|
// If the addressing is based on the instruction pointer, fix the address.
|
||||||
|
addr = addr + int64(fcn.Offset) + int64(s)
|
||||||
|
} else if arg.Base == 0 && arg.Disp > 0 {
|
||||||
|
// In order to support x32 direct addressing
|
||||||
|
} else {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// Resolve the pointer to the string. If we get no data, this is not the
|
||||||
|
// right instruction.
|
||||||
|
b, _ := f.Bytes(uint64(addr), uint64(0x20))
|
||||||
|
if b == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
r := bytes.NewReader(b)
|
||||||
|
ptr, err := readUIntTo64(r, f.FileInfo.ByteOrder, is32)
|
||||||
|
if err != nil {
|
||||||
|
// Probably not the right instruction, so go to next.
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the pointer is nil, it's not the right instruction
|
||||||
|
if ptr == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
l, err := readUIntTo64(r, f.FileInfo.ByteOrder, is32)
|
||||||
|
if err != nil {
|
||||||
|
// Probably not the right instruction, so go to next.
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
bstr, _ := f.Bytes(ptr, l)
|
||||||
|
if bstr == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
ver := string(bstr)
|
||||||
|
if !utf8.ValidString(ver) {
|
||||||
|
return "", ErrNoGoRootFound
|
||||||
|
}
|
||||||
|
return ver, nil
|
||||||
|
}
|
||||||
|
return "", ErrNoGoRootFound
|
||||||
|
}
|
||||||
|
|
||||||
|
func findGoRootPath(f *GoFile) (string, error) {
|
||||||
|
var goroot string
|
||||||
|
// There is no GOROOT function may be inlined (after go1.16)
|
||||||
|
// at this time GOROOT is obtained through time_init function
|
||||||
|
goroot, err := tryFromGOROOT(f)
|
||||||
|
if goroot != "" {
|
||||||
|
return goroot, nil
|
||||||
|
}
|
||||||
|
if err != nil && err != ErrNoGoRootFound {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
goroot, err = tryFromTimeInit(f)
|
||||||
|
if goroot != "" {
|
||||||
|
return goroot, nil
|
||||||
|
}
|
||||||
|
if err != nil && err != ErrNoGoRootFound {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try determine from std lib package paths.
|
||||||
|
pkg, err := f.GetSTDLib()
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("error when getting standard library packages: %w", err)
|
||||||
|
}
|
||||||
|
if len(pkg) == 0 {
|
||||||
|
return "", fmt.Errorf("no standard library packages found")
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, v := range pkg {
|
||||||
|
subpath := fmt.Sprintf("/src/%s", v.Name)
|
||||||
|
if strings.HasSuffix(v.Filepath, subpath) {
|
||||||
|
return strings.TrimSuffix(v.Filepath, subpath), nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return "", ErrNoGoRootFound
|
||||||
|
}
|
||||||
250
vendor/github.com/goretk/gore/goversion.go
generated
vendored
Normal file
250
vendor/github.com/goretk/gore/goversion.go
generated
vendored
Normal file
@ -0,0 +1,250 @@
|
|||||||
|
// This file is part of GoRE.
|
||||||
|
//
|
||||||
|
// Copyright (C) 2019-2021 GoRE Authors
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU Affero General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Affero General Public License
|
||||||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
package gore
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"regexp"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"golang.org/x/arch/x86/x86asm"
|
||||||
|
"golang.org/x/mod/semver"
|
||||||
|
)
|
||||||
|
|
||||||
|
var goVersionMatcher = regexp.MustCompile(`(go[\d+\.]*(beta|rc)?[\d*])`)
|
||||||
|
|
||||||
|
// GoVersion holds information about the compiler version.
|
||||||
|
type GoVersion struct {
|
||||||
|
// Name is a string representation of the version.
|
||||||
|
Name string
|
||||||
|
// SHA is a digest of the git commit for the release.
|
||||||
|
SHA string
|
||||||
|
// Timestamp is a string of the timestamp when the commit was created.
|
||||||
|
Timestamp string
|
||||||
|
}
|
||||||
|
|
||||||
|
// ResolveGoVersion tries to return the GoVersion for the given tag.
|
||||||
|
// For example the tag: go1 will return a GoVersion struct representing version 1.0 of the compiler.
|
||||||
|
// If no goversion for the given tag is found, nil is returned.
|
||||||
|
func ResolveGoVersion(tag string) *GoVersion {
|
||||||
|
v, ok := goversions[tag]
|
||||||
|
if !ok {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
|
// GoVersionCompare compares two version strings.
|
||||||
|
// If a < b, -1 is returned.
|
||||||
|
// If a == b, 0 is returned.
|
||||||
|
// If a > b, 1 is returned.
|
||||||
|
func GoVersionCompare(a, b string) int {
|
||||||
|
if a == b {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return semver.Compare(buildSemVerString(a), buildSemVerString(b))
|
||||||
|
}
|
||||||
|
|
||||||
|
func buildSemVerString(v string) string {
|
||||||
|
// First remove the go prefix
|
||||||
|
tmp := strings.TrimPrefix(v, "go")
|
||||||
|
|
||||||
|
// If it has a pre-release, we need to add a dash and patch version of 0.
|
||||||
|
if strings.Contains(tmp, "beta") {
|
||||||
|
tmp = strings.ReplaceAll(tmp, "beta", ".0-beta")
|
||||||
|
}
|
||||||
|
if strings.Contains(tmp, "rc") {
|
||||||
|
tmp = strings.ReplaceAll(tmp, "rc", ".0-rc")
|
||||||
|
}
|
||||||
|
|
||||||
|
return "v" + tmp
|
||||||
|
}
|
||||||
|
|
||||||
|
func findGoCompilerVersion(f *GoFile) (*GoVersion, error) {
|
||||||
|
// Try to determine the version based on the schedinit function.
|
||||||
|
if v := tryFromSchedInit(f); v != nil {
|
||||||
|
return v, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// If no version was found, search the sections for the
|
||||||
|
// version string.
|
||||||
|
|
||||||
|
data, err := f.fh.getRData()
|
||||||
|
// If read only data section does not exist, try text.
|
||||||
|
if err == ErrSectionDoesNotExist {
|
||||||
|
data, err = f.fh.getCodeSection()
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
notfound := false
|
||||||
|
for !notfound {
|
||||||
|
version := matchGoVersionString(data)
|
||||||
|
if version == "" {
|
||||||
|
return nil, ErrNoGoVersionFound
|
||||||
|
}
|
||||||
|
ver := ResolveGoVersion(version)
|
||||||
|
// Go before 1.4 does not have the version string so if we have found
|
||||||
|
// a version string below 1.4beta1 it is a false positive.
|
||||||
|
if ver == nil || GoVersionCompare(ver.Name, "go1.4beta1") < 0 {
|
||||||
|
off := bytes.Index(data, []byte(version))
|
||||||
|
// No match
|
||||||
|
if off == -1 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
data = data[off+2:]
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
return ver, nil
|
||||||
|
}
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// tryFromSchedInit tries to identify the version of the Go compiler that compiled the code.
|
||||||
|
// The function "schedinit" in the "runtime" package has the only reference to this string
|
||||||
|
// used to identify the version.
|
||||||
|
// The function returns nil if no version is found.
|
||||||
|
func tryFromSchedInit(f *GoFile) *GoVersion {
|
||||||
|
// Check for non supported architectures.
|
||||||
|
if f.FileInfo.Arch != Arch386 && f.FileInfo.Arch != ArchAMD64 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
is32 := false
|
||||||
|
if f.FileInfo.Arch == Arch386 {
|
||||||
|
is32 = true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find shedinit function.
|
||||||
|
var fcn *Function
|
||||||
|
std, err := f.GetSTDLib()
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
pkgLoop:
|
||||||
|
for _, v := range std {
|
||||||
|
if v.Name != "runtime" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
for _, vv := range v.Functions {
|
||||||
|
if vv.Name != "schedinit" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
fcn = vv
|
||||||
|
break pkgLoop
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the functions was found
|
||||||
|
if fcn == nil {
|
||||||
|
// If we can't find the function there is nothing to do.
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the raw hex.
|
||||||
|
buf, err := f.Bytes(fcn.Offset, fcn.End-fcn.Offset)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Disassemble the function until the loading of the Go version is found.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Counter for how many bytes has been read.
|
||||||
|
s := 0
|
||||||
|
mode := f.FileInfo.WordSize * 8
|
||||||
|
|
||||||
|
for s < len(buf) {
|
||||||
|
inst, err := x86asm.Decode(buf[s:], mode)
|
||||||
|
if err != nil {
|
||||||
|
// If we fail to decode the instruction, something is wrong so
|
||||||
|
// bailout.
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update next instruction location.
|
||||||
|
s = s + inst.Len
|
||||||
|
|
||||||
|
// Check if it's a "lea" instruction.
|
||||||
|
if inst.Op != x86asm.LEA {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check what it's loading and if it's pointing to the compiler version used.
|
||||||
|
// First assume that the address is a direct addressing.
|
||||||
|
arg := inst.Args[1].(x86asm.Mem)
|
||||||
|
addr := arg.Disp
|
||||||
|
if arg.Base == x86asm.EIP || arg.Base == x86asm.RIP {
|
||||||
|
// If the addressing is based on the instruction pointer, fix the address.
|
||||||
|
addr = addr + int64(fcn.Offset) + int64(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the addressing is based on the stack pointer, this is not the right
|
||||||
|
// instruction.
|
||||||
|
if arg.Base == x86asm.ESP || arg.Base == x86asm.RSP {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// Resolve the pointer to the string. If we get no data, this is not the
|
||||||
|
// right instruction.
|
||||||
|
b, _ := f.Bytes(uint64(addr), uint64(0x20))
|
||||||
|
if b == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
r := bytes.NewReader(b)
|
||||||
|
ptr, err := readUIntTo64(r, f.FileInfo.ByteOrder, is32)
|
||||||
|
if err != nil {
|
||||||
|
// Probably not the right instruction, so go to next.
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
l, err := readUIntTo64(r, f.FileInfo.ByteOrder, is32)
|
||||||
|
if err != nil {
|
||||||
|
// Probably not the right instruction, so go to next.
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
bstr, _ := f.Bytes(ptr, l)
|
||||||
|
if bstr == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if !bytes.HasPrefix(bstr, []byte("go1.")) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// Likely the version string.
|
||||||
|
ver := string(bstr)
|
||||||
|
|
||||||
|
gover := ResolveGoVersion(ver)
|
||||||
|
if gover != nil {
|
||||||
|
return gover
|
||||||
|
}
|
||||||
|
|
||||||
|
// An unknown version.
|
||||||
|
return &GoVersion{Name: ver}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func matchGoVersionString(data []byte) string {
|
||||||
|
return string(goVersionMatcher.Find(data))
|
||||||
|
}
|
||||||
315
vendor/github.com/goretk/gore/goversion_gen.go
generated
vendored
Normal file
315
vendor/github.com/goretk/gore/goversion_gen.go
generated
vendored
Normal file
@ -0,0 +1,315 @@
|
|||||||
|
// This file is part of GoRE.
|
||||||
|
//
|
||||||
|
// Copyright (C) 2019-2021 GoRE Authors
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU Affero General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Affero General Public License
|
||||||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
// Code generated by go generate; DO NOT EDIT.
|
||||||
|
// This file was generated at
|
||||||
|
// 2023-11-10 16:31:23.856529581 +0000 UTC
|
||||||
|
|
||||||
|
package gore
|
||||||
|
|
||||||
|
var goversions = map[string]*GoVersion{
|
||||||
|
"go1": {Name: "go1", SHA: "6174b5e21e73714c63061e66efdbe180e1c5491d", Timestamp: "2012-03-28T12:41:59Z"},
|
||||||
|
"go1.0.1": {Name: "go1.0.1", SHA: "2fffba7fe19690e038314d17a117d6b87979c89f", Timestamp: "2012-04-26T19:50:14Z"},
|
||||||
|
"go1.0.2": {Name: "go1.0.2", SHA: "cb6c6570b73a1c4d19cad94570ed277f7dae55ac", Timestamp: "2012-06-14T02:50:42Z"},
|
||||||
|
"go1.0.3": {Name: "go1.0.3", SHA: "30be9b4313622c2077539e68826194cb1028c691", Timestamp: "2012-09-21T22:10:44Z"},
|
||||||
|
"go1.1": {Name: "go1.1", SHA: "205f850ceacfc39d1e9d76a9569416284594ce8c", Timestamp: "2013-05-13T20:03:09Z"},
|
||||||
|
"go1.1.1": {Name: "go1.1.1", SHA: "d260448f6b6ac10efe4ae7f6dfe944e72bc2a676", Timestamp: "2013-06-13T02:49:43Z"},
|
||||||
|
"go1.1.2": {Name: "go1.1.2", SHA: "1d6d8fca241bb611af51e265c1b5a2e9ae904702", Timestamp: "2013-08-13T05:33:06Z"},
|
||||||
|
"go1.10": {Name: "go1.10", SHA: "bf86aec25972f3a100c3aa58a6abcbcc35bdea49", Timestamp: "2018-02-16T16:05:53Z"},
|
||||||
|
"go1.10.1": {Name: "go1.10.1", SHA: "ac7c0ee26dda18076d5f6c151d8f920b43340ae3", Timestamp: "2018-03-29T06:09:52Z"},
|
||||||
|
"go1.10.2": {Name: "go1.10.2", SHA: "71bdbf431b79dff61944f22c25c7e085ccfc25d5", Timestamp: "2018-04-30T19:03:55Z"},
|
||||||
|
"go1.10.3": {Name: "go1.10.3", SHA: "fe8a0d12b14108cbe2408b417afcaab722b0727c", Timestamp: "2018-06-06T23:47:44Z"},
|
||||||
|
"go1.10.4": {Name: "go1.10.4", SHA: "2191fce26a7fd1cd5b4975e7bd44ab44b1d9dd78", Timestamp: "2018-08-24T19:26:40Z"},
|
||||||
|
"go1.10.5": {Name: "go1.10.5", SHA: "1ae739797ec72acbd6d90b94a2366a31566205c2", Timestamp: "2018-11-02T20:17:59Z"},
|
||||||
|
"go1.10.6": {Name: "go1.10.6", SHA: "25ca8f49c3fc4a68daff7a23ab613e3453be5cda", Timestamp: "2018-12-13T17:16:47Z"},
|
||||||
|
"go1.10.7": {Name: "go1.10.7", SHA: "f5ff72d62301c4e9d0a78167fab5914ca12919bd", Timestamp: "2018-12-14T23:34:23Z"},
|
||||||
|
"go1.10.8": {Name: "go1.10.8", SHA: "b0cb374daf646454998bac7b393f3236a2ab6aca", Timestamp: "2019-01-23T19:47:24Z"},
|
||||||
|
"go1.10beta1": {Name: "go1.10beta1", SHA: "9ce6b5c2ed5d3d5251b9a6a0c548d5fb2c8567e8", Timestamp: "2017-12-07T17:38:51Z"},
|
||||||
|
"go1.10beta2": {Name: "go1.10beta2", SHA: "594668a5a96267a46282ce3007a584ec07adf705", Timestamp: "2018-01-11T17:44:08Z"},
|
||||||
|
"go1.10rc1": {Name: "go1.10rc1", SHA: "5348aed83e39bd1d450d92d7f627e994c2db6ebf", Timestamp: "2018-01-25T17:24:13Z"},
|
||||||
|
"go1.10rc2": {Name: "go1.10rc2", SHA: "20e228f2fdb44350c858de941dff4aea9f3127b8", Timestamp: "2018-02-07T16:12:58Z"},
|
||||||
|
"go1.11": {Name: "go1.11", SHA: "41e62b8c49d21659b48a95216e3062032285250f", Timestamp: "2018-08-24T20:18:43Z"},
|
||||||
|
"go1.11.1": {Name: "go1.11.1", SHA: "26957168c4c0cdcc7ca4f0b19d0eb19474d224ac", Timestamp: "2018-10-01T20:59:20Z"},
|
||||||
|
"go1.11.10": {Name: "go1.11.10", SHA: "efa061d9f5d52846dfc3dda40eaf8eccfeeae8d2", Timestamp: "2019-05-06T20:50:17Z"},
|
||||||
|
"go1.11.11": {Name: "go1.11.11", SHA: "541c49144d73f2a03374517091835fa8a43eebe2", Timestamp: "2019-06-11T18:11:11Z"},
|
||||||
|
"go1.11.12": {Name: "go1.11.12", SHA: "4128f163d6dca1b8d703da8cf86ef679608856a0", Timestamp: "2019-07-08T19:49:55Z"},
|
||||||
|
"go1.11.13": {Name: "go1.11.13", SHA: "b2967c0e5c5271bb4469e1f615fb85879ebd8a57", Timestamp: "2019-08-13T16:26:07Z"},
|
||||||
|
"go1.11.2": {Name: "go1.11.2", SHA: "e8a95aeb75536496432bcace1fb2bbfa449bf0fa", Timestamp: "2018-11-02T20:17:52Z"},
|
||||||
|
"go1.11.3": {Name: "go1.11.3", SHA: "90c896448691b5edb0ab11110f37234f63cd28ed", Timestamp: "2018-12-13T17:14:02Z"},
|
||||||
|
"go1.11.4": {Name: "go1.11.4", SHA: "4601a4c1b1c00fbe507508f0267ec5a9445bb7e5", Timestamp: "2018-12-14T23:34:32Z"},
|
||||||
|
"go1.11.5": {Name: "go1.11.5", SHA: "35bb62e60a7779ff82c3067903b3306ff8666471", Timestamp: "2019-01-23T19:49:15Z"},
|
||||||
|
"go1.11.6": {Name: "go1.11.6", SHA: "e18f2ca380f52bbf8cac039ccfdf445e9047c810", Timestamp: "2019-03-14T19:57:30Z"},
|
||||||
|
"go1.11.7": {Name: "go1.11.7", SHA: "2c5363d9c1cf51457d6d2466a63e6576e80327f8", Timestamp: "2019-04-05T19:09:03Z"},
|
||||||
|
"go1.11.8": {Name: "go1.11.8", SHA: "f8a63418e985d972c86d3da5bf90b7e81b72b468", Timestamp: "2019-04-08T21:30:39Z"},
|
||||||
|
"go1.11.9": {Name: "go1.11.9", SHA: "428e5f29a957b591d82e640b619b684aa25fba4e", Timestamp: "2019-04-11T23:31:23Z"},
|
||||||
|
"go1.11beta1": {Name: "go1.11beta1", SHA: "a12c1f26e4cc602dae62ec065a237172a5b8f926", Timestamp: "2018-06-26T20:00:51Z"},
|
||||||
|
"go1.11beta2": {Name: "go1.11beta2", SHA: "c814ac44c0571f844718f07aa52afa47e37fb1ed", Timestamp: "2018-07-19T21:30:27Z"},
|
||||||
|
"go1.11beta3": {Name: "go1.11beta3", SHA: "1b870077c896379c066b41657d3c9062097a6943", Timestamp: "2018-08-03T17:21:10Z"},
|
||||||
|
"go1.11rc1": {Name: "go1.11rc1", SHA: "807e7f2420c683384dc9c6db498808ba1b7aab17", Timestamp: "2018-08-13T23:43:08Z"},
|
||||||
|
"go1.11rc2": {Name: "go1.11rc2", SHA: "02c0c32960f65d0b9c66ec840c612f5f9623dc51", Timestamp: "2018-08-22T22:17:06Z"},
|
||||||
|
"go1.12": {Name: "go1.12", SHA: "05e77d41914d247a1e7caf37d7125ccaa5a53505", Timestamp: "2019-02-25T23:01:48Z"},
|
||||||
|
"go1.12.1": {Name: "go1.12.1", SHA: "0380c9ad38843d523d9c9804fe300cb7edd7cd3c", Timestamp: "2019-03-14T19:18:42Z"},
|
||||||
|
"go1.12.10": {Name: "go1.12.10", SHA: "6c15c7cce718e1e9a47f4f0ab1bd70923b04557b", Timestamp: "2019-09-25T18:48:21Z"},
|
||||||
|
"go1.12.11": {Name: "go1.12.11", SHA: "ef74bfc859c918aeab796c2fa18f4a5dde862343", Timestamp: "2019-10-17T17:32:27Z"},
|
||||||
|
"go1.12.12": {Name: "go1.12.12", SHA: "9e6d3ca2794c04b3f65019ee90b6e406bcfc9286", Timestamp: "2019-10-17T21:51:57Z"},
|
||||||
|
"go1.12.13": {Name: "go1.12.13", SHA: "a8528068d581fcd110d0cb4f3c04ad77261abf6d", Timestamp: "2019-10-31T22:53:22Z"},
|
||||||
|
"go1.12.14": {Name: "go1.12.14", SHA: "8a720dabf102975ced5664b9cf668ac4ca080245", Timestamp: "2019-12-04T21:35:28Z"},
|
||||||
|
"go1.12.15": {Name: "go1.12.15", SHA: "694e20f4e08af7e7669c9652424d0df9b0b83f00", Timestamp: "2020-01-09T19:00:28Z"},
|
||||||
|
"go1.12.16": {Name: "go1.12.16", SHA: "deac3221fc4cd365fb40d269dd56551e9d354356", Timestamp: "2020-01-27T22:27:19Z"},
|
||||||
|
"go1.12.17": {Name: "go1.12.17", SHA: "46cb016190389b7e37b21f04e5343a628ca1f662", Timestamp: "2020-02-12T19:55:29Z"},
|
||||||
|
"go1.12.2": {Name: "go1.12.2", SHA: "ac02fdec7cd16ea8d3de1fc33def9cfabec5170d", Timestamp: "2019-04-05T19:24:53Z"},
|
||||||
|
"go1.12.3": {Name: "go1.12.3", SHA: "62ec3dd260324d243491b271d53ccdfd4a1f14e3", Timestamp: "2019-04-08T21:30:25Z"},
|
||||||
|
"go1.12.4": {Name: "go1.12.4", SHA: "eda3401e807be8928eed48bb5fc85ffa8e62ddb4", Timestamp: "2019-04-11T23:31:30Z"},
|
||||||
|
"go1.12.5": {Name: "go1.12.5", SHA: "3a1b4e75f8b6c1b57db73bccf7ca871bf1a97ca9", Timestamp: "2019-05-06T21:12:37Z"},
|
||||||
|
"go1.12.6": {Name: "go1.12.6", SHA: "4ce6a8e89668b87dce67e2f55802903d6eb9110a", Timestamp: "2019-06-11T15:21:11Z"},
|
||||||
|
"go1.12.7": {Name: "go1.12.7", SHA: "7f416b4f048677d0784e6941516c0f1e6052b2d6", Timestamp: "2019-07-08T19:50:25Z"},
|
||||||
|
"go1.12.8": {Name: "go1.12.8", SHA: "306a74284eb261acb34ce7f70962f357906a2759", Timestamp: "2019-08-13T16:27:09Z"},
|
||||||
|
"go1.12.9": {Name: "go1.12.9", SHA: "06472b99cdf59f00049f3cd8c9e05ba283cb2c56", Timestamp: "2019-08-15T18:44:01Z"},
|
||||||
|
"go1.12beta1": {Name: "go1.12beta1", SHA: "e3b4b7baad555f74b6fbc0ddc00d46ed0ac03a0a", Timestamp: "2018-12-18T23:01:06Z"},
|
||||||
|
"go1.12beta2": {Name: "go1.12beta2", SHA: "4b3f04c63b5b1a1bbc4dfd71c34341ea4e935115", Timestamp: "2019-01-10T18:15:48Z"},
|
||||||
|
"go1.12rc1": {Name: "go1.12rc1", SHA: "1af509d46e31a14e7ff17e23b1fd84250976b405", Timestamp: "2019-02-11T20:14:50Z"},
|
||||||
|
"go1.13": {Name: "go1.13", SHA: "cc8838d645b2b7026c1f3aaceb011775c5ca3a08", Timestamp: "2019-09-03T17:05:17Z"},
|
||||||
|
"go1.13.1": {Name: "go1.13.1", SHA: "b17fd8e49d24eb298c53de5cd0a8923f1e0270ba", Timestamp: "2019-09-25T18:48:17Z"},
|
||||||
|
"go1.13.10": {Name: "go1.13.10", SHA: "a57f07aac237d366630e85d080ef1ce0c34f0d09", Timestamp: "2020-04-08T19:09:06Z"},
|
||||||
|
"go1.13.11": {Name: "go1.13.11", SHA: "237b6067c17ac3ef1e02632b77deefb5e9837cbb", Timestamp: "2020-05-14T19:18:42Z"},
|
||||||
|
"go1.13.12": {Name: "go1.13.12", SHA: "6be4a5eb4898c7b5e7557dda061cc09ba310698b", Timestamp: "2020-06-01T19:34:58Z"},
|
||||||
|
"go1.13.13": {Name: "go1.13.13", SHA: "1f8859c22ccdeb969b252c8139bf4b1aae5c4909", Timestamp: "2020-07-14T14:10:10Z"},
|
||||||
|
"go1.13.14": {Name: "go1.13.14", SHA: "d3ba94164a1c404a01369fb54ddd4f5b94d91348", Timestamp: "2020-07-16T22:23:43Z"},
|
||||||
|
"go1.13.15": {Name: "go1.13.15", SHA: "e71b61180aa19a60c23b3b7e3f6586726ebe4fd1", Timestamp: "2020-08-06T14:43:47Z"},
|
||||||
|
"go1.13.2": {Name: "go1.13.2", SHA: "72766093e6bd092eb18df3759055625ba8436484", Timestamp: "2019-10-17T17:32:17Z"},
|
||||||
|
"go1.13.3": {Name: "go1.13.3", SHA: "e64356a4484deb5da57396a4cd80e26667b86b79", Timestamp: "2019-10-17T21:56:53Z"},
|
||||||
|
"go1.13.4": {Name: "go1.13.4", SHA: "3f995c3f3b43033013013e6c7ccc93a9b1411ca9", Timestamp: "2019-10-31T22:47:33Z"},
|
||||||
|
"go1.13.5": {Name: "go1.13.5", SHA: "9341fe073e6f7742c9d61982084874560dac2014", Timestamp: "2019-12-04T21:55:02Z"},
|
||||||
|
"go1.13.6": {Name: "go1.13.6", SHA: "14b79df428fdab83ebc813a72ab714d1e2c488d2", Timestamp: "2020-01-09T19:00:05Z"},
|
||||||
|
"go1.13.7": {Name: "go1.13.7", SHA: "7d2473dc81c659fba3f3b83bc6e93ca5fe37a898", Timestamp: "2020-01-27T22:26:53Z"},
|
||||||
|
"go1.13.8": {Name: "go1.13.8", SHA: "a7acf9af07bdc288129fa5756768b41f312d05f4", Timestamp: "2020-02-12T19:55:45Z"},
|
||||||
|
"go1.13.9": {Name: "go1.13.9", SHA: "33554bc6af72f13e5eb319fd5f5aa5c9a150a60c", Timestamp: "2020-03-19T15:17:09Z"},
|
||||||
|
"go1.13beta1": {Name: "go1.13beta1", SHA: "60f14fddfee107dedd76c0be6b422a3d8ccc841a", Timestamp: "2019-06-26T16:35:14Z"},
|
||||||
|
"go1.13rc1": {Name: "go1.13rc1", SHA: "ed4f3f313438b8765da6c4605060529761db0797", Timestamp: "2019-08-21T19:21:42Z"},
|
||||||
|
"go1.13rc2": {Name: "go1.13rc2", SHA: "d7b402a49a8ef5af911d7873bdbc5f61335f1d41", Timestamp: "2019-08-29T14:35:17Z"},
|
||||||
|
"go1.14": {Name: "go1.14", SHA: "20a838ab94178c55bc4dc23ddc332fce8545a493", Timestamp: "2020-02-25T17:40:40Z"},
|
||||||
|
"go1.14.1": {Name: "go1.14.1", SHA: "564c76a268b75f56d6f465b82fba7f6fb929fd70", Timestamp: "2020-03-19T15:17:01Z"},
|
||||||
|
"go1.14.10": {Name: "go1.14.10", SHA: "b5a3989dac97270b89cfce250cbb42695647d5cb", Timestamp: "2020-10-14T19:10:36Z"},
|
||||||
|
"go1.14.11": {Name: "go1.14.11", SHA: "e82710b825958f30b924fc6dba1fd0a63b517199", Timestamp: "2020-11-05T21:21:19Z"},
|
||||||
|
"go1.14.12": {Name: "go1.14.12", SHA: "bc9c580409b61af6b29f0cbd9d45bec63dbe2ccb", Timestamp: "2020-11-12T16:47:42Z"},
|
||||||
|
"go1.14.13": {Name: "go1.14.13", SHA: "6eed7d361d276b69a1cfdeeb7690237a6385b073", Timestamp: "2020-12-03T17:27:26Z"},
|
||||||
|
"go1.14.14": {Name: "go1.14.14", SHA: "ccb4f250bd7e382e50824c36ec5a3e1a57dcf11a", Timestamp: "2021-01-19T19:47:38Z"},
|
||||||
|
"go1.14.15": {Name: "go1.14.15", SHA: "5cf057ddedfbb149b71c85ec86050431dd6b2d9d", Timestamp: "2021-02-04T20:43:04Z"},
|
||||||
|
"go1.14.2": {Name: "go1.14.2", SHA: "96745b980cfde139e8611772e2bc0c59a8e6cdf7", Timestamp: "2020-04-08T19:09:10Z"},
|
||||||
|
"go1.14.3": {Name: "go1.14.3", SHA: "f296b7a6f045325a230f77e9bda1470b1270f817", Timestamp: "2020-05-14T19:18:34Z"},
|
||||||
|
"go1.14.4": {Name: "go1.14.4", SHA: "83b181c68bf332ac7948f145f33d128377a09c42", Timestamp: "2020-06-01T19:34:54Z"},
|
||||||
|
"go1.14.5": {Name: "go1.14.5", SHA: "36fcde1676a0d3863cb5f295eed6938cd782fcbb", Timestamp: "2020-07-14T14:10:30Z"},
|
||||||
|
"go1.14.6": {Name: "go1.14.6", SHA: "edfd6f28486017dcb136cd3f3ec252706d4b326e", Timestamp: "2020-07-16T22:23:28Z"},
|
||||||
|
"go1.14.7": {Name: "go1.14.7", SHA: "d571a77846dfee8efd076223a882915cd6cb52f4", Timestamp: "2020-08-06T14:43:51Z"},
|
||||||
|
"go1.14.8": {Name: "go1.14.8", SHA: "c187a3d47c41d54bd570905caad128ba947e3d03", Timestamp: "2020-09-01T14:08:43Z"},
|
||||||
|
"go1.14.9": {Name: "go1.14.9", SHA: "26a85c3634b8b5dc9cf8adb30664dac0ddc6acf0", Timestamp: "2020-09-09T16:38:16Z"},
|
||||||
|
"go1.14beta1": {Name: "go1.14beta1", SHA: "a5bfd9da1d1b24f326399b6b75558ded14514f23", Timestamp: "2019-12-17T14:59:30Z"},
|
||||||
|
"go1.14rc1": {Name: "go1.14rc1", SHA: "a068054af141c01df5a4519844f4b77273605f4e", Timestamp: "2020-02-05T15:43:27Z"},
|
||||||
|
"go1.15": {Name: "go1.15", SHA: "0fdc3801bfd43d6f55e4ea5bf095e1ea55430339", Timestamp: "2020-08-11T19:01:57Z"},
|
||||||
|
"go1.15.1": {Name: "go1.15.1", SHA: "01af46f7cc419da19f8a6a444da8f6022c016803", Timestamp: "2020-09-01T14:08:32Z"},
|
||||||
|
"go1.15.10": {Name: "go1.15.10", SHA: "dcffdac515a1d409bcb61783d57ddb137b4741b9", Timestamp: "2021-03-11T17:08:16Z"},
|
||||||
|
"go1.15.11": {Name: "go1.15.11", SHA: "8c163e85267d146274f68854fe02b4a495586584", Timestamp: "2021-04-01T17:26:12Z"},
|
||||||
|
"go1.15.12": {Name: "go1.15.12", SHA: "07d8cba9e15f5c5a3b0462a9215dbeac0cebf027", Timestamp: "2021-05-06T14:59:58Z"},
|
||||||
|
"go1.15.13": {Name: "go1.15.13", SHA: "ab7f8297f9734b24a43a942930258cda411f16a3", Timestamp: "2021-06-03T17:14:37Z"},
|
||||||
|
"go1.15.14": {Name: "go1.15.14", SHA: "c6d89dbf9954b101589e2db8e170b84167782109", Timestamp: "2021-07-12T19:44:54Z"},
|
||||||
|
"go1.15.15": {Name: "go1.15.15", SHA: "acbe242f8a2cae8ef4749806291a37d23089b572", Timestamp: "2021-08-04T20:44:05Z"},
|
||||||
|
"go1.15.2": {Name: "go1.15.2", SHA: "9706f510a5e2754595d716bd64be8375997311fb", Timestamp: "2020-09-09T16:38:12Z"},
|
||||||
|
"go1.15.3": {Name: "go1.15.3", SHA: "1984ee00048b63eacd2155cd6d74a2d13e998272", Timestamp: "2020-10-14T19:10:41Z"},
|
||||||
|
"go1.15.4": {Name: "go1.15.4", SHA: "0e953add9656c32a788e06438cd7b533e968b7f8", Timestamp: "2020-11-05T21:21:32Z"},
|
||||||
|
"go1.15.5": {Name: "go1.15.5", SHA: "c53315d6cf1b4bfea6ff356b4a1524778c683bb9", Timestamp: "2020-11-12T16:39:58Z"},
|
||||||
|
"go1.15.6": {Name: "go1.15.6", SHA: "9b955d2d3fcff6a5bc8bce7bafdc4c634a28e95b", Timestamp: "2020-12-03T17:27:17Z"},
|
||||||
|
"go1.15.7": {Name: "go1.15.7", SHA: "2117ea9737bc9cb2e30cb087b76a283f68768819", Timestamp: "2021-01-19T19:47:12Z"},
|
||||||
|
"go1.15.8": {Name: "go1.15.8", SHA: "fa6752a5370735b8c2404d6de5191f2eea67130f", Timestamp: "2021-02-04T20:42:57Z"},
|
||||||
|
"go1.15.9": {Name: "go1.15.9", SHA: "13722418773b6a081816e8cc48131306565db1bd", Timestamp: "2021-03-10T14:24:59Z"},
|
||||||
|
"go1.15beta1": {Name: "go1.15beta1", SHA: "e92be18fd8b525b642ca25bdb3e2056b35d9d73c", Timestamp: "2020-06-10T14:56:01Z"},
|
||||||
|
"go1.15rc1": {Name: "go1.15rc1", SHA: "3e8f6b0791a670e52d25d76813d669daa68acfb4", Timestamp: "2020-07-24T16:28:26Z"},
|
||||||
|
"go1.15rc2": {Name: "go1.15rc2", SHA: "c4f8cb43caf0bcd0c730d7d04a3fce129393cecc", Timestamp: "2020-08-07T14:56:02Z"},
|
||||||
|
"go1.16": {Name: "go1.16", SHA: "f21be2fdc6f1becdbed1592ea0b245cdeedc5ac8", Timestamp: "2021-02-16T18:08:40Z"},
|
||||||
|
"go1.16.1": {Name: "go1.16.1", SHA: "e9e0473681e581040b4adcd64b53967e1572fe8d", Timestamp: "2021-03-10T14:25:03Z"},
|
||||||
|
"go1.16.10": {Name: "go1.16.10", SHA: "23991f50b34f8707bcfc7761321bb3b0e9dba10e", Timestamp: "2021-11-04T13:55:28Z"},
|
||||||
|
"go1.16.11": {Name: "go1.16.11", SHA: "8faefcbfce6d2b2875ab74d81bb4e94b2e3adaf5", Timestamp: "2021-12-02T20:00:54Z"},
|
||||||
|
"go1.16.12": {Name: "go1.16.12", SHA: "f1f3923d2e3a0952c698d2901fc052046fa4af3d", Timestamp: "2021-12-09T13:44:57Z"},
|
||||||
|
"go1.16.13": {Name: "go1.16.13", SHA: "378766af9ed0f2e28d67c2b50e73db7573656669", Timestamp: "2022-01-06T19:06:36Z"},
|
||||||
|
"go1.16.14": {Name: "go1.16.14", SHA: "0a6cf8706fdd0fe1bd26e4d1ecbcd41650bf5e6c", Timestamp: "2022-02-09T16:29:28Z"},
|
||||||
|
"go1.16.15": {Name: "go1.16.15", SHA: "7de0c90a1771146bcba5663fb257c52acffe6161", Timestamp: "2022-03-03T16:55:37Z"},
|
||||||
|
"go1.16.2": {Name: "go1.16.2", SHA: "3979fb9af9ccfc0b7ccb613dcf256b18c2c295f0", Timestamp: "2021-03-11T17:08:05Z"},
|
||||||
|
"go1.16.3": {Name: "go1.16.3", SHA: "9baddd3f21230c55f0ad2a10f5f20579dcf0a0bb", Timestamp: "2021-04-01T17:26:20Z"},
|
||||||
|
"go1.16.4": {Name: "go1.16.4", SHA: "04cd717a269d94d3b3459a3aaf43bc71e3112b7a", Timestamp: "2021-05-06T15:00:00Z"},
|
||||||
|
"go1.16.5": {Name: "go1.16.5", SHA: "7677616a263e8ded606cc8297cb67ddc667a876e", Timestamp: "2021-06-03T17:14:44Z"},
|
||||||
|
"go1.16.6": {Name: "go1.16.6", SHA: "bc51e930274a5d5835ac8797978afc0864c9e30c", Timestamp: "2021-07-12T19:45:05Z"},
|
||||||
|
"go1.16.7": {Name: "go1.16.7", SHA: "fa6aa872225f8d33a90d936e7a81b64d2cea68e1", Timestamp: "2021-08-04T20:44:12Z"},
|
||||||
|
"go1.16.8": {Name: "go1.16.8", SHA: "170a72e58bd128b421f4b3974fe2a37fd035efdf", Timestamp: "2021-09-09T15:27:16Z"},
|
||||||
|
"go1.16.9": {Name: "go1.16.9", SHA: "c580180744e60d6c84fc0b59d634fcff01290780", Timestamp: "2021-10-07T19:49:45Z"},
|
||||||
|
"go1.16beta1": {Name: "go1.16beta1", SHA: "2ff33f5e443165e55a080f3a649e4c070c4096d1", Timestamp: "2020-12-17T16:03:19Z"},
|
||||||
|
"go1.16rc1": {Name: "go1.16rc1", SHA: "3e06467282c6d5678a6273747658c04314e013ef", Timestamp: "2021-01-27T22:19:13Z"},
|
||||||
|
"go1.17": {Name: "go1.17", SHA: "ec5170397c724a8ae440b2bc529f857c86f0e6b1", Timestamp: "2021-08-16T16:23:06Z"},
|
||||||
|
"go1.17.1": {Name: "go1.17.1", SHA: "21a4e67ad58e3c4a7c5254f60cda5be5c3c450ff", Timestamp: "2021-09-09T15:27:21Z"},
|
||||||
|
"go1.17.10": {Name: "go1.17.10", SHA: "085c61ae517110168841be0afeb8f883d66fe95a", Timestamp: "2022-05-10T16:14:36Z"},
|
||||||
|
"go1.17.11": {Name: "go1.17.11", SHA: "26cdea3acca29db94541236f0037a20aa22ce2d7", Timestamp: "2022-06-01T15:18:41Z"},
|
||||||
|
"go1.17.12": {Name: "go1.17.12", SHA: "1ed3c127daceaffb9aadc806ba60f0b51b47421b", Timestamp: "2022-07-12T20:15:34Z"},
|
||||||
|
"go1.17.13": {Name: "go1.17.13", SHA: "15da892a4950a4caac987ee72c632436329f62d5", Timestamp: "2022-08-01T15:12:52Z"},
|
||||||
|
"go1.17.2": {Name: "go1.17.2", SHA: "2ac3bdf378ae408ad8c993084c1c6f7d05b7dff8", Timestamp: "2021-10-07T18:11:41Z"},
|
||||||
|
"go1.17.3": {Name: "go1.17.3", SHA: "f58c78a5771570667b26e8c74faa017bd4c2c448", Timestamp: "2021-11-04T13:55:24Z"},
|
||||||
|
"go1.17.4": {Name: "go1.17.4", SHA: "0f2d0d0694c8680909252ca45dbffbcaff8e430a", Timestamp: "2021-12-02T20:02:34Z"},
|
||||||
|
"go1.17.5": {Name: "go1.17.5", SHA: "de690c2ff8e323c7ce9e274f986dc6f824b35405", Timestamp: "2021-12-09T13:44:55Z"},
|
||||||
|
"go1.17.6": {Name: "go1.17.6", SHA: "9de1ac6ac2cad3871760d0aa288f5ca713afd0a6", Timestamp: "2022-01-06T19:06:43Z"},
|
||||||
|
"go1.17.7": {Name: "go1.17.7", SHA: "6a70ee2873b2367e2a0d6e7d7e167c072b99daf0", Timestamp: "2022-02-09T18:09:24Z"},
|
||||||
|
"go1.17.8": {Name: "go1.17.8", SHA: "7dd10d4ce20e64d96a10cb67794851a58d96a2aa", Timestamp: "2022-03-03T16:55:45Z"},
|
||||||
|
"go1.17.9": {Name: "go1.17.9", SHA: "346b18ee9d15410ab08dd583787c64dbed0666d2", Timestamp: "2022-04-12T15:40:31Z"},
|
||||||
|
"go1.17beta1": {Name: "go1.17beta1", SHA: "dc00dc6c6bf3b5554e37f60799aec092276ff807", Timestamp: "2021-06-10T12:41:37Z"},
|
||||||
|
"go1.17rc1": {Name: "go1.17rc1", SHA: "ddfd72f7d10a40a87513a320dae8c52b6dfdb778", Timestamp: "2021-07-13T17:12:38Z"},
|
||||||
|
"go1.17rc2": {Name: "go1.17rc2", SHA: "72ab3ff68b1ec894fe5599ec82b8849f3baa9d94", Timestamp: "2021-08-02T17:57:22Z"},
|
||||||
|
"go1.18": {Name: "go1.18", SHA: "4aa1efed4853ea067d665a952eee77c52faac774", Timestamp: "2022-03-15T14:06:18Z"},
|
||||||
|
"go1.18.1": {Name: "go1.18.1", SHA: "0b0d2fe66d2348fa694a925595807859bf08a391", Timestamp: "2022-04-12T15:40:19Z"},
|
||||||
|
"go1.18.10": {Name: "go1.18.10", SHA: "581603cb7d02019bbf4ff508014038f3120a3dcb", Timestamp: "2023-01-10T18:17:59Z"},
|
||||||
|
"go1.18.2": {Name: "go1.18.2", SHA: "8ed0e51b5e5cc50985444f39dc56c55e4fa3bcf9", Timestamp: "2022-05-10T16:47:15Z"},
|
||||||
|
"go1.18.3": {Name: "go1.18.3", SHA: "4068be56ce7721a3d75606ea986d11e9ca27077a", Timestamp: "2022-06-01T16:38:24Z"},
|
||||||
|
"go1.18.4": {Name: "go1.18.4", SHA: "88a06f40dfcdc4d37346be169f2b1b9070f38bb3", Timestamp: "2022-07-12T19:56:08Z"},
|
||||||
|
"go1.18.5": {Name: "go1.18.5", SHA: "be59153dd8e67d83428e18a44dd29df3059c21fe", Timestamp: "2022-08-01T15:12:43Z"},
|
||||||
|
"go1.18.6": {Name: "go1.18.6", SHA: "170d78d9baa82d1b64682c5d1f15e5f386f18f3e", Timestamp: "2022-09-06T16:17:30Z"},
|
||||||
|
"go1.18.7": {Name: "go1.18.7", SHA: "947091d31ccda14b0a362adff37b6e037f0f59f3", Timestamp: "2022-10-04T17:43:09Z"},
|
||||||
|
"go1.18.8": {Name: "go1.18.8", SHA: "156bf3dd36a9264f721dc98749c8899c559cca43", Timestamp: "2022-11-01T16:45:18Z"},
|
||||||
|
"go1.18.9": {Name: "go1.18.9", SHA: "0d8a92bdfd3d6d1b24f47e05f9be46645aec94f0", Timestamp: "2022-12-06T19:30:49Z"},
|
||||||
|
"go1.18beta1": {Name: "go1.18beta1", SHA: "becaeea1199b875bc24800fa88f2f4fea119bf78", Timestamp: "2021-12-14T17:43:51Z"},
|
||||||
|
"go1.18beta2": {Name: "go1.18beta2", SHA: "41f485b9a7d8fd647c415be1d11b612063dff21c", Timestamp: "2022-01-31T13:43:52Z"},
|
||||||
|
"go1.18rc1": {Name: "go1.18rc1", SHA: "cb5a598d7f2ebd276686403d141a97c026d33458", Timestamp: "2022-02-16T22:23:24Z"},
|
||||||
|
"go1.19": {Name: "go1.19", SHA: "43456202a1e55da55666fac9d56ace7654a65b64", Timestamp: "2022-08-02T16:54:47Z"},
|
||||||
|
"go1.19.1": {Name: "go1.19.1", SHA: "4a4127bccc826ebb6079af3252bc6bfeaec187c4", Timestamp: "2022-09-06T16:17:26Z"},
|
||||||
|
"go1.19.10": {Name: "go1.19.10", SHA: "7fe60b5df764f5a16a2c40e4412b5ed60f709192", Timestamp: "2023-06-06T17:46:04Z"},
|
||||||
|
"go1.19.11": {Name: "go1.19.11", SHA: "e58941fc25771784319ebd0178e566ecf7d3d8c1", Timestamp: "2023-07-11T16:38:32Z"},
|
||||||
|
"go1.19.12": {Name: "go1.19.12", SHA: "0ae54ddd37302bdd2a8c775135bf5f076a18eeb3", Timestamp: "2023-08-01T20:11:51Z"},
|
||||||
|
"go1.19.13": {Name: "go1.19.13", SHA: "619b8fd7d2c94af12933f409e962b99aa9263555", Timestamp: "2023-09-06T15:37:56Z"},
|
||||||
|
"go1.19.2": {Name: "go1.19.2", SHA: "895664482c0ebe5cec4a6935615a1e9610bbf1e3", Timestamp: "2022-10-04T17:43:19Z"},
|
||||||
|
"go1.19.3": {Name: "go1.19.3", SHA: "5d5ed57b134b7a02259ff070864f753c9e601a18", Timestamp: "2022-11-01T16:45:23Z"},
|
||||||
|
"go1.19.4": {Name: "go1.19.4", SHA: "dc04f3ba1f25313bc9c97e728620206c235db9ee", Timestamp: "2022-12-06T19:30:53Z"},
|
||||||
|
"go1.19.5": {Name: "go1.19.5", SHA: "1e9ff255a130200fcc4ec5e911d28181fce947d5", Timestamp: "2023-01-10T18:15:26Z"},
|
||||||
|
"go1.19.6": {Name: "go1.19.6", SHA: "8656c03fee94ce9cdc4da120b831c2fb9fd68d9d", Timestamp: "2023-02-14T18:09:51Z"},
|
||||||
|
"go1.19.7": {Name: "go1.19.7", SHA: "7bd22aafe41be40e2174335a3dc55431ca9548ec", Timestamp: "2023-03-07T16:49:31Z"},
|
||||||
|
"go1.19.8": {Name: "go1.19.8", SHA: "ca305e101d89969b5cc6a812b1f12038b769aaa2", Timestamp: "2023-04-04T17:30:16Z"},
|
||||||
|
"go1.19.9": {Name: "go1.19.9", SHA: "484330d038d060c6e4db3dc8e6ea2b811b2a44d8", Timestamp: "2023-05-02T17:21:05Z"},
|
||||||
|
"go1.19beta1": {Name: "go1.19beta1", SHA: "2cfbef438049fd4c3f73d1562773ad1f93900897", Timestamp: "2022-06-09T19:31:37Z"},
|
||||||
|
"go1.19rc1": {Name: "go1.19rc1", SHA: "bac4eb53d64ee402af1d52ac18fb9f0ea76c74e2", Timestamp: "2022-07-06T21:33:10Z"},
|
||||||
|
"go1.19rc2": {Name: "go1.19rc2", SHA: "ad672e7ce101cc52e38bae3d7484e4660a20d575", Timestamp: "2022-07-12T22:09:01Z"},
|
||||||
|
"go1.1rc2": {Name: "go1.1rc2", SHA: "1c5438aae896edcd1e9f9618f4776517f08053b3", Timestamp: "2013-05-07T00:33:44Z"},
|
||||||
|
"go1.1rc3": {Name: "go1.1rc3", SHA: "46a6097aa7943a490e9bd2e04274845d0e5e200f", Timestamp: "2013-05-08T23:04:56Z"},
|
||||||
|
"go1.2": {Name: "go1.2", SHA: "402d3590b54e4a0df9fb51ed14b2999e85ce0b76", Timestamp: "2013-11-28T21:32:31Z"},
|
||||||
|
"go1.2.1": {Name: "go1.2.1", SHA: "9c9802fad57c1bcb72ea98c5c55ea2652efc5772", Timestamp: "2014-03-03T00:53:08Z"},
|
||||||
|
"go1.2.2": {Name: "go1.2.2", SHA: "43d00b0942c1c6f43993ac71e1eea48e62e22b8d", Timestamp: "2014-05-05T17:43:37Z"},
|
||||||
|
"go1.20": {Name: "go1.20", SHA: "de4748c47c67392a57f250714509f590f68ad395", Timestamp: "2023-02-01T19:03:46Z"},
|
||||||
|
"go1.20.1": {Name: "go1.20.1", SHA: "202a1a57064127c3f19d96df57b9f9586145e21c", Timestamp: "2023-02-14T18:12:19Z"},
|
||||||
|
"go1.20.10": {Name: "go1.20.10", SHA: "8042fd87f37a725e34407994c9a11aaf95f5af45", Timestamp: "2023-10-10T16:26:21Z"},
|
||||||
|
"go1.20.11": {Name: "go1.20.11", SHA: "1d0d4b149ce71083ec474d0491851ab2d2dc695e", Timestamp: "2023-11-07T17:55:05Z"},
|
||||||
|
"go1.20.2": {Name: "go1.20.2", SHA: "aee9a19c559da6fd258a8609556d89f6fad2a6d8", Timestamp: "2023-03-07T16:47:18Z"},
|
||||||
|
"go1.20.3": {Name: "go1.20.3", SHA: "7c47a6b15782b13ecb76fd3c6c18e5f1edc34733", Timestamp: "2023-04-04T17:30:09Z"},
|
||||||
|
"go1.20.4": {Name: "go1.20.4", SHA: "324c3ace2d2e4e30949baa23b4c9aac8a4123317", Timestamp: "2023-05-02T17:21:02Z"},
|
||||||
|
"go1.20.5": {Name: "go1.20.5", SHA: "e827d41c0a2ea392c117a790cdfed0022e419424", Timestamp: "2023-06-06T17:39:34Z"},
|
||||||
|
"go1.20.6": {Name: "go1.20.6", SHA: "2c358ffe9762ba08c8db0196942395f97775e31b", Timestamp: "2023-07-11T15:58:20Z"},
|
||||||
|
"go1.20.7": {Name: "go1.20.7", SHA: "adb775e309dea43157e931835e920ac9e7769abe", Timestamp: "2023-08-01T19:34:15Z"},
|
||||||
|
"go1.20.8": {Name: "go1.20.8", SHA: "d5b851804329aa547dafa278a0c35dd62298d651", Timestamp: "2023-09-06T15:31:47Z"},
|
||||||
|
"go1.20.9": {Name: "go1.20.9", SHA: "68f9a6e2addc828246992e66e79c6a51a32d1d71", Timestamp: "2023-10-05T19:28:06Z"},
|
||||||
|
"go1.20rc1": {Name: "go1.20rc1", SHA: "9f0234214473dfb785a5ad84a8fc62a6a395cbc3", Timestamp: "2022-12-07T22:00:46Z"},
|
||||||
|
"go1.20rc2": {Name: "go1.20rc2", SHA: "32593a91927dbb891e00a5a94abb04105f6a8aa8", Timestamp: "2023-01-04T16:02:35Z"},
|
||||||
|
"go1.20rc3": {Name: "go1.20rc3", SHA: "b3160e8bcedb25c5266e047ada01b6f462521401", Timestamp: "2023-01-12T17:16:08Z"},
|
||||||
|
"go1.21.0": {Name: "go1.21.0", SHA: "c19c4c566c63818dfd059b352e52c4710eecf14d", Timestamp: "2023-08-08T15:00:52Z"},
|
||||||
|
"go1.21.1": {Name: "go1.21.1", SHA: "2c1e5b05fe39fc5e6c730dd60e82946b8e67c6ba", Timestamp: "2023-09-06T15:31:51Z"},
|
||||||
|
"go1.21.2": {Name: "go1.21.2", SHA: "26b5783b72376acd0386f78295e678b9a6bff30e", Timestamp: "2023-10-05T19:06:58Z"},
|
||||||
|
"go1.21.3": {Name: "go1.21.3", SHA: "883f062fc0a097bf561030ad453fd3e300896975", Timestamp: "2023-10-10T16:31:03Z"},
|
||||||
|
"go1.21.4": {Name: "go1.21.4", SHA: "ed817f1c4055a559a94afffecbb91c78e4f39942", Timestamp: "2023-11-07T17:38:04Z"},
|
||||||
|
"go1.21rc1": {Name: "go1.21rc1", SHA: "1c1c82432a78b06c8010c7257df58ff11cc05b61", Timestamp: "2023-06-16T14:21:46Z"},
|
||||||
|
"go1.21rc2": {Name: "go1.21rc2", SHA: "d8117459c513e048eb72f11988d5416110dff359", Timestamp: "2023-06-21T15:40:05Z"},
|
||||||
|
"go1.21rc3": {Name: "go1.21rc3", SHA: "4aeac326b5cb41a24d6e48c01008abf2f0fda7ff", Timestamp: "2023-07-14T15:07:26Z"},
|
||||||
|
"go1.21rc4": {Name: "go1.21rc4", SHA: "041dd5ce051caf72d64b6d5f2f975515b3676a71", Timestamp: "2023-08-02T13:51:49Z"},
|
||||||
|
"go1.2rc2": {Name: "go1.2rc2", SHA: "309e16554aab1686c5bb744cababfbaa2d83db4d", Timestamp: "2013-10-18T04:53:33Z"},
|
||||||
|
"go1.2rc3": {Name: "go1.2rc3", SHA: "2eb51b1ba8cbf593124ab95e2ea9efb5d3ddf21e", Timestamp: "2013-11-01T01:44:30Z"},
|
||||||
|
"go1.2rc4": {Name: "go1.2rc4", SHA: "a5940dddba6e7995c6f7e4b4d11df17609c247be", Timestamp: "2013-11-13T04:29:48Z"},
|
||||||
|
"go1.2rc5": {Name: "go1.2rc5", SHA: "4abdb873be5c4bbd1e0edec56f992b201d8e0e68", Timestamp: "2013-11-18T01:44:03Z"},
|
||||||
|
"go1.3": {Name: "go1.3", SHA: "1cdd48c8a276cef9e3e20b7350d13556b6c96a71", Timestamp: "2014-06-19T00:20:01Z"},
|
||||||
|
"go1.3.1": {Name: "go1.3.1", SHA: "1657de2d6dbb020e15908668f209f3be7dcef151", Timestamp: "2014-08-13T03:18:02Z"},
|
||||||
|
"go1.3.2": {Name: "go1.3.2", SHA: "f3c81ed821268e2f2e2945b0816f495809bbdf21", Timestamp: "2014-09-25T22:32:20Z"},
|
||||||
|
"go1.3.3": {Name: "go1.3.3", SHA: "3dbc53ae6ad4e3b93f31d35d98b38f6dda25f4ee", Timestamp: "2014-10-01T01:20:15Z"},
|
||||||
|
"go1.3beta1": {Name: "go1.3beta1", SHA: "7ff8e90eb7ceb2016aa9fc736febd8a5902ec65e", Timestamp: "2014-04-22T00:00:27Z"},
|
||||||
|
"go1.3beta2": {Name: "go1.3beta2", SHA: "c00043b5d8bd53130bddb5ef1e88643dccc4586f", Timestamp: "2014-05-21T00:46:08Z"},
|
||||||
|
"go1.3rc1": {Name: "go1.3rc1", SHA: "a5565ec7d9c04843bc91c06a0d5a652716ee75a7", Timestamp: "2014-06-02T04:34:50Z"},
|
||||||
|
"go1.3rc2": {Name: "go1.3rc2", SHA: "2a3daa8bdd5bd06808c51cb4f2921655f70d7617", Timestamp: "2014-06-13T03:24:50Z"},
|
||||||
|
"go1.4": {Name: "go1.4", SHA: "c303df658d43b9f3e98e56e646f8e84a83495991", Timestamp: "2014-12-11T00:27:56Z"},
|
||||||
|
"go1.4.1": {Name: "go1.4.1", SHA: "886b02d705ffb1be8b4974ac4c355d480a24e3ec", Timestamp: "2015-01-15T21:04:23Z"},
|
||||||
|
"go1.4.2": {Name: "go1.4.2", SHA: "883bc6ed0ea815293fe6309d66f967ea60630e87", Timestamp: "2015-02-18T04:24:51Z"},
|
||||||
|
"go1.4.3": {Name: "go1.4.3", SHA: "50eb39bb23e8b03e823c38e844f0410d0b5325d2", Timestamp: "2015-09-23T04:20:05Z"},
|
||||||
|
"go1.4beta1": {Name: "go1.4beta1", SHA: "ca230d2d6ffeaef0be2f58fd46ba6ed34a8dbf46", Timestamp: "2014-10-30T01:02:58Z"},
|
||||||
|
"go1.4rc1": {Name: "go1.4rc1", SHA: "30ef146819d031ccd875de806c4edad66366d4bc", Timestamp: "2014-11-17T02:55:59Z"},
|
||||||
|
"go1.4rc2": {Name: "go1.4rc2", SHA: "3d344611770d03a9d2f822216074edd83af67677", Timestamp: "2014-12-02T02:43:43Z"},
|
||||||
|
"go1.5": {Name: "go1.5", SHA: "bb03defe933c89fee44be675d7aa0fbd893ced30", Timestamp: "2015-08-19T05:04:37Z"},
|
||||||
|
"go1.5.1": {Name: "go1.5.1", SHA: "f2e4c8b5fb3660d793b2c545ef207153db0a34b1", Timestamp: "2015-09-09T00:52:53Z"},
|
||||||
|
"go1.5.2": {Name: "go1.5.2", SHA: "40cbf58f960a8f5287d2c3a93b3ca6119df67e85", Timestamp: "2015-12-03T00:44:15Z"},
|
||||||
|
"go1.5.3": {Name: "go1.5.3", SHA: "27d5c0ede5b4411089f4bf52a41dd2f4eed36123", Timestamp: "2016-01-13T19:43:20Z"},
|
||||||
|
"go1.5.4": {Name: "go1.5.4", SHA: "a1ef950a15517bca223d079a6cf65948c3db9694", Timestamp: "2016-04-11T23:39:07Z"},
|
||||||
|
"go1.5beta1": {Name: "go1.5beta1", SHA: "b6ead9f171742cd5b519a22ecc690354b0d1ce27", Timestamp: "2015-07-07T21:53:11Z"},
|
||||||
|
"go1.5beta2": {Name: "go1.5beta2", SHA: "cc8f5441980a8c2f9e6c8ec3222985ed488e76ba", Timestamp: "2015-07-17T03:34:11Z"},
|
||||||
|
"go1.5beta3": {Name: "go1.5beta3", SHA: "d3ffc975f38890abbd8ca3f7833772e6423297e8", Timestamp: "2015-07-29T23:50:20Z"},
|
||||||
|
"go1.5rc1": {Name: "go1.5rc1", SHA: "0d20a61e68ba22fb416fe2aa8b6532026822bad0", Timestamp: "2015-08-06T04:06:12Z"},
|
||||||
|
"go1.6": {Name: "go1.6", SHA: "7bc40ffb05d8813bf9b41a331b45d37216f9e747", Timestamp: "2016-02-17T19:53:47Z"},
|
||||||
|
"go1.6.1": {Name: "go1.6.1", SHA: "f5cf5673590a68c55b2330df9dfcdd6fac75b893", Timestamp: "2016-04-11T23:39:37Z"},
|
||||||
|
"go1.6.2": {Name: "go1.6.2", SHA: "57e459e02b4b01567f92542f92cd9afde209e193", Timestamp: "2016-04-19T23:27:35Z"},
|
||||||
|
"go1.6.3": {Name: "go1.6.3", SHA: "da6b9ec7bf1722fa00196e1eadc10a29156b6b28", Timestamp: "2016-07-18T15:36:26Z"},
|
||||||
|
"go1.6.4": {Name: "go1.6.4", SHA: "aa1e69f3fc21795b6fab531a07008e0744ffe5bf", Timestamp: "2016-12-01T20:56:30Z"},
|
||||||
|
"go1.6beta1": {Name: "go1.6beta1", SHA: "8db371b3d58a1c139f0854738f9962de05ca5d7a", Timestamp: "2015-12-17T22:45:50Z"},
|
||||||
|
"go1.6beta2": {Name: "go1.6beta2", SHA: "66330d8c6c0a23b7eb48688f9954264e48b039da", Timestamp: "2016-01-13T23:40:13Z"},
|
||||||
|
"go1.6rc1": {Name: "go1.6rc1", SHA: "036b8fd40b60830ca1d152f17148e52b96d8aa6c", Timestamp: "2016-01-28T00:06:14Z"},
|
||||||
|
"go1.6rc2": {Name: "go1.6rc2", SHA: "5d343bdfb140970cc37f099064226d104ca6d817", Timestamp: "2016-02-03T23:11:17Z"},
|
||||||
|
"go1.7": {Name: "go1.7", SHA: "0d818588685976407c81c60d2fda289361cbc8ec", Timestamp: "2016-08-15T22:43:38Z"},
|
||||||
|
"go1.7.1": {Name: "go1.7.1", SHA: "f75aafdf56dd90eab75cfeac8cf69358f73ba171", Timestamp: "2016-09-07T19:11:54Z"},
|
||||||
|
"go1.7.2": {Name: "go1.7.2", SHA: "edecc650ec95ac1a96d2312980e18d959f89835e", Timestamp: "2016-10-17T21:08:12Z"},
|
||||||
|
"go1.7.3": {Name: "go1.7.3", SHA: "2f6557233c5a5c311547144c34b4045640ff9f71", Timestamp: "2016-10-19T17:04:39Z"},
|
||||||
|
"go1.7.4": {Name: "go1.7.4", SHA: "6b36535cf382bce845dd2d272276e7ba350b0c6b", Timestamp: "2016-12-01T22:13:49Z"},
|
||||||
|
"go1.7.5": {Name: "go1.7.5", SHA: "753452fac6f6963b5a6e38a239b05362385a3842", Timestamp: "2017-01-26T17:38:29Z"},
|
||||||
|
"go1.7.6": {Name: "go1.7.6", SHA: "2b7a7b710f096b1b7e6f2ab5e9e3ec003ad7cd12", Timestamp: "2017-05-23T18:33:01Z"},
|
||||||
|
"go1.7beta1": {Name: "go1.7beta1", SHA: "3c6b6684ce21c1092ba208a0f1744ad7c930248a", Timestamp: "2016-06-02T00:22:03Z"},
|
||||||
|
"go1.7beta2": {Name: "go1.7beta2", SHA: "fca9fc52c831ab6af56e30f8c48062a99ded2580", Timestamp: "2016-06-16T19:45:33Z"},
|
||||||
|
"go1.7rc1": {Name: "go1.7rc1", SHA: "53da5fd4d431881bb3583c9790db7735a6530a1b", Timestamp: "2016-07-08T03:48:20Z"},
|
||||||
|
"go1.7rc2": {Name: "go1.7rc2", SHA: "0ebf6ce087388cdd501a02ff92f2f8cafc3e1378", Timestamp: "2016-07-18T15:36:41Z"},
|
||||||
|
"go1.7rc3": {Name: "go1.7rc3", SHA: "8707f31c0abc6b607014e843b7cc188b3019daa9", Timestamp: "2016-07-21T21:19:33Z"},
|
||||||
|
"go1.7rc4": {Name: "go1.7rc4", SHA: "c628d83ec5309cd679e16c734456fed1b9a85806", Timestamp: "2016-08-02T02:22:22Z"},
|
||||||
|
"go1.7rc5": {Name: "go1.7rc5", SHA: "09fc3cc5df6b37b62a219bd4cacd8898a2328b76", Timestamp: "2016-08-02T23:34:48Z"},
|
||||||
|
"go1.7rc6": {Name: "go1.7rc6", SHA: "1e933ed7c091bd8e077ffd123234af10a69e3978", Timestamp: "2016-08-08T18:42:30Z"},
|
||||||
|
"go1.8": {Name: "go1.8", SHA: "cd6b6202dd1559b3ac63179b45f1833fcfbe7eca", Timestamp: "2017-02-16T17:12:24Z"},
|
||||||
|
"go1.8.1": {Name: "go1.8.1", SHA: "a4c18f063b6659079ca2848ca217a0587dabc001", Timestamp: "2017-04-07T16:48:41Z"},
|
||||||
|
"go1.8.2": {Name: "go1.8.2", SHA: "59870f9e19384c3155f603f799b61b401fa20cc9", Timestamp: "2017-05-23T18:32:59Z"},
|
||||||
|
"go1.8.3": {Name: "go1.8.3", SHA: "352996a381701cfa0c16e8de29cbde8f3922182f", Timestamp: "2017-05-24T18:14:11Z"},
|
||||||
|
"go1.8.4": {Name: "go1.8.4", SHA: "f5bcb9b8fe9dd8949d4682b74be6ba72e5d554fb", Timestamp: "2017-10-04T18:39:32Z"},
|
||||||
|
"go1.8.5": {Name: "go1.8.5", SHA: "d4ccbd8833aa45819e903abfc4337555f1832d3c", Timestamp: "2017-10-25T18:57:21Z"},
|
||||||
|
"go1.8.5rc4": {Name: "go1.8.5rc4", SHA: "fab5e254b2a03d3153f850774d87a79840740fe9", Timestamp: "2017-10-20T16:43:01Z"},
|
||||||
|
"go1.8.5rc5": {Name: "go1.8.5rc5", SHA: "0ab2c8872d648bc155e41bf5a7ed0cfee133ff70", Timestamp: "2017-10-25T16:24:05Z"},
|
||||||
|
"go1.8.6": {Name: "go1.8.6", SHA: "96c72e94687d1d78770a204f35993cb2cd3c91e4", Timestamp: "2018-01-23T03:33:54Z"},
|
||||||
|
"go1.8.7": {Name: "go1.8.7", SHA: "357c9141369361101345f3048a6b2b3e149299d5", Timestamp: "2018-02-07T15:33:09Z"},
|
||||||
|
"go1.8beta1": {Name: "go1.8beta1", SHA: "41908a54530120b68a79e0fd22b5e709d33cced0", Timestamp: "2016-12-01T02:54:21Z"},
|
||||||
|
"go1.8beta2": {Name: "go1.8beta2", SHA: "9cd3c0662aa63eea8e7fae80f558fda9d646ba98", Timestamp: "2016-12-15T20:06:07Z"},
|
||||||
|
"go1.8rc1": {Name: "go1.8rc1", SHA: "3de6e96e4b8147f5267a2e8218a7c780b09a434f", Timestamp: "2017-01-10T19:35:03Z"},
|
||||||
|
"go1.8rc2": {Name: "go1.8rc2", SHA: "59f181b6fda68ece22882945853ca2df9dbf1c88", Timestamp: "2017-01-19T20:58:37Z"},
|
||||||
|
"go1.8rc3": {Name: "go1.8rc3", SHA: "2a5f65a98ca483aad2dd74dc2636a7baecc59cf2", Timestamp: "2017-01-26T17:42:08Z"},
|
||||||
|
"go1.9": {Name: "go1.9", SHA: "c8aec4095e089ff6ac50d18e97c3f46561f14f48", Timestamp: "2017-08-24T20:52:14Z"},
|
||||||
|
"go1.9.1": {Name: "go1.9.1", SHA: "7f40c1214dd67cf171a347a5230da70bd8e10d32", Timestamp: "2017-10-04T18:39:31Z"},
|
||||||
|
"go1.9.2": {Name: "go1.9.2", SHA: "2ea7d3461bb41d0ae12b56ee52d43314bcdb97f9", Timestamp: "2017-10-25T20:24:05Z"},
|
||||||
|
"go1.9.3": {Name: "go1.9.3", SHA: "a563954b799c6921fc3666b4723d38413f442145", Timestamp: "2018-01-22T21:38:28Z"},
|
||||||
|
"go1.9.4": {Name: "go1.9.4", SHA: "6732fcc06df713fc737cee5c5860bad87599bc6d", Timestamp: "2018-02-07T15:34:31Z"},
|
||||||
|
"go1.9.5": {Name: "go1.9.5", SHA: "f69b0c627f94b7dcaf4ec654df8e0ffa4bf46957", Timestamp: "2018-03-29T06:06:28Z"},
|
||||||
|
"go1.9.6": {Name: "go1.9.6", SHA: "20f58c6075aef1bb7327ab0691ae095f9412ab5b", Timestamp: "2018-04-30T19:04:08Z"},
|
||||||
|
"go1.9.7": {Name: "go1.9.7", SHA: "7df09b4a03f9e53334672674ba7983d5e7128646", Timestamp: "2018-06-06T20:29:29Z"},
|
||||||
|
"go1.9beta1": {Name: "go1.9beta1", SHA: "952ecbe0a27aadd184ca3e2c342beb464d6b1653", Timestamp: "2017-06-14T21:44:01Z"},
|
||||||
|
"go1.9beta2": {Name: "go1.9beta2", SHA: "eab99a8d548f8ba864647ab171a44f0a5376a6b3", Timestamp: "2017-06-26T21:12:22Z"},
|
||||||
|
"go1.9rc1": {Name: "go1.9rc1", SHA: "65c6c88a9442b91d8b2fd0230337b1fda4bb6cdf", Timestamp: "2017-07-24T19:35:04Z"},
|
||||||
|
"go1.9rc2": {Name: "go1.9rc2", SHA: "048c9cfaacb6fe7ac342b0acd8ca8322b6c49508", Timestamp: "2017-08-07T20:29:01Z"},
|
||||||
|
}
|
||||||
139
vendor/github.com/goretk/gore/macho.go
generated
vendored
Normal file
139
vendor/github.com/goretk/gore/macho.go
generated
vendored
Normal file
@ -0,0 +1,139 @@
|
|||||||
|
// This file is part of GoRE.
|
||||||
|
//
|
||||||
|
// Copyright (C) 2019-2021 GoRE Authors
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU Affero General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Affero General Public License
|
||||||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
package gore
|
||||||
|
|
||||||
|
import (
|
||||||
|
"debug/gosym"
|
||||||
|
"debug/macho"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
func openMachO(fp string) (*machoFile, error) {
|
||||||
|
osFile, err := os.Open(fp)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("error when opening the file: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
f, err := macho.NewFile(osFile)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("error when parsing the Mach-O file: %w", err)
|
||||||
|
}
|
||||||
|
return &machoFile{file: f, osFile: osFile}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type machoFile struct {
|
||||||
|
file *macho.File
|
||||||
|
osFile *os.File
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *machoFile) getFile() *os.File {
|
||||||
|
return m.osFile
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *machoFile) Close() error {
|
||||||
|
err := m.file.Close()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return m.osFile.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *machoFile) getPCLNTab() (*gosym.Table, error) {
|
||||||
|
section := m.file.Section("__gopclntab")
|
||||||
|
if section == nil {
|
||||||
|
return nil, ErrNoPCLNTab
|
||||||
|
}
|
||||||
|
data, err := section.Data()
|
||||||
|
if data == nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
pcln := gosym.NewLineTable(data, m.file.Section("__text").Addr)
|
||||||
|
return gosym.NewTable(nil, pcln)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *machoFile) getRData() ([]byte, error) {
|
||||||
|
_, data, err := m.getSectionData("__rodata")
|
||||||
|
return data, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *machoFile) getCodeSection() ([]byte, error) {
|
||||||
|
_, data, err := m.getSectionData("__text")
|
||||||
|
return data, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *machoFile) getSectionDataFromOffset(off uint64) (uint64, []byte, error) {
|
||||||
|
for _, section := range m.file.Sections {
|
||||||
|
if section.Offset == 0 {
|
||||||
|
// Only exist in memory
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if section.Addr <= off && off < (section.Addr+section.Size) {
|
||||||
|
data, err := section.Data()
|
||||||
|
return section.Addr, data, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0, nil, ErrSectionDoesNotExist
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *machoFile) getSectionData(s string) (uint64, []byte, error) {
|
||||||
|
section := m.file.Section(s)
|
||||||
|
if section == nil {
|
||||||
|
return 0, nil, ErrSectionDoesNotExist
|
||||||
|
}
|
||||||
|
data, err := section.Data()
|
||||||
|
return section.Addr, data, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *machoFile) getFileInfo() *FileInfo {
|
||||||
|
fi := &FileInfo{
|
||||||
|
ByteOrder: m.file.ByteOrder,
|
||||||
|
OS: "macOS",
|
||||||
|
}
|
||||||
|
switch m.file.Cpu {
|
||||||
|
case macho.Cpu386:
|
||||||
|
fi.WordSize = intSize32
|
||||||
|
fi.Arch = Arch386
|
||||||
|
case macho.CpuAmd64:
|
||||||
|
fi.WordSize = intSize64
|
||||||
|
fi.Arch = ArchAMD64
|
||||||
|
case macho.CpuArm64:
|
||||||
|
fi.WordSize = intSize64
|
||||||
|
fi.Arch = ArchARM64
|
||||||
|
default:
|
||||||
|
panic("Unsupported architecture")
|
||||||
|
}
|
||||||
|
return fi
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *machoFile) getPCLNTABData() (uint64, []byte, error) {
|
||||||
|
return m.getSectionData("__gopclntab")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *machoFile) moduledataSection() string {
|
||||||
|
return "__noptrdata"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *machoFile) getBuildID() (string, error) {
|
||||||
|
data, err := m.getCodeSection()
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("failed to get code section: %w", err)
|
||||||
|
}
|
||||||
|
return parseBuildIDFromRaw(data)
|
||||||
|
}
|
||||||
53
vendor/github.com/goretk/gore/modinfo.go
generated
vendored
Normal file
53
vendor/github.com/goretk/gore/modinfo.go
generated
vendored
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
// This file is part of GoRE.
|
||||||
|
//
|
||||||
|
// Copyright (C) 2019-2021 GoRE Authors
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU Affero General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Affero General Public License
|
||||||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
package gore
|
||||||
|
|
||||||
|
import (
|
||||||
|
"debug/buildinfo"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"runtime/debug"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
// ErrNoBuildInfo is returned if the file has no build information available.
|
||||||
|
ErrNoBuildInfo = errors.New("no build info available")
|
||||||
|
)
|
||||||
|
|
||||||
|
// BuildInfo that was extracted from the file.
|
||||||
|
type BuildInfo struct {
|
||||||
|
// Compiler version. Can be nil.
|
||||||
|
Compiler *GoVersion
|
||||||
|
// ModInfo holds information about the Go modules in this file.
|
||||||
|
// Can be nil.
|
||||||
|
ModInfo *debug.BuildInfo
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *GoFile) extractBuildInfo() (*BuildInfo, error) {
|
||||||
|
info, err := buildinfo.Read(f.fh.getFile())
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("error when extracting build information: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
result := &BuildInfo{
|
||||||
|
Compiler: ResolveGoVersion(info.GoVersion),
|
||||||
|
ModInfo: info,
|
||||||
|
}
|
||||||
|
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
914
vendor/github.com/goretk/gore/moduledata.go
generated
vendored
Normal file
914
vendor/github.com/goretk/gore/moduledata.go
generated
vendored
Normal file
@ -0,0 +1,914 @@
|
|||||||
|
// This file is part of GoRE.
|
||||||
|
//
|
||||||
|
// Copyright (C) 2019-2022 GoRE Authors
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU Affero General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Affero General Public License
|
||||||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
package gore
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/binary"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"reflect"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Moduledata extracts the file's moduledata.
|
||||||
|
func (f *GoFile) Moduledata() (Moduledata, error) {
|
||||||
|
// We need the Go version to be defined to find the module data.
|
||||||
|
ver, err := f.GetCompilerVersion()
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("could not get the Go version for the moduledata extraction: %w", err)
|
||||||
|
}
|
||||||
|
f.FileInfo.goversion = ver
|
||||||
|
|
||||||
|
md, err := parseModuledata(f.FileInfo, f.fh)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("error when parsing the moduledata: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return md, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Moduledata holds information about the layout of the executable image in memory.
|
||||||
|
type Moduledata interface {
|
||||||
|
// Text returns the text secion.
|
||||||
|
Text() ModuleDataSection
|
||||||
|
// NoPtrData returns the noptrdata section.
|
||||||
|
NoPtrData() ModuleDataSection
|
||||||
|
// Data returns the data section.
|
||||||
|
Data() ModuleDataSection
|
||||||
|
// Bss returns the bss section.
|
||||||
|
Bss() ModuleDataSection
|
||||||
|
// NoPtrBss returns the noptrbss section.
|
||||||
|
NoPtrBss() ModuleDataSection
|
||||||
|
// Types returns the types section.
|
||||||
|
Types() ModuleDataSection
|
||||||
|
// PCLNTab returns the pclntab section.
|
||||||
|
PCLNTab() ModuleDataSection
|
||||||
|
// FuncTab returns the functab section.
|
||||||
|
FuncTab() ModuleDataSection
|
||||||
|
// ITabLinks returns the itablinks section.
|
||||||
|
ITabLinks() ModuleDataSection
|
||||||
|
// TypeLink returns the typelink section.
|
||||||
|
TypeLink() ([]int32, error)
|
||||||
|
// GoFuncValue returns the value of the 'go:func.*' symbol.
|
||||||
|
GoFuncValue() uint64
|
||||||
|
}
|
||||||
|
|
||||||
|
type moduledata struct {
|
||||||
|
TextAddr, TextLen uint64
|
||||||
|
NoPtrDataAddr, NoPtrDataLen uint64
|
||||||
|
DataAddr, DataLen uint64
|
||||||
|
BssAddr, BssLen uint64
|
||||||
|
NoPtrBssAddr, NoPtrBssLen uint64
|
||||||
|
|
||||||
|
TypesAddr, TypesLen uint64
|
||||||
|
TypelinkAddr, TypelinkLen uint64
|
||||||
|
ITabLinkAddr, ITabLinkLen uint64
|
||||||
|
FuncTabAddr, FuncTabLen uint64
|
||||||
|
PCLNTabAddr, PCLNTabLen uint64
|
||||||
|
|
||||||
|
GoFuncVal uint64
|
||||||
|
|
||||||
|
fh fileHandler
|
||||||
|
}
|
||||||
|
|
||||||
|
// Text returns the text secion.
|
||||||
|
func (m moduledata) Text() ModuleDataSection {
|
||||||
|
return ModuleDataSection{
|
||||||
|
Address: m.TextAddr,
|
||||||
|
Length: m.TextLen,
|
||||||
|
fh: m.fh,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NoPtrData returns the noptrdata section.
|
||||||
|
func (m moduledata) NoPtrData() ModuleDataSection {
|
||||||
|
return ModuleDataSection{
|
||||||
|
Address: m.NoPtrDataAddr,
|
||||||
|
Length: m.NoPtrDataLen,
|
||||||
|
fh: m.fh,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Data returns the data section.
|
||||||
|
func (m moduledata) Data() ModuleDataSection {
|
||||||
|
return ModuleDataSection{
|
||||||
|
Address: m.DataAddr,
|
||||||
|
Length: m.DataLen,
|
||||||
|
fh: m.fh,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bss returns the bss section.
|
||||||
|
func (m moduledata) Bss() ModuleDataSection {
|
||||||
|
return ModuleDataSection{
|
||||||
|
Address: m.BssAddr,
|
||||||
|
Length: m.BssLen,
|
||||||
|
fh: m.fh,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NoPtrBss returns the noptrbss section.
|
||||||
|
func (m moduledata) NoPtrBss() ModuleDataSection {
|
||||||
|
return ModuleDataSection{
|
||||||
|
Address: m.NoPtrBssAddr,
|
||||||
|
Length: m.NoPtrBssLen,
|
||||||
|
fh: m.fh,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Types returns the types section.
|
||||||
|
func (m moduledata) Types() ModuleDataSection {
|
||||||
|
return ModuleDataSection{
|
||||||
|
Address: m.TypesAddr,
|
||||||
|
Length: m.TypesLen,
|
||||||
|
fh: m.fh,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// PCLNTab returns the pclntab section.
|
||||||
|
func (m moduledata) PCLNTab() ModuleDataSection {
|
||||||
|
return ModuleDataSection{
|
||||||
|
Address: m.PCLNTabAddr,
|
||||||
|
Length: m.PCLNTabLen,
|
||||||
|
fh: m.fh,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// FuncTab returns the functab section.
|
||||||
|
func (m moduledata) FuncTab() ModuleDataSection {
|
||||||
|
return ModuleDataSection{
|
||||||
|
Address: m.FuncTabAddr,
|
||||||
|
Length: m.FuncTabLen,
|
||||||
|
fh: m.fh,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ITabLinks returns the itablinks section.
|
||||||
|
func (m moduledata) ITabLinks() ModuleDataSection {
|
||||||
|
return ModuleDataSection{
|
||||||
|
Address: m.ITabLinkAddr,
|
||||||
|
Length: m.ITabLinkLen,
|
||||||
|
fh: m.fh,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TypeLink returns the typelink section.
|
||||||
|
func (m moduledata) TypeLink() ([]int32, error) {
|
||||||
|
base, data, err := m.fh.getSectionDataFromOffset(m.TypelinkAddr)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to get the typelink data section: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
r := bytes.NewReader(data[m.TypelinkAddr-base:])
|
||||||
|
a := make([]int32, 0, m.TypelinkLen)
|
||||||
|
bo := m.fh.getFileInfo().ByteOrder
|
||||||
|
for i := uint64(0); i < m.TypelinkLen; i++ {
|
||||||
|
// Type offsets are always int32
|
||||||
|
var off int32
|
||||||
|
err = binary.Read(r, bo, &off)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to read typelink item %d: %w", i, err)
|
||||||
|
}
|
||||||
|
a = append(a, off)
|
||||||
|
}
|
||||||
|
|
||||||
|
return a, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GoFuncValue returns the value of the "go:func.*" symbol.
|
||||||
|
func (m moduledata) GoFuncValue() uint64 {
|
||||||
|
return m.GoFuncVal
|
||||||
|
}
|
||||||
|
|
||||||
|
// ModuleDataSection is a section defined in the Moduledata structure.
|
||||||
|
type ModuleDataSection struct {
|
||||||
|
// Address is the virtual address where the section start.
|
||||||
|
Address uint64
|
||||||
|
// Length is the byte length for the data in this section.
|
||||||
|
Length uint64
|
||||||
|
fh fileHandler
|
||||||
|
}
|
||||||
|
|
||||||
|
// Data returns the data in the section.
|
||||||
|
func (m ModuleDataSection) Data() ([]byte, error) {
|
||||||
|
// If we don't have any data, return an empty slice.
|
||||||
|
if m.Length == 0 {
|
||||||
|
return []byte{}, nil
|
||||||
|
}
|
||||||
|
base, data, err := m.fh.getSectionDataFromOffset(m.Address)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("getting module data section failed: %w", err)
|
||||||
|
}
|
||||||
|
start := m.Address - base
|
||||||
|
if uint64(len(data)) < start+m.Length {
|
||||||
|
return nil, fmt.Errorf("the length of module data section is to big: address 0x%x, base 0x%x, length 0x%x", m.Address, base, m.Length)
|
||||||
|
}
|
||||||
|
buf := make([]byte, m.Length)
|
||||||
|
copy(buf, data[start:start+m.Length])
|
||||||
|
return buf, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func findModuledata(f fileHandler) ([]byte, error) {
|
||||||
|
_, secData, err := f.getSectionData(f.moduledataSection())
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
tabAddr, _, err := f.getPCLNTABData()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Search for moduledata
|
||||||
|
buf := new(bytes.Buffer)
|
||||||
|
err = binary.Write(buf, binary.LittleEndian, &tabAddr)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
off := bytes.Index(secData, buf.Bytes()[:intSize32])
|
||||||
|
if off == -1 {
|
||||||
|
return nil, errors.New("could not find moduledata")
|
||||||
|
}
|
||||||
|
// TODO: Verify that hit is correct.
|
||||||
|
|
||||||
|
return secData[off : off+0x300], nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseModuledata(fileInfo *FileInfo, f fileHandler) (moduledata, error) {
|
||||||
|
data, err := findModuledata(f)
|
||||||
|
if err != nil {
|
||||||
|
return moduledata{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// buf will hold the struct type that represents the data in the file we are processing.
|
||||||
|
var buf interface{}
|
||||||
|
is32bit := fileInfo.WordSize == intSize32
|
||||||
|
|
||||||
|
// Determine what kind of struct we need to extract the module data from the file.
|
||||||
|
|
||||||
|
if GoVersionCompare("go1.20rc1", fileInfo.goversion.Name) <= 0 {
|
||||||
|
if is32bit {
|
||||||
|
buf = &moduledata2032{}
|
||||||
|
} else {
|
||||||
|
buf = &moduledata2064{}
|
||||||
|
}
|
||||||
|
} else if GoVersionCompare("go1.18beta1", fileInfo.goversion.Name) <= 0 {
|
||||||
|
if is32bit {
|
||||||
|
buf = &moduledata1832{}
|
||||||
|
} else {
|
||||||
|
buf = &moduledata1864{}
|
||||||
|
}
|
||||||
|
} else if GoVersionCompare("go1.16beta1", fileInfo.goversion.Name) <= 0 {
|
||||||
|
if is32bit {
|
||||||
|
buf = &moduledata1632{}
|
||||||
|
} else {
|
||||||
|
buf = &moduledata1664{}
|
||||||
|
}
|
||||||
|
} else if GoVersionCompare("go1.8beta1", fileInfo.goversion.Name) <= 0 {
|
||||||
|
if is32bit {
|
||||||
|
buf = &moduledata832{}
|
||||||
|
} else {
|
||||||
|
buf = &moduledata864{}
|
||||||
|
}
|
||||||
|
} else if GoVersionCompare("go1.7beta1", fileInfo.goversion.Name) <= 0 {
|
||||||
|
if is32bit {
|
||||||
|
buf = &moduledata732{}
|
||||||
|
} else {
|
||||||
|
buf = &moduledata764{}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if is32bit {
|
||||||
|
buf = &moduledata532{}
|
||||||
|
} else {
|
||||||
|
buf = &moduledata564{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read the module struct from the file.
|
||||||
|
r := bytes.NewReader(data)
|
||||||
|
err = readStruct(r, fileInfo.ByteOrder, buf)
|
||||||
|
if err != nil {
|
||||||
|
return moduledata{}, fmt.Errorf("error when reading module data from file: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert the read struct to the type we return to the caller.
|
||||||
|
md, err := processModuledata(buf)
|
||||||
|
if err != nil {
|
||||||
|
return md, fmt.Errorf("error when processing module data: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add the file handler.
|
||||||
|
md.fh = f
|
||||||
|
|
||||||
|
return md, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func readUIntTo64(r io.Reader, byteOrder binary.ByteOrder, is32bit bool) (uint64, error) {
|
||||||
|
if is32bit {
|
||||||
|
var addr uint32
|
||||||
|
err := binary.Read(r, byteOrder, &addr)
|
||||||
|
return uint64(addr), err
|
||||||
|
}
|
||||||
|
var addr uint64
|
||||||
|
err := binary.Read(r, byteOrder, &addr)
|
||||||
|
return addr, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// readStruct performs a binary read from the reader to the data object. Data object must
|
||||||
|
// be a pointer to the struct.
|
||||||
|
func readStruct(r io.Reader, byteOrder binary.ByteOrder, data interface{}) error {
|
||||||
|
return binary.Read(r, byteOrder, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
func processModuledata(data interface{}) (moduledata, error) {
|
||||||
|
md := moduledata{}
|
||||||
|
// This will panic if the data passed in is not a pointer to
|
||||||
|
// a struct. But this function should not be called outside
|
||||||
|
// of this file, we can ensure this is always the case.
|
||||||
|
val := reflect.ValueOf(data).Elem()
|
||||||
|
|
||||||
|
extractModFieldValue(&md, "TextAddr", val, "Text")
|
||||||
|
extractModFieldValue(&md, "TextLen", val, "Etext")
|
||||||
|
if md.TextLen > md.TextAddr {
|
||||||
|
md.TextLen = md.TextLen - md.TextAddr
|
||||||
|
}
|
||||||
|
|
||||||
|
extractModFieldValue(&md, "NoPtrDataAddr", val, "Noptrdata")
|
||||||
|
extractModFieldValue(&md, "NoPtrDataLen", val, "Enoptrdata")
|
||||||
|
if md.NoPtrDataLen > md.NoPtrDataAddr {
|
||||||
|
md.NoPtrDataLen = md.NoPtrDataLen - md.NoPtrDataAddr
|
||||||
|
}
|
||||||
|
|
||||||
|
extractModFieldValue(&md, "DataAddr", val, "Data")
|
||||||
|
extractModFieldValue(&md, "DataLen", val, "Edata")
|
||||||
|
if md.DataLen > md.DataAddr {
|
||||||
|
md.DataLen = md.DataLen - md.DataAddr
|
||||||
|
}
|
||||||
|
|
||||||
|
extractModFieldValue(&md, "BssAddr", val, "Bss")
|
||||||
|
extractModFieldValue(&md, "BssLen", val, "Ebss")
|
||||||
|
if md.BssLen > md.BssAddr {
|
||||||
|
md.BssLen = md.BssLen - md.BssAddr
|
||||||
|
}
|
||||||
|
|
||||||
|
extractModFieldValue(&md, "NoPtrBssAddr", val, "Noptrbss")
|
||||||
|
extractModFieldValue(&md, "NoPtrBssLen", val, "Enoptrbss")
|
||||||
|
if md.NoPtrBssLen > md.NoPtrBssAddr {
|
||||||
|
md.NoPtrBssLen = md.NoPtrBssLen - md.NoPtrBssAddr
|
||||||
|
}
|
||||||
|
|
||||||
|
extractModFieldValue(&md, "TypelinkAddr", val, "Typelinks")
|
||||||
|
extractModFieldValue(&md, "TypelinkLen", val, "Typelinkslen")
|
||||||
|
extractModFieldValue(&md, "ITabLinkAddr", val, "Itablinks")
|
||||||
|
extractModFieldValue(&md, "ITabLinkLen", val, "Itablinkslen")
|
||||||
|
extractModFieldValue(&md, "FuncTabAddr", val, "Ftab")
|
||||||
|
extractModFieldValue(&md, "FuncTabLen", val, "Ftablen")
|
||||||
|
extractModFieldValue(&md, "PCLNTabAddr", val, "Pclntable")
|
||||||
|
extractModFieldValue(&md, "PCLNTabLen", val, "Pclntablelen")
|
||||||
|
|
||||||
|
extractModFieldValue(&md, "TypesAddr", val, "Types")
|
||||||
|
extractModFieldValue(&md, "TypesLen", val, "Etypes")
|
||||||
|
if md.TypesLen > md.TypesAddr {
|
||||||
|
md.TypesLen = md.TypesLen - md.TypesAddr
|
||||||
|
}
|
||||||
|
|
||||||
|
extractModFieldValue(&md, "GoFuncVal", val, "GoFunc")
|
||||||
|
|
||||||
|
return md, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func extractModFieldValue(md *moduledata, dst string, val reflect.Value, src string) {
|
||||||
|
field := val.FieldByName(src)
|
||||||
|
// Not all versions of the module struct has all the fields. If we don't have the
|
||||||
|
// field, we skip it.
|
||||||
|
if !field.IsValid() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save 32 to 64 uint casting if needed.
|
||||||
|
var num uint64
|
||||||
|
switch field.Interface().(type) {
|
||||||
|
case uint64:
|
||||||
|
num = field.Uint()
|
||||||
|
case uint32:
|
||||||
|
t := field.Interface().(uint32)
|
||||||
|
num = uint64(t)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the value.
|
||||||
|
mdField := reflect.ValueOf(md).Elem().FieldByName(dst)
|
||||||
|
mdField.SetUint(num)
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Internal module structures from Go's runtime.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Moduledata structure for Go 1.20 and newer
|
||||||
|
|
||||||
|
type moduledata2064 struct {
|
||||||
|
PcHeader uint64
|
||||||
|
Funcnametab, Funcnametablen, Funcnametabcap uint64
|
||||||
|
Cutab, Cutablen, Cutabcap uint64
|
||||||
|
Filetab, Filetablen, Filetabcap uint64
|
||||||
|
Pctab, Pctablen, Pctabcap uint64
|
||||||
|
Pclntable, Pclntablelen, Pclntablecap uint64
|
||||||
|
Ftab, Ftablen, Ftabcap uint64
|
||||||
|
Findfunctab uint64
|
||||||
|
Minpc, Maxpc uint64
|
||||||
|
|
||||||
|
Text, Etext uint64
|
||||||
|
Noptrdata, Enoptrdata uint64
|
||||||
|
Data, Edata uint64
|
||||||
|
Bss, Ebss uint64
|
||||||
|
Noptrbss, Enoptrbss uint64
|
||||||
|
Covctrs, Ecovctrs uint64
|
||||||
|
End, Gcdata, Gcbss uint64
|
||||||
|
Types, Etypes uint64
|
||||||
|
RData uint64
|
||||||
|
GoFunc uint64
|
||||||
|
|
||||||
|
Textsectmap, Textsectmaplen, Textsectmapcap uint64
|
||||||
|
Typelinks, Typelinkslen, Typelinkscap uint64 // offsets from types
|
||||||
|
Itablinks, Itablinkslen, Itablinkscap uint64
|
||||||
|
|
||||||
|
Ptab, Ptablen, Ptabcap uint64
|
||||||
|
|
||||||
|
Pluginpath, Pluginpathlen uint64
|
||||||
|
Pkghashes, Pkghasheslen, Pkghashescap uint64
|
||||||
|
|
||||||
|
Modulename, Modulenamelen uint64
|
||||||
|
Modulehashes, Modulehasheslen, Modulehashescap uint64
|
||||||
|
|
||||||
|
/* These fields we are not planning to use so skipping the parsing of them.
|
||||||
|
|
||||||
|
hasmain uint8 // 1 if module contains the main function, 0 otherwise
|
||||||
|
|
||||||
|
gcdatamask, gcbssmask bitvector
|
||||||
|
|
||||||
|
typemap map[typeOff]*_type // offset to *_rtype in previous module
|
||||||
|
|
||||||
|
bad bool // module failed to load and should be ignored
|
||||||
|
|
||||||
|
next *moduledata
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
type moduledata2032 struct {
|
||||||
|
PcHeader uint32
|
||||||
|
Funcnametab, Funcnametablen, Funcnametabcap uint32
|
||||||
|
Cutab, Cutablen, Cutabcap uint32
|
||||||
|
Filetab, Filetablen, Filetabcap uint32
|
||||||
|
Pctab, Pctablen, Pctabcap uint32
|
||||||
|
Pclntable, Pclntablelen, Pclntablecap uint32
|
||||||
|
Ftab, Ftablen, Ftabcap uint32
|
||||||
|
Findfunctab uint32
|
||||||
|
Minpc, Maxpc uint32
|
||||||
|
|
||||||
|
Text, Etext uint32
|
||||||
|
Noptrdata, Enoptrdata uint32
|
||||||
|
Data, Edata uint32
|
||||||
|
Bss, Ebss uint32
|
||||||
|
Noptrbss, Enoptrbss uint32
|
||||||
|
Covctrs, Ecovctrs uint32
|
||||||
|
End, Gcdata, Gcbss uint32
|
||||||
|
Types, Etypes uint32
|
||||||
|
RData uint32
|
||||||
|
GoFunc uint32
|
||||||
|
|
||||||
|
Textsectmap, Textsectmaplen, Textsectmapcap uint32
|
||||||
|
Typelinks, Typelinkslen, Typelinkscap uint32 // offsets from types
|
||||||
|
Itablinks, Itablinkslen, Itablinkscap uint32
|
||||||
|
|
||||||
|
Ptab, Ptablen, Ptabcap uint32
|
||||||
|
|
||||||
|
Pluginpath, Pluginpathlen uint32
|
||||||
|
Pkghashes, Pkghasheslen, Pkghashescap uint32
|
||||||
|
|
||||||
|
Modulename, Modulenamelen uint32
|
||||||
|
Modulehashes, Modulehasheslen, Modulehashescap uint32
|
||||||
|
|
||||||
|
/* These fields we are not planning to use so skipping the parsing of them.
|
||||||
|
|
||||||
|
hasmain uint8 // 1 if module contains the main function, 0 otherwise
|
||||||
|
|
||||||
|
gcdatamask, gcbssmask bitvector
|
||||||
|
|
||||||
|
typemap map[typeOff]*_type // offset to *_rtype in previous module
|
||||||
|
|
||||||
|
bad bool // module failed to load and should be ignored
|
||||||
|
|
||||||
|
next *moduledata
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
// Moduledata structure for Go 1.18 and Go 1.19
|
||||||
|
|
||||||
|
type moduledata1864 struct {
|
||||||
|
PcHeader uint64
|
||||||
|
Funcnametab, Funcnametablen, Funcnametabcap uint64
|
||||||
|
Cutab, Cutablen, Cutabcap uint64
|
||||||
|
Filetab, Filetablen, Filetabcap uint64
|
||||||
|
Pctab, Pctablen, Pctabcap uint64
|
||||||
|
Pclntable, Pclntablelen, Pclntablecap uint64
|
||||||
|
Ftab, Ftablen, Ftabcap uint64
|
||||||
|
Findfunctab uint64
|
||||||
|
Minpc, Maxpc uint64
|
||||||
|
|
||||||
|
Text, Etext uint64
|
||||||
|
Noptrdata, Enoptrdata uint64
|
||||||
|
Data, Edata uint64
|
||||||
|
Bss, Ebss uint64
|
||||||
|
Noptrbss, Enoptrbss uint64
|
||||||
|
End, Gcdata, Gcbss uint64
|
||||||
|
Types, Etypes uint64
|
||||||
|
RData uint64
|
||||||
|
GoFunc uint64
|
||||||
|
|
||||||
|
Textsectmap, Textsectmaplen, Textsectmapcap uint64
|
||||||
|
Typelinks, Typelinkslen, Typelinkscap uint64 // offsets from types
|
||||||
|
Itablinks, Itablinkslen, Itablinkscap uint64
|
||||||
|
|
||||||
|
Ptab, Ptablen, Ptabcap uint64
|
||||||
|
|
||||||
|
Pluginpath, Pluginpathlen uint64
|
||||||
|
Pkghashes, Pkghasheslen, Pkghashescap uint64
|
||||||
|
|
||||||
|
Modulename, Modulenamelen uint64
|
||||||
|
Modulehashes, Modulehasheslen, Modulehashescap uint64
|
||||||
|
|
||||||
|
/* These fields we are not planning to use so skipping the parsing of them.
|
||||||
|
|
||||||
|
hasmain uint8 // 1 if module contains the main function, 0 otherwise
|
||||||
|
|
||||||
|
gcdatamask, gcbssmask bitvector
|
||||||
|
|
||||||
|
typemap map[typeOff]*_type // offset to *_rtype in previous module
|
||||||
|
|
||||||
|
bad bool // module failed to load and should be ignored
|
||||||
|
|
||||||
|
next *moduledata
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
type moduledata1832 struct {
|
||||||
|
PcHeader uint32
|
||||||
|
Funcnametab, Funcnametablen, Funcnametabcap uint32
|
||||||
|
Cutab, Cutablen, Cutabcap uint32
|
||||||
|
Filetab, Filetablen, Filetabcap uint32
|
||||||
|
Pctab, Pctablen, Pctabcap uint32
|
||||||
|
Pclntable, Pclntablelen, Pclntablecap uint32
|
||||||
|
Ftab, Ftablen, Ftabcap uint32
|
||||||
|
Findfunctab uint32
|
||||||
|
Minpc, Maxpc uint32
|
||||||
|
|
||||||
|
Text, Etext uint32
|
||||||
|
Noptrdata, Enoptrdata uint32
|
||||||
|
Data, Edata uint32
|
||||||
|
Bss, Ebss uint32
|
||||||
|
Noptrbss, Enoptrbss uint32
|
||||||
|
End, Gcdata, Gcbss uint32
|
||||||
|
Types, Etypes uint32
|
||||||
|
RData uint32
|
||||||
|
GoFunc uint32
|
||||||
|
|
||||||
|
Textsectmap, Textsectmaplen, Textsectmapcap uint32
|
||||||
|
Typelinks, Typelinkslen, Typelinkscap uint32 // offsets from types
|
||||||
|
Itablinks, Itablinkslen, Itablinkscap uint32
|
||||||
|
|
||||||
|
Ptab, Ptablen, Ptabcap uint32
|
||||||
|
|
||||||
|
Pluginpath, Pluginpathlen uint32
|
||||||
|
Pkghashes, Pkghasheslen, Pkghashescap uint32
|
||||||
|
|
||||||
|
Modulename, Modulenamelen uint32
|
||||||
|
Modulehashes, Modulehasheslen, Modulehashescap uint32
|
||||||
|
|
||||||
|
/* These fields we are not planning to use so skipping the parsing of them.
|
||||||
|
|
||||||
|
hasmain uint8 // 1 if module contains the main function, 0 otherwise
|
||||||
|
|
||||||
|
gcdatamask, gcbssmask bitvector
|
||||||
|
|
||||||
|
typemap map[typeOff]*_type // offset to *_rtype in previous module
|
||||||
|
|
||||||
|
bad bool // module failed to load and should be ignored
|
||||||
|
|
||||||
|
next *moduledata
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
// Moduledata structure for Go 1.16 to 1.17
|
||||||
|
|
||||||
|
type moduledata1664 struct {
|
||||||
|
PcHeader uint64
|
||||||
|
Funcnametab, Funcnametablen, Funcnametabcap uint64
|
||||||
|
Cutab, Cutablen, Cutabcap uint64
|
||||||
|
Filetab, Filetablen, Filetabcap uint64
|
||||||
|
Pctab, Pctablen, Pctabcap uint64
|
||||||
|
Pclntable, Pclntablelen, Pclntablecap uint64
|
||||||
|
Ftab, Ftablen, Ftabcap uint64
|
||||||
|
Findfunctab uint64
|
||||||
|
Minpc, Maxpc uint64
|
||||||
|
|
||||||
|
Text, Etext uint64
|
||||||
|
Noptrdata, Enoptrdata uint64
|
||||||
|
Data, Edata uint64
|
||||||
|
Bss, Ebss uint64
|
||||||
|
Noptrbss, Enoptrbss uint64
|
||||||
|
End, Gcdata, Gcbss uint64
|
||||||
|
Types, Etypes uint64
|
||||||
|
|
||||||
|
Textsectmap, Textsectmaplen, Textsectmapcap uint64
|
||||||
|
Typelinks, Typelinkslen, Typelinkscap uint64 // offsets from types
|
||||||
|
Itablinks, Itablinkslen, Itablinkscap uint64
|
||||||
|
|
||||||
|
Ptab, Ptablen, Ptabcap uint64
|
||||||
|
|
||||||
|
Pluginpath, Pluginpathlen uint64
|
||||||
|
Pkghashes, Pkghasheslen, Pkghashescap uint64
|
||||||
|
|
||||||
|
Modulename, Modulenamelen uint64
|
||||||
|
Modulehashes, Modulehasheslen, Modulehashescap uint64
|
||||||
|
|
||||||
|
/* These fields we are not planning to use so skipping the parsing of them.
|
||||||
|
|
||||||
|
hasmain uint8 // 1 if module contains the main function, 0 otherwise
|
||||||
|
|
||||||
|
gcdatamask, gcbssmask bitvector
|
||||||
|
|
||||||
|
typemap map[typeOff]*_type // offset to *_rtype in previous module
|
||||||
|
|
||||||
|
bad bool // module failed to load and should be ignored
|
||||||
|
|
||||||
|
next *moduledata
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
type moduledata1632 struct {
|
||||||
|
PcHeader uint32
|
||||||
|
Funcnametab, Funcnametablen, Funcnametabcap uint32
|
||||||
|
Cutab, Cutablen, Cutabcap uint32
|
||||||
|
Filetab, Filetablen, Filetabcap uint32
|
||||||
|
Pctab, Pctablen, Pctabcap uint32
|
||||||
|
Pclntable, Pclntablelen, Pclntablecap uint32
|
||||||
|
Ftab, Ftablen, Ftabcap uint32
|
||||||
|
Findfunctab uint32
|
||||||
|
Minpc, Maxpc uint32
|
||||||
|
|
||||||
|
Text, Etext uint32
|
||||||
|
Noptrdata, Enoptrdata uint32
|
||||||
|
Data, Edata uint32
|
||||||
|
Bss, Ebss uint32
|
||||||
|
Noptrbss, Enoptrbss uint32
|
||||||
|
End, Gcdata, Gcbss uint32
|
||||||
|
Types, Etypes uint32
|
||||||
|
|
||||||
|
Textsectmap, Textsectmaplen, Textsectmapcap uint32
|
||||||
|
Typelinks, Typelinkslen, Typelinkscap uint32 // offsets from types
|
||||||
|
Itablinks, Itablinkslen, Itablinkscap uint32
|
||||||
|
|
||||||
|
Ptab, Ptablen, Ptabcap uint32
|
||||||
|
|
||||||
|
Pluginpath, Pluginpathlen uint32
|
||||||
|
Pkghashes, Pkghasheslen, Pkghashescap uint32
|
||||||
|
|
||||||
|
Modulename, Modulenamelen uint32
|
||||||
|
Modulehashes, Modulehasheslen, Modulehashescap uint32
|
||||||
|
|
||||||
|
/* These fields we are not planning to use so skipping the parsing of them.
|
||||||
|
|
||||||
|
hasmain uint8 // 1 if module contains the main function, 0 otherwise
|
||||||
|
|
||||||
|
gcdatamask, gcbssmask bitvector
|
||||||
|
|
||||||
|
typemap map[typeOff]*_type // offset to *_rtype in previous module
|
||||||
|
|
||||||
|
bad bool // module failed to load and should be ignored
|
||||||
|
|
||||||
|
next *moduledata
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
// Moduledata structure for Go 1.8 to 1.15
|
||||||
|
|
||||||
|
type moduledata864 struct {
|
||||||
|
Pclntable, Pclntablelen, Pclntablecap uint64
|
||||||
|
Ftab, Ftablen, Ftabcap uint64
|
||||||
|
Filetab, Filetablen, Filetabcap uint64
|
||||||
|
Findfunctab uint64
|
||||||
|
Minpc, Maxpc uint64
|
||||||
|
|
||||||
|
Text, Etext uint64
|
||||||
|
Noptrdata, Enoptrdata uint64
|
||||||
|
Data, Edata uint64
|
||||||
|
Bss, Ebss uint64
|
||||||
|
Noptrbss, Enoptrbss uint64
|
||||||
|
End, Gcdata, Gcbss uint64
|
||||||
|
Types, Etypes uint64
|
||||||
|
|
||||||
|
Textsectmap, Textsectmaplen, Textsectmapcap uint64
|
||||||
|
Typelinks, Typelinkslen, Typelinkscap uint64 // offsets from types
|
||||||
|
Itablinks, Itablinkslen, Itablinkscap uint64
|
||||||
|
|
||||||
|
Ptab, Ptablen, Ptabcap uint64
|
||||||
|
|
||||||
|
Pluginpath, Pluginpathlen uint64
|
||||||
|
Pkghashes, Pkghasheslen, Pkghashescap uint64
|
||||||
|
|
||||||
|
Modulename, Modulenamelen uint64
|
||||||
|
Modulehashes, Modulehasheslen, Modulehashescap uint64
|
||||||
|
|
||||||
|
/* These fields we are not planning to use so skipping the parsing of them.
|
||||||
|
|
||||||
|
hasmain uint8 // 1 if module contains the main function, 0 otherwise
|
||||||
|
|
||||||
|
gcdatamask, gcbssmask bitvector
|
||||||
|
|
||||||
|
typemap map[typeOff]*_type // offset to *_rtype in previous module
|
||||||
|
|
||||||
|
bad bool // module failed to load and should be ignored
|
||||||
|
|
||||||
|
next *moduledata
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
type moduledata832 struct {
|
||||||
|
Pclntable, Pclntablelen, Pclntablecap uint32
|
||||||
|
Ftab, Ftablen, Ftabcap uint32
|
||||||
|
Filetab, Filetablen, Filetabcap uint32
|
||||||
|
Findfunctab uint32
|
||||||
|
Minpc, Maxpc uint32
|
||||||
|
|
||||||
|
Text, Etext uint32
|
||||||
|
Noptrdata, Enoptrdata uint32
|
||||||
|
Data, Edata uint32
|
||||||
|
Bss, Ebss uint32
|
||||||
|
Noptrbss, Enoptrbss uint32
|
||||||
|
End, Gcdata, Gcbss uint32
|
||||||
|
Types, Etypes uint32
|
||||||
|
|
||||||
|
Textsectmap, Textsectmaplen, Textsectmapcap uint32
|
||||||
|
Typelinks, Typelinkslen, Typelinkscap uint32 // offsets from types
|
||||||
|
Itablinks, Itablinkslen, Itablinkscap uint32
|
||||||
|
|
||||||
|
Ptab, Ptablen, Ptabcap uint32
|
||||||
|
|
||||||
|
Pluginpath, Pluginpathlen uint32
|
||||||
|
Pkghashes, Pkghasheslen, Pkghashescap uint32
|
||||||
|
|
||||||
|
Modulename, Modulenamelen uint32
|
||||||
|
Modulehashes, Modulehasheslen, Modulehashescap uint32
|
||||||
|
|
||||||
|
/* These fields we are not planning to use so skipping the parsing of them.
|
||||||
|
|
||||||
|
hasmain uint8 // 1 if module contains the main function, 0 otherwise
|
||||||
|
|
||||||
|
gcdatamask, gcbssmask bitvector
|
||||||
|
|
||||||
|
typemap map[typeOff]*_type // offset to *_rtype in previous module
|
||||||
|
|
||||||
|
bad bool // module failed to load and should be ignored
|
||||||
|
|
||||||
|
next *moduledata
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
// Moduledata structure for Go 1.7
|
||||||
|
|
||||||
|
type moduledata764 struct {
|
||||||
|
Pclntable, Pclntablelen, Pclntablecap uint64
|
||||||
|
Ftab, Ftablen, Ftabcap uint64
|
||||||
|
Filetab, Filetablen, Filetabcap uint64
|
||||||
|
Findfunctab uint64
|
||||||
|
Minpc, Maxpc uint64
|
||||||
|
|
||||||
|
Text, Etext uint64
|
||||||
|
Noptrdata, Enoptrdata uint64
|
||||||
|
Data, Edata uint64
|
||||||
|
Bss, Ebss uint64
|
||||||
|
Noptrbss, Enoptrbss uint64
|
||||||
|
End, Gcdata, Gcbss uint64
|
||||||
|
Types, Etypes uint64
|
||||||
|
|
||||||
|
Typelinks, Typelinkslen, Typelinkscap uint64 // offsets from types
|
||||||
|
Itablinks, Itablinkslen, Itablinkscap uint64
|
||||||
|
|
||||||
|
Modulename, Modulenamelen uint64
|
||||||
|
Modulehashes, Modulehasheslen, Modulehashescap uint64
|
||||||
|
|
||||||
|
/* These fields we are not planning to use so skipping the parsing of them.
|
||||||
|
|
||||||
|
gcdatamask, gcbssmask bitvector
|
||||||
|
|
||||||
|
typemap map[typeOff]*_type // offset to *_rtype in previous module
|
||||||
|
|
||||||
|
next *moduledata
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
type moduledata732 struct {
|
||||||
|
Pclntable, Pclntablelen, Pclntablecap uint32
|
||||||
|
Ftab, Ftablen, Ftabcap uint32
|
||||||
|
Filetab, Filetablen, Filetabcap uint32
|
||||||
|
Findfunctab uint32
|
||||||
|
Minpc, Maxpc uint32
|
||||||
|
|
||||||
|
Text, Etext uint32
|
||||||
|
Noptrdata, Enoptrdata uint32
|
||||||
|
Data, Edata uint32
|
||||||
|
Bss, Ebss uint32
|
||||||
|
Noptrbss, Enoptrbss uint32
|
||||||
|
End, Gcdata, Gcbss uint32
|
||||||
|
Types, Etypes uint32
|
||||||
|
|
||||||
|
Typelinks, Typelinkslen, Typelinkscap uint32 // offsets from types
|
||||||
|
Itablinks, Itablinkslen, Itablinkscap uint32
|
||||||
|
|
||||||
|
Modulename, Modulenamelen uint32
|
||||||
|
Modulehashes, Modulehasheslen, Modulehashescap uint32
|
||||||
|
|
||||||
|
/* These fields we are not planning to use so skipping the parsing of them.
|
||||||
|
|
||||||
|
gcdatamask, gcbssmask bitvector
|
||||||
|
|
||||||
|
typemap map[typeOff]*_type // offset to *_rtype in previous module
|
||||||
|
|
||||||
|
next *moduledata
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
// Moduledata structure for Go 1.5 to 1.6
|
||||||
|
|
||||||
|
type moduledata564 struct {
|
||||||
|
Pclntable, Pclntablelen, Pclntablecap uint64
|
||||||
|
Ftab, Ftablen, Ftabcap uint64
|
||||||
|
Filetab, Filetablen, Filetabcap uint64
|
||||||
|
Findfunctab uint64
|
||||||
|
Minpc, Maxpc uint64
|
||||||
|
|
||||||
|
Text, Etext uint64
|
||||||
|
Noptrdata, Enoptrdata uint64
|
||||||
|
Data, Edata uint64
|
||||||
|
Bss, Ebss uint64
|
||||||
|
Noptrbss, Enoptrbss uint64
|
||||||
|
End, Gcdata, Gcbss uint64
|
||||||
|
|
||||||
|
Typelinks, Typelinkslen, Typelinkscap uint64
|
||||||
|
|
||||||
|
Modulename, Modulenamelen uint64
|
||||||
|
Modulehashes, Modulehasheslen, Modulehashescap uint64
|
||||||
|
|
||||||
|
/* These fields we are not planning to use so skipping the parsing of them.
|
||||||
|
|
||||||
|
gcdatamask, gcbssmask bitvector
|
||||||
|
|
||||||
|
typemap map[typeOff]*_type // offset to *_rtype in previous module
|
||||||
|
|
||||||
|
next *moduledata
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
type moduledata532 struct {
|
||||||
|
Pclntable, Pclntablelen, Pclntablecap uint32
|
||||||
|
Ftab, Ftablen, Ftabcap uint32
|
||||||
|
Filetab, Filetablen, Filetabcap uint32
|
||||||
|
Findfunctab uint32
|
||||||
|
Minpc, Maxpc uint32
|
||||||
|
|
||||||
|
Text, Etext uint32
|
||||||
|
Noptrdata, Enoptrdata uint32
|
||||||
|
Data, Edata uint32
|
||||||
|
Bss, Ebss uint32
|
||||||
|
Noptrbss, Enoptrbss uint32
|
||||||
|
End, Gcdata, Gcbss uint32
|
||||||
|
|
||||||
|
Typelinks, Typelinkslen, Typelinkscap uint32
|
||||||
|
|
||||||
|
Modulename, Modulenamelen uint32
|
||||||
|
Modulehashes, Modulehasheslen, Modulehashescap uint32
|
||||||
|
|
||||||
|
/* These fields we are not planning to use so skipping the parsing of them.
|
||||||
|
|
||||||
|
gcdatamask, gcbssmask bitvector
|
||||||
|
|
||||||
|
typemap map[typeOff]*_type // offset to *_rtype in previous module
|
||||||
|
|
||||||
|
next *moduledata
|
||||||
|
*/
|
||||||
|
}
|
||||||
300
vendor/github.com/goretk/gore/package.go
generated
vendored
Normal file
300
vendor/github.com/goretk/gore/package.go
generated
vendored
Normal file
@ -0,0 +1,300 @@
|
|||||||
|
// This file is part of GoRE.
|
||||||
|
//
|
||||||
|
// Copyright (C) 2019-2021 GoRE Authors
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU Affero General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Affero General Public License
|
||||||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
package gore
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"path/filepath"
|
||||||
|
"runtime/debug"
|
||||||
|
"sort"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
//go:generate go run gen.go
|
||||||
|
|
||||||
|
var (
|
||||||
|
knownRepos = []string{"golang.org", "github.com", "gitlab.com"}
|
||||||
|
)
|
||||||
|
|
||||||
|
// Package is a representation of a Go package.
|
||||||
|
type Package struct {
|
||||||
|
// Name is the name of the package.
|
||||||
|
Name string `json:"name"`
|
||||||
|
// Filepath is the extracted file path for the package.
|
||||||
|
Filepath string `json:"path"`
|
||||||
|
// Functions is a list of functions that are part of the package.
|
||||||
|
Functions []*Function `json:"functions"`
|
||||||
|
// Methods a list of methods that are part of the package.
|
||||||
|
Methods []*Method `json:"methods"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetSourceFiles returns a slice of source files within the package.
|
||||||
|
// The source files are a representations of the source code files in the package.
|
||||||
|
func (f *GoFile) GetSourceFiles(p *Package) []*SourceFile {
|
||||||
|
tmp := make(map[string]*SourceFile)
|
||||||
|
getSourceFile := func(fileName string) *SourceFile {
|
||||||
|
sf, ok := tmp[fileName]
|
||||||
|
if !ok {
|
||||||
|
return &SourceFile{Name: filepath.Base(fileName)}
|
||||||
|
}
|
||||||
|
return sf
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sort functions and methods by source file.
|
||||||
|
for _, fn := range p.Functions {
|
||||||
|
fileName, _, _ := f.pclntab.PCToLine(fn.Offset)
|
||||||
|
start, end := findSourceLines(fn.Offset, fn.End, f.pclntab)
|
||||||
|
|
||||||
|
e := FileEntry{Name: fn.Name, Start: start, End: end}
|
||||||
|
|
||||||
|
sf := getSourceFile(fileName)
|
||||||
|
sf.entries = append(sf.entries, e)
|
||||||
|
tmp[fileName] = sf
|
||||||
|
}
|
||||||
|
for _, m := range p.Methods {
|
||||||
|
fileName, _, _ := f.pclntab.PCToLine(m.Offset)
|
||||||
|
start, end := findSourceLines(m.Offset, m.End, f.pclntab)
|
||||||
|
|
||||||
|
e := FileEntry{Name: fmt.Sprintf("%s%s", m.Receiver, m.Name), Start: start, End: end}
|
||||||
|
|
||||||
|
sf := getSourceFile(fileName)
|
||||||
|
sf.entries = append(sf.entries, e)
|
||||||
|
tmp[fileName] = sf
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create final slice and populate it.
|
||||||
|
files := make([]*SourceFile, len(tmp))
|
||||||
|
i := 0
|
||||||
|
for _, sf := range tmp {
|
||||||
|
files[i] = sf
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sort the file list.
|
||||||
|
sort.Slice(files, func(i, j int) bool {
|
||||||
|
return files[i].Name < files[j].Name
|
||||||
|
})
|
||||||
|
return files
|
||||||
|
}
|
||||||
|
|
||||||
|
// PackageClass is a type used to indicate the package kind.
|
||||||
|
type PackageClass uint8
|
||||||
|
|
||||||
|
const (
|
||||||
|
// ClassUnknown is used for packages that could not be classified.
|
||||||
|
ClassUnknown PackageClass = iota
|
||||||
|
// ClassSTD is used for packages that are part of the standard library.
|
||||||
|
ClassSTD
|
||||||
|
// ClassMain is used for the main package and its subpackages.
|
||||||
|
ClassMain
|
||||||
|
// ClassVendor is used for vendor packages.
|
||||||
|
ClassVendor
|
||||||
|
// ClassGenerated are used for packages generated by the compiler.
|
||||||
|
ClassGenerated
|
||||||
|
)
|
||||||
|
|
||||||
|
// PackageClassifier classifies a package to the correct class type.
|
||||||
|
type PackageClassifier interface {
|
||||||
|
// Classify performs the classification.
|
||||||
|
Classify(pkg *Package) PackageClass
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewPathPackageClassifier constructs a new classifier based on the main package's filepath.
|
||||||
|
func NewPathPackageClassifier(mainPkgFilepath string) *PathPackageClassifier {
|
||||||
|
return &PathPackageClassifier{
|
||||||
|
mainFilepath: mainPkgFilepath, mainFolders: []string{
|
||||||
|
filepath.Dir(mainPkgFilepath),
|
||||||
|
mainPkgFilepath,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// PathPackageClassifier can classify the class of a go package.
|
||||||
|
type PathPackageClassifier struct {
|
||||||
|
mainFilepath string
|
||||||
|
mainFolders []string
|
||||||
|
}
|
||||||
|
|
||||||
|
// Classify returns the package class for the package.
|
||||||
|
func (c *PathPackageClassifier) Classify(pkg *Package) PackageClass {
|
||||||
|
if pkg.Name == "type" || strings.HasPrefix(pkg.Name, "type..") {
|
||||||
|
return ClassGenerated
|
||||||
|
}
|
||||||
|
|
||||||
|
if IsStandardLibrary(pkg.Name) {
|
||||||
|
return ClassSTD
|
||||||
|
}
|
||||||
|
|
||||||
|
if isGeneratedPackage(pkg) {
|
||||||
|
return ClassGenerated
|
||||||
|
}
|
||||||
|
|
||||||
|
// Detect internal/golang.org/x/net/http2/hpack type/
|
||||||
|
tmp := strings.Split(pkg.Name, "/golang.org")[0]
|
||||||
|
if len(tmp) < len(pkg.Name) && IsStandardLibrary(tmp) {
|
||||||
|
return ClassSTD
|
||||||
|
}
|
||||||
|
|
||||||
|
// cgo packages.
|
||||||
|
if strings.HasPrefix(pkg.Name, "_cgo_") || strings.HasPrefix(pkg.Name, "x_cgo_") {
|
||||||
|
return ClassSTD
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the file path contains "@v", it's a 3rd party package.
|
||||||
|
if strings.Contains(pkg.Filepath, "@v") {
|
||||||
|
return ClassVendor
|
||||||
|
}
|
||||||
|
|
||||||
|
parentFolder := filepath.Dir(pkg.Filepath)
|
||||||
|
|
||||||
|
if strings.HasPrefix(pkg.Filepath, c.mainFilepath+"/vendor/") ||
|
||||||
|
strings.HasPrefix(pkg.Filepath, filepath.Dir(c.mainFilepath)+"/vendor/") ||
|
||||||
|
strings.HasPrefix(pkg.Filepath, filepath.Dir(filepath.Dir(c.mainFilepath))+"/vendor/") {
|
||||||
|
return ClassVendor
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, folder := range c.mainFolders {
|
||||||
|
if parentFolder == folder {
|
||||||
|
return ClassMain
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the package name starts with "vendor/" assume it's a vendor package.
|
||||||
|
if strings.HasPrefix(pkg.Name, "vendor/") {
|
||||||
|
return ClassVendor
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start with repo url.and has it in the path.
|
||||||
|
for _, url := range knownRepos {
|
||||||
|
if strings.HasPrefix(pkg.Name, url) && strings.Contains(pkg.Filepath, url) {
|
||||||
|
return ClassVendor
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the path does not contain the "vendor" in path but has the main package folder name, assume part of main.
|
||||||
|
if !strings.Contains(pkg.Filepath, "vendor/") &&
|
||||||
|
(filepath.Base(filepath.Dir(pkg.Filepath)) == filepath.Base(c.mainFilepath)) {
|
||||||
|
return ClassMain
|
||||||
|
}
|
||||||
|
|
||||||
|
// Special case for entry point package.
|
||||||
|
if pkg.Name == "" && filepath.Base(pkg.Filepath) == "runtime" {
|
||||||
|
return ClassSTD
|
||||||
|
}
|
||||||
|
|
||||||
|
// At this point, if it's a subpackage of the main assume main.
|
||||||
|
if strings.HasPrefix(pkg.Filepath, c.mainFilepath) {
|
||||||
|
return ClassMain
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if it's the main parent package.
|
||||||
|
if pkg.Name != "" && !strings.Contains(pkg.Name, "/") && strings.Contains(c.mainFilepath, pkg.Name) {
|
||||||
|
return ClassMain
|
||||||
|
}
|
||||||
|
|
||||||
|
// At this point, if the main package has a file path of "command-line-arguments" and we haven't figured out
|
||||||
|
// what class it is. We assume it being part of the main package.
|
||||||
|
if c.mainFilepath == "command-line-arguments" {
|
||||||
|
return ClassMain
|
||||||
|
}
|
||||||
|
|
||||||
|
return ClassUnknown
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsStandardLibrary returns true if the package is from the standard library.
|
||||||
|
// Otherwise, false is retuned.
|
||||||
|
func IsStandardLibrary(pkg string) bool {
|
||||||
|
_, ok := stdPkgs[pkg]
|
||||||
|
return ok
|
||||||
|
}
|
||||||
|
|
||||||
|
func isGeneratedPackage(pkg *Package) bool {
|
||||||
|
// Detect regexp.(*onePassInst).regexp/syntax type packages
|
||||||
|
tmp := strings.Split(pkg.Name, ".")[0]
|
||||||
|
if len(tmp) < len(pkg.Name) && IsStandardLibrary(tmp) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Special case for no package name and path of ".".
|
||||||
|
if pkg.Name == "" && pkg.Filepath == "." {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Some internal stuff, classify it as Generated
|
||||||
|
if pkg.Filepath == "." && (pkg.Name == "__x86" || pkg.Name == "__i686") {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewModPackageClassifier creates a new mod based package classifier.
|
||||||
|
func NewModPackageClassifier(buildInfo *debug.BuildInfo) *ModPackageClassifier {
|
||||||
|
return &ModPackageClassifier{modInfo: buildInfo}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ModPackageClassifier uses the mod info extracted from the binary to classify packages.
|
||||||
|
type ModPackageClassifier struct {
|
||||||
|
modInfo *debug.BuildInfo
|
||||||
|
}
|
||||||
|
|
||||||
|
// Classify performs the classification.
|
||||||
|
func (c *ModPackageClassifier) Classify(pkg *Package) PackageClass {
|
||||||
|
if IsStandardLibrary(pkg.Name) {
|
||||||
|
return ClassSTD
|
||||||
|
}
|
||||||
|
|
||||||
|
// Main package.
|
||||||
|
if pkg.Name == "main" {
|
||||||
|
return ClassMain
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the build info path is not an empty string and the package has the path as a substring, it is part of the main module.
|
||||||
|
if c.modInfo.Path != "" && (strings.HasPrefix(pkg.Filepath, c.modInfo.Path) || strings.HasPrefix(pkg.Name, c.modInfo.Path)) {
|
||||||
|
return ClassMain
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the main module path is not an empty string and the package has the path as a substring, it is part of the main module.
|
||||||
|
if c.modInfo.Main.Path != "" && (strings.HasPrefix(pkg.Filepath, c.modInfo.Main.Path) || strings.HasPrefix(pkg.Name, c.modInfo.Main.Path)) {
|
||||||
|
return ClassMain
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the package is a direct dependency.
|
||||||
|
for _, dep := range c.modInfo.Deps {
|
||||||
|
if strings.HasPrefix(pkg.Filepath, dep.Path) || strings.HasPrefix(pkg.Name, dep.Path) {
|
||||||
|
// If the vendor it matched on has the version of "(devel)", it is treated as part of
|
||||||
|
// the main module.
|
||||||
|
if dep.Version == "(devel)" {
|
||||||
|
return ClassMain
|
||||||
|
}
|
||||||
|
return ClassVendor
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if isGeneratedPackage(pkg) {
|
||||||
|
return ClassGenerated
|
||||||
|
}
|
||||||
|
|
||||||
|
// cgo packages.
|
||||||
|
if strings.HasPrefix(pkg.Name, "_cgo_") || strings.HasPrefix(pkg.Name, "x_cgo_") {
|
||||||
|
return ClassSTD
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only indirect dependencies should be left.
|
||||||
|
return ClassVendor
|
||||||
|
}
|
||||||
95
vendor/github.com/goretk/gore/pclntab.go
generated
vendored
Normal file
95
vendor/github.com/goretk/gore/pclntab.go
generated
vendored
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
// This file is part of GoRE.
|
||||||
|
//
|
||||||
|
// Copyright (C) 2019-2021 GoRE Authors
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU Affero General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Affero General Public License
|
||||||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
package gore
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"debug/pe"
|
||||||
|
)
|
||||||
|
|
||||||
|
// pclntab12magic is the magic bytes used for binaries compiled with Go
|
||||||
|
// prior to 1.16
|
||||||
|
var pclntab12magic = []byte{0xfb, 0xff, 0xff, 0xff, 0x0, 0x0}
|
||||||
|
|
||||||
|
// pclntab116magic is the magic bytes used for binaries compiled with
|
||||||
|
// Go 1.16 and Go 1.17.
|
||||||
|
var pclntab116magic = []byte{0xfa, 0xff, 0xff, 0xff, 0x0, 0x0}
|
||||||
|
|
||||||
|
// pclntab118magic is the magic bytes used for binaries compiled with
|
||||||
|
// Go 1.18 and Go 1.19.
|
||||||
|
var pclntab118magic = []byte{0xf0, 0xff, 0xff, 0xff, 0x0, 0x0}
|
||||||
|
|
||||||
|
// pclntab120magic is the magic bytes used for binaries compiled with
|
||||||
|
// Go 1.20 and onwards.
|
||||||
|
var pclntab120magic = []byte{0xf1, 0xff, 0xff, 0xff, 0x0, 0x0}
|
||||||
|
|
||||||
|
// searchFileForPCLNTab will search the .rdata and .text section for the
|
||||||
|
// PCLN table. Note!! The address returned by this function needs to be
|
||||||
|
// adjusted by adding the image base address!!!
|
||||||
|
func searchFileForPCLNTab(f *pe.File) (uint32, []byte, error) {
|
||||||
|
for _, v := range []string{".rdata", ".text"} {
|
||||||
|
sec := f.Section(v)
|
||||||
|
if sec == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
secData, err := sec.Data()
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
tab, err := searchSectionForTab(secData)
|
||||||
|
if err == ErrNoPCLNTab {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// TODO: Switch to returning a uint64 instead.
|
||||||
|
addr := sec.VirtualAddress + uint32(len(secData)-len(tab))
|
||||||
|
return addr, tab, err
|
||||||
|
}
|
||||||
|
return 0, []byte{}, ErrNoPCLNTab
|
||||||
|
}
|
||||||
|
|
||||||
|
// searchSectionForTab looks for the PCLN table within the section.
|
||||||
|
func searchSectionForTab(secData []byte) ([]byte, error) {
|
||||||
|
// First check for the current magic used. If this fails, it could be
|
||||||
|
// an older version. So check for the old header.
|
||||||
|
MAGIC_LOOP:
|
||||||
|
for _, magic := range [][]byte{pclntab120magic, pclntab118magic, pclntab116magic, pclntab12magic} {
|
||||||
|
off := bytes.LastIndex(secData, magic)
|
||||||
|
if off == -1 {
|
||||||
|
continue // Try other magic.
|
||||||
|
}
|
||||||
|
for off != -1 {
|
||||||
|
if off != 0 {
|
||||||
|
buf := secData[off:]
|
||||||
|
if len(buf) < 16 || buf[4] != 0 || buf[5] != 0 ||
|
||||||
|
(buf[6] != 1 && buf[6] != 2 && buf[6] != 4) || // pc quantum
|
||||||
|
(buf[7] != 4 && buf[7] != 8) { // pointer size
|
||||||
|
// Header doesn't match.
|
||||||
|
if off-1 <= 0 {
|
||||||
|
continue MAGIC_LOOP
|
||||||
|
}
|
||||||
|
off = bytes.LastIndex(secData[:off-1], magic)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// Header match
|
||||||
|
return secData[off:], nil
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil, ErrNoPCLNTab
|
||||||
|
}
|
||||||
153
vendor/github.com/goretk/gore/pe.go
generated
vendored
Normal file
153
vendor/github.com/goretk/gore/pe.go
generated
vendored
Normal file
@ -0,0 +1,153 @@
|
|||||||
|
// This file is part of GoRE.
|
||||||
|
//
|
||||||
|
// Copyright (C) 2019-2021 GoRE Authors
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU Affero General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Affero General Public License
|
||||||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
package gore
|
||||||
|
|
||||||
|
import (
|
||||||
|
"debug/gosym"
|
||||||
|
"debug/pe"
|
||||||
|
"encoding/binary"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
func openPE(fp string) (peF *peFile, err error) {
|
||||||
|
// Parsing by the file by debug/pe can panic if the PE file is malformed.
|
||||||
|
// To prevent a crash, we recover the panic and return it as an error
|
||||||
|
// instead.
|
||||||
|
go func() {
|
||||||
|
if r := recover(); r != nil {
|
||||||
|
err = fmt.Errorf("error when processing PE file, probably corrupt: %s", r)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
osFile, err := os.Open(fp)
|
||||||
|
if err != nil {
|
||||||
|
err = fmt.Errorf("error when opening the file: %w", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
f, err := pe.NewFile(osFile)
|
||||||
|
if err != nil {
|
||||||
|
err = fmt.Errorf("error when parsing the PE file: %w", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
peF = &peFile{file: f, osFile: osFile}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
type peFile struct {
|
||||||
|
file *pe.File
|
||||||
|
osFile *os.File
|
||||||
|
pclntabAddr uint64
|
||||||
|
imageBase uint64
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *peFile) getFile() *os.File {
|
||||||
|
return p.osFile
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *peFile) getPCLNTab() (*gosym.Table, error) {
|
||||||
|
addr, pclndat, err := searchFileForPCLNTab(p.file)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
pcln := gosym.NewLineTable(pclndat, uint64(p.file.Section(".text").VirtualAddress)+p.imageBase)
|
||||||
|
p.pclntabAddr = uint64(addr) + p.imageBase
|
||||||
|
return gosym.NewTable(make([]byte, 0), pcln)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *peFile) Close() error {
|
||||||
|
err := p.file.Close()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return p.osFile.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *peFile) getRData() ([]byte, error) {
|
||||||
|
section := p.file.Section(".rdata")
|
||||||
|
if section == nil {
|
||||||
|
return nil, ErrSectionDoesNotExist
|
||||||
|
}
|
||||||
|
return section.Data()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *peFile) getCodeSection() ([]byte, error) {
|
||||||
|
section := p.file.Section(".text")
|
||||||
|
if section == nil {
|
||||||
|
return nil, ErrSectionDoesNotExist
|
||||||
|
}
|
||||||
|
return section.Data()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *peFile) moduledataSection() string {
|
||||||
|
return ".data"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *peFile) getPCLNTABData() (uint64, []byte, error) {
|
||||||
|
b, d, e := searchFileForPCLNTab(p.file)
|
||||||
|
return p.imageBase + uint64(b), d, e
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *peFile) getSectionDataFromOffset(off uint64) (uint64, []byte, error) {
|
||||||
|
for _, section := range p.file.Sections {
|
||||||
|
if section.Offset == 0 {
|
||||||
|
// Only exist in memory
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if p.imageBase+uint64(section.VirtualAddress) <= off && off < p.imageBase+uint64(section.VirtualAddress+section.Size) {
|
||||||
|
data, err := section.Data()
|
||||||
|
return p.imageBase + uint64(section.VirtualAddress), data, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0, nil, ErrSectionDoesNotExist
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *peFile) getSectionData(name string) (uint64, []byte, error) {
|
||||||
|
section := p.file.Section(name)
|
||||||
|
if section == nil {
|
||||||
|
return 0, nil, ErrSectionDoesNotExist
|
||||||
|
}
|
||||||
|
data, err := section.Data()
|
||||||
|
return p.imageBase + uint64(section.VirtualAddress), data, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *peFile) getFileInfo() *FileInfo {
|
||||||
|
fi := &FileInfo{ByteOrder: binary.LittleEndian, OS: "windows"}
|
||||||
|
if p.file.Machine == pe.IMAGE_FILE_MACHINE_I386 {
|
||||||
|
fi.WordSize = intSize32
|
||||||
|
optHdr := p.file.OptionalHeader.(*pe.OptionalHeader32)
|
||||||
|
p.imageBase = uint64(optHdr.ImageBase)
|
||||||
|
fi.Arch = Arch386
|
||||||
|
} else {
|
||||||
|
fi.WordSize = intSize64
|
||||||
|
optHdr := p.file.OptionalHeader.(*pe.OptionalHeader64)
|
||||||
|
p.imageBase = optHdr.ImageBase
|
||||||
|
fi.Arch = ArchAMD64
|
||||||
|
}
|
||||||
|
return fi
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *peFile) getBuildID() (string, error) {
|
||||||
|
data, err := p.getCodeSection()
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("failed to get code section: %w", err)
|
||||||
|
}
|
||||||
|
return parseBuildIDFromRaw(data)
|
||||||
|
}
|
||||||
494
vendor/github.com/goretk/gore/stdpkg_gen.go
generated
vendored
Normal file
494
vendor/github.com/goretk/gore/stdpkg_gen.go
generated
vendored
Normal file
@ -0,0 +1,494 @@
|
|||||||
|
// This file is part of GoRE.
|
||||||
|
//
|
||||||
|
// Copyright (C) 2019-2021 GoRE Authors
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU Affero General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Affero General Public License
|
||||||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
// Code generated by go generate; DO NOT EDIT.
|
||||||
|
// This file was generated at
|
||||||
|
// 2023-11-10 16:31:24.540225333 +0000 UTC
|
||||||
|
|
||||||
|
package gore
|
||||||
|
|
||||||
|
var stdPkgs = map[string]struct{}{
|
||||||
|
"archive": {},
|
||||||
|
"archive/tar": {},
|
||||||
|
"archive/tar/testdata": {},
|
||||||
|
"archive/zip": {},
|
||||||
|
"archive/zip/testdata": {},
|
||||||
|
"arena": {},
|
||||||
|
"bufio": {},
|
||||||
|
"builtin": {},
|
||||||
|
"bytes": {},
|
||||||
|
"cmp": {},
|
||||||
|
"compress": {},
|
||||||
|
"compress/bzip2": {},
|
||||||
|
"compress/bzip2/testdata": {},
|
||||||
|
"compress/flate": {},
|
||||||
|
"compress/flate/testdata": {},
|
||||||
|
"compress/gzip": {},
|
||||||
|
"compress/gzip/testdata": {},
|
||||||
|
"compress/lzw": {},
|
||||||
|
"compress/testdata": {},
|
||||||
|
"compress/zlib": {},
|
||||||
|
"container": {},
|
||||||
|
"container/heap": {},
|
||||||
|
"container/list": {},
|
||||||
|
"container/ring": {},
|
||||||
|
"context": {},
|
||||||
|
"crypto": {},
|
||||||
|
"crypto/aes": {},
|
||||||
|
"crypto/boring": {},
|
||||||
|
"crypto/cipher": {},
|
||||||
|
"crypto/des": {},
|
||||||
|
"crypto/dsa": {},
|
||||||
|
"crypto/ecdh": {},
|
||||||
|
"crypto/ecdsa": {},
|
||||||
|
"crypto/ecdsa/testdata": {},
|
||||||
|
"crypto/ed25519": {},
|
||||||
|
"crypto/ed25519/testdata": {},
|
||||||
|
"crypto/elliptic": {},
|
||||||
|
"crypto/hmac": {},
|
||||||
|
"crypto/internal": {},
|
||||||
|
"crypto/internal/alias": {},
|
||||||
|
"crypto/internal/bigmod": {},
|
||||||
|
"crypto/internal/bigmod/_asm": {},
|
||||||
|
"crypto/internal/boring": {},
|
||||||
|
"crypto/internal/boring/bbig": {},
|
||||||
|
"crypto/internal/boring/bcache": {},
|
||||||
|
"crypto/internal/boring/fipstls": {},
|
||||||
|
"crypto/internal/boring/sig": {},
|
||||||
|
"crypto/internal/boring/syso": {},
|
||||||
|
"crypto/internal/edwards25519": {},
|
||||||
|
"crypto/internal/edwards25519/field": {},
|
||||||
|
"crypto/internal/edwards25519/field/_asm": {},
|
||||||
|
"crypto/internal/nistec": {},
|
||||||
|
"crypto/internal/nistec/fiat": {},
|
||||||
|
"crypto/internal/randutil": {},
|
||||||
|
"crypto/md5": {},
|
||||||
|
"crypto/rand": {},
|
||||||
|
"crypto/rc4": {},
|
||||||
|
"crypto/rsa": {},
|
||||||
|
"crypto/rsa/testdata": {},
|
||||||
|
"crypto/sha1": {},
|
||||||
|
"crypto/sha256": {},
|
||||||
|
"crypto/sha512": {},
|
||||||
|
"crypto/subtle": {},
|
||||||
|
"crypto/tls": {},
|
||||||
|
"crypto/tls/fipsonly": {},
|
||||||
|
"crypto/tls/testdata": {},
|
||||||
|
"crypto/x509": {},
|
||||||
|
"crypto/x509/internal": {},
|
||||||
|
"crypto/x509/internal/macos": {},
|
||||||
|
"crypto/x509/pkix": {},
|
||||||
|
"crypto/x509/testdata": {},
|
||||||
|
"database": {},
|
||||||
|
"database/sql": {},
|
||||||
|
"database/sql/driver": {},
|
||||||
|
"debug": {},
|
||||||
|
"debug/buildinfo": {},
|
||||||
|
"debug/dwarf": {},
|
||||||
|
"debug/dwarf/testdata": {},
|
||||||
|
"debug/elf": {},
|
||||||
|
"debug/elf/testdata": {},
|
||||||
|
"debug/gosym": {},
|
||||||
|
"debug/gosym/testdata": {},
|
||||||
|
"debug/macho": {},
|
||||||
|
"debug/macho/testdata": {},
|
||||||
|
"debug/pe": {},
|
||||||
|
"debug/pe/testdata": {},
|
||||||
|
"debug/plan9obj": {},
|
||||||
|
"debug/plan9obj/testdata": {},
|
||||||
|
"embed": {},
|
||||||
|
"embed/internal": {},
|
||||||
|
"embed/internal/embedtest": {},
|
||||||
|
"embed/internal/embedtest/testdata": {},
|
||||||
|
"embed/internal/embedtest/testdata/-not-hidden": {},
|
||||||
|
"embed/internal/embedtest/testdata/.hidden": {},
|
||||||
|
"embed/internal/embedtest/testdata/.hidden/.more": {},
|
||||||
|
"embed/internal/embedtest/testdata/.hidden/_more": {},
|
||||||
|
"embed/internal/embedtest/testdata/.hidden/more": {},
|
||||||
|
"embed/internal/embedtest/testdata/_hidden": {},
|
||||||
|
"embed/internal/embedtest/testdata/i": {},
|
||||||
|
"embed/internal/embedtest/testdata/i/j": {},
|
||||||
|
"embed/internal/embedtest/testdata/i/j/k": {},
|
||||||
|
"encoding": {},
|
||||||
|
"encoding/ascii85": {},
|
||||||
|
"encoding/asn1": {},
|
||||||
|
"encoding/base32": {},
|
||||||
|
"encoding/base64": {},
|
||||||
|
"encoding/binary": {},
|
||||||
|
"encoding/csv": {},
|
||||||
|
"encoding/gob": {},
|
||||||
|
"encoding/hex": {},
|
||||||
|
"encoding/json": {},
|
||||||
|
"encoding/json/testdata": {},
|
||||||
|
"encoding/pem": {},
|
||||||
|
"encoding/xml": {},
|
||||||
|
"errors": {},
|
||||||
|
"expvar": {},
|
||||||
|
"flag": {},
|
||||||
|
"fmt": {},
|
||||||
|
"go": {},
|
||||||
|
"go/ast": {},
|
||||||
|
"go/build": {},
|
||||||
|
"go/build/constraint": {},
|
||||||
|
"go/build/testdata": {},
|
||||||
|
"go/build/testdata/alltags": {},
|
||||||
|
"go/build/testdata/bads": {},
|
||||||
|
"go/build/testdata/cgo_disabled": {},
|
||||||
|
"go/build/testdata/directives": {},
|
||||||
|
"go/build/testdata/doc": {},
|
||||||
|
"go/build/testdata/empty": {},
|
||||||
|
"go/build/testdata/multi": {},
|
||||||
|
"go/build/testdata/non_source_tags": {},
|
||||||
|
"go/build/testdata/other": {},
|
||||||
|
"go/build/testdata/other/file": {},
|
||||||
|
"go/build/testdata/withvendor": {},
|
||||||
|
"go/build/testdata/withvendor/src": {},
|
||||||
|
"go/build/testdata/withvendor/src/a": {},
|
||||||
|
"go/build/testdata/withvendor/src/a/b": {},
|
||||||
|
"go/build/testdata/withvendor/src/a/vendor": {},
|
||||||
|
"go/build/testdata/withvendor/src/a/vendor/c": {},
|
||||||
|
"go/build/testdata/withvendor/src/a/vendor/c/d": {},
|
||||||
|
"go/constant": {},
|
||||||
|
"go/doc": {},
|
||||||
|
"go/doc/comment": {},
|
||||||
|
"go/doc/comment/testdata": {},
|
||||||
|
"go/doc/testdata": {},
|
||||||
|
"go/doc/testdata/examples": {},
|
||||||
|
"go/doc/testdata/pkgdoc": {},
|
||||||
|
"go/format": {},
|
||||||
|
"go/importer": {},
|
||||||
|
"go/internal": {},
|
||||||
|
"go/internal/gccgoimporter": {},
|
||||||
|
"go/internal/gccgoimporter/testdata": {},
|
||||||
|
"go/internal/gcimporter": {},
|
||||||
|
"go/internal/gcimporter/testdata": {},
|
||||||
|
"go/internal/gcimporter/testdata/versions": {},
|
||||||
|
"go/internal/srcimporter": {},
|
||||||
|
"go/internal/srcimporter/testdata": {},
|
||||||
|
"go/internal/srcimporter/testdata/issue20855": {},
|
||||||
|
"go/internal/srcimporter/testdata/issue23092": {},
|
||||||
|
"go/internal/srcimporter/testdata/issue24392": {},
|
||||||
|
"go/internal/typeparams": {},
|
||||||
|
"go/parser": {},
|
||||||
|
"go/parser/testdata": {},
|
||||||
|
"go/parser/testdata/goversion": {},
|
||||||
|
"go/parser/testdata/issue42951": {},
|
||||||
|
"go/parser/testdata/issue42951/not_a_file.go": {},
|
||||||
|
"go/parser/testdata/resolution": {},
|
||||||
|
"go/printer": {},
|
||||||
|
"go/printer/testdata": {},
|
||||||
|
"go/scanner": {},
|
||||||
|
"go/token": {},
|
||||||
|
"go/types": {},
|
||||||
|
"go/types/testdata": {},
|
||||||
|
"go/types/testdata/local": {},
|
||||||
|
"go/version": {},
|
||||||
|
"hash": {},
|
||||||
|
"hash/adler32": {},
|
||||||
|
"hash/crc32": {},
|
||||||
|
"hash/crc64": {},
|
||||||
|
"hash/fnv": {},
|
||||||
|
"hash/maphash": {},
|
||||||
|
"html": {},
|
||||||
|
"html/template": {},
|
||||||
|
"html/template/testdata": {},
|
||||||
|
"image": {},
|
||||||
|
"image/color": {},
|
||||||
|
"image/color/palette": {},
|
||||||
|
"image/draw": {},
|
||||||
|
"image/gif": {},
|
||||||
|
"image/internal": {},
|
||||||
|
"image/internal/imageutil": {},
|
||||||
|
"image/jpeg": {},
|
||||||
|
"image/png": {},
|
||||||
|
"image/png/testdata": {},
|
||||||
|
"image/png/testdata/pngsuite": {},
|
||||||
|
"image/testdata": {},
|
||||||
|
"index": {},
|
||||||
|
"index/suffixarray": {},
|
||||||
|
"internal": {},
|
||||||
|
"internal/abi": {},
|
||||||
|
"internal/abi/testdata": {},
|
||||||
|
"internal/bisect": {},
|
||||||
|
"internal/buildcfg": {},
|
||||||
|
"internal/bytealg": {},
|
||||||
|
"internal/cfg": {},
|
||||||
|
"internal/coverage": {},
|
||||||
|
"internal/coverage/calloc": {},
|
||||||
|
"internal/coverage/cformat": {},
|
||||||
|
"internal/coverage/cmerge": {},
|
||||||
|
"internal/coverage/decodecounter": {},
|
||||||
|
"internal/coverage/decodemeta": {},
|
||||||
|
"internal/coverage/encodecounter": {},
|
||||||
|
"internal/coverage/encodemeta": {},
|
||||||
|
"internal/coverage/pods": {},
|
||||||
|
"internal/coverage/rtcov": {},
|
||||||
|
"internal/coverage/slicereader": {},
|
||||||
|
"internal/coverage/slicewriter": {},
|
||||||
|
"internal/coverage/stringtab": {},
|
||||||
|
"internal/coverage/test": {},
|
||||||
|
"internal/coverage/uleb128": {},
|
||||||
|
"internal/cpu": {},
|
||||||
|
"internal/dag": {},
|
||||||
|
"internal/diff": {},
|
||||||
|
"internal/diff/testdata": {},
|
||||||
|
"internal/fmtsort": {},
|
||||||
|
"internal/fuzz": {},
|
||||||
|
"internal/goarch": {},
|
||||||
|
"internal/godebug": {},
|
||||||
|
"internal/godebugs": {},
|
||||||
|
"internal/goexperiment": {},
|
||||||
|
"internal/goos": {},
|
||||||
|
"internal/goroot": {},
|
||||||
|
"internal/gover": {},
|
||||||
|
"internal/goversion": {},
|
||||||
|
"internal/intern": {},
|
||||||
|
"internal/itoa": {},
|
||||||
|
"internal/lazyregexp": {},
|
||||||
|
"internal/lazytemplate": {},
|
||||||
|
"internal/nettrace": {},
|
||||||
|
"internal/obscuretestdata": {},
|
||||||
|
"internal/oserror": {},
|
||||||
|
"internal/pkgbits": {},
|
||||||
|
"internal/platform": {},
|
||||||
|
"internal/poll": {},
|
||||||
|
"internal/profile": {},
|
||||||
|
"internal/race": {},
|
||||||
|
"internal/reflectlite": {},
|
||||||
|
"internal/safefilepath": {},
|
||||||
|
"internal/saferio": {},
|
||||||
|
"internal/singleflight": {},
|
||||||
|
"internal/syscall": {},
|
||||||
|
"internal/syscall/execenv": {},
|
||||||
|
"internal/syscall/unix": {},
|
||||||
|
"internal/syscall/windows": {},
|
||||||
|
"internal/syscall/windows/registry": {},
|
||||||
|
"internal/syscall/windows/sysdll": {},
|
||||||
|
"internal/sysinfo": {},
|
||||||
|
"internal/testenv": {},
|
||||||
|
"internal/testlog": {},
|
||||||
|
"internal/testpty": {},
|
||||||
|
"internal/trace": {},
|
||||||
|
"internal/trace/testdata": {},
|
||||||
|
"internal/trace/v2": {},
|
||||||
|
"internal/trace/v2/event": {},
|
||||||
|
"internal/trace/v2/event/go122": {},
|
||||||
|
"internal/trace/v2/internal": {},
|
||||||
|
"internal/trace/v2/internal/testgen": {},
|
||||||
|
"internal/trace/v2/internal/testgen/go122": {},
|
||||||
|
"internal/trace/v2/raw": {},
|
||||||
|
"internal/trace/v2/testdata": {},
|
||||||
|
"internal/trace/v2/testdata/cmd": {},
|
||||||
|
"internal/trace/v2/testdata/cmd/gotraceraw": {},
|
||||||
|
"internal/trace/v2/testdata/cmd/gotracevalidate": {},
|
||||||
|
"internal/trace/v2/testdata/generators": {},
|
||||||
|
"internal/trace/v2/testdata/testprog": {},
|
||||||
|
"internal/trace/v2/testdata/tests": {},
|
||||||
|
"internal/trace/v2/testtrace": {},
|
||||||
|
"internal/trace/v2/version": {},
|
||||||
|
"internal/txtar": {},
|
||||||
|
"internal/types": {},
|
||||||
|
"internal/types/errors": {},
|
||||||
|
"internal/types/testdata": {},
|
||||||
|
"internal/types/testdata/check": {},
|
||||||
|
"internal/types/testdata/check/decls2": {},
|
||||||
|
"internal/types/testdata/check/importdecl0": {},
|
||||||
|
"internal/types/testdata/check/importdecl1": {},
|
||||||
|
"internal/types/testdata/check/issue25008": {},
|
||||||
|
"internal/types/testdata/examples": {},
|
||||||
|
"internal/types/testdata/fixedbugs": {},
|
||||||
|
"internal/types/testdata/spec": {},
|
||||||
|
"internal/unsafeheader": {},
|
||||||
|
"internal/xcoff": {},
|
||||||
|
"internal/xcoff/testdata": {},
|
||||||
|
"internal/zstd": {},
|
||||||
|
"internal/zstd/testdata": {},
|
||||||
|
"io": {},
|
||||||
|
"io/fs": {},
|
||||||
|
"io/ioutil": {},
|
||||||
|
"io/ioutil/testdata": {},
|
||||||
|
"log": {},
|
||||||
|
"log/internal": {},
|
||||||
|
"log/slog": {},
|
||||||
|
"log/slog/internal": {},
|
||||||
|
"log/slog/internal/benchmarks": {},
|
||||||
|
"log/slog/internal/buffer": {},
|
||||||
|
"log/slog/internal/slogtest": {},
|
||||||
|
"log/syslog": {},
|
||||||
|
"maps": {},
|
||||||
|
"math": {},
|
||||||
|
"math/big": {},
|
||||||
|
"math/bits": {},
|
||||||
|
"math/cmplx": {},
|
||||||
|
"math/rand": {},
|
||||||
|
"math/rand/v2": {},
|
||||||
|
"mime": {},
|
||||||
|
"mime/multipart": {},
|
||||||
|
"mime/multipart/testdata": {},
|
||||||
|
"mime/quotedprintable": {},
|
||||||
|
"mime/testdata": {},
|
||||||
|
"net": {},
|
||||||
|
"net/http": {},
|
||||||
|
"net/http/cgi": {},
|
||||||
|
"net/http/cookiejar": {},
|
||||||
|
"net/http/fcgi": {},
|
||||||
|
"net/http/httptest": {},
|
||||||
|
"net/http/httptrace": {},
|
||||||
|
"net/http/httputil": {},
|
||||||
|
"net/http/internal": {},
|
||||||
|
"net/http/internal/ascii": {},
|
||||||
|
"net/http/internal/testcert": {},
|
||||||
|
"net/http/pprof": {},
|
||||||
|
"net/http/testdata": {},
|
||||||
|
"net/internal": {},
|
||||||
|
"net/internal/socktest": {},
|
||||||
|
"net/mail": {},
|
||||||
|
"net/netip": {},
|
||||||
|
"net/rpc": {},
|
||||||
|
"net/rpc/jsonrpc": {},
|
||||||
|
"net/smtp": {},
|
||||||
|
"net/testdata": {},
|
||||||
|
"net/textproto": {},
|
||||||
|
"net/url": {},
|
||||||
|
"os": {},
|
||||||
|
"os/exec": {},
|
||||||
|
"os/exec/internal": {},
|
||||||
|
"os/exec/internal/fdtest": {},
|
||||||
|
"os/signal": {},
|
||||||
|
"os/testdata": {},
|
||||||
|
"os/testdata/dirfs": {},
|
||||||
|
"os/testdata/dirfs/dir": {},
|
||||||
|
"os/testdata/issue37161": {},
|
||||||
|
"os/user": {},
|
||||||
|
"path": {},
|
||||||
|
"path/filepath": {},
|
||||||
|
"plugin": {},
|
||||||
|
"reflect": {},
|
||||||
|
"reflect/internal": {},
|
||||||
|
"reflect/internal/example1": {},
|
||||||
|
"reflect/internal/example2": {},
|
||||||
|
"regexp": {},
|
||||||
|
"regexp/syntax": {},
|
||||||
|
"regexp/testdata": {},
|
||||||
|
"runtime": {},
|
||||||
|
"runtime/asan": {},
|
||||||
|
"runtime/cgo": {},
|
||||||
|
"runtime/coverage": {},
|
||||||
|
"runtime/coverage/testdata": {},
|
||||||
|
"runtime/coverage/testdata/issue56006": {},
|
||||||
|
"runtime/coverage/testdata/issue59563": {},
|
||||||
|
"runtime/debug": {},
|
||||||
|
"runtime/debug/testdata": {},
|
||||||
|
"runtime/debug/testdata/fuzz": {},
|
||||||
|
"runtime/debug/testdata/fuzz/FuzzParseBuildInfoRoundTrip": {},
|
||||||
|
"runtime/internal": {},
|
||||||
|
"runtime/internal/atomic": {},
|
||||||
|
"runtime/internal/math": {},
|
||||||
|
"runtime/internal/startlinetest": {},
|
||||||
|
"runtime/internal/sys": {},
|
||||||
|
"runtime/internal/syscall": {},
|
||||||
|
"runtime/internal/wasitest": {},
|
||||||
|
"runtime/internal/wasitest/testdata": {},
|
||||||
|
"runtime/metrics": {},
|
||||||
|
"runtime/msan": {},
|
||||||
|
"runtime/pprof": {},
|
||||||
|
"runtime/pprof/testdata": {},
|
||||||
|
"runtime/pprof/testdata/mappingtest": {},
|
||||||
|
"runtime/race": {},
|
||||||
|
"runtime/race/internal": {},
|
||||||
|
"runtime/race/internal/amd64v1": {},
|
||||||
|
"runtime/race/internal/amd64v3": {},
|
||||||
|
"runtime/race/testdata": {},
|
||||||
|
"runtime/testdata": {},
|
||||||
|
"runtime/testdata/testexithooks": {},
|
||||||
|
"runtime/testdata/testfaketime": {},
|
||||||
|
"runtime/testdata/testfds": {},
|
||||||
|
"runtime/testdata/testprog": {},
|
||||||
|
"runtime/testdata/testprogcgo": {},
|
||||||
|
"runtime/testdata/testprogcgo/windows": {},
|
||||||
|
"runtime/testdata/testprognet": {},
|
||||||
|
"runtime/testdata/testsuid": {},
|
||||||
|
"runtime/testdata/testwinlib": {},
|
||||||
|
"runtime/testdata/testwinlibsignal": {},
|
||||||
|
"runtime/testdata/testwinlibthrow": {},
|
||||||
|
"runtime/testdata/testwinsignal": {},
|
||||||
|
"runtime/testdata/testwintls": {},
|
||||||
|
"runtime/trace": {},
|
||||||
|
"slices": {},
|
||||||
|
"sort": {},
|
||||||
|
"strconv": {},
|
||||||
|
"strconv/testdata": {},
|
||||||
|
"strings": {},
|
||||||
|
"sync": {},
|
||||||
|
"sync/atomic": {},
|
||||||
|
"syscall": {},
|
||||||
|
"syscall/js": {},
|
||||||
|
"testdata": {},
|
||||||
|
"testing": {},
|
||||||
|
"testing/fstest": {},
|
||||||
|
"testing/internal": {},
|
||||||
|
"testing/internal/testdeps": {},
|
||||||
|
"testing/iotest": {},
|
||||||
|
"testing/quick": {},
|
||||||
|
"testing/slogtest": {},
|
||||||
|
"text": {},
|
||||||
|
"text/scanner": {},
|
||||||
|
"text/tabwriter": {},
|
||||||
|
"text/template": {},
|
||||||
|
"text/template/parse": {},
|
||||||
|
"text/template/testdata": {},
|
||||||
|
"time": {},
|
||||||
|
"time/testdata": {},
|
||||||
|
"time/tzdata": {},
|
||||||
|
"unicode": {},
|
||||||
|
"unicode/utf16": {},
|
||||||
|
"unicode/utf8": {},
|
||||||
|
"unsafe": {},
|
||||||
|
"vendor": {},
|
||||||
|
"vendor/golang.org": {},
|
||||||
|
"vendor/golang.org/x": {},
|
||||||
|
"vendor/golang.org/x/crypto": {},
|
||||||
|
"vendor/golang.org/x/crypto/chacha20": {},
|
||||||
|
"vendor/golang.org/x/crypto/chacha20poly1305": {},
|
||||||
|
"vendor/golang.org/x/crypto/cryptobyte": {},
|
||||||
|
"vendor/golang.org/x/crypto/cryptobyte/asn1": {},
|
||||||
|
"vendor/golang.org/x/crypto/hkdf": {},
|
||||||
|
"vendor/golang.org/x/crypto/internal": {},
|
||||||
|
"vendor/golang.org/x/crypto/internal/alias": {},
|
||||||
|
"vendor/golang.org/x/crypto/internal/poly1305": {},
|
||||||
|
"vendor/golang.org/x/net": {},
|
||||||
|
"vendor/golang.org/x/net/dns": {},
|
||||||
|
"vendor/golang.org/x/net/dns/dnsmessage": {},
|
||||||
|
"vendor/golang.org/x/net/http": {},
|
||||||
|
"vendor/golang.org/x/net/http/httpguts": {},
|
||||||
|
"vendor/golang.org/x/net/http/httpproxy": {},
|
||||||
|
"vendor/golang.org/x/net/http2": {},
|
||||||
|
"vendor/golang.org/x/net/http2/hpack": {},
|
||||||
|
"vendor/golang.org/x/net/idna": {},
|
||||||
|
"vendor/golang.org/x/net/lif": {},
|
||||||
|
"vendor/golang.org/x/net/nettest": {},
|
||||||
|
"vendor/golang.org/x/net/route": {},
|
||||||
|
"vendor/golang.org/x/sys": {},
|
||||||
|
"vendor/golang.org/x/sys/cpu": {},
|
||||||
|
"vendor/golang.org/x/text": {},
|
||||||
|
"vendor/golang.org/x/text/secure": {},
|
||||||
|
"vendor/golang.org/x/text/secure/bidirule": {},
|
||||||
|
"vendor/golang.org/x/text/transform": {},
|
||||||
|
"vendor/golang.org/x/text/unicode": {},
|
||||||
|
"vendor/golang.org/x/text/unicode/bidi": {},
|
||||||
|
"vendor/golang.org/x/text/unicode/norm": {},
|
||||||
|
}
|
||||||
826
vendor/github.com/goretk/gore/type.go
generated
vendored
Normal file
826
vendor/github.com/goretk/gore/type.go
generated
vendored
Normal file
@ -0,0 +1,826 @@
|
|||||||
|
// This file is part of GoRE.
|
||||||
|
//
|
||||||
|
// Copyright (C) 2019-2021 GoRE Authors
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU Affero General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Affero General Public License
|
||||||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
package gore
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/binary"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"reflect"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
intSize32 = 4
|
||||||
|
intSize64 = intSize32 * 2
|
||||||
|
kindMask = (1 << 5) - 1
|
||||||
|
tflagExtraStar uint8 = 1 << 1
|
||||||
|
tflagUncommon uint8 = 1 << 0
|
||||||
|
)
|
||||||
|
|
||||||
|
type _typeField uint8
|
||||||
|
|
||||||
|
const (
|
||||||
|
_typeFieldSize = iota
|
||||||
|
_typeFieldKind
|
||||||
|
_typeFieldStr
|
||||||
|
_typeFieldFlag
|
||||||
|
_typeFieldEnd
|
||||||
|
)
|
||||||
|
|
||||||
|
// ChanDir is a channel direction.
|
||||||
|
type ChanDir int
|
||||||
|
|
||||||
|
const (
|
||||||
|
// ChanRecv is a receive only chan (<-chan)
|
||||||
|
ChanRecv ChanDir = 1 << iota
|
||||||
|
// ChanSend is a send only chan (chan<-)
|
||||||
|
ChanSend
|
||||||
|
// ChanBoth is a send and receive chan (chan)
|
||||||
|
ChanBoth = ChanRecv | ChanSend
|
||||||
|
)
|
||||||
|
|
||||||
|
func getTypes(fileInfo *FileInfo, f fileHandler) (map[uint64]*GoType, error) {
|
||||||
|
if GoVersionCompare(fileInfo.goversion.Name, "go1.7beta1") < 0 {
|
||||||
|
return getLegacyTypes(fileInfo, f)
|
||||||
|
}
|
||||||
|
|
||||||
|
md, err := parseModuledata(fileInfo, f)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to parse the module data: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
types, err := md.Types().Data()
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to get types data section: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
typeLink, err := md.TypeLink()
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to get type link data: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// New parser
|
||||||
|
parser := newTypeParser(types, md.Types().Address, fileInfo)
|
||||||
|
for _, off := range typeLink {
|
||||||
|
typ, err := parser.parseType(uint64(off) + parser.base)
|
||||||
|
if err != nil || typ == nil {
|
||||||
|
return nil, fmt.Errorf("failed to parse type at offset 0x%x: %w", off, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return parser.parsedTypes(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func getLegacyTypes(fileInfo *FileInfo, f fileHandler) (map[uint64]*GoType, error) {
|
||||||
|
md, err := parseModuledata(fileInfo, f)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
typelinkAddr, typelinkData, err := f.getSectionDataFromOffset(md.TypelinkAddr)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("no typelink section found: %w", err)
|
||||||
|
}
|
||||||
|
r := bytes.NewReader(typelinkData)
|
||||||
|
_, err = r.Seek(int64(md.TypelinkAddr)-int64(typelinkAddr), io.SeekStart)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
goTypes := make(map[uint64]*GoType)
|
||||||
|
for i := uint64(0); i < md.TypelinkLen; i++ {
|
||||||
|
// Type offsets are always *_type
|
||||||
|
off, err := readUIntTo64(r, fileInfo.ByteOrder, fileInfo.WordSize == intSize32)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
baseAddr, baseData, err := f.getSectionDataFromOffset(off)
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
typ := typeParse(goTypes, fileInfo, off-baseAddr, baseData, baseAddr)
|
||||||
|
if typ == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return goTypes, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GoType is a representation of all types in Go.
|
||||||
|
type GoType struct {
|
||||||
|
// Kind indicates the specific kind of type the GoType
|
||||||
|
Kind reflect.Kind
|
||||||
|
// Name is the name of the type.
|
||||||
|
Name string
|
||||||
|
// Addr is the virtual address to where the type struct is defined.
|
||||||
|
Addr uint64
|
||||||
|
// PtrResolvAddr is the address to where the resolved structure is located
|
||||||
|
// if the GoType is of pointer kind.
|
||||||
|
PtrResolvAddr uint64
|
||||||
|
// PackagePath is the name of the package import path for the GoType.
|
||||||
|
PackagePath string
|
||||||
|
// Fields is a slice of the struct fields if the GoType is of kind struct.
|
||||||
|
Fields []*GoType
|
||||||
|
// FieldName is the name of the field if the GoType is a struct field.
|
||||||
|
FieldName string
|
||||||
|
// FieldTag holds the extracted tag for the field.
|
||||||
|
FieldTag string
|
||||||
|
// FieldAnon is true if the field does not have a name and is an embedded type.
|
||||||
|
FieldAnon bool
|
||||||
|
// Element is the element type for arrays, slices channels or the resolved type for
|
||||||
|
// a pointer type. For example int if the slice is a []int.
|
||||||
|
Element *GoType
|
||||||
|
// Length is the array or slice length.
|
||||||
|
Length int
|
||||||
|
// ChanDir is the channel direction
|
||||||
|
ChanDir ChanDir
|
||||||
|
// Key is the key type for a map.
|
||||||
|
Key *GoType
|
||||||
|
// FuncArgs holds the argument types for the function if the type is a function kind.
|
||||||
|
FuncArgs []*GoType
|
||||||
|
// FuncReturnVals holds the return types for the function if the type is a function kind.
|
||||||
|
FuncReturnVals []*GoType
|
||||||
|
// IsVariadic is true if the last argument type is variadic. For example "func(s string, n ...int)"
|
||||||
|
IsVariadic bool
|
||||||
|
// Methods holds information of the types methods.
|
||||||
|
Methods []*TypeMethod
|
||||||
|
flag uint8
|
||||||
|
}
|
||||||
|
|
||||||
|
// String implements the fmt.Stringer interface.
|
||||||
|
func (t *GoType) String() string {
|
||||||
|
switch t.Kind {
|
||||||
|
case reflect.Slice:
|
||||||
|
return fmt.Sprintf("[]%s", t.Element)
|
||||||
|
case reflect.Array:
|
||||||
|
return fmt.Sprintf("[%d]%s", t.Length, t.Element)
|
||||||
|
case reflect.Map:
|
||||||
|
return fmt.Sprintf("map[%s]%s", t.Key, t.Element)
|
||||||
|
case reflect.Struct:
|
||||||
|
// Handle empty struct type
|
||||||
|
if t.Name == "" {
|
||||||
|
return "struct{}"
|
||||||
|
}
|
||||||
|
return t.Name
|
||||||
|
case reflect.Ptr:
|
||||||
|
return fmt.Sprintf("*%s", t.Element)
|
||||||
|
case reflect.Chan:
|
||||||
|
if t.ChanDir == ChanRecv {
|
||||||
|
return fmt.Sprintf("<-chan %s", t.Element)
|
||||||
|
}
|
||||||
|
if t.ChanDir == ChanSend {
|
||||||
|
return fmt.Sprintf("chan<- %s", t.Element)
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("chan %s", t.Element)
|
||||||
|
case reflect.Func:
|
||||||
|
buf := "func("
|
||||||
|
for i, a := range t.FuncArgs {
|
||||||
|
if i != 0 {
|
||||||
|
buf += ", "
|
||||||
|
}
|
||||||
|
if a.Kind == reflect.Func && a.Name == t.Name {
|
||||||
|
buf += a.Name
|
||||||
|
} else {
|
||||||
|
buf += a.String()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(t.FuncReturnVals) > 1 {
|
||||||
|
buf += ") ("
|
||||||
|
} else if len(t.FuncReturnVals) == 1 {
|
||||||
|
buf += ") "
|
||||||
|
} else {
|
||||||
|
buf += ")"
|
||||||
|
}
|
||||||
|
for i, r := range t.FuncReturnVals {
|
||||||
|
if i != 0 {
|
||||||
|
buf += ", "
|
||||||
|
}
|
||||||
|
if r.Kind == reflect.Func && r.Name == t.Name {
|
||||||
|
buf += r.Name
|
||||||
|
} else {
|
||||||
|
buf += r.String()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(t.FuncReturnVals) > 1 {
|
||||||
|
buf += ")"
|
||||||
|
}
|
||||||
|
return buf
|
||||||
|
case reflect.Interface:
|
||||||
|
// Handle empty interface
|
||||||
|
if t.Name == "" {
|
||||||
|
return "interface{}"
|
||||||
|
}
|
||||||
|
return t.Name
|
||||||
|
case reflect.Invalid:
|
||||||
|
return t.Name
|
||||||
|
default:
|
||||||
|
return t.Kind.String()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// StructDef reconstructs the type definition code for the struct.
|
||||||
|
// If the type is not a struct, an empty string is returned.
|
||||||
|
func StructDef(typ *GoType) string {
|
||||||
|
if typ.Kind != reflect.Struct {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
buf := fmt.Sprintf("type %s struct{", typ.Name)
|
||||||
|
for _, f := range typ.Fields {
|
||||||
|
if f.FieldAnon {
|
||||||
|
buf += fmt.Sprintf("\n\t%s", f)
|
||||||
|
} else {
|
||||||
|
buf += fmt.Sprintf("\n\t%s %s", f.FieldName, f)
|
||||||
|
}
|
||||||
|
if f.FieldTag != "" {
|
||||||
|
buf += "\t`" + f.FieldTag + "`"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(typ.Fields) > 0 {
|
||||||
|
buf += "\n"
|
||||||
|
}
|
||||||
|
return buf + "}"
|
||||||
|
}
|
||||||
|
|
||||||
|
// InterfaceDef reconstructs the type definition code for the interface.
|
||||||
|
// If the type is not an interface, an empty string is returned.
|
||||||
|
func InterfaceDef(typ *GoType) string {
|
||||||
|
if typ.Kind != reflect.Interface {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
// Handle interface with no methods defined.
|
||||||
|
if len(typ.Methods) == 0 {
|
||||||
|
return "type " + typ.Name + " interface{}"
|
||||||
|
}
|
||||||
|
// Remove package from name.
|
||||||
|
buf := fmt.Sprintf("type %s interface {", typ.Name)
|
||||||
|
for _, m := range typ.Methods {
|
||||||
|
buf += fmt.Sprintf("\n\t%s%s", m.Name, m.Type.String()[4:])
|
||||||
|
}
|
||||||
|
return buf + "\n}"
|
||||||
|
}
|
||||||
|
|
||||||
|
// MethodDef constructs a string summary of all methods for the type.
|
||||||
|
// If type information exists for the methods, it is used to determine function parameters.
|
||||||
|
// If the type does not have any methods, an empty string is returned.
|
||||||
|
func MethodDef(typ *GoType) string {
|
||||||
|
if len(typ.Methods) == 0 {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
var buf string
|
||||||
|
for i, m := range typ.Methods {
|
||||||
|
if i > 0 {
|
||||||
|
buf += "\n"
|
||||||
|
}
|
||||||
|
if m.Type != nil {
|
||||||
|
buf += fmt.Sprintf("func (%s) %s%s", typ.Name, m.Name, m.Type.String()[4:])
|
||||||
|
} else {
|
||||||
|
buf += fmt.Sprintf("func (%s) %s()", typ.Name, m.Name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return buf
|
||||||
|
}
|
||||||
|
|
||||||
|
// TypeMethod is description of a method owned by the GoType.
|
||||||
|
type TypeMethod struct {
|
||||||
|
// Name is the string name for the method.
|
||||||
|
Name string
|
||||||
|
// Type is the specific function type for the method.
|
||||||
|
// This can be nil. If it is nil, the method is not part of an
|
||||||
|
// implementation of a interface or it is not exported.
|
||||||
|
Type *GoType
|
||||||
|
// IfaceCallOffset is the offset from the beginning of the .text section
|
||||||
|
// where the function code starts. According to code comments in the
|
||||||
|
// standard library, it is used for interface calls.
|
||||||
|
// Can be 0 if the code is not called in the binary and was optimized out
|
||||||
|
// by the compiler or linker.
|
||||||
|
IfaceCallOffset uint64
|
||||||
|
// FuncCallOffset is the offset from the beginning of the .text section
|
||||||
|
// where the function code starts. According to code comments in the
|
||||||
|
// standard library, it is used for normal method calls.
|
||||||
|
// Can be 0 if the code is not called in the binary and was optimized out
|
||||||
|
// by the compiler or linker.
|
||||||
|
FuncCallOffset uint64
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Size: 32 or 48
|
||||||
|
type _type struct {
|
||||||
|
size uintptr 4 or 8
|
||||||
|
ptrdata uintptr 4 or 8
|
||||||
|
hash uint32 4
|
||||||
|
tflag tflag 1
|
||||||
|
align uint8 1
|
||||||
|
fieldalign uint8 1
|
||||||
|
kind uint8 1
|
||||||
|
alg *typeAlg 4 or 8
|
||||||
|
gcdata *byte 4 or 8
|
||||||
|
str nameOff 4
|
||||||
|
ptrToThis typeOff 4
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
func typeParse(types map[uint64]*GoType, fileInfo *FileInfo, offset uint64, sectionData []byte, sectionBaseAddr uint64) *GoType {
|
||||||
|
typ, ok := types[offset+sectionBaseAddr]
|
||||||
|
if ok {
|
||||||
|
return typ
|
||||||
|
}
|
||||||
|
typ = new(GoType)
|
||||||
|
// XXX: This is to catch bad parsing. The current parser does not handle
|
||||||
|
// uncommon functions correctly. This ensures an out of bounds read does
|
||||||
|
// not occur.
|
||||||
|
if offset > uint64(len(sectionData)) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
r := bytes.NewReader(sectionData[offset:])
|
||||||
|
|
||||||
|
// Parse size
|
||||||
|
off := typeOffset(fileInfo, _typeFieldSize)
|
||||||
|
r.Seek(off, io.SeekStart)
|
||||||
|
_, err := readUIntTo64(r, fileInfo.ByteOrder, fileInfo.WordSize == intSize32)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse kind
|
||||||
|
off = typeOffset(fileInfo, _typeFieldKind)
|
||||||
|
// Defined as uint8
|
||||||
|
var k uint8
|
||||||
|
r.Seek(off, io.SeekStart)
|
||||||
|
binary.Read(r, fileInfo.ByteOrder, &k)
|
||||||
|
typ.Kind = reflect.Kind(k & kindMask)
|
||||||
|
|
||||||
|
// Parse flag
|
||||||
|
off = typeOffset(fileInfo, _typeFieldFlag)
|
||||||
|
// Defined as uint8
|
||||||
|
var f uint8
|
||||||
|
r.Seek(off, io.SeekStart)
|
||||||
|
binary.Read(r, fileInfo.ByteOrder, &f)
|
||||||
|
typ.flag = f
|
||||||
|
|
||||||
|
// Parse nameOff
|
||||||
|
off = typeOffset(fileInfo, _typeFieldStr)
|
||||||
|
r.Seek(off, io.SeekStart)
|
||||||
|
ptrN, err := readUIntTo64(r, fileInfo.ByteOrder, fileInfo.WordSize == intSize32)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if ptrN != 0 {
|
||||||
|
typ.Name = parseString(fileInfo, ptrN, sectionBaseAddr, sectionData)
|
||||||
|
}
|
||||||
|
|
||||||
|
typ.Addr = offset + sectionBaseAddr
|
||||||
|
types[typ.Addr] = typ
|
||||||
|
|
||||||
|
// Legacy types has a field with a pointer to the uncommonType.
|
||||||
|
// The flags location is unused, hence 0, so the parsing of the uncommonType
|
||||||
|
// is skipped below. So instead, if the binary uses legacy types parse it now.
|
||||||
|
// Pointer is right after the string pointer.
|
||||||
|
off = typeOffset(fileInfo, _typeFieldStr) + int64(fileInfo.WordSize)
|
||||||
|
r.Seek(off, io.SeekStart)
|
||||||
|
ptr, err := readUIntTo64(r, fileInfo.ByteOrder, fileInfo.WordSize == intSize32)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if ptr != 0 {
|
||||||
|
// Since we don't know if the struct is located before or after this type,
|
||||||
|
// create a new reader.
|
||||||
|
ur := bytes.NewReader(sectionData)
|
||||||
|
ur.Seek(int64(ptr-sectionBaseAddr), io.SeekStart)
|
||||||
|
parseUncommonType(typ, ur, fileInfo, sectionData, sectionBaseAddr, types)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse extra fields
|
||||||
|
off = typeOffset(fileInfo, _typeFieldEnd)
|
||||||
|
r.Seek(off, io.SeekStart)
|
||||||
|
switch typ.Kind {
|
||||||
|
|
||||||
|
case reflect.Ptr:
|
||||||
|
ptr, err := readUIntTo64(r, fileInfo.ByteOrder, fileInfo.WordSize == intSize32)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
typ.PtrResolvAddr = ptr
|
||||||
|
if ptr != 0 {
|
||||||
|
c := typeParse(types, fileInfo, ptr-sectionBaseAddr, sectionData, sectionBaseAddr)
|
||||||
|
typ.Element = c
|
||||||
|
}
|
||||||
|
|
||||||
|
case reflect.Struct:
|
||||||
|
|
||||||
|
// Parse struct fields
|
||||||
|
fieldptr, err := readUIntTo64(r, fileInfo.ByteOrder, fileInfo.WordSize == intSize32)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
numfield, err := readUIntTo64(r, fileInfo.ByteOrder, fileInfo.WordSize == intSize32)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
// Eat cap
|
||||||
|
_, err = readUIntTo64(r, fileInfo.ByteOrder, fileInfo.WordSize == intSize32)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse methods
|
||||||
|
if typ.flag&tflagUncommon != 0 {
|
||||||
|
parseUncommonType(typ, r, fileInfo, sectionData, sectionBaseAddr, types)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse fields
|
||||||
|
typ.Fields = make([]*GoType, numfield)
|
||||||
|
secR := bytes.NewReader(sectionData)
|
||||||
|
for i := 0; i < int(numfield); i++ {
|
||||||
|
var fieldName string
|
||||||
|
var tag string
|
||||||
|
o := int64(fieldptr + uint64(i*5*fileInfo.WordSize) - sectionBaseAddr)
|
||||||
|
secR.Seek(o, io.SeekStart)
|
||||||
|
nptr, err := readUIntTo64(secR, fileInfo.ByteOrder, fileInfo.WordSize == intSize32)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
ppp, err := readUIntTo64(secR, fileInfo.ByteOrder, fileInfo.WordSize == intSize32)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if ppp != 0 {
|
||||||
|
pps := parseString(fileInfo, ppp, sectionBaseAddr, sectionData)
|
||||||
|
if pps != "" {
|
||||||
|
typ.PackagePath = pps
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tptr, err := readUIntTo64(secR, fileInfo.ByteOrder, fileInfo.WordSize == intSize32)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
tagptr, err := readUIntTo64(secR, fileInfo.ByteOrder, fileInfo.WordSize == intSize32)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if tagptr != 0 {
|
||||||
|
tag = parseString(fileInfo, tagptr, sectionBaseAddr, sectionData)
|
||||||
|
}
|
||||||
|
uptr, err := readUIntTo64(secR, fileInfo.ByteOrder, fileInfo.WordSize == intSize32)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
gt := typeParse(types, fileInfo, tptr-sectionBaseAddr, sectionData, sectionBaseAddr)
|
||||||
|
// Make a copy
|
||||||
|
field := *gt
|
||||||
|
|
||||||
|
fieldName = parseString(fileInfo, nptr, sectionBaseAddr, sectionData)
|
||||||
|
field.FieldName = fieldName
|
||||||
|
if tag != "" {
|
||||||
|
field.FieldTag = tag
|
||||||
|
}
|
||||||
|
// Older versions has no field name for anonymous fields. New versions
|
||||||
|
// uses a bit flag on the offset.
|
||||||
|
field.FieldAnon = fieldName == "" || uptr&1 != 0
|
||||||
|
typ.Fields[i] = &field
|
||||||
|
}
|
||||||
|
case reflect.Array:
|
||||||
|
|
||||||
|
elementAddr, err := readUIntTo64(r, fileInfo.ByteOrder, fileInfo.WordSize == intSize32)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if elementAddr != 0 {
|
||||||
|
e := typeParse(types, fileInfo, elementAddr-sectionBaseAddr, sectionData, sectionBaseAddr)
|
||||||
|
typ.Element = e
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read and skip slice type
|
||||||
|
_, err = readUIntTo64(r, fileInfo.ByteOrder, fileInfo.WordSize == intSize32)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read length
|
||||||
|
l, err := readUIntTo64(r, fileInfo.ByteOrder, fileInfo.WordSize == intSize32)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
typ.Length = int(l)
|
||||||
|
|
||||||
|
case reflect.Slice:
|
||||||
|
|
||||||
|
elementAddr, err := readUIntTo64(r, fileInfo.ByteOrder, fileInfo.WordSize == intSize32)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if elementAddr != 0 {
|
||||||
|
e := typeParse(types, fileInfo, elementAddr-sectionBaseAddr, sectionData, sectionBaseAddr)
|
||||||
|
typ.Element = e
|
||||||
|
}
|
||||||
|
|
||||||
|
case reflect.Chan:
|
||||||
|
|
||||||
|
elementAddr, err := readUIntTo64(r, fileInfo.ByteOrder, fileInfo.WordSize == intSize32)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if elementAddr != 0 {
|
||||||
|
e := typeParse(types, fileInfo, elementAddr-sectionBaseAddr, sectionData, sectionBaseAddr)
|
||||||
|
typ.Element = e
|
||||||
|
}
|
||||||
|
|
||||||
|
// Direction
|
||||||
|
d, err := readUIntTo64(r, fileInfo.ByteOrder, fileInfo.WordSize == intSize32)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
typ.ChanDir = ChanDir(int(d))
|
||||||
|
|
||||||
|
case reflect.Map:
|
||||||
|
|
||||||
|
keyAddr, err := readUIntTo64(r, fileInfo.ByteOrder, fileInfo.WordSize == intSize32)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if keyAddr != 0 {
|
||||||
|
k := typeParse(types, fileInfo, keyAddr-sectionBaseAddr, sectionData, sectionBaseAddr)
|
||||||
|
typ.Key = k
|
||||||
|
}
|
||||||
|
|
||||||
|
elementAddr, err := readUIntTo64(r, fileInfo.ByteOrder, fileInfo.WordSize == intSize32)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if elementAddr != 0 {
|
||||||
|
e := typeParse(types, fileInfo, elementAddr-sectionBaseAddr, sectionData, sectionBaseAddr)
|
||||||
|
typ.Element = e
|
||||||
|
}
|
||||||
|
|
||||||
|
case reflect.Func:
|
||||||
|
|
||||||
|
// bool plus padding.
|
||||||
|
dotdotdot, err := readUIntTo64(r, fileInfo.ByteOrder, fileInfo.WordSize == intSize32)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
typ.IsVariadic = dotdotdot > uint64(0)
|
||||||
|
// One for args and one for returns
|
||||||
|
rtypes := make([]uint64, 2)
|
||||||
|
typelens := make([]uint64, 2)
|
||||||
|
for i := 0; i < 2; i++ {
|
||||||
|
p, err := readUIntTo64(r, fileInfo.ByteOrder, fileInfo.WordSize == intSize32)
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
rtypes[i] = p
|
||||||
|
l, err := readUIntTo64(r, fileInfo.ByteOrder, fileInfo.WordSize == intSize32)
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
typelens[i] = l
|
||||||
|
|
||||||
|
// Eat cap
|
||||||
|
_, err = readUIntTo64(r, fileInfo.ByteOrder, fileInfo.WordSize == intSize32)
|
||||||
|
if err != nil {
|
||||||
|
println("Error when reading padding:", err)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Full section reader
|
||||||
|
sr := bytes.NewReader(sectionData)
|
||||||
|
// Parse the arg types and result types.
|
||||||
|
for i := 0; i < 2; i++ {
|
||||||
|
if rtypes[i] == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
_, err = sr.Seek(int64(rtypes[i]-sectionBaseAddr), io.SeekStart)
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
for j := 0; j < int(typelens[i]); j++ {
|
||||||
|
p, err := readUIntTo64(sr, fileInfo.ByteOrder, fileInfo.WordSize == intSize32)
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if p == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
t := typeParse(types, fileInfo, p-sectionBaseAddr, sectionData, sectionBaseAddr)
|
||||||
|
if i == 0 {
|
||||||
|
typ.FuncArgs = append(typ.FuncArgs, t)
|
||||||
|
} else {
|
||||||
|
typ.FuncReturnVals = append(typ.FuncReturnVals, t)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
case reflect.Interface:
|
||||||
|
|
||||||
|
ptrMethods, err := readUIntTo64(r, fileInfo.ByteOrder, fileInfo.WordSize == intSize32)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
numMethods, err := readUIntTo64(r, fileInfo.ByteOrder, fileInfo.WordSize == intSize32)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
// Eat cap
|
||||||
|
_, err = readUIntTo64(r, fileInfo.ByteOrder, fileInfo.WordSize == intSize32)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse imethods
|
||||||
|
secR := bytes.NewReader(sectionData)
|
||||||
|
imethSize := uint64(2 * intSize32)
|
||||||
|
int32ptr := true
|
||||||
|
if GoVersionCompare(fileInfo.goversion.Name, "go1.7beta1") < 0 {
|
||||||
|
imethSize = uint64(3 * fileInfo.WordSize)
|
||||||
|
int32ptr = fileInfo.WordSize == intSize32
|
||||||
|
}
|
||||||
|
for i := 0; i < int(numMethods); i++ {
|
||||||
|
meth := new(TypeMethod)
|
||||||
|
// All fields has the size of int32
|
||||||
|
secR.Seek(int64(ptrMethods+uint64(i)*imethSize-sectionBaseAddr), io.SeekStart)
|
||||||
|
nameOff, err := readUIntTo64(secR, fileInfo.ByteOrder, int32ptr)
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if nameOff != 0 {
|
||||||
|
meth.Name = parseString(fileInfo, nameOff, sectionBaseAddr, sectionData)
|
||||||
|
}
|
||||||
|
|
||||||
|
pkgPathPtr, err := readUIntTo64(secR, fileInfo.ByteOrder, int32ptr)
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if pkgPathPtr != 0 {
|
||||||
|
pkgPathStr := parseString(fileInfo, pkgPathPtr, sectionBaseAddr, sectionData)
|
||||||
|
if pkgPathStr != "" {
|
||||||
|
typ.PackagePath = pkgPathStr
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
typeOff, err := readUIntTo64(secR, fileInfo.ByteOrder, int32ptr)
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if typeOff != 0 {
|
||||||
|
typeOff = typeOff - sectionBaseAddr
|
||||||
|
meth.Type = typeParse(types, fileInfo, typeOff, sectionData, sectionBaseAddr)
|
||||||
|
}
|
||||||
|
typ.Methods = append(typ.Methods, meth)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return typ
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseString(fileInfo *FileInfo, off, base uint64, baseData []byte) string {
|
||||||
|
if off == 0 {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
r := bytes.NewReader(baseData)
|
||||||
|
r.Seek(int64(off-base), io.SeekStart)
|
||||||
|
h, err := readUIntTo64(r, fileInfo.ByteOrder, fileInfo.WordSize == intSize32)
|
||||||
|
if err != nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
l, err := readUIntTo64(r, fileInfo.ByteOrder, fileInfo.WordSize == intSize32)
|
||||||
|
if err != nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
if h == 0 || l == 0 {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
str := string(baseData[h-base : h-base+l])
|
||||||
|
return str
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseUncommonType(typ *GoType, r *bytes.Reader, fileInfo *FileInfo, sectionData []byte, sectionBaseAddr uint64, types map[uint64]*GoType) {
|
||||||
|
pname, err := readUIntTo64(r, fileInfo.ByteOrder, fileInfo.WordSize == intSize32)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if pname != 0 {
|
||||||
|
n := parseString(fileInfo, pname, sectionBaseAddr, sectionData)
|
||||||
|
if typ.Name == "" && n != "" {
|
||||||
|
typ.Name = n
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ppkg, err := readUIntTo64(r, fileInfo.ByteOrder, fileInfo.WordSize == intSize32)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if ppkg != 0 {
|
||||||
|
p := parseString(fileInfo, ppkg, sectionBaseAddr, sectionData)
|
||||||
|
if typ.PackagePath == "" && p != "" {
|
||||||
|
typ.PackagePath = p
|
||||||
|
}
|
||||||
|
}
|
||||||
|
typ.Methods = parseMethods(r, fileInfo, sectionData, sectionBaseAddr, types)
|
||||||
|
}
|
||||||
|
|
||||||
|
// The methods must start at the readers current location.
|
||||||
|
func parseMethods(r *bytes.Reader, fileInfo *FileInfo, sectionData []byte, sectionBaseAddr uint64, types map[uint64]*GoType) []*TypeMethod {
|
||||||
|
pdata, err := readUIntTo64(r, fileInfo.ByteOrder, fileInfo.WordSize == intSize32)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
numMeth, err := readUIntTo64(r, fileInfo.ByteOrder, fileInfo.WordSize == intSize32)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
methods := make([]*TypeMethod, numMeth)
|
||||||
|
r.Seek(int64(pdata-sectionBaseAddr), io.SeekStart)
|
||||||
|
for i := 0; i < int(numMeth); i++ {
|
||||||
|
m := &TypeMethod{}
|
||||||
|
p, err := readUIntTo64(r, fileInfo.ByteOrder, fileInfo.WordSize == intSize32)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
m.Name = parseString(fileInfo, p, sectionBaseAddr, sectionData)
|
||||||
|
|
||||||
|
// Eat package path
|
||||||
|
_, err = readUIntTo64(r, fileInfo.ByteOrder, fileInfo.WordSize == intSize32)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// mtyp
|
||||||
|
mtype, err := readUIntTo64(r, fileInfo.ByteOrder, fileInfo.WordSize == intSize32)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if mtype != 0 {
|
||||||
|
m.Type = typeParse(types, fileInfo, mtype-sectionBaseAddr, sectionData, sectionBaseAddr)
|
||||||
|
}
|
||||||
|
|
||||||
|
// typ
|
||||||
|
p, err = readUIntTo64(r, fileInfo.ByteOrder, fileInfo.WordSize == intSize32)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if p != 0 {
|
||||||
|
// Parse it so we capture it in the global type list.
|
||||||
|
typeParse(types, fileInfo, p-sectionBaseAddr, sectionData, sectionBaseAddr)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ifn
|
||||||
|
ifn, err := readUIntTo64(r, fileInfo.ByteOrder, fileInfo.WordSize == intSize32)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
m.IfaceCallOffset = ifn
|
||||||
|
|
||||||
|
// tfn
|
||||||
|
tfn, err := readUIntTo64(r, fileInfo.ByteOrder, fileInfo.WordSize == intSize32)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
m.FuncCallOffset = tfn
|
||||||
|
methods[i] = m
|
||||||
|
}
|
||||||
|
return methods
|
||||||
|
}
|
||||||
|
|
||||||
|
func typeOffset(fileInfo *FileInfo, field _typeField) int64 {
|
||||||
|
intSize := intSize64
|
||||||
|
if fileInfo.WordSize == intSize32 {
|
||||||
|
intSize = intSize32
|
||||||
|
}
|
||||||
|
if field == _typeFieldSize {
|
||||||
|
return int64(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
if field == _typeFieldKind {
|
||||||
|
return int64(2*intSize + 4 + 3)
|
||||||
|
}
|
||||||
|
|
||||||
|
if field == _typeFieldStr {
|
||||||
|
return int64(4*intSize + 4 + 4)
|
||||||
|
}
|
||||||
|
|
||||||
|
if field == _typeFieldFlag {
|
||||||
|
return int64(2*intSize + 4)
|
||||||
|
}
|
||||||
|
|
||||||
|
if field == _typeFieldEnd {
|
||||||
|
if GoVersionCompare(fileInfo.goversion.Name, "go1.6beta1") < 0 {
|
||||||
|
return int64(8*intSize + 8)
|
||||||
|
}
|
||||||
|
if GoVersionCompare(fileInfo.goversion.Name, "go1.7beta1") < 0 {
|
||||||
|
return int64(7*intSize + 8)
|
||||||
|
}
|
||||||
|
return int64(4*intSize + 16)
|
||||||
|
}
|
||||||
|
return int64(-1)
|
||||||
|
}
|
||||||
1248
vendor/github.com/goretk/gore/type2.go
generated
vendored
Normal file
1248
vendor/github.com/goretk/gore/type2.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
9
vendor/modules.txt
vendored
9
vendor/modules.txt
vendored
@ -30,6 +30,9 @@ github.com/go-delve/liner
|
|||||||
# github.com/google/go-dap v0.11.0
|
# github.com/google/go-dap v0.11.0
|
||||||
## explicit; go 1.13
|
## explicit; go 1.13
|
||||||
github.com/google/go-dap
|
github.com/google/go-dap
|
||||||
|
# github.com/goretk/gore v0.11.3
|
||||||
|
## explicit; go 1.21
|
||||||
|
github.com/goretk/gore
|
||||||
# github.com/hashicorp/golang-lru v1.0.2
|
# github.com/hashicorp/golang-lru v1.0.2
|
||||||
## explicit; go 1.12
|
## explicit; go 1.12
|
||||||
github.com/hashicorp/golang-lru/simplelru
|
github.com/hashicorp/golang-lru/simplelru
|
||||||
@ -70,8 +73,8 @@ go.starlark.net/resolve
|
|||||||
go.starlark.net/starlark
|
go.starlark.net/starlark
|
||||||
go.starlark.net/starlarkstruct
|
go.starlark.net/starlarkstruct
|
||||||
go.starlark.net/syntax
|
go.starlark.net/syntax
|
||||||
# golang.org/x/arch v0.5.0
|
# golang.org/x/arch v0.6.0
|
||||||
## explicit; go 1.17
|
## explicit; go 1.18
|
||||||
golang.org/x/arch/arm64/arm64asm
|
golang.org/x/arch/arm64/arm64asm
|
||||||
golang.org/x/arch/ppc64/ppc64asm
|
golang.org/x/arch/ppc64/ppc64asm
|
||||||
golang.org/x/arch/x86/x86asm
|
golang.org/x/arch/x86/x86asm
|
||||||
@ -80,7 +83,7 @@ golang.org/x/arch/x86/x86asm
|
|||||||
golang.org/x/exp/constraints
|
golang.org/x/exp/constraints
|
||||||
golang.org/x/exp/maps
|
golang.org/x/exp/maps
|
||||||
golang.org/x/exp/slices
|
golang.org/x/exp/slices
|
||||||
# golang.org/x/mod v0.13.0
|
# golang.org/x/mod v0.14.0
|
||||||
## explicit; go 1.18
|
## explicit; go 1.18
|
||||||
golang.org/x/mod/semver
|
golang.org/x/mod/semver
|
||||||
# golang.org/x/sys v0.13.0
|
# golang.org/x/sys v0.13.0
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user