*: Initial eBPF tracing support (#2625)
This commit is contained in:
parent
89ed5a0b19
commit
10406f96d5
3
.gitignore
vendored
3
.gitignore
vendored
@ -2,7 +2,7 @@
|
||||
.tags*
|
||||
tags
|
||||
.dbg_history
|
||||
cmd/dlv/dlv
|
||||
**/**/dlv
|
||||
.vagrant
|
||||
**/*.swp
|
||||
localtests
|
||||
@ -10,3 +10,4 @@ localtests
|
||||
*.iml
|
||||
.teamcity/target
|
||||
.vscode
|
||||
**/*.o
|
||||
|
@ -26,6 +26,7 @@ clear_breakpoint(Id, Name) | Equivalent to API call [ClearBreakpoint](https://go
|
||||
clear_checkpoint(ID) | Equivalent to API call [ClearCheckpoint](https://godoc.org/github.com/go-delve/delve/service/rpc2#RPCServer.ClearCheckpoint)
|
||||
raw_command(Name, ThreadID, GoroutineID, ReturnInfoLoadConfig, Expr, UnsafeCall) | Equivalent to API call [Command](https://godoc.org/github.com/go-delve/delve/service/rpc2#RPCServer.Command)
|
||||
create_breakpoint(Breakpoint) | Equivalent to API call [CreateBreakpoint](https://godoc.org/github.com/go-delve/delve/service/rpc2#RPCServer.CreateBreakpoint)
|
||||
create_ebpf_tracepoint(FunctionName) | Equivalent to API call [CreateEBPFTracepoint](https://godoc.org/github.com/go-delve/delve/service/rpc2#RPCServer.CreateEBPFTracepoint)
|
||||
create_watchpoint(Scope, Expr, Type) | Equivalent to API call [CreateWatchpoint](https://godoc.org/github.com/go-delve/delve/service/rpc2#RPCServer.CreateWatchpoint)
|
||||
detach(Kill) | Equivalent to API call [Detach](https://godoc.org/github.com/go-delve/delve/service/rpc2#RPCServer.Detach)
|
||||
disassemble(Scope, StartPC, EndPC, Flavour) | Equivalent to API call [Disassemble](https://godoc.org/github.com/go-delve/delve/service/rpc2#RPCServer.Disassemble)
|
||||
@ -37,6 +38,7 @@ examine_memory(Address, Length) | Equivalent to API call [ExamineMemory](https:/
|
||||
find_location(Scope, Loc, IncludeNonExecutableLines, SubstitutePathRules) | Equivalent to API call [FindLocation](https://godoc.org/github.com/go-delve/delve/service/rpc2#RPCServer.FindLocation)
|
||||
function_return_locations(FnName) | Equivalent to API call [FunctionReturnLocations](https://godoc.org/github.com/go-delve/delve/service/rpc2#RPCServer.FunctionReturnLocations)
|
||||
get_breakpoint(Id, Name) | Equivalent to API call [GetBreakpoint](https://godoc.org/github.com/go-delve/delve/service/rpc2#RPCServer.GetBreakpoint)
|
||||
get_buffered_tracepoints() | Equivalent to API call [GetBufferedTracepoints](https://godoc.org/github.com/go-delve/delve/service/rpc2#RPCServer.GetBufferedTracepoints)
|
||||
get_thread(Id) | Equivalent to API call [GetThread](https://godoc.org/github.com/go-delve/delve/service/rpc2#RPCServer.GetThread)
|
||||
is_multiclient() | Equivalent to API call [IsMulticlient](https://godoc.org/github.com/go-delve/delve/service/rpc2#RPCServer.IsMulticlient)
|
||||
last_modified() | Equivalent to API call [LastModified](https://godoc.org/github.com/go-delve/delve/service/rpc2#RPCServer.LastModified)
|
||||
|
@ -21,11 +21,12 @@ dlv trace [package] regexp [flags]
|
||||
### Options
|
||||
|
||||
```
|
||||
--ebpf Trace using eBPF (experimental).
|
||||
-e, --exec string Binary file to exec and trace.
|
||||
-h, --help help for trace
|
||||
--output string Output path for the binary. (default "debug")
|
||||
-p, --pid int Pid to attach to.
|
||||
-s, --stack int Show stack trace with given depth.
|
||||
-s, --stack int Show stack trace with given depth. (Ignored with -ebpf)
|
||||
-t, --test Trace a test binary.
|
||||
```
|
||||
|
||||
|
24
Makefile
24
Makefile
@ -1,12 +1,30 @@
|
||||
.DEFAULT_GOAL=test
|
||||
|
||||
BPF_OBJ := pkg/proc/internal/ebpf/trace_probe/trace.o
|
||||
BPF_SRC := $(shell find . -type f -name '*.bpf.*')
|
||||
GO_SRC := $(shell find . -type f -not -path './_fixtures/*' -not -path './vendor/*' -not -path './_scripts/*' -not -path './localtests/*' -name '*.go')
|
||||
|
||||
check-cert:
|
||||
@go run _scripts/make.go check-cert
|
||||
|
||||
build:
|
||||
build: $(GO_SRC)
|
||||
@go run _scripts/make.go build
|
||||
|
||||
install:
|
||||
$(BPF_OBJ): $(BPF_SRC)
|
||||
clang \
|
||||
-I /usr/include \
|
||||
-I /usr/src/kernels/$(uname -r)/tools/lib \
|
||||
-I /usr/src/kernels/$(uname -r)/tools/bpf/resolve_btfids/libbpf \
|
||||
-g -O2 \
|
||||
-c \
|
||||
-target bpf \
|
||||
-o $(BPF_OBJ) \
|
||||
pkg/proc/internal/ebpf/trace_probe/trace.bpf.c
|
||||
|
||||
build-bpf: $(BPF_OBJ) $(GO_SRC)
|
||||
@env CGO_LDFLAGS="/usr/lib64/libbpf.a" go run _scripts/make.go build --tags=ebpf
|
||||
|
||||
install: $(GO_SRC)
|
||||
@go run _scripts/make.go install
|
||||
|
||||
uninstall:
|
||||
@ -27,4 +45,4 @@ test-integration-run:
|
||||
vendor:
|
||||
@go run _scripts/make.go vendor
|
||||
|
||||
.PHONY: vendor test-integration-run test-proc-run test check-cert install build vet
|
||||
.PHONY: vendor test-integration-run test-proc-run test check-cert install build vet build-bpf uninstall
|
||||
|
@ -111,6 +111,8 @@ func processServerMethods(serverMethods []*types.Func) []binding {
|
||||
name = "set_expr"
|
||||
case "command":
|
||||
name = "raw_command"
|
||||
case "create_e_b_p_f_tracepoint":
|
||||
name = "create_ebpf_tracepoint"
|
||||
default:
|
||||
// remove list_ prefix, it looks better
|
||||
const listPrefix = "list_"
|
||||
|
@ -21,6 +21,7 @@ var Verbose bool
|
||||
var NOTimeout bool
|
||||
var TestIncludePIE bool
|
||||
var TestSet, TestRegex, TestBackend, TestBuildMode string
|
||||
var Tags *[]string
|
||||
|
||||
func NewMakeCommands() *cobra.Command {
|
||||
RootCommand := &cobra.Command{
|
||||
@ -34,17 +35,27 @@ func NewMakeCommands() *cobra.Command {
|
||||
Run: checkCertCmd,
|
||||
})
|
||||
|
||||
RootCommand.AddCommand(&cobra.Command{
|
||||
buildCmd := &cobra.Command{
|
||||
Use: "build",
|
||||
Short: "Build delve",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
tagFlag := prepareMacnative()
|
||||
execute("go", "build", tagFlag, buildFlags(), DelveMainPackagePath)
|
||||
if len(*Tags) > 0 {
|
||||
if len(tagFlag) == 0 {
|
||||
tagFlag = "-tags="
|
||||
} else {
|
||||
tagFlag += ","
|
||||
}
|
||||
tagFlag += strings.Join(*Tags, ",")
|
||||
}
|
||||
execute("go", "build", "-ldflags", "-extldflags -static", tagFlag, buildFlags(), DelveMainPackagePath)
|
||||
if runtime.GOOS == "darwin" && os.Getenv("CERT") != "" && canMacnative() {
|
||||
codesign("./dlv")
|
||||
}
|
||||
},
|
||||
})
|
||||
}
|
||||
Tags = buildCmd.PersistentFlags().StringArray("tags", []string{}, "Build tags")
|
||||
RootCommand.AddCommand(buildCmd)
|
||||
|
||||
RootCommand.AddCommand(&cobra.Command{
|
||||
Use: "install",
|
||||
|
@ -9,6 +9,7 @@ import (
|
||||
"os/exec"
|
||||
"os/signal"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
@ -76,6 +77,7 @@ var (
|
||||
traceExecFile string
|
||||
traceTestBinary bool
|
||||
traceStackDepth int
|
||||
traceUseEBPF bool
|
||||
|
||||
// redirect specifications for target process
|
||||
redirects []string
|
||||
@ -283,7 +285,8 @@ only see the output of the trace operations you can redirect stdout.`,
|
||||
traceCommand.Flags().IntVarP(&traceAttachPid, "pid", "p", 0, "Pid to attach to.")
|
||||
traceCommand.Flags().StringVarP(&traceExecFile, "exec", "e", "", "Binary file to exec and trace.")
|
||||
traceCommand.Flags().BoolVarP(&traceTestBinary, "test", "t", false, "Trace a test binary.")
|
||||
traceCommand.Flags().IntVarP(&traceStackDepth, "stack", "s", 0, "Show stack trace with given depth.")
|
||||
traceCommand.Flags().BoolVarP(&traceUseEBPF, "ebpf", "", false, "Trace using eBPF (experimental).")
|
||||
traceCommand.Flags().IntVarP(&traceStackDepth, "stack", "s", 0, "Show stack trace with given depth. (Ignored with -ebpf)")
|
||||
traceCommand.Flags().String("output", "debug", "Output path for the binary.")
|
||||
rootCommand.AddCommand(traceCommand)
|
||||
|
||||
@ -522,13 +525,14 @@ func traceCmd(cmd *cobra.Command, args []string) {
|
||||
dlvArgs = dlvArgs[:dlvArgsLen-1]
|
||||
}
|
||||
|
||||
var debugname string
|
||||
if traceAttachPid == 0 {
|
||||
if dlvArgsLen >= 2 && traceExecFile != "" {
|
||||
fmt.Fprintln(os.Stderr, "Cannot specify package when using exec.")
|
||||
return 1
|
||||
}
|
||||
|
||||
debugname := traceExecFile
|
||||
debugname = traceExecFile
|
||||
if traceExecFile == "" {
|
||||
debugname, err = filepath.Abs(cmd.Flag("output").Value.String())
|
||||
if err != nil {
|
||||
@ -583,39 +587,79 @@ func traceCmd(cmd *cobra.Command, args []string) {
|
||||
return 1
|
||||
}
|
||||
for i := range funcs {
|
||||
_, err = client.CreateBreakpoint(&api.Breakpoint{
|
||||
FunctionName: funcs[i],
|
||||
Tracepoint: true,
|
||||
Line: -1,
|
||||
Stacktrace: traceStackDepth,
|
||||
LoadArgs: &terminal.ShortLoadConfig,
|
||||
})
|
||||
if err != nil && !isBreakpointExistsErr(err) {
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
return 1
|
||||
}
|
||||
addrs, err := client.FunctionReturnLocations(funcs[i])
|
||||
if err != nil {
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
return 1
|
||||
}
|
||||
for i := range addrs {
|
||||
if traceUseEBPF {
|
||||
err := client.CreateEBPFTracepoint(funcs[i])
|
||||
if err != nil {
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
return 1
|
||||
}
|
||||
} else {
|
||||
// Fall back to breakpoint based tracing if we get an error.
|
||||
_, err = client.CreateBreakpoint(&api.Breakpoint{
|
||||
Addr: addrs[i],
|
||||
TraceReturn: true,
|
||||
Stacktrace: traceStackDepth,
|
||||
Line: -1,
|
||||
LoadArgs: &terminal.ShortLoadConfig,
|
||||
FunctionName: funcs[i],
|
||||
Tracepoint: true,
|
||||
Line: -1,
|
||||
Stacktrace: traceStackDepth,
|
||||
LoadArgs: &terminal.ShortLoadConfig,
|
||||
})
|
||||
if err != nil && !isBreakpointExistsErr(err) {
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
return 1
|
||||
}
|
||||
addrs, err := client.FunctionReturnLocations(funcs[i])
|
||||
if err != nil {
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
return 1
|
||||
}
|
||||
for i := range addrs {
|
||||
_, err = client.CreateBreakpoint(&api.Breakpoint{
|
||||
Addr: addrs[i],
|
||||
TraceReturn: true,
|
||||
Stacktrace: traceStackDepth,
|
||||
Line: -1,
|
||||
LoadArgs: &terminal.ShortLoadConfig,
|
||||
})
|
||||
if err != nil && !isBreakpointExistsErr(err) {
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
return 1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
cmds := terminal.DebugCommands(client)
|
||||
t := terminal.New(client, nil)
|
||||
defer t.Close()
|
||||
if traceUseEBPF {
|
||||
done := make(chan struct{})
|
||||
defer close(done)
|
||||
go func() {
|
||||
for {
|
||||
select {
|
||||
case <-done:
|
||||
return
|
||||
default:
|
||||
tracepoints, err := client.GetBufferedTracepoints()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
for _, t := range tracepoints {
|
||||
var params strings.Builder
|
||||
for _, p := range t.InputParams {
|
||||
if params.Len() > 0 {
|
||||
params.WriteString(", ")
|
||||
}
|
||||
if p.Kind == reflect.String {
|
||||
params.WriteString(fmt.Sprintf("%q", p.Value))
|
||||
} else {
|
||||
params.WriteString(p.Value)
|
||||
}
|
||||
}
|
||||
fmt.Printf("%s:%d %s(%s)\n", t.File, t.Line, t.FunctionName, params.String())
|
||||
}
|
||||
}
|
||||
}
|
||||
}()
|
||||
}
|
||||
cmds.Call("continue", t)
|
||||
return 0
|
||||
}()
|
||||
|
5
go.mod
5
go.mod
@ -1,8 +1,9 @@
|
||||
module github.com/go-delve/delve
|
||||
|
||||
go 1.11
|
||||
go 1.16
|
||||
|
||||
require (
|
||||
github.com/aquasecurity/libbpfgo v0.1.2-0.20210708203834-4928d36fafac
|
||||
github.com/cosiner/argv v0.1.0
|
||||
github.com/creack/pty v1.1.9
|
||||
github.com/google/go-dap v0.5.0
|
||||
@ -14,7 +15,7 @@ require (
|
||||
github.com/spf13/cobra v1.1.3
|
||||
go.starlark.net v0.0.0-20200821142938-949cc6f4b097
|
||||
golang.org/x/arch v0.0.0-20190927153633-4e8777c89be4
|
||||
golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae
|
||||
golang.org/x/sys v0.0.0-20210514084401-e8d321eab015
|
||||
golang.org/x/tools v0.0.0-20191127201027-ecd32218bd7f
|
||||
gopkg.in/yaml.v2 v2.4.0
|
||||
)
|
||||
|
12
go.sum
12
go.sum
@ -16,6 +16,8 @@ github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym
|
||||
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
|
||||
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||
github.com/aquasecurity/libbpfgo v0.1.2-0.20210708203834-4928d36fafac h1:oehMMAySC3p8eSwcwQ8lTXxeCkkPll+AwNesUNowbJ8=
|
||||
github.com/aquasecurity/libbpfgo v0.1.2-0.20210708203834-4928d36fafac/go.mod h1:/+clceXE103FaXvVTIY2HAkQjxNtkra4DRWvZYr2SKw=
|
||||
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
|
||||
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
|
||||
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
|
||||
@ -181,10 +183,13 @@ github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
|
||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
||||
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
|
||||
@ -257,8 +262,9 @@ golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae h1:Ih9Yo4hSPImZOpfGuA4bR/ORKTAbhZo2AbWNRCnevdo=
|
||||
golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210514084401-e8d321eab015 h1:hZR0X1kPW+nwyJ9xRxqZk1vx5RUObAPBdKVvXPDUH/E=
|
||||
golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
@ -317,6 +323,8 @@ gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
|
@ -787,6 +787,7 @@ func readType(d *dwarf.Data, name string, r *dwarf.Reader, off dwarf.Offset, typ
|
||||
case reflect.String:
|
||||
str := new(StringType)
|
||||
t = &str.StructType
|
||||
str.ReflectKind = reflect.String
|
||||
typ = str
|
||||
default:
|
||||
typ = t
|
||||
|
@ -145,7 +145,7 @@ func PrettyPrint(out io.Writer, instructions []byte) {
|
||||
|
||||
func callframecfa(opcode Opcode, ctxt *context) error {
|
||||
if ctxt.CFA == 0 {
|
||||
return fmt.Errorf("Could not retrieve CFA for current PC")
|
||||
return errors.New("could not retrieve CFA for current PC")
|
||||
}
|
||||
ctxt.stack = append(ctxt.stack, int64(ctxt.CFA))
|
||||
return nil
|
||||
|
@ -1,6 +1,7 @@
|
||||
package proc
|
||||
|
||||
import (
|
||||
"debug/dwarf"
|
||||
"errors"
|
||||
"fmt"
|
||||
"go/ast"
|
||||
@ -8,6 +9,11 @@ import (
|
||||
"go/parser"
|
||||
"go/token"
|
||||
"reflect"
|
||||
|
||||
"github.com/go-delve/delve/pkg/dwarf/op"
|
||||
"github.com/go-delve/delve/pkg/dwarf/reader"
|
||||
"github.com/go-delve/delve/pkg/goversion"
|
||||
"github.com/go-delve/delve/pkg/proc/internal/ebpf"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -384,6 +390,52 @@ func (t *Target) SetBreakpoint(addr uint64, kind BreakpointKind, cond ast.Expr)
|
||||
return t.setBreakpointInternal(addr, kind, 0, cond)
|
||||
}
|
||||
|
||||
func (t *Target) SetEBPFTracepoint(fnName string) error {
|
||||
if !t.proc.SupportsBPF() {
|
||||
return errors.New("eBPF is not supported")
|
||||
}
|
||||
var args []ebpf.UProbeArgMap
|
||||
fn, ok := t.BinInfo().LookupFunc[fnName]
|
||||
if !ok {
|
||||
return fmt.Errorf("could not find function %s", fnName)
|
||||
}
|
||||
dwarfTree, err := fn.cu.image.getDwarfTree(fn.offset)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
variablesFlags := reader.VariablesOnlyVisible
|
||||
if t.BinInfo().Producer() != "" && goversion.ProducerAfterOrEqual(t.BinInfo().Producer(), 1, 15) {
|
||||
variablesFlags |= reader.VariablesTrustDeclLine
|
||||
}
|
||||
_, l, _ := t.BinInfo().PCToLine(fn.Entry)
|
||||
|
||||
varEntries := reader.Variables(dwarfTree, fn.Entry, l, variablesFlags)
|
||||
for _, entry := range varEntries {
|
||||
isret, _ := entry.Val(dwarf.AttrVarParam).(bool)
|
||||
if isret {
|
||||
continue
|
||||
}
|
||||
_, dt, err := readVarEntry(entry.Tree, fn.cu.image)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
offset, pieces, _, err := t.BinInfo().Location(entry, dwarf.AttrLocation, fn.Entry, op.DwarfRegisters{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
paramPieces := make([]int, 0, len(pieces))
|
||||
for _, piece := range pieces {
|
||||
if piece.Kind == op.RegPiece {
|
||||
paramPieces = append(paramPieces, int(piece.Val))
|
||||
}
|
||||
}
|
||||
offset += int64(t.BinInfo().Arch.PtrSize())
|
||||
args = append(args, ebpf.UProbeArgMap{Offset: offset, Size: dt.Size(), Kind: dt.Common().ReflectKind, Pieces: paramPieces, InReg: len(pieces) > 0})
|
||||
}
|
||||
t.proc.SetUProbe(fnName, args)
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetWatchpoint sets a data breakpoint at addr and stores it in the
|
||||
// process wide break point table.
|
||||
func (t *Target) SetWatchpoint(scope *EvalScope, expr string, wtype WatchType, cond ast.Expr) (*Breakpoint, error) {
|
||||
|
@ -5,9 +5,10 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"github.com/go-delve/delve/pkg/elfwriter"
|
||||
"github.com/go-delve/delve/pkg/dwarf/op"
|
||||
"github.com/go-delve/delve/pkg/elfwriter"
|
||||
"github.com/go-delve/delve/pkg/proc"
|
||||
"github.com/go-delve/delve/pkg/proc/internal/ebpf"
|
||||
)
|
||||
|
||||
// ErrNoThreads core file did not contain any threads.
|
||||
@ -269,6 +270,14 @@ func (p *process) Checkpoints() ([]proc.Checkpoint, error) { return nil, nil }
|
||||
// ClearCheckpoint clears a checkpoint, but will only return an error for core files.
|
||||
func (p *process) ClearCheckpoint(int) error { return errors.New("checkpoint not found") }
|
||||
|
||||
func (p *process) SupportsBPF() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (dbp *process) SetUProbe(fnName string, args []ebpf.UProbeArgMap) error {
|
||||
panic("not implemented")
|
||||
}
|
||||
|
||||
// ReadMemory will return memory from the core file at the specified location and put the
|
||||
// read memory into `data`, returning the length read, and returning an error if
|
||||
// the length read is shorter than the length of the `data` buffer.
|
||||
@ -471,3 +480,7 @@ func (p *process) MemoryMap() ([]proc.MemoryMapEntry, error) {
|
||||
func (p *process) DumpProcessNotes(notes []elfwriter.Note, threadDone func()) (threadsDone bool, out []elfwriter.Note, err error) {
|
||||
return false, notes, nil
|
||||
}
|
||||
|
||||
func (dbp *process) GetBufferedTracepoints() []ebpf.RawUProbeParams {
|
||||
return nil
|
||||
}
|
||||
|
@ -81,6 +81,7 @@ import (
|
||||
"github.com/go-delve/delve/pkg/elfwriter"
|
||||
"github.com/go-delve/delve/pkg/logflags"
|
||||
"github.com/go-delve/delve/pkg/proc"
|
||||
"github.com/go-delve/delve/pkg/proc/internal/ebpf"
|
||||
"github.com/go-delve/delve/pkg/proc/linutil"
|
||||
"github.com/go-delve/delve/pkg/proc/macutil"
|
||||
isatty "github.com/mattn/go-isatty"
|
||||
@ -361,6 +362,18 @@ func (p *gdbProcess) Connect(conn net.Conn, path string, pid int, debugInfoDirs
|
||||
return tgt, nil
|
||||
}
|
||||
|
||||
func (p *gdbProcess) SupportsBPF() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (dbp *gdbProcess) GetBufferedTracepoints() []ebpf.RawUProbeParams {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (dbp *gdbProcess) SetUProbe(fnName string, args []ebpf.UProbeArgMap) error {
|
||||
panic("not implemented")
|
||||
}
|
||||
|
||||
// unusedPort returns an unused tcp port
|
||||
// This is a hack and subject to a race condition with other running
|
||||
// programs, but most (all?) OS will cycle through all ephemeral ports
|
||||
|
@ -1,6 +1,9 @@
|
||||
package proc
|
||||
|
||||
import "github.com/go-delve/delve/pkg/elfwriter"
|
||||
import (
|
||||
"github.com/go-delve/delve/pkg/elfwriter"
|
||||
"github.com/go-delve/delve/pkg/proc/internal/ebpf"
|
||||
)
|
||||
|
||||
// Process represents the target of the debugger. This
|
||||
// target could be a system process, core file, etc.
|
||||
@ -42,11 +45,16 @@ type ProcessInternal interface {
|
||||
WriteBreakpoint(*Breakpoint) error
|
||||
EraseBreakpoint(*Breakpoint) error
|
||||
|
||||
SupportsBPF() bool
|
||||
SetUProbe(string, []ebpf.UProbeArgMap) error
|
||||
|
||||
// DumpProcessNotes returns ELF core notes describing the process and its threads.
|
||||
// Implementing this method is optional.
|
||||
DumpProcessNotes(notes []elfwriter.Note, threadDone func()) (bool, []elfwriter.Note, error)
|
||||
// MemoryMap returns the memory map of the target process. This method must be implemented if CanDump is true.
|
||||
MemoryMap() ([]MemoryMapEntry, error)
|
||||
|
||||
GetBufferedTracepoints() []ebpf.RawUProbeParams
|
||||
}
|
||||
|
||||
// RecordingManipulation is an interface for manipulating process recordings.
|
||||
|
31
pkg/proc/internal/ebpf/context.go
Normal file
31
pkg/proc/internal/ebpf/context.go
Normal file
@ -0,0 +1,31 @@
|
||||
package ebpf
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
|
||||
"github.com/go-delve/delve/pkg/dwarf/godwarf"
|
||||
"github.com/go-delve/delve/pkg/dwarf/op"
|
||||
)
|
||||
|
||||
type UProbeArgMap struct {
|
||||
Offset int64 // Offset from the stackpointer.
|
||||
Size int64 // Size in bytes.
|
||||
Kind reflect.Kind // Kind of variable.
|
||||
Pieces []int // Pieces of the variables as stored in registers.
|
||||
InReg bool // True if this param is contained in a register.
|
||||
}
|
||||
|
||||
type RawUProbeParam struct {
|
||||
Pieces []op.Piece
|
||||
RealType godwarf.Type
|
||||
Kind reflect.Kind
|
||||
Len int64
|
||||
Base uint64
|
||||
Addr uint64
|
||||
Data []byte
|
||||
}
|
||||
|
||||
type RawUProbeParams struct {
|
||||
FnAddr int
|
||||
InputParams []*RawUProbeParam
|
||||
}
|
191
pkg/proc/internal/ebpf/helpers.go
Normal file
191
pkg/proc/internal/ebpf/helpers.go
Normal file
@ -0,0 +1,191 @@
|
||||
//go:build ebpf
|
||||
// +build ebpf
|
||||
|
||||
package ebpf
|
||||
|
||||
// #include "./trace_probe/function_vals.bpf.h"
|
||||
import "C"
|
||||
import (
|
||||
_ "embed"
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"reflect"
|
||||
"runtime"
|
||||
"sync"
|
||||
"unsafe"
|
||||
|
||||
"github.com/go-delve/delve/pkg/dwarf/godwarf"
|
||||
"github.com/go-delve/delve/pkg/dwarf/op"
|
||||
|
||||
bpf "github.com/aquasecurity/libbpfgo"
|
||||
"github.com/aquasecurity/libbpfgo/helpers"
|
||||
)
|
||||
|
||||
//go:embed trace_probe/trace.o
|
||||
var TraceProbeBytes []byte
|
||||
|
||||
const FakeAddressBase = 0xbeed000000000000
|
||||
|
||||
type EBPFContext struct {
|
||||
bpfModule *bpf.Module
|
||||
bpfProg *bpf.BPFProg
|
||||
bpfEvents chan []byte
|
||||
bpfRingBuf *bpf.RingBuffer
|
||||
bpfArgMap *bpf.BPFMap
|
||||
|
||||
parsedBpfEvents []RawUProbeParams
|
||||
m sync.Mutex
|
||||
}
|
||||
|
||||
func (ctx *EBPFContext) Close() {
|
||||
if ctx.bpfModule != nil {
|
||||
ctx.bpfModule.Close()
|
||||
}
|
||||
}
|
||||
|
||||
func (ctx *EBPFContext) AttachUprobe(pid int, name string, offset uint32) error {
|
||||
if ctx.bpfProg == nil {
|
||||
return errors.New("no eBPF program loaded")
|
||||
}
|
||||
_, err := ctx.bpfProg.AttachUprobe(pid, name, offset)
|
||||
return err
|
||||
}
|
||||
|
||||
func (ctx *EBPFContext) UpdateArgMap(key uint64, args []UProbeArgMap) error {
|
||||
if ctx.bpfArgMap == nil {
|
||||
return errors.New("eBPF map not loaded")
|
||||
}
|
||||
params := createFunctionParameterList(key, args)
|
||||
return ctx.bpfArgMap.Update(unsafe.Pointer(&key), unsafe.Pointer(¶ms))
|
||||
}
|
||||
|
||||
func (ctx *EBPFContext) GetBufferedTracepoints() []RawUProbeParams {
|
||||
ctx.m.Lock()
|
||||
defer ctx.m.Unlock()
|
||||
|
||||
if len(ctx.parsedBpfEvents) == 0 {
|
||||
return make([]RawUProbeParams, 0)
|
||||
}
|
||||
|
||||
events := make([]RawUProbeParams, len(ctx.parsedBpfEvents))
|
||||
copy(events, ctx.parsedBpfEvents)
|
||||
ctx.parsedBpfEvents = ctx.parsedBpfEvents[:0]
|
||||
return events
|
||||
}
|
||||
|
||||
func SymbolToOffset(file, symbol string) (uint32, error) {
|
||||
return helpers.SymbolToOffset(file, symbol)
|
||||
}
|
||||
|
||||
func LoadEBPFTracingProgram() (*EBPFContext, error) {
|
||||
var ctx EBPFContext
|
||||
var err error
|
||||
|
||||
ctx.bpfModule, err = bpf.NewModuleFromBuffer(TraceProbeBytes, "trace.o")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ctx.bpfModule.BPFLoadObject()
|
||||
prog, err := ctx.bpfModule.GetProgram("uprobe__dlv_trace")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ctx.bpfProg = prog
|
||||
|
||||
ctx.bpfEvents = make(chan []byte)
|
||||
ctx.bpfRingBuf, err = ctx.bpfModule.InitRingBuf("events", ctx.bpfEvents)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ctx.bpfRingBuf.Start()
|
||||
|
||||
ctx.bpfArgMap, err = ctx.bpfModule.GetMap("arg_map")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// TODO(derekparker): This should eventually be moved to a more generalized place.
|
||||
go func() {
|
||||
for {
|
||||
b, ok := <-ctx.bpfEvents
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
parsed := ParseFunctionParameterList(b)
|
||||
|
||||
ctx.m.Lock()
|
||||
ctx.parsedBpfEvents = append(ctx.parsedBpfEvents, parsed)
|
||||
ctx.m.Unlock()
|
||||
}
|
||||
}()
|
||||
|
||||
return &ctx, nil
|
||||
}
|
||||
|
||||
func ParseFunctionParameterList(rawParamBytes []byte) RawUProbeParams {
|
||||
params := (*C.function_parameter_list_t)(unsafe.Pointer(&rawParamBytes[0]))
|
||||
|
||||
defer runtime.KeepAlive(params) // Ensure the param is not garbage collected.
|
||||
|
||||
var rawParams RawUProbeParams
|
||||
rawParams.FnAddr = int(params.fn_addr)
|
||||
|
||||
for i := 0; i < int(params.n_parameters); i++ {
|
||||
iparam := &RawUProbeParam{}
|
||||
data := make([]byte, 0x60)
|
||||
ret := params.params[i]
|
||||
iparam.Kind = reflect.Kind(ret.kind)
|
||||
|
||||
val := C.GoBytes(unsafe.Pointer(&ret.val), C.int(ret.size))
|
||||
rawDerefValue := C.GoBytes(unsafe.Pointer(&ret.deref_val[0]), 0x30)
|
||||
copy(data, val)
|
||||
copy(data[0x30:], rawDerefValue)
|
||||
iparam.Data = data
|
||||
|
||||
pieces := make([]op.Piece, 0, 2)
|
||||
pieces = append(pieces, op.Piece{Size: 0x30, Kind: op.AddrPiece, Val: FakeAddressBase})
|
||||
pieces = append(pieces, op.Piece{Size: 0x30, Kind: op.AddrPiece, Val: FakeAddressBase + 0x30})
|
||||
iparam.Pieces = pieces
|
||||
|
||||
iparam.Addr = FakeAddressBase
|
||||
|
||||
switch iparam.Kind {
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||||
iparam.RealType = &godwarf.IntType{BasicType: godwarf.BasicType{CommonType: godwarf.CommonType{ByteSize: 8}}}
|
||||
case reflect.String:
|
||||
strLen := binary.LittleEndian.Uint64(val[8:])
|
||||
iparam.Base = FakeAddressBase + 0x30
|
||||
iparam.Len = int64(strLen)
|
||||
}
|
||||
|
||||
rawParams.InputParams = append(rawParams.InputParams, iparam)
|
||||
}
|
||||
|
||||
return rawParams
|
||||
}
|
||||
|
||||
func createFunctionParameterList(entry uint64, args []UProbeArgMap) C.function_parameter_list_t {
|
||||
var params C.function_parameter_list_t
|
||||
params.n_parameters = C.uint(len(args))
|
||||
params.fn_addr = C.uint(entry)
|
||||
for i, arg := range args {
|
||||
var param C.function_parameter_t
|
||||
param.size = C.uint(arg.Size)
|
||||
param.offset = C.uint(arg.Offset)
|
||||
param.kind = C.uint(arg.Kind)
|
||||
if arg.InReg {
|
||||
param.in_reg = true
|
||||
param.n_pieces = C.int(len(arg.Pieces))
|
||||
for i := range arg.Pieces {
|
||||
if i > 5 {
|
||||
break
|
||||
}
|
||||
param.reg_nums[i] = C.int(arg.Pieces[i])
|
||||
}
|
||||
}
|
||||
params.params[i] = param
|
||||
}
|
||||
return params
|
||||
}
|
39
pkg/proc/internal/ebpf/helpers_disabled.go
Normal file
39
pkg/proc/internal/ebpf/helpers_disabled.go
Normal file
@ -0,0 +1,39 @@
|
||||
//go:build !ebpf
|
||||
// +build !ebpf
|
||||
|
||||
package ebpf
|
||||
|
||||
import (
|
||||
"errors"
|
||||
)
|
||||
|
||||
type EBPFContext struct {
|
||||
}
|
||||
|
||||
func (ctx *EBPFContext) Close() {
|
||||
|
||||
}
|
||||
|
||||
func (ctx *EBPFContext) AttachUprobe(pid int, name string, offset uint32) error {
|
||||
return errors.New("eBPF is disabled")
|
||||
}
|
||||
|
||||
func (ctx *EBPFContext) UpdateArgMap(key uint64, args []UProbeArgMap) error {
|
||||
return errors.New("eBPF is disabled")
|
||||
}
|
||||
|
||||
func (ctx *EBPFContext) GetBufferedTracepoints() []RawUProbeParams {
|
||||
return nil
|
||||
}
|
||||
|
||||
func SymbolToOffset(file, symbol string) (uint32, error) {
|
||||
return 0, errors.New("eBPF disabled")
|
||||
}
|
||||
|
||||
func LoadEBPFTracingProgram() (*EBPFContext, error) {
|
||||
return nil, errors.New("eBPF disabled")
|
||||
}
|
||||
|
||||
func ParseFunctionParameterList(rawParamBytes []byte) RawUProbeParams {
|
||||
return RawUProbeParams{}
|
||||
}
|
34
pkg/proc/internal/ebpf/trace_probe/function_vals.bpf.h
Normal file
34
pkg/proc/internal/ebpf/trace_probe/function_vals.bpf.h
Normal file
@ -0,0 +1,34 @@
|
||||
#include <stdbool.h>
|
||||
|
||||
// function_parameter stores information about a single parameter to a function.
|
||||
typedef struct function_parameter {
|
||||
// Type of the parameter as defined by the reflect.Kind enum.
|
||||
unsigned int kind;
|
||||
// Size of the variable in bytes.
|
||||
unsigned int size;
|
||||
|
||||
// Offset from stack pointer. This should only be set from the Go side.
|
||||
unsigned int offset;
|
||||
|
||||
// If true, the parameter is passed in a register.
|
||||
bool in_reg;
|
||||
// The number of register pieces the parameter is passed in.
|
||||
int n_pieces;
|
||||
// If in_reg is true, this represents the registers that the parameter is passed in.
|
||||
// This is an array because the number of registers may vary and the parameter may be
|
||||
// passed in multiple registers.
|
||||
int reg_nums[6];
|
||||
|
||||
// The following are filled in by the eBPF program.
|
||||
unsigned int daddr; // Data address.
|
||||
char val[0x30]; // Value of the parameter.
|
||||
char deref_val[0x30]; // Dereference value of the parameter.
|
||||
} function_parameter_t;
|
||||
|
||||
// function_parameter_list holds info about the function parameters and
|
||||
// stores information on up to 8 parameters.
|
||||
typedef struct function_parameter_list {
|
||||
unsigned int fn_addr;
|
||||
unsigned int n_parameters; // number of parameters.
|
||||
function_parameter_t params[6]; // list of parameters.
|
||||
} function_parameter_list_t;
|
183
pkg/proc/internal/ebpf/trace_probe/trace.bpf.c
Normal file
183
pkg/proc/internal/ebpf/trace_probe/trace.bpf.c
Normal file
@ -0,0 +1,183 @@
|
||||
#include "trace.bpf.h"
|
||||
#include <string.h>
|
||||
|
||||
#define STRING_KIND 24
|
||||
|
||||
// parse_string_param will parse a string parameter. The parsed value of the string
|
||||
// will be put into param->deref_val. This function expects the string struct
|
||||
// which contains a pointer to the string and the length of the string to have
|
||||
// already been read from memory and passed in as param->val.
|
||||
__always_inline
|
||||
int parse_string_param(struct pt_regs *ctx, function_parameter_t *param) {
|
||||
u64 str_len;
|
||||
size_t str_addr;
|
||||
|
||||
memcpy(&str_addr, param->val, sizeof(str_addr));
|
||||
memcpy(&str_len, param->val + sizeof(str_addr), sizeof(str_len));
|
||||
param->daddr = str_addr;
|
||||
|
||||
if (str_addr != 0) {
|
||||
if (str_len > 0x30) {
|
||||
str_len = 0x30;
|
||||
}
|
||||
int ret = bpf_probe_read_user(¶m->deref_val, str_len, (void *)(str_addr));
|
||||
if (ret < 0) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
__always_inline
|
||||
int parse_param_stack(struct pt_regs *ctx, function_parameter_t *param) {
|
||||
long ret;
|
||||
size_t addr = ctx->sp + param->offset;
|
||||
ret = bpf_probe_read_user(¶m->val, param->size, (void *)(addr));
|
||||
if (ret < 0) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
__always_inline
|
||||
void get_value_from_register(struct pt_regs *ctx, void *dest, int reg_num) {
|
||||
switch (reg_num) {
|
||||
case 0: // RAX
|
||||
memcpy(dest, &ctx->ax, sizeof(ctx->ax));
|
||||
break;
|
||||
case 1: // RDX
|
||||
memcpy(dest, &ctx->dx, sizeof(ctx->dx));
|
||||
break;
|
||||
case 2: // RCX
|
||||
memcpy(dest, &ctx->cx, sizeof(ctx->cx));
|
||||
break;
|
||||
case 3: // RBX
|
||||
memcpy(dest, &ctx->bx, sizeof(ctx->bx));
|
||||
break;
|
||||
case 4: // RSI
|
||||
memcpy(dest, &ctx->si, sizeof(ctx->si));
|
||||
break;
|
||||
case 5: // RDI
|
||||
memcpy(dest, &ctx->di, sizeof(ctx->di));
|
||||
break;
|
||||
case 6: // RBP
|
||||
memcpy(dest, &ctx->bp, sizeof(ctx->bp));
|
||||
break;
|
||||
case 7: // RSP
|
||||
memcpy(dest, &ctx->sp, sizeof(ctx->sp));
|
||||
break;
|
||||
case 8: // R8
|
||||
memcpy(dest, &ctx->r8, sizeof(ctx->r8));
|
||||
break;
|
||||
case 9: // R9
|
||||
memcpy(dest, &ctx->r9, sizeof(ctx->r9));
|
||||
break;
|
||||
case 10: // R10
|
||||
memcpy(dest, &ctx->r10, sizeof(ctx->r10));
|
||||
break;
|
||||
case 11: // R11
|
||||
memcpy(dest, &ctx->r11, sizeof(ctx->r11));
|
||||
break;
|
||||
case 12: // R12
|
||||
memcpy(dest, &ctx->r12, sizeof(ctx->r12));
|
||||
break;
|
||||
case 13: // R13
|
||||
memcpy(dest, &ctx->r13, sizeof(ctx->r13));
|
||||
break;
|
||||
case 14: // R14
|
||||
memcpy(dest, &ctx->r14, sizeof(ctx->r14));
|
||||
break;
|
||||
case 15: // R15
|
||||
memcpy(dest, &ctx->r15, sizeof(ctx->r15));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
__always_inline
|
||||
int parse_param_registers(struct pt_regs *ctx, function_parameter_t *param) {
|
||||
switch (param->n_pieces) {
|
||||
case 6:
|
||||
get_value_from_register(ctx, param->val+40, param->reg_nums[5]);
|
||||
case 5:
|
||||
get_value_from_register(ctx, param->val+32, param->reg_nums[4]);
|
||||
case 4:
|
||||
get_value_from_register(ctx, param->val+24, param->reg_nums[3]);
|
||||
case 3:
|
||||
get_value_from_register(ctx, param->val+16, param->reg_nums[2]);
|
||||
case 2:
|
||||
get_value_from_register(ctx, param->val+8, param->reg_nums[1]);
|
||||
case 1:
|
||||
get_value_from_register(ctx, param->val, param->reg_nums[0]);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
__always_inline
|
||||
int parse_param(struct pt_regs *ctx, function_parameter_t *param) {
|
||||
if (param->size > 0x30) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Parse the initial value of the parameter.
|
||||
// If the parameter is a basic type, we will be finished here.
|
||||
// If the parameter is a more complex type such as a string or
|
||||
// a slice we will need some further processing below.
|
||||
int ret = 0;
|
||||
if (param->in_reg) {
|
||||
parse_param_registers(ctx, param);
|
||||
} else {
|
||||
parse_param_stack(ctx, param);
|
||||
}
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
switch (param->kind) {
|
||||
case STRING_KIND:
|
||||
return parse_string_param(ctx, param);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
SEC("uprobe/dlv_trace")
|
||||
int uprobe__dlv_trace(struct pt_regs *ctx) {
|
||||
function_parameter_list_t *args;
|
||||
function_parameter_list_t *parsed_args;
|
||||
function_parameter_t param;
|
||||
uint64_t key = ctx->ip;
|
||||
|
||||
args = bpf_map_lookup_elem(&arg_map, &key);
|
||||
if (!args) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
parsed_args = bpf_ringbuf_reserve(&events, sizeof(function_parameter_list_t), 0);
|
||||
if (!parsed_args) {
|
||||
return 1;
|
||||
}
|
||||
memcpy(parsed_args, args, sizeof(function_parameter_list_t));
|
||||
|
||||
// Since we cannot loop in eBPF programs let's take adavantage of the
|
||||
// fact that in C switch cases will pass through automatically.
|
||||
switch (args->n_parameters) {
|
||||
case 6:
|
||||
parse_param(ctx, &parsed_args->params[5]);
|
||||
case 5:
|
||||
parse_param(ctx, &parsed_args->params[4]);
|
||||
case 4:
|
||||
parse_param(ctx, &parsed_args->params[3]);
|
||||
case 3:
|
||||
parse_param(ctx, &parsed_args->params[2]);
|
||||
case 2:
|
||||
parse_param(ctx, &parsed_args->params[1]);
|
||||
case 1:
|
||||
parse_param(ctx, &parsed_args->params[0]);
|
||||
}
|
||||
|
||||
bpf_ringbuf_submit(parsed_args, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
char _license[] SEC("license") = "GPL";
|
19
pkg/proc/internal/ebpf/trace_probe/trace.bpf.h
Normal file
19
pkg/proc/internal/ebpf/trace_probe/trace.bpf.h
Normal file
@ -0,0 +1,19 @@
|
||||
#include "vmlinux.h"
|
||||
#include "function_vals.bpf.h"
|
||||
#include <bpf/bpf_helpers.h>
|
||||
#include <bpf/bpf_tracing.h>
|
||||
|
||||
#define BPF_MAX_VAR_SIZ (1 << 29)
|
||||
|
||||
// Ring buffer to handle communication of variable values back to userspace.
|
||||
struct {
|
||||
__uint(type, BPF_MAP_TYPE_RINGBUF);
|
||||
__uint(max_entries, BPF_MAX_VAR_SIZ);
|
||||
} events SEC(".maps");
|
||||
|
||||
struct {
|
||||
__uint(max_entries, 42);
|
||||
__uint(type, BPF_MAP_TYPE_HASH);
|
||||
__type(key, u64);
|
||||
__type(value, function_parameter_list_t);
|
||||
} arg_map SEC(".maps");
|
124044
pkg/proc/internal/ebpf/trace_probe/vmlinux.h
Normal file
124044
pkg/proc/internal/ebpf/trace_probe/vmlinux.h
Normal file
File diff suppressed because it is too large
Load Diff
@ -58,6 +58,10 @@ func (m *memCache) WriteMemory(addr uint64, data []byte) (written int, err error
|
||||
return m.mem.WriteMemory(addr, data)
|
||||
}
|
||||
|
||||
func CreateLoadedCachedMemory(data []byte) MemoryReadWriter {
|
||||
return &memCache{loaded: true, cacheAddr: fakeAddressUnresolv, cache: data, mem: nil}
|
||||
}
|
||||
|
||||
func cacheMemory(mem MemoryReadWriter, addr uint64, size int) MemoryReadWriter {
|
||||
if !cacheEnabled {
|
||||
return mem
|
||||
@ -92,6 +96,18 @@ type compositeMemory struct {
|
||||
data []byte
|
||||
}
|
||||
|
||||
// CreateCompositeMemory created a new composite memory type using the provided MemoryReadWriter as the
|
||||
// underlying memory buffer.
|
||||
func CreateCompositeMemory(mem MemoryReadWriter, arch *Arch, regs op.DwarfRegisters, pieces []op.Piece) (*compositeMemory, error) {
|
||||
// This is basically a small wrapper to avoid having to change all callers
|
||||
// of newCompositeMemory since it existed first.
|
||||
cm, err := newCompositeMemory(mem, arch, regs, pieces)
|
||||
if cm != nil {
|
||||
cm.base = fakeAddressUnresolv
|
||||
}
|
||||
return cm, err
|
||||
}
|
||||
|
||||
func newCompositeMemory(mem MemoryReadWriter, arch *Arch, regs op.DwarfRegisters, pieces []op.Piece) (*compositeMemory, error) {
|
||||
cmem := &compositeMemory{realmem: mem, arch: arch, regs: regs, pieces: pieces, data: []byte{}}
|
||||
for i := range pieces {
|
||||
|
@ -1,4 +1,5 @@
|
||||
//+build darwin,!macnative
|
||||
//go:build darwin && !macnative
|
||||
// +build darwin,!macnative
|
||||
|
||||
package native
|
||||
|
||||
@ -8,6 +9,7 @@ import (
|
||||
|
||||
"github.com/go-delve/delve/pkg/dwarf/op"
|
||||
"github.com/go-delve/delve/pkg/proc"
|
||||
"github.com/go-delve/delve/pkg/proc/internal/ebpf"
|
||||
)
|
||||
|
||||
var ErrNativeBackendDisabled = errors.New("native backend disabled during compilation")
|
||||
@ -32,6 +34,8 @@ type osSpecificDetails struct{}
|
||||
// osProcessDetails holds Darwin specific information.
|
||||
type osProcessDetails struct{}
|
||||
|
||||
func (os *osProcessDetails) Close() {}
|
||||
|
||||
func findExecutable(path string, pid int) string {
|
||||
panic(ErrNativeBackendDisabled)
|
||||
}
|
||||
@ -82,6 +86,18 @@ func (dbp *nativeProcess) EntryPoint() (uint64, error) {
|
||||
panic(ErrNativeBackendDisabled)
|
||||
}
|
||||
|
||||
func (dbp *nativeProcess) SupportsBPF() bool {
|
||||
panic(ErrNativeBackendDisabled)
|
||||
}
|
||||
|
||||
func (dbp *nativeProcess) SetUProbe(fnName string, args []ebpf.UProbeArgMap) error {
|
||||
panic(ErrNativeBackendDisabled)
|
||||
}
|
||||
|
||||
func (dbp *nativeProcess) GetBufferedTracepoints() []ebpf.RawUProbeParams {
|
||||
panic(ErrNativeBackendDisabled)
|
||||
}
|
||||
|
||||
// SetPC sets the value of the PC register.
|
||||
func (t *nativeThread) setPC(pc uint64) error {
|
||||
panic(ErrNativeBackendDisabled)
|
||||
|
@ -343,6 +343,7 @@ func (dbp *nativeProcess) postExit() {
|
||||
if dbp.ctty != nil {
|
||||
dbp.ctty.Close()
|
||||
}
|
||||
dbp.os.Close()
|
||||
}
|
||||
|
||||
func (dbp *nativeProcess) writeSoftwareBreakpoint(thread *nativeThread, addr uint64) error {
|
||||
|
@ -1,4 +1,5 @@
|
||||
//+build darwin,macnative
|
||||
//go:build darwin && macnative
|
||||
// +build darwin,macnative
|
||||
|
||||
package native
|
||||
|
||||
@ -18,6 +19,7 @@ import (
|
||||
sys "golang.org/x/sys/unix"
|
||||
|
||||
"github.com/go-delve/delve/pkg/proc"
|
||||
"github.com/go-delve/delve/pkg/proc/internal/ebpf"
|
||||
"github.com/go-delve/delve/pkg/proc/macutil"
|
||||
)
|
||||
|
||||
@ -34,6 +36,8 @@ type osProcessDetails struct {
|
||||
portSet C.mach_port_t
|
||||
}
|
||||
|
||||
func (os *osProcessDetails) Close() {}
|
||||
|
||||
// Launch creates and begins debugging a new process. Uses a
|
||||
// custom fork/exec process in order to take advantage of
|
||||
// PT_SIGEXC on Darwin which will turn Unix signals into
|
||||
@ -469,4 +473,16 @@ func (dbp *nativeProcess) EntryPoint() (uint64, error) {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
func (dbp *nativeProcess) SupportsBPF() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (dbp *nativeProcess) SetUProbe(fnName string, args []ebpf.UProbeArgMap) error {
|
||||
panic("not implemented")
|
||||
}
|
||||
|
||||
func (dbp *nativeProcess) GetBufferedTracepoints() []ebpf.RawUProbeParams {
|
||||
panic("not implemented")
|
||||
}
|
||||
|
||||
func initialize(dbp *nativeProcess) error { return nil }
|
||||
|
8
pkg/proc/native/proc_ebpf_linux.go
Normal file
8
pkg/proc/native/proc_ebpf_linux.go
Normal file
@ -0,0 +1,8 @@
|
||||
//go:build ebpf
|
||||
// +build ebpf
|
||||
|
||||
package native
|
||||
|
||||
func (dbp *nativeProcess) SupportsBPF() bool {
|
||||
return true
|
||||
}
|
@ -15,6 +15,7 @@ import (
|
||||
sys "golang.org/x/sys/unix"
|
||||
|
||||
"github.com/go-delve/delve/pkg/proc"
|
||||
"github.com/go-delve/delve/pkg/proc/internal/ebpf"
|
||||
|
||||
isatty "github.com/mattn/go-isatty"
|
||||
)
|
||||
@ -37,6 +38,8 @@ type osProcessDetails struct {
|
||||
tid int
|
||||
}
|
||||
|
||||
func (os *osProcessDetails) Close() {}
|
||||
|
||||
// Launch creates and begins debugging a new process. First entry in
|
||||
// `cmd` is the program to run, and then rest are the arguments
|
||||
// to be supplied to that process. `wd` is working directory of the program.
|
||||
@ -374,6 +377,18 @@ func (dbp *nativeProcess) EntryPoint() (uint64, error) {
|
||||
return uint64(ep), err
|
||||
}
|
||||
|
||||
func (dbp *nativeProcess) SupportsBPF() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (dbp *nativeProcess) SetUProbe(fnName string, args []ebpf.UProbeArgMap) error {
|
||||
panic("not implemented")
|
||||
}
|
||||
|
||||
func (dbp *nativeProcess) GetBufferedTracepoints() []ebpf.RawUProbeParams {
|
||||
panic("not implemented")
|
||||
}
|
||||
|
||||
// Usedy by Detach
|
||||
func killProcess(pid int) error {
|
||||
return sys.Kill(pid, sys.SIGINT)
|
||||
|
@ -19,6 +19,7 @@ import (
|
||||
sys "golang.org/x/sys/unix"
|
||||
|
||||
"github.com/go-delve/delve/pkg/proc"
|
||||
"github.com/go-delve/delve/pkg/proc/internal/ebpf"
|
||||
"github.com/go-delve/delve/pkg/proc/linutil"
|
||||
|
||||
isatty "github.com/mattn/go-isatty"
|
||||
@ -45,6 +46,14 @@ const (
|
||||
// process details.
|
||||
type osProcessDetails struct {
|
||||
comm string
|
||||
|
||||
ebpf *ebpf.EBPFContext
|
||||
}
|
||||
|
||||
func (os *osProcessDetails) Close() {
|
||||
if os.ebpf != nil {
|
||||
os.ebpf.Close()
|
||||
}
|
||||
}
|
||||
|
||||
// Launch creates and begins debugging a new process. First entry in
|
||||
@ -183,9 +192,17 @@ func initialize(dbp *nativeProcess) error {
|
||||
comm = match[1]
|
||||
}
|
||||
dbp.os.comm = strings.ReplaceAll(string(comm), "%", "%%")
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (dbp *nativeProcess) GetBufferedTracepoints() []ebpf.RawUProbeParams {
|
||||
if dbp.os.ebpf == nil {
|
||||
return nil
|
||||
}
|
||||
return dbp.os.ebpf.GetBufferedTracepoints()
|
||||
}
|
||||
|
||||
// kill kills the target process.
|
||||
func (dbp *nativeProcess) kill() error {
|
||||
if dbp.exited {
|
||||
@ -213,7 +230,6 @@ func (dbp *nativeProcess) kill() error {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (dbp *nativeProcess) requestManualStop() (err error) {
|
||||
@ -689,6 +705,36 @@ func (dbp *nativeProcess) EntryPoint() (uint64, error) {
|
||||
return linutil.EntryPointFromAuxv(auxvbuf, dbp.bi.Arch.PtrSize()), nil
|
||||
}
|
||||
|
||||
func (dbp *nativeProcess) SetUProbe(fnName string, args []ebpf.UProbeArgMap) error {
|
||||
// Lazily load and initialize the BPF program upon request to set a uprobe.
|
||||
if dbp.os.ebpf == nil {
|
||||
dbp.os.ebpf, _ = ebpf.LoadEBPFTracingProgram()
|
||||
}
|
||||
|
||||
// We only allow up to 6 args for a BPF probe.
|
||||
// Return early if we have more.
|
||||
if len(args) > 6 {
|
||||
return errors.New("too many arguments in traced function, max is 6")
|
||||
}
|
||||
|
||||
debugname := dbp.bi.Images[0].Path
|
||||
offset, err := ebpf.SymbolToOffset(debugname, fnName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = dbp.os.ebpf.AttachUprobe(dbp.Pid(), debugname, offset)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fn, ok := dbp.bi.LookupFunc[fnName]
|
||||
if !ok {
|
||||
return fmt.Errorf("could not find function: %s", fnName)
|
||||
}
|
||||
|
||||
key := fn.Entry
|
||||
return dbp.os.ebpf.UpdateArgMap(key, args)
|
||||
}
|
||||
|
||||
func killProcess(pid int) error {
|
||||
return sys.Kill(pid, sys.SIGINT)
|
||||
}
|
||||
|
8
pkg/proc/native/proc_no_ebpf_linux.go
Normal file
8
pkg/proc/native/proc_no_ebpf_linux.go
Normal file
@ -0,0 +1,8 @@
|
||||
//go:build !ebpf
|
||||
// +build !ebpf
|
||||
|
||||
package native
|
||||
|
||||
func (dbp *nativeProcess) SupportsBPF() bool {
|
||||
return false
|
||||
}
|
@ -20,6 +20,8 @@ type osProcessDetails struct {
|
||||
running bool
|
||||
}
|
||||
|
||||
func (os *osProcessDetails) Close() {}
|
||||
|
||||
// Launch creates and begins debugging a new process.
|
||||
func Launch(cmd []string, wd string, flags proc.LaunchFlags, _ []string, _ string, redirects [3]string) (*proc.Target, error) {
|
||||
argv0Go, err := filepath.Abs(cmd[0])
|
||||
@ -485,6 +487,13 @@ func (dbp *nativeProcess) EntryPoint() (uint64, error) {
|
||||
return dbp.os.entryPoint, nil
|
||||
}
|
||||
|
||||
func (dbp *nativeProcess) SupportsBPF() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (dbp *nativeProcess) SetUProbe(fnName string, args []proc.UProbeArgMap) {
|
||||
}
|
||||
|
||||
func killProcess(pid int) error {
|
||||
p, err := os.FindProcess(pid)
|
||||
if err != nil {
|
||||
|
@ -391,13 +391,46 @@ func (t *Target) CurrentThread() Thread {
|
||||
return t.currentThread
|
||||
}
|
||||
|
||||
type UProbeTraceResult struct {
|
||||
FnAddr int
|
||||
InputParams []*Variable
|
||||
}
|
||||
|
||||
func (t *Target) GetBufferedTracepoints() []*UProbeTraceResult {
|
||||
var results []*UProbeTraceResult
|
||||
tracepoints := t.proc.GetBufferedTracepoints()
|
||||
for _, tp := range tracepoints {
|
||||
r := &UProbeTraceResult{}
|
||||
r.FnAddr = tp.FnAddr
|
||||
for _, ip := range tp.InputParams {
|
||||
v := &Variable{}
|
||||
v.RealType = ip.RealType
|
||||
v.Len = ip.Len
|
||||
v.Base = ip.Base
|
||||
v.Addr = ip.Addr
|
||||
v.Kind = ip.Kind
|
||||
|
||||
cachedMem := CreateLoadedCachedMemory(ip.Data)
|
||||
compMem, _ := CreateCompositeMemory(cachedMem, t.BinInfo().Arch, op.DwarfRegisters{}, ip.Pieces)
|
||||
v.mem = compMem
|
||||
|
||||
// Load the value here so that we don't have to export
|
||||
// loadValue outside of proc.
|
||||
v.loadValue(loadFullValue)
|
||||
r.InputParams = append(r.InputParams, v)
|
||||
}
|
||||
results = append(results, r)
|
||||
}
|
||||
return results
|
||||
}
|
||||
|
||||
// SetNextBreakpointID sets the breakpoint ID of the next breakpoint
|
||||
func (t *Target) SetNextBreakpointID(id int) {
|
||||
t.Breakpoints().breakpointIDCounter = id
|
||||
}
|
||||
|
||||
const (
|
||||
fakeAddressBase = 0xbeef000000000000
|
||||
FakeAddressBase = 0xbeef000000000000
|
||||
fakeAddressUnresolv = 0xbeed000000000000 // this address never resloves to memory
|
||||
)
|
||||
|
||||
@ -435,7 +468,7 @@ func (t *Target) newCompositeMemory(mem MemoryReadWriter, regs op.DwarfRegisters
|
||||
|
||||
func (t *Target) registerFakeMemory(mem *compositeMemory) (addr uint64) {
|
||||
t.fakeMemoryRegistry = append(t.fakeMemoryRegistry, mem)
|
||||
addr = fakeAddressBase
|
||||
addr = FakeAddressBase
|
||||
if len(t.fakeMemoryRegistry) > 1 {
|
||||
prevMem := t.fakeMemoryRegistry[len(t.fakeMemoryRegistry)-2]
|
||||
addr = uint64(alignAddr(int64(prevMem.base+uint64(len(prevMem.data))), 0x100)) // the call to alignAddr just makes the address look nicer, it is not necessary
|
||||
|
@ -313,6 +313,36 @@ func (env *Env) starlarkPredeclare() starlark.StringDict {
|
||||
}
|
||||
return env.interfaceToStarlarkValue(rpcRet), nil
|
||||
})
|
||||
r["create_ebpf_tracepoint"] = starlark.NewBuiltin("create_ebpf_tracepoint", func(thread *starlark.Thread, _ *starlark.Builtin, args starlark.Tuple, kwargs []starlark.Tuple) (starlark.Value, error) {
|
||||
if err := isCancelled(thread); err != nil {
|
||||
return starlark.None, decorateError(thread, err)
|
||||
}
|
||||
var rpcArgs rpc2.CreateEBPFTracepointIn
|
||||
var rpcRet rpc2.CreateEBPFTracepointOut
|
||||
if len(args) > 0 && args[0] != starlark.None {
|
||||
err := unmarshalStarlarkValue(args[0], &rpcArgs.FunctionName, "FunctionName")
|
||||
if err != nil {
|
||||
return starlark.None, decorateError(thread, err)
|
||||
}
|
||||
}
|
||||
for _, kv := range kwargs {
|
||||
var err error
|
||||
switch kv[0].(starlark.String) {
|
||||
case "FunctionName":
|
||||
err = unmarshalStarlarkValue(kv[1], &rpcArgs.FunctionName, "FunctionName")
|
||||
default:
|
||||
err = fmt.Errorf("unknown argument %q", kv[0])
|
||||
}
|
||||
if err != nil {
|
||||
return starlark.None, decorateError(thread, err)
|
||||
}
|
||||
}
|
||||
err := env.ctx.Client().CallAPI("CreateEBPFTracepoint", &rpcArgs, &rpcRet)
|
||||
if err != nil {
|
||||
return starlark.None, err
|
||||
}
|
||||
return env.interfaceToStarlarkValue(rpcRet), nil
|
||||
})
|
||||
r["create_watchpoint"] = starlark.NewBuiltin("create_watchpoint", func(thread *starlark.Thread, _ *starlark.Builtin, args starlark.Tuple, kwargs []starlark.Tuple) (starlark.Value, error) {
|
||||
if err := isCancelled(thread); err != nil {
|
||||
return starlark.None, decorateError(thread, err)
|
||||
@ -732,6 +762,18 @@ func (env *Env) starlarkPredeclare() starlark.StringDict {
|
||||
}
|
||||
return env.interfaceToStarlarkValue(rpcRet), nil
|
||||
})
|
||||
r["get_buffered_tracepoints"] = starlark.NewBuiltin("get_buffered_tracepoints", func(thread *starlark.Thread, _ *starlark.Builtin, args starlark.Tuple, kwargs []starlark.Tuple) (starlark.Value, error) {
|
||||
if err := isCancelled(thread); err != nil {
|
||||
return starlark.None, decorateError(thread, err)
|
||||
}
|
||||
var rpcArgs rpc2.GetBufferedTracepointsIn
|
||||
var rpcRet rpc2.GetBufferedTracepointsOut
|
||||
err := env.ctx.Client().CallAPI("GetBufferedTracepoints", &rpcArgs, &rpcRet)
|
||||
if err != nil {
|
||||
return starlark.None, err
|
||||
}
|
||||
return env.interfaceToStarlarkValue(rpcRet), nil
|
||||
})
|
||||
r["get_thread"] = starlark.NewBuiltin("get_thread", func(thread *starlark.Thread, _ *starlark.Builtin, args starlark.Tuple, kwargs []starlark.Tuple) (starlark.Value, error) {
|
||||
if err := isCancelled(thread); err != nil {
|
||||
return starlark.None, decorateError(thread, err)
|
||||
|
@ -48,6 +48,21 @@ type DebuggerState struct {
|
||||
Err error `json:"-"`
|
||||
}
|
||||
|
||||
type TracepointResult struct {
|
||||
// Addr is deprecated, use Addrs.
|
||||
Addr uint64 `json:"addr"`
|
||||
// File is the source file for the breakpoint.
|
||||
File string `json:"file"`
|
||||
// Line is a line in File for the breakpoint.
|
||||
Line int `json:"line"`
|
||||
// FunctionName is the name of the function at the current breakpoint, and
|
||||
// may not always be available.
|
||||
FunctionName string `json:"functionName,omitempty"`
|
||||
|
||||
InputParams []Variable `json:"inputParams,omitempty"`
|
||||
ReturnParams []Variable `json:"returnParams,omitempty"`
|
||||
}
|
||||
|
||||
// Breakpoint addresses a set of locations at which process execution may be
|
||||
// suspended.
|
||||
type Breakpoint struct {
|
||||
|
@ -757,6 +757,13 @@ func isBreakpointExistsErr(err error) bool {
|
||||
return r
|
||||
}
|
||||
|
||||
func (d *Debugger) CreateEBPFTracepoint(fnName string) error {
|
||||
d.targetMutex.Lock()
|
||||
defer d.targetMutex.Unlock()
|
||||
|
||||
return d.target.SetEBPFTracepoint(fnName)
|
||||
}
|
||||
|
||||
// AmendBreakpoint will update the breakpoint with the matching ID.
|
||||
// It also enables or disables the breakpoint.
|
||||
func (d *Debugger) AmendBreakpoint(amend *api.Breakpoint) error {
|
||||
@ -2116,6 +2123,29 @@ func (d *Debugger) Target() *proc.Target {
|
||||
return d.target
|
||||
}
|
||||
|
||||
func (d *Debugger) GetBufferedTracepoints() []api.TracepointResult {
|
||||
d.targetMutex.Lock()
|
||||
defer d.targetMutex.Unlock()
|
||||
|
||||
traces := d.target.GetBufferedTracepoints()
|
||||
if traces == nil {
|
||||
return nil
|
||||
}
|
||||
results := make([]api.TracepointResult, len(traces))
|
||||
for i, trace := range traces {
|
||||
f, l, fn := d.target.BinInfo().PCToLine(uint64(trace.FnAddr))
|
||||
|
||||
results[i].FunctionName = fn.Name
|
||||
results[i].Line = l
|
||||
results[i].File = f
|
||||
|
||||
for _, p := range trace.InputParams {
|
||||
results[i].InputParams = append(results[i].InputParams, *api.ConvertVar(p))
|
||||
}
|
||||
}
|
||||
return results
|
||||
}
|
||||
|
||||
func go11DecodeErrorCheck(err error) error {
|
||||
if _, isdecodeerr := err.(dwarf.DecodeError); !isdecodeerr {
|
||||
return err
|
||||
|
@ -214,6 +214,12 @@ func (c *RPCClient) Halt() (*api.DebuggerState, error) {
|
||||
return &out.State, err
|
||||
}
|
||||
|
||||
func (c *RPCClient) GetBufferedTracepoints() ([]api.TracepointResult, error) {
|
||||
var out GetBufferedTracepointsOut
|
||||
err := c.call("GetBufferedTracepoints", GetBufferedTracepointsIn{}, &out)
|
||||
return out.TracepointResults, err
|
||||
}
|
||||
|
||||
func (c *RPCClient) GetBreakpoint(id int) (*api.Breakpoint, error) {
|
||||
var out GetBreakpointOut
|
||||
err := c.call("GetBreakpoint", GetBreakpointIn{id, ""}, &out)
|
||||
@ -236,6 +242,11 @@ func (c *RPCClient) CreateBreakpoint(breakPoint *api.Breakpoint) (*api.Breakpoin
|
||||
return &out.Breakpoint, err
|
||||
}
|
||||
|
||||
func (c *RPCClient) CreateEBPFTracepoint(fnName string) error {
|
||||
var out CreateEBPFTracepointOut
|
||||
return c.call("CreateEBPFTracepoint", CreateEBPFTracepointIn{FunctionName: fnName}, &out)
|
||||
}
|
||||
|
||||
func (c *RPCClient) CreateWatchpoint(scope api.EvalScope, expr string, wtype api.WatchType) (*api.Breakpoint, error) {
|
||||
var out CreateWatchpointOut
|
||||
err := c.call("CreateWatchpoint", CreateWatchpointIn{scope, expr, wtype}, &out)
|
||||
|
@ -136,6 +136,18 @@ func (s *RPCServer) Command(command api.DebuggerCommand, cb service.RPCCallback)
|
||||
cb.Return(out, nil)
|
||||
}
|
||||
|
||||
type GetBufferedTracepointsIn struct {
|
||||
}
|
||||
|
||||
type GetBufferedTracepointsOut struct {
|
||||
TracepointResults []api.TracepointResult
|
||||
}
|
||||
|
||||
func (s *RPCServer) GetBufferedTracepoints(arg GetBufferedTracepointsIn, out *GetBufferedTracepointsOut) error {
|
||||
out.TracepointResults = s.debugger.GetBufferedTracepoints()
|
||||
return nil
|
||||
}
|
||||
|
||||
type GetBreakpointIn struct {
|
||||
Id int
|
||||
Name string
|
||||
@ -251,6 +263,18 @@ func (s *RPCServer) CreateBreakpoint(arg CreateBreakpointIn, out *CreateBreakpoi
|
||||
return nil
|
||||
}
|
||||
|
||||
type CreateEBPFTracepointIn struct {
|
||||
FunctionName string
|
||||
}
|
||||
|
||||
type CreateEBPFTracepointOut struct {
|
||||
Breakpoint api.Breakpoint
|
||||
}
|
||||
|
||||
func (s *RPCServer) CreateEBPFTracepoint(arg CreateEBPFTracepointIn, out *CreateEBPFTracepointOut) error {
|
||||
return s.debugger.CreateEBPFTracepoint(arg.FunctionName)
|
||||
}
|
||||
|
||||
type ClearBreakpointIn struct {
|
||||
Id int
|
||||
Name string
|
||||
|
1
vendor/github.com/aquasecurity/libbpfgo/.gitignore
generated
vendored
Normal file
1
vendor/github.com/aquasecurity/libbpfgo/.gitignore
generated
vendored
Normal file
@ -0,0 +1 @@
|
||||
selftest/dist
|
4
vendor/github.com/aquasecurity/libbpfgo/.gitmodules
generated
vendored
Normal file
4
vendor/github.com/aquasecurity/libbpfgo/.gitmodules
generated
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
|
||||
[submodule "selftest/libbpf-module"]
|
||||
path = selftest/libbpf-module
|
||||
url = https://github.com/libbpf/libbpf
|
202
vendor/github.com/aquasecurity/libbpfgo/LICENSE
generated
vendored
Normal file
202
vendor/github.com/aquasecurity/libbpfgo/LICENSE
generated
vendored
Normal file
@ -0,0 +1,202 @@
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
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.
|
29
vendor/github.com/aquasecurity/libbpfgo/Makefile
generated
vendored
Normal file
29
vendor/github.com/aquasecurity/libbpfgo/Makefile
generated
vendored
Normal file
@ -0,0 +1,29 @@
|
||||
TARGET_BPF := test/test.bpf.o
|
||||
VMLINUX_H = test/vmlinux.h
|
||||
|
||||
GO_SRC := $(shell find . -type f -name '*.go')
|
||||
BPF_SRC := $(shell find . -type f -name '*.bpf.c')
|
||||
PWD := $(shell pwd)
|
||||
|
||||
LIBBPF_HEADERS := /usr/include/bpf
|
||||
LIBBPF := "-lbpf"
|
||||
|
||||
.PHONY: all
|
||||
all: test
|
||||
|
||||
$(VMLINUX_H):
|
||||
bpftool btf dump file /sys/kernel/btf/vmlinux format c > test/vmlinux.h
|
||||
|
||||
go_env := CC=gcc CGO_CFLAGS="-I $(LIBBPF_HEADERS)" CGO_LDFLAGS="$(LIBBPF)"
|
||||
.PHONY: test
|
||||
test: $(TARGET_BPF) $(GO_SRC)
|
||||
$(go_env) go test -ldflags '-extldflags "-static"' .
|
||||
|
||||
$(TARGET_BPF): $(BPF_SRC) $(VMLINUX_H)
|
||||
clang \
|
||||
-g -O2 -c -target bpf \
|
||||
-o $@ $<
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
rm $(TARGET_BPF) $(VMLINUX_H)
|
61
vendor/github.com/aquasecurity/libbpfgo/Readme.md
generated
vendored
Normal file
61
vendor/github.com/aquasecurity/libbpfgo/Readme.md
generated
vendored
Normal file
@ -0,0 +1,61 @@
|
||||
# libbpfgo
|
||||
|
||||
<img src="docs/images/aqua-tux.png" width="150" height="auto">
|
||||
|
||||
___
|
||||
|
||||
libbpfgo is a Go library for working with Linux's [eBPF](https://ebpf.io/). It was created for [Tracee](https://github.com/aquasecurity/tracee), our open source Runtime Security and eBPF tracing tools written in Go. If you are interested in eBPF and it's applications, check out Tracee on Github: [https://github.com/aquasecurity/tracee](https://github.com/aquasecurity/tracee).
|
||||
|
||||
libbpfgo is built around libbpf - the standard library for interacting with eBPF from userspace, which is a C library maintained in Linux upstream. We have created libbpfgo as a thin Go wrapper around libbpf.
|
||||
|
||||
## Installing
|
||||
|
||||
libbpfgo is using CGO to interop with libbpf and will expect to be linked with libbpf at run or link time. Simply importing libbpfgo is not enough to get started, and you will need to fulfill the required dependency in one of the following ways:
|
||||
|
||||
1. Install the libbpf as a shared object in the system. Libbpf may already be packaged for you distribution, if not, you can build and install from source. More info [here](https://github.com/libbpf/libbpf).
|
||||
1. Embed libbpf into your Go project as a vendored dependency. This means that the libbpf code is statically linked into the resulting binary, and there are no runtime dependencies. [Tracee](https://github.com/aquasecurity/tracee) takes this approach and you can take example from it's [Makefile](https://github.com/aquasecurity/tracee/blob/f8df7da6a27f729610992b6bd52e89d510fcf384/tracee-ebpf/Makefile#L62).
|
||||
|
||||
## Concepts
|
||||
|
||||
libbpfgo tries to make it natural for Go developers to use, by abstracting away C technicalities. For example, it will translate low level return codes into Go `error`, it will organize functionality around Go `struct`, and it will use `channel` as to let you consume events.
|
||||
|
||||
In a high level, this is a typical workflow for working with the library:
|
||||
|
||||
1. Compile your bpf program into an object file.
|
||||
1. Initialize a `Module` struct - that is a unit of BPF functionality around your compiled object file.
|
||||
1. Load bpf programs from the object file using the `BPFProg` struct.
|
||||
1. Attach `BPFProg` to system facilities, for example to "raw tracepoints" or "kprobes" using the `BPFProg`'s associated functions.
|
||||
1. Instantiate and manipulate BPF Maps via the `BPFMap` struct and it's associated methods.
|
||||
1. Instantiate and manipulate Perf Buffer for communicating events from your BPF program to the driving userspace program, using the `RingBuffer` struct and it's associated objects.
|
||||
|
||||
## Example
|
||||
|
||||
```go
|
||||
// initializing
|
||||
import bpf "github.com/aquasecurity/libbpfgo"
|
||||
...
|
||||
bpfModule := bpf.NewModuleFromFile(bpfObjectPath)
|
||||
bpfModule.BPFLoadObject()
|
||||
|
||||
// maps
|
||||
mymap, _ := bpfModule.GetMap("mymap")
|
||||
mymap.Update(key, value)
|
||||
|
||||
// ring buffer
|
||||
rb, _ := bpfModule.InitRingBuffer("events", eventsChannel, buffSize)
|
||||
rb.Start()
|
||||
e := <-eventsChannel
|
||||
```
|
||||
|
||||
Please check our github milestones for an idea of the project roadmap. The general goal is to fully implement/expose libbpf's API in Go as seamlessly as possible.
|
||||
|
||||
|
||||
## Learn more
|
||||
|
||||
- Blost post on [how to Build eBPF Programs with libbpfgo](https://blog.aquasec.com/libbpf-ebpf-programs)
|
||||
|
||||
- The [selftests](./selftest) are small programs that use libbpfgo to verify functionality, they're good examples to look at for usage.
|
||||
|
||||
- [tracee-ebpf](https://github.com/aquasecurity/tracee/tree/main/tracee-ebpf) is a robust consumer of this package.
|
||||
|
||||
- Feel free to ask questions by creating a new [Discussion](https://github.com/aquasecurity/libbpfgo/discussions) and we'd love to help.
|
8
vendor/github.com/aquasecurity/libbpfgo/go.mod
generated
vendored
Normal file
8
vendor/github.com/aquasecurity/libbpfgo/go.mod
generated
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
module github.com/aquasecurity/libbpfgo
|
||||
|
||||
go 1.16
|
||||
|
||||
require (
|
||||
github.com/stretchr/testify v1.7.0
|
||||
golang.org/x/sys v0.0.0-20210514084401-e8d321eab015
|
||||
)
|
13
vendor/github.com/aquasecurity/libbpfgo/go.sum
generated
vendored
Normal file
13
vendor/github.com/aquasecurity/libbpfgo/go.sum
generated
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
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/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
golang.org/x/sys v0.0.0-20210514084401-e8d321eab015 h1:hZR0X1kPW+nwyJ9xRxqZk1vx5RUObAPBdKVvXPDUH/E=
|
||||
golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
603
vendor/github.com/aquasecurity/libbpfgo/helpers/argumentParsers.go
generated
vendored
Normal file
603
vendor/github.com/aquasecurity/libbpfgo/helpers/argumentParsers.go
generated
vendored
Normal file
@ -0,0 +1,603 @@
|
||||
package helpers
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"net"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// ParseInodeMode parses the `mode` bitmask argument of the `mknod` syscall
|
||||
// http://man7.org/linux/man-pages/man7/inode.7.html
|
||||
func ParseInodeMode(mode uint32) string {
|
||||
var f []string
|
||||
|
||||
// File Type
|
||||
switch {
|
||||
case mode&0140000 == 0140000:
|
||||
f = append(f, "S_IFSOCK")
|
||||
case mode&0120000 == 0120000:
|
||||
f = append(f, "S_IFLNK")
|
||||
case mode&0100000 == 0100000:
|
||||
f = append(f, "S_IFREG")
|
||||
case mode&060000 == 060000:
|
||||
f = append(f, "S_IFBLK")
|
||||
case mode&040000 == 040000:
|
||||
f = append(f, "S_IFDIR")
|
||||
case mode&020000 == 020000:
|
||||
f = append(f, "S_IFCHR")
|
||||
case mode&010000 == 010000:
|
||||
f = append(f, "S_IFIFO")
|
||||
}
|
||||
|
||||
// File Mode
|
||||
// Owner
|
||||
if mode&00700 == 00700 {
|
||||
f = append(f, "S_IRWXU")
|
||||
} else {
|
||||
if mode&00400 == 00400 {
|
||||
f = append(f, "S_IRUSR")
|
||||
}
|
||||
if mode&00200 == 00200 {
|
||||
f = append(f, "S_IWUSR")
|
||||
}
|
||||
if mode&00100 == 00100 {
|
||||
f = append(f, "S_IXUSR")
|
||||
}
|
||||
}
|
||||
// Group
|
||||
if mode&00070 == 00070 {
|
||||
f = append(f, "S_IRWXG")
|
||||
} else {
|
||||
if mode&00040 == 00040 {
|
||||
f = append(f, "S_IRGRP")
|
||||
}
|
||||
if mode&00020 == 00020 {
|
||||
f = append(f, "S_IWGRP")
|
||||
}
|
||||
if mode&00010 == 00010 {
|
||||
f = append(f, "S_IXGRP")
|
||||
}
|
||||
}
|
||||
// Others
|
||||
if mode&00007 == 00007 {
|
||||
f = append(f, "S_IRWXO")
|
||||
} else {
|
||||
if mode&00004 == 00004 {
|
||||
f = append(f, "S_IROTH")
|
||||
}
|
||||
if mode&00002 == 00002 {
|
||||
f = append(f, "S_IWOTH")
|
||||
}
|
||||
if mode&00001 == 00001 {
|
||||
f = append(f, "S_IXOTH")
|
||||
}
|
||||
}
|
||||
|
||||
return strings.Join(f, "|")
|
||||
}
|
||||
|
||||
// ParseMemProt parses the `prot` bitmask argument of the `mmap` syscall
|
||||
// http://man7.org/linux/man-pages/man2/mmap.2.html
|
||||
// https://elixir.bootlin.com/linux/v5.5.3/source/include/uapi/asm-generic/mman-common.h#L10
|
||||
func ParseMemProt(prot uint32) string {
|
||||
var f []string
|
||||
if prot == 0x0 {
|
||||
f = append(f, "PROT_NONE")
|
||||
} else {
|
||||
if prot&0x01 == 0x01 {
|
||||
f = append(f, "PROT_READ")
|
||||
}
|
||||
if prot&0x02 == 0x02 {
|
||||
f = append(f, "PROT_WRITE")
|
||||
}
|
||||
if prot&0x04 == 0x04 {
|
||||
f = append(f, "PROT_EXEC")
|
||||
}
|
||||
}
|
||||
return strings.Join(f, "|")
|
||||
}
|
||||
|
||||
// ParseOpenFlags parses the `flags` bitmask argument of the `open` syscall
|
||||
// http://man7.org/linux/man-pages/man2/open.2.html
|
||||
// https://elixir.bootlin.com/linux/v5.5.3/source/include/uapi/asm-generic/fcntl.h
|
||||
func ParseOpenFlags(flags uint32) string {
|
||||
var f []string
|
||||
|
||||
//access mode
|
||||
switch {
|
||||
case flags&01 == 01:
|
||||
f = append(f, "O_WRONLY")
|
||||
case flags&02 == 02:
|
||||
f = append(f, "O_RDWR")
|
||||
default:
|
||||
f = append(f, "O_RDONLY")
|
||||
}
|
||||
|
||||
// file creation and status flags
|
||||
if flags&0100 == 0100 {
|
||||
f = append(f, "O_CREAT")
|
||||
}
|
||||
if flags&0200 == 0200 {
|
||||
f = append(f, "O_EXCL")
|
||||
}
|
||||
if flags&0400 == 0400 {
|
||||
f = append(f, "O_NOCTTY")
|
||||
}
|
||||
if flags&01000 == 01000 {
|
||||
f = append(f, "O_TRUNC")
|
||||
}
|
||||
if flags&02000 == 02000 {
|
||||
f = append(f, "O_APPEND")
|
||||
}
|
||||
if flags&04000 == 04000 {
|
||||
f = append(f, "O_NONBLOCK")
|
||||
}
|
||||
if flags&04010000 == 04010000 {
|
||||
f = append(f, "O_SYNC")
|
||||
}
|
||||
if flags&020000 == 020000 {
|
||||
f = append(f, "O_ASYNC")
|
||||
}
|
||||
if flags&0100000 == 0100000 {
|
||||
f = append(f, "O_LARGEFILE")
|
||||
}
|
||||
if flags&0200000 == 0200000 {
|
||||
f = append(f, "O_DIRECTORY")
|
||||
}
|
||||
if flags&0400000 == 0400000 {
|
||||
f = append(f, "O_NOFOLLOW")
|
||||
}
|
||||
if flags&02000000 == 02000000 {
|
||||
f = append(f, "O_CLOEXEC")
|
||||
}
|
||||
if flags&040000 == 040000 {
|
||||
f = append(f, "O_DIRECT")
|
||||
}
|
||||
if flags&01000000 == 01000000 {
|
||||
f = append(f, "O_NOATIME")
|
||||
}
|
||||
if flags&010000000 == 010000000 {
|
||||
f = append(f, "O_PATH")
|
||||
}
|
||||
if flags&020000000 == 020000000 {
|
||||
f = append(f, "O_TMPFILE")
|
||||
}
|
||||
|
||||
return strings.Join(f, "|")
|
||||
}
|
||||
|
||||
// ParseAccessMode parses the mode from the `access` system call
|
||||
// http://man7.org/linux/man-pages/man2/access.2.html
|
||||
func ParseAccessMode(mode uint32) string {
|
||||
var f []string
|
||||
if mode == 0x0 {
|
||||
f = append(f, "F_OK")
|
||||
} else {
|
||||
if mode&0x04 == 0x04 {
|
||||
f = append(f, "R_OK")
|
||||
}
|
||||
if mode&0x02 == 0x02 {
|
||||
f = append(f, "W_OK")
|
||||
}
|
||||
if mode&0x01 == 0x01 {
|
||||
f = append(f, "X_OK")
|
||||
}
|
||||
}
|
||||
return strings.Join(f, "|")
|
||||
}
|
||||
|
||||
// ParseExecFlags parses the `flags` bitmask argument of the `execve` syscall
|
||||
// http://man7.org/linux/man-pages/man2/axecveat.2.html
|
||||
func ParseExecFlags(flags uint32) string {
|
||||
var f []string
|
||||
if flags&0x100 == 0x100 {
|
||||
f = append(f, "AT_EMPTY_PATH")
|
||||
}
|
||||
if flags&0x1000 == 0x1000 {
|
||||
f = append(f, "AT_SYMLINK_NOFOLLOW")
|
||||
}
|
||||
if len(f) == 0 {
|
||||
f = append(f, "0")
|
||||
}
|
||||
return strings.Join(f, "|")
|
||||
}
|
||||
|
||||
// ParseCloneFlags parses the `flags` bitmask argument of the `clone` syscall
|
||||
// https://man7.org/linux/man-pages/man2/clone.2.html
|
||||
func ParseCloneFlags(flags uint64) string {
|
||||
var f []string
|
||||
if flags&0x00000100 == 0x00000100 {
|
||||
f = append(f, "CLONE_VM")
|
||||
}
|
||||
if flags&0x00000200 == 0x00000200 {
|
||||
f = append(f, "CLONE_FS")
|
||||
}
|
||||
if flags&0x00000400 == 0x00000400 {
|
||||
f = append(f, "CLONE_FILES")
|
||||
}
|
||||
if flags&0x00000800 == 0x00000800 {
|
||||
f = append(f, "CLONE_SIGHAND")
|
||||
}
|
||||
if flags&0x00001000 == 0x00001000 {
|
||||
f = append(f, "CLONE_PIDFD")
|
||||
}
|
||||
if flags&0x00002000 == 0x00002000 {
|
||||
f = append(f, "CLONE_PTRACE")
|
||||
}
|
||||
if flags&0x00004000 == 0x00004000 {
|
||||
f = append(f, "CLONE_VFORK")
|
||||
}
|
||||
if flags&0x00008000 == 0x00008000 {
|
||||
f = append(f, "CLONE_PARENT")
|
||||
}
|
||||
if flags&0x00010000 == 0x00010000 {
|
||||
f = append(f, "CLONE_THREAD")
|
||||
}
|
||||
if flags&0x00020000 == 0x00020000 {
|
||||
f = append(f, "CLONE_NEWNS")
|
||||
}
|
||||
if flags&0x00040000 == 0x00040000 {
|
||||
f = append(f, "CLONE_SYSVSEM")
|
||||
}
|
||||
if flags&0x00080000 == 0x00080000 {
|
||||
f = append(f, "CLONE_SETTLS")
|
||||
}
|
||||
if flags&0x00100000 == 0x00100000 {
|
||||
f = append(f, "CLONE_PARENT_SETTID")
|
||||
}
|
||||
if flags&0x00200000 == 0x00200000 {
|
||||
f = append(f, "CLONE_CHILD_CLEARTID")
|
||||
}
|
||||
if flags&0x00400000 == 0x00400000 {
|
||||
f = append(f, "CLONE_DETACHED")
|
||||
}
|
||||
if flags&0x00800000 == 0x00800000 {
|
||||
f = append(f, "CLONE_UNTRACED")
|
||||
}
|
||||
if flags&0x01000000 == 0x01000000 {
|
||||
f = append(f, "CLONE_CHILD_SETTID")
|
||||
}
|
||||
if flags&0x02000000 == 0x02000000 {
|
||||
f = append(f, "CLONE_NEWCGROUP")
|
||||
}
|
||||
if flags&0x04000000 == 0x04000000 {
|
||||
f = append(f, "CLONE_NEWUTS")
|
||||
}
|
||||
if flags&0x08000000 == 0x08000000 {
|
||||
f = append(f, "CLONE_NEWIPC")
|
||||
}
|
||||
if flags&0x10000000 == 0x10000000 {
|
||||
f = append(f, "CLONE_NEWUSER")
|
||||
}
|
||||
if flags&0x20000000 == 0x20000000 {
|
||||
f = append(f, "CLONE_NEWPID")
|
||||
}
|
||||
if flags&0x40000000 == 0x40000000 {
|
||||
f = append(f, "CLONE_NEWNET")
|
||||
}
|
||||
if flags&0x80000000 == 0x80000000 {
|
||||
f = append(f, "CLONE_IO")
|
||||
}
|
||||
if len(f) == 0 {
|
||||
f = append(f, "0")
|
||||
}
|
||||
return strings.Join(f, "|")
|
||||
}
|
||||
|
||||
// ParseSocketType parses the `type` bitmask argument of the `socket` syscall
|
||||
// http://man7.org/linux/man-pages/man2/socket.2.html
|
||||
func ParseSocketType(st uint32) string {
|
||||
var socketTypes = map[uint32]string{
|
||||
1: "SOCK_STREAM",
|
||||
2: "SOCK_DGRAM",
|
||||
3: "SOCK_RAW",
|
||||
4: "SOCK_RDM",
|
||||
5: "SOCK_SEQPACKET",
|
||||
6: "SOCK_DCCP",
|
||||
10: "SOCK_PACKET",
|
||||
}
|
||||
var f []string
|
||||
if stName, ok := socketTypes[st&0xf]; ok {
|
||||
f = append(f, stName)
|
||||
} else {
|
||||
f = append(f, strconv.Itoa(int(st)))
|
||||
}
|
||||
if st&000004000 == 000004000 {
|
||||
f = append(f, "SOCK_NONBLOCK")
|
||||
}
|
||||
if st&002000000 == 002000000 {
|
||||
f = append(f, "SOCK_CLOEXEC")
|
||||
}
|
||||
return strings.Join(f, "|")
|
||||
}
|
||||
|
||||
// ParseSocketDomain parses the `domain` bitmask argument of the `socket` syscall
|
||||
// http://man7.org/linux/man-pages/man2/socket.2.html
|
||||
func ParseSocketDomain(sd uint32) string {
|
||||
var socketDomains = map[uint32]string{
|
||||
0: "AF_UNSPEC",
|
||||
1: "AF_UNIX",
|
||||
2: "AF_INET",
|
||||
3: "AF_AX25",
|
||||
4: "AF_IPX",
|
||||
5: "AF_APPLETALK",
|
||||
6: "AF_NETROM",
|
||||
7: "AF_BRIDGE",
|
||||
8: "AF_ATMPVC",
|
||||
9: "AF_X25",
|
||||
10: "AF_INET6",
|
||||
11: "AF_ROSE",
|
||||
12: "AF_DECnet",
|
||||
13: "AF_NETBEUI",
|
||||
14: "AF_SECURITY",
|
||||
15: "AF_KEY",
|
||||
16: "AF_NETLINK",
|
||||
17: "AF_PACKET",
|
||||
18: "AF_ASH",
|
||||
19: "AF_ECONET",
|
||||
20: "AF_ATMSVC",
|
||||
21: "AF_RDS",
|
||||
22: "AF_SNA",
|
||||
23: "AF_IRDA",
|
||||
24: "AF_PPPOX",
|
||||
25: "AF_WANPIPE",
|
||||
26: "AF_LLC",
|
||||
27: "AF_IB",
|
||||
28: "AF_MPLS",
|
||||
29: "AF_CAN",
|
||||
30: "AF_TIPC",
|
||||
31: "AF_BLUETOOTH",
|
||||
32: "AF_IUCV",
|
||||
33: "AF_RXRPC",
|
||||
34: "AF_ISDN",
|
||||
35: "AF_PHONET",
|
||||
36: "AF_IEEE802154",
|
||||
37: "AF_CAIF",
|
||||
38: "AF_ALG",
|
||||
39: "AF_NFC",
|
||||
40: "AF_VSOCK",
|
||||
41: "AF_KCM",
|
||||
42: "AF_QIPCRTR",
|
||||
43: "AF_SMC",
|
||||
44: "AF_XDP",
|
||||
}
|
||||
var res string
|
||||
if sdName, ok := socketDomains[sd]; ok {
|
||||
res = sdName
|
||||
} else {
|
||||
res = strconv.Itoa(int(sd))
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
// ParseUint32IP parses the IP address encoded as a uint32
|
||||
func ParseUint32IP(in uint32) string {
|
||||
ip := make(net.IP, net.IPv4len)
|
||||
binary.BigEndian.PutUint32(ip, in)
|
||||
return ip.String()
|
||||
}
|
||||
|
||||
// Parse16BytesSliceIP parses the IP address encoded as 16 bytes long PrintBytesSliceIP
|
||||
// It would be more correct to accept a [16]byte instead of variable lenth slice, but that would case unnecessary memory copying and type conversions
|
||||
func Parse16BytesSliceIP(in []byte) string {
|
||||
ip := net.IP(in)
|
||||
return ip.String()
|
||||
}
|
||||
|
||||
// ParseCapability parses the `capability` bitmask argument of the `cap_capable` function
|
||||
// include/uapi/linux/capability.h
|
||||
func ParseCapability(cap int32) string {
|
||||
var capabilities = map[int32]string{
|
||||
0: "CAP_CHOWN",
|
||||
1: "CAP_DAC_OVERRIDE",
|
||||
2: "CAP_DAC_READ_SEARCH",
|
||||
3: "CAP_FOWNER",
|
||||
4: "CAP_FSETID",
|
||||
5: "CAP_KILL",
|
||||
6: "CAP_SETGID",
|
||||
7: "CAP_SETUID",
|
||||
8: "CAP_SETPCAP",
|
||||
9: "CAP_LINUX_IMMUTABLE",
|
||||
10: "CAP_NET_BIND_SERVICE",
|
||||
11: "CAP_NET_BROADCAST",
|
||||
12: "CAP_NET_ADMIN",
|
||||
13: "CAP_NET_RAW",
|
||||
14: "CAP_IPC_LOCK",
|
||||
15: "CAP_IPC_OWNER",
|
||||
16: "CAP_SYS_MODULE",
|
||||
17: "CAP_SYS_RAWIO",
|
||||
18: "CAP_SYS_CHROOT",
|
||||
19: "CAP_SYS_PTRACE",
|
||||
20: "CAP_SYS_PACCT",
|
||||
21: "CAP_SYS_ADMIN",
|
||||
22: "CAP_SYS_BOOT",
|
||||
23: "CAP_SYS_NICE",
|
||||
24: "CAP_SYS_RESOURCE",
|
||||
25: "CAP_SYS_TIME",
|
||||
26: "CAP_SYS_TTY_CONFIG",
|
||||
27: "CAP_MKNOD",
|
||||
28: "CAP_LEASE",
|
||||
29: "CAP_AUDIT_WRITE",
|
||||
30: "CAP_AUDIT_CONTROL",
|
||||
31: "CAP_SETFCAP",
|
||||
32: "CAP_MAC_OVERRIDE",
|
||||
33: "CAP_MAC_ADMIN",
|
||||
34: "CAP_SYSLOG",
|
||||
35: "CAP_WAKE_ALARM",
|
||||
36: "CAP_BLOCK_SUSPEND",
|
||||
37: "CAP_AUDIT_READ",
|
||||
}
|
||||
var res string
|
||||
if capName, ok := capabilities[cap]; ok {
|
||||
res = capName
|
||||
} else {
|
||||
res = strconv.Itoa(int(cap))
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
// ParsePrctlOption parses the `option` argument of the `prctl` syscall
|
||||
// http://man7.org/linux/man-pages/man2/prctl.2.html
|
||||
func ParsePrctlOption(op int32) string {
|
||||
var prctlOptions = map[int32]string{
|
||||
1: "PR_SET_PDEATHSIG",
|
||||
2: "PR_GET_PDEATHSIG",
|
||||
3: "PR_GET_DUMPABLE",
|
||||
4: "PR_SET_DUMPABLE",
|
||||
5: "PR_GET_UNALIGN",
|
||||
6: "PR_SET_UNALIGN",
|
||||
7: "PR_GET_KEEPCAPS",
|
||||
8: "PR_SET_KEEPCAPS",
|
||||
9: "PR_GET_FPEMU",
|
||||
10: "PR_SET_FPEMU",
|
||||
11: "PR_GET_FPEXC",
|
||||
12: "PR_SET_FPEXC",
|
||||
13: "PR_GET_TIMING",
|
||||
14: "PR_SET_TIMING",
|
||||
15: "PR_SET_NAME",
|
||||
16: "PR_GET_NAME",
|
||||
19: "PR_GET_ENDIAN",
|
||||
20: "PR_SET_ENDIAN",
|
||||
21: "PR_GET_SECCOMP",
|
||||
22: "PR_SET_SECCOMP",
|
||||
23: "PR_CAPBSET_READ",
|
||||
24: "PR_CAPBSET_DROP",
|
||||
25: "PR_GET_TSC",
|
||||
26: "PR_SET_TSC",
|
||||
27: "PR_GET_SECUREBITS",
|
||||
28: "PR_SET_SECUREBITS",
|
||||
29: "PR_SET_TIMERSLACK",
|
||||
30: "PR_GET_TIMERSLACK",
|
||||
31: "PR_TASK_PERF_EVENTS_DISABLE",
|
||||
32: "PR_TASK_PERF_EVENTS_ENABLE",
|
||||
33: "PR_MCE_KILL",
|
||||
34: "PR_MCE_KILL_GET",
|
||||
35: "PR_SET_MM",
|
||||
36: "PR_SET_CHILD_SUBREAPER",
|
||||
37: "PR_GET_CHILD_SUBREAPER",
|
||||
38: "PR_SET_NO_NEW_PRIVS",
|
||||
39: "PR_GET_NO_NEW_PRIVS",
|
||||
40: "PR_GET_TID_ADDRESS",
|
||||
41: "PR_SET_THP_DISABLE",
|
||||
42: "PR_GET_THP_DISABLE",
|
||||
43: "PR_MPX_ENABLE_MANAGEMENT",
|
||||
44: "PR_MPX_DISABLE_MANAGEMENT",
|
||||
45: "PR_SET_FP_MODE",
|
||||
46: "PR_GET_FP_MODE",
|
||||
47: "PR_CAP_AMBIENT",
|
||||
50: "PR_SVE_SET_VL",
|
||||
51: "PR_SVE_GET_VL",
|
||||
52: "PR_GET_SPECULATION_CTRL",
|
||||
53: "PR_SET_SPECULATION_CTRL",
|
||||
54: "PR_PAC_RESET_KEYS",
|
||||
55: "PR_SET_TAGGED_ADDR_CTRL",
|
||||
56: "PR_GET_TAGGED_ADDR_CTRL",
|
||||
}
|
||||
|
||||
var res string
|
||||
if opName, ok := prctlOptions[op]; ok {
|
||||
res = opName
|
||||
} else {
|
||||
res = strconv.Itoa(int(op))
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
// ParsePtraceRequest parses the `request` argument of the `ptrace` syscall
|
||||
// http://man7.org/linux/man-pages/man2/ptrace.2.html
|
||||
func ParsePtraceRequest(req int64) string {
|
||||
var ptraceRequest = map[int64]string{
|
||||
0: "PTRACE_TRACEME",
|
||||
1: "PTRACE_PEEKTEXT",
|
||||
2: "PTRACE_PEEKDATA",
|
||||
3: "PTRACE_PEEKUSER",
|
||||
4: "PTRACE_POKETEXT",
|
||||
5: "PTRACE_POKEDATA",
|
||||
6: "PTRACE_POKEUSER",
|
||||
7: "PTRACE_CONT",
|
||||
8: "PTRACE_KILL",
|
||||
9: "PTRACE_SINGLESTEP",
|
||||
12: "PTRACE_GETREGS",
|
||||
13: "PTRACE_SETREGS",
|
||||
14: "PTRACE_GETFPREGS",
|
||||
15: "PTRACE_SETFPREGS",
|
||||
16: "PTRACE_ATTACH",
|
||||
17: "PTRACE_DETACH",
|
||||
18: "PTRACE_GETFPXREGS",
|
||||
19: "PTRACE_SETFPXREGS",
|
||||
24: "PTRACE_SYSCALL",
|
||||
0x4200: "PTRACE_SETOPTIONS",
|
||||
0x4201: "PTRACE_GETEVENTMSG",
|
||||
0x4202: "PTRACE_GETSIGINFO",
|
||||
0x4203: "PTRACE_SETSIGINFO",
|
||||
0x4204: "PTRACE_GETREGSET",
|
||||
0x4205: "PTRACE_SETREGSET",
|
||||
0x4206: "PTRACE_SEIZE",
|
||||
0x4207: "PTRACE_INTERRUPT",
|
||||
0x4208: "PTRACE_LISTEN",
|
||||
0x4209: "PTRACE_PEEKSIGINFO",
|
||||
0x420a: "PTRACE_GETSIGMASK",
|
||||
0x420b: "PTRACE_SETSIGMASK",
|
||||
0x420c: "PTRACE_SECCOMP_GET_FILTER",
|
||||
0x420d: "PTRACE_SECCOMP_GET_METADATA",
|
||||
}
|
||||
|
||||
var res string
|
||||
if reqName, ok := ptraceRequest[req]; ok {
|
||||
res = reqName
|
||||
} else {
|
||||
res = strconv.Itoa(int(req))
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
// ParseBPFCmd parses the `cmd` argument of the `bpf` syscall
|
||||
// https://man7.org/linux/man-pages/man2/bpf.2.html
|
||||
func ParseBPFCmd(cmd int32) string {
|
||||
var bpfCmd = map[int32]string{
|
||||
0: "BPF_MAP_CREATE",
|
||||
1: "BPF_MAP_LOOKUP_ELEM",
|
||||
2: "BPF_MAP_UPDATE_ELEM",
|
||||
3: "BPF_MAP_DELETE_ELEM",
|
||||
4: "BPF_MAP_GET_NEXT_KEY",
|
||||
5: "BPF_PROG_LOAD",
|
||||
6: "BPF_OBJ_PIN",
|
||||
7: "BPF_OBJ_GET",
|
||||
8: "BPF_PROG_ATTACH",
|
||||
9: "BPF_PROG_DETACH",
|
||||
10: "BPF_PROG_TEST_RUN",
|
||||
11: "BPF_PROG_GET_NEXT_ID",
|
||||
12: "BPF_MAP_GET_NEXT_ID",
|
||||
13: "BPF_PROG_GET_FD_BY_ID",
|
||||
14: "BPF_MAP_GET_FD_BY_ID",
|
||||
15: "BPF_OBJ_GET_INFO_BY_FD",
|
||||
16: "BPF_PROG_QUERY",
|
||||
17: "BPF_RAW_TRACEPOINT_OPEN",
|
||||
18: "BPF_BTF_LOAD",
|
||||
19: "BPF_BTF_GET_FD_BY_ID",
|
||||
20: "BPF_TASK_FD_QUERY",
|
||||
21: "BPF_MAP_LOOKUP_AND_DELETE_ELEM",
|
||||
22: "BPF_MAP_FREEZE",
|
||||
23: "BPF_BTF_GET_NEXT_ID",
|
||||
24: "BPF_MAP_LOOKUP_BATCH",
|
||||
25: "BPF_MAP_LOOKUP_AND_DELETE_BATCH",
|
||||
26: "BPF_MAP_UPDATE_BATCH",
|
||||
27: "BPF_MAP_DELETE_BATCH",
|
||||
28: "BPF_LINK_CREATE",
|
||||
29: "BPF_LINK_UPDATE",
|
||||
30: "BPF_LINK_GET_FD_BY_ID",
|
||||
31: "BPF_LINK_GET_NEXT_ID",
|
||||
32: "BPF_ENABLE_STATS",
|
||||
33: "BPF_ITER_CREATE",
|
||||
34: "BPF_LINK_DETACH",
|
||||
}
|
||||
|
||||
var res string
|
||||
if cmdName, ok := bpfCmd[cmd]; ok {
|
||||
res = cmdName
|
||||
} else {
|
||||
res = strconv.Itoa(int(cmd))
|
||||
}
|
||||
return res
|
||||
}
|
52
vendor/github.com/aquasecurity/libbpfgo/helpers/elf.go
generated
vendored
Normal file
52
vendor/github.com/aquasecurity/libbpfgo/helpers/elf.go
generated
vendored
Normal file
@ -0,0 +1,52 @@
|
||||
package helpers
|
||||
|
||||
import (
|
||||
"debug/elf"
|
||||
"errors"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// SymbolToOffset attempts to resolve a 'symbol' name in the binary found at
|
||||
// 'path' to an offset. The offset can be used for attaching a u(ret)probe
|
||||
func SymbolToOffset(path, symbol string) (uint32, error) {
|
||||
|
||||
f, err := elf.Open(path)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("could not open elf file to resolve symbol offset: %v", err)
|
||||
}
|
||||
|
||||
syms, err := f.Symbols()
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("could not open symbol section to resolve symbol offset: %v", err)
|
||||
}
|
||||
|
||||
sectionsToSearchForSymbol := []*elf.Section{}
|
||||
|
||||
for i := range f.Sections {
|
||||
if f.Sections[i].Flags == elf.SHF_ALLOC+elf.SHF_EXECINSTR {
|
||||
sectionsToSearchForSymbol = append(sectionsToSearchForSymbol, f.Sections[i])
|
||||
}
|
||||
}
|
||||
|
||||
var executableSection *elf.Section
|
||||
for i := range syms {
|
||||
if syms[i].Name == symbol {
|
||||
|
||||
// Find what section the symbol is in by checking the executable section's
|
||||
// addr space.
|
||||
for m := range sectionsToSearchForSymbol {
|
||||
if syms[i].Value > sectionsToSearchForSymbol[m].Addr &&
|
||||
syms[i].Value < sectionsToSearchForSymbol[m].Addr+sectionsToSearchForSymbol[m].Size {
|
||||
executableSection = sectionsToSearchForSymbol[m]
|
||||
}
|
||||
}
|
||||
|
||||
if executableSection == nil {
|
||||
return 0, errors.New("could not find symbol in executable sections of binary")
|
||||
}
|
||||
|
||||
return uint32(syms[i].Value - executableSection.Addr + executableSection.Offset), nil
|
||||
}
|
||||
}
|
||||
return 0, fmt.Errorf("symbol not found")
|
||||
}
|
228
vendor/github.com/aquasecurity/libbpfgo/helpers/kernel_features.go
generated
vendored
Normal file
228
vendor/github.com/aquasecurity/libbpfgo/helpers/kernel_features.go
generated
vendored
Normal file
@ -0,0 +1,228 @@
|
||||
package helpers
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"compress/gzip"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
// These constants are a limited number of the total kernel config options,
|
||||
// but are provided because they are most relevant for BPF
|
||||
// development.
|
||||
const (
|
||||
CONFIG_BPF uint32 = iota + 1
|
||||
CONFIG_BPF_SYSCALL
|
||||
CONFIG_HAVE_EBPF_JIT
|
||||
CONFIG_BPF_JIT
|
||||
CONFIG_BPF_JIT_ALWAYS_ON
|
||||
CONFIG_CGROUPS
|
||||
CONFIG_CGROUP_BPF
|
||||
CONFIG_CGROUP_NET_CLASSID
|
||||
CONFIG_SOCK_CGROUP_DATA
|
||||
CONFIG_BPF_EVENTS
|
||||
CONFIG_KPROBE_EVENTS
|
||||
CONFIG_UPROBE_EVENTS
|
||||
CONFIG_TRACING
|
||||
CONFIG_FTRACE_SYSCALLS
|
||||
CONFIG_FUNCTION_ERROR_INJECTION
|
||||
CONFIG_BPF_KPROBE_OVERRIDE
|
||||
CONFIG_NET
|
||||
CONFIG_XDP_SOCKETS
|
||||
CONFIG_LWTUNNEL_BPF
|
||||
CONFIG_NET_ACT_BPF
|
||||
CONFIG_NET_CLS_BPF
|
||||
CONFIG_NET_CLS_ACT
|
||||
CONFIG_NET_SCH_INGRESS
|
||||
CONFIG_XFRM
|
||||
CONFIG_IP_ROUTE_CLASSID
|
||||
CONFIG_IPV6_SEG6_BPF
|
||||
CONFIG_BPF_LIRC_MODE2
|
||||
CONFIG_BPF_STREAM_PARSER
|
||||
CONFIG_NETFILTER_XT_MATCH_BPF
|
||||
CONFIG_BPFILTER
|
||||
CONFIG_BPFILTER_UMH
|
||||
CONFIG_TEST_BPF
|
||||
CONFIG_HZ
|
||||
CONFIG_DEBUG_INFO_BTF
|
||||
CONFIG_DEBUG_INFO_BTF_MODULES
|
||||
CONFIG_BPF_LSM
|
||||
CONFIG_BPF_PRELOAD
|
||||
CONFIG_BPF_PRELOAD_UMD
|
||||
)
|
||||
|
||||
var KernelConfigKeyStringToID map[string]uint32 = map[string]uint32{
|
||||
"CONFIG_BPF": CONFIG_BPF,
|
||||
"CONFIG_BPF_SYSCALL": CONFIG_BPF_SYSCALL,
|
||||
"CONFIG_HAVE_EBPF_JIT": CONFIG_HAVE_EBPF_JIT,
|
||||
"CONFIG_BPF_JIT": CONFIG_BPF_JIT,
|
||||
"CONFIG_BPF_JIT_ALWAYS_ON": CONFIG_BPF_JIT_ALWAYS_ON,
|
||||
"CONFIG_CGROUPS": CONFIG_CGROUPS,
|
||||
"CONFIG_CGROUP_BPF": CONFIG_CGROUP_BPF,
|
||||
"CONFIG_CGROUP_NET_CLASSID": CONFIG_CGROUP_NET_CLASSID,
|
||||
"CONFIG_SOCK_CGROUP_DATA": CONFIG_SOCK_CGROUP_DATA,
|
||||
"CONFIG_BPF_EVENTS": CONFIG_BPF_EVENTS,
|
||||
"CONFIG_KPROBE_EVENTS": CONFIG_KPROBE_EVENTS,
|
||||
"CONFIG_UPROBE_EVENTS": CONFIG_UPROBE_EVENTS,
|
||||
"CONFIG_TRACING": CONFIG_TRACING,
|
||||
"CONFIG_FTRACE_SYSCALLS": CONFIG_FTRACE_SYSCALLS,
|
||||
"CONFIG_FUNCTION_ERROR_INJECTION": CONFIG_FUNCTION_ERROR_INJECTION,
|
||||
"CONFIG_BPF_KPROBE_OVERRIDE": CONFIG_BPF_KPROBE_OVERRIDE,
|
||||
"CONFIG_NET": CONFIG_NET,
|
||||
"CONFIG_XDP_SOCKETS": CONFIG_XDP_SOCKETS,
|
||||
"CONFIG_LWTUNNEL_BPF": CONFIG_LWTUNNEL_BPF,
|
||||
"CONFIG_NET_ACT_BPF": CONFIG_NET_ACT_BPF,
|
||||
"CONFIG_NET_CLS_BPF": CONFIG_NET_CLS_BPF,
|
||||
"CONFIG_NET_CLS_ACT": CONFIG_NET_CLS_ACT,
|
||||
"CONFIG_NET_SCH_INGRESS": CONFIG_NET_SCH_INGRESS,
|
||||
"CONFIG_XFRM": CONFIG_XFRM,
|
||||
"CONFIG_IP_ROUTE_CLASSID": CONFIG_IP_ROUTE_CLASSID,
|
||||
"CONFIG_IPV6_SEG6_BPF": CONFIG_IPV6_SEG6_BPF,
|
||||
"CONFIG_BPF_LIRC_MODE2": CONFIG_BPF_LIRC_MODE2,
|
||||
"CONFIG_BPF_STREAM_PARSER": CONFIG_BPF_STREAM_PARSER,
|
||||
"CONFIG_NETFILTER_XT_MATCH_BPF": CONFIG_NETFILTER_XT_MATCH_BPF,
|
||||
"CONFIG_BPFILTER": CONFIG_BPFILTER,
|
||||
"CONFIG_BPFILTER_UMH": CONFIG_BPFILTER_UMH,
|
||||
"CONFIG_TEST_BPF": CONFIG_TEST_BPF,
|
||||
"CONFIG_HZ": CONFIG_HZ,
|
||||
"CONFIG_DEBUG_INFO_BTF": CONFIG_DEBUG_INFO_BTF,
|
||||
"CONFIG_DEBUG_INFO_BTF_MODULES": CONFIG_DEBUG_INFO_BTF_MODULES,
|
||||
"CONFIG_BPF_LSM": CONFIG_BPF_LSM,
|
||||
"CONFIG_BPF_PRELOAD": CONFIG_BPF_PRELOAD,
|
||||
"CONFIG_BPF_PRELOAD_UMD": CONFIG_BPF_PRELOAD_UMD,
|
||||
}
|
||||
|
||||
var KernelConfigKeyIDToString map[uint32]string = map[uint32]string{
|
||||
CONFIG_BPF: "CONFIG_BPF",
|
||||
CONFIG_BPF_SYSCALL: "CONFIG_BPF_SYSCALL",
|
||||
CONFIG_HAVE_EBPF_JIT: "CONFIG_HAVE_EBPF_JIT",
|
||||
CONFIG_BPF_JIT: "CONFIG_BPF_JIT",
|
||||
CONFIG_BPF_JIT_ALWAYS_ON: "CONFIG_BPF_JIT_ALWAYS_ON",
|
||||
CONFIG_CGROUPS: "CONFIG_CGROUPS",
|
||||
CONFIG_CGROUP_BPF: "CONFIG_CGROUP_BPF",
|
||||
CONFIG_CGROUP_NET_CLASSID: "CONFIG_CGROUP_NET_CLASSID",
|
||||
CONFIG_SOCK_CGROUP_DATA: "CONFIG_SOCK_CGROUP_DATA",
|
||||
CONFIG_BPF_EVENTS: "CONFIG_BPF_EVENTS",
|
||||
CONFIG_KPROBE_EVENTS: "CONFIG_KPROBE_EVENTS",
|
||||
CONFIG_UPROBE_EVENTS: "CONFIG_UPROBE_EVENTS",
|
||||
CONFIG_TRACING: "CONFIG_TRACING",
|
||||
CONFIG_FTRACE_SYSCALLS: "CONFIG_FTRACE_SYSCALLS",
|
||||
CONFIG_FUNCTION_ERROR_INJECTION: "CONFIG_FUNCTION_ERROR_INJECTION",
|
||||
CONFIG_BPF_KPROBE_OVERRIDE: "CONFIG_BPF_KPROBE_OVERRIDE",
|
||||
CONFIG_NET: "CONFIG_NET",
|
||||
CONFIG_XDP_SOCKETS: "CONFIG_XDP_SOCKETS",
|
||||
CONFIG_LWTUNNEL_BPF: "CONFIG_LWTUNNEL_BPF",
|
||||
CONFIG_NET_ACT_BPF: "CONFIG_NET_ACT_BPF",
|
||||
CONFIG_NET_CLS_BPF: "CONFIG_NET_CLS_BPF",
|
||||
CONFIG_NET_CLS_ACT: "CONFIG_NET_CLS_ACT",
|
||||
CONFIG_NET_SCH_INGRESS: "CONFIG_NET_SCH_INGRESS",
|
||||
CONFIG_XFRM: "CONFIG_XFRM",
|
||||
CONFIG_IP_ROUTE_CLASSID: "CONFIG_IP_ROUTE_CLASSID",
|
||||
CONFIG_IPV6_SEG6_BPF: "CONFIG_IPV6_SEG6_BPF",
|
||||
CONFIG_BPF_LIRC_MODE2: "CONFIG_BPF_LIRC_MODE2",
|
||||
CONFIG_BPF_STREAM_PARSER: "CONFIG_BPF_STREAM_PARSER",
|
||||
CONFIG_NETFILTER_XT_MATCH_BPF: "CONFIG_NETFILTER_XT_MATCH_BPF",
|
||||
CONFIG_BPFILTER: "CONFIG_BPFILTER",
|
||||
CONFIG_BPFILTER_UMH: "CONFIG_BPFILTER_UMH",
|
||||
CONFIG_TEST_BPF: "CONFIG_TEST_BPF",
|
||||
CONFIG_HZ: "CONFIG_HZ",
|
||||
CONFIG_DEBUG_INFO_BTF: "CONFIG_DEBUG_INFO_BTF",
|
||||
CONFIG_DEBUG_INFO_BTF_MODULES: "CONFIG_DEBUG_INFO_BTF_MODULES",
|
||||
CONFIG_BPF_LSM: "CONFIG_BPF_LSM",
|
||||
CONFIG_BPF_PRELOAD: "CONFIG_BPF_PRELOAD",
|
||||
CONFIG_BPF_PRELOAD_UMD: "CONFIG_BPF_PRELOAD_UMD",
|
||||
}
|
||||
|
||||
type KernelConfig map[uint32]string
|
||||
|
||||
// InitKernelConfig populates the passed KernelConfig
|
||||
// by attempting to read the kernel config into it from:
|
||||
// /proc/config-$(uname -r)
|
||||
// or
|
||||
// /boot/config.gz
|
||||
func (k KernelConfig) InitKernelConfig() error {
|
||||
|
||||
x := unix.Utsname{}
|
||||
err := unix.Uname(&x)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not determine uname release: %v", err)
|
||||
}
|
||||
|
||||
bootConfigPath := fmt.Sprintf("/boot/config-%s", bytes.Trim(x.Release[:], "\x00"))
|
||||
|
||||
err = k.getBootConfigByPath(bootConfigPath)
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
err2 := k.getProcGZConfigByPath("/proc/config.gz")
|
||||
if err != nil {
|
||||
return fmt.Errorf("%v %v", err, err2)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetKernelConfigValue retrieves a value from the kernel config
|
||||
// If the config value does not exist an error will be returned
|
||||
func (k KernelConfig) GetKernelConfigValue(key uint32) (string, error) {
|
||||
v, exists := k[key]
|
||||
if !exists {
|
||||
return "", errors.New("kernel config value does not exist, it's possible this option is not present in your kernel version or the KernelConfig has not been initialized")
|
||||
}
|
||||
return v, nil
|
||||
}
|
||||
|
||||
func (k KernelConfig) getBootConfigByPath(bootConfigPath string) error {
|
||||
|
||||
configFile, err := os.Open(bootConfigPath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not open %s: %v", bootConfigPath, err)
|
||||
}
|
||||
|
||||
k.readConfigFromScanner(configFile)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (k KernelConfig) getProcGZConfigByPath(procConfigPath string) error {
|
||||
|
||||
configFile, err := os.Open(procConfigPath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not open %s: %v", procConfigPath, err)
|
||||
}
|
||||
|
||||
return k.getProcGZConfig(configFile)
|
||||
}
|
||||
|
||||
func (k KernelConfig) getProcGZConfig(reader io.Reader) error {
|
||||
zreader, err := gzip.NewReader(reader)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
k.readConfigFromScanner(zreader)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (k KernelConfig) readConfigFromScanner(reader io.Reader) {
|
||||
scanner := bufio.NewScanner(reader)
|
||||
|
||||
for scanner.Scan() {
|
||||
kv := strings.Split(scanner.Text(), "=")
|
||||
if len(kv) != 2 {
|
||||
continue
|
||||
}
|
||||
configKeyID := KernelConfigKeyStringToID[kv[0]]
|
||||
if configKeyID == 0 {
|
||||
continue
|
||||
}
|
||||
k[configKeyID] = kv[1]
|
||||
}
|
||||
}
|
74
vendor/github.com/aquasecurity/libbpfgo/helpers/rwArray.go
generated
vendored
Normal file
74
vendor/github.com/aquasecurity/libbpfgo/helpers/rwArray.go
generated
vendored
Normal file
@ -0,0 +1,74 @@
|
||||
package helpers
|
||||
|
||||
import (
|
||||
"sync"
|
||||
)
|
||||
|
||||
type slot struct {
|
||||
value interface{}
|
||||
used bool
|
||||
}
|
||||
|
||||
// RWArray allows for multiple concurrent readers but
|
||||
// only a single writer. The writers lock a mutex while the readers
|
||||
// are lock free.
|
||||
// It is implemented as an array of slots where each slot holds a
|
||||
// value (of type interface{}) and a boolean marker to indicate if it's
|
||||
// in use or not. The insertion (Put) performs a linear probe
|
||||
// looking for an available slot as indicated by the in-use marker.
|
||||
// While probing, it is not touching the value itself, as it's
|
||||
// being read without a lock by the readers.
|
||||
type RWArray struct {
|
||||
slots []slot
|
||||
mux sync.Mutex
|
||||
}
|
||||
|
||||
func NewRWArray(capacity uint) RWArray {
|
||||
return RWArray{
|
||||
slots: make([]slot, capacity),
|
||||
}
|
||||
}
|
||||
|
||||
func (a *RWArray) Put(v interface{}) int {
|
||||
a.mux.Lock()
|
||||
defer a.mux.Unlock()
|
||||
|
||||
limit := len(a.slots)
|
||||
|
||||
for i := 0; i < limit; i++ {
|
||||
if !a.slots[i].used {
|
||||
a.slots[i].value = v
|
||||
a.slots[i].used = true
|
||||
return i
|
||||
}
|
||||
}
|
||||
|
||||
return -1
|
||||
}
|
||||
|
||||
func (a *RWArray) Remove(index uint) {
|
||||
a.mux.Lock()
|
||||
defer a.mux.Unlock()
|
||||
|
||||
if int(index) >= len(a.slots) {
|
||||
return
|
||||
}
|
||||
|
||||
a.slots[index].value = nil
|
||||
a.slots[index].used = false
|
||||
}
|
||||
|
||||
func (a *RWArray) Get(index uint) interface{} {
|
||||
if int(index) >= len(a.slots) {
|
||||
return nil
|
||||
}
|
||||
|
||||
// N.B. If slot[index].used == false, this is technically
|
||||
// a race since Put() might be putting the value in there
|
||||
// at the same time.
|
||||
return a.slots[index].value
|
||||
}
|
||||
|
||||
func (a *RWArray) Capacity() uint {
|
||||
return uint(len(a.slots))
|
||||
}
|
33
vendor/github.com/aquasecurity/libbpfgo/helpers/tracelisten.go
generated
vendored
Normal file
33
vendor/github.com/aquasecurity/libbpfgo/helpers/tracelisten.go
generated
vendored
Normal file
@ -0,0 +1,33 @@
|
||||
package helpers
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"os"
|
||||
)
|
||||
|
||||
// TracePipeListen reads data from the trace pipe that bpf_trace_printk() writes to,
|
||||
// (/sys/kernel/debug/tracing/trace_pipe).
|
||||
// It writes the data to stdout. The pipe is global, so this function is not
|
||||
// associated with any BPF program. It is recommended to use bpf_trace_printk()
|
||||
// and this function for debug purposes only.
|
||||
// This is a blocking function intended to be called from a goroutine.
|
||||
func TracePipeListen() error {
|
||||
f, err := os.Open("/sys/kernel/debug/tracing/trace_pipe")
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to open trace pipe: %v", err)
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
r := bufio.NewReader(f)
|
||||
b := make([]byte, 1024)
|
||||
for {
|
||||
len, err := r.Read(b)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to read from trace pipe: %v", err)
|
||||
}
|
||||
|
||||
s := string(b[:len])
|
||||
fmt.Println(s)
|
||||
}
|
||||
}
|
30
vendor/github.com/aquasecurity/libbpfgo/libbpf_cb.go
generated
vendored
Normal file
30
vendor/github.com/aquasecurity/libbpfgo/libbpf_cb.go
generated
vendored
Normal file
@ -0,0 +1,30 @@
|
||||
package libbpfgo
|
||||
|
||||
import (
|
||||
"C"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// This callback definition needs to be in a different file from where it is declared in C
|
||||
// Otherwise, multiple definition compilation error will occur
|
||||
|
||||
//export perfCallback
|
||||
func perfCallback(ctx unsafe.Pointer, cpu C.int, data unsafe.Pointer, size C.int) {
|
||||
pb := eventChannels.Get(uint(uintptr(ctx))).(*PerfBuffer)
|
||||
pb.eventsChan <- C.GoBytes(data, size)
|
||||
}
|
||||
|
||||
//export perfLostCallback
|
||||
func perfLostCallback(ctx unsafe.Pointer, cpu C.int, cnt C.ulonglong) {
|
||||
pb := eventChannels.Get(uint(uintptr(ctx))).(*PerfBuffer)
|
||||
if pb.lostChan != nil {
|
||||
pb.lostChan <- uint64(cnt)
|
||||
}
|
||||
}
|
||||
|
||||
//export ringbufferCallback
|
||||
func ringbufferCallback(ctx unsafe.Pointer, data unsafe.Pointer, size C.int) C.int {
|
||||
ch := eventChannels.Get(uint(uintptr(ctx))).(chan []byte)
|
||||
ch <- C.GoBytes(data, size)
|
||||
return C.int(0)
|
||||
}
|
1194
vendor/github.com/aquasecurity/libbpfgo/libbpfgo.go
generated
vendored
Normal file
1194
vendor/github.com/aquasecurity/libbpfgo/libbpfgo.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
3
vendor/golang.org/x/sys/unix/aliases.go
generated
vendored
3
vendor/golang.org/x/sys/unix/aliases.go
generated
vendored
@ -2,7 +2,8 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris
|
||||
//go:build (aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || zos) && go1.9
|
||||
// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris zos
|
||||
// +build go1.9
|
||||
|
||||
package unix
|
||||
|
3
vendor/golang.org/x/sys/unix/asm_aix_ppc64.s
generated
vendored
3
vendor/golang.org/x/sys/unix/asm_aix_ppc64.s
generated
vendored
@ -2,7 +2,8 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build !gccgo
|
||||
//go:build gc
|
||||
// +build gc
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
|
12
vendor/golang.org/x/sys/unix/asm_darwin_386.s → vendor/golang.org/x/sys/unix/asm_bsd_386.s
generated
vendored
12
vendor/golang.org/x/sys/unix/asm_darwin_386.s → vendor/golang.org/x/sys/unix/asm_bsd_386.s
generated
vendored
@ -1,14 +1,14 @@
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Copyright 2021 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build !gccgo
|
||||
//go:build (darwin || freebsd || netbsd || openbsd) && gc
|
||||
// +build darwin freebsd netbsd openbsd
|
||||
// +build gc
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
//
|
||||
// System call support for 386, Darwin
|
||||
//
|
||||
// System call support for 386 BSD
|
||||
|
||||
// Just jump to package syscall's implementation for all these functions.
|
||||
// The runtime may know about them.
|
||||
@ -22,7 +22,7 @@ TEXT ·Syscall6(SB),NOSPLIT,$0-40
|
||||
TEXT ·Syscall9(SB),NOSPLIT,$0-52
|
||||
JMP syscall·Syscall9(SB)
|
||||
|
||||
TEXT ·RawSyscall(SB),NOSPLIT,$0-28
|
||||
TEXT ·RawSyscall(SB),NOSPLIT,$0-28
|
||||
JMP syscall·RawSyscall(SB)
|
||||
|
||||
TEXT ·RawSyscall6(SB),NOSPLIT,$0-40
|
10
vendor/golang.org/x/sys/unix/asm_darwin_amd64.s → vendor/golang.org/x/sys/unix/asm_bsd_amd64.s
generated
vendored
10
vendor/golang.org/x/sys/unix/asm_darwin_amd64.s → vendor/golang.org/x/sys/unix/asm_bsd_amd64.s
generated
vendored
@ -1,14 +1,14 @@
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Copyright 2021 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build !gccgo
|
||||
//go:build (darwin || dragonfly || freebsd || netbsd || openbsd) && gc
|
||||
// +build darwin dragonfly freebsd netbsd openbsd
|
||||
// +build gc
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
//
|
||||
// System call support for AMD64, Darwin
|
||||
//
|
||||
// System call support for AMD64 BSD
|
||||
|
||||
// Just jump to package syscall's implementation for all these functions.
|
||||
// The runtime may know about them.
|
10
vendor/golang.org/x/sys/unix/asm_netbsd_arm.s → vendor/golang.org/x/sys/unix/asm_bsd_arm.s
generated
vendored
10
vendor/golang.org/x/sys/unix/asm_netbsd_arm.s → vendor/golang.org/x/sys/unix/asm_bsd_arm.s
generated
vendored
@ -1,14 +1,14 @@
|
||||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Copyright 2021 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build !gccgo
|
||||
//go:build (darwin || freebsd || netbsd || openbsd) && gc
|
||||
// +build darwin freebsd netbsd openbsd
|
||||
// +build gc
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
//
|
||||
// System call support for ARM, NetBSD
|
||||
//
|
||||
// System call support for ARM BSD
|
||||
|
||||
// Just jump to package syscall's implementation for all these functions.
|
||||
// The runtime may know about them.
|
10
vendor/golang.org/x/sys/unix/asm_netbsd_amd64.s → vendor/golang.org/x/sys/unix/asm_bsd_arm64.s
generated
vendored
10
vendor/golang.org/x/sys/unix/asm_netbsd_amd64.s → vendor/golang.org/x/sys/unix/asm_bsd_arm64.s
generated
vendored
@ -1,14 +1,14 @@
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Copyright 2021 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build !gccgo
|
||||
//go:build (darwin || freebsd || netbsd || openbsd) && gc
|
||||
// +build darwin freebsd netbsd openbsd
|
||||
// +build gc
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
//
|
||||
// System call support for AMD64, NetBSD
|
||||
//
|
||||
// System call support for ARM64 BSD
|
||||
|
||||
// Just jump to package syscall's implementation for all these functions.
|
||||
// The runtime may know about them.
|
30
vendor/golang.org/x/sys/unix/asm_darwin_arm.s
generated
vendored
30
vendor/golang.org/x/sys/unix/asm_darwin_arm.s
generated
vendored
@ -1,30 +0,0 @@
|
||||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build !gccgo
|
||||
// +build arm,darwin
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
//
|
||||
// System call support for ARM, Darwin
|
||||
//
|
||||
|
||||
// Just jump to package syscall's implementation for all these functions.
|
||||
// The runtime may know about them.
|
||||
|
||||
TEXT ·Syscall(SB),NOSPLIT,$0-28
|
||||
B syscall·Syscall(SB)
|
||||
|
||||
TEXT ·Syscall6(SB),NOSPLIT,$0-40
|
||||
B syscall·Syscall6(SB)
|
||||
|
||||
TEXT ·Syscall9(SB),NOSPLIT,$0-52
|
||||
B syscall·Syscall9(SB)
|
||||
|
||||
TEXT ·RawSyscall(SB),NOSPLIT,$0-28
|
||||
B syscall·RawSyscall(SB)
|
||||
|
||||
TEXT ·RawSyscall6(SB),NOSPLIT,$0-40
|
||||
B syscall·RawSyscall6(SB)
|
30
vendor/golang.org/x/sys/unix/asm_darwin_arm64.s
generated
vendored
30
vendor/golang.org/x/sys/unix/asm_darwin_arm64.s
generated
vendored
@ -1,30 +0,0 @@
|
||||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build !gccgo
|
||||
// +build arm64,darwin
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
//
|
||||
// System call support for AMD64, Darwin
|
||||
//
|
||||
|
||||
// Just jump to package syscall's implementation for all these functions.
|
||||
// The runtime may know about them.
|
||||
|
||||
TEXT ·Syscall(SB),NOSPLIT,$0-56
|
||||
B syscall·Syscall(SB)
|
||||
|
||||
TEXT ·Syscall6(SB),NOSPLIT,$0-80
|
||||
B syscall·Syscall6(SB)
|
||||
|
||||
TEXT ·Syscall9(SB),NOSPLIT,$0-104
|
||||
B syscall·Syscall9(SB)
|
||||
|
||||
TEXT ·RawSyscall(SB),NOSPLIT,$0-56
|
||||
B syscall·RawSyscall(SB)
|
||||
|
||||
TEXT ·RawSyscall6(SB),NOSPLIT,$0-80
|
||||
B syscall·RawSyscall6(SB)
|
29
vendor/golang.org/x/sys/unix/asm_dragonfly_amd64.s
generated
vendored
29
vendor/golang.org/x/sys/unix/asm_dragonfly_amd64.s
generated
vendored
@ -1,29 +0,0 @@
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build !gccgo
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
//
|
||||
// System call support for AMD64, DragonFly
|
||||
//
|
||||
|
||||
// Just jump to package syscall's implementation for all these functions.
|
||||
// The runtime may know about them.
|
||||
|
||||
TEXT ·Syscall(SB),NOSPLIT,$0-56
|
||||
JMP syscall·Syscall(SB)
|
||||
|
||||
TEXT ·Syscall6(SB),NOSPLIT,$0-80
|
||||
JMP syscall·Syscall6(SB)
|
||||
|
||||
TEXT ·Syscall9(SB),NOSPLIT,$0-104
|
||||
JMP syscall·Syscall9(SB)
|
||||
|
||||
TEXT ·RawSyscall(SB),NOSPLIT,$0-56
|
||||
JMP syscall·RawSyscall(SB)
|
||||
|
||||
TEXT ·RawSyscall6(SB),NOSPLIT,$0-80
|
||||
JMP syscall·RawSyscall6(SB)
|
29
vendor/golang.org/x/sys/unix/asm_freebsd_386.s
generated
vendored
29
vendor/golang.org/x/sys/unix/asm_freebsd_386.s
generated
vendored
@ -1,29 +0,0 @@
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build !gccgo
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
//
|
||||
// System call support for 386, FreeBSD
|
||||
//
|
||||
|
||||
// Just jump to package syscall's implementation for all these functions.
|
||||
// The runtime may know about them.
|
||||
|
||||
TEXT ·Syscall(SB),NOSPLIT,$0-28
|
||||
JMP syscall·Syscall(SB)
|
||||
|
||||
TEXT ·Syscall6(SB),NOSPLIT,$0-40
|
||||
JMP syscall·Syscall6(SB)
|
||||
|
||||
TEXT ·Syscall9(SB),NOSPLIT,$0-52
|
||||
JMP syscall·Syscall9(SB)
|
||||
|
||||
TEXT ·RawSyscall(SB),NOSPLIT,$0-28
|
||||
JMP syscall·RawSyscall(SB)
|
||||
|
||||
TEXT ·RawSyscall6(SB),NOSPLIT,$0-40
|
||||
JMP syscall·RawSyscall6(SB)
|
29
vendor/golang.org/x/sys/unix/asm_freebsd_amd64.s
generated
vendored
29
vendor/golang.org/x/sys/unix/asm_freebsd_amd64.s
generated
vendored
@ -1,29 +0,0 @@
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build !gccgo
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
//
|
||||
// System call support for AMD64, FreeBSD
|
||||
//
|
||||
|
||||
// Just jump to package syscall's implementation for all these functions.
|
||||
// The runtime may know about them.
|
||||
|
||||
TEXT ·Syscall(SB),NOSPLIT,$0-56
|
||||
JMP syscall·Syscall(SB)
|
||||
|
||||
TEXT ·Syscall6(SB),NOSPLIT,$0-80
|
||||
JMP syscall·Syscall6(SB)
|
||||
|
||||
TEXT ·Syscall9(SB),NOSPLIT,$0-104
|
||||
JMP syscall·Syscall9(SB)
|
||||
|
||||
TEXT ·RawSyscall(SB),NOSPLIT,$0-56
|
||||
JMP syscall·RawSyscall(SB)
|
||||
|
||||
TEXT ·RawSyscall6(SB),NOSPLIT,$0-80
|
||||
JMP syscall·RawSyscall6(SB)
|
29
vendor/golang.org/x/sys/unix/asm_freebsd_arm.s
generated
vendored
29
vendor/golang.org/x/sys/unix/asm_freebsd_arm.s
generated
vendored
@ -1,29 +0,0 @@
|
||||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build !gccgo
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
//
|
||||
// System call support for ARM, FreeBSD
|
||||
//
|
||||
|
||||
// Just jump to package syscall's implementation for all these functions.
|
||||
// The runtime may know about them.
|
||||
|
||||
TEXT ·Syscall(SB),NOSPLIT,$0-28
|
||||
B syscall·Syscall(SB)
|
||||
|
||||
TEXT ·Syscall6(SB),NOSPLIT,$0-40
|
||||
B syscall·Syscall6(SB)
|
||||
|
||||
TEXT ·Syscall9(SB),NOSPLIT,$0-52
|
||||
B syscall·Syscall9(SB)
|
||||
|
||||
TEXT ·RawSyscall(SB),NOSPLIT,$0-28
|
||||
B syscall·RawSyscall(SB)
|
||||
|
||||
TEXT ·RawSyscall6(SB),NOSPLIT,$0-40
|
||||
B syscall·RawSyscall6(SB)
|
29
vendor/golang.org/x/sys/unix/asm_freebsd_arm64.s
generated
vendored
29
vendor/golang.org/x/sys/unix/asm_freebsd_arm64.s
generated
vendored
@ -1,29 +0,0 @@
|
||||
// Copyright 2018 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build !gccgo
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
//
|
||||
// System call support for ARM64, FreeBSD
|
||||
//
|
||||
|
||||
// Just jump to package syscall's implementation for all these functions.
|
||||
// The runtime may know about them.
|
||||
|
||||
TEXT ·Syscall(SB),NOSPLIT,$0-56
|
||||
JMP syscall·Syscall(SB)
|
||||
|
||||
TEXT ·Syscall6(SB),NOSPLIT,$0-80
|
||||
JMP syscall·Syscall6(SB)
|
||||
|
||||
TEXT ·Syscall9(SB),NOSPLIT,$0-104
|
||||
JMP syscall·Syscall9(SB)
|
||||
|
||||
TEXT ·RawSyscall(SB),NOSPLIT,$0-56
|
||||
JMP syscall·RawSyscall(SB)
|
||||
|
||||
TEXT ·RawSyscall6(SB),NOSPLIT,$0-80
|
||||
JMP syscall·RawSyscall6(SB)
|
3
vendor/golang.org/x/sys/unix/asm_linux_386.s
generated
vendored
3
vendor/golang.org/x/sys/unix/asm_linux_386.s
generated
vendored
@ -2,7 +2,8 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build !gccgo
|
||||
//go:build gc
|
||||
// +build gc
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
|
3
vendor/golang.org/x/sys/unix/asm_linux_amd64.s
generated
vendored
3
vendor/golang.org/x/sys/unix/asm_linux_amd64.s
generated
vendored
@ -2,7 +2,8 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build !gccgo
|
||||
//go:build gc
|
||||
// +build gc
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
|
3
vendor/golang.org/x/sys/unix/asm_linux_arm.s
generated
vendored
3
vendor/golang.org/x/sys/unix/asm_linux_arm.s
generated
vendored
@ -2,7 +2,8 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build !gccgo
|
||||
//go:build gc
|
||||
// +build gc
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
|
3
vendor/golang.org/x/sys/unix/asm_linux_arm64.s
generated
vendored
3
vendor/golang.org/x/sys/unix/asm_linux_arm64.s
generated
vendored
@ -2,9 +2,10 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build linux && arm64 && gc
|
||||
// +build linux
|
||||
// +build arm64
|
||||
// +build !gccgo
|
||||
// +build gc
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
|
3
vendor/golang.org/x/sys/unix/asm_linux_mips64x.s
generated
vendored
3
vendor/golang.org/x/sys/unix/asm_linux_mips64x.s
generated
vendored
@ -2,9 +2,10 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build linux && (mips64 || mips64le) && gc
|
||||
// +build linux
|
||||
// +build mips64 mips64le
|
||||
// +build !gccgo
|
||||
// +build gc
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
|
3
vendor/golang.org/x/sys/unix/asm_linux_mipsx.s
generated
vendored
3
vendor/golang.org/x/sys/unix/asm_linux_mipsx.s
generated
vendored
@ -2,9 +2,10 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build linux && (mips || mipsle) && gc
|
||||
// +build linux
|
||||
// +build mips mipsle
|
||||
// +build !gccgo
|
||||
// +build gc
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
|
3
vendor/golang.org/x/sys/unix/asm_linux_ppc64x.s
generated
vendored
3
vendor/golang.org/x/sys/unix/asm_linux_ppc64x.s
generated
vendored
@ -2,9 +2,10 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build linux && (ppc64 || ppc64le) && gc
|
||||
// +build linux
|
||||
// +build ppc64 ppc64le
|
||||
// +build !gccgo
|
||||
// +build gc
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
|
4
vendor/golang.org/x/sys/unix/asm_linux_riscv64.s
generated
vendored
4
vendor/golang.org/x/sys/unix/asm_linux_riscv64.s
generated
vendored
@ -2,7 +2,9 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build riscv64,!gccgo
|
||||
//go:build riscv64 && gc
|
||||
// +build riscv64
|
||||
// +build gc
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
|
5
vendor/golang.org/x/sys/unix/asm_linux_s390x.s
generated
vendored
5
vendor/golang.org/x/sys/unix/asm_linux_s390x.s
generated
vendored
@ -2,9 +2,10 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build s390x
|
||||
//go:build linux && s390x && gc
|
||||
// +build linux
|
||||
// +build !gccgo
|
||||
// +build s390x
|
||||
// +build gc
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
|
29
vendor/golang.org/x/sys/unix/asm_netbsd_386.s
generated
vendored
29
vendor/golang.org/x/sys/unix/asm_netbsd_386.s
generated
vendored
@ -1,29 +0,0 @@
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build !gccgo
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
//
|
||||
// System call support for 386, NetBSD
|
||||
//
|
||||
|
||||
// Just jump to package syscall's implementation for all these functions.
|
||||
// The runtime may know about them.
|
||||
|
||||
TEXT ·Syscall(SB),NOSPLIT,$0-28
|
||||
JMP syscall·Syscall(SB)
|
||||
|
||||
TEXT ·Syscall6(SB),NOSPLIT,$0-40
|
||||
JMP syscall·Syscall6(SB)
|
||||
|
||||
TEXT ·Syscall9(SB),NOSPLIT,$0-52
|
||||
JMP syscall·Syscall9(SB)
|
||||
|
||||
TEXT ·RawSyscall(SB),NOSPLIT,$0-28
|
||||
JMP syscall·RawSyscall(SB)
|
||||
|
||||
TEXT ·RawSyscall6(SB),NOSPLIT,$0-40
|
||||
JMP syscall·RawSyscall6(SB)
|
29
vendor/golang.org/x/sys/unix/asm_netbsd_arm64.s
generated
vendored
29
vendor/golang.org/x/sys/unix/asm_netbsd_arm64.s
generated
vendored
@ -1,29 +0,0 @@
|
||||
// Copyright 2019 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build !gccgo
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
//
|
||||
// System call support for ARM64, NetBSD
|
||||
//
|
||||
|
||||
// Just jump to package syscall's implementation for all these functions.
|
||||
// The runtime may know about them.
|
||||
|
||||
TEXT ·Syscall(SB),NOSPLIT,$0-56
|
||||
B syscall·Syscall(SB)
|
||||
|
||||
TEXT ·Syscall6(SB),NOSPLIT,$0-80
|
||||
B syscall·Syscall6(SB)
|
||||
|
||||
TEXT ·Syscall9(SB),NOSPLIT,$0-104
|
||||
B syscall·Syscall9(SB)
|
||||
|
||||
TEXT ·RawSyscall(SB),NOSPLIT,$0-56
|
||||
B syscall·RawSyscall(SB)
|
||||
|
||||
TEXT ·RawSyscall6(SB),NOSPLIT,$0-80
|
||||
B syscall·RawSyscall6(SB)
|
29
vendor/golang.org/x/sys/unix/asm_openbsd_386.s
generated
vendored
29
vendor/golang.org/x/sys/unix/asm_openbsd_386.s
generated
vendored
@ -1,29 +0,0 @@
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build !gccgo
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
//
|
||||
// System call support for 386, OpenBSD
|
||||
//
|
||||
|
||||
// Just jump to package syscall's implementation for all these functions.
|
||||
// The runtime may know about them.
|
||||
|
||||
TEXT ·Syscall(SB),NOSPLIT,$0-28
|
||||
JMP syscall·Syscall(SB)
|
||||
|
||||
TEXT ·Syscall6(SB),NOSPLIT,$0-40
|
||||
JMP syscall·Syscall6(SB)
|
||||
|
||||
TEXT ·Syscall9(SB),NOSPLIT,$0-52
|
||||
JMP syscall·Syscall9(SB)
|
||||
|
||||
TEXT ·RawSyscall(SB),NOSPLIT,$0-28
|
||||
JMP syscall·RawSyscall(SB)
|
||||
|
||||
TEXT ·RawSyscall6(SB),NOSPLIT,$0-40
|
||||
JMP syscall·RawSyscall6(SB)
|
29
vendor/golang.org/x/sys/unix/asm_openbsd_amd64.s
generated
vendored
29
vendor/golang.org/x/sys/unix/asm_openbsd_amd64.s
generated
vendored
@ -1,29 +0,0 @@
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build !gccgo
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
//
|
||||
// System call support for AMD64, OpenBSD
|
||||
//
|
||||
|
||||
// Just jump to package syscall's implementation for all these functions.
|
||||
// The runtime may know about them.
|
||||
|
||||
TEXT ·Syscall(SB),NOSPLIT,$0-56
|
||||
JMP syscall·Syscall(SB)
|
||||
|
||||
TEXT ·Syscall6(SB),NOSPLIT,$0-80
|
||||
JMP syscall·Syscall6(SB)
|
||||
|
||||
TEXT ·Syscall9(SB),NOSPLIT,$0-104
|
||||
JMP syscall·Syscall9(SB)
|
||||
|
||||
TEXT ·RawSyscall(SB),NOSPLIT,$0-56
|
||||
JMP syscall·RawSyscall(SB)
|
||||
|
||||
TEXT ·RawSyscall6(SB),NOSPLIT,$0-80
|
||||
JMP syscall·RawSyscall6(SB)
|
29
vendor/golang.org/x/sys/unix/asm_openbsd_arm.s
generated
vendored
29
vendor/golang.org/x/sys/unix/asm_openbsd_arm.s
generated
vendored
@ -1,29 +0,0 @@
|
||||
// Copyright 2017 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build !gccgo
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
//
|
||||
// System call support for ARM, OpenBSD
|
||||
//
|
||||
|
||||
// Just jump to package syscall's implementation for all these functions.
|
||||
// The runtime may know about them.
|
||||
|
||||
TEXT ·Syscall(SB),NOSPLIT,$0-28
|
||||
B syscall·Syscall(SB)
|
||||
|
||||
TEXT ·Syscall6(SB),NOSPLIT,$0-40
|
||||
B syscall·Syscall6(SB)
|
||||
|
||||
TEXT ·Syscall9(SB),NOSPLIT,$0-52
|
||||
B syscall·Syscall9(SB)
|
||||
|
||||
TEXT ·RawSyscall(SB),NOSPLIT,$0-28
|
||||
B syscall·RawSyscall(SB)
|
||||
|
||||
TEXT ·RawSyscall6(SB),NOSPLIT,$0-40
|
||||
B syscall·RawSyscall6(SB)
|
5
vendor/golang.org/x/sys/unix/asm_openbsd_arm64.s → vendor/golang.org/x/sys/unix/asm_openbsd_mips64.s
generated
vendored
5
vendor/golang.org/x/sys/unix/asm_openbsd_arm64.s → vendor/golang.org/x/sys/unix/asm_openbsd_mips64.s
generated
vendored
@ -2,12 +2,13 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build !gccgo
|
||||
//go:build gc
|
||||
// +build gc
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
//
|
||||
// System call support for arm64, OpenBSD
|
||||
// System call support for mips64, OpenBSD
|
||||
//
|
||||
|
||||
// Just jump to package syscall's implementation for all these functions.
|
3
vendor/golang.org/x/sys/unix/asm_solaris_amd64.s
generated
vendored
3
vendor/golang.org/x/sys/unix/asm_solaris_amd64.s
generated
vendored
@ -2,7 +2,8 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build !gccgo
|
||||
//go:build gc
|
||||
// +build gc
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
|
426
vendor/golang.org/x/sys/unix/asm_zos_s390x.s
generated
vendored
Normal file
426
vendor/golang.org/x/sys/unix/asm_zos_s390x.s
generated
vendored
Normal file
@ -0,0 +1,426 @@
|
||||
// Copyright 2020 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build zos && s390x && gc
|
||||
// +build zos
|
||||
// +build s390x
|
||||
// +build gc
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
#define PSALAA 1208(R0)
|
||||
#define GTAB64(x) 80(x)
|
||||
#define LCA64(x) 88(x)
|
||||
#define CAA(x) 8(x)
|
||||
#define EDCHPXV(x) 1016(x) // in the CAA
|
||||
#define SAVSTACK_ASYNC(x) 336(x) // in the LCA
|
||||
|
||||
// SS_*, where x=SAVSTACK_ASYNC
|
||||
#define SS_LE(x) 0(x)
|
||||
#define SS_GO(x) 8(x)
|
||||
#define SS_ERRNO(x) 16(x)
|
||||
#define SS_ERRNOJR(x) 20(x)
|
||||
|
||||
#define LE_CALL BYTE $0x0D; BYTE $0x76; // BL R7, R6
|
||||
|
||||
TEXT ·clearErrno(SB),NOSPLIT,$0-0
|
||||
BL addrerrno<>(SB)
|
||||
MOVD $0, 0(R3)
|
||||
RET
|
||||
|
||||
// Returns the address of errno in R3.
|
||||
TEXT addrerrno<>(SB),NOSPLIT|NOFRAME,$0-0
|
||||
// Get library control area (LCA).
|
||||
MOVW PSALAA, R8
|
||||
MOVD LCA64(R8), R8
|
||||
|
||||
// Get __errno FuncDesc.
|
||||
MOVD CAA(R8), R9
|
||||
MOVD EDCHPXV(R9), R9
|
||||
ADD $(0x156*16), R9
|
||||
LMG 0(R9), R5, R6
|
||||
|
||||
// Switch to saved LE stack.
|
||||
MOVD SAVSTACK_ASYNC(R8), R9
|
||||
MOVD 0(R9), R4
|
||||
MOVD $0, 0(R9)
|
||||
|
||||
// Call __errno function.
|
||||
LE_CALL
|
||||
NOPH
|
||||
|
||||
// Switch back to Go stack.
|
||||
XOR R0, R0 // Restore R0 to $0.
|
||||
MOVD R4, 0(R9) // Save stack pointer.
|
||||
RET
|
||||
|
||||
TEXT ·syscall_syscall(SB),NOSPLIT,$0-56
|
||||
BL runtime·entersyscall(SB)
|
||||
MOVD a1+8(FP), R1
|
||||
MOVD a2+16(FP), R2
|
||||
MOVD a3+24(FP), R3
|
||||
|
||||
// Get library control area (LCA).
|
||||
MOVW PSALAA, R8
|
||||
MOVD LCA64(R8), R8
|
||||
|
||||
// Get function.
|
||||
MOVD CAA(R8), R9
|
||||
MOVD EDCHPXV(R9), R9
|
||||
MOVD trap+0(FP), R5
|
||||
SLD $4, R5
|
||||
ADD R5, R9
|
||||
LMG 0(R9), R5, R6
|
||||
|
||||
// Restore LE stack.
|
||||
MOVD SAVSTACK_ASYNC(R8), R9
|
||||
MOVD 0(R9), R4
|
||||
MOVD $0, 0(R9)
|
||||
|
||||
// Call function.
|
||||
LE_CALL
|
||||
NOPH
|
||||
XOR R0, R0 // Restore R0 to $0.
|
||||
MOVD R4, 0(R9) // Save stack pointer.
|
||||
|
||||
MOVD R3, r1+32(FP)
|
||||
MOVD R0, r2+40(FP)
|
||||
MOVD R0, err+48(FP)
|
||||
MOVW R3, R4
|
||||
CMP R4, $-1
|
||||
BNE done
|
||||
BL addrerrno<>(SB)
|
||||
MOVWZ 0(R3), R3
|
||||
MOVD R3, err+48(FP)
|
||||
done:
|
||||
BL runtime·exitsyscall(SB)
|
||||
RET
|
||||
|
||||
TEXT ·syscall_rawsyscall(SB),NOSPLIT,$0-56
|
||||
MOVD a1+8(FP), R1
|
||||
MOVD a2+16(FP), R2
|
||||
MOVD a3+24(FP), R3
|
||||
|
||||
// Get library control area (LCA).
|
||||
MOVW PSALAA, R8
|
||||
MOVD LCA64(R8), R8
|
||||
|
||||
// Get function.
|
||||
MOVD CAA(R8), R9
|
||||
MOVD EDCHPXV(R9), R9
|
||||
MOVD trap+0(FP), R5
|
||||
SLD $4, R5
|
||||
ADD R5, R9
|
||||
LMG 0(R9), R5, R6
|
||||
|
||||
// Restore LE stack.
|
||||
MOVD SAVSTACK_ASYNC(R8), R9
|
||||
MOVD 0(R9), R4
|
||||
MOVD $0, 0(R9)
|
||||
|
||||
// Call function.
|
||||
LE_CALL
|
||||
NOPH
|
||||
XOR R0, R0 // Restore R0 to $0.
|
||||
MOVD R4, 0(R9) // Save stack pointer.
|
||||
|
||||
MOVD R3, r1+32(FP)
|
||||
MOVD R0, r2+40(FP)
|
||||
MOVD R0, err+48(FP)
|
||||
MOVW R3, R4
|
||||
CMP R4, $-1
|
||||
BNE done
|
||||
BL addrerrno<>(SB)
|
||||
MOVWZ 0(R3), R3
|
||||
MOVD R3, err+48(FP)
|
||||
done:
|
||||
RET
|
||||
|
||||
TEXT ·syscall_syscall6(SB),NOSPLIT,$0-80
|
||||
BL runtime·entersyscall(SB)
|
||||
MOVD a1+8(FP), R1
|
||||
MOVD a2+16(FP), R2
|
||||
MOVD a3+24(FP), R3
|
||||
|
||||
// Get library control area (LCA).
|
||||
MOVW PSALAA, R8
|
||||
MOVD LCA64(R8), R8
|
||||
|
||||
// Get function.
|
||||
MOVD CAA(R8), R9
|
||||
MOVD EDCHPXV(R9), R9
|
||||
MOVD trap+0(FP), R5
|
||||
SLD $4, R5
|
||||
ADD R5, R9
|
||||
LMG 0(R9), R5, R6
|
||||
|
||||
// Restore LE stack.
|
||||
MOVD SAVSTACK_ASYNC(R8), R9
|
||||
MOVD 0(R9), R4
|
||||
MOVD $0, 0(R9)
|
||||
|
||||
// Fill in parameter list.
|
||||
MOVD a4+32(FP), R12
|
||||
MOVD R12, (2176+24)(R4)
|
||||
MOVD a5+40(FP), R12
|
||||
MOVD R12, (2176+32)(R4)
|
||||
MOVD a6+48(FP), R12
|
||||
MOVD R12, (2176+40)(R4)
|
||||
|
||||
// Call function.
|
||||
LE_CALL
|
||||
NOPH
|
||||
XOR R0, R0 // Restore R0 to $0.
|
||||
MOVD R4, 0(R9) // Save stack pointer.
|
||||
|
||||
MOVD R3, r1+56(FP)
|
||||
MOVD R0, r2+64(FP)
|
||||
MOVD R0, err+72(FP)
|
||||
MOVW R3, R4
|
||||
CMP R4, $-1
|
||||
BNE done
|
||||
BL addrerrno<>(SB)
|
||||
MOVWZ 0(R3), R3
|
||||
MOVD R3, err+72(FP)
|
||||
done:
|
||||
BL runtime·exitsyscall(SB)
|
||||
RET
|
||||
|
||||
TEXT ·syscall_rawsyscall6(SB),NOSPLIT,$0-80
|
||||
MOVD a1+8(FP), R1
|
||||
MOVD a2+16(FP), R2
|
||||
MOVD a3+24(FP), R3
|
||||
|
||||
// Get library control area (LCA).
|
||||
MOVW PSALAA, R8
|
||||
MOVD LCA64(R8), R8
|
||||
|
||||
// Get function.
|
||||
MOVD CAA(R8), R9
|
||||
MOVD EDCHPXV(R9), R9
|
||||
MOVD trap+0(FP), R5
|
||||
SLD $4, R5
|
||||
ADD R5, R9
|
||||
LMG 0(R9), R5, R6
|
||||
|
||||
// Restore LE stack.
|
||||
MOVD SAVSTACK_ASYNC(R8), R9
|
||||
MOVD 0(R9), R4
|
||||
MOVD $0, 0(R9)
|
||||
|
||||
// Fill in parameter list.
|
||||
MOVD a4+32(FP), R12
|
||||
MOVD R12, (2176+24)(R4)
|
||||
MOVD a5+40(FP), R12
|
||||
MOVD R12, (2176+32)(R4)
|
||||
MOVD a6+48(FP), R12
|
||||
MOVD R12, (2176+40)(R4)
|
||||
|
||||
// Call function.
|
||||
LE_CALL
|
||||
NOPH
|
||||
XOR R0, R0 // Restore R0 to $0.
|
||||
MOVD R4, 0(R9) // Save stack pointer.
|
||||
|
||||
MOVD R3, r1+56(FP)
|
||||
MOVD R0, r2+64(FP)
|
||||
MOVD R0, err+72(FP)
|
||||
MOVW R3, R4
|
||||
CMP R4, $-1
|
||||
BNE done
|
||||
BL ·rrno<>(SB)
|
||||
MOVWZ 0(R3), R3
|
||||
MOVD R3, err+72(FP)
|
||||
done:
|
||||
RET
|
||||
|
||||
TEXT ·syscall_syscall9(SB),NOSPLIT,$0
|
||||
BL runtime·entersyscall(SB)
|
||||
MOVD a1+8(FP), R1
|
||||
MOVD a2+16(FP), R2
|
||||
MOVD a3+24(FP), R3
|
||||
|
||||
// Get library control area (LCA).
|
||||
MOVW PSALAA, R8
|
||||
MOVD LCA64(R8), R8
|
||||
|
||||
// Get function.
|
||||
MOVD CAA(R8), R9
|
||||
MOVD EDCHPXV(R9), R9
|
||||
MOVD trap+0(FP), R5
|
||||
SLD $4, R5
|
||||
ADD R5, R9
|
||||
LMG 0(R9), R5, R6
|
||||
|
||||
// Restore LE stack.
|
||||
MOVD SAVSTACK_ASYNC(R8), R9
|
||||
MOVD 0(R9), R4
|
||||
MOVD $0, 0(R9)
|
||||
|
||||
// Fill in parameter list.
|
||||
MOVD a4+32(FP), R12
|
||||
MOVD R12, (2176+24)(R4)
|
||||
MOVD a5+40(FP), R12
|
||||
MOVD R12, (2176+32)(R4)
|
||||
MOVD a6+48(FP), R12
|
||||
MOVD R12, (2176+40)(R4)
|
||||
MOVD a7+56(FP), R12
|
||||
MOVD R12, (2176+48)(R4)
|
||||
MOVD a8+64(FP), R12
|
||||
MOVD R12, (2176+56)(R4)
|
||||
MOVD a9+72(FP), R12
|
||||
MOVD R12, (2176+64)(R4)
|
||||
|
||||
// Call function.
|
||||
LE_CALL
|
||||
NOPH
|
||||
XOR R0, R0 // Restore R0 to $0.
|
||||
MOVD R4, 0(R9) // Save stack pointer.
|
||||
|
||||
MOVD R3, r1+80(FP)
|
||||
MOVD R0, r2+88(FP)
|
||||
MOVD R0, err+96(FP)
|
||||
MOVW R3, R4
|
||||
CMP R4, $-1
|
||||
BNE done
|
||||
BL addrerrno<>(SB)
|
||||
MOVWZ 0(R3), R3
|
||||
MOVD R3, err+96(FP)
|
||||
done:
|
||||
BL runtime·exitsyscall(SB)
|
||||
RET
|
||||
|
||||
TEXT ·syscall_rawsyscall9(SB),NOSPLIT,$0
|
||||
MOVD a1+8(FP), R1
|
||||
MOVD a2+16(FP), R2
|
||||
MOVD a3+24(FP), R3
|
||||
|
||||
// Get library control area (LCA).
|
||||
MOVW PSALAA, R8
|
||||
MOVD LCA64(R8), R8
|
||||
|
||||
// Get function.
|
||||
MOVD CAA(R8), R9
|
||||
MOVD EDCHPXV(R9), R9
|
||||
MOVD trap+0(FP), R5
|
||||
SLD $4, R5
|
||||
ADD R5, R9
|
||||
LMG 0(R9), R5, R6
|
||||
|
||||
// Restore LE stack.
|
||||
MOVD SAVSTACK_ASYNC(R8), R9
|
||||
MOVD 0(R9), R4
|
||||
MOVD $0, 0(R9)
|
||||
|
||||
// Fill in parameter list.
|
||||
MOVD a4+32(FP), R12
|
||||
MOVD R12, (2176+24)(R4)
|
||||
MOVD a5+40(FP), R12
|
||||
MOVD R12, (2176+32)(R4)
|
||||
MOVD a6+48(FP), R12
|
||||
MOVD R12, (2176+40)(R4)
|
||||
MOVD a7+56(FP), R12
|
||||
MOVD R12, (2176+48)(R4)
|
||||
MOVD a8+64(FP), R12
|
||||
MOVD R12, (2176+56)(R4)
|
||||
MOVD a9+72(FP), R12
|
||||
MOVD R12, (2176+64)(R4)
|
||||
|
||||
// Call function.
|
||||
LE_CALL
|
||||
NOPH
|
||||
XOR R0, R0 // Restore R0 to $0.
|
||||
MOVD R4, 0(R9) // Save stack pointer.
|
||||
|
||||
MOVD R3, r1+80(FP)
|
||||
MOVD R0, r2+88(FP)
|
||||
MOVD R0, err+96(FP)
|
||||
MOVW R3, R4
|
||||
CMP R4, $-1
|
||||
BNE done
|
||||
BL addrerrno<>(SB)
|
||||
MOVWZ 0(R3), R3
|
||||
MOVD R3, err+96(FP)
|
||||
done:
|
||||
RET
|
||||
|
||||
// func svcCall(fnptr unsafe.Pointer, argv *unsafe.Pointer, dsa *uint64)
|
||||
TEXT ·svcCall(SB),NOSPLIT,$0
|
||||
BL runtime·save_g(SB) // Save g and stack pointer
|
||||
MOVW PSALAA, R8
|
||||
MOVD LCA64(R8), R8
|
||||
MOVD SAVSTACK_ASYNC(R8), R9
|
||||
MOVD R15, 0(R9)
|
||||
|
||||
MOVD argv+8(FP), R1 // Move function arguments into registers
|
||||
MOVD dsa+16(FP), g
|
||||
MOVD fnptr+0(FP), R15
|
||||
|
||||
BYTE $0x0D // Branch to function
|
||||
BYTE $0xEF
|
||||
|
||||
BL runtime·load_g(SB) // Restore g and stack pointer
|
||||
MOVW PSALAA, R8
|
||||
MOVD LCA64(R8), R8
|
||||
MOVD SAVSTACK_ASYNC(R8), R9
|
||||
MOVD 0(R9), R15
|
||||
|
||||
RET
|
||||
|
||||
// func svcLoad(name *byte) unsafe.Pointer
|
||||
TEXT ·svcLoad(SB),NOSPLIT,$0
|
||||
MOVD R15, R2 // Save go stack pointer
|
||||
MOVD name+0(FP), R0 // Move SVC args into registers
|
||||
MOVD $0x80000000, R1
|
||||
MOVD $0, R15
|
||||
BYTE $0x0A // SVC 08 LOAD
|
||||
BYTE $0x08
|
||||
MOVW R15, R3 // Save return code from SVC
|
||||
MOVD R2, R15 // Restore go stack pointer
|
||||
CMP R3, $0 // Check SVC return code
|
||||
BNE error
|
||||
|
||||
MOVD $-2, R3 // Reset last bit of entry point to zero
|
||||
AND R0, R3
|
||||
MOVD R3, addr+8(FP) // Return entry point returned by SVC
|
||||
CMP R0, R3 // Check if last bit of entry point was set
|
||||
BNE done
|
||||
|
||||
MOVD R15, R2 // Save go stack pointer
|
||||
MOVD $0, R15 // Move SVC args into registers (entry point still in r0 from SVC 08)
|
||||
BYTE $0x0A // SVC 09 DELETE
|
||||
BYTE $0x09
|
||||
MOVD R2, R15 // Restore go stack pointer
|
||||
|
||||
error:
|
||||
MOVD $0, addr+8(FP) // Return 0 on failure
|
||||
done:
|
||||
XOR R0, R0 // Reset r0 to 0
|
||||
RET
|
||||
|
||||
// func svcUnload(name *byte, fnptr unsafe.Pointer) int64
|
||||
TEXT ·svcUnload(SB),NOSPLIT,$0
|
||||
MOVD R15, R2 // Save go stack pointer
|
||||
MOVD name+0(FP), R0 // Move SVC args into registers
|
||||
MOVD addr+8(FP), R15
|
||||
BYTE $0x0A // SVC 09
|
||||
BYTE $0x09
|
||||
XOR R0, R0 // Reset r0 to 0
|
||||
MOVD R15, R1 // Save SVC return code
|
||||
MOVD R2, R15 // Restore go stack pointer
|
||||
MOVD R1, rc+0(FP) // Return SVC return code
|
||||
RET
|
||||
|
||||
// func gettid() uint64
|
||||
TEXT ·gettid(SB), NOSPLIT, $0
|
||||
// Get library control area (LCA).
|
||||
MOVW PSALAA, R8
|
||||
MOVD LCA64(R8), R8
|
||||
|
||||
// Get CEECAATHDID
|
||||
MOVD CAA(R8), R9
|
||||
MOVD 0x3D0(R9), R9
|
||||
MOVD R9, ret+0(FP)
|
||||
|
||||
RET
|
1
vendor/golang.org/x/sys/unix/cap_freebsd.go
generated
vendored
1
vendor/golang.org/x/sys/unix/cap_freebsd.go
generated
vendored
@ -2,6 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build freebsd
|
||||
// +build freebsd
|
||||
|
||||
package unix
|
||||
|
3
vendor/golang.org/x/sys/unix/constants.go
generated
vendored
3
vendor/golang.org/x/sys/unix/constants.go
generated
vendored
@ -2,7 +2,8 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris
|
||||
//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || zos
|
||||
// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris zos
|
||||
|
||||
package unix
|
||||
|
||||
|
4
vendor/golang.org/x/sys/unix/dev_aix_ppc.go
generated
vendored
4
vendor/golang.org/x/sys/unix/dev_aix_ppc.go
generated
vendored
@ -2,8 +2,8 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build aix
|
||||
// +build ppc
|
||||
//go:build aix && ppc
|
||||
// +build aix,ppc
|
||||
|
||||
// Functions to access/create device major and minor numbers matching the
|
||||
// encoding used by AIX.
|
||||
|
4
vendor/golang.org/x/sys/unix/dev_aix_ppc64.go
generated
vendored
4
vendor/golang.org/x/sys/unix/dev_aix_ppc64.go
generated
vendored
@ -2,8 +2,8 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build aix
|
||||
// +build ppc64
|
||||
//go:build aix && ppc64
|
||||
// +build aix,ppc64
|
||||
|
||||
// Functions to access/create device major and minor numbers matching the
|
||||
// encoding used AIX.
|
||||
|
29
vendor/golang.org/x/sys/unix/dev_zos.go
generated
vendored
Normal file
29
vendor/golang.org/x/sys/unix/dev_zos.go
generated
vendored
Normal file
@ -0,0 +1,29 @@
|
||||
// Copyright 2020 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build zos && s390x
|
||||
// +build zos,s390x
|
||||
|
||||
// Functions to access/create device major and minor numbers matching the
|
||||
// encoding used by z/OS.
|
||||
//
|
||||
// The information below is extracted and adapted from <sys/stat.h> macros.
|
||||
|
||||
package unix
|
||||
|
||||
// Major returns the major component of a z/OS device number.
|
||||
func Major(dev uint64) uint32 {
|
||||
return uint32((dev >> 16) & 0x0000FFFF)
|
||||
}
|
||||
|
||||
// Minor returns the minor component of a z/OS device number.
|
||||
func Minor(dev uint64) uint32 {
|
||||
return uint32(dev & 0x0000FFFF)
|
||||
}
|
||||
|
||||
// Mkdev returns a z/OS device number generated from the given major and minor
|
||||
// components.
|
||||
func Mkdev(major, minor uint32) uint64 {
|
||||
return (uint64(major) << 16) | uint64(minor)
|
||||
}
|
1
vendor/golang.org/x/sys/unix/dirent.go
generated
vendored
1
vendor/golang.org/x/sys/unix/dirent.go
generated
vendored
@ -2,6 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris
|
||||
// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris
|
||||
|
||||
package unix
|
||||
|
3
vendor/golang.org/x/sys/unix/endian_big.go
generated
vendored
3
vendor/golang.org/x/sys/unix/endian_big.go
generated
vendored
@ -2,7 +2,8 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
//
|
||||
// +build ppc64 s390x mips mips64
|
||||
//go:build armbe || arm64be || m68k || mips || mips64 || mips64p32 || ppc || ppc64 || s390 || s390x || shbe || sparc || sparc64
|
||||
// +build armbe arm64be m68k mips mips64 mips64p32 ppc ppc64 s390 s390x shbe sparc sparc64
|
||||
|
||||
package unix
|
||||
|
||||
|
3
vendor/golang.org/x/sys/unix/endian_little.go
generated
vendored
3
vendor/golang.org/x/sys/unix/endian_little.go
generated
vendored
@ -2,7 +2,8 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
//
|
||||
// +build 386 amd64 amd64p32 arm arm64 ppc64le mipsle mips64le riscv64
|
||||
//go:build 386 || amd64 || amd64p32 || alpha || arm || arm64 || mipsle || mips64le || mips64p32le || nios2 || ppc64le || riscv || riscv64 || sh
|
||||
// +build 386 amd64 amd64p32 alpha arm arm64 mipsle mips64le mips64p32le nios2 ppc64le riscv riscv64 sh
|
||||
|
||||
package unix
|
||||
|
||||
|
3
vendor/golang.org/x/sys/unix/env_unix.go
generated
vendored
3
vendor/golang.org/x/sys/unix/env_unix.go
generated
vendored
@ -2,7 +2,8 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris
|
||||
//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || zos
|
||||
// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris zos
|
||||
|
||||
// Unix environment variables.
|
||||
|
||||
|
221
vendor/golang.org/x/sys/unix/epoll_zos.go
generated
vendored
Normal file
221
vendor/golang.org/x/sys/unix/epoll_zos.go
generated
vendored
Normal file
@ -0,0 +1,221 @@
|
||||
// Copyright 2020 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build zos && s390x
|
||||
// +build zos,s390x
|
||||
|
||||
package unix
|
||||
|
||||
import (
|
||||
"sync"
|
||||
)
|
||||
|
||||
// This file simulates epoll on z/OS using poll.
|
||||
|
||||
// Analogous to epoll_event on Linux.
|
||||
// TODO(neeilan): Pad is because the Linux kernel expects a 96-bit struct. We never pass this to the kernel; remove?
|
||||
type EpollEvent struct {
|
||||
Events uint32
|
||||
Fd int32
|
||||
Pad int32
|
||||
}
|
||||
|
||||
const (
|
||||
EPOLLERR = 0x8
|
||||
EPOLLHUP = 0x10
|
||||
EPOLLIN = 0x1
|
||||
EPOLLMSG = 0x400
|
||||
EPOLLOUT = 0x4
|
||||
EPOLLPRI = 0x2
|
||||
EPOLLRDBAND = 0x80
|
||||
EPOLLRDNORM = 0x40
|
||||
EPOLLWRBAND = 0x200
|
||||
EPOLLWRNORM = 0x100
|
||||
EPOLL_CTL_ADD = 0x1
|
||||
EPOLL_CTL_DEL = 0x2
|
||||
EPOLL_CTL_MOD = 0x3
|
||||
// The following constants are part of the epoll API, but represent
|
||||
// currently unsupported functionality on z/OS.
|
||||
// EPOLL_CLOEXEC = 0x80000
|
||||
// EPOLLET = 0x80000000
|
||||
// EPOLLONESHOT = 0x40000000
|
||||
// EPOLLRDHUP = 0x2000 // Typically used with edge-triggered notis
|
||||
// EPOLLEXCLUSIVE = 0x10000000 // Exclusive wake-up mode
|
||||
// EPOLLWAKEUP = 0x20000000 // Relies on Linux's BLOCK_SUSPEND capability
|
||||
)
|
||||
|
||||
// TODO(neeilan): We can eliminate these epToPoll / pToEpoll calls by using identical mask values for POLL/EPOLL
|
||||
// constants where possible The lower 16 bits of epoll events (uint32) can fit any system poll event (int16).
|
||||
|
||||
// epToPollEvt converts epoll event field to poll equivalent.
|
||||
// In epoll, Events is a 32-bit field, while poll uses 16 bits.
|
||||
func epToPollEvt(events uint32) int16 {
|
||||
var ep2p = map[uint32]int16{
|
||||
EPOLLIN: POLLIN,
|
||||
EPOLLOUT: POLLOUT,
|
||||
EPOLLHUP: POLLHUP,
|
||||
EPOLLPRI: POLLPRI,
|
||||
EPOLLERR: POLLERR,
|
||||
}
|
||||
|
||||
var pollEvts int16 = 0
|
||||
for epEvt, pEvt := range ep2p {
|
||||
if (events & epEvt) != 0 {
|
||||
pollEvts |= pEvt
|
||||
}
|
||||
}
|
||||
|
||||
return pollEvts
|
||||
}
|
||||
|
||||
// pToEpollEvt converts 16 bit poll event bitfields to 32-bit epoll event fields.
|
||||
func pToEpollEvt(revents int16) uint32 {
|
||||
var p2ep = map[int16]uint32{
|
||||
POLLIN: EPOLLIN,
|
||||
POLLOUT: EPOLLOUT,
|
||||
POLLHUP: EPOLLHUP,
|
||||
POLLPRI: EPOLLPRI,
|
||||
POLLERR: EPOLLERR,
|
||||
}
|
||||
|
||||
var epollEvts uint32 = 0
|
||||
for pEvt, epEvt := range p2ep {
|
||||
if (revents & pEvt) != 0 {
|
||||
epollEvts |= epEvt
|
||||
}
|
||||
}
|
||||
|
||||
return epollEvts
|
||||
}
|
||||
|
||||
// Per-process epoll implementation.
|
||||
type epollImpl struct {
|
||||
mu sync.Mutex
|
||||
epfd2ep map[int]*eventPoll
|
||||
nextEpfd int
|
||||
}
|
||||
|
||||
// eventPoll holds a set of file descriptors being watched by the process. A process can have multiple epoll instances.
|
||||
// On Linux, this is an in-kernel data structure accessed through a fd.
|
||||
type eventPoll struct {
|
||||
mu sync.Mutex
|
||||
fds map[int]*EpollEvent
|
||||
}
|
||||
|
||||
// epoll impl for this process.
|
||||
var impl epollImpl = epollImpl{
|
||||
epfd2ep: make(map[int]*eventPoll),
|
||||
nextEpfd: 0,
|
||||
}
|
||||
|
||||
func (e *epollImpl) epollcreate(size int) (epfd int, err error) {
|
||||
e.mu.Lock()
|
||||
defer e.mu.Unlock()
|
||||
epfd = e.nextEpfd
|
||||
e.nextEpfd++
|
||||
|
||||
e.epfd2ep[epfd] = &eventPoll{
|
||||
fds: make(map[int]*EpollEvent),
|
||||
}
|
||||
return epfd, nil
|
||||
}
|
||||
|
||||
func (e *epollImpl) epollcreate1(flag int) (fd int, err error) {
|
||||
return e.epollcreate(4)
|
||||
}
|
||||
|
||||
func (e *epollImpl) epollctl(epfd int, op int, fd int, event *EpollEvent) (err error) {
|
||||
e.mu.Lock()
|
||||
defer e.mu.Unlock()
|
||||
|
||||
ep, ok := e.epfd2ep[epfd]
|
||||
if !ok {
|
||||
|
||||
return EBADF
|
||||
}
|
||||
|
||||
switch op {
|
||||
case EPOLL_CTL_ADD:
|
||||
// TODO(neeilan): When we make epfds and fds disjoint, detect epoll
|
||||
// loops here (instances watching each other) and return ELOOP.
|
||||
if _, ok := ep.fds[fd]; ok {
|
||||
return EEXIST
|
||||
}
|
||||
ep.fds[fd] = event
|
||||
case EPOLL_CTL_MOD:
|
||||
if _, ok := ep.fds[fd]; !ok {
|
||||
return ENOENT
|
||||
}
|
||||
ep.fds[fd] = event
|
||||
case EPOLL_CTL_DEL:
|
||||
if _, ok := ep.fds[fd]; !ok {
|
||||
return ENOENT
|
||||
}
|
||||
delete(ep.fds, fd)
|
||||
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Must be called while holding ep.mu
|
||||
func (ep *eventPoll) getFds() []int {
|
||||
fds := make([]int, len(ep.fds))
|
||||
for fd := range ep.fds {
|
||||
fds = append(fds, fd)
|
||||
}
|
||||
return fds
|
||||
}
|
||||
|
||||
func (e *epollImpl) epollwait(epfd int, events []EpollEvent, msec int) (n int, err error) {
|
||||
e.mu.Lock() // in [rare] case of concurrent epollcreate + epollwait
|
||||
ep, ok := e.epfd2ep[epfd]
|
||||
|
||||
if !ok {
|
||||
e.mu.Unlock()
|
||||
return 0, EBADF
|
||||
}
|
||||
|
||||
pollfds := make([]PollFd, 4)
|
||||
for fd, epollevt := range ep.fds {
|
||||
pollfds = append(pollfds, PollFd{Fd: int32(fd), Events: epToPollEvt(epollevt.Events)})
|
||||
}
|
||||
e.mu.Unlock()
|
||||
|
||||
n, err = Poll(pollfds, msec)
|
||||
if err != nil {
|
||||
return n, err
|
||||
}
|
||||
|
||||
i := 0
|
||||
for _, pFd := range pollfds {
|
||||
if pFd.Revents != 0 {
|
||||
events[i] = EpollEvent{Fd: pFd.Fd, Events: pToEpollEvt(pFd.Revents)}
|
||||
i++
|
||||
}
|
||||
|
||||
if i == n {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return n, nil
|
||||
}
|
||||
|
||||
func EpollCreate(size int) (fd int, err error) {
|
||||
return impl.epollcreate(size)
|
||||
}
|
||||
|
||||
func EpollCreate1(flag int) (fd int, err error) {
|
||||
return impl.epollcreate1(flag)
|
||||
}
|
||||
|
||||
func EpollCtl(epfd int, op int, fd int, event *EpollEvent) (err error) {
|
||||
return impl.epollctl(epfd, op, fd, event)
|
||||
}
|
||||
|
||||
// Because EpollWait mutates events, the caller is expected to coordinate
|
||||
// concurrent access if calling with the same epfd from multiple goroutines.
|
||||
func EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) {
|
||||
return impl.epollwait(epfd, events, msec)
|
||||
}
|
1
vendor/golang.org/x/sys/unix/fcntl.go
generated
vendored
1
vendor/golang.org/x/sys/unix/fcntl.go
generated
vendored
@ -2,6 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build dragonfly || freebsd || linux || netbsd || openbsd
|
||||
// +build dragonfly freebsd linux netbsd openbsd
|
||||
|
||||
package unix
|
||||
|
6
vendor/golang.org/x/sys/unix/fcntl_darwin.go
generated
vendored
6
vendor/golang.org/x/sys/unix/fcntl_darwin.go
generated
vendored
@ -16,3 +16,9 @@ func FcntlFlock(fd uintptr, cmd int, lk *Flock_t) error {
|
||||
_, err := fcntl(int(fd), cmd, int(uintptr(unsafe.Pointer(lk))))
|
||||
return err
|
||||
}
|
||||
|
||||
// FcntlFstore performs a fcntl syscall for the F_PREALLOCATE command.
|
||||
func FcntlFstore(fd uintptr, cmd int, fstore *Fstore_t) error {
|
||||
_, err := fcntl(int(fd), cmd, int(uintptr(unsafe.Pointer(fstore))))
|
||||
return err
|
||||
}
|
||||
|
5
vendor/golang.org/x/sys/unix/fcntl_linux_32bit.go
generated
vendored
5
vendor/golang.org/x/sys/unix/fcntl_linux_32bit.go
generated
vendored
@ -1,9 +1,10 @@
|
||||
// +build linux,386 linux,arm linux,mips linux,mipsle
|
||||
|
||||
// Copyright 2014 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build (linux && 386) || (linux && arm) || (linux && mips) || (linux && mipsle) || (linux && ppc)
|
||||
// +build linux,386 linux,arm linux,mips linux,mipsle linux,ppc
|
||||
|
||||
package unix
|
||||
|
||||
func init() {
|
||||
|
3
vendor/golang.org/x/sys/unix/fdset.go
generated
vendored
3
vendor/golang.org/x/sys/unix/fdset.go
generated
vendored
@ -2,7 +2,8 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris
|
||||
//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || zos
|
||||
// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris zos
|
||||
|
||||
package unix
|
||||
|
||||
|
164
vendor/golang.org/x/sys/unix/fstatfs_zos.go
generated
vendored
Normal file
164
vendor/golang.org/x/sys/unix/fstatfs_zos.go
generated
vendored
Normal file
@ -0,0 +1,164 @@
|
||||
// Copyright 2020 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build zos && s390x
|
||||
// +build zos,s390x
|
||||
|
||||
package unix
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// This file simulates fstatfs on z/OS using fstatvfs and w_getmntent.
|
||||
|
||||
func Fstatfs(fd int, stat *Statfs_t) (err error) {
|
||||
var stat_v Statvfs_t
|
||||
err = Fstatvfs(fd, &stat_v)
|
||||
if err == nil {
|
||||
// populate stat
|
||||
stat.Type = 0
|
||||
stat.Bsize = stat_v.Bsize
|
||||
stat.Blocks = stat_v.Blocks
|
||||
stat.Bfree = stat_v.Bfree
|
||||
stat.Bavail = stat_v.Bavail
|
||||
stat.Files = stat_v.Files
|
||||
stat.Ffree = stat_v.Ffree
|
||||
stat.Fsid = stat_v.Fsid
|
||||
stat.Namelen = stat_v.Namemax
|
||||
stat.Frsize = stat_v.Frsize
|
||||
stat.Flags = stat_v.Flag
|
||||
for passn := 0; passn < 5; passn++ {
|
||||
switch passn {
|
||||
case 0:
|
||||
err = tryGetmntent64(stat)
|
||||
break
|
||||
case 1:
|
||||
err = tryGetmntent128(stat)
|
||||
break
|
||||
case 2:
|
||||
err = tryGetmntent256(stat)
|
||||
break
|
||||
case 3:
|
||||
err = tryGetmntent512(stat)
|
||||
break
|
||||
case 4:
|
||||
err = tryGetmntent1024(stat)
|
||||
break
|
||||
default:
|
||||
break
|
||||
}
|
||||
//proceed to return if: err is nil (found), err is nonnil but not ERANGE (another error occurred)
|
||||
if err == nil || err != nil && err != ERANGE {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func tryGetmntent64(stat *Statfs_t) (err error) {
|
||||
var mnt_ent_buffer struct {
|
||||
header W_Mnth
|
||||
filesys_info [64]W_Mntent
|
||||
}
|
||||
var buffer_size int = int(unsafe.Sizeof(mnt_ent_buffer))
|
||||
fs_count, err := W_Getmntent((*byte)(unsafe.Pointer(&mnt_ent_buffer)), buffer_size)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = ERANGE //return ERANGE if no match is found in this batch
|
||||
for i := 0; i < fs_count; i++ {
|
||||
if stat.Fsid == uint64(mnt_ent_buffer.filesys_info[i].Dev) {
|
||||
stat.Type = uint32(mnt_ent_buffer.filesys_info[i].Fstname[0])
|
||||
err = nil
|
||||
break
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func tryGetmntent128(stat *Statfs_t) (err error) {
|
||||
var mnt_ent_buffer struct {
|
||||
header W_Mnth
|
||||
filesys_info [128]W_Mntent
|
||||
}
|
||||
var buffer_size int = int(unsafe.Sizeof(mnt_ent_buffer))
|
||||
fs_count, err := W_Getmntent((*byte)(unsafe.Pointer(&mnt_ent_buffer)), buffer_size)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = ERANGE //return ERANGE if no match is found in this batch
|
||||
for i := 0; i < fs_count; i++ {
|
||||
if stat.Fsid == uint64(mnt_ent_buffer.filesys_info[i].Dev) {
|
||||
stat.Type = uint32(mnt_ent_buffer.filesys_info[i].Fstname[0])
|
||||
err = nil
|
||||
break
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func tryGetmntent256(stat *Statfs_t) (err error) {
|
||||
var mnt_ent_buffer struct {
|
||||
header W_Mnth
|
||||
filesys_info [256]W_Mntent
|
||||
}
|
||||
var buffer_size int = int(unsafe.Sizeof(mnt_ent_buffer))
|
||||
fs_count, err := W_Getmntent((*byte)(unsafe.Pointer(&mnt_ent_buffer)), buffer_size)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = ERANGE //return ERANGE if no match is found in this batch
|
||||
for i := 0; i < fs_count; i++ {
|
||||
if stat.Fsid == uint64(mnt_ent_buffer.filesys_info[i].Dev) {
|
||||
stat.Type = uint32(mnt_ent_buffer.filesys_info[i].Fstname[0])
|
||||
err = nil
|
||||
break
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func tryGetmntent512(stat *Statfs_t) (err error) {
|
||||
var mnt_ent_buffer struct {
|
||||
header W_Mnth
|
||||
filesys_info [512]W_Mntent
|
||||
}
|
||||
var buffer_size int = int(unsafe.Sizeof(mnt_ent_buffer))
|
||||
fs_count, err := W_Getmntent((*byte)(unsafe.Pointer(&mnt_ent_buffer)), buffer_size)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = ERANGE //return ERANGE if no match is found in this batch
|
||||
for i := 0; i < fs_count; i++ {
|
||||
if stat.Fsid == uint64(mnt_ent_buffer.filesys_info[i].Dev) {
|
||||
stat.Type = uint32(mnt_ent_buffer.filesys_info[i].Fstname[0])
|
||||
err = nil
|
||||
break
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func tryGetmntent1024(stat *Statfs_t) (err error) {
|
||||
var mnt_ent_buffer struct {
|
||||
header W_Mnth
|
||||
filesys_info [1024]W_Mntent
|
||||
}
|
||||
var buffer_size int = int(unsafe.Sizeof(mnt_ent_buffer))
|
||||
fs_count, err := W_Getmntent((*byte)(unsafe.Pointer(&mnt_ent_buffer)), buffer_size)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = ERANGE //return ERANGE if no match is found in this batch
|
||||
for i := 0; i < fs_count; i++ {
|
||||
if stat.Fsid == uint64(mnt_ent_buffer.filesys_info[i].Dev) {
|
||||
stat.Type = uint32(mnt_ent_buffer.filesys_info[i].Fstname[0])
|
||||
err = nil
|
||||
break
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
6
vendor/golang.org/x/sys/unix/gccgo.go
generated
vendored
6
vendor/golang.org/x/sys/unix/gccgo.go
generated
vendored
@ -2,8 +2,8 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build gccgo
|
||||
// +build !aix
|
||||
//go:build gccgo && !aix
|
||||
// +build gccgo,!aix
|
||||
|
||||
package unix
|
||||
|
||||
@ -12,10 +12,8 @@ import "syscall"
|
||||
// We can't use the gc-syntax .s files for gccgo. On the plus side
|
||||
// much of the functionality can be written directly in Go.
|
||||
|
||||
//extern gccgoRealSyscallNoError
|
||||
func realSyscallNoError(trap, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r uintptr)
|
||||
|
||||
//extern gccgoRealSyscall
|
||||
func realSyscall(trap, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r, errno uintptr)
|
||||
|
||||
func SyscallNoError(trap, a1, a2, a3 uintptr) (r1, r2 uintptr) {
|
||||
|
6
vendor/golang.org/x/sys/unix/gccgo_c.c
generated
vendored
6
vendor/golang.org/x/sys/unix/gccgo_c.c
generated
vendored
@ -21,6 +21,9 @@ struct ret {
|
||||
uintptr_t err;
|
||||
};
|
||||
|
||||
struct ret gccgoRealSyscall(uintptr_t trap, uintptr_t a1, uintptr_t a2, uintptr_t a3, uintptr_t a4, uintptr_t a5, uintptr_t a6, uintptr_t a7, uintptr_t a8, uintptr_t a9)
|
||||
__asm__(GOSYM_PREFIX GOPKGPATH ".realSyscall");
|
||||
|
||||
struct ret
|
||||
gccgoRealSyscall(uintptr_t trap, uintptr_t a1, uintptr_t a2, uintptr_t a3, uintptr_t a4, uintptr_t a5, uintptr_t a6, uintptr_t a7, uintptr_t a8, uintptr_t a9)
|
||||
{
|
||||
@ -32,6 +35,9 @@ gccgoRealSyscall(uintptr_t trap, uintptr_t a1, uintptr_t a2, uintptr_t a3, uintp
|
||||
return r;
|
||||
}
|
||||
|
||||
uintptr_t gccgoRealSyscallNoError(uintptr_t trap, uintptr_t a1, uintptr_t a2, uintptr_t a3, uintptr_t a4, uintptr_t a5, uintptr_t a6, uintptr_t a7, uintptr_t a8, uintptr_t a9)
|
||||
__asm__(GOSYM_PREFIX GOPKGPATH ".realSyscallNoError");
|
||||
|
||||
uintptr_t
|
||||
gccgoRealSyscallNoError(uintptr_t trap, uintptr_t a1, uintptr_t a2, uintptr_t a3, uintptr_t a4, uintptr_t a5, uintptr_t a6, uintptr_t a7, uintptr_t a8, uintptr_t a9)
|
||||
{
|
||||
|
1
vendor/golang.org/x/sys/unix/gccgo_linux_amd64.go
generated
vendored
1
vendor/golang.org/x/sys/unix/gccgo_linux_amd64.go
generated
vendored
@ -2,6 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build gccgo && linux && amd64
|
||||
// +build gccgo,linux,amd64
|
||||
|
||||
package unix
|
||||
|
10
vendor/golang.org/x/sys/unix/ioctl.go
generated
vendored
10
vendor/golang.org/x/sys/unix/ioctl.go
generated
vendored
@ -2,6 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris
|
||||
// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris
|
||||
|
||||
package unix
|
||||
@ -20,6 +21,15 @@ func IoctlSetInt(fd int, req uint, value int) error {
|
||||
return ioctl(fd, req, uintptr(value))
|
||||
}
|
||||
|
||||
// IoctlSetPointerInt performs an ioctl operation which sets an
|
||||
// integer value on fd, using the specified request number. The ioctl
|
||||
// argument is called with a pointer to the integer value, rather than
|
||||
// passing the integer value directly.
|
||||
func IoctlSetPointerInt(fd int, req uint, value int) error {
|
||||
v := int32(value)
|
||||
return ioctl(fd, req, uintptr(unsafe.Pointer(&v)))
|
||||
}
|
||||
|
||||
// IoctlSetWinsize performs an ioctl on fd with a *Winsize argument.
|
||||
//
|
||||
// To change fd's window size, the req argument should be TIOCSWINSZ.
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user