mirror of
https://github.com/beego/bee.git
synced 2025-04-23 12:56:50 +00:00
fix: Fix github.com/go-delve/delve import error and add go mod
This commit is contained in:
parent
6a86284cec
commit
b1dbdd023c
1
.gitignore
vendored
1
.gitignore
vendored
@ -30,3 +30,4 @@ _testmain.go
|
||||
bee
|
||||
*.exe~
|
||||
.goxc.local.json
|
||||
vendor
|
||||
|
@ -28,10 +28,10 @@ import (
|
||||
"github.com/beego/bee/cmd/commands/version"
|
||||
beeLogger "github.com/beego/bee/logger"
|
||||
"github.com/beego/bee/utils"
|
||||
"github.com/derekparker/delve/service"
|
||||
"github.com/derekparker/delve/service/rpc2"
|
||||
"github.com/derekparker/delve/service/rpccommon"
|
||||
"github.com/derekparker/delve/terminal"
|
||||
"github.com/go-delve/delve/service"
|
||||
"github.com/go-delve/delve/service/rpc2"
|
||||
"github.com/go-delve/delve/service/rpccommon"
|
||||
"github.com/go-delve/delve/pkg/terminal"
|
||||
"github.com/fsnotify/fsnotify"
|
||||
)
|
||||
|
||||
@ -43,7 +43,7 @@ var cmdDlv = &commands.Command{
|
||||
|
||||
To debug your application using Delve, use: {{"$ bee dlv" | bold}}
|
||||
|
||||
For more information on Delve: https://github.com/derekparker/delve
|
||||
For more information on Delve: https://github.com/go-delve/delve
|
||||
`,
|
||||
PreRun: func(cmd *commands.Command, args []string) { version.ShowShortVersionBanner() },
|
||||
Run: runDlv,
|
||||
@ -152,7 +152,7 @@ func startDelveDebugger(addr string, ch chan int) int {
|
||||
APIVersion: 2,
|
||||
WorkingDir: ".",
|
||||
ProcessArgs: []string{abs},
|
||||
}, false)
|
||||
})
|
||||
if err := server.Run(); err != nil {
|
||||
beeLogger.Log.Fatalf("Could not start debugger server: %v", err)
|
||||
}
|
||||
@ -182,7 +182,7 @@ func startDelveDebugger(addr string, ch chan int) int {
|
||||
}
|
||||
|
||||
// Stop and kill the debugger server once user quits the REPL
|
||||
if err := server.Stop(true); err != nil {
|
||||
if err := server.Stop(); err != nil {
|
||||
beeLogger.Log.Fatalf("Could not stop Delve server: %v", err)
|
||||
}
|
||||
return status
|
||||
|
13
go.mod
Normal file
13
go.mod
Normal file
@ -0,0 +1,13 @@
|
||||
module github.com/beego/bee
|
||||
|
||||
go 1.14
|
||||
|
||||
require (
|
||||
github.com/astaxie/beego v1.12.1
|
||||
github.com/fsnotify/fsnotify v1.4.9
|
||||
github.com/go-delve/delve v1.3.2
|
||||
github.com/go-sql-driver/mysql v1.5.0
|
||||
github.com/gorilla/websocket v1.4.2
|
||||
github.com/lib/pq v1.3.0
|
||||
gopkg.in/yaml.v2 v2.2.8
|
||||
)
|
120
go.sum
Normal file
120
go.sum
Normal file
@ -0,0 +1,120 @@
|
||||
github.com/Knetic/govaluate v3.0.0+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
|
||||
github.com/OwnLocal/goes v1.0.0/go.mod h1:8rIFjBGTue3lCU0wplczcUgt9Gxgrkkrw7etMIcn8TM=
|
||||
github.com/astaxie/beego v1.12.1 h1:dfpuoxpzLVgclveAXe4PyNKqkzgm5zF4tgF2B3kkM2I=
|
||||
github.com/astaxie/beego v1.12.1/go.mod h1:kPBWpSANNbSdIqOc8SUL9h+1oyBMZhROeYsXQDbidWQ=
|
||||
github.com/beego/goyaml2 v0.0.0-20130207012346-5545475820dd/go.mod h1:1b+Y/CofkYwXMUU0OhQqGvsY2Bvgr4j6jfT699wyZKQ=
|
||||
github.com/beego/x2j v0.0.0-20131220205130-a0352aadc542/go.mod h1:kSeGC/p1AbBiEp5kat81+DSQrZenVBZXklMLaELspWU=
|
||||
github.com/bradfitz/gomemcache v0.0.0-20180710155616-bc664df96737/go.mod h1:PmM6Mmwb0LSuEubjR8N7PtNe1KxZLtOUHtbeikc5h60=
|
||||
github.com/casbin/casbin v1.7.0/go.mod h1:c67qKN6Oum3UF5Q1+BByfFxkwKvhwW57ITjqwtzR1KE=
|
||||
github.com/cloudflare/golz4 v0.0.0-20150217214814-ef862a3cdc58/go.mod h1:EOBUe0h4xcZ5GoxqC5SDxFQ8gwyZPKQoEzownBlhI80=
|
||||
github.com/cosiner/argv v0.0.0-20170225145430-13bacc38a0a5 h1:rIXlvz2IWiupMFlC45cZCXZFvKX/ExBcSLrDy2G0Lp8=
|
||||
github.com/cosiner/argv v0.0.0-20170225145430-13bacc38a0a5/go.mod h1:p/NrK5tF6ICIly4qwEDsf6VDirFiWWz0FenfYBwJaKQ=
|
||||
github.com/couchbase/go-couchbase v0.0.0-20181122212707-3e9b6e1258bb/go.mod h1:TWI8EKQMs5u5jLKW/tsb9VwauIrMIxQG1r5fMsswK5U=
|
||||
github.com/couchbase/gomemcached v0.0.0-20181122193126-5125a94a666c/go.mod h1:srVSlQLB8iXBVXHgnqemxUXqN6FCvClgCMPCsjBDR7c=
|
||||
github.com/couchbase/goutils v0.0.0-20180530154633-e865a1461c8a/go.mod h1:BQwMFlJzDjFDG3DJUdU0KORxn88UlsOULuxLExMh3Hs=
|
||||
github.com/cpuguy83/go-md2man v1.0.8/go.mod h1:N6JayAiVKtlHSnuTCeuLSQVs75hb8q+dYQLjr7cDsKY=
|
||||
github.com/cupcake/rdb v0.0.0-20161107195141-43ba34106c76/go.mod h1:vYwsqCOLxGiisLwp9rITslkFNpZD5rz43tf41QFkTWY=
|
||||
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/edsrzf/mmap-go v0.0.0-20170320065105-0bce6a688712/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M=
|
||||
github.com/elazarl/go-bindata-assetfs v1.0.0/go.mod h1:v+YaWX3bdea5J/mo8dSETolEo7R71Vk1u8bnjau5yw4=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
|
||||
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
||||
github.com/go-delve/delve v1.3.2 h1:K8VjV+Q2YnBYlPq0ctjrvc9h7h03wXszlszzfGW5Tog=
|
||||
github.com/go-delve/delve v1.3.2/go.mod h1:LLw6qJfIsRK9WcwV2IRRqsdlgrqzOeuGrQOCOIhDpt8=
|
||||
github.com/go-redis/redis v6.14.2+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA=
|
||||
github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
|
||||
github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs=
|
||||
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
|
||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/gomodule/redigo v2.0.0+incompatible/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4=
|
||||
github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
|
||||
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||
github.com/lib/pq v1.3.0 h1:/qkRGz8zljWiDcFvgpwUpwIAPu3r07TDvs3Rws+o/pU=
|
||||
github.com/lib/pq v1.3.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||
github.com/mattn/go-colorable v0.0.0-20170327083344-ded68f7a9561 h1:isR/L+BIZ+rqODWYR/f526ygrBMGKZYFhaaFRDGvuZ8=
|
||||
github.com/mattn/go-colorable v0.0.0-20170327083344-ded68f7a9561/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
|
||||
github.com/mattn/go-isatty v0.0.3 h1:ns/ykhmWi7G9O+8a448SecJU3nSMBXJfqQkl0upE1jI=
|
||||
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
||||
github.com/mattn/go-sqlite3 v1.10.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
|
||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.8.0 h1:VkHVNpR4iVnU8XQR6DBm8BqYjN7CRzw+xKUbVVbbW9w=
|
||||
github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/gomega v1.5.0 h1:izbySO9zDPmjJ8rDjLvkA2zJHIo+HkYXHnf7eN7SSyo=
|
||||
github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
||||
github.com/peterh/liner v0.0.0-20170317030525-88609521dc4b h1:8uaXtUkxiy+T/zdLWuxa/PG4so0TPZDZfafFNNSaptE=
|
||||
github.com/peterh/liner v0.0.0-20170317030525-88609521dc4b/go.mod h1:xIteQHvHuaLYG9IFj6mSxM0fCKrs34IrEQUhOYuGPHc=
|
||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/profile v0.0.0-20170413231811-06b906832ed0 h1:wBza4Dlm/NCQF572oSGNZ69flNFxlwIHjtwS6oy3Rvw=
|
||||
github.com/pkg/profile v0.0.0-20170413231811-06b906832ed0/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA=
|
||||
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/russross/blackfriday v0.0.0-20180428102519-11635eb403ff/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
|
||||
github.com/siddontang/go v0.0.0-20180604090527-bdc77568d726/go.mod h1:3yhqj7WBBfRhbBlzyOC3gUxftwsU0u8gqevxwIHQpMw=
|
||||
github.com/siddontang/ledisdb v0.0.0-20181029004158-becf5f38d373/go.mod h1:mF1DpOSOUiJRMR+FDqaqu3EBqrybQtrDDszLUZ6oxPg=
|
||||
github.com/siddontang/rdb v0.0.0-20150307021120-fc89ed2e418d/go.mod h1:AMEsy7v5z92TR1JKMkLLoaOQk++LVnOKL3ScbJ8GNGA=
|
||||
github.com/sirupsen/logrus v0.0.0-20180523074243-ea8897e79973 h1:3AJZYTzw3gm3TNTt30x0CCKD7GOn2sdd50Hn35fQkGY=
|
||||
github.com/sirupsen/logrus v0.0.0-20180523074243-ea8897e79973/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc=
|
||||
github.com/spf13/cobra v0.0.0-20170417170307-b6cb39589372/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
|
||||
github.com/spf13/pflag v0.0.0-20170417173400-9e4c21054fa1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||
github.com/ssdb/gossdb v0.0.0-20180723034631-88f6b59b84ec/go.mod h1:QBvMkMya+gXctz3kmljlUCu/yB3GZ6oee+dUozsezQE=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/syndtr/goleveldb v0.0.0-20181127023241-353a9fca669c/go.mod h1:Z4AUp2Km+PwemOoO/VB5AOx9XSsIItzFjoJlOSiYmn0=
|
||||
github.com/wendal/errors v0.0.0-20130201093226-f66c77a7882b/go.mod h1:Q12BUT7DqIlHRmgv3RskH+UCM/4eqVMgI0EMmlSpAXc=
|
||||
go.starlark.net v0.0.0-20190702223751-32f345186213 h1:lkYv5AKwvvduv5XWP6szk/bvvgO6aDeUujhZQXIFTes=
|
||||
go.starlark.net v0.0.0-20190702223751-32f345186213/go.mod h1:c1/X6cHgvdXj6pUlmWKMkuqRnW4K8x2vwt6JAaaircg=
|
||||
golang.org/x/arch v0.0.0-20171004143515-077ac972c2e4 h1:TP7YcWHbnFq4v8/3wM2JwgM0SRRtsYJ7Z6Oj0arz2bs=
|
||||
golang.org/x/arch v0.0.0-20171004143515-077ac972c2e4/go.mod h1:cYlCBUl1MsqxdiKgmc4uh7TxZfWSFLOGSRR090WDxt8=
|
||||
golang.org/x/crypto v0.0.0-20180614174826-fd5f17ee7299/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550 h1:ObdrDkeb4kJdCP557AjRjq69pTHfNouLtWZG7j9rPN8=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859 h1:R/3boaszxrf1GEUWTVDzSKVwLmSJpwZ1yqXm8j0v2QI=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/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-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9 h1:L2auWcuQIvxz9xSEqzESnV/QN/gNRXNApHi3fYwl2w0=
|
||||
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/tools v0.0.0-20181120060634-fc4f04983f62/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20200117065230-39095c1d176c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
gopkg.in/airbrake/gobrake.v2 v2.0.9 h1:7z2uVWwn7oVeeugY1DtlPAy5H+KYgB1KeKTnqjNatLo=
|
||||
gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
|
||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||
gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2 h1:OAj3g0cR6Dx/R07QgQe8wkA9RNjB2u4i700xBkIT4e0=
|
||||
gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKWaSkCsqBpgog8nAV2xsGOxlo=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
|
||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
174
vendor/github.com/astaxie/beego/swagger/swagger.go
generated
vendored
174
vendor/github.com/astaxie/beego/swagger/swagger.go
generated
vendored
@ -1,174 +0,0 @@
|
||||
// Copyright 2014 beego Author. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
// Swagger™ is a project used to describe and document RESTful APIs.
|
||||
//
|
||||
// The Swagger specification defines a set of files required to describe such an API. These files can then be used by the Swagger-UI project to display the API and Swagger-Codegen to generate clients in various languages. Additional utilities can also take advantage of the resulting files, such as testing tools.
|
||||
// Now in version 2.0, Swagger is more enabling than ever. And it's 100% open source software.
|
||||
|
||||
// Package swagger struct definition
|
||||
package swagger
|
||||
|
||||
// Swagger list the resource
|
||||
type Swagger struct {
|
||||
SwaggerVersion string `json:"swagger,omitempty" yaml:"swagger,omitempty"`
|
||||
Infos Information `json:"info" yaml:"info"`
|
||||
Host string `json:"host,omitempty" yaml:"host,omitempty"`
|
||||
BasePath string `json:"basePath,omitempty" yaml:"basePath,omitempty"`
|
||||
Schemes []string `json:"schemes,omitempty" yaml:"schemes,omitempty"`
|
||||
Consumes []string `json:"consumes,omitempty" yaml:"consumes,omitempty"`
|
||||
Produces []string `json:"produces,omitempty" yaml:"produces,omitempty"`
|
||||
Paths map[string]*Item `json:"paths" yaml:"paths"`
|
||||
Definitions map[string]Schema `json:"definitions,omitempty" yaml:"definitions,omitempty"`
|
||||
SecurityDefinitions map[string]Security `json:"securityDefinitions,omitempty" yaml:"securityDefinitions,omitempty"`
|
||||
Security []map[string][]string `json:"security,omitempty" yaml:"security,omitempty"`
|
||||
Tags []Tag `json:"tags,omitempty" yaml:"tags,omitempty"`
|
||||
ExternalDocs *ExternalDocs `json:"externalDocs,omitempty" yaml:"externalDocs,omitempty"`
|
||||
}
|
||||
|
||||
// Information Provides metadata about the API. The metadata can be used by the clients if needed.
|
||||
type Information struct {
|
||||
Title string `json:"title,omitempty" yaml:"title,omitempty"`
|
||||
Description string `json:"description,omitempty" yaml:"description,omitempty"`
|
||||
Version string `json:"version,omitempty" yaml:"version,omitempty"`
|
||||
TermsOfService string `json:"termsOfService,omitempty" yaml:"termsOfService,omitempty"`
|
||||
|
||||
Contact Contact `json:"contact,omitempty" yaml:"contact,omitempty"`
|
||||
License *License `json:"license,omitempty" yaml:"license,omitempty"`
|
||||
}
|
||||
|
||||
// Contact information for the exposed API.
|
||||
type Contact struct {
|
||||
Name string `json:"name,omitempty" yaml:"name,omitempty"`
|
||||
URL string `json:"url,omitempty" yaml:"url,omitempty"`
|
||||
EMail string `json:"email,omitempty" yaml:"email,omitempty"`
|
||||
}
|
||||
|
||||
// License information for the exposed API.
|
||||
type License struct {
|
||||
Name string `json:"name,omitempty" yaml:"name,omitempty"`
|
||||
URL string `json:"url,omitempty" yaml:"url,omitempty"`
|
||||
}
|
||||
|
||||
// Item Describes the operations available on a single path.
|
||||
type Item struct {
|
||||
Ref string `json:"$ref,omitempty" yaml:"$ref,omitempty"`
|
||||
Get *Operation `json:"get,omitempty" yaml:"get,omitempty"`
|
||||
Put *Operation `json:"put,omitempty" yaml:"put,omitempty"`
|
||||
Post *Operation `json:"post,omitempty" yaml:"post,omitempty"`
|
||||
Delete *Operation `json:"delete,omitempty" yaml:"delete,omitempty"`
|
||||
Options *Operation `json:"options,omitempty" yaml:"options,omitempty"`
|
||||
Head *Operation `json:"head,omitempty" yaml:"head,omitempty"`
|
||||
Patch *Operation `json:"patch,omitempty" yaml:"patch,omitempty"`
|
||||
}
|
||||
|
||||
// Operation Describes a single API operation on a path.
|
||||
type Operation struct {
|
||||
Tags []string `json:"tags,omitempty" yaml:"tags,omitempty"`
|
||||
Summary string `json:"summary,omitempty" yaml:"summary,omitempty"`
|
||||
Description string `json:"description,omitempty" yaml:"description,omitempty"`
|
||||
OperationID string `json:"operationId,omitempty" yaml:"operationId,omitempty"`
|
||||
Consumes []string `json:"consumes,omitempty" yaml:"consumes,omitempty"`
|
||||
Produces []string `json:"produces,omitempty" yaml:"produces,omitempty"`
|
||||
Schemes []string `json:"schemes,omitempty" yaml:"schemes,omitempty"`
|
||||
Parameters []Parameter `json:"parameters,omitempty" yaml:"parameters,omitempty"`
|
||||
Responses map[string]Response `json:"responses,omitempty" yaml:"responses,omitempty"`
|
||||
Security []map[string][]string `json:"security,omitempty" yaml:"security,omitempty"`
|
||||
Deprecated bool `json:"deprecated,omitempty" yaml:"deprecated,omitempty"`
|
||||
}
|
||||
|
||||
// Parameter Describes a single operation parameter.
|
||||
type Parameter struct {
|
||||
In string `json:"in,omitempty" yaml:"in,omitempty"`
|
||||
Name string `json:"name,omitempty" yaml:"name,omitempty"`
|
||||
Description string `json:"description,omitempty" yaml:"description,omitempty"`
|
||||
Required bool `json:"required,omitempty" yaml:"required,omitempty"`
|
||||
Schema *Schema `json:"schema,omitempty" yaml:"schema,omitempty"`
|
||||
Type string `json:"type,omitempty" yaml:"type,omitempty"`
|
||||
Format string `json:"format,omitempty" yaml:"format,omitempty"`
|
||||
Items *ParameterItems `json:"items,omitempty" yaml:"items,omitempty"`
|
||||
Default interface{} `json:"default,omitempty" yaml:"default,omitempty"`
|
||||
}
|
||||
|
||||
// ParameterItems A limited subset of JSON-Schema's items object. It is used by parameter definitions that are not located in "body".
|
||||
// http://swagger.io/specification/#itemsObject
|
||||
type ParameterItems struct {
|
||||
Type string `json:"type,omitempty" yaml:"type,omitempty"`
|
||||
Format string `json:"format,omitempty" yaml:"format,omitempty"`
|
||||
Items []*ParameterItems `json:"items,omitempty" yaml:"items,omitempty"` //Required if type is "array". Describes the type of items in the array.
|
||||
CollectionFormat string `json:"collectionFormat,omitempty" yaml:"collectionFormat,omitempty"`
|
||||
Default string `json:"default,omitempty" yaml:"default,omitempty"`
|
||||
}
|
||||
|
||||
// Schema Object allows the definition of input and output data types.
|
||||
type Schema struct {
|
||||
Ref string `json:"$ref,omitempty" yaml:"$ref,omitempty"`
|
||||
Title string `json:"title,omitempty" yaml:"title,omitempty"`
|
||||
Format string `json:"format,omitempty" yaml:"format,omitempty"`
|
||||
Description string `json:"description,omitempty" yaml:"description,omitempty"`
|
||||
Required []string `json:"required,omitempty" yaml:"required,omitempty"`
|
||||
Type string `json:"type,omitempty" yaml:"type,omitempty"`
|
||||
Items *Schema `json:"items,omitempty" yaml:"items,omitempty"`
|
||||
Properties map[string]Propertie `json:"properties,omitempty" yaml:"properties,omitempty"`
|
||||
Enum []interface{} `json:"enum,omitempty" yaml:"enum,omitempty"`
|
||||
Example interface{} `json:"example,omitempty" yaml:"example,omitempty"`
|
||||
}
|
||||
|
||||
// Propertie are taken from the JSON Schema definition but their definitions were adjusted to the Swagger Specification
|
||||
type Propertie struct {
|
||||
Ref string `json:"$ref,omitempty" yaml:"$ref,omitempty"`
|
||||
Title string `json:"title,omitempty" yaml:"title,omitempty"`
|
||||
Description string `json:"description,omitempty" yaml:"description,omitempty"`
|
||||
Default interface{} `json:"default,omitempty" yaml:"default,omitempty"`
|
||||
Type string `json:"type,omitempty" yaml:"type,omitempty"`
|
||||
Example interface{} `json:"example,omitempty" yaml:"example,omitempty"`
|
||||
Required []string `json:"required,omitempty" yaml:"required,omitempty"`
|
||||
Format string `json:"format,omitempty" yaml:"format,omitempty"`
|
||||
ReadOnly bool `json:"readOnly,omitempty" yaml:"readOnly,omitempty"`
|
||||
Properties map[string]Propertie `json:"properties,omitempty" yaml:"properties,omitempty"`
|
||||
Items *Propertie `json:"items,omitempty" yaml:"items,omitempty"`
|
||||
AdditionalProperties *Propertie `json:"additionalProperties,omitempty" yaml:"additionalProperties,omitempty"`
|
||||
}
|
||||
|
||||
// Response as they are returned from executing this operation.
|
||||
type Response struct {
|
||||
Description string `json:"description" yaml:"description"`
|
||||
Schema *Schema `json:"schema,omitempty" yaml:"schema,omitempty"`
|
||||
Ref string `json:"$ref,omitempty" yaml:"$ref,omitempty"`
|
||||
}
|
||||
|
||||
// Security Allows the definition of a security scheme that can be used by the operations
|
||||
type Security struct {
|
||||
Type string `json:"type,omitempty" yaml:"type,omitempty"` // Valid values are "basic", "apiKey" or "oauth2".
|
||||
Description string `json:"description,omitempty" yaml:"description,omitempty"`
|
||||
Name string `json:"name,omitempty" yaml:"name,omitempty"`
|
||||
In string `json:"in,omitempty" yaml:"in,omitempty"` // Valid values are "query" or "header".
|
||||
Flow string `json:"flow,omitempty" yaml:"flow,omitempty"` // Valid values are "implicit", "password", "application" or "accessCode".
|
||||
AuthorizationURL string `json:"authorizationUrl,omitempty" yaml:"authorizationUrl,omitempty"`
|
||||
TokenURL string `json:"tokenUrl,omitempty" yaml:"tokenUrl,omitempty"`
|
||||
Scopes map[string]string `json:"scopes,omitempty" yaml:"scopes,omitempty"` // The available scopes for the OAuth2 security scheme.
|
||||
}
|
||||
|
||||
// Tag Allows adding meta data to a single tag that is used by the Operation Object
|
||||
type Tag struct {
|
||||
Name string `json:"name,omitempty" yaml:"name,omitempty"`
|
||||
Description string `json:"description,omitempty" yaml:"description,omitempty"`
|
||||
ExternalDocs *ExternalDocs `json:"externalDocs,omitempty" yaml:"externalDocs,omitempty"`
|
||||
}
|
||||
|
||||
// ExternalDocs include Additional external documentation
|
||||
type ExternalDocs struct {
|
||||
Description string `json:"description,omitempty" yaml:"description,omitempty"`
|
||||
URL string `json:"url,omitempty" yaml:"url,omitempty"`
|
||||
}
|
25
vendor/github.com/astaxie/beego/utils/caller.go
generated
vendored
25
vendor/github.com/astaxie/beego/utils/caller.go
generated
vendored
@ -1,25 +0,0 @@
|
||||
// Copyright 2014 beego Author. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package utils
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"runtime"
|
||||
)
|
||||
|
||||
// GetFuncName get function name
|
||||
func GetFuncName(i interface{}) string {
|
||||
return runtime.FuncForPC(reflect.ValueOf(i).Pointer()).Name()
|
||||
}
|
478
vendor/github.com/astaxie/beego/utils/debug.go
generated
vendored
478
vendor/github.com/astaxie/beego/utils/debug.go
generated
vendored
@ -1,478 +0,0 @@
|
||||
// Copyright 2014 beego Author. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package utils
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"log"
|
||||
"reflect"
|
||||
"runtime"
|
||||
)
|
||||
|
||||
var (
|
||||
dunno = []byte("???")
|
||||
centerDot = []byte("·")
|
||||
dot = []byte(".")
|
||||
)
|
||||
|
||||
type pointerInfo struct {
|
||||
prev *pointerInfo
|
||||
n int
|
||||
addr uintptr
|
||||
pos int
|
||||
used []int
|
||||
}
|
||||
|
||||
// Display print the data in console
|
||||
func Display(data ...interface{}) {
|
||||
display(true, data...)
|
||||
}
|
||||
|
||||
// GetDisplayString return data print string
|
||||
func GetDisplayString(data ...interface{}) string {
|
||||
return display(false, data...)
|
||||
}
|
||||
|
||||
func display(displayed bool, data ...interface{}) string {
|
||||
var pc, file, line, ok = runtime.Caller(2)
|
||||
|
||||
if !ok {
|
||||
return ""
|
||||
}
|
||||
|
||||
var buf = new(bytes.Buffer)
|
||||
|
||||
fmt.Fprintf(buf, "[Debug] at %s() [%s:%d]\n", function(pc), file, line)
|
||||
|
||||
fmt.Fprintf(buf, "\n[Variables]\n")
|
||||
|
||||
for i := 0; i < len(data); i += 2 {
|
||||
var output = fomateinfo(len(data[i].(string))+3, data[i+1])
|
||||
fmt.Fprintf(buf, "%s = %s", data[i], output)
|
||||
}
|
||||
|
||||
if displayed {
|
||||
log.Print(buf)
|
||||
}
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
// return data dump and format bytes
|
||||
func fomateinfo(headlen int, data ...interface{}) []byte {
|
||||
var buf = new(bytes.Buffer)
|
||||
|
||||
if len(data) > 1 {
|
||||
fmt.Fprint(buf, " ")
|
||||
|
||||
fmt.Fprint(buf, "[")
|
||||
|
||||
fmt.Fprintln(buf)
|
||||
}
|
||||
|
||||
for k, v := range data {
|
||||
var buf2 = new(bytes.Buffer)
|
||||
var pointers *pointerInfo
|
||||
var interfaces = make([]reflect.Value, 0, 10)
|
||||
|
||||
printKeyValue(buf2, reflect.ValueOf(v), &pointers, &interfaces, nil, true, " ", 1)
|
||||
|
||||
if k < len(data)-1 {
|
||||
fmt.Fprint(buf2, ", ")
|
||||
}
|
||||
|
||||
fmt.Fprintln(buf2)
|
||||
|
||||
buf.Write(buf2.Bytes())
|
||||
}
|
||||
|
||||
if len(data) > 1 {
|
||||
fmt.Fprintln(buf)
|
||||
|
||||
fmt.Fprint(buf, " ")
|
||||
|
||||
fmt.Fprint(buf, "]")
|
||||
}
|
||||
|
||||
return buf.Bytes()
|
||||
}
|
||||
|
||||
// check data is golang basic type
|
||||
func isSimpleType(val reflect.Value, kind reflect.Kind, pointers **pointerInfo, interfaces *[]reflect.Value) bool {
|
||||
switch kind {
|
||||
case reflect.Bool:
|
||||
return true
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
return true
|
||||
case reflect.Uint8, reflect.Uint16, reflect.Uint, reflect.Uint32, reflect.Uint64:
|
||||
return true
|
||||
case reflect.Float32, reflect.Float64:
|
||||
return true
|
||||
case reflect.Complex64, reflect.Complex128:
|
||||
return true
|
||||
case reflect.String:
|
||||
return true
|
||||
case reflect.Chan:
|
||||
return true
|
||||
case reflect.Invalid:
|
||||
return true
|
||||
case reflect.Interface:
|
||||
for _, in := range *interfaces {
|
||||
if reflect.DeepEqual(in, val) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
case reflect.UnsafePointer:
|
||||
if val.IsNil() {
|
||||
return true
|
||||
}
|
||||
|
||||
var elem = val.Elem()
|
||||
|
||||
if isSimpleType(elem, elem.Kind(), pointers, interfaces) {
|
||||
return true
|
||||
}
|
||||
|
||||
var addr = val.Elem().UnsafeAddr()
|
||||
|
||||
for p := *pointers; p != nil; p = p.prev {
|
||||
if addr == p.addr {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// dump value
|
||||
func printKeyValue(buf *bytes.Buffer, val reflect.Value, pointers **pointerInfo, interfaces *[]reflect.Value, structFilter func(string, string) bool, formatOutput bool, indent string, level int) {
|
||||
var t = val.Kind()
|
||||
|
||||
switch t {
|
||||
case reflect.Bool:
|
||||
fmt.Fprint(buf, val.Bool())
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
fmt.Fprint(buf, val.Int())
|
||||
case reflect.Uint8, reflect.Uint16, reflect.Uint, reflect.Uint32, reflect.Uint64:
|
||||
fmt.Fprint(buf, val.Uint())
|
||||
case reflect.Float32, reflect.Float64:
|
||||
fmt.Fprint(buf, val.Float())
|
||||
case reflect.Complex64, reflect.Complex128:
|
||||
fmt.Fprint(buf, val.Complex())
|
||||
case reflect.UnsafePointer:
|
||||
fmt.Fprintf(buf, "unsafe.Pointer(0x%X)", val.Pointer())
|
||||
case reflect.Ptr:
|
||||
if val.IsNil() {
|
||||
fmt.Fprint(buf, "nil")
|
||||
return
|
||||
}
|
||||
|
||||
var addr = val.Elem().UnsafeAddr()
|
||||
|
||||
for p := *pointers; p != nil; p = p.prev {
|
||||
if addr == p.addr {
|
||||
p.used = append(p.used, buf.Len())
|
||||
fmt.Fprintf(buf, "0x%X", addr)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
*pointers = &pointerInfo{
|
||||
prev: *pointers,
|
||||
addr: addr,
|
||||
pos: buf.Len(),
|
||||
used: make([]int, 0),
|
||||
}
|
||||
|
||||
fmt.Fprint(buf, "&")
|
||||
|
||||
printKeyValue(buf, val.Elem(), pointers, interfaces, structFilter, formatOutput, indent, level)
|
||||
case reflect.String:
|
||||
fmt.Fprint(buf, "\"", val.String(), "\"")
|
||||
case reflect.Interface:
|
||||
var value = val.Elem()
|
||||
|
||||
if !value.IsValid() {
|
||||
fmt.Fprint(buf, "nil")
|
||||
} else {
|
||||
for _, in := range *interfaces {
|
||||
if reflect.DeepEqual(in, val) {
|
||||
fmt.Fprint(buf, "repeat")
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
*interfaces = append(*interfaces, val)
|
||||
|
||||
printKeyValue(buf, value, pointers, interfaces, structFilter, formatOutput, indent, level+1)
|
||||
}
|
||||
case reflect.Struct:
|
||||
var t = val.Type()
|
||||
|
||||
fmt.Fprint(buf, t)
|
||||
fmt.Fprint(buf, "{")
|
||||
|
||||
for i := 0; i < val.NumField(); i++ {
|
||||
if formatOutput {
|
||||
fmt.Fprintln(buf)
|
||||
} else {
|
||||
fmt.Fprint(buf, " ")
|
||||
}
|
||||
|
||||
var name = t.Field(i).Name
|
||||
|
||||
if formatOutput {
|
||||
for ind := 0; ind < level; ind++ {
|
||||
fmt.Fprint(buf, indent)
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Fprint(buf, name)
|
||||
fmt.Fprint(buf, ": ")
|
||||
|
||||
if structFilter != nil && structFilter(t.String(), name) {
|
||||
fmt.Fprint(buf, "ignore")
|
||||
} else {
|
||||
printKeyValue(buf, val.Field(i), pointers, interfaces, structFilter, formatOutput, indent, level+1)
|
||||
}
|
||||
|
||||
fmt.Fprint(buf, ",")
|
||||
}
|
||||
|
||||
if formatOutput {
|
||||
fmt.Fprintln(buf)
|
||||
|
||||
for ind := 0; ind < level-1; ind++ {
|
||||
fmt.Fprint(buf, indent)
|
||||
}
|
||||
} else {
|
||||
fmt.Fprint(buf, " ")
|
||||
}
|
||||
|
||||
fmt.Fprint(buf, "}")
|
||||
case reflect.Array, reflect.Slice:
|
||||
fmt.Fprint(buf, val.Type())
|
||||
fmt.Fprint(buf, "{")
|
||||
|
||||
var allSimple = true
|
||||
|
||||
for i := 0; i < val.Len(); i++ {
|
||||
var elem = val.Index(i)
|
||||
|
||||
var isSimple = isSimpleType(elem, elem.Kind(), pointers, interfaces)
|
||||
|
||||
if !isSimple {
|
||||
allSimple = false
|
||||
}
|
||||
|
||||
if formatOutput && !isSimple {
|
||||
fmt.Fprintln(buf)
|
||||
} else {
|
||||
fmt.Fprint(buf, " ")
|
||||
}
|
||||
|
||||
if formatOutput && !isSimple {
|
||||
for ind := 0; ind < level; ind++ {
|
||||
fmt.Fprint(buf, indent)
|
||||
}
|
||||
}
|
||||
|
||||
printKeyValue(buf, elem, pointers, interfaces, structFilter, formatOutput, indent, level+1)
|
||||
|
||||
if i != val.Len()-1 || !allSimple {
|
||||
fmt.Fprint(buf, ",")
|
||||
}
|
||||
}
|
||||
|
||||
if formatOutput && !allSimple {
|
||||
fmt.Fprintln(buf)
|
||||
|
||||
for ind := 0; ind < level-1; ind++ {
|
||||
fmt.Fprint(buf, indent)
|
||||
}
|
||||
} else {
|
||||
fmt.Fprint(buf, " ")
|
||||
}
|
||||
|
||||
fmt.Fprint(buf, "}")
|
||||
case reflect.Map:
|
||||
var t = val.Type()
|
||||
var keys = val.MapKeys()
|
||||
|
||||
fmt.Fprint(buf, t)
|
||||
fmt.Fprint(buf, "{")
|
||||
|
||||
var allSimple = true
|
||||
|
||||
for i := 0; i < len(keys); i++ {
|
||||
var elem = val.MapIndex(keys[i])
|
||||
|
||||
var isSimple = isSimpleType(elem, elem.Kind(), pointers, interfaces)
|
||||
|
||||
if !isSimple {
|
||||
allSimple = false
|
||||
}
|
||||
|
||||
if formatOutput && !isSimple {
|
||||
fmt.Fprintln(buf)
|
||||
} else {
|
||||
fmt.Fprint(buf, " ")
|
||||
}
|
||||
|
||||
if formatOutput && !isSimple {
|
||||
for ind := 0; ind <= level; ind++ {
|
||||
fmt.Fprint(buf, indent)
|
||||
}
|
||||
}
|
||||
|
||||
printKeyValue(buf, keys[i], pointers, interfaces, structFilter, formatOutput, indent, level+1)
|
||||
fmt.Fprint(buf, ": ")
|
||||
printKeyValue(buf, elem, pointers, interfaces, structFilter, formatOutput, indent, level+1)
|
||||
|
||||
if i != val.Len()-1 || !allSimple {
|
||||
fmt.Fprint(buf, ",")
|
||||
}
|
||||
}
|
||||
|
||||
if formatOutput && !allSimple {
|
||||
fmt.Fprintln(buf)
|
||||
|
||||
for ind := 0; ind < level-1; ind++ {
|
||||
fmt.Fprint(buf, indent)
|
||||
}
|
||||
} else {
|
||||
fmt.Fprint(buf, " ")
|
||||
}
|
||||
|
||||
fmt.Fprint(buf, "}")
|
||||
case reflect.Chan:
|
||||
fmt.Fprint(buf, val.Type())
|
||||
case reflect.Invalid:
|
||||
fmt.Fprint(buf, "invalid")
|
||||
default:
|
||||
fmt.Fprint(buf, "unknow")
|
||||
}
|
||||
}
|
||||
|
||||
// PrintPointerInfo dump pointer value
|
||||
func PrintPointerInfo(buf *bytes.Buffer, headlen int, pointers *pointerInfo) {
|
||||
var anyused = false
|
||||
var pointerNum = 0
|
||||
|
||||
for p := pointers; p != nil; p = p.prev {
|
||||
if len(p.used) > 0 {
|
||||
anyused = true
|
||||
}
|
||||
pointerNum++
|
||||
p.n = pointerNum
|
||||
}
|
||||
|
||||
if anyused {
|
||||
var pointerBufs = make([][]rune, pointerNum+1)
|
||||
|
||||
for i := 0; i < len(pointerBufs); i++ {
|
||||
var pointerBuf = make([]rune, buf.Len()+headlen)
|
||||
|
||||
for j := 0; j < len(pointerBuf); j++ {
|
||||
pointerBuf[j] = ' '
|
||||
}
|
||||
|
||||
pointerBufs[i] = pointerBuf
|
||||
}
|
||||
|
||||
for pn := 0; pn <= pointerNum; pn++ {
|
||||
for p := pointers; p != nil; p = p.prev {
|
||||
if len(p.used) > 0 && p.n >= pn {
|
||||
if pn == p.n {
|
||||
pointerBufs[pn][p.pos+headlen] = '└'
|
||||
|
||||
var maxpos = 0
|
||||
|
||||
for i, pos := range p.used {
|
||||
if i < len(p.used)-1 {
|
||||
pointerBufs[pn][pos+headlen] = '┴'
|
||||
} else {
|
||||
pointerBufs[pn][pos+headlen] = '┘'
|
||||
}
|
||||
|
||||
maxpos = pos
|
||||
}
|
||||
|
||||
for i := 0; i < maxpos-p.pos-1; i++ {
|
||||
if pointerBufs[pn][i+p.pos+headlen+1] == ' ' {
|
||||
pointerBufs[pn][i+p.pos+headlen+1] = '─'
|
||||
}
|
||||
}
|
||||
} else {
|
||||
pointerBufs[pn][p.pos+headlen] = '│'
|
||||
|
||||
for _, pos := range p.used {
|
||||
if pointerBufs[pn][pos+headlen] == ' ' {
|
||||
pointerBufs[pn][pos+headlen] = '│'
|
||||
} else {
|
||||
pointerBufs[pn][pos+headlen] = '┼'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
buf.WriteString(string(pointerBufs[pn]) + "\n")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Stack get stack bytes
|
||||
func Stack(skip int, indent string) []byte {
|
||||
var buf = new(bytes.Buffer)
|
||||
|
||||
for i := skip; ; i++ {
|
||||
var pc, file, line, ok = runtime.Caller(i)
|
||||
|
||||
if !ok {
|
||||
break
|
||||
}
|
||||
|
||||
buf.WriteString(indent)
|
||||
|
||||
fmt.Fprintf(buf, "at %s() [%s:%d]\n", function(pc), file, line)
|
||||
}
|
||||
|
||||
return buf.Bytes()
|
||||
}
|
||||
|
||||
// return the name of the function containing the PC if possible,
|
||||
func function(pc uintptr) []byte {
|
||||
fn := runtime.FuncForPC(pc)
|
||||
if fn == nil {
|
||||
return dunno
|
||||
}
|
||||
name := []byte(fn.Name())
|
||||
// The name includes the path name to the package, which is unnecessary
|
||||
// since the file name is already included. Plus, it has center dots.
|
||||
// That is, we see
|
||||
// runtime/debug.*T·ptrmethod
|
||||
// and want
|
||||
// *T.ptrmethod
|
||||
if period := bytes.Index(name, dot); period >= 0 {
|
||||
name = name[period+1:]
|
||||
}
|
||||
name = bytes.Replace(name, centerDot, dot, -1)
|
||||
return name
|
||||
}
|
101
vendor/github.com/astaxie/beego/utils/file.go
generated
vendored
101
vendor/github.com/astaxie/beego/utils/file.go
generated
vendored
@ -1,101 +0,0 @@
|
||||
// Copyright 2014 beego Author. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package utils
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"errors"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
)
|
||||
|
||||
// SelfPath gets compiled executable file absolute path
|
||||
func SelfPath() string {
|
||||
path, _ := filepath.Abs(os.Args[0])
|
||||
return path
|
||||
}
|
||||
|
||||
// SelfDir gets compiled executable file directory
|
||||
func SelfDir() string {
|
||||
return filepath.Dir(SelfPath())
|
||||
}
|
||||
|
||||
// FileExists reports whether the named file or directory exists.
|
||||
func FileExists(name string) bool {
|
||||
if _, err := os.Stat(name); err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// SearchFile Search a file in paths.
|
||||
// this is often used in search config file in /etc ~/
|
||||
func SearchFile(filename string, paths ...string) (fullpath string, err error) {
|
||||
for _, path := range paths {
|
||||
if fullpath = filepath.Join(path, filename); FileExists(fullpath) {
|
||||
return
|
||||
}
|
||||
}
|
||||
err = errors.New(fullpath + " not found in paths")
|
||||
return
|
||||
}
|
||||
|
||||
// GrepFile like command grep -E
|
||||
// for example: GrepFile(`^hello`, "hello.txt")
|
||||
// \n is striped while read
|
||||
func GrepFile(patten string, filename string) (lines []string, err error) {
|
||||
re, err := regexp.Compile(patten)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
fd, err := os.Open(filename)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
lines = make([]string, 0)
|
||||
reader := bufio.NewReader(fd)
|
||||
prefix := ""
|
||||
isLongLine := false
|
||||
for {
|
||||
byteLine, isPrefix, er := reader.ReadLine()
|
||||
if er != nil && er != io.EOF {
|
||||
return nil, er
|
||||
}
|
||||
if er == io.EOF {
|
||||
break
|
||||
}
|
||||
line := string(byteLine)
|
||||
if isPrefix {
|
||||
prefix += line
|
||||
continue
|
||||
} else {
|
||||
isLongLine = true
|
||||
}
|
||||
|
||||
line = prefix + line
|
||||
if isLongLine {
|
||||
prefix = ""
|
||||
}
|
||||
if re.MatchString(line) {
|
||||
lines = append(lines, line)
|
||||
}
|
||||
}
|
||||
return lines, nil
|
||||
}
|
423
vendor/github.com/astaxie/beego/utils/mail.go
generated
vendored
423
vendor/github.com/astaxie/beego/utils/mail.go
generated
vendored
@ -1,423 +0,0 @@
|
||||
// Copyright 2014 beego Author. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package utils
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"mime"
|
||||
"mime/multipart"
|
||||
"net/mail"
|
||||
"net/smtp"
|
||||
"net/textproto"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
)
|
||||
|
||||
const (
|
||||
maxLineLength = 76
|
||||
|
||||
upperhex = "0123456789ABCDEF"
|
||||
)
|
||||
|
||||
// Email is the type used for email messages
|
||||
type Email struct {
|
||||
Auth smtp.Auth
|
||||
Identity string `json:"identity"`
|
||||
Username string `json:"username"`
|
||||
Password string `json:"password"`
|
||||
Host string `json:"host"`
|
||||
Port int `json:"port"`
|
||||
From string `json:"from"`
|
||||
To []string
|
||||
Bcc []string
|
||||
Cc []string
|
||||
Subject string
|
||||
Text string // Plaintext message (optional)
|
||||
HTML string // Html message (optional)
|
||||
Headers textproto.MIMEHeader
|
||||
Attachments []*Attachment
|
||||
ReadReceipt []string
|
||||
}
|
||||
|
||||
// Attachment is a struct representing an email attachment.
|
||||
// Based on the mime/multipart.FileHeader struct, Attachment contains the name, MIMEHeader, and content of the attachment in question
|
||||
type Attachment struct {
|
||||
Filename string
|
||||
Header textproto.MIMEHeader
|
||||
Content []byte
|
||||
}
|
||||
|
||||
// NewEMail create new Email struct with config json.
|
||||
// config json is followed from Email struct fields.
|
||||
func NewEMail(config string) *Email {
|
||||
e := new(Email)
|
||||
e.Headers = textproto.MIMEHeader{}
|
||||
err := json.Unmarshal([]byte(config), e)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
return e
|
||||
}
|
||||
|
||||
// Bytes Make all send information to byte
|
||||
func (e *Email) Bytes() ([]byte, error) {
|
||||
buff := &bytes.Buffer{}
|
||||
w := multipart.NewWriter(buff)
|
||||
// Set the appropriate headers (overwriting any conflicts)
|
||||
// Leave out Bcc (only included in envelope headers)
|
||||
e.Headers.Set("To", strings.Join(e.To, ","))
|
||||
if e.Cc != nil {
|
||||
e.Headers.Set("Cc", strings.Join(e.Cc, ","))
|
||||
}
|
||||
e.Headers.Set("From", e.From)
|
||||
e.Headers.Set("Subject", e.Subject)
|
||||
if len(e.ReadReceipt) != 0 {
|
||||
e.Headers.Set("Disposition-Notification-To", strings.Join(e.ReadReceipt, ","))
|
||||
}
|
||||
e.Headers.Set("MIME-Version", "1.0")
|
||||
|
||||
// Write the envelope headers (including any custom headers)
|
||||
if err := headerToBytes(buff, e.Headers); err != nil {
|
||||
return nil, fmt.Errorf("Failed to render message headers: %s", err)
|
||||
}
|
||||
|
||||
e.Headers.Set("Content-Type", fmt.Sprintf("multipart/mixed;\r\n boundary=%s\r\n", w.Boundary()))
|
||||
fmt.Fprintf(buff, "%s:", "Content-Type")
|
||||
fmt.Fprintf(buff, " %s\r\n", fmt.Sprintf("multipart/mixed;\r\n boundary=%s\r\n", w.Boundary()))
|
||||
|
||||
// Start the multipart/mixed part
|
||||
fmt.Fprintf(buff, "--%s\r\n", w.Boundary())
|
||||
header := textproto.MIMEHeader{}
|
||||
// Check to see if there is a Text or HTML field
|
||||
if e.Text != "" || e.HTML != "" {
|
||||
subWriter := multipart.NewWriter(buff)
|
||||
// Create the multipart alternative part
|
||||
header.Set("Content-Type", fmt.Sprintf("multipart/alternative;\r\n boundary=%s\r\n", subWriter.Boundary()))
|
||||
// Write the header
|
||||
if err := headerToBytes(buff, header); err != nil {
|
||||
return nil, fmt.Errorf("Failed to render multipart message headers: %s", err)
|
||||
}
|
||||
// Create the body sections
|
||||
if e.Text != "" {
|
||||
header.Set("Content-Type", fmt.Sprintf("text/plain; charset=UTF-8"))
|
||||
header.Set("Content-Transfer-Encoding", "quoted-printable")
|
||||
if _, err := subWriter.CreatePart(header); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Write the text
|
||||
if err := quotePrintEncode(buff, e.Text); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
if e.HTML != "" {
|
||||
header.Set("Content-Type", fmt.Sprintf("text/html; charset=UTF-8"))
|
||||
header.Set("Content-Transfer-Encoding", "quoted-printable")
|
||||
if _, err := subWriter.CreatePart(header); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Write the text
|
||||
if err := quotePrintEncode(buff, e.HTML); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
if err := subWriter.Close(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
// Create attachment part, if necessary
|
||||
for _, a := range e.Attachments {
|
||||
ap, err := w.CreatePart(a.Header)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Write the base64Wrapped content to the part
|
||||
base64Wrap(ap, a.Content)
|
||||
}
|
||||
if err := w.Close(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return buff.Bytes(), nil
|
||||
}
|
||||
|
||||
// AttachFile Add attach file to the send mail
|
||||
func (e *Email) AttachFile(args ...string) (a *Attachment, err error) {
|
||||
if len(args) < 1 && len(args) > 2 {
|
||||
err = errors.New("Must specify a file name and number of parameters can not exceed at least two")
|
||||
return
|
||||
}
|
||||
filename := args[0]
|
||||
id := ""
|
||||
if len(args) > 1 {
|
||||
id = args[1]
|
||||
}
|
||||
f, err := os.Open(filename)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
ct := mime.TypeByExtension(filepath.Ext(filename))
|
||||
basename := path.Base(filename)
|
||||
return e.Attach(f, basename, ct, id)
|
||||
}
|
||||
|
||||
// Attach is used to attach content from an io.Reader to the email.
|
||||
// Parameters include an io.Reader, the desired filename for the attachment, and the Content-Type.
|
||||
func (e *Email) Attach(r io.Reader, filename string, args ...string) (a *Attachment, err error) {
|
||||
if len(args) < 1 && len(args) > 2 {
|
||||
err = errors.New("Must specify the file type and number of parameters can not exceed at least two")
|
||||
return
|
||||
}
|
||||
c := args[0] //Content-Type
|
||||
id := ""
|
||||
if len(args) > 1 {
|
||||
id = args[1] //Content-ID
|
||||
}
|
||||
var buffer bytes.Buffer
|
||||
if _, err = io.Copy(&buffer, r); err != nil {
|
||||
return
|
||||
}
|
||||
at := &Attachment{
|
||||
Filename: filename,
|
||||
Header: textproto.MIMEHeader{},
|
||||
Content: buffer.Bytes(),
|
||||
}
|
||||
// Get the Content-Type to be used in the MIMEHeader
|
||||
if c != "" {
|
||||
at.Header.Set("Content-Type", c)
|
||||
} else {
|
||||
// If the Content-Type is blank, set the Content-Type to "application/octet-stream"
|
||||
at.Header.Set("Content-Type", "application/octet-stream")
|
||||
}
|
||||
if id != "" {
|
||||
at.Header.Set("Content-Disposition", fmt.Sprintf("inline;\r\n filename=\"%s\"", filename))
|
||||
at.Header.Set("Content-ID", fmt.Sprintf("<%s>", id))
|
||||
} else {
|
||||
at.Header.Set("Content-Disposition", fmt.Sprintf("attachment;\r\n filename=\"%s\"", filename))
|
||||
}
|
||||
at.Header.Set("Content-Transfer-Encoding", "base64")
|
||||
e.Attachments = append(e.Attachments, at)
|
||||
return at, nil
|
||||
}
|
||||
|
||||
// Send will send out the mail
|
||||
func (e *Email) Send() error {
|
||||
if e.Auth == nil {
|
||||
e.Auth = smtp.PlainAuth(e.Identity, e.Username, e.Password, e.Host)
|
||||
}
|
||||
// Merge the To, Cc, and Bcc fields
|
||||
to := make([]string, 0, len(e.To)+len(e.Cc)+len(e.Bcc))
|
||||
to = append(append(append(to, e.To...), e.Cc...), e.Bcc...)
|
||||
// Check to make sure there is at least one recipient and one "From" address
|
||||
if len(to) == 0 {
|
||||
return errors.New("Must specify at least one To address")
|
||||
}
|
||||
|
||||
// Use the username if no From is provided
|
||||
if len(e.From) == 0 {
|
||||
e.From = e.Username
|
||||
}
|
||||
|
||||
from, err := mail.ParseAddress(e.From)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// use mail's RFC 2047 to encode any string
|
||||
e.Subject = qEncode("utf-8", e.Subject)
|
||||
|
||||
raw, err := e.Bytes()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return smtp.SendMail(e.Host+":"+strconv.Itoa(e.Port), e.Auth, from.Address, to, raw)
|
||||
}
|
||||
|
||||
// quotePrintEncode writes the quoted-printable text to the IO Writer (according to RFC 2045)
|
||||
func quotePrintEncode(w io.Writer, s string) error {
|
||||
var buf [3]byte
|
||||
mc := 0
|
||||
for i := 0; i < len(s); i++ {
|
||||
c := s[i]
|
||||
// We're assuming Unix style text formats as input (LF line break), and
|
||||
// quoted-printble uses CRLF line breaks. (Literal CRs will become
|
||||
// "=0D", but probably shouldn't be there to begin with!)
|
||||
if c == '\n' {
|
||||
io.WriteString(w, "\r\n")
|
||||
mc = 0
|
||||
continue
|
||||
}
|
||||
|
||||
var nextOut []byte
|
||||
if isPrintable(c) {
|
||||
nextOut = append(buf[:0], c)
|
||||
} else {
|
||||
nextOut = buf[:]
|
||||
qpEscape(nextOut, c)
|
||||
}
|
||||
|
||||
// Add a soft line break if the next (encoded) byte would push this line
|
||||
// to or past the limit.
|
||||
if mc+len(nextOut) >= maxLineLength {
|
||||
if _, err := io.WriteString(w, "=\r\n"); err != nil {
|
||||
return err
|
||||
}
|
||||
mc = 0
|
||||
}
|
||||
|
||||
if _, err := w.Write(nextOut); err != nil {
|
||||
return err
|
||||
}
|
||||
mc += len(nextOut)
|
||||
}
|
||||
// No trailing end-of-line?? Soft line break, then. TODO: is this sane?
|
||||
if mc > 0 {
|
||||
io.WriteString(w, "=\r\n")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// isPrintable returns true if the rune given is "printable" according to RFC 2045, false otherwise
|
||||
func isPrintable(c byte) bool {
|
||||
return (c >= '!' && c <= '<') || (c >= '>' && c <= '~') || (c == ' ' || c == '\n' || c == '\t')
|
||||
}
|
||||
|
||||
// qpEscape is a helper function for quotePrintEncode which escapes a
|
||||
// non-printable byte. Expects len(dest) == 3.
|
||||
func qpEscape(dest []byte, c byte) {
|
||||
const nums = "0123456789ABCDEF"
|
||||
dest[0] = '='
|
||||
dest[1] = nums[(c&0xf0)>>4]
|
||||
dest[2] = nums[(c & 0xf)]
|
||||
}
|
||||
|
||||
// headerToBytes enumerates the key and values in the header, and writes the results to the IO Writer
|
||||
func headerToBytes(w io.Writer, t textproto.MIMEHeader) error {
|
||||
for k, v := range t {
|
||||
// Write the header key
|
||||
_, err := fmt.Fprintf(w, "%s:", k)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Write each value in the header
|
||||
for _, c := range v {
|
||||
_, err := fmt.Fprintf(w, " %s\r\n", c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// base64Wrap encodes the attachment content, and wraps it according to RFC 2045 standards (every 76 chars)
|
||||
// The output is then written to the specified io.Writer
|
||||
func base64Wrap(w io.Writer, b []byte) {
|
||||
// 57 raw bytes per 76-byte base64 line.
|
||||
const maxRaw = 57
|
||||
// Buffer for each line, including trailing CRLF.
|
||||
var buffer [maxLineLength + len("\r\n")]byte
|
||||
copy(buffer[maxLineLength:], "\r\n")
|
||||
// Process raw chunks until there's no longer enough to fill a line.
|
||||
for len(b) >= maxRaw {
|
||||
base64.StdEncoding.Encode(buffer[:], b[:maxRaw])
|
||||
w.Write(buffer[:])
|
||||
b = b[maxRaw:]
|
||||
}
|
||||
// Handle the last chunk of bytes.
|
||||
if len(b) > 0 {
|
||||
out := buffer[:base64.StdEncoding.EncodedLen(len(b))]
|
||||
base64.StdEncoding.Encode(out, b)
|
||||
out = append(out, "\r\n"...)
|
||||
w.Write(out)
|
||||
}
|
||||
}
|
||||
|
||||
// Encode returns the encoded-word form of s. If s is ASCII without special
|
||||
// characters, it is returned unchanged. The provided charset is the IANA
|
||||
// charset name of s. It is case insensitive.
|
||||
// RFC 2047 encoded-word
|
||||
func qEncode(charset, s string) string {
|
||||
if !needsEncoding(s) {
|
||||
return s
|
||||
}
|
||||
return encodeWord(charset, s)
|
||||
}
|
||||
|
||||
func needsEncoding(s string) bool {
|
||||
for _, b := range s {
|
||||
if (b < ' ' || b > '~') && b != '\t' {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// encodeWord encodes a string into an encoded-word.
|
||||
func encodeWord(charset, s string) string {
|
||||
buf := getBuffer()
|
||||
|
||||
buf.WriteString("=?")
|
||||
buf.WriteString(charset)
|
||||
buf.WriteByte('?')
|
||||
buf.WriteByte('q')
|
||||
buf.WriteByte('?')
|
||||
|
||||
enc := make([]byte, 3)
|
||||
for i := 0; i < len(s); i++ {
|
||||
b := s[i]
|
||||
switch {
|
||||
case b == ' ':
|
||||
buf.WriteByte('_')
|
||||
case b <= '~' && b >= '!' && b != '=' && b != '?' && b != '_':
|
||||
buf.WriteByte(b)
|
||||
default:
|
||||
enc[0] = '='
|
||||
enc[1] = upperhex[b>>4]
|
||||
enc[2] = upperhex[b&0x0f]
|
||||
buf.Write(enc)
|
||||
}
|
||||
}
|
||||
buf.WriteString("?=")
|
||||
|
||||
es := buf.String()
|
||||
putBuffer(buf)
|
||||
return es
|
||||
}
|
||||
|
||||
var bufPool = sync.Pool{
|
||||
New: func() interface{} {
|
||||
return new(bytes.Buffer)
|
||||
},
|
||||
}
|
||||
|
||||
func getBuffer() *bytes.Buffer {
|
||||
return bufPool.Get().(*bytes.Buffer)
|
||||
}
|
||||
|
||||
func putBuffer(buf *bytes.Buffer) {
|
||||
if buf.Len() > 1024 {
|
||||
return
|
||||
}
|
||||
buf.Reset()
|
||||
bufPool.Put(buf)
|
||||
}
|
44
vendor/github.com/astaxie/beego/utils/rand.go
generated
vendored
44
vendor/github.com/astaxie/beego/utils/rand.go
generated
vendored
@ -1,44 +0,0 @@
|
||||
// Copyright 2014 beego Author. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package utils
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
r "math/rand"
|
||||
"time"
|
||||
)
|
||||
|
||||
var alphaNum = []byte(`0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz`)
|
||||
|
||||
// RandomCreateBytes generate random []byte by specify chars.
|
||||
func RandomCreateBytes(n int, alphabets ...byte) []byte {
|
||||
if len(alphabets) == 0 {
|
||||
alphabets = alphaNum
|
||||
}
|
||||
var bytes = make([]byte, n)
|
||||
var randBy bool
|
||||
if num, err := rand.Read(bytes); num != n || err != nil {
|
||||
r.Seed(time.Now().UnixNano())
|
||||
randBy = true
|
||||
}
|
||||
for i, b := range bytes {
|
||||
if randBy {
|
||||
bytes[i] = alphabets[r.Intn(len(alphabets))]
|
||||
} else {
|
||||
bytes[i] = alphabets[b%byte(len(alphabets))]
|
||||
}
|
||||
}
|
||||
return bytes
|
||||
}
|
91
vendor/github.com/astaxie/beego/utils/safemap.go
generated
vendored
91
vendor/github.com/astaxie/beego/utils/safemap.go
generated
vendored
@ -1,91 +0,0 @@
|
||||
// Copyright 2014 beego Author. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package utils
|
||||
|
||||
import (
|
||||
"sync"
|
||||
)
|
||||
|
||||
// BeeMap is a map with lock
|
||||
type BeeMap struct {
|
||||
lock *sync.RWMutex
|
||||
bm map[interface{}]interface{}
|
||||
}
|
||||
|
||||
// NewBeeMap return new safemap
|
||||
func NewBeeMap() *BeeMap {
|
||||
return &BeeMap{
|
||||
lock: new(sync.RWMutex),
|
||||
bm: make(map[interface{}]interface{}),
|
||||
}
|
||||
}
|
||||
|
||||
// Get from maps return the k's value
|
||||
func (m *BeeMap) Get(k interface{}) interface{} {
|
||||
m.lock.RLock()
|
||||
defer m.lock.RUnlock()
|
||||
if val, ok := m.bm[k]; ok {
|
||||
return val
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Set Maps the given key and value. Returns false
|
||||
// if the key is already in the map and changes nothing.
|
||||
func (m *BeeMap) Set(k interface{}, v interface{}) bool {
|
||||
m.lock.Lock()
|
||||
defer m.lock.Unlock()
|
||||
if val, ok := m.bm[k]; !ok {
|
||||
m.bm[k] = v
|
||||
} else if val != v {
|
||||
m.bm[k] = v
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// Check Returns true if k is exist in the map.
|
||||
func (m *BeeMap) Check(k interface{}) bool {
|
||||
m.lock.RLock()
|
||||
defer m.lock.RUnlock()
|
||||
_, ok := m.bm[k]
|
||||
return ok
|
||||
}
|
||||
|
||||
// Delete the given key and value.
|
||||
func (m *BeeMap) Delete(k interface{}) {
|
||||
m.lock.Lock()
|
||||
defer m.lock.Unlock()
|
||||
delete(m.bm, k)
|
||||
}
|
||||
|
||||
// Items returns all items in safemap.
|
||||
func (m *BeeMap) Items() map[interface{}]interface{} {
|
||||
m.lock.RLock()
|
||||
defer m.lock.RUnlock()
|
||||
r := make(map[interface{}]interface{})
|
||||
for k, v := range m.bm {
|
||||
r[k] = v
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
// Count returns the number of items within the map.
|
||||
func (m *BeeMap) Count() int {
|
||||
m.lock.RLock()
|
||||
defer m.lock.RUnlock()
|
||||
return len(m.bm)
|
||||
}
|
170
vendor/github.com/astaxie/beego/utils/slice.go
generated
vendored
170
vendor/github.com/astaxie/beego/utils/slice.go
generated
vendored
@ -1,170 +0,0 @@
|
||||
// Copyright 2014 beego Author. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package utils
|
||||
|
||||
import (
|
||||
"math/rand"
|
||||
"time"
|
||||
)
|
||||
|
||||
type reducetype func(interface{}) interface{}
|
||||
type filtertype func(interface{}) bool
|
||||
|
||||
// InSlice checks given string in string slice or not.
|
||||
func InSlice(v string, sl []string) bool {
|
||||
for _, vv := range sl {
|
||||
if vv == v {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// InSliceIface checks given interface in interface slice.
|
||||
func InSliceIface(v interface{}, sl []interface{}) bool {
|
||||
for _, vv := range sl {
|
||||
if vv == v {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// SliceRandList generate an int slice from min to max.
|
||||
func SliceRandList(min, max int) []int {
|
||||
if max < min {
|
||||
min, max = max, min
|
||||
}
|
||||
length := max - min + 1
|
||||
t0 := time.Now()
|
||||
rand.Seed(int64(t0.Nanosecond()))
|
||||
list := rand.Perm(length)
|
||||
for index := range list {
|
||||
list[index] += min
|
||||
}
|
||||
return list
|
||||
}
|
||||
|
||||
// SliceMerge merges interface slices to one slice.
|
||||
func SliceMerge(slice1, slice2 []interface{}) (c []interface{}) {
|
||||
c = append(slice1, slice2...)
|
||||
return
|
||||
}
|
||||
|
||||
// SliceReduce generates a new slice after parsing every value by reduce function
|
||||
func SliceReduce(slice []interface{}, a reducetype) (dslice []interface{}) {
|
||||
for _, v := range slice {
|
||||
dslice = append(dslice, a(v))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// SliceRand returns random one from slice.
|
||||
func SliceRand(a []interface{}) (b interface{}) {
|
||||
randnum := rand.Intn(len(a))
|
||||
b = a[randnum]
|
||||
return
|
||||
}
|
||||
|
||||
// SliceSum sums all values in int64 slice.
|
||||
func SliceSum(intslice []int64) (sum int64) {
|
||||
for _, v := range intslice {
|
||||
sum += v
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// SliceFilter generates a new slice after filter function.
|
||||
func SliceFilter(slice []interface{}, a filtertype) (ftslice []interface{}) {
|
||||
for _, v := range slice {
|
||||
if a(v) {
|
||||
ftslice = append(ftslice, v)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// SliceDiff returns diff slice of slice1 - slice2.
|
||||
func SliceDiff(slice1, slice2 []interface{}) (diffslice []interface{}) {
|
||||
for _, v := range slice1 {
|
||||
if !InSliceIface(v, slice2) {
|
||||
diffslice = append(diffslice, v)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// SliceIntersect returns slice that are present in all the slice1 and slice2.
|
||||
func SliceIntersect(slice1, slice2 []interface{}) (diffslice []interface{}) {
|
||||
for _, v := range slice1 {
|
||||
if InSliceIface(v, slice2) {
|
||||
diffslice = append(diffslice, v)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// SliceChunk separates one slice to some sized slice.
|
||||
func SliceChunk(slice []interface{}, size int) (chunkslice [][]interface{}) {
|
||||
if size >= len(slice) {
|
||||
chunkslice = append(chunkslice, slice)
|
||||
return
|
||||
}
|
||||
end := size
|
||||
for i := 0; i <= (len(slice) - size); i += size {
|
||||
chunkslice = append(chunkslice, slice[i:end])
|
||||
end += size
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// SliceRange generates a new slice from begin to end with step duration of int64 number.
|
||||
func SliceRange(start, end, step int64) (intslice []int64) {
|
||||
for i := start; i <= end; i += step {
|
||||
intslice = append(intslice, i)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// SlicePad prepends size number of val into slice.
|
||||
func SlicePad(slice []interface{}, size int, val interface{}) []interface{} {
|
||||
if size <= len(slice) {
|
||||
return slice
|
||||
}
|
||||
for i := 0; i < (size - len(slice)); i++ {
|
||||
slice = append(slice, val)
|
||||
}
|
||||
return slice
|
||||
}
|
||||
|
||||
// SliceUnique cleans repeated values in slice.
|
||||
func SliceUnique(slice []interface{}) (uniqueslice []interface{}) {
|
||||
for _, v := range slice {
|
||||
if !InSliceIface(v, uniqueslice) {
|
||||
uniqueslice = append(uniqueslice, v)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// SliceShuffle shuffles a slice.
|
||||
func SliceShuffle(slice []interface{}) []interface{} {
|
||||
for i := 0; i < len(slice); i++ {
|
||||
a := rand.Intn(len(slice))
|
||||
b := rand.Intn(len(slice))
|
||||
slice[a], slice[b] = slice[b], slice[a]
|
||||
}
|
||||
return slice
|
||||
}
|
20
vendor/github.com/derekparker/delve/LICENSE
generated
vendored
20
vendor/github.com/derekparker/delve/LICENSE
generated
vendored
@ -1,20 +0,0 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2014 Derek Parker
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
134
vendor/github.com/derekparker/delve/config/config.go
generated
vendored
134
vendor/github.com/derekparker/delve/config/config.go
generated
vendored
@ -1,134 +0,0 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/user"
|
||||
"path"
|
||||
|
||||
yaml "gopkg.in/yaml.v2"
|
||||
)
|
||||
|
||||
const (
|
||||
configDir string = ".dlv"
|
||||
configFile string = "config.yml"
|
||||
)
|
||||
|
||||
// Describes a rule for substitution of path to source code file.
|
||||
type SubstitutePathRule struct {
|
||||
// Directory path will be substituted if it matches `From`.
|
||||
From string
|
||||
// Path to which substitution is performed.
|
||||
To string
|
||||
}
|
||||
|
||||
// Slice of source code path substitution rules.
|
||||
type SubstitutePathRules []SubstitutePathRule
|
||||
|
||||
// Config defines all configuration options available to be set through the config file.
|
||||
type Config struct {
|
||||
// Commands aliases.
|
||||
Aliases map[string][]string
|
||||
// Source code path substitution rules.
|
||||
SubstitutePath SubstitutePathRules `yaml:"substitute-path"`
|
||||
}
|
||||
|
||||
// LoadConfig attempts to populate a Config object from the config.yml file.
|
||||
func LoadConfig() *Config {
|
||||
err := createConfigPath()
|
||||
if err != nil {
|
||||
fmt.Printf("Could not create config directory: %v.", err)
|
||||
return nil
|
||||
}
|
||||
fullConfigFile, err := GetConfigFilePath(configFile)
|
||||
if err != nil {
|
||||
fmt.Printf("Unable to get config file path: %v.", err)
|
||||
return nil
|
||||
}
|
||||
|
||||
f, err := os.Open(fullConfigFile)
|
||||
if err != nil {
|
||||
createDefaultConfig(fullConfigFile)
|
||||
return nil
|
||||
}
|
||||
defer func() {
|
||||
err := f.Close()
|
||||
if err != nil {
|
||||
fmt.Printf("Closing config file failed: %v.", err)
|
||||
}
|
||||
}()
|
||||
|
||||
data, err := ioutil.ReadAll(f)
|
||||
if err != nil {
|
||||
fmt.Printf("Unable to read config data: %v.", err)
|
||||
return nil
|
||||
}
|
||||
|
||||
var c Config
|
||||
err = yaml.Unmarshal(data, &c)
|
||||
if err != nil {
|
||||
fmt.Printf("Unable to decode config file: %v.", err)
|
||||
return nil
|
||||
}
|
||||
|
||||
return &c
|
||||
}
|
||||
|
||||
func createDefaultConfig(path string) {
|
||||
f, err := os.Create(path)
|
||||
if err != nil {
|
||||
fmt.Printf("Unable to create config file: %v.", err)
|
||||
return
|
||||
}
|
||||
defer func() {
|
||||
err := f.Close()
|
||||
if err != nil {
|
||||
fmt.Printf("Closing config file failed: %v.", err)
|
||||
}
|
||||
}()
|
||||
err = writeDefaultConfig(f)
|
||||
if err != nil {
|
||||
fmt.Printf("Unable to write default configuration: %v.", err)
|
||||
}
|
||||
}
|
||||
|
||||
func writeDefaultConfig(f *os.File) error {
|
||||
_, err := f.WriteString(
|
||||
`# Configuration file for the delve debugger.
|
||||
|
||||
# This is the default configuration file. Available options are provided, but disabled.
|
||||
# Delete the leading hash mark to enable an item.
|
||||
|
||||
# Provided aliases will be added to the default aliases for a given command.
|
||||
aliases:
|
||||
# command: ["alias1", "alias2"]
|
||||
|
||||
# Define sources path substitution rules. Can be used to rewrite a source path stored
|
||||
# in program's debug information, if the sources were moved to a different place
|
||||
# between compilation and debugging.
|
||||
# Note that substitution rules will not be used for paths passed to "break" and "trace"
|
||||
# commands.
|
||||
substitute-path:
|
||||
# - {from: path, to: path}
|
||||
`)
|
||||
return err
|
||||
}
|
||||
|
||||
// createConfigPath creates the directory structure at which all config files are saved.
|
||||
func createConfigPath() error {
|
||||
path, err := GetConfigFilePath("")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return os.MkdirAll(path, 0700)
|
||||
}
|
||||
|
||||
// GetConfigFilePath gets the full path to the given config file name.
|
||||
func GetConfigFilePath(file string) (string, error) {
|
||||
usr, err := user.Current()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return path.Join(usr.HomeDir, configDir, file), nil
|
||||
}
|
95
vendor/github.com/derekparker/delve/dwarf/frame/entries.go
generated
vendored
95
vendor/github.com/derekparker/delve/dwarf/frame/entries.go
generated
vendored
@ -1,95 +0,0 @@
|
||||
package frame
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"sort"
|
||||
)
|
||||
|
||||
// Represents a Common Information Entry in
|
||||
// the Dwarf .debug_frame section.
|
||||
type CommonInformationEntry struct {
|
||||
Length uint32
|
||||
CIE_id uint32
|
||||
Version uint8
|
||||
Augmentation string
|
||||
CodeAlignmentFactor uint64
|
||||
DataAlignmentFactor int64
|
||||
ReturnAddressRegister uint64
|
||||
InitialInstructions []byte
|
||||
}
|
||||
|
||||
// Represents a Frame Descriptor Entry in the
|
||||
// Dwarf .debug_frame section.
|
||||
type FrameDescriptionEntry struct {
|
||||
Length uint32
|
||||
CIE *CommonInformationEntry
|
||||
Instructions []byte
|
||||
begin, end uint64
|
||||
order binary.ByteOrder
|
||||
}
|
||||
|
||||
// Returns whether or not the given address is within the
|
||||
// bounds of this frame.
|
||||
func (fde *FrameDescriptionEntry) Cover(addr uint64) bool {
|
||||
if (addr - fde.begin) < fde.end {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Address of first location for this frame.
|
||||
func (fde *FrameDescriptionEntry) Begin() uint64 {
|
||||
return fde.begin
|
||||
}
|
||||
|
||||
// Address of last location for this frame.
|
||||
func (fde *FrameDescriptionEntry) End() uint64 {
|
||||
return fde.begin + fde.end
|
||||
}
|
||||
|
||||
// Set up frame for the given PC.
|
||||
func (fde *FrameDescriptionEntry) EstablishFrame(pc uint64) *FrameContext {
|
||||
return executeDwarfProgramUntilPC(fde, pc)
|
||||
}
|
||||
|
||||
// Return the offset from the current SP that the return address is stored at.
|
||||
func (fde *FrameDescriptionEntry) ReturnAddressOffset(pc uint64) (frameOffset, returnAddressOffset int64) {
|
||||
frame := fde.EstablishFrame(pc)
|
||||
return frame.cfa.offset, frame.regs[fde.CIE.ReturnAddressRegister].offset
|
||||
}
|
||||
|
||||
type FrameDescriptionEntries []*FrameDescriptionEntry
|
||||
|
||||
func NewFrameIndex() FrameDescriptionEntries {
|
||||
return make(FrameDescriptionEntries, 0, 1000)
|
||||
}
|
||||
|
||||
type NoFDEForPCError struct {
|
||||
PC uint64
|
||||
}
|
||||
|
||||
func (err *NoFDEForPCError) Error() string {
|
||||
return fmt.Sprintf("could not find FDE for PC %#v", err.PC)
|
||||
}
|
||||
|
||||
// Returns the Frame Description Entry for the given PC.
|
||||
func (fdes FrameDescriptionEntries) FDEForPC(pc uint64) (*FrameDescriptionEntry, error) {
|
||||
idx := sort.Search(len(fdes), func(i int) bool {
|
||||
if fdes[i].Cover(pc) {
|
||||
return true
|
||||
}
|
||||
if fdes[i].LessThan(pc) {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
})
|
||||
if idx == len(fdes) {
|
||||
return nil, &NoFDEForPCError{pc}
|
||||
}
|
||||
return fdes[idx], nil
|
||||
}
|
||||
|
||||
func (frame *FrameDescriptionEntry) LessThan(pc uint64) bool {
|
||||
return frame.End() <= pc
|
||||
}
|
164
vendor/github.com/derekparker/delve/dwarf/frame/expression_constants.go
generated
vendored
164
vendor/github.com/derekparker/delve/dwarf/frame/expression_constants.go
generated
vendored
@ -1,164 +0,0 @@
|
||||
package frame
|
||||
|
||||
// Operation opcodes
|
||||
const (
|
||||
DW_OP_addr = 0x03
|
||||
DW_OP_const1s = 0x09
|
||||
)
|
||||
|
||||
const (
|
||||
DW_OP_const2u = 0x0a
|
||||
DW_OP_const2s = 0x0b
|
||||
DW_OP_const4u = iota
|
||||
DW_OP_const4s
|
||||
DW_OP_const8u
|
||||
DW_OP_const8s
|
||||
DW_OP_constu
|
||||
DW_OP_consts
|
||||
DW_OP_dup
|
||||
DW_OP_drop
|
||||
DW_OP_over
|
||||
DW_OP_pick
|
||||
DW_OP_swap
|
||||
DW_OP_rot
|
||||
DW_OP_xderef
|
||||
DW_OP_abs
|
||||
DW_OP_and
|
||||
DW_OP_div
|
||||
DW_OP_minus
|
||||
DW_OP_mod
|
||||
DW_OP_mul
|
||||
DW_OP_neg
|
||||
DW_OP_not
|
||||
DW_OP_or
|
||||
DW_OP_plus
|
||||
DW_OP_plus_uconst
|
||||
DW_OP_shl
|
||||
DW_OP_shr
|
||||
DW_OP_shra
|
||||
DW_OP_xor
|
||||
DW_OP_skip
|
||||
DW_OP_bra
|
||||
DW_OP_eq
|
||||
DW_OP_ge
|
||||
DW_OP_gt
|
||||
DW_OP_le
|
||||
DW_OP_lt
|
||||
DW_OP_ne
|
||||
)
|
||||
|
||||
const (
|
||||
DW_OP_lit0 = 0x30
|
||||
DW_OP_lit1 = 0x31
|
||||
DW_OP_lit2 = iota
|
||||
DW_OP_lit3
|
||||
DW_OP_lit4
|
||||
DW_OP_lit5
|
||||
DW_OP_lit6
|
||||
DW_OP_lit7
|
||||
DW_OP_lit8
|
||||
DW_OP_lit9
|
||||
DW_OP_lit10
|
||||
DW_OP_lit11
|
||||
DW_OP_lit12
|
||||
DW_OP_lit13
|
||||
DW_OP_lit14
|
||||
DW_OP_lit15
|
||||
DW_OP_lit16
|
||||
DW_OP_lit17
|
||||
DW_OP_lit18
|
||||
DW_OP_lit19
|
||||
DW_OP_lit20
|
||||
DW_OP_lit21
|
||||
DW_OP_lit22
|
||||
DW_OP_lit23
|
||||
DW_OP_lit24
|
||||
DW_OP_lit25
|
||||
DW_OP_lit26
|
||||
DW_OP_lit27
|
||||
DW_OP_lit28
|
||||
DW_OP_lit29
|
||||
DW_OP_lit30
|
||||
DW_OP_lit31
|
||||
DW_OP_reg0
|
||||
DW_OP_reg1
|
||||
DW_OP_reg2
|
||||
DW_OP_reg3
|
||||
DW_OP_reg4
|
||||
DW_OP_reg5
|
||||
DW_OP_reg6
|
||||
DW_OP_reg7
|
||||
DW_OP_reg8
|
||||
DW_OP_reg9
|
||||
DW_OP_reg10
|
||||
DW_OP_reg11
|
||||
DW_OP_reg12
|
||||
DW_OP_reg13
|
||||
DW_OP_reg14
|
||||
DW_OP_reg15
|
||||
DW_OP_reg16
|
||||
DW_OP_reg17
|
||||
DW_OP_reg18
|
||||
DW_OP_reg19
|
||||
DW_OP_reg20
|
||||
DW_OP_reg21
|
||||
DW_OP_reg22
|
||||
DW_OP_reg23
|
||||
DW_OP_reg24
|
||||
DW_OP_reg25
|
||||
DW_OP_reg26
|
||||
DW_OP_reg27
|
||||
DW_OP_reg28
|
||||
DW_OP_reg29
|
||||
DW_OP_reg30
|
||||
DW_OP_reg31
|
||||
DW_OP_breg0
|
||||
DW_OP_breg1
|
||||
DW_OP_breg2
|
||||
DW_OP_breg3
|
||||
DW_OP_breg4
|
||||
DW_OP_breg5
|
||||
DW_OP_breg6
|
||||
DW_OP_breg7
|
||||
DW_OP_breg8
|
||||
DW_OP_breg9
|
||||
DW_OP_breg10
|
||||
DW_OP_breg11
|
||||
DW_OP_breg12
|
||||
DW_OP_breg13
|
||||
DW_OP_breg14
|
||||
DW_OP_breg15
|
||||
DW_OP_breg16
|
||||
DW_OP_breg17
|
||||
DW_OP_breg18
|
||||
DW_OP_breg19
|
||||
DW_OP_breg20
|
||||
DW_OP_breg21
|
||||
DW_OP_breg22
|
||||
DW_OP_breg23
|
||||
DW_OP_breg24
|
||||
DW_OP_breg25
|
||||
DW_OP_breg26
|
||||
DW_OP_breg27
|
||||
DW_OP_breg28
|
||||
DW_OP_breg29
|
||||
DW_OP_breg30
|
||||
DW_OP_breg31
|
||||
DW_OP_regx
|
||||
DW_OP_fbreg
|
||||
DW_OP_bregx
|
||||
DW_OP_piece
|
||||
DW_OP_deref_size
|
||||
DW_OP_xderef_size
|
||||
DW_OP_nop
|
||||
DW_OP_push_object_address
|
||||
DW_OP_call2
|
||||
DW_OP_call4
|
||||
DW_OP_call_ref
|
||||
DW_OP_form_tls_address
|
||||
DW_OP_call_frame_cfa
|
||||
DW_OP_bit_piece
|
||||
|
||||
DW_OP_lo_user = 0xe0
|
||||
DW_OP_hi_user = 0xff
|
||||
)
|
125
vendor/github.com/derekparker/delve/dwarf/frame/parser.go
generated
vendored
125
vendor/github.com/derekparker/delve/dwarf/frame/parser.go
generated
vendored
@ -1,125 +0,0 @@
|
||||
// Package frame contains data structures and
|
||||
// related functions for parsing and searching
|
||||
// through Dwarf .debug_frame data.
|
||||
package frame
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
|
||||
"github.com/derekparker/delve/dwarf/util"
|
||||
)
|
||||
|
||||
type parsefunc func(*parseContext) parsefunc
|
||||
|
||||
type parseContext struct {
|
||||
buf *bytes.Buffer
|
||||
entries FrameDescriptionEntries
|
||||
common *CommonInformationEntry
|
||||
frame *FrameDescriptionEntry
|
||||
length uint32
|
||||
}
|
||||
|
||||
// Parse takes in data (a byte slice) and returns a slice of
|
||||
// commonInformationEntry structures. Each commonInformationEntry
|
||||
// has a slice of frameDescriptionEntry structures.
|
||||
func Parse(data []byte, order binary.ByteOrder) FrameDescriptionEntries {
|
||||
var (
|
||||
buf = bytes.NewBuffer(data)
|
||||
pctx = &parseContext{buf: buf, entries: NewFrameIndex()}
|
||||
)
|
||||
|
||||
for fn := parselength; buf.Len() != 0; {
|
||||
fn = fn(pctx)
|
||||
}
|
||||
|
||||
for i := range pctx.entries {
|
||||
pctx.entries[i].order = order
|
||||
}
|
||||
|
||||
return pctx.entries
|
||||
}
|
||||
|
||||
func cieEntry(data []byte) bool {
|
||||
return bytes.Equal(data, []byte{0xff, 0xff, 0xff, 0xff})
|
||||
}
|
||||
|
||||
func parselength(ctx *parseContext) parsefunc {
|
||||
var data = ctx.buf.Next(8)
|
||||
|
||||
ctx.length = binary.LittleEndian.Uint32(data[:4]) - 4 // take off the length of the CIE id / CIE pointer.
|
||||
|
||||
if cieEntry(data[4:]) {
|
||||
ctx.common = &CommonInformationEntry{Length: ctx.length}
|
||||
return parseCIE
|
||||
}
|
||||
|
||||
ctx.frame = &FrameDescriptionEntry{Length: ctx.length, CIE: ctx.common}
|
||||
return parseFDE
|
||||
}
|
||||
|
||||
func parseFDE(ctx *parseContext) parsefunc {
|
||||
r := ctx.buf.Next(int(ctx.length))
|
||||
|
||||
ctx.frame.begin = binary.LittleEndian.Uint64(r[:8])
|
||||
ctx.frame.end = binary.LittleEndian.Uint64(r[8:16])
|
||||
|
||||
// Insert into the tree after setting address range begin
|
||||
// otherwise compares won't work.
|
||||
ctx.entries = append(ctx.entries, ctx.frame)
|
||||
|
||||
// The rest of this entry consists of the instructions
|
||||
// so we can just grab all of the data from the buffer
|
||||
// cursor to length.
|
||||
ctx.frame.Instructions = r[16:]
|
||||
ctx.length = 0
|
||||
|
||||
return parselength
|
||||
}
|
||||
|
||||
func parseCIE(ctx *parseContext) parsefunc {
|
||||
data := ctx.buf.Next(int(ctx.length))
|
||||
buf := bytes.NewBuffer(data)
|
||||
// parse version
|
||||
ctx.common.Version = data[0]
|
||||
|
||||
// parse augmentation
|
||||
ctx.common.Augmentation, _ = util.ParseString(buf)
|
||||
|
||||
// parse code alignment factor
|
||||
ctx.common.CodeAlignmentFactor, _ = util.DecodeULEB128(buf)
|
||||
|
||||
// parse data alignment factor
|
||||
ctx.common.DataAlignmentFactor, _ = util.DecodeSLEB128(buf)
|
||||
|
||||
// parse return address register
|
||||
ctx.common.ReturnAddressRegister, _ = util.DecodeULEB128(buf)
|
||||
|
||||
// parse initial instructions
|
||||
// The rest of this entry consists of the instructions
|
||||
// so we can just grab all of the data from the buffer
|
||||
// cursor to length.
|
||||
ctx.common.InitialInstructions = buf.Bytes() //ctx.buf.Next(int(ctx.length))
|
||||
ctx.length = 0
|
||||
|
||||
return parselength
|
||||
}
|
||||
|
||||
// DwarfEndian determines the endianness of the DWARF by using the version number field in the debug_info section
|
||||
// Trick borrowed from "debug/dwarf".New()
|
||||
func DwarfEndian(infoSec []byte) binary.ByteOrder {
|
||||
if len(infoSec) < 6 {
|
||||
return binary.BigEndian
|
||||
}
|
||||
x, y := infoSec[4], infoSec[5]
|
||||
switch {
|
||||
case x == 0 && y == 0:
|
||||
return binary.BigEndian
|
||||
case x == 0:
|
||||
return binary.BigEndian
|
||||
case y == 0:
|
||||
return binary.LittleEndian
|
||||
default:
|
||||
return binary.BigEndian
|
||||
}
|
||||
}
|
429
vendor/github.com/derekparker/delve/dwarf/frame/table.go
generated
vendored
429
vendor/github.com/derekparker/delve/dwarf/frame/table.go
generated
vendored
@ -1,429 +0,0 @@
|
||||
package frame
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
|
||||
"github.com/derekparker/delve/dwarf/util"
|
||||
)
|
||||
|
||||
type CurrentFrameAddress struct {
|
||||
register uint64
|
||||
offset int64
|
||||
expression []byte
|
||||
rule byte
|
||||
}
|
||||
|
||||
type DWRule struct {
|
||||
rule byte
|
||||
offset int64
|
||||
newreg uint64
|
||||
expression []byte
|
||||
}
|
||||
|
||||
type FrameContext struct {
|
||||
loc uint64
|
||||
order binary.ByteOrder
|
||||
address uint64
|
||||
cfa CurrentFrameAddress
|
||||
regs map[uint64]DWRule
|
||||
initialRegs map[uint64]DWRule
|
||||
prevRegs map[uint64]DWRule
|
||||
buf *bytes.Buffer
|
||||
cie *CommonInformationEntry
|
||||
codeAlignment uint64
|
||||
dataAlignment int64
|
||||
}
|
||||
|
||||
func (fctx *FrameContext) CFAOffset() int64 {
|
||||
return fctx.cfa.offset
|
||||
}
|
||||
|
||||
// Instructions used to recreate the table from the .debug_frame data.
|
||||
const (
|
||||
DW_CFA_nop = 0x0 // No ops
|
||||
DW_CFA_set_loc = 0x01 // op1: address
|
||||
DW_CFA_advance_loc1 = iota // op1: 1-bytes delta
|
||||
DW_CFA_advance_loc2 // op1: 2-byte delta
|
||||
DW_CFA_advance_loc4 // op1: 4-byte delta
|
||||
DW_CFA_offset_extended // op1: ULEB128 register, op2: ULEB128 offset
|
||||
DW_CFA_restore_extended // op1: ULEB128 register
|
||||
DW_CFA_undefined // op1: ULEB128 register
|
||||
DW_CFA_same_value // op1: ULEB128 register
|
||||
DW_CFA_register // op1: ULEB128 register, op2: ULEB128 register
|
||||
DW_CFA_remember_state // No ops
|
||||
DW_CFA_restore_state // No ops
|
||||
DW_CFA_def_cfa // op1: ULEB128 register, op2: ULEB128 offset
|
||||
DW_CFA_def_cfa_register // op1: ULEB128 register
|
||||
DW_CFA_def_cfa_offset // op1: ULEB128 offset
|
||||
DW_CFA_def_cfa_expression // op1: BLOCK
|
||||
DW_CFA_expression // op1: ULEB128 register, op2: BLOCK
|
||||
DW_CFA_offset_extended_sf // op1: ULEB128 register, op2: SLEB128 BLOCK
|
||||
DW_CFA_def_cfa_sf // op1: ULEB128 register, op2: SLEB128 offset
|
||||
DW_CFA_def_cfa_offset_sf // op1: SLEB128 offset
|
||||
DW_CFA_val_offset // op1: ULEB128, op2: ULEB128
|
||||
DW_CFA_val_offset_sf // op1: ULEB128, op2: SLEB128
|
||||
DW_CFA_val_expression // op1: ULEB128, op2: BLOCK
|
||||
DW_CFA_lo_user = 0x1c // op1: BLOCK
|
||||
DW_CFA_hi_user = 0x3f // op1: ULEB128 register, op2: BLOCK
|
||||
DW_CFA_advance_loc = (0x1 << 6) // High 2 bits: 0x1, low 6: delta
|
||||
DW_CFA_offset = (0x2 << 6) // High 2 bits: 0x2, low 6: register
|
||||
DW_CFA_restore = (0x3 << 6) // High 2 bits: 0x3, low 6: register
|
||||
)
|
||||
|
||||
// Rules defined for register values.
|
||||
const (
|
||||
rule_undefined = iota
|
||||
rule_sameval
|
||||
rule_offset
|
||||
rule_valoffset
|
||||
rule_register
|
||||
rule_expression
|
||||
rule_valexpression
|
||||
rule_architectural
|
||||
)
|
||||
|
||||
const low_6_offset = 0x3f
|
||||
|
||||
type instruction func(frame *FrameContext)
|
||||
|
||||
// // Mapping from DWARF opcode to function.
|
||||
var fnlookup = map[byte]instruction{
|
||||
DW_CFA_advance_loc: advanceloc,
|
||||
DW_CFA_offset: offset,
|
||||
DW_CFA_restore: restore,
|
||||
DW_CFA_set_loc: setloc,
|
||||
DW_CFA_advance_loc1: advanceloc1,
|
||||
DW_CFA_advance_loc2: advanceloc2,
|
||||
DW_CFA_advance_loc4: advanceloc4,
|
||||
DW_CFA_offset_extended: offsetextended,
|
||||
DW_CFA_restore_extended: restoreextended,
|
||||
DW_CFA_undefined: undefined,
|
||||
DW_CFA_same_value: samevalue,
|
||||
DW_CFA_register: register,
|
||||
DW_CFA_remember_state: rememberstate,
|
||||
DW_CFA_restore_state: restorestate,
|
||||
DW_CFA_def_cfa: defcfa,
|
||||
DW_CFA_def_cfa_register: defcfaregister,
|
||||
DW_CFA_def_cfa_offset: defcfaoffset,
|
||||
DW_CFA_def_cfa_expression: defcfaexpression,
|
||||
DW_CFA_expression: expression,
|
||||
DW_CFA_offset_extended_sf: offsetextendedsf,
|
||||
DW_CFA_def_cfa_sf: defcfasf,
|
||||
DW_CFA_def_cfa_offset_sf: defcfaoffsetsf,
|
||||
DW_CFA_val_offset: valoffset,
|
||||
DW_CFA_val_offset_sf: valoffsetsf,
|
||||
DW_CFA_val_expression: valexpression,
|
||||
DW_CFA_lo_user: louser,
|
||||
DW_CFA_hi_user: hiuser,
|
||||
}
|
||||
|
||||
func executeCIEInstructions(cie *CommonInformationEntry) *FrameContext {
|
||||
initialInstructions := make([]byte, len(cie.InitialInstructions))
|
||||
copy(initialInstructions, cie.InitialInstructions)
|
||||
frame := &FrameContext{
|
||||
cie: cie,
|
||||
regs: make(map[uint64]DWRule),
|
||||
initialRegs: make(map[uint64]DWRule),
|
||||
prevRegs: make(map[uint64]DWRule),
|
||||
codeAlignment: cie.CodeAlignmentFactor,
|
||||
dataAlignment: cie.DataAlignmentFactor,
|
||||
buf: bytes.NewBuffer(initialInstructions),
|
||||
}
|
||||
|
||||
frame.ExecuteDwarfProgram()
|
||||
return frame
|
||||
}
|
||||
|
||||
// Unwind the stack to find the return address register.
|
||||
func executeDwarfProgramUntilPC(fde *FrameDescriptionEntry, pc uint64) *FrameContext {
|
||||
frame := executeCIEInstructions(fde.CIE)
|
||||
frame.order = fde.order
|
||||
frame.loc = fde.Begin()
|
||||
frame.address = pc
|
||||
fdeInstructions := make([]byte, len(fde.Instructions))
|
||||
copy(fdeInstructions, fde.Instructions)
|
||||
frame.ExecuteUntilPC(fdeInstructions)
|
||||
|
||||
return frame
|
||||
}
|
||||
|
||||
func (frame *FrameContext) ExecuteDwarfProgram() {
|
||||
for frame.buf.Len() > 0 {
|
||||
executeDwarfInstruction(frame)
|
||||
}
|
||||
}
|
||||
|
||||
// Execute dwarf instructions.
|
||||
func (frame *FrameContext) ExecuteUntilPC(instructions []byte) {
|
||||
frame.buf.Truncate(0)
|
||||
frame.buf.Write(instructions)
|
||||
|
||||
// We only need to execute the instructions until
|
||||
// ctx.loc > ctx.addess (which is the address we
|
||||
// are currently at in the traced process).
|
||||
for frame.address >= frame.loc && frame.buf.Len() > 0 {
|
||||
executeDwarfInstruction(frame)
|
||||
}
|
||||
}
|
||||
|
||||
func executeDwarfInstruction(frame *FrameContext) {
|
||||
instruction, err := frame.buf.ReadByte()
|
||||
if err != nil {
|
||||
panic("Could not read from instruction buffer")
|
||||
}
|
||||
|
||||
if instruction == DW_CFA_nop {
|
||||
return
|
||||
}
|
||||
|
||||
fn := lookupFunc(instruction, frame.buf)
|
||||
|
||||
fn(frame)
|
||||
}
|
||||
|
||||
func lookupFunc(instruction byte, buf *bytes.Buffer) instruction {
|
||||
const high_2_bits = 0xc0
|
||||
var restore bool
|
||||
|
||||
// Special case the 3 opcodes that have their argument encoded in the opcode itself.
|
||||
switch instruction & high_2_bits {
|
||||
case DW_CFA_advance_loc:
|
||||
instruction = DW_CFA_advance_loc
|
||||
restore = true
|
||||
|
||||
case DW_CFA_offset:
|
||||
instruction = DW_CFA_offset
|
||||
restore = true
|
||||
|
||||
case DW_CFA_restore:
|
||||
instruction = DW_CFA_restore
|
||||
restore = true
|
||||
}
|
||||
|
||||
if restore {
|
||||
// Restore the last byte as it actually contains the argument for the opcode.
|
||||
err := buf.UnreadByte()
|
||||
if err != nil {
|
||||
panic("Could not unread byte")
|
||||
}
|
||||
}
|
||||
|
||||
fn, ok := fnlookup[instruction]
|
||||
if !ok {
|
||||
panic(fmt.Sprintf("Encountered an unexpected DWARF CFA opcode: %#v", instruction))
|
||||
}
|
||||
|
||||
return fn
|
||||
}
|
||||
|
||||
func advanceloc(frame *FrameContext) {
|
||||
b, err := frame.buf.ReadByte()
|
||||
if err != nil {
|
||||
panic("Could not read byte")
|
||||
}
|
||||
|
||||
delta := b & low_6_offset
|
||||
frame.loc += uint64(delta) * frame.codeAlignment
|
||||
}
|
||||
|
||||
func advanceloc1(frame *FrameContext) {
|
||||
delta, err := frame.buf.ReadByte()
|
||||
if err != nil {
|
||||
panic("Could not read byte")
|
||||
}
|
||||
|
||||
frame.loc += uint64(delta) * frame.codeAlignment
|
||||
}
|
||||
|
||||
func advanceloc2(frame *FrameContext) {
|
||||
var delta uint16
|
||||
binary.Read(frame.buf, frame.order, &delta)
|
||||
|
||||
frame.loc += uint64(delta) * frame.codeAlignment
|
||||
}
|
||||
|
||||
func advanceloc4(frame *FrameContext) {
|
||||
var delta uint32
|
||||
binary.Read(frame.buf, frame.order, &delta)
|
||||
|
||||
frame.loc += uint64(delta) * frame.codeAlignment
|
||||
}
|
||||
|
||||
func offset(frame *FrameContext) {
|
||||
b, err := frame.buf.ReadByte()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
var (
|
||||
reg = b & low_6_offset
|
||||
offset, _ = util.DecodeULEB128(frame.buf)
|
||||
)
|
||||
|
||||
frame.regs[uint64(reg)] = DWRule{offset: int64(offset) * frame.dataAlignment, rule: rule_offset}
|
||||
}
|
||||
|
||||
func restore(frame *FrameContext) {
|
||||
b, err := frame.buf.ReadByte()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
reg := uint64(b & low_6_offset)
|
||||
oldrule, ok := frame.initialRegs[reg]
|
||||
if ok {
|
||||
frame.regs[reg] = DWRule{offset: oldrule.offset, rule: rule_offset}
|
||||
} else {
|
||||
frame.regs[reg] = DWRule{rule: rule_undefined}
|
||||
}
|
||||
}
|
||||
|
||||
func setloc(frame *FrameContext) {
|
||||
var loc uint64
|
||||
binary.Read(frame.buf, frame.order, &loc)
|
||||
|
||||
frame.loc = loc
|
||||
}
|
||||
|
||||
func offsetextended(frame *FrameContext) {
|
||||
var (
|
||||
reg, _ = util.DecodeULEB128(frame.buf)
|
||||
offset, _ = util.DecodeULEB128(frame.buf)
|
||||
)
|
||||
|
||||
frame.regs[reg] = DWRule{offset: int64(offset) * frame.dataAlignment, rule: rule_offset}
|
||||
}
|
||||
|
||||
func undefined(frame *FrameContext) {
|
||||
reg, _ := util.DecodeULEB128(frame.buf)
|
||||
frame.regs[reg] = DWRule{rule: rule_undefined}
|
||||
}
|
||||
|
||||
func samevalue(frame *FrameContext) {
|
||||
reg, _ := util.DecodeULEB128(frame.buf)
|
||||
frame.regs[reg] = DWRule{rule: rule_sameval}
|
||||
}
|
||||
|
||||
func register(frame *FrameContext) {
|
||||
reg1, _ := util.DecodeULEB128(frame.buf)
|
||||
reg2, _ := util.DecodeULEB128(frame.buf)
|
||||
frame.regs[reg1] = DWRule{newreg: reg2, rule: rule_register}
|
||||
}
|
||||
|
||||
func rememberstate(frame *FrameContext) {
|
||||
frame.prevRegs = frame.regs
|
||||
}
|
||||
|
||||
func restorestate(frame *FrameContext) {
|
||||
frame.regs = frame.prevRegs
|
||||
}
|
||||
|
||||
func restoreextended(frame *FrameContext) {
|
||||
reg, _ := util.DecodeULEB128(frame.buf)
|
||||
|
||||
oldrule, ok := frame.initialRegs[reg]
|
||||
if ok {
|
||||
frame.regs[reg] = DWRule{offset: oldrule.offset, rule: rule_offset}
|
||||
} else {
|
||||
frame.regs[reg] = DWRule{rule: rule_undefined}
|
||||
}
|
||||
}
|
||||
|
||||
func defcfa(frame *FrameContext) {
|
||||
reg, _ := util.DecodeULEB128(frame.buf)
|
||||
offset, _ := util.DecodeULEB128(frame.buf)
|
||||
|
||||
frame.cfa.register = reg
|
||||
frame.cfa.offset = int64(offset)
|
||||
}
|
||||
|
||||
func defcfaregister(frame *FrameContext) {
|
||||
reg, _ := util.DecodeULEB128(frame.buf)
|
||||
frame.cfa.register = reg
|
||||
}
|
||||
|
||||
func defcfaoffset(frame *FrameContext) {
|
||||
offset, _ := util.DecodeULEB128(frame.buf)
|
||||
frame.cfa.offset = int64(offset)
|
||||
}
|
||||
|
||||
func defcfasf(frame *FrameContext) {
|
||||
reg, _ := util.DecodeULEB128(frame.buf)
|
||||
offset, _ := util.DecodeSLEB128(frame.buf)
|
||||
|
||||
frame.cfa.register = reg
|
||||
frame.cfa.offset = offset * frame.dataAlignment
|
||||
}
|
||||
|
||||
func defcfaoffsetsf(frame *FrameContext) {
|
||||
offset, _ := util.DecodeSLEB128(frame.buf)
|
||||
offset *= frame.dataAlignment
|
||||
frame.cfa.offset = offset
|
||||
}
|
||||
|
||||
func defcfaexpression(frame *FrameContext) {
|
||||
var (
|
||||
l, _ = util.DecodeULEB128(frame.buf)
|
||||
expr = frame.buf.Next(int(l))
|
||||
)
|
||||
|
||||
frame.cfa.expression = expr
|
||||
frame.cfa.rule = rule_expression
|
||||
}
|
||||
|
||||
func expression(frame *FrameContext) {
|
||||
var (
|
||||
reg, _ = util.DecodeULEB128(frame.buf)
|
||||
l, _ = util.DecodeULEB128(frame.buf)
|
||||
expr = frame.buf.Next(int(l))
|
||||
)
|
||||
|
||||
frame.regs[reg] = DWRule{rule: rule_expression, expression: expr}
|
||||
}
|
||||
|
||||
func offsetextendedsf(frame *FrameContext) {
|
||||
var (
|
||||
reg, _ = util.DecodeULEB128(frame.buf)
|
||||
offset, _ = util.DecodeSLEB128(frame.buf)
|
||||
)
|
||||
|
||||
frame.regs[reg] = DWRule{offset: offset * frame.dataAlignment, rule: rule_offset}
|
||||
}
|
||||
|
||||
func valoffset(frame *FrameContext) {
|
||||
var (
|
||||
reg, _ = util.DecodeULEB128(frame.buf)
|
||||
offset, _ = util.DecodeULEB128(frame.buf)
|
||||
)
|
||||
|
||||
frame.regs[reg] = DWRule{offset: int64(offset), rule: rule_valoffset}
|
||||
}
|
||||
|
||||
func valoffsetsf(frame *FrameContext) {
|
||||
var (
|
||||
reg, _ = util.DecodeULEB128(frame.buf)
|
||||
offset, _ = util.DecodeSLEB128(frame.buf)
|
||||
)
|
||||
|
||||
frame.regs[reg] = DWRule{offset: offset * frame.dataAlignment, rule: rule_valoffset}
|
||||
}
|
||||
|
||||
func valexpression(frame *FrameContext) {
|
||||
var (
|
||||
reg, _ = util.DecodeULEB128(frame.buf)
|
||||
l, _ = util.DecodeULEB128(frame.buf)
|
||||
expr = frame.buf.Next(int(l))
|
||||
)
|
||||
|
||||
frame.regs[reg] = DWRule{rule: rule_valexpression, expression: expr}
|
||||
}
|
||||
|
||||
func louser(frame *FrameContext) {
|
||||
frame.buf.Next(1)
|
||||
}
|
||||
|
||||
func hiuser(frame *FrameContext) {
|
||||
frame.buf.Next(1)
|
||||
}
|
122
vendor/github.com/derekparker/delve/dwarf/line/line_parser.go
generated
vendored
122
vendor/github.com/derekparker/delve/dwarf/line/line_parser.go
generated
vendored
@ -1,122 +0,0 @@
|
||||
package line
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
|
||||
"github.com/derekparker/delve/dwarf/util"
|
||||
)
|
||||
|
||||
type DebugLinePrologue struct {
|
||||
UnitLength uint32
|
||||
Version uint16
|
||||
Length uint32
|
||||
MinInstrLength uint8
|
||||
InitialIsStmt uint8
|
||||
LineBase int8
|
||||
LineRange uint8
|
||||
OpcodeBase uint8
|
||||
StdOpLengths []uint8
|
||||
}
|
||||
|
||||
type DebugLineInfo struct {
|
||||
Prologue *DebugLinePrologue
|
||||
IncludeDirs []string
|
||||
FileNames []*FileEntry
|
||||
Instructions []byte
|
||||
Lookup map[string]*FileEntry
|
||||
}
|
||||
|
||||
type FileEntry struct {
|
||||
Name string
|
||||
DirIdx uint64
|
||||
LastModTime uint64
|
||||
Length uint64
|
||||
}
|
||||
|
||||
type DebugLines []*DebugLineInfo
|
||||
|
||||
func (d *DebugLines) GetLineInfo(name string) *DebugLineInfo {
|
||||
// Find in which table file exists and return it.
|
||||
for _, l := range *d {
|
||||
if _, ok := l.Lookup[name]; ok {
|
||||
return l
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func Parse(data []byte) DebugLines {
|
||||
var (
|
||||
lines = make(DebugLines, 0)
|
||||
buf = bytes.NewBuffer(data)
|
||||
)
|
||||
|
||||
// We have to parse multiple file name tables here.
|
||||
for buf.Len() > 0 {
|
||||
dbl := new(DebugLineInfo)
|
||||
dbl.Lookup = make(map[string]*FileEntry)
|
||||
|
||||
parseDebugLinePrologue(dbl, buf)
|
||||
parseIncludeDirs(dbl, buf)
|
||||
parseFileEntries(dbl, buf)
|
||||
|
||||
// Instructions size calculation breakdown:
|
||||
// - dbl.Prologue.UnitLength is the length of the entire unit, not including the 4 bytes to represent that length.
|
||||
// - dbl.Prologue.Length is the length of the prologue not including unit length, version or prologue length itself.
|
||||
// - So you have UnitLength - PrologueLength - (version_length_bytes(2) + prologue_length_bytes(4)).
|
||||
dbl.Instructions = buf.Next(int(dbl.Prologue.UnitLength - dbl.Prologue.Length - 6))
|
||||
|
||||
lines = append(lines, dbl)
|
||||
}
|
||||
|
||||
return lines
|
||||
}
|
||||
|
||||
func parseDebugLinePrologue(dbl *DebugLineInfo, buf *bytes.Buffer) {
|
||||
p := new(DebugLinePrologue)
|
||||
|
||||
p.UnitLength = binary.LittleEndian.Uint32(buf.Next(4))
|
||||
p.Version = binary.LittleEndian.Uint16(buf.Next(2))
|
||||
p.Length = binary.LittleEndian.Uint32(buf.Next(4))
|
||||
p.MinInstrLength = uint8(buf.Next(1)[0])
|
||||
p.InitialIsStmt = uint8(buf.Next(1)[0])
|
||||
p.LineBase = int8(buf.Next(1)[0])
|
||||
p.LineRange = uint8(buf.Next(1)[0])
|
||||
p.OpcodeBase = uint8(buf.Next(1)[0])
|
||||
|
||||
p.StdOpLengths = make([]uint8, p.OpcodeBase-1)
|
||||
binary.Read(buf, binary.LittleEndian, &p.StdOpLengths)
|
||||
|
||||
dbl.Prologue = p
|
||||
}
|
||||
|
||||
func parseIncludeDirs(info *DebugLineInfo, buf *bytes.Buffer) {
|
||||
for {
|
||||
str, _ := util.ParseString(buf)
|
||||
if str == "" {
|
||||
break
|
||||
}
|
||||
|
||||
info.IncludeDirs = append(info.IncludeDirs, str)
|
||||
}
|
||||
}
|
||||
|
||||
func parseFileEntries(info *DebugLineInfo, buf *bytes.Buffer) {
|
||||
for {
|
||||
entry := new(FileEntry)
|
||||
|
||||
name, _ := util.ParseString(buf)
|
||||
if name == "" {
|
||||
break
|
||||
}
|
||||
|
||||
entry.Name = name
|
||||
entry.DirIdx, _ = util.DecodeULEB128(buf)
|
||||
entry.LastModTime, _ = util.DecodeULEB128(buf)
|
||||
entry.Length, _ = util.DecodeULEB128(buf)
|
||||
|
||||
info.FileNames = append(info.FileNames, entry)
|
||||
info.Lookup[name] = entry
|
||||
}
|
||||
}
|
252
vendor/github.com/derekparker/delve/dwarf/line/state_machine.go
generated
vendored
252
vendor/github.com/derekparker/delve/dwarf/line/state_machine.go
generated
vendored
@ -1,252 +0,0 @@
|
||||
package line
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/derekparker/delve/dwarf/util"
|
||||
)
|
||||
|
||||
type Location struct {
|
||||
File string
|
||||
Line int
|
||||
Address uint64
|
||||
Delta int
|
||||
}
|
||||
|
||||
type StateMachine struct {
|
||||
dbl *DebugLineInfo
|
||||
file string
|
||||
line int
|
||||
address uint64
|
||||
column uint
|
||||
isStmt bool
|
||||
basicBlock bool
|
||||
endSeq bool
|
||||
lastWasStandard bool
|
||||
lastDelta int
|
||||
}
|
||||
|
||||
type opcodefn func(*StateMachine, *bytes.Buffer)
|
||||
|
||||
// Special opcodes
|
||||
const (
|
||||
DW_LNS_copy = 1
|
||||
DW_LNS_advance_pc = 2
|
||||
DW_LNS_advance_line = 3
|
||||
DW_LNS_set_file = 4
|
||||
DW_LNS_set_column = 5
|
||||
DW_LNS_negate_stmt = 6
|
||||
DW_LNS_set_basic_block = 7
|
||||
DW_LNS_const_add_pc = 8
|
||||
DW_LNS_fixed_advance_pc = 9
|
||||
)
|
||||
|
||||
// Extended opcodes
|
||||
const (
|
||||
DW_LINE_end_sequence = 1
|
||||
DW_LINE_set_address = 2
|
||||
DW_LINE_define_file = 3
|
||||
)
|
||||
|
||||
var standardopcodes = map[byte]opcodefn{
|
||||
DW_LNS_copy: copyfn,
|
||||
DW_LNS_advance_pc: advancepc,
|
||||
DW_LNS_advance_line: advanceline,
|
||||
DW_LNS_set_file: setfile,
|
||||
DW_LNS_set_column: setcolumn,
|
||||
DW_LNS_negate_stmt: negatestmt,
|
||||
DW_LNS_set_basic_block: setbasicblock,
|
||||
DW_LNS_const_add_pc: constaddpc,
|
||||
DW_LNS_fixed_advance_pc: fixedadvancepc,
|
||||
}
|
||||
|
||||
var extendedopcodes = map[byte]opcodefn{
|
||||
DW_LINE_end_sequence: endsequence,
|
||||
DW_LINE_set_address: setaddress,
|
||||
DW_LINE_define_file: definefile,
|
||||
}
|
||||
|
||||
func newStateMachine(dbl *DebugLineInfo) *StateMachine {
|
||||
return &StateMachine{dbl: dbl, file: dbl.FileNames[0].Name, line: 1}
|
||||
}
|
||||
|
||||
// Returns all PCs for a given file/line. Useful for loops where the 'for' line
|
||||
// could be split amongst 2 PCs.
|
||||
func (dbl *DebugLines) AllPCsForFileLine(f string, l int) (pcs []uint64) {
|
||||
var (
|
||||
foundFile bool
|
||||
lastAddr uint64
|
||||
lineInfo = dbl.GetLineInfo(f)
|
||||
sm = newStateMachine(lineInfo)
|
||||
buf = bytes.NewBuffer(lineInfo.Instructions)
|
||||
)
|
||||
|
||||
for b, err := buf.ReadByte(); err == nil; b, err = buf.ReadByte() {
|
||||
findAndExecOpcode(sm, buf, b)
|
||||
if foundFile && sm.file != f {
|
||||
return
|
||||
}
|
||||
if sm.line == l && sm.file == f && sm.address != lastAddr {
|
||||
foundFile = true
|
||||
pcs = append(pcs, sm.address)
|
||||
line := sm.line
|
||||
// Keep going until we're on a different line. We only care about
|
||||
// when a line comes back around (i.e. for loop) so get to next line,
|
||||
// and try to find the line we care about again.
|
||||
for b, err := buf.ReadByte(); err == nil; b, err = buf.ReadByte() {
|
||||
findAndExecOpcode(sm, buf, b)
|
||||
if line < sm.line {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
var NoSourceError = errors.New("no source available")
|
||||
|
||||
func (dbl *DebugLines) AllPCsBetween(begin, end uint64, filename string) ([]uint64, error) {
|
||||
lineInfo := dbl.GetLineInfo(filename)
|
||||
if lineInfo == nil {
|
||||
return nil, NoSourceError
|
||||
}
|
||||
var (
|
||||
pcs []uint64
|
||||
lastaddr uint64
|
||||
sm = newStateMachine(lineInfo)
|
||||
buf = bytes.NewBuffer(lineInfo.Instructions)
|
||||
)
|
||||
|
||||
for b, err := buf.ReadByte(); err == nil; b, err = buf.ReadByte() {
|
||||
findAndExecOpcode(sm, buf, b)
|
||||
if sm.address > end {
|
||||
break
|
||||
}
|
||||
if sm.address >= begin && sm.address > lastaddr {
|
||||
lastaddr = sm.address
|
||||
pcs = append(pcs, sm.address)
|
||||
}
|
||||
}
|
||||
return pcs, nil
|
||||
}
|
||||
|
||||
func findAndExecOpcode(sm *StateMachine, buf *bytes.Buffer, b byte) {
|
||||
switch {
|
||||
case b == 0:
|
||||
execExtendedOpcode(sm, b, buf)
|
||||
case b < sm.dbl.Prologue.OpcodeBase:
|
||||
execStandardOpcode(sm, b, buf)
|
||||
default:
|
||||
execSpecialOpcode(sm, b)
|
||||
}
|
||||
}
|
||||
|
||||
func execSpecialOpcode(sm *StateMachine, instr byte) {
|
||||
var (
|
||||
opcode = uint8(instr)
|
||||
decoded = opcode - sm.dbl.Prologue.OpcodeBase
|
||||
)
|
||||
|
||||
if sm.dbl.Prologue.InitialIsStmt == uint8(1) {
|
||||
sm.isStmt = true
|
||||
}
|
||||
|
||||
sm.lastDelta = int(sm.dbl.Prologue.LineBase + int8(decoded%sm.dbl.Prologue.LineRange))
|
||||
sm.line += sm.lastDelta
|
||||
sm.address += uint64(decoded / sm.dbl.Prologue.LineRange)
|
||||
sm.basicBlock = false
|
||||
sm.lastWasStandard = false
|
||||
}
|
||||
|
||||
func execExtendedOpcode(sm *StateMachine, instr byte, buf *bytes.Buffer) {
|
||||
_, _ = util.DecodeULEB128(buf)
|
||||
b, _ := buf.ReadByte()
|
||||
fn, ok := extendedopcodes[b]
|
||||
if !ok {
|
||||
panic(fmt.Sprintf("Encountered unknown extended opcode %#v\n", b))
|
||||
}
|
||||
sm.lastWasStandard = false
|
||||
|
||||
fn(sm, buf)
|
||||
}
|
||||
|
||||
func execStandardOpcode(sm *StateMachine, instr byte, buf *bytes.Buffer) {
|
||||
fn, ok := standardopcodes[instr]
|
||||
if !ok {
|
||||
panic(fmt.Sprintf("Encountered unknown standard opcode %#v\n", instr))
|
||||
}
|
||||
sm.lastWasStandard = true
|
||||
|
||||
fn(sm, buf)
|
||||
}
|
||||
|
||||
func copyfn(sm *StateMachine, buf *bytes.Buffer) {
|
||||
sm.basicBlock = false
|
||||
}
|
||||
|
||||
func advancepc(sm *StateMachine, buf *bytes.Buffer) {
|
||||
addr, _ := util.DecodeULEB128(buf)
|
||||
sm.address += addr * uint64(sm.dbl.Prologue.MinInstrLength)
|
||||
}
|
||||
|
||||
func advanceline(sm *StateMachine, buf *bytes.Buffer) {
|
||||
line, _ := util.DecodeSLEB128(buf)
|
||||
sm.line += int(line)
|
||||
sm.lastDelta = int(line)
|
||||
}
|
||||
|
||||
func setfile(sm *StateMachine, buf *bytes.Buffer) {
|
||||
i, _ := util.DecodeULEB128(buf)
|
||||
sm.file = sm.dbl.FileNames[i-1].Name
|
||||
}
|
||||
|
||||
func setcolumn(sm *StateMachine, buf *bytes.Buffer) {
|
||||
c, _ := util.DecodeULEB128(buf)
|
||||
sm.column = uint(c)
|
||||
}
|
||||
|
||||
func negatestmt(sm *StateMachine, buf *bytes.Buffer) {
|
||||
sm.isStmt = !sm.isStmt
|
||||
}
|
||||
|
||||
func setbasicblock(sm *StateMachine, buf *bytes.Buffer) {
|
||||
sm.basicBlock = true
|
||||
}
|
||||
|
||||
func constaddpc(sm *StateMachine, buf *bytes.Buffer) {
|
||||
sm.address += (255 / uint64(sm.dbl.Prologue.LineRange))
|
||||
}
|
||||
|
||||
func fixedadvancepc(sm *StateMachine, buf *bytes.Buffer) {
|
||||
var operand uint16
|
||||
binary.Read(buf, binary.LittleEndian, &operand)
|
||||
|
||||
sm.address += uint64(operand)
|
||||
}
|
||||
|
||||
func endsequence(sm *StateMachine, buf *bytes.Buffer) {
|
||||
sm.endSeq = true
|
||||
}
|
||||
|
||||
func setaddress(sm *StateMachine, buf *bytes.Buffer) {
|
||||
var addr uint64
|
||||
|
||||
binary.Read(buf, binary.LittleEndian, &addr)
|
||||
|
||||
sm.address = addr
|
||||
}
|
||||
|
||||
func definefile(sm *StateMachine, buf *bytes.Buffer) {
|
||||
var (
|
||||
_, _ = util.ParseString(buf)
|
||||
_, _ = util.DecodeULEB128(buf)
|
||||
_, _ = util.DecodeULEB128(buf)
|
||||
_, _ = util.DecodeULEB128(buf)
|
||||
)
|
||||
|
||||
// Don't do anything here yet.
|
||||
}
|
84
vendor/github.com/derekparker/delve/dwarf/op/op.go
generated
vendored
84
vendor/github.com/derekparker/delve/dwarf/op/op.go
generated
vendored
@ -1,84 +0,0 @@
|
||||
package op
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/derekparker/delve/dwarf/util"
|
||||
)
|
||||
|
||||
const (
|
||||
DW_OP_addr = 0x3
|
||||
DW_OP_call_frame_cfa = 0x9c
|
||||
DW_OP_plus = 0x22
|
||||
DW_OP_consts = 0x11
|
||||
DW_OP_plus_uconsts = 0x23
|
||||
)
|
||||
|
||||
type stackfn func(*bytes.Buffer, []int64, int64) ([]int64, error)
|
||||
|
||||
var oplut = map[byte]stackfn{
|
||||
DW_OP_call_frame_cfa: callframecfa,
|
||||
DW_OP_plus: plus,
|
||||
DW_OP_consts: consts,
|
||||
DW_OP_addr: addr,
|
||||
DW_OP_plus_uconsts: plusuconsts,
|
||||
}
|
||||
|
||||
func ExecuteStackProgram(cfa int64, instructions []byte) (int64, error) {
|
||||
stack := make([]int64, 0, 3)
|
||||
buf := bytes.NewBuffer(instructions)
|
||||
|
||||
for opcode, err := buf.ReadByte(); err == nil; opcode, err = buf.ReadByte() {
|
||||
fn, ok := oplut[opcode]
|
||||
if !ok {
|
||||
return 0, fmt.Errorf("invalid instruction %#v", opcode)
|
||||
}
|
||||
|
||||
stack, err = fn(buf, stack, cfa)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
}
|
||||
|
||||
if len(stack) == 0 {
|
||||
return 0, errors.New("empty OP stack")
|
||||
}
|
||||
|
||||
return stack[len(stack)-1], nil
|
||||
}
|
||||
|
||||
func callframecfa(buf *bytes.Buffer, stack []int64, cfa int64) ([]int64, error) {
|
||||
if cfa == 0 {
|
||||
return stack, fmt.Errorf("Could not retrieve CFA for current PC")
|
||||
}
|
||||
return append(stack, int64(cfa)), nil
|
||||
}
|
||||
|
||||
func addr(buf *bytes.Buffer, stack []int64, cfa int64) ([]int64, error) {
|
||||
return append(stack, int64(binary.LittleEndian.Uint64(buf.Next(8)))), nil
|
||||
}
|
||||
|
||||
func plus(buf *bytes.Buffer, stack []int64, cfa int64) ([]int64, error) {
|
||||
var (
|
||||
slen = len(stack)
|
||||
digits = stack[slen-2 : slen]
|
||||
st = stack[:slen-2]
|
||||
)
|
||||
|
||||
return append(st, digits[0]+digits[1]), nil
|
||||
}
|
||||
|
||||
func plusuconsts(buf *bytes.Buffer, stack []int64, cfa int64) ([]int64, error) {
|
||||
slen := len(stack)
|
||||
num, _ := util.DecodeULEB128(buf)
|
||||
stack[slen-1] = stack[slen-1] + int64(num)
|
||||
return stack, nil
|
||||
}
|
||||
|
||||
func consts(buf *bytes.Buffer, stack []int64, cfa int64) ([]int64, error) {
|
||||
num, _ := util.DecodeSLEB128(buf)
|
||||
return append(stack, num), nil
|
||||
}
|
345
vendor/github.com/derekparker/delve/dwarf/reader/reader.go
generated
vendored
345
vendor/github.com/derekparker/delve/dwarf/reader/reader.go
generated
vendored
@ -1,345 +0,0 @@
|
||||
package reader
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"golang.org/x/debug/dwarf"
|
||||
"github.com/derekparker/delve/dwarf/op"
|
||||
)
|
||||
|
||||
type Reader struct {
|
||||
*dwarf.Reader
|
||||
depth int
|
||||
}
|
||||
|
||||
// New returns a reader for the specified dwarf data.
|
||||
func New(data *dwarf.Data) *Reader {
|
||||
return &Reader{data.Reader(), 0}
|
||||
}
|
||||
|
||||
// Seek moves the reader to an arbitrary offset.
|
||||
func (reader *Reader) Seek(off dwarf.Offset) {
|
||||
reader.depth = 0
|
||||
reader.Reader.Seek(off)
|
||||
}
|
||||
|
||||
// SeekToEntry moves the reader to an arbitrary entry.
|
||||
func (reader *Reader) SeekToEntry(entry *dwarf.Entry) error {
|
||||
reader.Seek(entry.Offset)
|
||||
// Consume the current entry so .Next works as intended
|
||||
_, err := reader.Next()
|
||||
return err
|
||||
}
|
||||
|
||||
// SeekToFunctionEntry moves the reader to the function that includes the
|
||||
// specified program counter.
|
||||
func (reader *Reader) SeekToFunction(pc uint64) (*dwarf.Entry, error) {
|
||||
reader.Seek(0)
|
||||
for entry, err := reader.Next(); entry != nil; entry, err = reader.Next() {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if entry.Tag != dwarf.TagSubprogram {
|
||||
continue
|
||||
}
|
||||
|
||||
lowpc, ok := entry.Val(dwarf.AttrLowpc).(uint64)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
highpc, ok := entry.Val(dwarf.AttrHighpc).(uint64)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
if lowpc <= pc && highpc > pc {
|
||||
return entry, nil
|
||||
}
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("unable to find function context")
|
||||
}
|
||||
|
||||
// Returns the address for the named entry.
|
||||
func (reader *Reader) AddrFor(name string) (uint64, error) {
|
||||
entry, err := reader.FindEntryNamed(name, false)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
instructions, ok := entry.Val(dwarf.AttrLocation).([]byte)
|
||||
if !ok {
|
||||
return 0, fmt.Errorf("type assertion failed")
|
||||
}
|
||||
addr, err := op.ExecuteStackProgram(0, instructions)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return uint64(addr), nil
|
||||
}
|
||||
|
||||
// Returns the address for the named struct member. Expects the reader to be at the parent entry
|
||||
// or one of the parents children, thus does not seek to parent by itself.
|
||||
func (reader *Reader) AddrForMember(member string, initialInstructions []byte) (uint64, error) {
|
||||
for {
|
||||
entry, err := reader.NextMemberVariable()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if entry == nil {
|
||||
return 0, fmt.Errorf("nil entry for member named %s", member)
|
||||
}
|
||||
name, ok := entry.Val(dwarf.AttrName).(string)
|
||||
if !ok || name != member {
|
||||
continue
|
||||
}
|
||||
instructions, ok := entry.Val(dwarf.AttrDataMemberLoc).([]byte)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
addr, err := op.ExecuteStackProgram(0, append(initialInstructions, instructions...))
|
||||
return uint64(addr), err
|
||||
}
|
||||
}
|
||||
|
||||
var TypeNotFoundErr = errors.New("no type entry found, use 'types' for a list of valid types")
|
||||
|
||||
// SeekToType moves the reader to the type specified by the entry,
|
||||
// optionally resolving typedefs and pointer types. If the reader is set
|
||||
// to a struct type the NextMemberVariable call can be used to walk all member data.
|
||||
func (reader *Reader) SeekToType(entry *dwarf.Entry, resolveTypedefs bool, resolvePointerTypes bool) (*dwarf.Entry, error) {
|
||||
offset, ok := entry.Val(dwarf.AttrType).(dwarf.Offset)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("entry does not have a type attribute")
|
||||
}
|
||||
|
||||
// Seek to the first type offset
|
||||
reader.Seek(offset)
|
||||
|
||||
// Walk the types to the base
|
||||
for typeEntry, err := reader.Next(); typeEntry != nil; typeEntry, err = reader.Next() {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if typeEntry.Tag == dwarf.TagTypedef && !resolveTypedefs {
|
||||
return typeEntry, nil
|
||||
}
|
||||
|
||||
if typeEntry.Tag == dwarf.TagPointerType && !resolvePointerTypes {
|
||||
return typeEntry, nil
|
||||
}
|
||||
|
||||
offset, ok = typeEntry.Val(dwarf.AttrType).(dwarf.Offset)
|
||||
if !ok {
|
||||
return typeEntry, nil
|
||||
}
|
||||
|
||||
reader.Seek(offset)
|
||||
}
|
||||
|
||||
return nil, TypeNotFoundErr
|
||||
}
|
||||
|
||||
func (reader *Reader) NextType() (*dwarf.Entry, error) {
|
||||
for entry, err := reader.Next(); entry != nil; entry, err = reader.Next() {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
switch entry.Tag {
|
||||
case dwarf.TagArrayType, dwarf.TagBaseType, dwarf.TagClassType, dwarf.TagStructType, dwarf.TagUnionType, dwarf.TagConstType, dwarf.TagVolatileType, dwarf.TagRestrictType, dwarf.TagEnumerationType, dwarf.TagPointerType, dwarf.TagSubroutineType, dwarf.TagTypedef, dwarf.TagUnspecifiedType:
|
||||
return entry, nil
|
||||
}
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// SeekToTypeNamed moves the reader to the type specified by the name.
|
||||
// If the reader is set to a struct type the NextMemberVariable call
|
||||
// can be used to walk all member data.
|
||||
func (reader *Reader) SeekToTypeNamed(name string) (*dwarf.Entry, error) {
|
||||
// Walk the types to the base
|
||||
for entry, err := reader.NextType(); entry != nil; entry, err = reader.NextType() {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
n, ok := entry.Val(dwarf.AttrName).(string)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
if n == name {
|
||||
return entry, nil
|
||||
}
|
||||
}
|
||||
|
||||
return nil, TypeNotFoundErr
|
||||
}
|
||||
|
||||
// Finds the entry for 'name'.
|
||||
func (reader *Reader) FindEntryNamed(name string, member bool) (*dwarf.Entry, error) {
|
||||
depth := 1
|
||||
for entry, err := reader.Next(); entry != nil; entry, err = reader.Next() {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if entry.Children {
|
||||
depth++
|
||||
}
|
||||
|
||||
if entry.Tag == 0 {
|
||||
depth--
|
||||
if depth <= 0 {
|
||||
return nil, fmt.Errorf("could not find symbol value for %s", name)
|
||||
}
|
||||
}
|
||||
|
||||
if member {
|
||||
if entry.Tag != dwarf.TagMember {
|
||||
continue
|
||||
}
|
||||
} else {
|
||||
if entry.Tag != dwarf.TagVariable && entry.Tag != dwarf.TagFormalParameter && entry.Tag != dwarf.TagStructType {
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
n, ok := entry.Val(dwarf.AttrName).(string)
|
||||
if !ok || n != name {
|
||||
continue
|
||||
}
|
||||
return entry, nil
|
||||
}
|
||||
return nil, fmt.Errorf("could not find symbol value for %s", name)
|
||||
}
|
||||
|
||||
func (reader *Reader) InstructionsForEntryNamed(name string, member bool) ([]byte, error) {
|
||||
entry, err := reader.FindEntryNamed(name, member)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var attr dwarf.Attr
|
||||
if member {
|
||||
attr = dwarf.AttrDataMemberLoc
|
||||
} else {
|
||||
attr = dwarf.AttrLocation
|
||||
}
|
||||
instr, ok := entry.Val(attr).([]byte)
|
||||
if !ok {
|
||||
return nil, errors.New("invalid typecast for Dwarf instructions")
|
||||
}
|
||||
return instr, nil
|
||||
}
|
||||
|
||||
func (reader *Reader) InstructionsForEntry(entry *dwarf.Entry) ([]byte, error) {
|
||||
if entry.Tag == dwarf.TagMember {
|
||||
instructions, ok := entry.Val(dwarf.AttrDataMemberLoc).([]byte)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("member data has no data member location attribute")
|
||||
}
|
||||
// clone slice to prevent stomping on the dwarf data
|
||||
return append([]byte{}, instructions...), nil
|
||||
}
|
||||
|
||||
// non-member
|
||||
instructions, ok := entry.Val(dwarf.AttrLocation).([]byte)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("entry has no location attribute")
|
||||
}
|
||||
|
||||
// clone slice to prevent stomping on the dwarf data
|
||||
return append([]byte{}, instructions...), nil
|
||||
}
|
||||
|
||||
// NextScopeVariable moves the reader to the next debug entry that describes a local variable and returns the entry.
|
||||
func (reader *Reader) NextScopeVariable() (*dwarf.Entry, error) {
|
||||
for entry, err := reader.Next(); entry != nil; entry, err = reader.Next() {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// All scope variables will be at the same depth
|
||||
reader.SkipChildren()
|
||||
|
||||
// End of the current depth
|
||||
if entry.Tag == 0 {
|
||||
break
|
||||
}
|
||||
|
||||
if entry.Tag == dwarf.TagVariable || entry.Tag == dwarf.TagFormalParameter {
|
||||
return entry, nil
|
||||
}
|
||||
}
|
||||
|
||||
// No more items
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// NextMememberVariable moves the reader to the next debug entry that describes a member variable and returns the entry.
|
||||
func (reader *Reader) NextMemberVariable() (*dwarf.Entry, error) {
|
||||
for entry, err := reader.Next(); entry != nil; entry, err = reader.Next() {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// All member variables will be at the same depth
|
||||
reader.SkipChildren()
|
||||
|
||||
// End of the current depth
|
||||
if entry.Tag == 0 {
|
||||
break
|
||||
}
|
||||
|
||||
if entry.Tag == dwarf.TagMember {
|
||||
return entry, nil
|
||||
}
|
||||
}
|
||||
|
||||
// No more items
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// NextPackageVariable moves the reader to the next debug entry that describes a package variable.
|
||||
// Any TagVariable entry that is not inside a sub prgram entry and is marked external is considered a package variable.
|
||||
func (reader *Reader) NextPackageVariable() (*dwarf.Entry, error) {
|
||||
for entry, err := reader.Next(); entry != nil; entry, err = reader.Next() {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if entry.Tag == dwarf.TagVariable {
|
||||
ext, ok := entry.Val(dwarf.AttrExternal).(bool)
|
||||
if ok && ext {
|
||||
return entry, nil
|
||||
}
|
||||
}
|
||||
|
||||
// Ignore everything inside sub programs
|
||||
if entry.Tag == dwarf.TagSubprogram {
|
||||
reader.SkipChildren()
|
||||
}
|
||||
}
|
||||
|
||||
// No more items
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (reader *Reader) NextCompileUnit() (*dwarf.Entry, error) {
|
||||
for entry, err := reader.Next(); entry != nil; entry, err = reader.Next() {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if entry.Tag == dwarf.TagCompileUnit {
|
||||
return entry, nil
|
||||
}
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
}
|
81
vendor/github.com/derekparker/delve/dwarf/util/util.go
generated
vendored
81
vendor/github.com/derekparker/delve/dwarf/util/util.go
generated
vendored
@ -1,81 +0,0 @@
|
||||
package util
|
||||
|
||||
import "bytes"
|
||||
|
||||
// DecodeULEB128 decodes an unsigned Little Endian Base 128
|
||||
// represented number.
|
||||
func DecodeULEB128(buf *bytes.Buffer) (uint64, uint32) {
|
||||
var (
|
||||
result uint64
|
||||
shift uint64
|
||||
length uint32
|
||||
)
|
||||
|
||||
if buf.Len() == 0 {
|
||||
return 0, 0
|
||||
}
|
||||
|
||||
for {
|
||||
b, err := buf.ReadByte()
|
||||
if err != nil {
|
||||
panic("Could not parse ULEB128 value")
|
||||
}
|
||||
length++
|
||||
|
||||
result |= uint64((uint(b) & 0x7f) << shift)
|
||||
|
||||
// If high order bit is 1.
|
||||
if b&0x80 == 0 {
|
||||
break
|
||||
}
|
||||
|
||||
shift += 7
|
||||
}
|
||||
|
||||
return result, length
|
||||
}
|
||||
|
||||
// DecodeSLEB128 decodes a signed Little Endian Base 128
|
||||
// represented number.
|
||||
func DecodeSLEB128(buf *bytes.Buffer) (int64, uint32) {
|
||||
var (
|
||||
b byte
|
||||
err error
|
||||
result int64
|
||||
shift uint64
|
||||
length uint32
|
||||
)
|
||||
|
||||
if buf.Len() == 0 {
|
||||
return 0, 0
|
||||
}
|
||||
|
||||
for {
|
||||
b, err = buf.ReadByte()
|
||||
if err != nil {
|
||||
panic("Could not parse SLEB128 value")
|
||||
}
|
||||
length++
|
||||
|
||||
result |= int64((int64(b) & 0x7f) << shift)
|
||||
shift += 7
|
||||
if b&0x80 == 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if (shift < 8*uint64(length)) && (b&0x40 > 0) {
|
||||
result |= -(1 << shift)
|
||||
}
|
||||
|
||||
return result, length
|
||||
}
|
||||
|
||||
func ParseString(data *bytes.Buffer) (string, uint32) {
|
||||
str, err := data.ReadString(0x0)
|
||||
if err != nil {
|
||||
panic("Could not parse string")
|
||||
}
|
||||
|
||||
return str[:len(str)-1], uint32(len(str))
|
||||
}
|
79
vendor/github.com/derekparker/delve/proc/arch.go
generated
vendored
79
vendor/github.com/derekparker/delve/proc/arch.go
generated
vendored
@ -1,79 +0,0 @@
|
||||
package proc
|
||||
|
||||
import "runtime"
|
||||
|
||||
// Arch defines an interface for representing a
|
||||
// CPU architecture.
|
||||
type Arch interface {
|
||||
SetGStructOffset(ver GoVersion, iscgo bool)
|
||||
PtrSize() int
|
||||
BreakpointInstruction() []byte
|
||||
BreakpointSize() int
|
||||
GStructOffset() uint64
|
||||
}
|
||||
|
||||
// AMD64 represents the AMD64 CPU architecture.
|
||||
type AMD64 struct {
|
||||
ptrSize int
|
||||
breakInstruction []byte
|
||||
breakInstructionLen int
|
||||
gStructOffset uint64
|
||||
hardwareBreakpointUsage []bool
|
||||
}
|
||||
|
||||
// AMD64Arch returns an initialized AMD64
|
||||
// struct.
|
||||
func AMD64Arch() *AMD64 {
|
||||
var breakInstr = []byte{0xCC}
|
||||
|
||||
return &AMD64{
|
||||
ptrSize: 8,
|
||||
breakInstruction: breakInstr,
|
||||
breakInstructionLen: len(breakInstr),
|
||||
hardwareBreakpointUsage: make([]bool, 4),
|
||||
}
|
||||
}
|
||||
|
||||
// SetGStructOffset sets the offset of the G struct on the AMD64
|
||||
// arch struct. The offset is dependent on the Go compiler Version
|
||||
// and whether or not the target program was externally linked.
|
||||
func (a *AMD64) SetGStructOffset(ver GoVersion, isextld bool) {
|
||||
switch runtime.GOOS {
|
||||
case "darwin":
|
||||
a.gStructOffset = 0x8a0
|
||||
case "linux":
|
||||
a.gStructOffset = 0xfffffffffffffff0
|
||||
if isextld || ver.AfterOrEqual(GoVersion{1, 5, -1, 2, 0}) || ver.IsDevel() {
|
||||
a.gStructOffset += 8
|
||||
}
|
||||
case "windows":
|
||||
// Use ArbitraryUserPointer (0x28) as pointer to pointer
|
||||
// to G struct per:
|
||||
// https://golang.org/src/runtime/cgo/gcc_windows_amd64.c
|
||||
a.gStructOffset = 0x28
|
||||
}
|
||||
}
|
||||
|
||||
// PtrSize returns the size of a pointer
|
||||
// on this architecture.
|
||||
func (a *AMD64) PtrSize() int {
|
||||
return a.ptrSize
|
||||
}
|
||||
|
||||
// BreakpointInstruction returns the Breakpoint
|
||||
// instruction for this architecture.
|
||||
func (a *AMD64) BreakpointInstruction() []byte {
|
||||
return a.breakInstruction
|
||||
}
|
||||
|
||||
// BreakpointSize returns the size of the
|
||||
// breakpoint instruction on this architecture.
|
||||
func (a *AMD64) BreakpointSize() int {
|
||||
return a.breakInstructionLen
|
||||
}
|
||||
|
||||
// GStructOffset returns the offset of the G
|
||||
// struct in thread local storage.
|
||||
func (a *AMD64) GStructOffset() uint64 {
|
||||
return a.gStructOffset
|
||||
}
|
163
vendor/github.com/derekparker/delve/proc/breakpoints.go
generated
vendored
163
vendor/github.com/derekparker/delve/proc/breakpoints.go
generated
vendored
@ -1,163 +0,0 @@
|
||||
package proc
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"go/ast"
|
||||
"go/constant"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
// Breakpoint represents a breakpoint. Stores information on the break
|
||||
// point including the byte of data that originally was stored at that
|
||||
// address.
|
||||
type Breakpoint struct {
|
||||
// File & line information for printing.
|
||||
FunctionName string
|
||||
File string
|
||||
Line int
|
||||
|
||||
Addr uint64 // Address breakpoint is set for.
|
||||
OriginalData []byte // If software breakpoint, the data we replace with breakpoint instruction.
|
||||
Name string // User defined name of the breakpoint
|
||||
ID int // Monotonically increasing ID.
|
||||
Kind BreakpointKind // Whether this is an internal breakpoint (for next'ing or stepping).
|
||||
|
||||
// Breakpoint information
|
||||
Tracepoint bool // Tracepoint flag
|
||||
Goroutine bool // Retrieve goroutine information
|
||||
Stacktrace int // Number of stack frames to retrieve
|
||||
Variables []string // Variables to evaluate
|
||||
LoadArgs *LoadConfig
|
||||
LoadLocals *LoadConfig
|
||||
HitCount map[int]uint64 // Number of times a breakpoint has been reached in a certain goroutine
|
||||
TotalHitCount uint64 // Number of times a breakpoint has been reached
|
||||
|
||||
// DeferReturns: when kind == NextDeferBreakpoint this breakpoint
|
||||
// will also check if the caller is runtime.gopanic or if the return
|
||||
// address is in the DeferReturns array.
|
||||
// Next uses NextDeferBreakpoints for the breakpoint it sets on the
|
||||
// deferred function, DeferReturns is populated with the
|
||||
// addresses of calls to runtime.deferreturn in the current
|
||||
// function. This insures that the breakpoint on the deferred
|
||||
// function only triggers on panic or on the defer call to
|
||||
// the function, not when the function is called directly
|
||||
DeferReturns []uint64
|
||||
// Cond: if not nil the breakpoint will be triggered only if evaluating Cond returns true
|
||||
Cond ast.Expr
|
||||
}
|
||||
|
||||
// Breakpoint Kind determines the behavior of delve when the
|
||||
// breakpoint is reached.
|
||||
type BreakpointKind int
|
||||
|
||||
const (
|
||||
// UserBreakpoint is a user set breakpoint
|
||||
UserBreakpoint BreakpointKind = iota
|
||||
// NextBreakpoint is a breakpoint set by Next, Continue
|
||||
// will stop on it and delete it
|
||||
NextBreakpoint
|
||||
// NextDeferBreakpoint is a breakpoint set by Next on the
|
||||
// first deferred function. In addition to checking their condition
|
||||
// breakpoints of this kind will also check that the function has been
|
||||
// called by runtime.gopanic or through runtime.deferreturn.
|
||||
NextDeferBreakpoint
|
||||
// StepBreakpoint is a breakpoint set by Step on a CALL instruction,
|
||||
// Continue will set a new breakpoint (of NextBreakpoint kind) on the
|
||||
// destination of CALL, delete this breakpoint and then continue again
|
||||
StepBreakpoint
|
||||
)
|
||||
|
||||
func (bp *Breakpoint) String() string {
|
||||
return fmt.Sprintf("Breakpoint %d at %#v %s:%d (%d)", bp.ID, bp.Addr, bp.File, bp.Line, bp.TotalHitCount)
|
||||
}
|
||||
|
||||
// Clear this breakpoint appropriately depending on whether it is a
|
||||
// hardware or software breakpoint.
|
||||
func (bp *Breakpoint) Clear(thread *Thread) (*Breakpoint, error) {
|
||||
if _, err := thread.writeMemory(uintptr(bp.Addr), bp.OriginalData); err != nil {
|
||||
return nil, fmt.Errorf("could not clear breakpoint %s", err)
|
||||
}
|
||||
return bp, nil
|
||||
}
|
||||
|
||||
// BreakpointExistsError is returned when trying to set a breakpoint at
|
||||
// an address that already has a breakpoint set for it.
|
||||
type BreakpointExistsError struct {
|
||||
file string
|
||||
line int
|
||||
addr uint64
|
||||
}
|
||||
|
||||
func (bpe BreakpointExistsError) Error() string {
|
||||
return fmt.Sprintf("Breakpoint exists at %s:%d at %x", bpe.file, bpe.line, bpe.addr)
|
||||
}
|
||||
|
||||
// InvalidAddressError represents the result of
|
||||
// attempting to set a breakpoint at an invalid address.
|
||||
type InvalidAddressError struct {
|
||||
address uint64
|
||||
}
|
||||
|
||||
func (iae InvalidAddressError) Error() string {
|
||||
return fmt.Sprintf("Invalid address %#v\n", iae.address)
|
||||
}
|
||||
|
||||
func (dbp *Process) writeSoftwareBreakpoint(thread *Thread, addr uint64) error {
|
||||
_, err := thread.writeMemory(uintptr(addr), dbp.arch.BreakpointInstruction())
|
||||
return err
|
||||
}
|
||||
|
||||
func (bp *Breakpoint) checkCondition(thread *Thread) (bool, error) {
|
||||
if bp.Cond == nil {
|
||||
return true, nil
|
||||
}
|
||||
if bp.Kind == NextDeferBreakpoint {
|
||||
frames, err := thread.Stacktrace(2)
|
||||
if err == nil {
|
||||
ispanic := len(frames) >= 3 && frames[2].Current.Fn != nil && frames[2].Current.Fn.Name == "runtime.gopanic"
|
||||
isdeferreturn := false
|
||||
if len(frames) >= 1 {
|
||||
for _, pc := range bp.DeferReturns {
|
||||
if frames[0].Ret == pc {
|
||||
isdeferreturn = true
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if !ispanic && !isdeferreturn {
|
||||
return false, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
scope, err := thread.Scope()
|
||||
if err != nil {
|
||||
return true, err
|
||||
}
|
||||
v, err := scope.evalAST(bp.Cond)
|
||||
if err != nil {
|
||||
return true, fmt.Errorf("error evaluating expression: %v", err)
|
||||
}
|
||||
if v.Unreadable != nil {
|
||||
return true, fmt.Errorf("condition expression unreadable: %v", v.Unreadable)
|
||||
}
|
||||
if v.Kind != reflect.Bool {
|
||||
return true, errors.New("condition expression not boolean")
|
||||
}
|
||||
return constant.BoolVal(v.Value), nil
|
||||
}
|
||||
|
||||
// Internal returns true for breakpoints not set directly by the user.
|
||||
func (bp *Breakpoint) Internal() bool {
|
||||
return bp.Kind != UserBreakpoint
|
||||
}
|
||||
|
||||
// NoBreakpointError is returned when trying to
|
||||
// clear a breakpoint that does not exist.
|
||||
type NoBreakpointError struct {
|
||||
addr uint64
|
||||
}
|
||||
|
||||
func (nbp NoBreakpointError) Error() string {
|
||||
return fmt.Sprintf("no breakpoint at %#v", nbp.addr)
|
||||
}
|
67
vendor/github.com/derekparker/delve/proc/disasm.go
generated
vendored
67
vendor/github.com/derekparker/delve/proc/disasm.go
generated
vendored
@ -1,67 +0,0 @@
|
||||
package proc
|
||||
|
||||
type AsmInstruction struct {
|
||||
Loc Location
|
||||
DestLoc *Location
|
||||
Bytes []byte
|
||||
Breakpoint bool
|
||||
AtPC bool
|
||||
Inst *ArchInst
|
||||
}
|
||||
|
||||
type AssemblyFlavour int
|
||||
|
||||
const (
|
||||
GNUFlavour = AssemblyFlavour(iota)
|
||||
IntelFlavour
|
||||
)
|
||||
|
||||
// Disassemble disassembles target memory between startPC and endPC
|
||||
// If currentGoroutine is set and thread is stopped at a CALL instruction Disassemble will evaluate the argument of the CALL instruction using the thread's registers
|
||||
// Be aware that the Bytes field of each returned instruction is a slice of a larger array of size endPC - startPC
|
||||
func (thread *Thread) Disassemble(startPC, endPC uint64, currentGoroutine bool) ([]AsmInstruction, error) {
|
||||
if thread.dbp.exited {
|
||||
return nil, &ProcessExitedError{}
|
||||
}
|
||||
mem, err := thread.readMemory(uintptr(startPC), int(endPC-startPC))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
r := make([]AsmInstruction, 0, len(mem)/15)
|
||||
pc := startPC
|
||||
|
||||
var curpc uint64
|
||||
var regs Registers
|
||||
if currentGoroutine {
|
||||
regs, _ = thread.Registers(false)
|
||||
if regs != nil {
|
||||
curpc = regs.PC()
|
||||
}
|
||||
}
|
||||
|
||||
for len(mem) > 0 {
|
||||
bp, atbp := thread.dbp.Breakpoints[pc]
|
||||
if atbp {
|
||||
for i := range bp.OriginalData {
|
||||
mem[i] = bp.OriginalData[i]
|
||||
}
|
||||
}
|
||||
file, line, fn := thread.dbp.PCToLine(pc)
|
||||
loc := Location{PC: pc, File: file, Line: line, Fn: fn}
|
||||
inst, err := asmDecode(mem, pc)
|
||||
if err == nil {
|
||||
atpc := currentGoroutine && (curpc == pc)
|
||||
destloc := thread.resolveCallArg(inst, atpc, regs)
|
||||
r = append(r, AsmInstruction{Loc: loc, DestLoc: destloc, Bytes: mem[:inst.Len], Breakpoint: atbp, AtPC: atpc, Inst: inst})
|
||||
|
||||
pc += uint64(inst.Size())
|
||||
mem = mem[inst.Size():]
|
||||
} else {
|
||||
r = append(r, AsmInstruction{Loc: loc, Bytes: mem[:1], Breakpoint: atbp, Inst: nil})
|
||||
pc++
|
||||
mem = mem[1:]
|
||||
}
|
||||
}
|
||||
return r, nil
|
||||
}
|
183
vendor/github.com/derekparker/delve/proc/disasm_amd64.go
generated
vendored
183
vendor/github.com/derekparker/delve/proc/disasm_amd64.go
generated
vendored
@ -1,183 +0,0 @@
|
||||
package proc
|
||||
|
||||
import (
|
||||
"debug/gosym"
|
||||
"encoding/binary"
|
||||
"rsc.io/x86/x86asm"
|
||||
)
|
||||
|
||||
var maxInstructionLength uint64 = 15
|
||||
|
||||
type ArchInst x86asm.Inst
|
||||
|
||||
func asmDecode(mem []byte, pc uint64) (*ArchInst, error) {
|
||||
inst, err := x86asm.Decode(mem, 64)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
patchPCRel(pc, &inst)
|
||||
r := ArchInst(inst)
|
||||
return &r, nil
|
||||
}
|
||||
|
||||
func (inst *ArchInst) Size() int {
|
||||
return inst.Len
|
||||
}
|
||||
|
||||
// converts PC relative arguments to absolute addresses
|
||||
func patchPCRel(pc uint64, inst *x86asm.Inst) {
|
||||
for i := range inst.Args {
|
||||
rel, isrel := inst.Args[i].(x86asm.Rel)
|
||||
if isrel {
|
||||
inst.Args[i] = x86asm.Imm(int64(pc) + int64(rel) + int64(inst.Len))
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (inst *AsmInstruction) Text(flavour AssemblyFlavour) string {
|
||||
if inst.Inst == nil {
|
||||
return "?"
|
||||
}
|
||||
|
||||
var text string
|
||||
|
||||
switch flavour {
|
||||
case GNUFlavour:
|
||||
text = x86asm.GNUSyntax(x86asm.Inst(*inst.Inst))
|
||||
case IntelFlavour:
|
||||
fallthrough
|
||||
default:
|
||||
text = x86asm.IntelSyntax(x86asm.Inst(*inst.Inst))
|
||||
}
|
||||
|
||||
if inst.IsCall() && inst.DestLoc != nil && inst.DestLoc.Fn != nil {
|
||||
text += " " + inst.DestLoc.Fn.Name
|
||||
}
|
||||
|
||||
return text
|
||||
}
|
||||
|
||||
func (inst *AsmInstruction) IsCall() bool {
|
||||
return inst.Inst.Op == x86asm.CALL || inst.Inst.Op == x86asm.LCALL
|
||||
}
|
||||
|
||||
func (thread *Thread) resolveCallArg(inst *ArchInst, currentGoroutine bool, regs Registers) *Location {
|
||||
if inst.Op != x86asm.CALL && inst.Op != x86asm.LCALL {
|
||||
return nil
|
||||
}
|
||||
|
||||
var pc uint64
|
||||
var err error
|
||||
|
||||
switch arg := inst.Args[0].(type) {
|
||||
case x86asm.Imm:
|
||||
pc = uint64(arg)
|
||||
case x86asm.Reg:
|
||||
if !currentGoroutine || regs == nil {
|
||||
return nil
|
||||
}
|
||||
pc, err = regs.Get(int(arg))
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
case x86asm.Mem:
|
||||
if !currentGoroutine || regs == nil {
|
||||
return nil
|
||||
}
|
||||
if arg.Segment != 0 {
|
||||
return nil
|
||||
}
|
||||
regs, err := thread.Registers(false)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
base, err1 := regs.Get(int(arg.Base))
|
||||
index, err2 := regs.Get(int(arg.Index))
|
||||
if err1 != nil || err2 != nil {
|
||||
return nil
|
||||
}
|
||||
addr := uintptr(int64(base) + int64(index*uint64(arg.Scale)) + arg.Disp)
|
||||
//TODO: should this always be 64 bits instead of inst.MemBytes?
|
||||
pcbytes, err := thread.readMemory(addr, inst.MemBytes)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
pc = binary.LittleEndian.Uint64(pcbytes)
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
|
||||
file, line, fn := thread.dbp.PCToLine(pc)
|
||||
if fn == nil {
|
||||
return nil
|
||||
}
|
||||
return &Location{PC: pc, File: file, Line: line, Fn: fn}
|
||||
}
|
||||
|
||||
type instrseq []x86asm.Op
|
||||
|
||||
// Possible stacksplit prologues are inserted by stacksplit in
|
||||
// $GOROOT/src/cmd/internal/obj/x86/obj6.go.
|
||||
// The stacksplit prologue will always begin with loading curg in CX, this
|
||||
// instruction is added by load_g_cx in the same file and is either 1 or 2
|
||||
// MOVs.
|
||||
var prologues []instrseq
|
||||
|
||||
func init() {
|
||||
var tinyStacksplit = instrseq{x86asm.CMP, x86asm.JBE}
|
||||
var smallStacksplit = instrseq{x86asm.LEA, x86asm.CMP, x86asm.JBE}
|
||||
var bigStacksplit = instrseq{x86asm.MOV, x86asm.CMP, x86asm.JE, x86asm.LEA, x86asm.SUB, x86asm.CMP, x86asm.JBE}
|
||||
var unixGetG = instrseq{x86asm.MOV}
|
||||
var windowsGetG = instrseq{x86asm.MOV, x86asm.MOV}
|
||||
|
||||
prologues = make([]instrseq, 0, 2*3)
|
||||
for _, getG := range []instrseq{unixGetG, windowsGetG} {
|
||||
for _, stacksplit := range []instrseq{tinyStacksplit, smallStacksplit, bigStacksplit} {
|
||||
prologue := make(instrseq, 0, len(getG)+len(stacksplit))
|
||||
prologue = append(prologue, getG...)
|
||||
prologue = append(prologue, stacksplit...)
|
||||
prologues = append(prologues, prologue)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// FirstPCAfterPrologue returns the address of the first instruction after the prologue for function fn
|
||||
// If sameline is set FirstPCAfterPrologue will always return an address associated with the same line as fn.Entry
|
||||
func (dbp *Process) FirstPCAfterPrologue(fn *gosym.Func, sameline bool) (uint64, error) {
|
||||
text, err := dbp.CurrentThread.Disassemble(fn.Entry, fn.End, false)
|
||||
if err != nil {
|
||||
return fn.Entry, err
|
||||
}
|
||||
|
||||
if len(text) <= 0 {
|
||||
return fn.Entry, nil
|
||||
}
|
||||
|
||||
for _, prologue := range prologues {
|
||||
if len(prologue) >= len(text) {
|
||||
continue
|
||||
}
|
||||
if checkPrologue(text, prologue) {
|
||||
r := &text[len(prologue)]
|
||||
if sameline {
|
||||
if r.Loc.Line != text[0].Loc.Line {
|
||||
return fn.Entry, nil
|
||||
}
|
||||
}
|
||||
return r.Loc.PC, nil
|
||||
}
|
||||
}
|
||||
|
||||
return fn.Entry, nil
|
||||
}
|
||||
|
||||
func checkPrologue(s []AsmInstruction, prologuePattern instrseq) bool {
|
||||
line := s[0].Loc.Line
|
||||
for i, op := range prologuePattern {
|
||||
if s[i].Inst.Op != op || s[i].Loc.Line != line {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
9
vendor/github.com/derekparker/delve/proc/doc.go
generated
vendored
9
vendor/github.com/derekparker/delve/proc/doc.go
generated
vendored
@ -1,9 +0,0 @@
|
||||
// Package proc is a low-level package that provides methods to manipulate
|
||||
// the process we are debugging.
|
||||
//
|
||||
// proc implements all core functionality including:
|
||||
// * creating / attaching to a process
|
||||
// * process manipulation (step, next, continue, halt)
|
||||
// * methods to explore the memory of the process
|
||||
//
|
||||
package proc
|
1121
vendor/github.com/derekparker/delve/proc/eval.go
generated
vendored
1121
vendor/github.com/derekparker/delve/proc/eval.go
generated
vendored
File diff suppressed because it is too large
Load Diff
283
vendor/github.com/derekparker/delve/proc/exc.h
generated
vendored
283
vendor/github.com/derekparker/delve/proc/exc.h
generated
vendored
@ -1,283 +0,0 @@
|
||||
#ifndef _exc_user_
|
||||
#define _exc_user_
|
||||
|
||||
/* Module exc */
|
||||
|
||||
#include <string.h>
|
||||
#include <mach/ndr.h>
|
||||
#include <mach/boolean.h>
|
||||
#include <mach/kern_return.h>
|
||||
#include <mach/notify.h>
|
||||
#include <mach/mach_types.h>
|
||||
#include <mach/message.h>
|
||||
#include <mach/mig_errors.h>
|
||||
#include <mach/port.h>
|
||||
|
||||
/* BEGIN VOUCHER CODE */
|
||||
|
||||
#ifndef KERNEL
|
||||
#if defined(__has_include)
|
||||
#if __has_include(<mach/mig_voucher_support.h>)
|
||||
#ifndef USING_VOUCHERS
|
||||
#define USING_VOUCHERS
|
||||
#endif
|
||||
#ifndef __VOUCHER_FORWARD_TYPE_DECLS__
|
||||
#define __VOUCHER_FORWARD_TYPE_DECLS__
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
extern boolean_t voucher_mach_msg_set(mach_msg_header_t *msg) __attribute__((weak_import));
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif // __VOUCHER_FORWARD_TYPE_DECLS__
|
||||
#endif // __has_include(<mach/mach_voucher_types.h>)
|
||||
#endif // __has_include
|
||||
#endif // !KERNEL
|
||||
|
||||
/* END VOUCHER CODE */
|
||||
|
||||
|
||||
#ifdef AUTOTEST
|
||||
#ifndef FUNCTION_PTR_T
|
||||
#define FUNCTION_PTR_T
|
||||
typedef void (*function_ptr_t)(mach_port_t, char *, mach_msg_type_number_t);
|
||||
typedef struct {
|
||||
char *name;
|
||||
function_ptr_t function;
|
||||
} function_table_entry;
|
||||
typedef function_table_entry *function_table_t;
|
||||
#endif /* FUNCTION_PTR_T */
|
||||
#endif /* AUTOTEST */
|
||||
|
||||
#ifndef exc_MSG_COUNT
|
||||
#define exc_MSG_COUNT 3
|
||||
#endif /* exc_MSG_COUNT */
|
||||
|
||||
#include <mach/std_types.h>
|
||||
#include <mach/mig.h>
|
||||
#include <mach/mig.h>
|
||||
#include <mach/mach_types.h>
|
||||
|
||||
#ifdef __BeforeMigUserHeader
|
||||
__BeforeMigUserHeader
|
||||
#endif /* __BeforeMigUserHeader */
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__BEGIN_DECLS
|
||||
|
||||
|
||||
/* Routine exception_raise */
|
||||
#ifdef mig_external
|
||||
mig_external
|
||||
#else
|
||||
extern
|
||||
#endif /* mig_external */
|
||||
kern_return_t exception_raise
|
||||
(
|
||||
mach_port_t exception_port,
|
||||
mach_port_t thread,
|
||||
mach_port_t task,
|
||||
exception_type_t exception,
|
||||
exception_data_t code,
|
||||
mach_msg_type_number_t codeCnt
|
||||
);
|
||||
|
||||
/* Routine exception_raise_state */
|
||||
#ifdef mig_external
|
||||
mig_external
|
||||
#else
|
||||
extern
|
||||
#endif /* mig_external */
|
||||
kern_return_t exception_raise_state
|
||||
(
|
||||
mach_port_t exception_port,
|
||||
exception_type_t exception,
|
||||
const exception_data_t code,
|
||||
mach_msg_type_number_t codeCnt,
|
||||
int *flavor,
|
||||
const thread_state_t old_state,
|
||||
mach_msg_type_number_t old_stateCnt,
|
||||
thread_state_t new_state,
|
||||
mach_msg_type_number_t *new_stateCnt
|
||||
);
|
||||
|
||||
/* Routine exception_raise_state_identity */
|
||||
#ifdef mig_external
|
||||
mig_external
|
||||
#else
|
||||
extern
|
||||
#endif /* mig_external */
|
||||
kern_return_t exception_raise_state_identity
|
||||
(
|
||||
mach_port_t exception_port,
|
||||
mach_port_t thread,
|
||||
mach_port_t task,
|
||||
exception_type_t exception,
|
||||
exception_data_t code,
|
||||
mach_msg_type_number_t codeCnt,
|
||||
int *flavor,
|
||||
thread_state_t old_state,
|
||||
mach_msg_type_number_t old_stateCnt,
|
||||
thread_state_t new_state,
|
||||
mach_msg_type_number_t *new_stateCnt
|
||||
);
|
||||
|
||||
__END_DECLS
|
||||
|
||||
/********************** Caution **************************/
|
||||
/* The following data types should be used to calculate */
|
||||
/* maximum message sizes only. The actual message may be */
|
||||
/* smaller, and the position of the arguments within the */
|
||||
/* message layout may vary from what is presented here. */
|
||||
/* For example, if any of the arguments are variable- */
|
||||
/* sized, and less than the maximum is sent, the data */
|
||||
/* will be packed tight in the actual message to reduce */
|
||||
/* the presence of holes. */
|
||||
/********************** Caution **************************/
|
||||
|
||||
/* typedefs for all requests */
|
||||
|
||||
#ifndef __Request__exc_subsystem__defined
|
||||
#define __Request__exc_subsystem__defined
|
||||
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack(4)
|
||||
#endif
|
||||
typedef struct {
|
||||
mach_msg_header_t Head;
|
||||
/* start of the kernel processed data */
|
||||
mach_msg_body_t msgh_body;
|
||||
mach_msg_port_descriptor_t thread;
|
||||
mach_msg_port_descriptor_t task;
|
||||
/* end of the kernel processed data */
|
||||
NDR_record_t NDR;
|
||||
exception_type_t exception;
|
||||
mach_msg_type_number_t codeCnt;
|
||||
integer_t code[2];
|
||||
} __Request__exception_raise_t;
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack()
|
||||
#endif
|
||||
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack(4)
|
||||
#endif
|
||||
typedef struct {
|
||||
mach_msg_header_t Head;
|
||||
NDR_record_t NDR;
|
||||
exception_type_t exception;
|
||||
mach_msg_type_number_t codeCnt;
|
||||
integer_t code[2];
|
||||
int flavor;
|
||||
mach_msg_type_number_t old_stateCnt;
|
||||
natural_t old_state[224];
|
||||
} __Request__exception_raise_state_t;
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack()
|
||||
#endif
|
||||
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack(4)
|
||||
#endif
|
||||
typedef struct {
|
||||
mach_msg_header_t Head;
|
||||
/* start of the kernel processed data */
|
||||
mach_msg_body_t msgh_body;
|
||||
mach_msg_port_descriptor_t thread;
|
||||
mach_msg_port_descriptor_t task;
|
||||
/* end of the kernel processed data */
|
||||
NDR_record_t NDR;
|
||||
exception_type_t exception;
|
||||
mach_msg_type_number_t codeCnt;
|
||||
integer_t code[2];
|
||||
int flavor;
|
||||
mach_msg_type_number_t old_stateCnt;
|
||||
natural_t old_state[224];
|
||||
} __Request__exception_raise_state_identity_t;
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack()
|
||||
#endif
|
||||
#endif /* !__Request__exc_subsystem__defined */
|
||||
|
||||
/* union of all requests */
|
||||
|
||||
#ifndef __RequestUnion__exc_subsystem__defined
|
||||
#define __RequestUnion__exc_subsystem__defined
|
||||
union __RequestUnion__exc_subsystem {
|
||||
__Request__exception_raise_t Request_exception_raise;
|
||||
__Request__exception_raise_state_t Request_exception_raise_state;
|
||||
__Request__exception_raise_state_identity_t Request_exception_raise_state_identity;
|
||||
};
|
||||
#endif /* !__RequestUnion__exc_subsystem__defined */
|
||||
/* typedefs for all replies */
|
||||
|
||||
#ifndef __Reply__exc_subsystem__defined
|
||||
#define __Reply__exc_subsystem__defined
|
||||
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack(4)
|
||||
#endif
|
||||
typedef struct {
|
||||
mach_msg_header_t Head;
|
||||
NDR_record_t NDR;
|
||||
kern_return_t RetCode;
|
||||
} __Reply__exception_raise_t;
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack()
|
||||
#endif
|
||||
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack(4)
|
||||
#endif
|
||||
typedef struct {
|
||||
mach_msg_header_t Head;
|
||||
NDR_record_t NDR;
|
||||
kern_return_t RetCode;
|
||||
int flavor;
|
||||
mach_msg_type_number_t new_stateCnt;
|
||||
natural_t new_state[224];
|
||||
} __Reply__exception_raise_state_t;
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack()
|
||||
#endif
|
||||
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack(4)
|
||||
#endif
|
||||
typedef struct {
|
||||
mach_msg_header_t Head;
|
||||
NDR_record_t NDR;
|
||||
kern_return_t RetCode;
|
||||
int flavor;
|
||||
mach_msg_type_number_t new_stateCnt;
|
||||
natural_t new_state[224];
|
||||
} __Reply__exception_raise_state_identity_t;
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack()
|
||||
#endif
|
||||
#endif /* !__Reply__exc_subsystem__defined */
|
||||
|
||||
/* union of all replies */
|
||||
|
||||
#ifndef __ReplyUnion__exc_subsystem__defined
|
||||
#define __ReplyUnion__exc_subsystem__defined
|
||||
union __ReplyUnion__exc_subsystem {
|
||||
__Reply__exception_raise_t Reply_exception_raise;
|
||||
__Reply__exception_raise_state_t Reply_exception_raise_state;
|
||||
__Reply__exception_raise_state_identity_t Reply_exception_raise_state_identity;
|
||||
};
|
||||
#endif /* !__RequestUnion__exc_subsystem__defined */
|
||||
|
||||
#ifndef subsystem_to_name_map_exc
|
||||
#define subsystem_to_name_map_exc \
|
||||
{ "exception_raise", 2401 },\
|
||||
{ "exception_raise_state", 2402 },\
|
||||
{ "exception_raise_state_identity", 2403 }
|
||||
#endif
|
||||
|
||||
#ifdef __AfterMigUserHeader
|
||||
__AfterMigUserHeader
|
||||
#endif /* __AfterMigUserHeader */
|
||||
|
||||
#endif /* _exc_user_ */
|
768
vendor/github.com/derekparker/delve/proc/exc_user_darwin.c
generated
vendored
768
vendor/github.com/derekparker/delve/proc/exc_user_darwin.c
generated
vendored
@ -1,768 +0,0 @@
|
||||
/*
|
||||
* IDENTIFICATION:
|
||||
* stub generated Sun Feb 22 20:54:31 2015
|
||||
* with a MiG generated by bootstrap_cmds-91
|
||||
* OPTIONS:
|
||||
*/
|
||||
#define __MIG_check__Reply__exc_subsystem__ 1
|
||||
|
||||
#include "exc.h"
|
||||
|
||||
|
||||
#ifndef mig_internal
|
||||
#define mig_internal static __inline__
|
||||
#endif /* mig_internal */
|
||||
|
||||
#ifndef mig_external
|
||||
#define mig_external
|
||||
#endif /* mig_external */
|
||||
|
||||
#if !defined(__MigTypeCheck) && defined(TypeCheck)
|
||||
#define __MigTypeCheck TypeCheck /* Legacy setting */
|
||||
#endif /* !defined(__MigTypeCheck) */
|
||||
|
||||
#if !defined(__MigKernelSpecificCode) && defined(_MIG_KERNEL_SPECIFIC_CODE_)
|
||||
#define __MigKernelSpecificCode _MIG_KERNEL_SPECIFIC_CODE_ /* Legacy setting */
|
||||
#endif /* !defined(__MigKernelSpecificCode) */
|
||||
|
||||
#ifndef LimitCheck
|
||||
#define LimitCheck 0
|
||||
#endif /* LimitCheck */
|
||||
|
||||
#ifndef min
|
||||
#define min(a,b) ( ((a) < (b))? (a): (b) )
|
||||
#endif /* min */
|
||||
|
||||
#if !defined(_WALIGN_)
|
||||
#define _WALIGN_(x) (((x) + 3) & ~3)
|
||||
#endif /* !defined(_WALIGN_) */
|
||||
|
||||
#if !defined(_WALIGNSZ_)
|
||||
#define _WALIGNSZ_(x) _WALIGN_(sizeof(x))
|
||||
#endif /* !defined(_WALIGNSZ_) */
|
||||
|
||||
#ifndef UseStaticTemplates
|
||||
#define UseStaticTemplates 0
|
||||
#endif /* UseStaticTemplates */
|
||||
|
||||
#ifndef __MachMsgErrorWithTimeout
|
||||
#define __MachMsgErrorWithTimeout(_R_) { \
|
||||
switch (_R_) { \
|
||||
case MACH_SEND_INVALID_DATA: \
|
||||
case MACH_SEND_INVALID_DEST: \
|
||||
case MACH_SEND_INVALID_HEADER: \
|
||||
mig_put_reply_port(InP->Head.msgh_reply_port); \
|
||||
break; \
|
||||
case MACH_SEND_TIMED_OUT: \
|
||||
case MACH_RCV_TIMED_OUT: \
|
||||
default: \
|
||||
mig_dealloc_reply_port(InP->Head.msgh_reply_port); \
|
||||
} \
|
||||
}
|
||||
#endif /* __MachMsgErrorWithTimeout */
|
||||
|
||||
#ifndef __MachMsgErrorWithoutTimeout
|
||||
#define __MachMsgErrorWithoutTimeout(_R_) { \
|
||||
switch (_R_) { \
|
||||
case MACH_SEND_INVALID_DATA: \
|
||||
case MACH_SEND_INVALID_DEST: \
|
||||
case MACH_SEND_INVALID_HEADER: \
|
||||
mig_put_reply_port(InP->Head.msgh_reply_port); \
|
||||
break; \
|
||||
default: \
|
||||
mig_dealloc_reply_port(InP->Head.msgh_reply_port); \
|
||||
} \
|
||||
}
|
||||
#endif /* __MachMsgErrorWithoutTimeout */
|
||||
|
||||
#ifndef __DeclareSendRpc
|
||||
#define __DeclareSendRpc(_NUM_, _NAME_)
|
||||
#endif /* __DeclareSendRpc */
|
||||
|
||||
#ifndef __BeforeSendRpc
|
||||
#define __BeforeSendRpc(_NUM_, _NAME_)
|
||||
#endif /* __BeforeSendRpc */
|
||||
|
||||
#ifndef __AfterSendRpc
|
||||
#define __AfterSendRpc(_NUM_, _NAME_)
|
||||
#endif /* __AfterSendRpc */
|
||||
|
||||
#ifndef __DeclareSendSimple
|
||||
#define __DeclareSendSimple(_NUM_, _NAME_)
|
||||
#endif /* __DeclareSendSimple */
|
||||
|
||||
#ifndef __BeforeSendSimple
|
||||
#define __BeforeSendSimple(_NUM_, _NAME_)
|
||||
#endif /* __BeforeSendSimple */
|
||||
|
||||
#ifndef __AfterSendSimple
|
||||
#define __AfterSendSimple(_NUM_, _NAME_)
|
||||
#endif /* __AfterSendSimple */
|
||||
|
||||
#define msgh_request_port msgh_remote_port
|
||||
#define msgh_reply_port msgh_local_port
|
||||
|
||||
|
||||
|
||||
#if ( __MigTypeCheck )
|
||||
#if __MIG_check__Reply__exc_subsystem__
|
||||
#if !defined(__MIG_check__Reply__exception_raise_t__defined)
|
||||
#define __MIG_check__Reply__exception_raise_t__defined
|
||||
|
||||
mig_internal kern_return_t __MIG_check__Reply__exception_raise_t(__Reply__exception_raise_t *Out0P)
|
||||
{
|
||||
|
||||
typedef __Reply__exception_raise_t __Reply;
|
||||
if (Out0P->Head.msgh_id != 2501) {
|
||||
if (Out0P->Head.msgh_id == MACH_NOTIFY_SEND_ONCE)
|
||||
{ return MIG_SERVER_DIED; }
|
||||
else
|
||||
{ return MIG_REPLY_MISMATCH; }
|
||||
}
|
||||
|
||||
#if __MigTypeCheck
|
||||
if ((Out0P->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) ||
|
||||
(Out0P->Head.msgh_size != (mach_msg_size_t)sizeof(__Reply)))
|
||||
{ return MIG_TYPE_ERROR ; }
|
||||
#endif /* __MigTypeCheck */
|
||||
|
||||
{
|
||||
return Out0P->RetCode;
|
||||
}
|
||||
}
|
||||
#endif /* !defined(__MIG_check__Reply__exception_raise_t__defined) */
|
||||
#endif /* __MIG_check__Reply__exc_subsystem__ */
|
||||
#endif /* ( __MigTypeCheck ) */
|
||||
|
||||
|
||||
/* Routine exception_raise */
|
||||
mig_external kern_return_t exception_raise
|
||||
(
|
||||
mach_port_t exception_port,
|
||||
mach_port_t thread,
|
||||
mach_port_t task,
|
||||
exception_type_t exception,
|
||||
exception_data_t code,
|
||||
mach_msg_type_number_t codeCnt
|
||||
)
|
||||
{
|
||||
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack(4)
|
||||
#endif
|
||||
typedef struct {
|
||||
mach_msg_header_t Head;
|
||||
/* start of the kernel processed data */
|
||||
mach_msg_body_t msgh_body;
|
||||
mach_msg_port_descriptor_t thread;
|
||||
mach_msg_port_descriptor_t task;
|
||||
/* end of the kernel processed data */
|
||||
NDR_record_t NDR;
|
||||
exception_type_t exception;
|
||||
mach_msg_type_number_t codeCnt;
|
||||
integer_t code[2];
|
||||
} Request;
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack()
|
||||
#endif
|
||||
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack(4)
|
||||
#endif
|
||||
typedef struct {
|
||||
mach_msg_header_t Head;
|
||||
NDR_record_t NDR;
|
||||
kern_return_t RetCode;
|
||||
mach_msg_trailer_t trailer;
|
||||
} Reply;
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack()
|
||||
#endif
|
||||
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack(4)
|
||||
#endif
|
||||
typedef struct {
|
||||
mach_msg_header_t Head;
|
||||
NDR_record_t NDR;
|
||||
kern_return_t RetCode;
|
||||
} __Reply;
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack()
|
||||
#endif
|
||||
/*
|
||||
* typedef struct {
|
||||
* mach_msg_header_t Head;
|
||||
* NDR_record_t NDR;
|
||||
* kern_return_t RetCode;
|
||||
* } mig_reply_error_t;
|
||||
*/
|
||||
|
||||
union {
|
||||
Request In;
|
||||
Reply Out;
|
||||
} Mess;
|
||||
|
||||
Request *InP = &Mess.In;
|
||||
Reply *Out0P = &Mess.Out;
|
||||
|
||||
mach_msg_return_t msg_result;
|
||||
unsigned int msgh_size;
|
||||
|
||||
#ifdef __MIG_check__Reply__exception_raise_t__defined
|
||||
kern_return_t check_result;
|
||||
#endif /* __MIG_check__Reply__exception_raise_t__defined */
|
||||
|
||||
__DeclareSendRpc(2401, "exception_raise")
|
||||
|
||||
#if UseStaticTemplates
|
||||
const static mach_msg_port_descriptor_t threadTemplate = {
|
||||
/* name = */ MACH_PORT_NULL,
|
||||
/* pad1 = */ 0,
|
||||
/* pad2 = */ 0,
|
||||
/* disp = */ 19,
|
||||
/* type = */ MACH_MSG_PORT_DESCRIPTOR,
|
||||
};
|
||||
#endif /* UseStaticTemplates */
|
||||
|
||||
#if UseStaticTemplates
|
||||
const static mach_msg_port_descriptor_t taskTemplate = {
|
||||
/* name = */ MACH_PORT_NULL,
|
||||
/* pad1 = */ 0,
|
||||
/* pad2 = */ 0,
|
||||
/* disp = */ 19,
|
||||
/* type = */ MACH_MSG_PORT_DESCRIPTOR,
|
||||
};
|
||||
#endif /* UseStaticTemplates */
|
||||
|
||||
InP->msgh_body.msgh_descriptor_count = 2;
|
||||
#if UseStaticTemplates
|
||||
InP->thread = threadTemplate;
|
||||
InP->thread.name = thread;
|
||||
#else /* UseStaticTemplates */
|
||||
InP->thread.name = thread;
|
||||
InP->thread.disposition = 19;
|
||||
InP->thread.type = MACH_MSG_PORT_DESCRIPTOR;
|
||||
#endif /* UseStaticTemplates */
|
||||
|
||||
#if UseStaticTemplates
|
||||
InP->task = taskTemplate;
|
||||
InP->task.name = task;
|
||||
#else /* UseStaticTemplates */
|
||||
InP->task.name = task;
|
||||
InP->task.disposition = 19;
|
||||
InP->task.type = MACH_MSG_PORT_DESCRIPTOR;
|
||||
#endif /* UseStaticTemplates */
|
||||
|
||||
InP->NDR = NDR_record;
|
||||
|
||||
InP->exception = exception;
|
||||
|
||||
if (codeCnt > 2) {
|
||||
{ return MIG_ARRAY_TOO_LARGE; }
|
||||
}
|
||||
(void)memcpy((char *) InP->code, (const char *) code, 4 * codeCnt);
|
||||
|
||||
InP->codeCnt = codeCnt;
|
||||
|
||||
msgh_size = (mach_msg_size_t)(sizeof(Request) - 8) + ((4 * codeCnt));
|
||||
InP->Head.msgh_bits = MACH_MSGH_BITS_COMPLEX|
|
||||
MACH_MSGH_BITS(19, MACH_MSG_TYPE_MAKE_SEND_ONCE);
|
||||
/* msgh_size passed as argument */
|
||||
InP->Head.msgh_request_port = exception_port;
|
||||
InP->Head.msgh_reply_port = mig_get_reply_port();
|
||||
InP->Head.msgh_id = 2401;
|
||||
|
||||
/* BEGIN VOUCHER CODE */
|
||||
|
||||
#ifdef USING_VOUCHERS
|
||||
if (voucher_mach_msg_set != NULL) {
|
||||
voucher_mach_msg_set(&InP->Head);
|
||||
}
|
||||
#endif // USING_VOUCHERS
|
||||
|
||||
/* END VOUCHER CODE */
|
||||
|
||||
__BeforeSendRpc(2401, "exception_raise")
|
||||
msg_result = mach_msg(&InP->Head, MACH_SEND_MSG|MACH_RCV_MSG|MACH_MSG_OPTION_NONE, msgh_size, (mach_msg_size_t)sizeof(Reply), InP->Head.msgh_reply_port, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
|
||||
__AfterSendRpc(2401, "exception_raise")
|
||||
if (msg_result != MACH_MSG_SUCCESS) {
|
||||
__MachMsgErrorWithoutTimeout(msg_result);
|
||||
{ return msg_result; }
|
||||
}
|
||||
|
||||
|
||||
#if defined(__MIG_check__Reply__exception_raise_t__defined)
|
||||
check_result = __MIG_check__Reply__exception_raise_t((__Reply__exception_raise_t *)Out0P);
|
||||
if (check_result != MACH_MSG_SUCCESS)
|
||||
{ return check_result; }
|
||||
#endif /* defined(__MIG_check__Reply__exception_raise_t__defined) */
|
||||
|
||||
return KERN_SUCCESS;
|
||||
}
|
||||
|
||||
#if ( __MigTypeCheck )
|
||||
#if __MIG_check__Reply__exc_subsystem__
|
||||
#if !defined(__MIG_check__Reply__exception_raise_state_t__defined)
|
||||
#define __MIG_check__Reply__exception_raise_state_t__defined
|
||||
|
||||
mig_internal kern_return_t __MIG_check__Reply__exception_raise_state_t(__Reply__exception_raise_state_t *Out0P)
|
||||
{
|
||||
|
||||
typedef __Reply__exception_raise_state_t __Reply;
|
||||
#if __MigTypeCheck
|
||||
unsigned int msgh_size;
|
||||
#endif /* __MigTypeCheck */
|
||||
|
||||
if (Out0P->Head.msgh_id != 2502) {
|
||||
if (Out0P->Head.msgh_id == MACH_NOTIFY_SEND_ONCE)
|
||||
{ return MIG_SERVER_DIED; }
|
||||
else
|
||||
{ return MIG_REPLY_MISMATCH; }
|
||||
}
|
||||
|
||||
#if __MigTypeCheck
|
||||
msgh_size = Out0P->Head.msgh_size;
|
||||
|
||||
if ((Out0P->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) ||
|
||||
((msgh_size > (mach_msg_size_t)sizeof(__Reply) || msgh_size < (mach_msg_size_t)(sizeof(__Reply) - 896)) &&
|
||||
(msgh_size != (mach_msg_size_t)sizeof(mig_reply_error_t) ||
|
||||
Out0P->RetCode == KERN_SUCCESS)))
|
||||
{ return MIG_TYPE_ERROR ; }
|
||||
#endif /* __MigTypeCheck */
|
||||
|
||||
if (Out0P->RetCode != KERN_SUCCESS) {
|
||||
return ((mig_reply_error_t *)Out0P)->RetCode;
|
||||
}
|
||||
|
||||
#if __MigTypeCheck
|
||||
if ( Out0P->new_stateCnt > 224 )
|
||||
return MIG_TYPE_ERROR;
|
||||
if (((msgh_size - (mach_msg_size_t)(sizeof(__Reply) - 896)) / 4< Out0P->new_stateCnt) ||
|
||||
(msgh_size != (mach_msg_size_t)(sizeof(__Reply) - 896) + Out0P->new_stateCnt * 4))
|
||||
{ return MIG_TYPE_ERROR ; }
|
||||
#endif /* __MigTypeCheck */
|
||||
|
||||
return MACH_MSG_SUCCESS;
|
||||
}
|
||||
#endif /* !defined(__MIG_check__Reply__exception_raise_state_t__defined) */
|
||||
#endif /* __MIG_check__Reply__exc_subsystem__ */
|
||||
#endif /* ( __MigTypeCheck ) */
|
||||
|
||||
|
||||
/* Routine exception_raise_state */
|
||||
mig_external kern_return_t exception_raise_state
|
||||
(
|
||||
mach_port_t exception_port,
|
||||
exception_type_t exception,
|
||||
const exception_data_t code,
|
||||
mach_msg_type_number_t codeCnt,
|
||||
int *flavor,
|
||||
const thread_state_t old_state,
|
||||
mach_msg_type_number_t old_stateCnt,
|
||||
thread_state_t new_state,
|
||||
mach_msg_type_number_t *new_stateCnt
|
||||
)
|
||||
{
|
||||
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack(4)
|
||||
#endif
|
||||
typedef struct {
|
||||
mach_msg_header_t Head;
|
||||
NDR_record_t NDR;
|
||||
exception_type_t exception;
|
||||
mach_msg_type_number_t codeCnt;
|
||||
integer_t code[2];
|
||||
int flavor;
|
||||
mach_msg_type_number_t old_stateCnt;
|
||||
natural_t old_state[224];
|
||||
} Request;
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack()
|
||||
#endif
|
||||
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack(4)
|
||||
#endif
|
||||
typedef struct {
|
||||
mach_msg_header_t Head;
|
||||
NDR_record_t NDR;
|
||||
kern_return_t RetCode;
|
||||
int flavor;
|
||||
mach_msg_type_number_t new_stateCnt;
|
||||
natural_t new_state[224];
|
||||
mach_msg_trailer_t trailer;
|
||||
} Reply;
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack()
|
||||
#endif
|
||||
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack(4)
|
||||
#endif
|
||||
typedef struct {
|
||||
mach_msg_header_t Head;
|
||||
NDR_record_t NDR;
|
||||
kern_return_t RetCode;
|
||||
int flavor;
|
||||
mach_msg_type_number_t new_stateCnt;
|
||||
natural_t new_state[224];
|
||||
} __Reply;
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack()
|
||||
#endif
|
||||
/*
|
||||
* typedef struct {
|
||||
* mach_msg_header_t Head;
|
||||
* NDR_record_t NDR;
|
||||
* kern_return_t RetCode;
|
||||
* } mig_reply_error_t;
|
||||
*/
|
||||
|
||||
union {
|
||||
Request In;
|
||||
Reply Out;
|
||||
} Mess;
|
||||
|
||||
Request *InP = &Mess.In;
|
||||
Reply *Out0P = &Mess.Out;
|
||||
|
||||
mach_msg_return_t msg_result;
|
||||
unsigned int msgh_size;
|
||||
unsigned int msgh_size_delta;
|
||||
|
||||
|
||||
#ifdef __MIG_check__Reply__exception_raise_state_t__defined
|
||||
kern_return_t check_result;
|
||||
#endif /* __MIG_check__Reply__exception_raise_state_t__defined */
|
||||
|
||||
__DeclareSendRpc(2402, "exception_raise_state")
|
||||
|
||||
InP->NDR = NDR_record;
|
||||
|
||||
InP->exception = exception;
|
||||
|
||||
if (codeCnt > 2) {
|
||||
{ return MIG_ARRAY_TOO_LARGE; }
|
||||
}
|
||||
(void)memcpy((char *) InP->code, (const char *) code, 4 * codeCnt);
|
||||
|
||||
InP->codeCnt = codeCnt;
|
||||
|
||||
msgh_size_delta = (4 * codeCnt);
|
||||
msgh_size = (mach_msg_size_t)(sizeof(Request) - 904) + msgh_size_delta;
|
||||
InP = (Request *) ((pointer_t) InP + msgh_size_delta - 8);
|
||||
|
||||
InP->flavor = *flavor;
|
||||
|
||||
if (old_stateCnt > 224) {
|
||||
{ return MIG_ARRAY_TOO_LARGE; }
|
||||
}
|
||||
(void)memcpy((char *) InP->old_state, (const char *) old_state, 4 * old_stateCnt);
|
||||
|
||||
InP->old_stateCnt = old_stateCnt;
|
||||
|
||||
msgh_size += (4 * old_stateCnt);
|
||||
InP = &Mess.In;
|
||||
InP->Head.msgh_bits =
|
||||
MACH_MSGH_BITS(19, MACH_MSG_TYPE_MAKE_SEND_ONCE);
|
||||
/* msgh_size passed as argument */
|
||||
InP->Head.msgh_request_port = exception_port;
|
||||
InP->Head.msgh_reply_port = mig_get_reply_port();
|
||||
InP->Head.msgh_id = 2402;
|
||||
|
||||
/* BEGIN VOUCHER CODE */
|
||||
|
||||
#ifdef USING_VOUCHERS
|
||||
if (voucher_mach_msg_set != NULL) {
|
||||
voucher_mach_msg_set(&InP->Head);
|
||||
}
|
||||
#endif // USING_VOUCHERS
|
||||
|
||||
/* END VOUCHER CODE */
|
||||
|
||||
__BeforeSendRpc(2402, "exception_raise_state")
|
||||
msg_result = mach_msg(&InP->Head, MACH_SEND_MSG|MACH_RCV_MSG|MACH_MSG_OPTION_NONE, msgh_size, (mach_msg_size_t)sizeof(Reply), InP->Head.msgh_reply_port, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
|
||||
__AfterSendRpc(2402, "exception_raise_state")
|
||||
if (msg_result != MACH_MSG_SUCCESS) {
|
||||
__MachMsgErrorWithoutTimeout(msg_result);
|
||||
{ return msg_result; }
|
||||
}
|
||||
|
||||
|
||||
#if defined(__MIG_check__Reply__exception_raise_state_t__defined)
|
||||
check_result = __MIG_check__Reply__exception_raise_state_t((__Reply__exception_raise_state_t *)Out0P);
|
||||
if (check_result != MACH_MSG_SUCCESS)
|
||||
{ return check_result; }
|
||||
#endif /* defined(__MIG_check__Reply__exception_raise_state_t__defined) */
|
||||
|
||||
*flavor = Out0P->flavor;
|
||||
|
||||
if (Out0P->new_stateCnt > 224) {
|
||||
(void)memcpy((char *) new_state, (const char *) Out0P->new_state, 4 * 224);
|
||||
*new_stateCnt = Out0P->new_stateCnt;
|
||||
{ return MIG_ARRAY_TOO_LARGE; }
|
||||
}
|
||||
(void)memcpy((char *) new_state, (const char *) Out0P->new_state, 4 * Out0P->new_stateCnt);
|
||||
|
||||
*new_stateCnt = Out0P->new_stateCnt;
|
||||
|
||||
return KERN_SUCCESS;
|
||||
}
|
||||
|
||||
#if ( __MigTypeCheck )
|
||||
#if __MIG_check__Reply__exc_subsystem__
|
||||
#if !defined(__MIG_check__Reply__exception_raise_state_identity_t__defined)
|
||||
#define __MIG_check__Reply__exception_raise_state_identity_t__defined
|
||||
|
||||
mig_internal kern_return_t __MIG_check__Reply__exception_raise_state_identity_t(__Reply__exception_raise_state_identity_t *Out0P)
|
||||
{
|
||||
|
||||
typedef __Reply__exception_raise_state_identity_t __Reply;
|
||||
#if __MigTypeCheck
|
||||
unsigned int msgh_size;
|
||||
#endif /* __MigTypeCheck */
|
||||
|
||||
if (Out0P->Head.msgh_id != 2503) {
|
||||
if (Out0P->Head.msgh_id == MACH_NOTIFY_SEND_ONCE)
|
||||
{ return MIG_SERVER_DIED; }
|
||||
else
|
||||
{ return MIG_REPLY_MISMATCH; }
|
||||
}
|
||||
|
||||
#if __MigTypeCheck
|
||||
msgh_size = Out0P->Head.msgh_size;
|
||||
|
||||
if ((Out0P->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) ||
|
||||
((msgh_size > (mach_msg_size_t)sizeof(__Reply) || msgh_size < (mach_msg_size_t)(sizeof(__Reply) - 896)) &&
|
||||
(msgh_size != (mach_msg_size_t)sizeof(mig_reply_error_t) ||
|
||||
Out0P->RetCode == KERN_SUCCESS)))
|
||||
{ return MIG_TYPE_ERROR ; }
|
||||
#endif /* __MigTypeCheck */
|
||||
|
||||
if (Out0P->RetCode != KERN_SUCCESS) {
|
||||
return ((mig_reply_error_t *)Out0P)->RetCode;
|
||||
}
|
||||
|
||||
#if __MigTypeCheck
|
||||
if ( Out0P->new_stateCnt > 224 )
|
||||
return MIG_TYPE_ERROR;
|
||||
if (((msgh_size - (mach_msg_size_t)(sizeof(__Reply) - 896)) / 4< Out0P->new_stateCnt) ||
|
||||
(msgh_size != (mach_msg_size_t)(sizeof(__Reply) - 896) + Out0P->new_stateCnt * 4))
|
||||
{ return MIG_TYPE_ERROR ; }
|
||||
#endif /* __MigTypeCheck */
|
||||
|
||||
return MACH_MSG_SUCCESS;
|
||||
}
|
||||
#endif /* !defined(__MIG_check__Reply__exception_raise_state_identity_t__defined) */
|
||||
#endif /* __MIG_check__Reply__exc_subsystem__ */
|
||||
#endif /* ( __MigTypeCheck ) */
|
||||
|
||||
|
||||
/* Routine exception_raise_state_identity */
|
||||
mig_external kern_return_t exception_raise_state_identity
|
||||
(
|
||||
mach_port_t exception_port,
|
||||
mach_port_t thread,
|
||||
mach_port_t task,
|
||||
exception_type_t exception,
|
||||
exception_data_t code,
|
||||
mach_msg_type_number_t codeCnt,
|
||||
int *flavor,
|
||||
thread_state_t old_state,
|
||||
mach_msg_type_number_t old_stateCnt,
|
||||
thread_state_t new_state,
|
||||
mach_msg_type_number_t *new_stateCnt
|
||||
)
|
||||
{
|
||||
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack(4)
|
||||
#endif
|
||||
typedef struct {
|
||||
mach_msg_header_t Head;
|
||||
/* start of the kernel processed data */
|
||||
mach_msg_body_t msgh_body;
|
||||
mach_msg_port_descriptor_t thread;
|
||||
mach_msg_port_descriptor_t task;
|
||||
/* end of the kernel processed data */
|
||||
NDR_record_t NDR;
|
||||
exception_type_t exception;
|
||||
mach_msg_type_number_t codeCnt;
|
||||
integer_t code[2];
|
||||
int flavor;
|
||||
mach_msg_type_number_t old_stateCnt;
|
||||
natural_t old_state[224];
|
||||
} Request;
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack()
|
||||
#endif
|
||||
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack(4)
|
||||
#endif
|
||||
typedef struct {
|
||||
mach_msg_header_t Head;
|
||||
NDR_record_t NDR;
|
||||
kern_return_t RetCode;
|
||||
int flavor;
|
||||
mach_msg_type_number_t new_stateCnt;
|
||||
natural_t new_state[224];
|
||||
mach_msg_trailer_t trailer;
|
||||
} Reply;
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack()
|
||||
#endif
|
||||
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack(4)
|
||||
#endif
|
||||
typedef struct {
|
||||
mach_msg_header_t Head;
|
||||
NDR_record_t NDR;
|
||||
kern_return_t RetCode;
|
||||
int flavor;
|
||||
mach_msg_type_number_t new_stateCnt;
|
||||
natural_t new_state[224];
|
||||
} __Reply;
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack()
|
||||
#endif
|
||||
/*
|
||||
* typedef struct {
|
||||
* mach_msg_header_t Head;
|
||||
* NDR_record_t NDR;
|
||||
* kern_return_t RetCode;
|
||||
* } mig_reply_error_t;
|
||||
*/
|
||||
|
||||
union {
|
||||
Request In;
|
||||
Reply Out;
|
||||
} Mess;
|
||||
|
||||
Request *InP = &Mess.In;
|
||||
Reply *Out0P = &Mess.Out;
|
||||
|
||||
mach_msg_return_t msg_result;
|
||||
unsigned int msgh_size;
|
||||
unsigned int msgh_size_delta;
|
||||
|
||||
|
||||
#ifdef __MIG_check__Reply__exception_raise_state_identity_t__defined
|
||||
kern_return_t check_result;
|
||||
#endif /* __MIG_check__Reply__exception_raise_state_identity_t__defined */
|
||||
|
||||
__DeclareSendRpc(2403, "exception_raise_state_identity")
|
||||
|
||||
#if UseStaticTemplates
|
||||
const static mach_msg_port_descriptor_t threadTemplate = {
|
||||
/* name = */ MACH_PORT_NULL,
|
||||
/* pad1 = */ 0,
|
||||
/* pad2 = */ 0,
|
||||
/* disp = */ 19,
|
||||
/* type = */ MACH_MSG_PORT_DESCRIPTOR,
|
||||
};
|
||||
#endif /* UseStaticTemplates */
|
||||
|
||||
#if UseStaticTemplates
|
||||
const static mach_msg_port_descriptor_t taskTemplate = {
|
||||
/* name = */ MACH_PORT_NULL,
|
||||
/* pad1 = */ 0,
|
||||
/* pad2 = */ 0,
|
||||
/* disp = */ 19,
|
||||
/* type = */ MACH_MSG_PORT_DESCRIPTOR,
|
||||
};
|
||||
#endif /* UseStaticTemplates */
|
||||
|
||||
InP->msgh_body.msgh_descriptor_count = 2;
|
||||
#if UseStaticTemplates
|
||||
InP->thread = threadTemplate;
|
||||
InP->thread.name = thread;
|
||||
#else /* UseStaticTemplates */
|
||||
InP->thread.name = thread;
|
||||
InP->thread.disposition = 19;
|
||||
InP->thread.type = MACH_MSG_PORT_DESCRIPTOR;
|
||||
#endif /* UseStaticTemplates */
|
||||
|
||||
#if UseStaticTemplates
|
||||
InP->task = taskTemplate;
|
||||
InP->task.name = task;
|
||||
#else /* UseStaticTemplates */
|
||||
InP->task.name = task;
|
||||
InP->task.disposition = 19;
|
||||
InP->task.type = MACH_MSG_PORT_DESCRIPTOR;
|
||||
#endif /* UseStaticTemplates */
|
||||
|
||||
InP->NDR = NDR_record;
|
||||
|
||||
InP->exception = exception;
|
||||
|
||||
if (codeCnt > 2) {
|
||||
{ return MIG_ARRAY_TOO_LARGE; }
|
||||
}
|
||||
(void)memcpy((char *) InP->code, (const char *) code, 4 * codeCnt);
|
||||
|
||||
InP->codeCnt = codeCnt;
|
||||
|
||||
msgh_size_delta = (4 * codeCnt);
|
||||
msgh_size = (mach_msg_size_t)(sizeof(Request) - 904) + msgh_size_delta;
|
||||
InP = (Request *) ((pointer_t) InP + msgh_size_delta - 8);
|
||||
|
||||
InP->flavor = *flavor;
|
||||
|
||||
if (old_stateCnt > 224) {
|
||||
{ return MIG_ARRAY_TOO_LARGE; }
|
||||
}
|
||||
(void)memcpy((char *) InP->old_state, (const char *) old_state, 4 * old_stateCnt);
|
||||
|
||||
InP->old_stateCnt = old_stateCnt;
|
||||
|
||||
msgh_size += (4 * old_stateCnt);
|
||||
InP = &Mess.In;
|
||||
InP->Head.msgh_bits = MACH_MSGH_BITS_COMPLEX|
|
||||
MACH_MSGH_BITS(19, MACH_MSG_TYPE_MAKE_SEND_ONCE);
|
||||
/* msgh_size passed as argument */
|
||||
InP->Head.msgh_request_port = exception_port;
|
||||
InP->Head.msgh_reply_port = mig_get_reply_port();
|
||||
InP->Head.msgh_id = 2403;
|
||||
|
||||
/* BEGIN VOUCHER CODE */
|
||||
|
||||
#ifdef USING_VOUCHERS
|
||||
if (voucher_mach_msg_set != NULL) {
|
||||
voucher_mach_msg_set(&InP->Head);
|
||||
}
|
||||
#endif // USING_VOUCHERS
|
||||
|
||||
/* END VOUCHER CODE */
|
||||
|
||||
__BeforeSendRpc(2403, "exception_raise_state_identity")
|
||||
msg_result = mach_msg(&InP->Head, MACH_SEND_MSG|MACH_RCV_MSG|MACH_MSG_OPTION_NONE, msgh_size, (mach_msg_size_t)sizeof(Reply), InP->Head.msgh_reply_port, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
|
||||
__AfterSendRpc(2403, "exception_raise_state_identity")
|
||||
if (msg_result != MACH_MSG_SUCCESS) {
|
||||
__MachMsgErrorWithoutTimeout(msg_result);
|
||||
{ return msg_result; }
|
||||
}
|
||||
|
||||
|
||||
#if defined(__MIG_check__Reply__exception_raise_state_identity_t__defined)
|
||||
check_result = __MIG_check__Reply__exception_raise_state_identity_t((__Reply__exception_raise_state_identity_t *)Out0P);
|
||||
if (check_result != MACH_MSG_SUCCESS)
|
||||
{ return check_result; }
|
||||
#endif /* defined(__MIG_check__Reply__exception_raise_state_identity_t__defined) */
|
||||
|
||||
*flavor = Out0P->flavor;
|
||||
|
||||
if (Out0P->new_stateCnt > 224) {
|
||||
(void)memcpy((char *) new_state, (const char *) Out0P->new_state, 4 * 224);
|
||||
*new_stateCnt = Out0P->new_stateCnt;
|
||||
{ return MIG_ARRAY_TOO_LARGE; }
|
||||
}
|
||||
(void)memcpy((char *) new_state, (const char *) Out0P->new_state, 4 * Out0P->new_stateCnt);
|
||||
|
||||
*new_stateCnt = Out0P->new_stateCnt;
|
||||
|
||||
return KERN_SUCCESS;
|
||||
}
|
112
vendor/github.com/derekparker/delve/proc/exec_darwin.c
generated
vendored
112
vendor/github.com/derekparker/delve/proc/exec_darwin.c
generated
vendored
@ -1,112 +0,0 @@
|
||||
#include "exec_darwin.h"
|
||||
#include "stdio.h"
|
||||
|
||||
extern char** environ;
|
||||
|
||||
int
|
||||
close_exec_pipe(int fd[2]) {
|
||||
if (pipe(fd) < 0) return -1;
|
||||
if (fcntl(fd[0], F_SETFD, FD_CLOEXEC) < 0) return -1;
|
||||
if (fcntl(fd[1], F_SETFD, FD_CLOEXEC) < 0) return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
fork_exec(char *argv0, char **argv, int size,
|
||||
char *wd,
|
||||
task_t *task,
|
||||
mach_port_t *port_set,
|
||||
mach_port_t *exception_port,
|
||||
mach_port_t *notification_port)
|
||||
{
|
||||
// Since we're using mach exceptions instead of signals,
|
||||
// we need to coordinate between parent and child via pipes
|
||||
// to ensure that the parent has set the exception ports on
|
||||
// the child task before it execs.
|
||||
int fd[2];
|
||||
if (close_exec_pipe(fd) < 0) return -1;
|
||||
|
||||
// Create another pipe to signal the parent on exec.
|
||||
int efd[2];
|
||||
if (close_exec_pipe(efd) < 0) return -1;
|
||||
|
||||
kern_return_t kret;
|
||||
pid_t pid = fork();
|
||||
if (pid > 0) {
|
||||
// In parent.
|
||||
close(fd[0]);
|
||||
close(efd[1]);
|
||||
kret = acquire_mach_task(pid, task, port_set, exception_port, notification_port);
|
||||
if (kret != KERN_SUCCESS) return -1;
|
||||
|
||||
char msg = 'c';
|
||||
write(fd[1], &msg, 1);
|
||||
close(fd[1]);
|
||||
|
||||
char w;
|
||||
size_t n = read(efd[0], &w, 1);
|
||||
close(efd[0]);
|
||||
if (n != 0) {
|
||||
// Child died, reap it.
|
||||
waitpid(pid, NULL, 0);
|
||||
return -1;
|
||||
}
|
||||
return pid;
|
||||
}
|
||||
|
||||
// Fork succeeded, we are in the child.
|
||||
int pret, cret;
|
||||
char sig;
|
||||
|
||||
close(fd[1]);
|
||||
read(fd[0], &sig, 1);
|
||||
close(fd[0]);
|
||||
|
||||
// Create a new process group.
|
||||
if (setpgid(0, 0) < 0) {
|
||||
perror("setpgid");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// Set errno to zero before a call to ptrace.
|
||||
// It is documented that ptrace can return -1 even
|
||||
// for successful calls.
|
||||
errno = 0;
|
||||
pret = ptrace(PT_TRACE_ME, 0, 0, 0);
|
||||
if (pret != 0 && errno != 0) {
|
||||
perror("ptrace");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// Change working directory if wd is not empty.
|
||||
if (wd && wd[0]) {
|
||||
errno = 0;
|
||||
cret = chdir(wd);
|
||||
if (cret != 0 && errno != 0) {
|
||||
char *error_msg;
|
||||
asprintf(&error_msg, "%s '%s'", "chdir", wd);
|
||||
perror(error_msg);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
errno = 0;
|
||||
pret = ptrace(PT_SIGEXC, 0, 0, 0);
|
||||
if (pret != 0 && errno != 0) {
|
||||
perror("ptrace");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
sleep(1);
|
||||
|
||||
// Create the child process.
|
||||
execve(argv0, argv, environ);
|
||||
|
||||
// We should never reach here, but if we did something went wrong.
|
||||
// Write a message to parent to alert that exec failed.
|
||||
char msg = 'd';
|
||||
write(efd[1], &msg, 1);
|
||||
close(efd[1]);
|
||||
|
||||
exit(1);
|
||||
}
|
10
vendor/github.com/derekparker/delve/proc/exec_darwin.h
generated
vendored
10
vendor/github.com/derekparker/delve/proc/exec_darwin.h
generated
vendored
@ -1,10 +0,0 @@
|
||||
#include "proc_darwin.h"
|
||||
|
||||
#include <unistd.h>
|
||||
#include <sys/ptrace.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
int
|
||||
fork_exec(char *, char **, int, char *, task_t*, mach_port_t*, mach_port_t*, mach_port_t*);
|
113
vendor/github.com/derekparker/delve/proc/go_version.go
generated
vendored
113
vendor/github.com/derekparker/delve/proc/go_version.go
generated
vendored
@ -1,113 +0,0 @@
|
||||
package proc
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// GoVersion represents the Go version of
|
||||
// the Go compiler version used to compile
|
||||
// the target binary.
|
||||
type GoVersion struct {
|
||||
Major int
|
||||
Minor int
|
||||
Rev int
|
||||
Beta int
|
||||
RC int
|
||||
}
|
||||
|
||||
func ParseVersionString(ver string) (GoVersion, bool) {
|
||||
var r GoVersion
|
||||
var err1, err2, err3 error
|
||||
|
||||
if strings.HasPrefix(ver, "devel") {
|
||||
return GoVersion{-1, 0, 0, 0, 0}, true
|
||||
}
|
||||
|
||||
if strings.HasPrefix(ver, "go") {
|
||||
ver := strings.Split(ver, " ")[0]
|
||||
v := strings.SplitN(ver[2:], ".", 3)
|
||||
switch len(v) {
|
||||
case 2:
|
||||
r.Major, err1 = strconv.Atoi(v[0])
|
||||
vr := strings.SplitN(v[1], "beta", 2)
|
||||
if len(vr) == 2 {
|
||||
r.Beta, err3 = strconv.Atoi(vr[1])
|
||||
} else {
|
||||
vr = strings.SplitN(v[1], "rc", 2)
|
||||
if len(vr) == 2 {
|
||||
r.RC, err3 = strconv.Atoi(vr[1])
|
||||
} else {
|
||||
r.Minor, err2 = strconv.Atoi(v[1])
|
||||
if err2 != nil {
|
||||
return GoVersion{}, false
|
||||
}
|
||||
return r, true
|
||||
}
|
||||
}
|
||||
|
||||
r.Minor, err2 = strconv.Atoi(vr[0])
|
||||
r.Rev = -1
|
||||
|
||||
if err1 != nil || err2 != nil || err3 != nil {
|
||||
return GoVersion{}, false
|
||||
}
|
||||
|
||||
return r, true
|
||||
|
||||
case 3:
|
||||
|
||||
r.Major, err1 = strconv.Atoi(v[0])
|
||||
r.Minor, err2 = strconv.Atoi(v[1])
|
||||
r.Rev, err3 = strconv.Atoi(v[2])
|
||||
if err1 != nil || err2 != nil || err3 != nil {
|
||||
return GoVersion{}, false
|
||||
}
|
||||
|
||||
return r, true
|
||||
|
||||
default:
|
||||
return GoVersion{}, false
|
||||
}
|
||||
}
|
||||
|
||||
return GoVersion{}, false
|
||||
}
|
||||
|
||||
// AfterOrEqual returns whether one GoVersion is after or
|
||||
// equal to the other.
|
||||
func (v *GoVersion) AfterOrEqual(b GoVersion) bool {
|
||||
if v.Major < b.Major {
|
||||
return false
|
||||
} else if v.Major > b.Major {
|
||||
return true
|
||||
}
|
||||
|
||||
if v.Minor < b.Minor {
|
||||
return false
|
||||
} else if v.Minor > b.Minor {
|
||||
return true
|
||||
}
|
||||
|
||||
if v.Rev < b.Rev {
|
||||
return false
|
||||
} else if v.Rev > b.Rev {
|
||||
return true
|
||||
}
|
||||
|
||||
if v.Beta < b.Beta {
|
||||
return false
|
||||
}
|
||||
|
||||
if v.RC < b.RC {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// IsDevel returns whether the GoVersion
|
||||
// is a development version.
|
||||
func (v *GoVersion) IsDevel() bool {
|
||||
return v.Major < 0
|
||||
}
|
119
vendor/github.com/derekparker/delve/proc/mach_exc.defs
generated
vendored
119
vendor/github.com/derekparker/delve/proc/mach_exc.defs
generated
vendored
@ -1,119 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2006 Apple Computer, Inc. All rights reserved.
|
||||
*
|
||||
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
|
||||
*
|
||||
* This file contains Original Code and/or Modifications of Original Code
|
||||
* as defined in and that are subject to the Apple Public Source License
|
||||
* Version 2.0 (the 'License'). You may not use this file except in
|
||||
* compliance with the License. The rights granted to you under the License
|
||||
* may not be used to create, or enable the creation or redistribution of,
|
||||
* unlawful or unlicensed copies of an Apple operating system, or to
|
||||
* circumvent, violate, or enable the circumvention or violation of, any
|
||||
* terms of an Apple operating system software license agreement.
|
||||
*
|
||||
* Please obtain a copy of the License at
|
||||
* http://www.opensource.apple.com/apsl/ and read it before using this file.
|
||||
*
|
||||
* The Original Code and all software distributed under the License are
|
||||
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
|
||||
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
|
||||
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
|
||||
* Please see the License for the specific language governing rights and
|
||||
* limitations under the License.
|
||||
*
|
||||
* @APPLE_OSREFERENCE_LICENSE_HEADER_END@
|
||||
*/
|
||||
/*
|
||||
* @OSF_COPYRIGHT@
|
||||
*/
|
||||
/*
|
||||
* Mach Operating System
|
||||
* Copyright (c) 1991,1990,1989,1988,1987 Carnegie Mellon University
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission to use, copy, modify and distribute this software and its
|
||||
* documentation is hereby granted, provided that both the copyright
|
||||
* notice and this permission notice appear in all copies of the
|
||||
* software, derivative works or modified versions, and any portions
|
||||
* thereof, and that both notices appear in supporting documentation.
|
||||
*
|
||||
* CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
|
||||
* CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
|
||||
* ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
|
||||
*
|
||||
* Carnegie Mellon requests users of this software to return to
|
||||
*
|
||||
* Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
|
||||
* School of Computer Science
|
||||
* Carnegie Mellon University
|
||||
* Pittsburgh PA 15213-3890
|
||||
*
|
||||
* any improvements or extensions that they make and grant Carnegie Mellon
|
||||
* the rights to redistribute these changes.
|
||||
*/
|
||||
/*
|
||||
*/
|
||||
/*
|
||||
* Abstract:
|
||||
* MiG definitions file for Mach exception interface.
|
||||
*/
|
||||
|
||||
subsystem
|
||||
#if KERNEL_USER
|
||||
KernelUser
|
||||
#endif
|
||||
mach_exc 2405;
|
||||
|
||||
#include <mach/std_types.defs>
|
||||
#include <mach/mach_types.defs>
|
||||
|
||||
ServerPrefix catch_;
|
||||
|
||||
type mach_exception_data_t = array[*:2] of int64_t;
|
||||
type exception_type_t = int;
|
||||
|
||||
routine mach_exception_raise(
|
||||
#if KERNEL_USER
|
||||
exception_port : mach_port_move_send_t;
|
||||
thread : mach_port_move_send_t;
|
||||
task : mach_port_move_send_t;
|
||||
#else /* KERNEL_USER */
|
||||
exception_port : mach_port_t;
|
||||
thread : mach_port_t;
|
||||
task : mach_port_t;
|
||||
#endif /* KERNEL_USER */
|
||||
exception : exception_type_t;
|
||||
code : mach_exception_data_t
|
||||
);
|
||||
|
||||
routine mach_exception_raise_state(
|
||||
#if KERNEL_USER
|
||||
exception_port : mach_port_move_send_t;
|
||||
#else /* KERNEL_USER */
|
||||
exception_port : mach_port_t;
|
||||
#endif /* KERNEL_USER */
|
||||
exception : exception_type_t;
|
||||
code : mach_exception_data_t, const;
|
||||
inout flavor : int;
|
||||
old_state : thread_state_t, const;
|
||||
out new_state : thread_state_t);
|
||||
|
||||
routine mach_exception_raise_state_identity(
|
||||
#if KERNEL_USER
|
||||
exception_port : mach_port_move_send_t;
|
||||
thread : mach_port_move_send_t;
|
||||
task : mach_port_move_send_t;
|
||||
#else /* KERNEL_USER */
|
||||
exception_port : mach_port_t;
|
||||
thread : mach_port_t;
|
||||
task : mach_port_t;
|
||||
#endif /* KERNEL_USER */
|
||||
exception : exception_type_t;
|
||||
code : mach_exception_data_t;
|
||||
inout flavor : int;
|
||||
old_state : thread_state_t;
|
||||
out new_state : thread_state_t);
|
||||
|
||||
/* vim: set ft=c : */
|
283
vendor/github.com/derekparker/delve/proc/mach_exc.h
generated
vendored
283
vendor/github.com/derekparker/delve/proc/mach_exc.h
generated
vendored
@ -1,283 +0,0 @@
|
||||
#ifndef _mach_exc_user_
|
||||
#define _mach_exc_user_
|
||||
|
||||
/* Module mach_exc */
|
||||
|
||||
#include <string.h>
|
||||
#include <mach/ndr.h>
|
||||
#include <mach/boolean.h>
|
||||
#include <mach/kern_return.h>
|
||||
#include <mach/notify.h>
|
||||
#include <mach/mach_types.h>
|
||||
#include <mach/message.h>
|
||||
#include <mach/mig_errors.h>
|
||||
#include <mach/port.h>
|
||||
|
||||
/* BEGIN VOUCHER CODE */
|
||||
|
||||
#ifndef KERNEL
|
||||
#if defined(__has_include)
|
||||
#if __has_include(<mach/mig_voucher_support.h>)
|
||||
#ifndef USING_VOUCHERS
|
||||
#define USING_VOUCHERS
|
||||
#endif
|
||||
#ifndef __VOUCHER_FORWARD_TYPE_DECLS__
|
||||
#define __VOUCHER_FORWARD_TYPE_DECLS__
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
extern boolean_t voucher_mach_msg_set(mach_msg_header_t *msg) __attribute__((weak_import));
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif // __VOUCHER_FORWARD_TYPE_DECLS__
|
||||
#endif // __has_include(<mach/mach_voucher_types.h>)
|
||||
#endif // __has_include
|
||||
#endif // !KERNEL
|
||||
|
||||
/* END VOUCHER CODE */
|
||||
|
||||
|
||||
#ifdef AUTOTEST
|
||||
#ifndef FUNCTION_PTR_T
|
||||
#define FUNCTION_PTR_T
|
||||
typedef void (*function_ptr_t)(mach_port_t, char *, mach_msg_type_number_t);
|
||||
typedef struct {
|
||||
char *name;
|
||||
function_ptr_t function;
|
||||
} function_table_entry;
|
||||
typedef function_table_entry *function_table_t;
|
||||
#endif /* FUNCTION_PTR_T */
|
||||
#endif /* AUTOTEST */
|
||||
|
||||
#ifndef mach_exc_MSG_COUNT
|
||||
#define mach_exc_MSG_COUNT 3
|
||||
#endif /* mach_exc_MSG_COUNT */
|
||||
|
||||
#include <mach/std_types.h>
|
||||
#include <mach/mig.h>
|
||||
#include <mach/mig.h>
|
||||
#include <mach/mach_types.h>
|
||||
|
||||
#ifdef __BeforeMigUserHeader
|
||||
__BeforeMigUserHeader
|
||||
#endif /* __BeforeMigUserHeader */
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__BEGIN_DECLS
|
||||
|
||||
|
||||
/* Routine mach_exception_raise */
|
||||
#ifdef mig_external
|
||||
mig_external
|
||||
#else
|
||||
extern
|
||||
#endif /* mig_external */
|
||||
kern_return_t mach_exception_raise
|
||||
(
|
||||
mach_port_t exception_port,
|
||||
mach_port_t thread,
|
||||
mach_port_t task,
|
||||
exception_type_t exception,
|
||||
mach_exception_data_t code,
|
||||
mach_msg_type_number_t codeCnt
|
||||
);
|
||||
|
||||
/* Routine mach_exception_raise_state */
|
||||
#ifdef mig_external
|
||||
mig_external
|
||||
#else
|
||||
extern
|
||||
#endif /* mig_external */
|
||||
kern_return_t mach_exception_raise_state
|
||||
(
|
||||
mach_port_t exception_port,
|
||||
exception_type_t exception,
|
||||
const mach_exception_data_t code,
|
||||
mach_msg_type_number_t codeCnt,
|
||||
int *flavor,
|
||||
const thread_state_t old_state,
|
||||
mach_msg_type_number_t old_stateCnt,
|
||||
thread_state_t new_state,
|
||||
mach_msg_type_number_t *new_stateCnt
|
||||
);
|
||||
|
||||
/* Routine mach_exception_raise_state_identity */
|
||||
#ifdef mig_external
|
||||
mig_external
|
||||
#else
|
||||
extern
|
||||
#endif /* mig_external */
|
||||
kern_return_t mach_exception_raise_state_identity
|
||||
(
|
||||
mach_port_t exception_port,
|
||||
mach_port_t thread,
|
||||
mach_port_t task,
|
||||
exception_type_t exception,
|
||||
mach_exception_data_t code,
|
||||
mach_msg_type_number_t codeCnt,
|
||||
int *flavor,
|
||||
thread_state_t old_state,
|
||||
mach_msg_type_number_t old_stateCnt,
|
||||
thread_state_t new_state,
|
||||
mach_msg_type_number_t *new_stateCnt
|
||||
);
|
||||
|
||||
__END_DECLS
|
||||
|
||||
/********************** Caution **************************/
|
||||
/* The following data types should be used to calculate */
|
||||
/* maximum message sizes only. The actual message may be */
|
||||
/* smaller, and the position of the arguments within the */
|
||||
/* message layout may vary from what is presented here. */
|
||||
/* For example, if any of the arguments are variable- */
|
||||
/* sized, and less than the maximum is sent, the data */
|
||||
/* will be packed tight in the actual message to reduce */
|
||||
/* the presence of holes. */
|
||||
/********************** Caution **************************/
|
||||
|
||||
/* typedefs for all requests */
|
||||
|
||||
#ifndef __Request__mach_exc_subsystem__defined
|
||||
#define __Request__mach_exc_subsystem__defined
|
||||
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack(4)
|
||||
#endif
|
||||
typedef struct {
|
||||
mach_msg_header_t Head;
|
||||
/* start of the kernel processed data */
|
||||
mach_msg_body_t msgh_body;
|
||||
mach_msg_port_descriptor_t thread;
|
||||
mach_msg_port_descriptor_t task;
|
||||
/* end of the kernel processed data */
|
||||
NDR_record_t NDR;
|
||||
exception_type_t exception;
|
||||
mach_msg_type_number_t codeCnt;
|
||||
int64_t code[2];
|
||||
} __Request__mach_exception_raise_t;
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack()
|
||||
#endif
|
||||
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack(4)
|
||||
#endif
|
||||
typedef struct {
|
||||
mach_msg_header_t Head;
|
||||
NDR_record_t NDR;
|
||||
exception_type_t exception;
|
||||
mach_msg_type_number_t codeCnt;
|
||||
int64_t code[2];
|
||||
int flavor;
|
||||
mach_msg_type_number_t old_stateCnt;
|
||||
natural_t old_state[224];
|
||||
} __Request__mach_exception_raise_state_t;
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack()
|
||||
#endif
|
||||
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack(4)
|
||||
#endif
|
||||
typedef struct {
|
||||
mach_msg_header_t Head;
|
||||
/* start of the kernel processed data */
|
||||
mach_msg_body_t msgh_body;
|
||||
mach_msg_port_descriptor_t thread;
|
||||
mach_msg_port_descriptor_t task;
|
||||
/* end of the kernel processed data */
|
||||
NDR_record_t NDR;
|
||||
exception_type_t exception;
|
||||
mach_msg_type_number_t codeCnt;
|
||||
int64_t code[2];
|
||||
int flavor;
|
||||
mach_msg_type_number_t old_stateCnt;
|
||||
natural_t old_state[224];
|
||||
} __Request__mach_exception_raise_state_identity_t;
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack()
|
||||
#endif
|
||||
#endif /* !__Request__mach_exc_subsystem__defined */
|
||||
|
||||
/* union of all requests */
|
||||
|
||||
#ifndef __RequestUnion__mach_exc_subsystem__defined
|
||||
#define __RequestUnion__mach_exc_subsystem__defined
|
||||
union __RequestUnion__mach_exc_subsystem {
|
||||
__Request__mach_exception_raise_t Request_mach_exception_raise;
|
||||
__Request__mach_exception_raise_state_t Request_mach_exception_raise_state;
|
||||
__Request__mach_exception_raise_state_identity_t Request_mach_exception_raise_state_identity;
|
||||
};
|
||||
#endif /* !__RequestUnion__mach_exc_subsystem__defined */
|
||||
/* typedefs for all replies */
|
||||
|
||||
#ifndef __Reply__mach_exc_subsystem__defined
|
||||
#define __Reply__mach_exc_subsystem__defined
|
||||
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack(4)
|
||||
#endif
|
||||
typedef struct {
|
||||
mach_msg_header_t Head;
|
||||
NDR_record_t NDR;
|
||||
kern_return_t RetCode;
|
||||
} __Reply__mach_exception_raise_t;
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack()
|
||||
#endif
|
||||
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack(4)
|
||||
#endif
|
||||
typedef struct {
|
||||
mach_msg_header_t Head;
|
||||
NDR_record_t NDR;
|
||||
kern_return_t RetCode;
|
||||
int flavor;
|
||||
mach_msg_type_number_t new_stateCnt;
|
||||
natural_t new_state[224];
|
||||
} __Reply__mach_exception_raise_state_t;
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack()
|
||||
#endif
|
||||
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack(4)
|
||||
#endif
|
||||
typedef struct {
|
||||
mach_msg_header_t Head;
|
||||
NDR_record_t NDR;
|
||||
kern_return_t RetCode;
|
||||
int flavor;
|
||||
mach_msg_type_number_t new_stateCnt;
|
||||
natural_t new_state[224];
|
||||
} __Reply__mach_exception_raise_state_identity_t;
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack()
|
||||
#endif
|
||||
#endif /* !__Reply__mach_exc_subsystem__defined */
|
||||
|
||||
/* union of all replies */
|
||||
|
||||
#ifndef __ReplyUnion__mach_exc_subsystem__defined
|
||||
#define __ReplyUnion__mach_exc_subsystem__defined
|
||||
union __ReplyUnion__mach_exc_subsystem {
|
||||
__Reply__mach_exception_raise_t Reply_mach_exception_raise;
|
||||
__Reply__mach_exception_raise_state_t Reply_mach_exception_raise_state;
|
||||
__Reply__mach_exception_raise_state_identity_t Reply_mach_exception_raise_state_identity;
|
||||
};
|
||||
#endif /* !__RequestUnion__mach_exc_subsystem__defined */
|
||||
|
||||
#ifndef subsystem_to_name_map_mach_exc
|
||||
#define subsystem_to_name_map_mach_exc \
|
||||
{ "mach_exception_raise", 2401 },\
|
||||
{ "mach_exception_raise_state", 2402 },\
|
||||
{ "mach_exception_raise_state_identity", 2403 }
|
||||
#endif
|
||||
|
||||
#ifdef __AfterMigUserHeader
|
||||
__AfterMigUserHeader
|
||||
#endif /* __AfterMigUserHeader */
|
||||
|
||||
#endif /* _mach_exc_user_ */
|
768
vendor/github.com/derekparker/delve/proc/mach_exc_user_darwin.c
generated
vendored
768
vendor/github.com/derekparker/delve/proc/mach_exc_user_darwin.c
generated
vendored
@ -1,768 +0,0 @@
|
||||
/*
|
||||
* IDENTIFICATION:
|
||||
* stub generated Sat Feb 21 18:10:52 2015
|
||||
* with a MiG generated by bootstrap_cmds-91
|
||||
* OPTIONS:
|
||||
*/
|
||||
#define __MIG_check__Reply__mach_exc_subsystem__ 1
|
||||
|
||||
#include "mach_exc.h"
|
||||
|
||||
|
||||
#ifndef mig_internal
|
||||
#define mig_internal static __inline__
|
||||
#endif /* mig_internal */
|
||||
|
||||
#ifndef mig_external
|
||||
#define mig_external
|
||||
#endif /* mig_external */
|
||||
|
||||
#if !defined(__MigTypeCheck) && defined(TypeCheck)
|
||||
#define __MigTypeCheck TypeCheck /* Legacy setting */
|
||||
#endif /* !defined(__MigTypeCheck) */
|
||||
|
||||
#if !defined(__MigKernelSpecificCode) && defined(_MIG_KERNEL_SPECIFIC_CODE_)
|
||||
#define __MigKernelSpecificCode _MIG_KERNEL_SPECIFIC_CODE_ /* Legacy setting */
|
||||
#endif /* !defined(__MigKernelSpecificCode) */
|
||||
|
||||
#ifndef LimitCheck
|
||||
#define LimitCheck 0
|
||||
#endif /* LimitCheck */
|
||||
|
||||
#ifndef min
|
||||
#define min(a,b) ( ((a) < (b))? (a): (b) )
|
||||
#endif /* min */
|
||||
|
||||
#if !defined(_WALIGN_)
|
||||
#define _WALIGN_(x) (((x) + 3) & ~3)
|
||||
#endif /* !defined(_WALIGN_) */
|
||||
|
||||
#if !defined(_WALIGNSZ_)
|
||||
#define _WALIGNSZ_(x) _WALIGN_(sizeof(x))
|
||||
#endif /* !defined(_WALIGNSZ_) */
|
||||
|
||||
#ifndef UseStaticTemplates
|
||||
#define UseStaticTemplates 0
|
||||
#endif /* UseStaticTemplates */
|
||||
|
||||
#ifndef __MachMsgErrorWithTimeout
|
||||
#define __MachMsgErrorWithTimeout(_R_) { \
|
||||
switch (_R_) { \
|
||||
case MACH_SEND_INVALID_DATA: \
|
||||
case MACH_SEND_INVALID_DEST: \
|
||||
case MACH_SEND_INVALID_HEADER: \
|
||||
mig_put_reply_port(InP->Head.msgh_reply_port); \
|
||||
break; \
|
||||
case MACH_SEND_TIMED_OUT: \
|
||||
case MACH_RCV_TIMED_OUT: \
|
||||
default: \
|
||||
mig_dealloc_reply_port(InP->Head.msgh_reply_port); \
|
||||
} \
|
||||
}
|
||||
#endif /* __MachMsgErrorWithTimeout */
|
||||
|
||||
#ifndef __MachMsgErrorWithoutTimeout
|
||||
#define __MachMsgErrorWithoutTimeout(_R_) { \
|
||||
switch (_R_) { \
|
||||
case MACH_SEND_INVALID_DATA: \
|
||||
case MACH_SEND_INVALID_DEST: \
|
||||
case MACH_SEND_INVALID_HEADER: \
|
||||
mig_put_reply_port(InP->Head.msgh_reply_port); \
|
||||
break; \
|
||||
default: \
|
||||
mig_dealloc_reply_port(InP->Head.msgh_reply_port); \
|
||||
} \
|
||||
}
|
||||
#endif /* __MachMsgErrorWithoutTimeout */
|
||||
|
||||
#ifndef __DeclareSendRpc
|
||||
#define __DeclareSendRpc(_NUM_, _NAME_)
|
||||
#endif /* __DeclareSendRpc */
|
||||
|
||||
#ifndef __BeforeSendRpc
|
||||
#define __BeforeSendRpc(_NUM_, _NAME_)
|
||||
#endif /* __BeforeSendRpc */
|
||||
|
||||
#ifndef __AfterSendRpc
|
||||
#define __AfterSendRpc(_NUM_, _NAME_)
|
||||
#endif /* __AfterSendRpc */
|
||||
|
||||
#ifndef __DeclareSendSimple
|
||||
#define __DeclareSendSimple(_NUM_, _NAME_)
|
||||
#endif /* __DeclareSendSimple */
|
||||
|
||||
#ifndef __BeforeSendSimple
|
||||
#define __BeforeSendSimple(_NUM_, _NAME_)
|
||||
#endif /* __BeforeSendSimple */
|
||||
|
||||
#ifndef __AfterSendSimple
|
||||
#define __AfterSendSimple(_NUM_, _NAME_)
|
||||
#endif /* __AfterSendSimple */
|
||||
|
||||
#define msgh_request_port msgh_remote_port
|
||||
#define msgh_reply_port msgh_local_port
|
||||
|
||||
|
||||
|
||||
#if ( __MigTypeCheck )
|
||||
#if __MIG_check__Reply__mach_exc_subsystem__
|
||||
#if !defined(__MIG_check__Reply__mach_exception_raise_t__defined)
|
||||
#define __MIG_check__Reply__mach_exception_raise_t__defined
|
||||
|
||||
mig_internal kern_return_t __MIG_check__Reply__mach_exception_raise_t(__Reply__mach_exception_raise_t *Out0P)
|
||||
{
|
||||
|
||||
typedef __Reply__mach_exception_raise_t __Reply;
|
||||
if (Out0P->Head.msgh_id != 2505) {
|
||||
if (Out0P->Head.msgh_id == MACH_NOTIFY_SEND_ONCE)
|
||||
{ return MIG_SERVER_DIED; }
|
||||
else
|
||||
{ return MIG_REPLY_MISMATCH; }
|
||||
}
|
||||
|
||||
#if __MigTypeCheck
|
||||
if ((Out0P->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) ||
|
||||
(Out0P->Head.msgh_size != (mach_msg_size_t)sizeof(__Reply)))
|
||||
{ return MIG_TYPE_ERROR ; }
|
||||
#endif /* __MigTypeCheck */
|
||||
|
||||
{
|
||||
return Out0P->RetCode;
|
||||
}
|
||||
}
|
||||
#endif /* !defined(__MIG_check__Reply__mach_exception_raise_t__defined) */
|
||||
#endif /* __MIG_check__Reply__mach_exc_subsystem__ */
|
||||
#endif /* ( __MigTypeCheck ) */
|
||||
|
||||
|
||||
/* Routine mach_exception_raise */
|
||||
mig_external kern_return_t mach_exception_raise
|
||||
(
|
||||
mach_port_t exception_port,
|
||||
mach_port_t thread,
|
||||
mach_port_t task,
|
||||
exception_type_t exception,
|
||||
mach_exception_data_t code,
|
||||
mach_msg_type_number_t codeCnt
|
||||
)
|
||||
{
|
||||
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack(4)
|
||||
#endif
|
||||
typedef struct {
|
||||
mach_msg_header_t Head;
|
||||
/* start of the kernel processed data */
|
||||
mach_msg_body_t msgh_body;
|
||||
mach_msg_port_descriptor_t thread;
|
||||
mach_msg_port_descriptor_t task;
|
||||
/* end of the kernel processed data */
|
||||
NDR_record_t NDR;
|
||||
exception_type_t exception;
|
||||
mach_msg_type_number_t codeCnt;
|
||||
int64_t code[2];
|
||||
} Request;
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack()
|
||||
#endif
|
||||
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack(4)
|
||||
#endif
|
||||
typedef struct {
|
||||
mach_msg_header_t Head;
|
||||
NDR_record_t NDR;
|
||||
kern_return_t RetCode;
|
||||
mach_msg_trailer_t trailer;
|
||||
} Reply;
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack()
|
||||
#endif
|
||||
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack(4)
|
||||
#endif
|
||||
typedef struct {
|
||||
mach_msg_header_t Head;
|
||||
NDR_record_t NDR;
|
||||
kern_return_t RetCode;
|
||||
} __Reply;
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack()
|
||||
#endif
|
||||
/*
|
||||
* typedef struct {
|
||||
* mach_msg_header_t Head;
|
||||
* NDR_record_t NDR;
|
||||
* kern_return_t RetCode;
|
||||
* } mig_reply_error_t;
|
||||
*/
|
||||
|
||||
union {
|
||||
Request In;
|
||||
Reply Out;
|
||||
} Mess;
|
||||
|
||||
Request *InP = &Mess.In;
|
||||
Reply *Out0P = &Mess.Out;
|
||||
|
||||
mach_msg_return_t msg_result;
|
||||
unsigned int msgh_size;
|
||||
|
||||
#ifdef __MIG_check__Reply__mach_exception_raise_t__defined
|
||||
kern_return_t check_result;
|
||||
#endif /* __MIG_check__Reply__mach_exception_raise_t__defined */
|
||||
|
||||
__DeclareSendRpc(2405, "mach_exception_raise")
|
||||
|
||||
#if UseStaticTemplates
|
||||
const static mach_msg_port_descriptor_t threadTemplate = {
|
||||
/* name = */ MACH_PORT_NULL,
|
||||
/* pad1 = */ 0,
|
||||
/* pad2 = */ 0,
|
||||
/* disp = */ 19,
|
||||
/* type = */ MACH_MSG_PORT_DESCRIPTOR,
|
||||
};
|
||||
#endif /* UseStaticTemplates */
|
||||
|
||||
#if UseStaticTemplates
|
||||
const static mach_msg_port_descriptor_t taskTemplate = {
|
||||
/* name = */ MACH_PORT_NULL,
|
||||
/* pad1 = */ 0,
|
||||
/* pad2 = */ 0,
|
||||
/* disp = */ 19,
|
||||
/* type = */ MACH_MSG_PORT_DESCRIPTOR,
|
||||
};
|
||||
#endif /* UseStaticTemplates */
|
||||
|
||||
InP->msgh_body.msgh_descriptor_count = 2;
|
||||
#if UseStaticTemplates
|
||||
InP->thread = threadTemplate;
|
||||
InP->thread.name = thread;
|
||||
#else /* UseStaticTemplates */
|
||||
InP->thread.name = thread;
|
||||
InP->thread.disposition = 19;
|
||||
InP->thread.type = MACH_MSG_PORT_DESCRIPTOR;
|
||||
#endif /* UseStaticTemplates */
|
||||
|
||||
#if UseStaticTemplates
|
||||
InP->task = taskTemplate;
|
||||
InP->task.name = task;
|
||||
#else /* UseStaticTemplates */
|
||||
InP->task.name = task;
|
||||
InP->task.disposition = 19;
|
||||
InP->task.type = MACH_MSG_PORT_DESCRIPTOR;
|
||||
#endif /* UseStaticTemplates */
|
||||
|
||||
InP->NDR = NDR_record;
|
||||
|
||||
InP->exception = exception;
|
||||
|
||||
if (codeCnt > 2) {
|
||||
{ return MIG_ARRAY_TOO_LARGE; }
|
||||
}
|
||||
(void)memcpy((char *) InP->code, (const char *) code, 8 * codeCnt);
|
||||
|
||||
InP->codeCnt = codeCnt;
|
||||
|
||||
msgh_size = (mach_msg_size_t)(sizeof(Request) - 16) + ((8 * codeCnt));
|
||||
InP->Head.msgh_bits = MACH_MSGH_BITS_COMPLEX|
|
||||
MACH_MSGH_BITS(19, MACH_MSG_TYPE_MAKE_SEND_ONCE);
|
||||
/* msgh_size passed as argument */
|
||||
InP->Head.msgh_request_port = exception_port;
|
||||
InP->Head.msgh_reply_port = mig_get_reply_port();
|
||||
InP->Head.msgh_id = 2405;
|
||||
|
||||
/* BEGIN VOUCHER CODE */
|
||||
|
||||
#ifdef USING_VOUCHERS
|
||||
if (voucher_mach_msg_set != NULL) {
|
||||
voucher_mach_msg_set(&InP->Head);
|
||||
}
|
||||
#endif // USING_VOUCHERS
|
||||
|
||||
/* END VOUCHER CODE */
|
||||
|
||||
__BeforeSendRpc(2405, "mach_exception_raise")
|
||||
msg_result = mach_msg(&InP->Head, MACH_SEND_MSG|MACH_RCV_MSG|MACH_MSG_OPTION_NONE, msgh_size, (mach_msg_size_t)sizeof(Reply), InP->Head.msgh_reply_port, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
|
||||
__AfterSendRpc(2405, "mach_exception_raise")
|
||||
if (msg_result != MACH_MSG_SUCCESS) {
|
||||
__MachMsgErrorWithoutTimeout(msg_result);
|
||||
{ return msg_result; }
|
||||
}
|
||||
|
||||
|
||||
#if defined(__MIG_check__Reply__mach_exception_raise_t__defined)
|
||||
check_result = __MIG_check__Reply__mach_exception_raise_t((__Reply__mach_exception_raise_t *)Out0P);
|
||||
if (check_result != MACH_MSG_SUCCESS)
|
||||
{ return check_result; }
|
||||
#endif /* defined(__MIG_check__Reply__mach_exception_raise_t__defined) */
|
||||
|
||||
return KERN_SUCCESS;
|
||||
}
|
||||
|
||||
#if ( __MigTypeCheck )
|
||||
#if __MIG_check__Reply__mach_exc_subsystem__
|
||||
#if !defined(__MIG_check__Reply__mach_exception_raise_state_t__defined)
|
||||
#define __MIG_check__Reply__mach_exception_raise_state_t__defined
|
||||
|
||||
mig_internal kern_return_t __MIG_check__Reply__mach_exception_raise_state_t(__Reply__mach_exception_raise_state_t *Out0P)
|
||||
{
|
||||
|
||||
typedef __Reply__mach_exception_raise_state_t __Reply;
|
||||
#if __MigTypeCheck
|
||||
unsigned int msgh_size;
|
||||
#endif /* __MigTypeCheck */
|
||||
|
||||
if (Out0P->Head.msgh_id != 2506) {
|
||||
if (Out0P->Head.msgh_id == MACH_NOTIFY_SEND_ONCE)
|
||||
{ return MIG_SERVER_DIED; }
|
||||
else
|
||||
{ return MIG_REPLY_MISMATCH; }
|
||||
}
|
||||
|
||||
#if __MigTypeCheck
|
||||
msgh_size = Out0P->Head.msgh_size;
|
||||
|
||||
if ((Out0P->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) ||
|
||||
((msgh_size > (mach_msg_size_t)sizeof(__Reply) || msgh_size < (mach_msg_size_t)(sizeof(__Reply) - 896)) &&
|
||||
(msgh_size != (mach_msg_size_t)sizeof(mig_reply_error_t) ||
|
||||
Out0P->RetCode == KERN_SUCCESS)))
|
||||
{ return MIG_TYPE_ERROR ; }
|
||||
#endif /* __MigTypeCheck */
|
||||
|
||||
if (Out0P->RetCode != KERN_SUCCESS) {
|
||||
return ((mig_reply_error_t *)Out0P)->RetCode;
|
||||
}
|
||||
|
||||
#if __MigTypeCheck
|
||||
if ( Out0P->new_stateCnt > 224 )
|
||||
return MIG_TYPE_ERROR;
|
||||
if (((msgh_size - (mach_msg_size_t)(sizeof(__Reply) - 896)) / 4< Out0P->new_stateCnt) ||
|
||||
(msgh_size != (mach_msg_size_t)(sizeof(__Reply) - 896) + Out0P->new_stateCnt * 4))
|
||||
{ return MIG_TYPE_ERROR ; }
|
||||
#endif /* __MigTypeCheck */
|
||||
|
||||
return MACH_MSG_SUCCESS;
|
||||
}
|
||||
#endif /* !defined(__MIG_check__Reply__mach_exception_raise_state_t__defined) */
|
||||
#endif /* __MIG_check__Reply__mach_exc_subsystem__ */
|
||||
#endif /* ( __MigTypeCheck ) */
|
||||
|
||||
|
||||
/* Routine mach_exception_raise_state */
|
||||
mig_external kern_return_t mach_exception_raise_state
|
||||
(
|
||||
mach_port_t exception_port,
|
||||
exception_type_t exception,
|
||||
const mach_exception_data_t code,
|
||||
mach_msg_type_number_t codeCnt,
|
||||
int *flavor,
|
||||
const thread_state_t old_state,
|
||||
mach_msg_type_number_t old_stateCnt,
|
||||
thread_state_t new_state,
|
||||
mach_msg_type_number_t *new_stateCnt
|
||||
)
|
||||
{
|
||||
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack(4)
|
||||
#endif
|
||||
typedef struct {
|
||||
mach_msg_header_t Head;
|
||||
NDR_record_t NDR;
|
||||
exception_type_t exception;
|
||||
mach_msg_type_number_t codeCnt;
|
||||
int64_t code[2];
|
||||
int flavor;
|
||||
mach_msg_type_number_t old_stateCnt;
|
||||
natural_t old_state[224];
|
||||
} Request;
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack()
|
||||
#endif
|
||||
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack(4)
|
||||
#endif
|
||||
typedef struct {
|
||||
mach_msg_header_t Head;
|
||||
NDR_record_t NDR;
|
||||
kern_return_t RetCode;
|
||||
int flavor;
|
||||
mach_msg_type_number_t new_stateCnt;
|
||||
natural_t new_state[224];
|
||||
mach_msg_trailer_t trailer;
|
||||
} Reply;
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack()
|
||||
#endif
|
||||
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack(4)
|
||||
#endif
|
||||
typedef struct {
|
||||
mach_msg_header_t Head;
|
||||
NDR_record_t NDR;
|
||||
kern_return_t RetCode;
|
||||
int flavor;
|
||||
mach_msg_type_number_t new_stateCnt;
|
||||
natural_t new_state[224];
|
||||
} __Reply;
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack()
|
||||
#endif
|
||||
/*
|
||||
* typedef struct {
|
||||
* mach_msg_header_t Head;
|
||||
* NDR_record_t NDR;
|
||||
* kern_return_t RetCode;
|
||||
* } mig_reply_error_t;
|
||||
*/
|
||||
|
||||
union {
|
||||
Request In;
|
||||
Reply Out;
|
||||
} Mess;
|
||||
|
||||
Request *InP = &Mess.In;
|
||||
Reply *Out0P = &Mess.Out;
|
||||
|
||||
mach_msg_return_t msg_result;
|
||||
unsigned int msgh_size;
|
||||
unsigned int msgh_size_delta;
|
||||
|
||||
|
||||
#ifdef __MIG_check__Reply__mach_exception_raise_state_t__defined
|
||||
kern_return_t check_result;
|
||||
#endif /* __MIG_check__Reply__mach_exception_raise_state_t__defined */
|
||||
|
||||
__DeclareSendRpc(2406, "mach_exception_raise_state")
|
||||
|
||||
InP->NDR = NDR_record;
|
||||
|
||||
InP->exception = exception;
|
||||
|
||||
if (codeCnt > 2) {
|
||||
{ return MIG_ARRAY_TOO_LARGE; }
|
||||
}
|
||||
(void)memcpy((char *) InP->code, (const char *) code, 8 * codeCnt);
|
||||
|
||||
InP->codeCnt = codeCnt;
|
||||
|
||||
msgh_size_delta = (8 * codeCnt);
|
||||
msgh_size = (mach_msg_size_t)(sizeof(Request) - 912) + msgh_size_delta;
|
||||
InP = (Request *) ((pointer_t) InP + msgh_size_delta - 16);
|
||||
|
||||
InP->flavor = *flavor;
|
||||
|
||||
if (old_stateCnt > 224) {
|
||||
{ return MIG_ARRAY_TOO_LARGE; }
|
||||
}
|
||||
(void)memcpy((char *) InP->old_state, (const char *) old_state, 4 * old_stateCnt);
|
||||
|
||||
InP->old_stateCnt = old_stateCnt;
|
||||
|
||||
msgh_size += (4 * old_stateCnt);
|
||||
InP = &Mess.In;
|
||||
InP->Head.msgh_bits =
|
||||
MACH_MSGH_BITS(19, MACH_MSG_TYPE_MAKE_SEND_ONCE);
|
||||
/* msgh_size passed as argument */
|
||||
InP->Head.msgh_request_port = exception_port;
|
||||
InP->Head.msgh_reply_port = mig_get_reply_port();
|
||||
InP->Head.msgh_id = 2406;
|
||||
|
||||
/* BEGIN VOUCHER CODE */
|
||||
|
||||
#ifdef USING_VOUCHERS
|
||||
if (voucher_mach_msg_set != NULL) {
|
||||
voucher_mach_msg_set(&InP->Head);
|
||||
}
|
||||
#endif // USING_VOUCHERS
|
||||
|
||||
/* END VOUCHER CODE */
|
||||
|
||||
__BeforeSendRpc(2406, "mach_exception_raise_state")
|
||||
msg_result = mach_msg(&InP->Head, MACH_SEND_MSG|MACH_RCV_MSG|MACH_MSG_OPTION_NONE, msgh_size, (mach_msg_size_t)sizeof(Reply), InP->Head.msgh_reply_port, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
|
||||
__AfterSendRpc(2406, "mach_exception_raise_state")
|
||||
if (msg_result != MACH_MSG_SUCCESS) {
|
||||
__MachMsgErrorWithoutTimeout(msg_result);
|
||||
{ return msg_result; }
|
||||
}
|
||||
|
||||
|
||||
#if defined(__MIG_check__Reply__mach_exception_raise_state_t__defined)
|
||||
check_result = __MIG_check__Reply__mach_exception_raise_state_t((__Reply__mach_exception_raise_state_t *)Out0P);
|
||||
if (check_result != MACH_MSG_SUCCESS)
|
||||
{ return check_result; }
|
||||
#endif /* defined(__MIG_check__Reply__mach_exception_raise_state_t__defined) */
|
||||
|
||||
*flavor = Out0P->flavor;
|
||||
|
||||
if (Out0P->new_stateCnt > 224) {
|
||||
(void)memcpy((char *) new_state, (const char *) Out0P->new_state, 4 * 224);
|
||||
*new_stateCnt = Out0P->new_stateCnt;
|
||||
{ return MIG_ARRAY_TOO_LARGE; }
|
||||
}
|
||||
(void)memcpy((char *) new_state, (const char *) Out0P->new_state, 4 * Out0P->new_stateCnt);
|
||||
|
||||
*new_stateCnt = Out0P->new_stateCnt;
|
||||
|
||||
return KERN_SUCCESS;
|
||||
}
|
||||
|
||||
#if ( __MigTypeCheck )
|
||||
#if __MIG_check__Reply__mach_exc_subsystem__
|
||||
#if !defined(__MIG_check__Reply__mach_exception_raise_state_identity_t__defined)
|
||||
#define __MIG_check__Reply__mach_exception_raise_state_identity_t__defined
|
||||
|
||||
mig_internal kern_return_t __MIG_check__Reply__mach_exception_raise_state_identity_t(__Reply__mach_exception_raise_state_identity_t *Out0P)
|
||||
{
|
||||
|
||||
typedef __Reply__mach_exception_raise_state_identity_t __Reply;
|
||||
#if __MigTypeCheck
|
||||
unsigned int msgh_size;
|
||||
#endif /* __MigTypeCheck */
|
||||
|
||||
if (Out0P->Head.msgh_id != 2507) {
|
||||
if (Out0P->Head.msgh_id == MACH_NOTIFY_SEND_ONCE)
|
||||
{ return MIG_SERVER_DIED; }
|
||||
else
|
||||
{ return MIG_REPLY_MISMATCH; }
|
||||
}
|
||||
|
||||
#if __MigTypeCheck
|
||||
msgh_size = Out0P->Head.msgh_size;
|
||||
|
||||
if ((Out0P->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) ||
|
||||
((msgh_size > (mach_msg_size_t)sizeof(__Reply) || msgh_size < (mach_msg_size_t)(sizeof(__Reply) - 896)) &&
|
||||
(msgh_size != (mach_msg_size_t)sizeof(mig_reply_error_t) ||
|
||||
Out0P->RetCode == KERN_SUCCESS)))
|
||||
{ return MIG_TYPE_ERROR ; }
|
||||
#endif /* __MigTypeCheck */
|
||||
|
||||
if (Out0P->RetCode != KERN_SUCCESS) {
|
||||
return ((mig_reply_error_t *)Out0P)->RetCode;
|
||||
}
|
||||
|
||||
#if __MigTypeCheck
|
||||
if ( Out0P->new_stateCnt > 224 )
|
||||
return MIG_TYPE_ERROR;
|
||||
if (((msgh_size - (mach_msg_size_t)(sizeof(__Reply) - 896)) / 4< Out0P->new_stateCnt) ||
|
||||
(msgh_size != (mach_msg_size_t)(sizeof(__Reply) - 896) + Out0P->new_stateCnt * 4))
|
||||
{ return MIG_TYPE_ERROR ; }
|
||||
#endif /* __MigTypeCheck */
|
||||
|
||||
return MACH_MSG_SUCCESS;
|
||||
}
|
||||
#endif /* !defined(__MIG_check__Reply__mach_exception_raise_state_identity_t__defined) */
|
||||
#endif /* __MIG_check__Reply__mach_exc_subsystem__ */
|
||||
#endif /* ( __MigTypeCheck ) */
|
||||
|
||||
|
||||
/* Routine mach_exception_raise_state_identity */
|
||||
mig_external kern_return_t mach_exception_raise_state_identity
|
||||
(
|
||||
mach_port_t exception_port,
|
||||
mach_port_t thread,
|
||||
mach_port_t task,
|
||||
exception_type_t exception,
|
||||
mach_exception_data_t code,
|
||||
mach_msg_type_number_t codeCnt,
|
||||
int *flavor,
|
||||
thread_state_t old_state,
|
||||
mach_msg_type_number_t old_stateCnt,
|
||||
thread_state_t new_state,
|
||||
mach_msg_type_number_t *new_stateCnt
|
||||
)
|
||||
{
|
||||
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack(4)
|
||||
#endif
|
||||
typedef struct {
|
||||
mach_msg_header_t Head;
|
||||
/* start of the kernel processed data */
|
||||
mach_msg_body_t msgh_body;
|
||||
mach_msg_port_descriptor_t thread;
|
||||
mach_msg_port_descriptor_t task;
|
||||
/* end of the kernel processed data */
|
||||
NDR_record_t NDR;
|
||||
exception_type_t exception;
|
||||
mach_msg_type_number_t codeCnt;
|
||||
int64_t code[2];
|
||||
int flavor;
|
||||
mach_msg_type_number_t old_stateCnt;
|
||||
natural_t old_state[224];
|
||||
} Request;
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack()
|
||||
#endif
|
||||
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack(4)
|
||||
#endif
|
||||
typedef struct {
|
||||
mach_msg_header_t Head;
|
||||
NDR_record_t NDR;
|
||||
kern_return_t RetCode;
|
||||
int flavor;
|
||||
mach_msg_type_number_t new_stateCnt;
|
||||
natural_t new_state[224];
|
||||
mach_msg_trailer_t trailer;
|
||||
} Reply;
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack()
|
||||
#endif
|
||||
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack(4)
|
||||
#endif
|
||||
typedef struct {
|
||||
mach_msg_header_t Head;
|
||||
NDR_record_t NDR;
|
||||
kern_return_t RetCode;
|
||||
int flavor;
|
||||
mach_msg_type_number_t new_stateCnt;
|
||||
natural_t new_state[224];
|
||||
} __Reply;
|
||||
#ifdef __MigPackStructs
|
||||
#pragma pack()
|
||||
#endif
|
||||
/*
|
||||
* typedef struct {
|
||||
* mach_msg_header_t Head;
|
||||
* NDR_record_t NDR;
|
||||
* kern_return_t RetCode;
|
||||
* } mig_reply_error_t;
|
||||
*/
|
||||
|
||||
union {
|
||||
Request In;
|
||||
Reply Out;
|
||||
} Mess;
|
||||
|
||||
Request *InP = &Mess.In;
|
||||
Reply *Out0P = &Mess.Out;
|
||||
|
||||
mach_msg_return_t msg_result;
|
||||
unsigned int msgh_size;
|
||||
unsigned int msgh_size_delta;
|
||||
|
||||
|
||||
#ifdef __MIG_check__Reply__mach_exception_raise_state_identity_t__defined
|
||||
kern_return_t check_result;
|
||||
#endif /* __MIG_check__Reply__mach_exception_raise_state_identity_t__defined */
|
||||
|
||||
__DeclareSendRpc(2407, "mach_exception_raise_state_identity")
|
||||
|
||||
#if UseStaticTemplates
|
||||
const static mach_msg_port_descriptor_t threadTemplate = {
|
||||
/* name = */ MACH_PORT_NULL,
|
||||
/* pad1 = */ 0,
|
||||
/* pad2 = */ 0,
|
||||
/* disp = */ 19,
|
||||
/* type = */ MACH_MSG_PORT_DESCRIPTOR,
|
||||
};
|
||||
#endif /* UseStaticTemplates */
|
||||
|
||||
#if UseStaticTemplates
|
||||
const static mach_msg_port_descriptor_t taskTemplate = {
|
||||
/* name = */ MACH_PORT_NULL,
|
||||
/* pad1 = */ 0,
|
||||
/* pad2 = */ 0,
|
||||
/* disp = */ 19,
|
||||
/* type = */ MACH_MSG_PORT_DESCRIPTOR,
|
||||
};
|
||||
#endif /* UseStaticTemplates */
|
||||
|
||||
InP->msgh_body.msgh_descriptor_count = 2;
|
||||
#if UseStaticTemplates
|
||||
InP->thread = threadTemplate;
|
||||
InP->thread.name = thread;
|
||||
#else /* UseStaticTemplates */
|
||||
InP->thread.name = thread;
|
||||
InP->thread.disposition = 19;
|
||||
InP->thread.type = MACH_MSG_PORT_DESCRIPTOR;
|
||||
#endif /* UseStaticTemplates */
|
||||
|
||||
#if UseStaticTemplates
|
||||
InP->task = taskTemplate;
|
||||
InP->task.name = task;
|
||||
#else /* UseStaticTemplates */
|
||||
InP->task.name = task;
|
||||
InP->task.disposition = 19;
|
||||
InP->task.type = MACH_MSG_PORT_DESCRIPTOR;
|
||||
#endif /* UseStaticTemplates */
|
||||
|
||||
InP->NDR = NDR_record;
|
||||
|
||||
InP->exception = exception;
|
||||
|
||||
if (codeCnt > 2) {
|
||||
{ return MIG_ARRAY_TOO_LARGE; }
|
||||
}
|
||||
(void)memcpy((char *) InP->code, (const char *) code, 8 * codeCnt);
|
||||
|
||||
InP->codeCnt = codeCnt;
|
||||
|
||||
msgh_size_delta = (8 * codeCnt);
|
||||
msgh_size = (mach_msg_size_t)(sizeof(Request) - 912) + msgh_size_delta;
|
||||
InP = (Request *) ((pointer_t) InP + msgh_size_delta - 16);
|
||||
|
||||
InP->flavor = *flavor;
|
||||
|
||||
if (old_stateCnt > 224) {
|
||||
{ return MIG_ARRAY_TOO_LARGE; }
|
||||
}
|
||||
(void)memcpy((char *) InP->old_state, (const char *) old_state, 4 * old_stateCnt);
|
||||
|
||||
InP->old_stateCnt = old_stateCnt;
|
||||
|
||||
msgh_size += (4 * old_stateCnt);
|
||||
InP = &Mess.In;
|
||||
InP->Head.msgh_bits = MACH_MSGH_BITS_COMPLEX|
|
||||
MACH_MSGH_BITS(19, MACH_MSG_TYPE_MAKE_SEND_ONCE);
|
||||
/* msgh_size passed as argument */
|
||||
InP->Head.msgh_request_port = exception_port;
|
||||
InP->Head.msgh_reply_port = mig_get_reply_port();
|
||||
InP->Head.msgh_id = 2407;
|
||||
|
||||
/* BEGIN VOUCHER CODE */
|
||||
|
||||
#ifdef USING_VOUCHERS
|
||||
if (voucher_mach_msg_set != NULL) {
|
||||
voucher_mach_msg_set(&InP->Head);
|
||||
}
|
||||
#endif // USING_VOUCHERS
|
||||
|
||||
/* END VOUCHER CODE */
|
||||
|
||||
__BeforeSendRpc(2407, "mach_exception_raise_state_identity")
|
||||
msg_result = mach_msg(&InP->Head, MACH_SEND_MSG|MACH_RCV_MSG|MACH_MSG_OPTION_NONE, msgh_size, (mach_msg_size_t)sizeof(Reply), InP->Head.msgh_reply_port, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
|
||||
__AfterSendRpc(2407, "mach_exception_raise_state_identity")
|
||||
if (msg_result != MACH_MSG_SUCCESS) {
|
||||
__MachMsgErrorWithoutTimeout(msg_result);
|
||||
{ return msg_result; }
|
||||
}
|
||||
|
||||
|
||||
#if defined(__MIG_check__Reply__mach_exception_raise_state_identity_t__defined)
|
||||
check_result = __MIG_check__Reply__mach_exception_raise_state_identity_t((__Reply__mach_exception_raise_state_identity_t *)Out0P);
|
||||
if (check_result != MACH_MSG_SUCCESS)
|
||||
{ return check_result; }
|
||||
#endif /* defined(__MIG_check__Reply__mach_exception_raise_state_identity_t__defined) */
|
||||
|
||||
*flavor = Out0P->flavor;
|
||||
|
||||
if (Out0P->new_stateCnt > 224) {
|
||||
(void)memcpy((char *) new_state, (const char *) Out0P->new_state, 4 * 224);
|
||||
*new_stateCnt = Out0P->new_stateCnt;
|
||||
{ return MIG_ARRAY_TOO_LARGE; }
|
||||
}
|
||||
(void)memcpy((char *) new_state, (const char *) Out0P->new_state, 4 * Out0P->new_stateCnt);
|
||||
|
||||
*new_stateCnt = Out0P->new_stateCnt;
|
||||
|
||||
return KERN_SUCCESS;
|
||||
}
|
57
vendor/github.com/derekparker/delve/proc/mem.go
generated
vendored
57
vendor/github.com/derekparker/delve/proc/mem.go
generated
vendored
@ -1,57 +0,0 @@
|
||||
package proc
|
||||
|
||||
const cacheEnabled = true
|
||||
|
||||
type memoryReadWriter interface {
|
||||
readMemory(addr uintptr, size int) (data []byte, err error)
|
||||
writeMemory(addr uintptr, data []byte) (written int, err error)
|
||||
}
|
||||
|
||||
type memCache struct {
|
||||
cacheAddr uintptr
|
||||
cache []byte
|
||||
mem memoryReadWriter
|
||||
}
|
||||
|
||||
func (m *memCache) contains(addr uintptr, size int) bool {
|
||||
return addr >= m.cacheAddr && addr <= (m.cacheAddr+uintptr(len(m.cache)-size))
|
||||
}
|
||||
|
||||
func (m *memCache) readMemory(addr uintptr, size int) (data []byte, err error) {
|
||||
if m.contains(addr, size) {
|
||||
d := make([]byte, size)
|
||||
copy(d, m.cache[addr-m.cacheAddr:])
|
||||
return d, nil
|
||||
}
|
||||
|
||||
return m.mem.readMemory(addr, size)
|
||||
}
|
||||
|
||||
func (m *memCache) writeMemory(addr uintptr, data []byte) (written int, err error) {
|
||||
return m.mem.writeMemory(addr, data)
|
||||
}
|
||||
|
||||
func cacheMemory(mem memoryReadWriter, addr uintptr, size int) memoryReadWriter {
|
||||
if !cacheEnabled {
|
||||
return mem
|
||||
}
|
||||
if size <= 0 {
|
||||
return mem
|
||||
}
|
||||
if cacheMem, isCache := mem.(*memCache); isCache {
|
||||
if cacheMem.contains(addr, size) {
|
||||
return mem
|
||||
} else {
|
||||
cache, err := cacheMem.mem.readMemory(addr, size)
|
||||
if err != nil {
|
||||
return mem
|
||||
}
|
||||
return &memCache{addr, cache, mem}
|
||||
}
|
||||
}
|
||||
cache, err := mem.readMemory(addr, size)
|
||||
if err != nil {
|
||||
return mem
|
||||
}
|
||||
return &memCache{addr, cache, mem}
|
||||
}
|
189
vendor/github.com/derekparker/delve/proc/moduledata.go
generated
vendored
189
vendor/github.com/derekparker/delve/proc/moduledata.go
generated
vendored
@ -1,189 +0,0 @@
|
||||
package proc
|
||||
|
||||
import (
|
||||
"go/constant"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// delve counterpart to runtime.moduledata
|
||||
type moduleData struct {
|
||||
types, etypes uintptr
|
||||
typemapVar *Variable
|
||||
}
|
||||
|
||||
func (dbp *Process) loadModuleData() (err error) {
|
||||
dbp.loadModuleDataOnce.Do(func() {
|
||||
scope := &EvalScope{Thread: dbp.CurrentThread, PC: 0, CFA: 0}
|
||||
var md *Variable
|
||||
md, err = scope.packageVarAddr("runtime.firstmoduledata")
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
for md.Addr != 0 {
|
||||
var typesVar, etypesVar, nextVar, typemapVar *Variable
|
||||
var types, etypes uint64
|
||||
|
||||
if typesVar, err = md.structMember("types"); err != nil {
|
||||
return
|
||||
}
|
||||
if etypesVar, err = md.structMember("etypes"); err != nil {
|
||||
return
|
||||
}
|
||||
if nextVar, err = md.structMember("next"); err != nil {
|
||||
return
|
||||
}
|
||||
if typemapVar, err = md.structMember("typemap"); err != nil {
|
||||
return
|
||||
}
|
||||
if types, err = typesVar.asUint(); err != nil {
|
||||
return
|
||||
}
|
||||
if etypes, err = etypesVar.asUint(); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
dbp.moduleData = append(dbp.moduleData, moduleData{uintptr(types), uintptr(etypes), typemapVar})
|
||||
|
||||
md = nextVar.maybeDereference()
|
||||
if md.Unreadable != nil {
|
||||
err = md.Unreadable
|
||||
return
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (dbp *Process) resolveTypeOff(typeAddr uintptr, off uintptr) (*Variable, error) {
|
||||
// See runtime.(*_type).typeOff in $GOROOT/src/runtime/type.go
|
||||
if err := dbp.loadModuleData(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var md *moduleData
|
||||
for i := range dbp.moduleData {
|
||||
if typeAddr >= dbp.moduleData[i].types && typeAddr < dbp.moduleData[i].etypes {
|
||||
md = &dbp.moduleData[i]
|
||||
}
|
||||
}
|
||||
|
||||
rtyp, err := dbp.findType("runtime._type")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if md == nil {
|
||||
v, err := dbp.reflectOffsMapAccess(off)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
v.loadValue(LoadConfig{false, 1, 0, 0, -1})
|
||||
addr, _ := constant.Int64Val(v.Value)
|
||||
return v.newVariable(v.Name, uintptr(addr), rtyp), nil
|
||||
}
|
||||
|
||||
if t, _ := md.typemapVar.mapAccess(newConstant(constant.MakeUint64(uint64(off)), dbp.CurrentThread)); t != nil {
|
||||
return t, nil
|
||||
}
|
||||
|
||||
res := md.types + uintptr(off)
|
||||
|
||||
return dbp.CurrentThread.newVariable("", res, rtyp), nil
|
||||
}
|
||||
|
||||
func (dbp *Process) resolveNameOff(typeAddr uintptr, off uintptr) (name, tag string, pkgpathoff int32, err error) {
|
||||
// See runtime.resolveNameOff in $GOROOT/src/runtime/type.go
|
||||
if err = dbp.loadModuleData(); err != nil {
|
||||
return "", "", 0, err
|
||||
}
|
||||
|
||||
for _, md := range dbp.moduleData {
|
||||
if typeAddr >= md.types && typeAddr < md.etypes {
|
||||
return dbp.loadName(md.types + off)
|
||||
}
|
||||
}
|
||||
|
||||
v, err := dbp.reflectOffsMapAccess(off)
|
||||
if err != nil {
|
||||
return "", "", 0, err
|
||||
}
|
||||
|
||||
resv := v.maybeDereference()
|
||||
if resv.Unreadable != nil {
|
||||
return "", "", 0, resv.Unreadable
|
||||
}
|
||||
|
||||
return dbp.loadName(resv.Addr)
|
||||
}
|
||||
|
||||
func (dbp *Process) reflectOffsMapAccess(off uintptr) (*Variable, error) {
|
||||
scope := &EvalScope{Thread: dbp.CurrentThread, PC: 0, CFA: 0}
|
||||
reflectOffs, err := scope.packageVarAddr("runtime.reflectOffs")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
reflectOffsm, err := reflectOffs.structMember("m")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return reflectOffsm.mapAccess(newConstant(constant.MakeUint64(uint64(off)), dbp.CurrentThread))
|
||||
}
|
||||
|
||||
const (
|
||||
// flags for the name struct (see 'type name struct' in $GOROOT/src/reflect/type.go)
|
||||
nameflagExported = 1 << 0
|
||||
nameflagHasTag = 1 << 1
|
||||
nameflagHasPkg = 1 << 2
|
||||
)
|
||||
|
||||
func (dbp *Process) loadName(addr uintptr) (name, tag string, pkgpathoff int32, err error) {
|
||||
off := addr
|
||||
namedata, err := dbp.CurrentThread.readMemory(off, 3)
|
||||
off += 3
|
||||
if err != nil {
|
||||
return "", "", 0, err
|
||||
}
|
||||
|
||||
namelen := uint16(namedata[1]<<8) | uint16(namedata[2])
|
||||
|
||||
rawstr, err := dbp.CurrentThread.readMemory(off, int(namelen))
|
||||
off += uintptr(namelen)
|
||||
if err != nil {
|
||||
return "", "", 0, err
|
||||
}
|
||||
|
||||
name = string(rawstr)
|
||||
|
||||
if namedata[0]&nameflagHasTag != 0 {
|
||||
taglendata, err := dbp.CurrentThread.readMemory(off, 2)
|
||||
off += 2
|
||||
if err != nil {
|
||||
return "", "", 0, err
|
||||
}
|
||||
taglen := uint16(taglendata[0]<<8) | uint16(taglendata[1])
|
||||
|
||||
rawstr, err := dbp.CurrentThread.readMemory(off, int(taglen))
|
||||
off += uintptr(taglen)
|
||||
if err != nil {
|
||||
return "", "", 0, err
|
||||
}
|
||||
|
||||
tag = string(rawstr)
|
||||
}
|
||||
|
||||
if namedata[0]&nameflagHasPkg != 0 {
|
||||
pkgdata, err := dbp.CurrentThread.readMemory(off, 4)
|
||||
if err != nil {
|
||||
return "", "", 0, err
|
||||
}
|
||||
|
||||
// see func pkgPath in $GOROOT/src/reflect/type.go
|
||||
copy((*[4]byte)(unsafe.Pointer(&pkgpathoff))[:], pkgdata)
|
||||
}
|
||||
|
||||
return name, tag, pkgpathoff, nil
|
||||
}
|
942
vendor/github.com/derekparker/delve/proc/proc.go
generated
vendored
942
vendor/github.com/derekparker/delve/proc/proc.go
generated
vendored
@ -1,942 +0,0 @@
|
||||
package proc
|
||||
|
||||
import (
|
||||
"debug/gosym"
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
"go/ast"
|
||||
"go/constant"
|
||||
"go/token"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/derekparker/delve/dwarf/frame"
|
||||
"github.com/derekparker/delve/dwarf/line"
|
||||
"github.com/derekparker/delve/dwarf/reader"
|
||||
"golang.org/x/debug/dwarf"
|
||||
)
|
||||
|
||||
// Process represents all of the information the debugger
|
||||
// is holding onto regarding the process we are debugging.
|
||||
type Process struct {
|
||||
Pid int // Process Pid
|
||||
Process *os.Process // Pointer to process struct for the actual process we are debugging
|
||||
LastModified time.Time // Time the executable of this process was last modified
|
||||
|
||||
// Breakpoint table, holds information on breakpoints.
|
||||
// Maps instruction address to Breakpoint struct.
|
||||
Breakpoints map[uint64]*Breakpoint
|
||||
|
||||
// List of threads mapped as such: pid -> *Thread
|
||||
Threads map[int]*Thread
|
||||
|
||||
// Active thread
|
||||
CurrentThread *Thread
|
||||
|
||||
// Goroutine that will be used by default to set breakpoint, eval variables, etc...
|
||||
// Normally SelectedGoroutine is CurrentThread.GetG, it will not be only if SwitchGoroutine is called with a goroutine that isn't attached to a thread
|
||||
SelectedGoroutine *G
|
||||
|
||||
// Maps package names to package paths, needed to lookup types inside DWARF info
|
||||
packageMap map[string]string
|
||||
|
||||
allGCache []*G
|
||||
dwarf *dwarf.Data
|
||||
goSymTable *gosym.Table
|
||||
frameEntries frame.FrameDescriptionEntries
|
||||
lineInfo line.DebugLines
|
||||
os *OSProcessDetails
|
||||
arch Arch
|
||||
breakpointIDCounter int
|
||||
internalBreakpointIDCounter int
|
||||
firstStart bool
|
||||
halt bool
|
||||
exited bool
|
||||
ptraceChan chan func()
|
||||
ptraceDoneChan chan interface{}
|
||||
types map[string]dwarf.Offset
|
||||
|
||||
loadModuleDataOnce sync.Once
|
||||
moduleData []moduleData
|
||||
nameOfRuntimeType map[uintptr]nameOfRuntimeTypeEntry
|
||||
}
|
||||
|
||||
var NotExecutableErr = errors.New("not an executable file")
|
||||
|
||||
// New returns an initialized Process struct. Before returning,
|
||||
// it will also launch a goroutine in order to handle ptrace(2)
|
||||
// functions. For more information, see the documentation on
|
||||
// `handlePtraceFuncs`.
|
||||
func New(pid int) *Process {
|
||||
dbp := &Process{
|
||||
Pid: pid,
|
||||
Threads: make(map[int]*Thread),
|
||||
Breakpoints: make(map[uint64]*Breakpoint),
|
||||
firstStart: true,
|
||||
os: new(OSProcessDetails),
|
||||
ptraceChan: make(chan func()),
|
||||
ptraceDoneChan: make(chan interface{}),
|
||||
nameOfRuntimeType: make(map[uintptr]nameOfRuntimeTypeEntry),
|
||||
}
|
||||
// TODO: find better way to determine proc arch (perhaps use executable file info)
|
||||
switch runtime.GOARCH {
|
||||
case "amd64":
|
||||
dbp.arch = AMD64Arch()
|
||||
}
|
||||
go dbp.handlePtraceFuncs()
|
||||
return dbp
|
||||
}
|
||||
|
||||
// ProcessExitedError indicates that the process has exited and contains both
|
||||
// process id and exit status.
|
||||
type ProcessExitedError struct {
|
||||
Pid int
|
||||
Status int
|
||||
}
|
||||
|
||||
func (pe ProcessExitedError) Error() string {
|
||||
return fmt.Sprintf("Process %d has exited with status %d", pe.Pid, pe.Status)
|
||||
}
|
||||
|
||||
// Detach from the process being debugged, optionally killing it.
|
||||
func (dbp *Process) Detach(kill bool) (err error) {
|
||||
if dbp.Running() {
|
||||
if err = dbp.Halt(); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
if !kill {
|
||||
// Clean up any breakpoints we've set.
|
||||
for _, bp := range dbp.Breakpoints {
|
||||
if bp != nil {
|
||||
_, err := dbp.ClearBreakpoint(bp.Addr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
dbp.execPtraceFunc(func() {
|
||||
err = PtraceDetach(dbp.Pid, 0)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if kill {
|
||||
err = killProcess(dbp.Pid)
|
||||
}
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// Exited returns whether the debugged
|
||||
// process has exited.
|
||||
func (dbp *Process) Exited() bool {
|
||||
return dbp.exited
|
||||
}
|
||||
|
||||
// Running returns whether the debugged
|
||||
// process is currently executing.
|
||||
func (dbp *Process) Running() bool {
|
||||
for _, th := range dbp.Threads {
|
||||
if th.running {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// LoadInformation finds the executable and then uses it
|
||||
// to parse the following information:
|
||||
// * Dwarf .debug_frame section
|
||||
// * Dwarf .debug_line section
|
||||
// * Go symbol table.
|
||||
func (dbp *Process) LoadInformation(path string) error {
|
||||
var wg sync.WaitGroup
|
||||
|
||||
exe, path, err := dbp.findExecutable(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fi, err := os.Stat(path)
|
||||
if err == nil {
|
||||
dbp.LastModified = fi.ModTime()
|
||||
}
|
||||
|
||||
wg.Add(5)
|
||||
go dbp.loadProcessInformation(&wg)
|
||||
go dbp.parseDebugFrame(exe, &wg)
|
||||
go dbp.obtainGoSymbols(exe, &wg)
|
||||
go dbp.parseDebugLineInfo(exe, &wg)
|
||||
go dbp.loadTypeMap(&wg)
|
||||
wg.Wait()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// FindFileLocation returns the PC for a given file:line.
|
||||
// Assumes that `file` is normailzed to lower case and '/' on Windows.
|
||||
func (dbp *Process) FindFileLocation(fileName string, lineno int) (uint64, error) {
|
||||
pc, fn, err := dbp.goSymTable.LineToPC(fileName, lineno)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if fn.Entry == pc {
|
||||
pc, _ = dbp.FirstPCAfterPrologue(fn, true)
|
||||
}
|
||||
return pc, nil
|
||||
}
|
||||
|
||||
// FindFunctionLocation finds address of a function's line
|
||||
// If firstLine == true is passed FindFunctionLocation will attempt to find the first line of the function
|
||||
// If lineOffset is passed FindFunctionLocation will return the address of that line
|
||||
// Pass lineOffset == 0 and firstLine == false if you want the address for the function's entry point
|
||||
// Note that setting breakpoints at that address will cause surprising behavior:
|
||||
// https://github.com/derekparker/delve/issues/170
|
||||
func (dbp *Process) FindFunctionLocation(funcName string, firstLine bool, lineOffset int) (uint64, error) {
|
||||
origfn := dbp.goSymTable.LookupFunc(funcName)
|
||||
if origfn == nil {
|
||||
return 0, fmt.Errorf("Could not find function %s\n", funcName)
|
||||
}
|
||||
|
||||
if firstLine {
|
||||
return dbp.FirstPCAfterPrologue(origfn, false)
|
||||
} else if lineOffset > 0 {
|
||||
filename, lineno, _ := dbp.goSymTable.PCToLine(origfn.Entry)
|
||||
breakAddr, _, err := dbp.goSymTable.LineToPC(filename, lineno+lineOffset)
|
||||
return breakAddr, err
|
||||
}
|
||||
|
||||
return origfn.Entry, nil
|
||||
}
|
||||
|
||||
// CurrentLocation returns the location of the current thread.
|
||||
func (dbp *Process) CurrentLocation() (*Location, error) {
|
||||
return dbp.CurrentThread.Location()
|
||||
}
|
||||
|
||||
// RequestManualStop sets the `halt` flag and
|
||||
// sends SIGSTOP to all threads.
|
||||
func (dbp *Process) RequestManualStop() error {
|
||||
if dbp.exited {
|
||||
return &ProcessExitedError{}
|
||||
}
|
||||
dbp.halt = true
|
||||
return dbp.requestManualStop()
|
||||
}
|
||||
|
||||
// SetBreakpoint sets a breakpoint at addr, and stores it in the process wide
|
||||
// break point table. Setting a break point must be thread specific due to
|
||||
// ptrace actions needing the thread to be in a signal-delivery-stop.
|
||||
func (dbp *Process) SetBreakpoint(addr uint64, kind BreakpointKind, cond ast.Expr) (*Breakpoint, error) {
|
||||
tid := dbp.CurrentThread.ID
|
||||
|
||||
if bp, ok := dbp.FindBreakpoint(addr); ok {
|
||||
return nil, BreakpointExistsError{bp.File, bp.Line, bp.Addr}
|
||||
}
|
||||
|
||||
f, l, fn := dbp.goSymTable.PCToLine(uint64(addr))
|
||||
if fn == nil {
|
||||
return nil, InvalidAddressError{address: addr}
|
||||
}
|
||||
|
||||
newBreakpoint := &Breakpoint{
|
||||
FunctionName: fn.Name,
|
||||
File: f,
|
||||
Line: l,
|
||||
Addr: addr,
|
||||
Kind: kind,
|
||||
Cond: cond,
|
||||
HitCount: map[int]uint64{},
|
||||
}
|
||||
|
||||
if kind != UserBreakpoint {
|
||||
dbp.internalBreakpointIDCounter++
|
||||
newBreakpoint.ID = dbp.internalBreakpointIDCounter
|
||||
} else {
|
||||
dbp.breakpointIDCounter++
|
||||
newBreakpoint.ID = dbp.breakpointIDCounter
|
||||
}
|
||||
|
||||
thread := dbp.Threads[tid]
|
||||
originalData, err := thread.readMemory(uintptr(addr), dbp.arch.BreakpointSize())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := dbp.writeSoftwareBreakpoint(thread, addr); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
newBreakpoint.OriginalData = originalData
|
||||
dbp.Breakpoints[addr] = newBreakpoint
|
||||
|
||||
return newBreakpoint, nil
|
||||
}
|
||||
|
||||
// ClearBreakpoint clears the breakpoint at addr.
|
||||
func (dbp *Process) ClearBreakpoint(addr uint64) (*Breakpoint, error) {
|
||||
if dbp.exited {
|
||||
return nil, &ProcessExitedError{}
|
||||
}
|
||||
bp, ok := dbp.FindBreakpoint(addr)
|
||||
if !ok {
|
||||
return nil, NoBreakpointError{addr: addr}
|
||||
}
|
||||
|
||||
if _, err := bp.Clear(dbp.CurrentThread); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
delete(dbp.Breakpoints, addr)
|
||||
|
||||
return bp, nil
|
||||
}
|
||||
|
||||
// Status returns the status of the current main thread context.
|
||||
func (dbp *Process) Status() *WaitStatus {
|
||||
return dbp.CurrentThread.Status
|
||||
}
|
||||
|
||||
// Next continues execution until the next source line.
|
||||
func (dbp *Process) Next() (err error) {
|
||||
if dbp.exited {
|
||||
return &ProcessExitedError{}
|
||||
}
|
||||
for i := range dbp.Breakpoints {
|
||||
if dbp.Breakpoints[i].Internal() {
|
||||
return fmt.Errorf("next while nexting")
|
||||
}
|
||||
}
|
||||
|
||||
if err = dbp.next(false); err != nil {
|
||||
switch err.(type) {
|
||||
case ThreadBlockedError, NoReturnAddr: // Noop
|
||||
default:
|
||||
dbp.ClearInternalBreakpoints()
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
return dbp.Continue()
|
||||
}
|
||||
|
||||
// Continue continues execution of the debugged
|
||||
// process. It will continue until it hits a breakpoint
|
||||
// or is otherwise stopped.
|
||||
func (dbp *Process) Continue() error {
|
||||
if dbp.exited {
|
||||
return &ProcessExitedError{}
|
||||
}
|
||||
for {
|
||||
if err := dbp.resume(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
dbp.allGCache = nil
|
||||
for _, th := range dbp.Threads {
|
||||
th.clearBreakpointState()
|
||||
}
|
||||
|
||||
trapthread, err := dbp.trapWait(-1)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := dbp.Halt(); err != nil {
|
||||
return dbp.exitGuard(err)
|
||||
}
|
||||
if err := dbp.setCurrentBreakpoints(trapthread); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := dbp.pickCurrentThread(trapthread); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
switch {
|
||||
case dbp.CurrentThread.CurrentBreakpoint == nil:
|
||||
// runtime.Breakpoint or manual stop
|
||||
if dbp.CurrentThread.onRuntimeBreakpoint() {
|
||||
for i := 0; i < 2; i++ {
|
||||
if err = dbp.CurrentThread.StepInstruction(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return dbp.conditionErrors()
|
||||
case dbp.CurrentThread.onTriggeredInternalBreakpoint():
|
||||
if dbp.CurrentThread.CurrentBreakpoint.Kind == StepBreakpoint {
|
||||
// See description of proc.(*Process).next for the meaning of StepBreakpoints
|
||||
if err := dbp.conditionErrors(); err != nil {
|
||||
return err
|
||||
}
|
||||
pc, err := dbp.CurrentThread.PC()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
text, err := dbp.CurrentThread.Disassemble(pc, pc+maxInstructionLength, true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// here we either set a breakpoint into the destination of the CALL
|
||||
// instruction or we determined that the called function is hidden,
|
||||
// either way we need to resume execution
|
||||
if err = dbp.setStepIntoBreakpoint(text, sameGoroutineCondition(dbp.SelectedGoroutine)); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
if err := dbp.ClearInternalBreakpoints(); err != nil {
|
||||
return err
|
||||
}
|
||||
return dbp.conditionErrors()
|
||||
}
|
||||
case dbp.CurrentThread.onTriggeredBreakpoint():
|
||||
onNextGoroutine, err := dbp.CurrentThread.onNextGoroutine()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if onNextGoroutine {
|
||||
err := dbp.ClearInternalBreakpoints()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return dbp.conditionErrors()
|
||||
default:
|
||||
// not a manual stop, not on runtime.Breakpoint, not on a breakpoint, just repeat
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (dbp *Process) conditionErrors() error {
|
||||
var condErr error
|
||||
for _, th := range dbp.Threads {
|
||||
if th.CurrentBreakpoint != nil && th.BreakpointConditionError != nil {
|
||||
if condErr == nil {
|
||||
condErr = th.BreakpointConditionError
|
||||
} else {
|
||||
return fmt.Errorf("multiple errors evaluating conditions")
|
||||
}
|
||||
}
|
||||
}
|
||||
return condErr
|
||||
}
|
||||
|
||||
// pick a new dbp.CurrentThread, with the following priority:
|
||||
// - a thread with onTriggeredInternalBreakpoint() == true
|
||||
// - a thread with onTriggeredBreakpoint() == true (prioritizing trapthread)
|
||||
// - trapthread
|
||||
func (dbp *Process) pickCurrentThread(trapthread *Thread) error {
|
||||
for _, th := range dbp.Threads {
|
||||
if th.onTriggeredInternalBreakpoint() {
|
||||
return dbp.SwitchThread(th.ID)
|
||||
}
|
||||
}
|
||||
if trapthread.onTriggeredBreakpoint() {
|
||||
return dbp.SwitchThread(trapthread.ID)
|
||||
}
|
||||
for _, th := range dbp.Threads {
|
||||
if th.onTriggeredBreakpoint() {
|
||||
return dbp.SwitchThread(th.ID)
|
||||
}
|
||||
}
|
||||
return dbp.SwitchThread(trapthread.ID)
|
||||
}
|
||||
|
||||
// Step will continue until another source line is reached.
|
||||
// Will step into functions.
|
||||
func (dbp *Process) Step() (err error) {
|
||||
if dbp.exited {
|
||||
return &ProcessExitedError{}
|
||||
}
|
||||
for i := range dbp.Breakpoints {
|
||||
if dbp.Breakpoints[i].Internal() {
|
||||
return fmt.Errorf("next while nexting")
|
||||
}
|
||||
}
|
||||
|
||||
if err = dbp.next(true); err != nil {
|
||||
switch err.(type) {
|
||||
case ThreadBlockedError, NoReturnAddr: // Noop
|
||||
default:
|
||||
dbp.ClearInternalBreakpoints()
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
return dbp.Continue()
|
||||
}
|
||||
|
||||
// Returns an expression that evaluates to true when the current goroutine is g
|
||||
func sameGoroutineCondition(g *G) ast.Expr {
|
||||
if g == nil {
|
||||
return nil
|
||||
}
|
||||
return &ast.BinaryExpr{
|
||||
Op: token.EQL,
|
||||
X: &ast.SelectorExpr{
|
||||
X: &ast.SelectorExpr{
|
||||
X: &ast.Ident{Name: "runtime"},
|
||||
Sel: &ast.Ident{Name: "curg"},
|
||||
},
|
||||
Sel: &ast.Ident{Name: "goid"},
|
||||
},
|
||||
Y: &ast.BasicLit{Kind: token.INT, Value: strconv.Itoa(g.ID)},
|
||||
}
|
||||
}
|
||||
|
||||
// StepInstruction will continue the current thread for exactly
|
||||
// one instruction. This method affects only the thread
|
||||
// asssociated with the selected goroutine. All other
|
||||
// threads will remain stopped.
|
||||
func (dbp *Process) StepInstruction() (err error) {
|
||||
if dbp.SelectedGoroutine == nil {
|
||||
return errors.New("cannot single step: no selected goroutine")
|
||||
}
|
||||
if dbp.SelectedGoroutine.thread == nil {
|
||||
// Step called on parked goroutine
|
||||
if _, err := dbp.SetBreakpoint(dbp.SelectedGoroutine.PC, NextBreakpoint, sameGoroutineCondition(dbp.SelectedGoroutine)); err != nil {
|
||||
return err
|
||||
}
|
||||
return dbp.Continue()
|
||||
}
|
||||
dbp.allGCache = nil
|
||||
if dbp.exited {
|
||||
return &ProcessExitedError{}
|
||||
}
|
||||
dbp.SelectedGoroutine.thread.clearBreakpointState()
|
||||
err = dbp.SelectedGoroutine.thread.StepInstruction()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return dbp.SelectedGoroutine.thread.SetCurrentBreakpoint()
|
||||
}
|
||||
|
||||
// StepOut will continue until the current goroutine exits the
|
||||
// function currently being executed or a deferred function is executed
|
||||
func (dbp *Process) StepOut() error {
|
||||
cond := sameGoroutineCondition(dbp.SelectedGoroutine)
|
||||
|
||||
topframe, err := topframe(dbp.SelectedGoroutine, dbp.CurrentThread)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
pcs := []uint64{}
|
||||
|
||||
var deferpc uint64 = 0
|
||||
if filepath.Ext(topframe.Current.File) == ".go" {
|
||||
if dbp.SelectedGoroutine != nil && dbp.SelectedGoroutine.DeferPC != 0 {
|
||||
_, _, deferfn := dbp.goSymTable.PCToLine(dbp.SelectedGoroutine.DeferPC)
|
||||
deferpc, err = dbp.FirstPCAfterPrologue(deferfn, false)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
pcs = append(pcs, deferpc)
|
||||
}
|
||||
}
|
||||
|
||||
if topframe.Ret == 0 && deferpc == 0 {
|
||||
return errors.New("nothing to stepout to")
|
||||
}
|
||||
|
||||
if deferpc != 0 && deferpc != topframe.Current.PC {
|
||||
bp, err := dbp.SetBreakpoint(deferpc, NextDeferBreakpoint, cond)
|
||||
if err != nil {
|
||||
if _, ok := err.(BreakpointExistsError); !ok {
|
||||
dbp.ClearInternalBreakpoints()
|
||||
return err
|
||||
}
|
||||
}
|
||||
if bp != nil {
|
||||
// For StepOut we do not want to step into the deferred function
|
||||
// when it's called by runtime.deferreturn so we do not populate
|
||||
// DeferReturns.
|
||||
bp.DeferReturns = []uint64{}
|
||||
}
|
||||
}
|
||||
|
||||
if topframe.Ret != 0 {
|
||||
if err := dbp.setInternalBreakpoints(topframe.Current.PC, []uint64{topframe.Ret}, NextBreakpoint, cond); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return dbp.Continue()
|
||||
}
|
||||
|
||||
// SwitchThread changes from current thread to the thread specified by `tid`.
|
||||
func (dbp *Process) SwitchThread(tid int) error {
|
||||
if dbp.exited {
|
||||
return &ProcessExitedError{}
|
||||
}
|
||||
if th, ok := dbp.Threads[tid]; ok {
|
||||
dbp.CurrentThread = th
|
||||
dbp.SelectedGoroutine, _ = dbp.CurrentThread.GetG()
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("thread %d does not exist", tid)
|
||||
}
|
||||
|
||||
// SwitchGoroutine changes from current thread to the thread
|
||||
// running the specified goroutine.
|
||||
func (dbp *Process) SwitchGoroutine(gid int) error {
|
||||
if dbp.exited {
|
||||
return &ProcessExitedError{}
|
||||
}
|
||||
g, err := dbp.FindGoroutine(gid)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if g == nil {
|
||||
// user specified -1 and SelectedGoroutine is nil
|
||||
return nil
|
||||
}
|
||||
if g.thread != nil {
|
||||
return dbp.SwitchThread(g.thread.ID)
|
||||
}
|
||||
dbp.SelectedGoroutine = g
|
||||
return nil
|
||||
}
|
||||
|
||||
// GoroutinesInfo returns an array of G structures representing the information
|
||||
// Delve cares about from the internal runtime G structure.
|
||||
func (dbp *Process) GoroutinesInfo() ([]*G, error) {
|
||||
if dbp.exited {
|
||||
return nil, &ProcessExitedError{}
|
||||
}
|
||||
if dbp.allGCache != nil {
|
||||
return dbp.allGCache, nil
|
||||
}
|
||||
|
||||
var (
|
||||
threadg = map[int]*Thread{}
|
||||
allg []*G
|
||||
rdr = dbp.DwarfReader()
|
||||
)
|
||||
|
||||
for i := range dbp.Threads {
|
||||
if dbp.Threads[i].blocked() {
|
||||
continue
|
||||
}
|
||||
g, _ := dbp.Threads[i].GetG()
|
||||
if g != nil {
|
||||
threadg[g.ID] = dbp.Threads[i]
|
||||
}
|
||||
}
|
||||
|
||||
addr, err := rdr.AddrFor("runtime.allglen")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
allglenBytes, err := dbp.CurrentThread.readMemory(uintptr(addr), 8)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
allglen := binary.LittleEndian.Uint64(allglenBytes)
|
||||
|
||||
rdr.Seek(0)
|
||||
allgentryaddr, err := rdr.AddrFor("runtime.allgs")
|
||||
if err != nil {
|
||||
// try old name (pre Go 1.6)
|
||||
allgentryaddr, err = rdr.AddrFor("runtime.allg")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
faddr, err := dbp.CurrentThread.readMemory(uintptr(allgentryaddr), dbp.arch.PtrSize())
|
||||
allgptr := binary.LittleEndian.Uint64(faddr)
|
||||
|
||||
for i := uint64(0); i < allglen; i++ {
|
||||
gvar, err := dbp.CurrentThread.newGVariable(uintptr(allgptr+(i*uint64(dbp.arch.PtrSize()))), true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
g, err := gvar.parseG()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if thread, allocated := threadg[g.ID]; allocated {
|
||||
loc, err := thread.Location()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
g.thread = thread
|
||||
// Prefer actual thread location information.
|
||||
g.CurrentLoc = *loc
|
||||
}
|
||||
if g.Status != Gdead {
|
||||
allg = append(allg, g)
|
||||
}
|
||||
}
|
||||
dbp.allGCache = allg
|
||||
return allg, nil
|
||||
}
|
||||
|
||||
func (g *G) Thread() *Thread {
|
||||
return g.thread
|
||||
}
|
||||
|
||||
// Halt stops all threads.
|
||||
func (dbp *Process) Halt() (err error) {
|
||||
if dbp.exited {
|
||||
return &ProcessExitedError{}
|
||||
}
|
||||
for _, th := range dbp.Threads {
|
||||
if err := th.Halt(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Registers obtains register values from the
|
||||
// "current" thread of the traced process.
|
||||
func (dbp *Process) Registers() (Registers, error) {
|
||||
return dbp.CurrentThread.Registers(false)
|
||||
}
|
||||
|
||||
// PC returns the PC of the current thread.
|
||||
func (dbp *Process) PC() (uint64, error) {
|
||||
return dbp.CurrentThread.PC()
|
||||
}
|
||||
|
||||
// CurrentBreakpoint returns the breakpoint the current thread
|
||||
// is stopped at.
|
||||
func (dbp *Process) CurrentBreakpoint() *Breakpoint {
|
||||
return dbp.CurrentThread.CurrentBreakpoint
|
||||
}
|
||||
|
||||
// DwarfReader returns a reader for the dwarf data
|
||||
func (dbp *Process) DwarfReader() *reader.Reader {
|
||||
return reader.New(dbp.dwarf)
|
||||
}
|
||||
|
||||
// Sources returns list of source files that comprise the debugged binary.
|
||||
func (dbp *Process) Sources() map[string]*gosym.Obj {
|
||||
return dbp.goSymTable.Files
|
||||
}
|
||||
|
||||
// Funcs returns list of functions present in the debugged program.
|
||||
func (dbp *Process) Funcs() []gosym.Func {
|
||||
return dbp.goSymTable.Funcs
|
||||
}
|
||||
|
||||
// Types returns list of types present in the debugged program.
|
||||
func (dbp *Process) Types() ([]string, error) {
|
||||
types := make([]string, 0, len(dbp.types))
|
||||
for k := range dbp.types {
|
||||
types = append(types, k)
|
||||
}
|
||||
return types, nil
|
||||
}
|
||||
|
||||
// PCToLine converts an instruction address to a file/line/function.
|
||||
func (dbp *Process) PCToLine(pc uint64) (string, int, *gosym.Func) {
|
||||
return dbp.goSymTable.PCToLine(pc)
|
||||
}
|
||||
|
||||
// FindBreakpointByID finds the breakpoint for the given ID.
|
||||
func (dbp *Process) FindBreakpointByID(id int) (*Breakpoint, bool) {
|
||||
for _, bp := range dbp.Breakpoints {
|
||||
if bp.ID == id {
|
||||
return bp, true
|
||||
}
|
||||
}
|
||||
return nil, false
|
||||
}
|
||||
|
||||
// FindBreakpoint finds the breakpoint for the given pc.
|
||||
func (dbp *Process) FindBreakpoint(pc uint64) (*Breakpoint, bool) {
|
||||
// Check to see if address is past the breakpoint, (i.e. breakpoint was hit).
|
||||
if bp, ok := dbp.Breakpoints[pc-uint64(dbp.arch.BreakpointSize())]; ok {
|
||||
return bp, true
|
||||
}
|
||||
// Directly use addr to lookup breakpoint.
|
||||
if bp, ok := dbp.Breakpoints[pc]; ok {
|
||||
return bp, true
|
||||
}
|
||||
return nil, false
|
||||
}
|
||||
|
||||
// Returns a new Process struct.
|
||||
func initializeDebugProcess(dbp *Process, path string, attach bool) (*Process, error) {
|
||||
if attach {
|
||||
var err error
|
||||
dbp.execPtraceFunc(func() { err = PtraceAttach(dbp.Pid) })
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_, _, err = dbp.wait(dbp.Pid, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
proc, err := os.FindProcess(dbp.Pid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
dbp.Process = proc
|
||||
err = dbp.LoadInformation(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := dbp.updateThreadList(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ver, isextld, err := dbp.getGoInformation()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
dbp.arch.SetGStructOffset(ver, isextld)
|
||||
// SelectedGoroutine can not be set correctly by the call to updateThreadList
|
||||
// because without calling SetGStructOffset we can not read the G struct of CurrentThread
|
||||
// but without calling updateThreadList we can not examine memory to determine
|
||||
// the offset of g struct inside TLS
|
||||
dbp.SelectedGoroutine, _ = dbp.CurrentThread.GetG()
|
||||
|
||||
panicpc, err := dbp.FindFunctionLocation("runtime.startpanic", true, 0)
|
||||
if err == nil {
|
||||
bp, err := dbp.SetBreakpoint(panicpc, UserBreakpoint, nil)
|
||||
if err == nil {
|
||||
bp.Name = "unrecovered-panic"
|
||||
bp.ID = -1
|
||||
dbp.breakpointIDCounter--
|
||||
}
|
||||
}
|
||||
|
||||
return dbp, nil
|
||||
}
|
||||
|
||||
func (dbp *Process) ClearInternalBreakpoints() error {
|
||||
for _, bp := range dbp.Breakpoints {
|
||||
if !bp.Internal() {
|
||||
continue
|
||||
}
|
||||
if _, err := dbp.ClearBreakpoint(bp.Addr); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
for i := range dbp.Threads {
|
||||
if dbp.Threads[i].CurrentBreakpoint != nil && dbp.Threads[i].CurrentBreakpoint.Internal() {
|
||||
dbp.Threads[i].CurrentBreakpoint = nil
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (dbp *Process) handlePtraceFuncs() {
|
||||
// We must ensure here that we are running on the same thread during
|
||||
// while invoking the ptrace(2) syscall. This is due to the fact that ptrace(2) expects
|
||||
// all commands after PTRACE_ATTACH to come from the same thread.
|
||||
runtime.LockOSThread()
|
||||
|
||||
for fn := range dbp.ptraceChan {
|
||||
fn()
|
||||
dbp.ptraceDoneChan <- nil
|
||||
}
|
||||
}
|
||||
|
||||
func (dbp *Process) execPtraceFunc(fn func()) {
|
||||
dbp.ptraceChan <- fn
|
||||
<-dbp.ptraceDoneChan
|
||||
}
|
||||
|
||||
func (dbp *Process) getGoInformation() (ver GoVersion, isextld bool, err error) {
|
||||
vv, err := dbp.EvalPackageVariable("runtime.buildVersion", LoadConfig{true, 0, 64, 0, 0})
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Could not determine version number: %v\n", err)
|
||||
return
|
||||
}
|
||||
if vv.Unreadable != nil {
|
||||
err = fmt.Errorf("Unreadable version number: %v\n", vv.Unreadable)
|
||||
return
|
||||
}
|
||||
|
||||
ver, ok := ParseVersionString(constant.StringVal(vv.Value))
|
||||
if !ok {
|
||||
err = fmt.Errorf("Could not parse version number: %v\n", vv.Value)
|
||||
return
|
||||
}
|
||||
|
||||
rdr := dbp.DwarfReader()
|
||||
rdr.Seek(0)
|
||||
for entry, err := rdr.NextCompileUnit(); entry != nil; entry, err = rdr.NextCompileUnit() {
|
||||
if err != nil {
|
||||
return ver, isextld, err
|
||||
}
|
||||
if prod, ok := entry.Val(dwarf.AttrProducer).(string); ok && (strings.HasPrefix(prod, "GNU AS")) {
|
||||
isextld = true
|
||||
break
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// FindGoroutine returns a G struct representing the goroutine
|
||||
// specified by `gid`.
|
||||
func (dbp *Process) FindGoroutine(gid int) (*G, error) {
|
||||
if gid == -1 {
|
||||
return dbp.SelectedGoroutine, nil
|
||||
}
|
||||
|
||||
gs, err := dbp.GoroutinesInfo()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for i := range gs {
|
||||
if gs[i].ID == gid {
|
||||
return gs[i], nil
|
||||
}
|
||||
}
|
||||
return nil, fmt.Errorf("Unknown goroutine %d", gid)
|
||||
}
|
||||
|
||||
// ConvertEvalScope returns a new EvalScope in the context of the
|
||||
// specified goroutine ID and stack frame.
|
||||
func (dbp *Process) ConvertEvalScope(gid, frame int) (*EvalScope, error) {
|
||||
if dbp.exited {
|
||||
return nil, &ProcessExitedError{}
|
||||
}
|
||||
g, err := dbp.FindGoroutine(gid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if g == nil {
|
||||
return dbp.CurrentThread.Scope()
|
||||
}
|
||||
|
||||
var out EvalScope
|
||||
|
||||
if g.thread == nil {
|
||||
out.Thread = dbp.CurrentThread
|
||||
} else {
|
||||
out.Thread = g.thread
|
||||
}
|
||||
|
||||
locs, err := g.Stacktrace(frame)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if frame >= len(locs) {
|
||||
return nil, fmt.Errorf("Frame %d does not exist in goroutine %d", frame, gid)
|
||||
}
|
||||
|
||||
out.PC, out.CFA = locs[frame].Current.PC, locs[frame].CFA
|
||||
|
||||
return &out, nil
|
||||
}
|
||||
|
||||
func (dbp *Process) postExit() {
|
||||
dbp.exited = true
|
||||
close(dbp.ptraceChan)
|
||||
close(dbp.ptraceDoneChan)
|
||||
}
|
231
vendor/github.com/derekparker/delve/proc/proc_darwin.c
generated
vendored
231
vendor/github.com/derekparker/delve/proc/proc_darwin.c
generated
vendored
@ -1,231 +0,0 @@
|
||||
#include "proc_darwin.h"
|
||||
|
||||
static const unsigned char info_plist[]
|
||||
__attribute__ ((section ("__TEXT,__info_plist"),used)) =
|
||||
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
|
||||
"<!DOCTYPE plist PUBLIC \"-//Apple Computer//DTD PLIST 1.0//EN\""
|
||||
" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n"
|
||||
"<plist version=\"1.0\">\n"
|
||||
"<dict>\n"
|
||||
" <key>CFBundleIdentifier</key>\n"
|
||||
" <string>org.dlv</string>\n"
|
||||
" <key>CFBundleName</key>\n"
|
||||
" <string>delve</string>\n"
|
||||
" <key>CFBundleVersion</key>\n"
|
||||
" <string>1.0</string>\n"
|
||||
" <key>SecTaskAccess</key>\n"
|
||||
" <array>\n"
|
||||
" <string>allowed</string>\n"
|
||||
" <string>debug</string>\n"
|
||||
" </array>\n"
|
||||
"</dict>\n"
|
||||
"</plist>\n";
|
||||
|
||||
kern_return_t
|
||||
acquire_mach_task(int tid,
|
||||
task_t *task,
|
||||
mach_port_t *port_set,
|
||||
mach_port_t *exception_port,
|
||||
mach_port_t *notification_port)
|
||||
{
|
||||
kern_return_t kret;
|
||||
mach_port_t prev_not;
|
||||
mach_port_t self = mach_task_self();
|
||||
|
||||
kret = task_for_pid(self, tid, task);
|
||||
if (kret != KERN_SUCCESS) return kret;
|
||||
|
||||
// Allocate exception port.
|
||||
kret = mach_port_allocate(self, MACH_PORT_RIGHT_RECEIVE, exception_port);
|
||||
if (kret != KERN_SUCCESS) return kret;
|
||||
|
||||
kret = mach_port_insert_right(self, *exception_port, *exception_port, MACH_MSG_TYPE_MAKE_SEND);
|
||||
if (kret != KERN_SUCCESS) return kret;
|
||||
|
||||
kret = task_set_exception_ports(*task, EXC_MASK_BREAKPOINT|EXC_MASK_SOFTWARE, *exception_port,
|
||||
EXCEPTION_DEFAULT, THREAD_STATE_NONE);
|
||||
if (kret != KERN_SUCCESS) return kret;
|
||||
|
||||
// Allocate notification port to alert of when the process dies.
|
||||
kret = mach_port_allocate(self, MACH_PORT_RIGHT_RECEIVE, notification_port);
|
||||
if (kret != KERN_SUCCESS) return kret;
|
||||
|
||||
kret = mach_port_insert_right(self, *notification_port, *notification_port, MACH_MSG_TYPE_MAKE_SEND);
|
||||
if (kret != KERN_SUCCESS) return kret;
|
||||
|
||||
kret = mach_port_request_notification(self, *task, MACH_NOTIFY_DEAD_NAME, 0, *notification_port,
|
||||
MACH_MSG_TYPE_MAKE_SEND_ONCE, &prev_not);
|
||||
if (kret != KERN_SUCCESS) return kret;
|
||||
|
||||
// Create port set.
|
||||
kret = mach_port_allocate(self, MACH_PORT_RIGHT_PORT_SET, port_set);
|
||||
if (kret != KERN_SUCCESS) return kret;
|
||||
|
||||
// Move exception and notification ports to port set.
|
||||
kret = mach_port_move_member(self, *exception_port, *port_set);
|
||||
if (kret != KERN_SUCCESS) return kret;
|
||||
|
||||
return mach_port_move_member(self, *notification_port, *port_set);
|
||||
}
|
||||
|
||||
kern_return_t
|
||||
reset_exception_ports(task_t task, mach_port_t *exception_port, mach_port_t *notification_port) {
|
||||
kern_return_t kret;
|
||||
mach_port_t prev_not;
|
||||
mach_port_t self = mach_task_self();
|
||||
|
||||
kret = task_set_exception_ports(task, EXC_MASK_BREAKPOINT|EXC_MASK_SOFTWARE, *exception_port,
|
||||
EXCEPTION_DEFAULT, THREAD_STATE_NONE);
|
||||
|