diff --git a/Gopkg.lock b/Gopkg.lock new file mode 100644 index 0000000..3274e11 --- /dev/null +++ b/Gopkg.lock @@ -0,0 +1,19 @@ +memo = "c464a3d83956b677421b9fc797a6c77aa6e94a28120ee71d2b19860a5ff39c20" + +[[projects]] + branch = "master" + name = "github.com/kardianos/osext" + packages = ["."] + revision = "ae77be60afb1dcacde03767a8c37337fad28ac14" + +[[projects]] + branch = "master" + name = "github.com/keybase/go-ps" + packages = [".","darwincgo"] + revision = "668c8856d9992f97248b3177d45743d2cc1068db" + +[[projects]] + branch = "master" + name = "golang.org/x/arch" + packages = ["arm/armasm","ppc64/ppc64asm","x86/x86asm"] + revision = "9dd86654181264cc7c76c929f3df20d11251e23a" diff --git a/Gopkg.toml b/Gopkg.toml new file mode 100644 index 0000000..88769ef --- /dev/null +++ b/Gopkg.toml @@ -0,0 +1,64 @@ + +## Gopkg.toml example (these lines may be deleted) + +## "required" lists a set of packages (not projects) that must be included in +## Gopkg.lock. This list is merged with the set of packages imported by the current +## project. Use it when your project needs a package it doesn't explicitly import - +## including "main" packages. +# required = ["github.com/user/thing/cmd/thing"] + +## "ignored" lists a set of packages (not projects) that are ignored when +## dep statically analyzes source code. Ignored packages can be in this project, +## or in a dependency. +# ignored = ["github.com/user/project/badpkg"] + +## Dependencies define constraints on dependent projects. They are respected by +## dep whether coming from the Gopkg.toml of the current project or a dependency. +# [[dependencies]] +## Required: the root import path of the project being constrained. +# name = "github.com/user/project" +# +## Recommended: the version constraint to enforce for the project. +## Only one of "branch", "version" or "revision" can be specified. +# version = "1.0.0" +# branch = "master" +# revision = "abc123" +# +## Optional: an alternate location (URL or import path) for the project's source. +# source = "https://github.com/myfork/package.git" + +## Overrides have the same structure as [[dependencies]], but supercede all +## [[dependencies]] declarations from all projects. Only the current project's +## [[overrides]] are applied. +## +## Overrides are a sledgehammer. Use them only as a last resort. +# [[overrides]] +## Required: the root import path of the project being constrained. +# name = "github.com/user/project" +# +## Optional: specifying a version constraint override will cause all other +## constraints on this project to be ignored; only the overriden constraint +## need be satisfied. +## Again, only one of "branch", "version" or "revision" can be specified. +# version = "1.0.0" +# branch = "master" +# revision = "abc123" +# +## Optional: specifying an alternate source location as an override will +## enforce that the alternate location is used for that project, regardless of +## what source location any dependent projects specify. +# source = "https://github.com/myfork/package.git" + + + +[[dependencies]] + branch = "master" + name = "github.com/kardianos/osext" + +[[dependencies]] + branch = "master" + name = "github.com/keybase/go-ps" + +[[dependencies]] + branch = "master" + name = "golang.org/x/arch" diff --git a/vendor/github.com/kardianos/osext/LICENSE b/vendor/github.com/kardianos/osext/LICENSE new file mode 100644 index 0000000..7448756 --- /dev/null +++ b/vendor/github.com/kardianos/osext/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2012 The Go Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/kardianos/osext/README.md b/vendor/github.com/kardianos/osext/README.md new file mode 100644 index 0000000..15cbc3d --- /dev/null +++ b/vendor/github.com/kardianos/osext/README.md @@ -0,0 +1,21 @@ +### Extensions to the "os" package. + +[![GoDoc](https://godoc.org/github.com/kardianos/osext?status.svg)](https://godoc.org/github.com/kardianos/osext) + +## Find the current Executable and ExecutableFolder. + +As of go1.8 the Executable function may be found in `os`. The Executable function +in the std lib `os` package is used if available. + +There is sometimes utility in finding the current executable file +that is running. This can be used for upgrading the current executable +or finding resources located relative to the executable file. Both +working directory and the os.Args[0] value are arbitrary and cannot +be relied on; os.Args[0] can be "faked". + +Multi-platform and supports: + * Linux + * OS X + * Windows + * Plan 9 + * BSDs. diff --git a/vendor/github.com/kardianos/osext/osext.go b/vendor/github.com/kardianos/osext/osext.go new file mode 100644 index 0000000..17f380f --- /dev/null +++ b/vendor/github.com/kardianos/osext/osext.go @@ -0,0 +1,33 @@ +// 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. + +// Extensions to the standard "os" package. +package osext // import "github.com/kardianos/osext" + +import "path/filepath" + +var cx, ce = executableClean() + +func executableClean() (string, error) { + p, err := executable() + return filepath.Clean(p), err +} + +// Executable returns an absolute path that can be used to +// re-invoke the current program. +// It may not be valid after the current program exits. +func Executable() (string, error) { + return cx, ce +} + +// Returns same path as Executable, returns just the folder +// path. Excludes the executable name and any trailing slash. +func ExecutableFolder() (string, error) { + p, err := Executable() + if err != nil { + return "", err + } + + return filepath.Dir(p), nil +} diff --git a/vendor/github.com/kardianos/osext/osext_go18.go b/vendor/github.com/kardianos/osext/osext_go18.go new file mode 100644 index 0000000..009d8a9 --- /dev/null +++ b/vendor/github.com/kardianos/osext/osext_go18.go @@ -0,0 +1,9 @@ +//+build go1.8,!openbsd + +package osext + +import "os" + +func executable() (string, error) { + return os.Executable() +} diff --git a/vendor/github.com/kardianos/osext/osext_plan9.go b/vendor/github.com/kardianos/osext/osext_plan9.go new file mode 100644 index 0000000..95e2371 --- /dev/null +++ b/vendor/github.com/kardianos/osext/osext_plan9.go @@ -0,0 +1,22 @@ +// 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 !go1.8 + +package osext + +import ( + "os" + "strconv" + "syscall" +) + +func executable() (string, error) { + f, err := os.Open("/proc/" + strconv.Itoa(os.Getpid()) + "/text") + if err != nil { + return "", err + } + defer f.Close() + return syscall.Fd2path(int(f.Fd())) +} diff --git a/vendor/github.com/kardianos/osext/osext_procfs.go b/vendor/github.com/kardianos/osext/osext_procfs.go new file mode 100644 index 0000000..e1f16f8 --- /dev/null +++ b/vendor/github.com/kardianos/osext/osext_procfs.go @@ -0,0 +1,36 @@ +// 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 !go1.8,android !go1.8,linux !go1.8,netbsd !go1.8,solaris !go1.8,dragonfly + +package osext + +import ( + "errors" + "fmt" + "os" + "runtime" + "strings" +) + +func executable() (string, error) { + switch runtime.GOOS { + case "linux", "android": + const deletedTag = " (deleted)" + execpath, err := os.Readlink("/proc/self/exe") + if err != nil { + return execpath, err + } + execpath = strings.TrimSuffix(execpath, deletedTag) + execpath = strings.TrimPrefix(execpath, deletedTag) + return execpath, nil + case "netbsd": + return os.Readlink("/proc/curproc/exe") + case "dragonfly": + return os.Readlink("/proc/curproc/file") + case "solaris": + return os.Readlink(fmt.Sprintf("/proc/%d/path/a.out", os.Getpid())) + } + return "", errors.New("ExecPath not implemented for " + runtime.GOOS) +} diff --git a/vendor/github.com/kardianos/osext/osext_sysctl.go b/vendor/github.com/kardianos/osext/osext_sysctl.go new file mode 100644 index 0000000..33cee25 --- /dev/null +++ b/vendor/github.com/kardianos/osext/osext_sysctl.go @@ -0,0 +1,126 @@ +// 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 !go1.8,darwin !go1.8,freebsd openbsd + +package osext + +import ( + "os" + "os/exec" + "path/filepath" + "runtime" + "syscall" + "unsafe" +) + +var initCwd, initCwdErr = os.Getwd() + +func executable() (string, error) { + var mib [4]int32 + switch runtime.GOOS { + case "freebsd": + mib = [4]int32{1 /* CTL_KERN */, 14 /* KERN_PROC */, 12 /* KERN_PROC_PATHNAME */, -1} + case "darwin": + mib = [4]int32{1 /* CTL_KERN */, 38 /* KERN_PROCARGS */, int32(os.Getpid()), -1} + case "openbsd": + mib = [4]int32{1 /* CTL_KERN */, 55 /* KERN_PROC_ARGS */, int32(os.Getpid()), 1 /* KERN_PROC_ARGV */} + } + + n := uintptr(0) + // Get length. + _, _, errNum := syscall.Syscall6(syscall.SYS___SYSCTL, uintptr(unsafe.Pointer(&mib[0])), 4, 0, uintptr(unsafe.Pointer(&n)), 0, 0) + if errNum != 0 { + return "", errNum + } + if n == 0 { // This shouldn't happen. + return "", nil + } + buf := make([]byte, n) + _, _, errNum = syscall.Syscall6(syscall.SYS___SYSCTL, uintptr(unsafe.Pointer(&mib[0])), 4, uintptr(unsafe.Pointer(&buf[0])), uintptr(unsafe.Pointer(&n)), 0, 0) + if errNum != 0 { + return "", errNum + } + if n == 0 { // This shouldn't happen. + return "", nil + } + + var execPath string + switch runtime.GOOS { + case "openbsd": + // buf now contains **argv, with pointers to each of the C-style + // NULL terminated arguments. + var args []string + argv := uintptr(unsafe.Pointer(&buf[0])) + Loop: + for { + argp := *(**[1 << 20]byte)(unsafe.Pointer(argv)) + if argp == nil { + break + } + for i := 0; uintptr(i) < n; i++ { + // we don't want the full arguments list + if string(argp[i]) == " " { + break Loop + } + if argp[i] != 0 { + continue + } + args = append(args, string(argp[:i])) + n -= uintptr(i) + break + } + if n < unsafe.Sizeof(argv) { + break + } + argv += unsafe.Sizeof(argv) + n -= unsafe.Sizeof(argv) + } + execPath = args[0] + // There is no canonical way to get an executable path on + // OpenBSD, so check PATH in case we are called directly + if execPath[0] != '/' && execPath[0] != '.' { + execIsInPath, err := exec.LookPath(execPath) + if err == nil { + execPath = execIsInPath + } + } + default: + for i, v := range buf { + if v == 0 { + buf = buf[:i] + break + } + } + execPath = string(buf) + } + + var err error + // execPath will not be empty due to above checks. + // Try to get the absolute path if the execPath is not rooted. + if execPath[0] != '/' { + execPath, err = getAbs(execPath) + if err != nil { + return execPath, err + } + } + // For darwin KERN_PROCARGS may return the path to a symlink rather than the + // actual executable. + if runtime.GOOS == "darwin" { + if execPath, err = filepath.EvalSymlinks(execPath); err != nil { + return execPath, err + } + } + return execPath, nil +} + +func getAbs(execPath string) (string, error) { + if initCwdErr != nil { + return execPath, initCwdErr + } + // The execPath may begin with a "../" or a "./" so clean it first. + // Join the two paths, trailing and starting slashes undetermined, so use + // the generic Join function. + return filepath.Join(initCwd, filepath.Clean(execPath)), nil +} diff --git a/vendor/github.com/kardianos/osext/osext_test.go b/vendor/github.com/kardianos/osext/osext_test.go new file mode 100644 index 0000000..eb18236 --- /dev/null +++ b/vendor/github.com/kardianos/osext/osext_test.go @@ -0,0 +1,203 @@ +// 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 darwin linux freebsd netbsd windows openbsd + +package osext + +import ( + "bytes" + "fmt" + "io" + "os" + "os/exec" + "path/filepath" + "runtime" + "testing" +) + +const ( + executableEnvVar = "OSTEST_OUTPUT_EXECUTABLE" + + executableEnvValueMatch = "match" + executableEnvValueDelete = "delete" +) + +func TestPrintExecutable(t *testing.T) { + ef, err := Executable() + if err != nil { + t.Fatalf("Executable failed: %v", err) + } + t.Log("Executable:", ef) +} +func TestPrintExecutableFolder(t *testing.T) { + ef, err := ExecutableFolder() + if err != nil { + t.Fatalf("ExecutableFolder failed: %v", err) + } + t.Log("Executable Folder:", ef) +} +func TestExecutableFolder(t *testing.T) { + ef, err := ExecutableFolder() + if err != nil { + t.Fatalf("ExecutableFolder failed: %v", err) + } + if ef[len(ef)-1] == filepath.Separator { + t.Fatal("ExecutableFolder ends with a trailing slash.") + } +} +func TestExecutableMatch(t *testing.T) { + ep, err := Executable() + if err != nil { + t.Fatalf("Executable failed: %v", err) + } + + // fullpath to be of the form "dir/prog". + dir := filepath.Dir(filepath.Dir(ep)) + fullpath, err := filepath.Rel(dir, ep) + if err != nil { + t.Fatalf("filepath.Rel: %v", err) + } + // Make child start with a relative program path. + // Alter argv[0] for child to verify getting real path without argv[0]. + cmd := &exec.Cmd{ + Dir: dir, + Path: fullpath, + Env: []string{fmt.Sprintf("%s=%s", executableEnvVar, executableEnvValueMatch)}, + } + out, err := cmd.CombinedOutput() + if err != nil { + t.Fatalf("exec(self) failed: %v", err) + } + outs := string(out) + if !filepath.IsAbs(outs) { + t.Fatalf("Child returned %q, want an absolute path", out) + } + if !sameFile(outs, ep) { + t.Fatalf("Child returned %q, not the same file as %q", out, ep) + } +} + +func TestExecutableDelete(t *testing.T) { + if runtime.GOOS != "linux" { + t.Skip() + } + fpath, err := Executable() + if err != nil { + t.Fatalf("Executable failed: %v", err) + } + + r, w := io.Pipe() + stderrBuff := &bytes.Buffer{} + stdoutBuff := &bytes.Buffer{} + cmd := &exec.Cmd{ + Path: fpath, + Env: []string{fmt.Sprintf("%s=%s", executableEnvVar, executableEnvValueDelete)}, + Stdin: r, + Stderr: stderrBuff, + Stdout: stdoutBuff, + } + err = cmd.Start() + if err != nil { + t.Fatalf("exec(self) start failed: %v", err) + } + + tempPath := fpath + "_copy" + _ = os.Remove(tempPath) + + err = copyFile(tempPath, fpath) + if err != nil { + t.Fatalf("copy file failed: %v", err) + } + err = os.Remove(fpath) + if err != nil { + t.Fatalf("remove running test file failed: %v", err) + } + err = os.Rename(tempPath, fpath) + if err != nil { + t.Fatalf("rename copy to previous name failed: %v", err) + } + + w.Write([]byte{0}) + w.Close() + + err = cmd.Wait() + if err != nil { + t.Fatalf("exec wait failed: %v", err) + } + + childPath := stderrBuff.String() + if !filepath.IsAbs(childPath) { + t.Fatalf("Child returned %q, want an absolute path", childPath) + } + if !sameFile(childPath, fpath) { + t.Fatalf("Child returned %q, not the same file as %q", childPath, fpath) + } +} + +func sameFile(fn1, fn2 string) bool { + fi1, err := os.Stat(fn1) + if err != nil { + return false + } + fi2, err := os.Stat(fn2) + if err != nil { + return false + } + return os.SameFile(fi1, fi2) +} +func copyFile(dest, src string) error { + df, err := os.Create(dest) + if err != nil { + return err + } + defer df.Close() + + sf, err := os.Open(src) + if err != nil { + return err + } + defer sf.Close() + + _, err = io.Copy(df, sf) + return err +} + +func TestMain(m *testing.M) { + env := os.Getenv(executableEnvVar) + switch env { + case "": + os.Exit(m.Run()) + case executableEnvValueMatch: + // First chdir to another path. + dir := "/" + if runtime.GOOS == "windows" { + dir = filepath.VolumeName(".") + } + os.Chdir(dir) + if ep, err := Executable(); err != nil { + fmt.Fprint(os.Stderr, "ERROR: ", err) + } else { + fmt.Fprint(os.Stderr, ep) + } + case executableEnvValueDelete: + bb := make([]byte, 1) + var err error + n, err := os.Stdin.Read(bb) + if err != nil { + fmt.Fprint(os.Stderr, "ERROR: ", err) + os.Exit(2) + } + if n != 1 { + fmt.Fprint(os.Stderr, "ERROR: n != 1, n == ", n) + os.Exit(2) + } + if ep, err := Executable(); err != nil { + fmt.Fprint(os.Stderr, "ERROR: ", err) + } else { + fmt.Fprint(os.Stderr, ep) + } + } + os.Exit(0) +} diff --git a/vendor/github.com/kardianos/osext/osext_windows.go b/vendor/github.com/kardianos/osext/osext_windows.go new file mode 100644 index 0000000..074b3b3 --- /dev/null +++ b/vendor/github.com/kardianos/osext/osext_windows.go @@ -0,0 +1,36 @@ +// 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 !go1.8 + +package osext + +import ( + "syscall" + "unicode/utf16" + "unsafe" +) + +var ( + kernel = syscall.MustLoadDLL("kernel32.dll") + getModuleFileNameProc = kernel.MustFindProc("GetModuleFileNameW") +) + +// GetModuleFileName() with hModule = NULL +func executable() (exePath string, err error) { + return getModuleFileName() +} + +func getModuleFileName() (string, error) { + var n uint32 + b := make([]uint16, syscall.MAX_PATH) + size := uint32(len(b)) + + r0, _, e1 := getModuleFileNameProc.Call(0, uintptr(unsafe.Pointer(&b[0])), uintptr(size)) + n = uint32(r0) + if n == 0 { + return "", e1 + } + return string(utf16.Decode(b[0:n])), nil +} diff --git a/vendor/github.com/keybase/go-ps/.gitignore b/vendor/github.com/keybase/go-ps/.gitignore new file mode 100644 index 0000000..a977916 --- /dev/null +++ b/vendor/github.com/keybase/go-ps/.gitignore @@ -0,0 +1 @@ +.vagrant/ diff --git a/vendor/github.com/keybase/go-ps/.pre-commit-config.yaml b/vendor/github.com/keybase/go-ps/.pre-commit-config.yaml new file mode 100644 index 0000000..b87b62d --- /dev/null +++ b/vendor/github.com/keybase/go-ps/.pre-commit-config.yaml @@ -0,0 +1,10 @@ +- repo: https://github.com/gabriel/pre-commit-golang + sha: c02a81d85a5295886022b8106c367518e6c3760e + hooks: + - id: go-fmt + - id: go-metalinter + args: + - --deadline=60s + - --vendor + - --cyclo-over=20 + - --dupl-threshold=100 diff --git a/vendor/github.com/keybase/go-ps/.travis.yml b/vendor/github.com/keybase/go-ps/.travis.yml new file mode 100644 index 0000000..f5b919d --- /dev/null +++ b/vendor/github.com/keybase/go-ps/.travis.yml @@ -0,0 +1,11 @@ +language: go +go: + - tip +os: + - linux + - osx +before_install: + - go get github.com/mattn/goveralls + - go get golang.org/x/tools/cmd/cover +script: + - $HOME/gopath/bin/goveralls -service=travis-ci diff --git a/vendor/github.com/keybase/go-ps/LICENSE.md b/vendor/github.com/keybase/go-ps/LICENSE.md new file mode 100644 index 0000000..83eb91b --- /dev/null +++ b/vendor/github.com/keybase/go-ps/LICENSE.md @@ -0,0 +1,44 @@ +The MIT License (MIT) + +Copyright (c) 2014 Mitchell Hashimoto + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + + +The MIT License (MIT) + +Copyright (c) 2015 Keybase + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/github.com/keybase/go-ps/README.md b/vendor/github.com/keybase/go-ps/README.md new file mode 100644 index 0000000..3d5762a --- /dev/null +++ b/vendor/github.com/keybase/go-ps/README.md @@ -0,0 +1,31 @@ +# Process List Library for Go + +[![Build Status](https://travis-ci.org/keybase/go-ps.svg?branch=master)](https://travis-ci.org/keybase/go-ps) +[![Build Status](https://ci.appveyor.com/api/projects/status/github/keybase/go-ps?branch=master&svg=true)](https://ci.appveyor.com/project/keybase/go-ps) +[![Coverage Status](https://coveralls.io/repos/github/keybase/go-ps/badge.svg?branch=master)](https://coveralls.io/github/keybase/go-ps?branch=master) +[![GoDoc](https://godoc.org/github.com/keybase/go-ps?status.svg)](https://godoc.org/github.com/keybase/go-ps) + + +go-ps is a library for Go that implements OS-specific APIs to list and +manipulate processes in a platform-safe way. The library can find and +list processes on Linux, Mac OS X, and Windows. + +If you're new to Go, this library has a good amount of advanced Go educational +value as well. It uses some advanced features of Go: build tags, accessing +DLL methods for Windows, cgo for Darwin, etc. + +How it works: + + * **Darwin** uses `sysctl` and `proc_listpids` (for the path) to retrieve the process table, via cgo. + * **Unix** uses the procfs at `/proc` to inspect the process tree. + * **Windows** uses the Windows API, and methods such as + `CreateToolhelp32Snapshot` to get a point-in-time snapshot of + the process table. + +## Installation + +Install using standard `go get`: + +``` +$ go get github.com/keybase/go-ps +``` diff --git a/vendor/github.com/keybase/go-ps/appveyor.yml b/vendor/github.com/keybase/go-ps/appveyor.yml new file mode 100644 index 0000000..59a98ac --- /dev/null +++ b/vendor/github.com/keybase/go-ps/appveyor.yml @@ -0,0 +1,31 @@ +# environment variables +environment: + global: + GOPATH: c:\work\ + +# clone path +clone_folder: c:\work\src\github.com\keybase\go-ps + +# build platform, i.e. x86, x64, Any CPU. This setting is optional. +#platform: Any CPU + +# scripts to run before build +before_build: + +# scripts to run after build +after_build: + +# to run your custom scripts instead of automatic MSBuild +build_script: + - go version + - go build + - go get github.com/stretchr/testify/assert + - go get github.com/stretchr/testify/require + - go test -short -v + - go test -short -race -v + +# to disable automatic tests +test: off + +# to disable deployment +deploy: off diff --git a/vendor/github.com/keybase/go-ps/darwincgo/empty.go b/vendor/github.com/keybase/go-ps/darwincgo/empty.go new file mode 100644 index 0000000..bc315c6 --- /dev/null +++ b/vendor/github.com/keybase/go-ps/darwincgo/empty.go @@ -0,0 +1 @@ +package darwincgo diff --git a/vendor/github.com/keybase/go-ps/darwincgo/process_darwin.c b/vendor/github.com/keybase/go-ps/darwincgo/process_darwin.c new file mode 100644 index 0000000..610a8ef --- /dev/null +++ b/vendor/github.com/keybase/go-ps/darwincgo/process_darwin.c @@ -0,0 +1,87 @@ +// +build darwin + +#include +#include +#include +#include +#include +#include +#include + +// This is declared in process_darwin.go +extern void goDarwinAppendProc(pid_t, pid_t, char *); +extern void goDarwinSetPath(pid_t, char *); + +// darwinProcesses loads the process table and calls the exported Go function to +// insert the data back into the Go space. +// +// This function is implemented in C because while it would technically +// be possible to do this all in Go, I didn't want to go spelunking through +// header files to get all the structures properly. It is much easier to just +// call it in C and be done with it. +int darwinProcesses() { + int err = 0; + int i = 0; + static const int name[] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL, 0 }; + size_t length = 0; + struct kinfo_proc *result = NULL; + size_t resultCount = 0; + + // Get the length first + err = sysctl((int*)name, (sizeof(name) / sizeof(*name)) - 1, + NULL, &length, NULL, 0); + if (err != 0) { + goto ERREXIT; + } + + // Allocate the appropriate sized buffer to read the process list + result = malloc(length); + + // Call sysctl again with our buffer to fill it with the process list + err = sysctl((int*)name, (sizeof(name) / sizeof(*name)) - 1, + result, &length, + NULL, 0); + if (err != 0) { + goto ERREXIT; + } + + resultCount = length / sizeof(struct kinfo_proc); + for (i = 0; i < resultCount; i++) { + struct kinfo_proc *single = &result[i]; + goDarwinAppendProc( + single->kp_proc.p_pid, + single->kp_eproc.e_ppid, + single->kp_proc.p_comm); + } + +ERREXIT: + if (result != NULL) { + free(result); + } + + if (err != 0) { + return errno; + } + return 0; +} + +// darwinProcessPaths looks up paths for process pids +void darwinProcessPaths() { + int pid_buf_size = proc_listpids(PROC_ALL_PIDS, 0, NULL, 0); + int pid_count = pid_buf_size / sizeof(pid_t); + + pid_t* pids = malloc(pid_buf_size); + bzero(pids, pid_buf_size); + + proc_listpids(PROC_ALL_PIDS, 0, pids, pid_buf_size); + char path_buffer[PROC_PIDPATHINFO_MAXSIZE]; + + for (int i=0; i < pid_count; i++) { + if (pids[i] == 0) break; + bzero(path_buffer, PROC_PIDPATHINFO_MAXSIZE); + if (proc_pidpath(pids[i], path_buffer, sizeof(path_buffer)) > 0) { + goDarwinSetPath(pids[i], path_buffer); + } + } + free(pids); +} diff --git a/vendor/github.com/keybase/go-ps/darwincgo/process_darwin.go b/vendor/github.com/keybase/go-ps/darwincgo/process_darwin.go new file mode 100644 index 0000000..ab9edf4 --- /dev/null +++ b/vendor/github.com/keybase/go-ps/darwincgo/process_darwin.go @@ -0,0 +1,84 @@ +// +build darwin + +package darwincgo + +/* +#include +#include +#include +extern int darwinProcesses(); +extern void darwinProcessPaths(); +*/ +import "C" + +import ( + "path/filepath" + "sync" +) + +// This lock is what verifies that C calling back into Go is only +// modifying data once at a time. +var darwinLock sync.Mutex +var darwinProcsByPID map[int]*DarwinProcess + +// DarwinProcess is process definition for OS X +type DarwinProcess struct { + pid int + ppid int + path string +} + +// Pid returns process id +func (p *DarwinProcess) Pid() int { + return p.pid +} + +// PPid returns parent process id +func (p *DarwinProcess) PPid() int { + return p.ppid +} + +// Executable returns process executable name +func (p *DarwinProcess) Executable() string { + path, _ := p.Path() + return filepath.Base(path) +} + +// Path returns path to process executable +func (p *DarwinProcess) Path() (string, error) { + return p.path, nil +} + +//export goDarwinAppendProc +func goDarwinAppendProc(pid C.pid_t, ppid C.pid_t, comm *C.char) { + proc := &DarwinProcess{ + pid: int(pid), + ppid: int(ppid), + } + darwinProcsByPID[proc.pid] = proc +} + +//export goDarwinSetPath +func goDarwinSetPath(pid C.pid_t, comm *C.char) { + if proc, ok := darwinProcsByPID[int(pid)]; ok && proc != nil { + proc.path = C.GoString(comm) + } +} + +// ProcessMap returns a map of processes for the main library package. +func ProcessMap() (map[int]*DarwinProcess, error) { + darwinLock.Lock() + defer darwinLock.Unlock() + darwinProcsByPID = make(map[int]*DarwinProcess) + + // To ignore deadcode warnings for exported functions + _ = goDarwinAppendProc + _ = goDarwinSetPath + + // TODO: Investigate why darwinProcesses returns error even if process list + // succeeds + C.darwinProcesses() + C.darwinProcessPaths() + + return darwinProcsByPID, nil +} diff --git a/vendor/github.com/keybase/go-ps/process.go b/vendor/github.com/keybase/go-ps/process.go new file mode 100644 index 0000000..042cd1b --- /dev/null +++ b/vendor/github.com/keybase/go-ps/process.go @@ -0,0 +1,75 @@ +// Package ps provides an API for finding and listing processes in a +// platform-agnostic way. +// +// NOTE: If you're reading these docs online via GoDocs or some other system, +// you might only see the Unix docs. This project makes heavy use of +// platform-specific implementations. We recommend reading the source if you +// are interested. +package ps + +import "fmt" + +// Process is the generic interface that is implemented on every platform +// and provides common operations for processes. +type Process interface { + // Pid is the process ID for this process. + Pid() int + + // PPid is the parent process ID for this process. + PPid() int + + // Executable name running this process. This is not a path to the + // executable. + Executable() string + + // Path is full path to the executable. The path may be unavailable if the + // exectuable was deleted from the system while it was still running. + Path() (string, error) +} + +type processesFn func() ([]Process, error) + +// Processes returns all processes. +// +// This of course will be a point-in-time snapshot of when this method was +// called. Some operating systems don't provide snapshot capability of the +// process table, in which case the process table returned might contain +// ephemeral entities that happened to be running when this was called. +func Processes() ([]Process, error) { + return processes() +} + +// FindProcess looks up a single process by pid. +// This may require a full process listing depending on the platform, so +// consider using os.FindProcess instead. +// Process will be nil and error will be nil if a matching process is not found. +func FindProcess(pid int) (Process, error) { + return findProcess(pid) +} + +type matchFn func(Process) bool + +// findProcessesWithFn finds processes using match function. +// If max is != 0, then we will return that max number of processes. +func findProcessesWithFn(processesFn processesFn, matchFn matchFn, max int) ([]Process, error) { + processes, err := processesFn() + if err != nil { + return nil, fmt.Errorf("Error listing processes: %s", err) + } + if processes == nil { + return nil, nil + } + procs := []Process{} + for _, p := range processes { + if matchFn(p) { + procs = append(procs, p) + } + if max != 0 && len(procs) >= max { + break + } + } + return procs, nil +} + +// Avoid linting error +var _ = findProcessesWithFn diff --git a/vendor/github.com/keybase/go-ps/process_darwin.go b/vendor/github.com/keybase/go-ps/process_darwin.go new file mode 100644 index 0000000..02cfa79 --- /dev/null +++ b/vendor/github.com/keybase/go-ps/process_darwin.go @@ -0,0 +1,31 @@ +// +build darwin + +package ps + +import ( + "github.com/keybase/go-ps/darwincgo" +) + +func findProcess(pid int) (Process, error) { + m, err := darwincgo.ProcessMap() + if err != nil { + return nil, err + } + p := m[pid] + if p == nil { + return nil, nil + } + return p, nil +} + +func processes() ([]Process, error) { + m, err := darwincgo.ProcessMap() + if err != nil { + return nil, err + } + ps := make([]Process, 0, len(m)) + for _, dp := range m { + ps = append(ps, dp) + } + return ps, nil +} diff --git a/vendor/github.com/keybase/go-ps/process_darwin_test.go b/vendor/github.com/keybase/go-ps/process_darwin_test.go new file mode 100644 index 0000000..31ef433 --- /dev/null +++ b/vendor/github.com/keybase/go-ps/process_darwin_test.go @@ -0,0 +1,38 @@ +// +build darwin + +package ps + +import ( + "os" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestFindProcessDarwin(t *testing.T) { + proc := testFindProcess(t, "go-ps.test") + assert.True(t, proc.PPid() > 0) +} + +func TestProcessesDarwin(t *testing.T) { + testProcesses(t, "go") +} + +func TestProcessesDarwinError(t *testing.T) { + proc, err := findProcess(-1) + assert.Nil(t, proc) + assert.Nil(t, err) +} + +func TestProcessExecRemoved(t *testing.T) { + procPath, cmd, proc := testExecRun(t) + defer cleanup(cmd, procPath) + t.Logf("Ran with PID: %d", cmd.Process.Pid) + // Remove it while it is running + _ = os.Remove(procPath) + matchPath := func(p Process) bool { return p.Pid() == proc.Pid() } + procs, err := findProcessesWithFn(processes, matchPath, 1) + require.NoError(t, err) + t.Logf("Proc: %#v", procs[0]) +} diff --git a/vendor/github.com/keybase/go-ps/process_freebsd.go b/vendor/github.com/keybase/go-ps/process_freebsd.go new file mode 100644 index 0000000..33942c8 --- /dev/null +++ b/vendor/github.com/keybase/go-ps/process_freebsd.go @@ -0,0 +1,269 @@ +// +build freebsd,amd64 + +package ps + +import ( + "bytes" + "encoding/binary" + "fmt" + "syscall" + "unsafe" +) + +// copied from sys/sysctl.h +const ( + CTL_KERN = 1 // "high kernel": proc, limits + KERN_PROC = 14 // struct: process entries + KERN_PROC_PID = 1 // by process id + KERN_PROC_PROC = 8 // only return procs + KERN_PROC_PATHNAME = 12 // path to executable +) + +// copied from sys/user.h +type Kinfo_proc struct { + Ki_structsize int32 + Ki_layout int32 + Ki_args int64 + Ki_paddr int64 + Ki_addr int64 + Ki_tracep int64 + Ki_textvp int64 + Ki_fd int64 + Ki_vmspace int64 + Ki_wchan int64 + Ki_pid int32 + Ki_ppid int32 + Ki_pgid int32 + Ki_tpgid int32 + Ki_sid int32 + Ki_tsid int32 + Ki_jobc [2]byte + Ki_spare_short1 [2]byte + Ki_tdev int32 + Ki_siglist [16]byte + Ki_sigmask [16]byte + Ki_sigignore [16]byte + Ki_sigcatch [16]byte + Ki_uid int32 + Ki_ruid int32 + Ki_svuid int32 + Ki_rgid int32 + Ki_svgid int32 + Ki_ngroups [2]byte + Ki_spare_short2 [2]byte + Ki_groups [64]byte + Ki_size int64 + Ki_rssize int64 + Ki_swrss int64 + Ki_tsize int64 + Ki_dsize int64 + Ki_ssize int64 + Ki_xstat [2]byte + Ki_acflag [2]byte + Ki_pctcpu int32 + Ki_estcpu int32 + Ki_slptime int32 + Ki_swtime int32 + Ki_cow int32 + Ki_runtime int64 + Ki_start [16]byte + Ki_childtime [16]byte + Ki_flag int64 + Ki_kiflag int64 + Ki_traceflag int32 + Ki_stat [1]byte + Ki_nice [1]byte + Ki_lock [1]byte + Ki_rqindex [1]byte + Ki_oncpu [1]byte + Ki_lastcpu [1]byte + Ki_ocomm [17]byte + Ki_wmesg [9]byte + Ki_login [18]byte + Ki_lockname [9]byte + Ki_comm [20]byte + Ki_emul [17]byte + Ki_sparestrings [68]byte + Ki_spareints [36]byte + Ki_cr_flags int32 + Ki_jid int32 + Ki_numthreads int32 + Ki_tid int32 + Ki_pri int32 + Ki_rusage [144]byte + Ki_rusage_ch [144]byte + Ki_pcb int64 + Ki_kstack int64 + Ki_udata int64 + Ki_tdaddr int64 + Ki_spareptrs [48]byte + Ki_spareint64s [96]byte + Ki_sflag int64 + Ki_tdflags int64 +} + +// UnixProcess is an implementation of Process that contains Unix-specific +// fields and information. +type UnixProcess struct { + pid int + ppid int + state rune + pgrp int + sid int + + binary string +} + +// Pid returns process id +func (p *UnixProcess) Pid() int { + return p.pid +} + +// PPid returns parent process id +func (p *UnixProcess) PPid() int { + return p.ppid +} + +// Executable returns process executable name +func (p *UnixProcess) Executable() string { + return p.binary +} + +// Path returns path to process executable +func (p *UnixProcess) Path() (string, error) { + return "", fmt.Errorf("Unsupported") +} + +// Refresh reloads all the data associated with this process. +func (p *UnixProcess) Refresh() error { + + mib := []int32{CTL_KERN, KERN_PROC, KERN_PROC_PID, int32(p.pid)} + + buf, length, err := call_syscall(mib) + if err != nil { + return err + } + proc_k := Kinfo_proc{} + if length != uint64(unsafe.Sizeof(proc_k)) { + return err + } + + k, err := parse_kinfo_proc(buf) + if err != nil { + return err + } + + p.ppid, p.pgrp, p.sid, p.binary = copy_params(&k) + return nil +} + +func copy_params(k *Kinfo_proc) (int, int, int, string) { + n := -1 + for i, b := range k.Ki_comm { + if b == 0 { + break + } + n = i + 1 + } + comm := string(k.Ki_comm[:n]) + + return int(k.Ki_ppid), int(k.Ki_pgid), int(k.Ki_sid), comm +} + +func findProcess(pid int) (Process, error) { + mib := []int32{CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, int32(pid)} + + _, _, err := call_syscall(mib) + if err != nil { + return nil, err + } + + return newUnixProcess(pid) +} + +func processes() ([]Process, error) { + results := make([]Process, 0, 50) + + mib := []int32{CTL_KERN, KERN_PROC, KERN_PROC_PROC, 0} + buf, length, err := call_syscall(mib) + if err != nil { + return results, err + } + + // get kinfo_proc size + k := Kinfo_proc{} + procinfo_len := int(unsafe.Sizeof(k)) + count := int(length / uint64(procinfo_len)) + + // parse buf to procs + for i := 0; i < count; i++ { + b := buf[i*procinfo_len : i*procinfo_len+procinfo_len] + k, err := parse_kinfo_proc(b) + if err != nil { + continue + } + p, err := newUnixProcess(int(k.Ki_pid)) + if err != nil { + continue + } + p.ppid, p.pgrp, p.sid, p.binary = copy_params(&k) + + results = append(results, p) + } + + return results, nil +} + +func parse_kinfo_proc(buf []byte) (Kinfo_proc, error) { + var k Kinfo_proc + br := bytes.NewReader(buf) + err := binary.Read(br, binary.LittleEndian, &k) + if err != nil { + return k, err + } + + return k, nil +} + +func call_syscall(mib []int32) ([]byte, uint64, error) { + miblen := uint64(len(mib)) + + // get required buffer size + length := uint64(0) + _, _, err := syscall.RawSyscall6( + syscall.SYS___SYSCTL, + uintptr(unsafe.Pointer(&mib[0])), + uintptr(miblen), + 0, + uintptr(unsafe.Pointer(&length)), + 0, + 0) + if err != 0 { + b := make([]byte, 0) + return b, length, err + } + if length == 0 { + b := make([]byte, 0) + return b, length, err + } + // get proc info itself + buf := make([]byte, length) + _, _, err = syscall.RawSyscall6( + syscall.SYS___SYSCTL, + uintptr(unsafe.Pointer(&mib[0])), + uintptr(miblen), + uintptr(unsafe.Pointer(&buf[0])), + uintptr(unsafe.Pointer(&length)), + 0, + 0) + if err != 0 { + return buf, length, err + } + + return buf, length, nil +} + +func newUnixProcess(pid int) (*UnixProcess, error) { + p := &UnixProcess{pid: pid} + return p, p.Refresh() +} diff --git a/vendor/github.com/keybase/go-ps/process_nix_test.go b/vendor/github.com/keybase/go-ps/process_nix_test.go new file mode 100644 index 0000000..ed2aec2 --- /dev/null +++ b/vendor/github.com/keybase/go-ps/process_nix_test.go @@ -0,0 +1,93 @@ +// +build darwin linux + +package ps + +import ( + "io" + "os" + "os/exec" + "path/filepath" + "testing" + + "github.com/stretchr/testify/require" +) + +func TestProcessExecRun(t *testing.T) { + procPath, cmd, _ := testExecRun(t) + defer cleanup(cmd, procPath) +} + +func testProcessPath(t *testing.T, procPath string) Process { + matchPath := func(p Process) bool { + return matchPath(t, p, procPath) + } + procs, err := findProcessesWithFn(processes, matchPath, 1) + require.NoError(t, err) + + require.Equal(t, 1, len(procs)) + proc := procs[0] + path, err := proc.Path() + require.NoError(t, err) + require.Equal(t, procPath, path) + return proc +} + +func cleanup(cmd *exec.Cmd, procPath string) { + if cmd != nil && cmd.Process != nil { + _ = cmd.Process.Kill() + } + _ = os.Remove(procPath) +} + +func testExecPath(t *testing.T) string { + // Copy sleep executable to tmp + procPath := filepath.Join(os.TempDir(), "sleeptest") + err := copyFile("/bin/sleep", procPath, 0777) + require.NoError(t, err) + // Temp dir might have symlinks in which case we need the eval'ed path + procPath, err = filepath.EvalSymlinks(procPath) + require.NoError(t, err) + return procPath +} + +func testExecRun(t *testing.T) (string, *exec.Cmd, Process) { + procPath := testExecPath(t) + cmd := exec.Command(procPath, "10") + err := cmd.Start() + require.NoError(t, err) + proc := testProcessPath(t, procPath) + return procPath, cmd, proc +} + +func copyFile(sourcePath string, destinationPath string, mode os.FileMode) error { + in, err := os.Open(sourcePath) + if err != nil { + return err + } + defer func() { _ = in.Close() }() + + out, err := os.Create(destinationPath) + if err != nil { + return err + } + defer func() { _ = out.Close() }() + _, err = io.Copy(out, in) + closeErr := out.Close() + if err != nil { + return err + } + err = os.Chmod(destinationPath, mode) + if err != nil { + return err + } + return closeErr +} + +func matchPath(t *testing.T, p Process, match string) bool { + path, err := p.Path() + if err != nil { + t.Logf("Error trying to get path: %s", err) + return false + } + return path == match +} diff --git a/vendor/github.com/keybase/go-ps/process_openbsd.go b/vendor/github.com/keybase/go-ps/process_openbsd.go new file mode 100644 index 0000000..51c446d --- /dev/null +++ b/vendor/github.com/keybase/go-ps/process_openbsd.go @@ -0,0 +1,302 @@ +// +build openbsd + +package ps + +import ( + "bytes" + "encoding/binary" + "fmt" + "syscall" + "unsafe" +) + +// copied from sys/sysctl.h +const ( + CTL_KERN = 1 + KERN_PROC = 66 + KERN_PROC_PID = 1 + KERN_PROC_ARGS = 55 + KERN_PROC_ARGV = 1 + KERN_PROC_ALL = 0 +) + +/* Generated via cgo: + +$ cat /tmp/gen_defs.go +// +build ignore +package ps +// #include +// #include +import "C" + +type Kinfo_proc C.struct_kinfo_proc + +$ go tool cgo -godefs temp.go + +*/ + +type Kinfo_proc struct { + Ki_forw uint64 + Ki_back uint64 + Ki_paddr uint64 + Ki_addr uint64 + Ki_fd uint64 + Ki_stats uint64 + Ki_limit uint64 + Ki_vmspace uint64 + Ki_sigacts uint64 + Ki_sess uint64 + Ki_tsess uint64 + Ki_ru uint64 + Ki_eflag int32 + Ki_exitsig int32 + Ki_flag int32 + Ki_pid int32 + Ki_ppid int32 + Ki_sid int32 + Ki_x_pgid int32 + Ki_tpgid int32 + Ki_uid uint32 + Ki_ruid uint32 + Ki_gid uint32 + Ki_rgid uint32 + Ki_groups [16]uint32 + Ki_ngroups int16 + Ki_jobc int16 + Ki_tdev uint32 + Ki_estcpu uint32 + Ki_rtime_sec uint32 + Ki_rtime_usec uint32 + Ki_cpticks int32 + Ki_pctcpu uint32 + Ki_swtime uint32 + Ki_slptime uint32 + Ki_schedflags int32 + Ki_uticks uint64 + Ki_sticks uint64 + Ki_iticks uint64 + Ki_tracep uint64 + Ki_traceflag int32 + Ki_holdcnt int32 + Ki_siglist int32 + Ki_sigmask uint32 + Ki_sigignore uint32 + Ki_sigcatch uint32 + Ki_stat int8 + Ki_priority uint8 + Ki_usrpri uint8 + Ki_nice uint8 + Ki_xstat uint16 + Ki_acflag uint16 + //Ki_comm [24]int8 + Ki_comm [20]byte + Ki_wmesg [8]int8 + Ki_wchan uint64 + Ki_login [32]int8 + Ki_vm_rssize int32 + Ki_vm_tsize int32 + Ki_vm_dsize int32 + Ki_vm_ssize int32 + Ki_uvalid int64 + Ki_ustart_sec uint64 + Ki_ustart_usec uint32 + Ki_uutime_sec uint32 + Ki_uutime_usec uint32 + Ki_ustime_sec uint32 + Ki_ustime_usec uint32 + Ki_pad_cgo_0 [4]byte + Ki_uru_maxrss uint64 + Ki_uru_ixrss uint64 + Ki_uru_idrss uint64 + Ki_uru_isrss uint64 + Ki_uru_minflt uint64 + Ki_uru_majflt uint64 + Ki_uru_nswap uint64 + Ki_uru_inblock uint64 + Ki_uru_oublock uint64 + Ki_uru_msgsnd uint64 + Ki_uru_msgrcv uint64 + Ki_uru_nsignals uint64 + Ki_uru_nvcsw uint64 + Ki_uru_nivcsw uint64 + Ki_uctime_sec uint32 + Ki_uctime_usec uint32 + Ki_psflags int32 + Ki_spare int32 + Ki_svuid uint32 + Ki_svgid uint32 + Ki_emul [8]int8 + Ki_rlim_rss_cur uint64 + Ki_cpuid uint64 + Ki_vm_map_size uint64 + Ki_tid int32 + Ki_rtableid uint32 +} + +var proc_k_size = unsafe.Sizeof(Kinfo_proc{}) + +// UnixProcess is an implementation of Process that contains Unix-specific +// fields and information. +type UnixProcess struct { + pid int + ppid int + state rune + pgrp int + sid int + + binary string +} + +// Pid returns process id +func (p *UnixProcess) Pid() int { + return p.pid +} + +// PPid returns parent process id +func (p *UnixProcess) PPid() int { + return p.ppid +} + +// Executable returns process executable name +func (p *UnixProcess) Executable() string { + return p.binary +} + +// Path returns path to process executable +func (p *UnixProcess) Path() (string, error) { + // On OpenBSD we don't have the actual path of a binary, the next + // best thing we can do is walk $PATH to hopefully find the binary. + // More info here: https://github.com/kardianos/osext/commit/b4814f465fb1f92d46e37f7ef84d732ece7c3e3a + return "", fmt.Errorf("Unsupported") +} + +// Refresh reloads all the data associated with this process. +func (p *UnixProcess) Refresh() error { + mib := []int32{CTL_KERN, KERN_PROC, KERN_PROC_PID, int32(p.pid), int32(proc_k_size), 1} + + buf, length, err := call_syscall(mib) + if err != nil { + return err + } + if length != uint64(proc_k_size) { + return err + } + + k, err := parse_kinfo_proc(buf) + if err != nil { + return err + } + + p.ppid, p.pgrp, p.sid, p.binary = copy_params(&k) + return nil +} + +func copy_params(k *Kinfo_proc) (int, int, int, string) { + n := -1 + for i, b := range k.Ki_comm { + if b == 0 { + break + } + n = i + 1 + } + comm := string(k.Ki_comm[:n]) + + return int(k.Ki_ppid), int(k.Ki_x_pgid), int(k.Ki_sid), comm +} + +func findProcess(pid int) (Process, error) { + mib := []int32{CTL_KERN, KERN_PROC, KERN_PROC_PID, int32(pid), int32(proc_k_size), 1} + + _, _, err := call_syscall(mib) + if err != nil { + return nil, err + } + + return newUnixProcess(pid) +} + +func processes() ([]Process, error) { + results := make([]Process, 0, 50) + + mib := []int32{CTL_KERN, KERN_PROC, KERN_PROC_ALL, 0, int32(proc_k_size), 400} + buf, length, err := call_syscall(mib) + if err != nil { + return results, err + } + + // get kinfo_proc size + procinfo_len := int(proc_k_size) + count := int(length / uint64(proc_k_size)) + + // parse buf to procs + for i := 0; i < count; i++ { + b := buf[i*procinfo_len : i*procinfo_len+procinfo_len] + k, err := parse_kinfo_proc(b) + if err != nil { + continue + } + p, err := newUnixProcess(int(k.Ki_pid)) + if err != nil { + continue + } + p.ppid, p.pgrp, p.sid, p.binary = copy_params(&k) + + results = append(results, p) + } + + return results, nil +} + +func parse_kinfo_proc(buf []byte) (Kinfo_proc, error) { + var k Kinfo_proc + br := bytes.NewReader(buf) + err := binary.Read(br, binary.LittleEndian, &k) + if err != nil { + return k, err + } + + return k, nil +} + +func call_syscall(mib []int32) ([]byte, uint64, error) { + miblen := uint64(len(mib)) + + // get required buffer size + length := uint64(0) + _, _, err := syscall.RawSyscall6( + syscall.SYS___SYSCTL, + uintptr(unsafe.Pointer(&mib[0])), + uintptr(miblen), + 0, + uintptr(unsafe.Pointer(&length)), + 0, + 0) + if err != 0 { + b := make([]byte, 0) + return b, length, err + } + if length == 0 { + b := make([]byte, 0) + return b, length, err + } + // get proc info itself + buf := make([]byte, length) + _, _, err = syscall.RawSyscall6( + syscall.SYS___SYSCTL, + uintptr(unsafe.Pointer(&mib[0])), + uintptr(miblen), + uintptr(unsafe.Pointer(&buf[0])), + uintptr(unsafe.Pointer(&length)), + 0, + 0) + if err != 0 { + return buf, length, err + } + + return buf, length, nil +} + +func newUnixProcess(pid int) (*UnixProcess, error) { + p := &UnixProcess{pid: pid} + return p, p.Refresh() +} diff --git a/vendor/github.com/keybase/go-ps/process_openbsd_test.go b/vendor/github.com/keybase/go-ps/process_openbsd_test.go new file mode 100644 index 0000000..1db63ef --- /dev/null +++ b/vendor/github.com/keybase/go-ps/process_openbsd_test.go @@ -0,0 +1,28 @@ +// +build openbsd + +package ps + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestFindProcessOpenBSD(t *testing.T) { + proc := testFindProcess(t, "go-ps.test") + assert.True(t, proc.PPid() > 0) +} + +func TestProcessesOpenBSD(t *testing.T) { + testProcesses(t, "go") +} + +/* +// Currently querying for -1 will return -1 :P + +func TestProcessesOpenBSDError(t *testing.T) { + proc, err := findProcess(-1) + assert.Nil(t, proc) + assert.Nil(t, err) +} +*/ diff --git a/vendor/github.com/keybase/go-ps/process_test.go b/vendor/github.com/keybase/go-ps/process_test.go new file mode 100644 index 0000000..5df4166 --- /dev/null +++ b/vendor/github.com/keybase/go-ps/process_test.go @@ -0,0 +1,72 @@ +package ps + +import ( + "errors" + "os" + "runtime" + "strings" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func testFindProcess(t *testing.T, name string) Process { + proc, err := FindProcess(os.Getpid()) + require.NoError(t, err) + require.NotNil(t, proc) + assert.Equal(t, os.Getpid(), proc.Pid()) + + if name != "" { + assert.Equal(t, name, proc.Executable()) + path, err := proc.Path() + require.NoError(t, err) + t.Logf("Path: %s", path) + assert.True(t, strings.HasSuffix(path, string(os.PathSeparator)+name)) + + } + return proc +} + +func testProcesses(t *testing.T, name string) { + // This test works because there will always be SOME processes running + procs, err := Processes() + require.NoError(t, err) + require.True(t, len(procs) > 0) + + if name != "" { + found := false + for _, p := range procs { + if p.Executable() == name { + found = true + break + } + } + assert.True(t, found) + } +} + +func TestFindProcess(t *testing.T) { + testFindProcess(t, "") +} + +func TestFindProcessGo(t *testing.T) { + var exe = "go-ps.test" + if runtime.GOOS == "windows" { + exe += ".exe" + } + testFindProcess(t, exe) +} + +func TestProcesses(t *testing.T) { + testProcesses(t, "") +} + +func TestFindProcessesWithFnError(t *testing.T) { + ps, err := findProcessesWithFn(func() ([]Process, error) { return nil, errors.New("TestFindProcessesWithFn Error") }, nil, 0) + require.Nil(t, ps) + require.NotNil(t, err) + ps, err = findProcessesWithFn(func() ([]Process, error) { return nil, nil }, nil, 0) + require.Nil(t, ps) + require.Nil(t, err) +} diff --git a/vendor/github.com/keybase/go-ps/process_unix.go b/vendor/github.com/keybase/go-ps/process_unix.go new file mode 100644 index 0000000..f4e8da2 --- /dev/null +++ b/vendor/github.com/keybase/go-ps/process_unix.go @@ -0,0 +1,144 @@ +// +build linux + +package ps + +import ( + "fmt" + "io" + "io/ioutil" + "os" + "path/filepath" + "strconv" + "strings" +) + +// UnixProcess is an implementation of Process that contains Unix-specific +// fields and information. +type UnixProcess struct { + pid int + ppid int + state rune + pgrp int + sid int + + binary string // binary name might be truncated +} + +// Pid returns process id +func (p *UnixProcess) Pid() int { + return p.pid +} + +// PPid returns parent process id +func (p *UnixProcess) PPid() int { + return p.ppid +} + +// Executable returns process executable name +func (p *UnixProcess) Executable() string { + path, err := p.Path() + if err != nil { + // Fall back to binary name which might be truncated + return p.binary + } + return filepath.Base(path) +} + +// Path returns path to process executable +func (p *UnixProcess) Path() (string, error) { + return filepath.EvalSymlinks(fmt.Sprintf("/proc/%d/exe", p.pid)) +} + +// Refresh reloads all the data associated with this process. +func (p *UnixProcess) Refresh() error { + statPath := fmt.Sprintf("/proc/%d/stat", p.pid) + dataBytes, err := ioutil.ReadFile(statPath) + if err != nil { + return err + } + + // First, parse out the image name + data := string(dataBytes) + binStart := strings.IndexRune(data, '(') + 1 + binEnd := strings.IndexRune(data[binStart:], ')') + p.binary = data[binStart : binStart+binEnd] + + // Move past the image name and start parsing the rest + // The name here might not be the full name + data = data[binStart+binEnd+2:] + _, err = fmt.Sscanf(data, + "%c %d %d %d", + &p.state, + &p.ppid, + &p.pgrp, + &p.sid) + + return err +} + +func findProcess(pid int) (Process, error) { + dir := fmt.Sprintf("/proc/%d", pid) + _, err := os.Stat(dir) + if err != nil { + if os.IsNotExist(err) { + return nil, nil + } + + return nil, err + } + + return newUnixProcess(pid) +} + +func processes() ([]Process, error) { + d, err := os.Open("/proc") + if err != nil { + return nil, err + } + defer d.Close() + + results := make([]Process, 0, 50) + for { + fis, err := d.Readdir(10) + if err == io.EOF { + break + } + if err != nil { + return nil, err + } + + for _, fi := range fis { + // We only care about directories, since all pids are dirs + if !fi.IsDir() { + continue + } + + // We only care if the name starts with a numeric + name := fi.Name() + if name[0] < '0' || name[0] > '9' { + continue + } + + // From this point forward, any errors we just ignore, because + // it might simply be that the process doesn't exist anymore. + pid, err := strconv.ParseInt(name, 10, 0) + if err != nil { + continue + } + + p, err := newUnixProcess(int(pid)) + if err != nil { + continue + } + + results = append(results, p) + } + } + + return results, nil +} + +func newUnixProcess(pid int) (*UnixProcess, error) { + p := &UnixProcess{pid: pid} + return p, p.Refresh() +} diff --git a/vendor/github.com/keybase/go-ps/process_unix_test.go b/vendor/github.com/keybase/go-ps/process_unix_test.go new file mode 100644 index 0000000..162366a --- /dev/null +++ b/vendor/github.com/keybase/go-ps/process_unix_test.go @@ -0,0 +1,29 @@ +// +build linux + +package ps + +import ( + "os" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestUnixProcess(t *testing.T) { + var _ Process = new(UnixProcess) +} + +func TestProcessesUnixError(t *testing.T) { + proc, err := findProcess(-1) + assert.Nil(t, proc) + assert.Nil(t, err) +} + +func TestProcessesUnixPPid(t *testing.T) { + proc, err := FindProcess(os.Getpid()) + require.NoError(t, err) + require.NotNil(t, proc) + assert.Equal(t, os.Getpid(), proc.Pid()) + assert.Equal(t, os.Getppid(), proc.PPid()) +} diff --git a/vendor/github.com/keybase/go-ps/process_windows.go b/vendor/github.com/keybase/go-ps/process_windows.go new file mode 100644 index 0000000..e4d89e3 --- /dev/null +++ b/vendor/github.com/keybase/go-ps/process_windows.go @@ -0,0 +1,196 @@ +// +build windows + +package ps + +import ( + "fmt" + "syscall" + "unsafe" +) + +// Windows API functions +var ( + modKernel32 = syscall.NewLazyDLL("kernel32.dll") + procCloseHandle = modKernel32.NewProc("CloseHandle") + procCreateToolhelp32Snapshot = modKernel32.NewProc("CreateToolhelp32Snapshot") + procProcess32First = modKernel32.NewProc("Process32FirstW") + procProcess32Next = modKernel32.NewProc("Process32NextW") + procModule32First = modKernel32.NewProc("Module32FirstW") + procModule32Next = modKernel32.NewProc("Module32NextW") +) + +// Some constants from the Windows API +const ( + ERROR_NO_MORE_FILES = 0x12 + MAX_PATH = 260 + MAX_MODULE_NAME32 = 255 +) + +type PROCESSENTRY32 struct { + Size uint32 + CntUsage uint32 + ProcessID uint32 + DefaultHeapID uintptr + ModuleID uint32 + CntThreads uint32 + ParentProcessID uint32 + PriorityClassBase int32 + Flags uint32 + ExeFile [MAX_PATH]uint16 +} + +// WindowsProcess is an implementation of Process for Windows. +type WindowsProcess struct { + pid int + ppid int + exe string +} + +// Pid returns process id +func (p *WindowsProcess) Pid() int { + return p.pid +} + +// PPid returns parent process id +func (p *WindowsProcess) PPid() int { + return p.ppid +} + +// Executable returns process executable name +func (p *WindowsProcess) Executable() string { + return p.exe +} + +// Path returns path to process executable +func (p *WindowsProcess) Path() (string, error) { + processModules, err := modules(p.pid) + if err != nil { + return "", err + } + if len(processModules) == 0 { + return "", fmt.Errorf("No modules found for process") + } + return processModules[0].path, nil +} + +func ptrToString(c []uint16) string { + i := 0 + for { + if c[i] == 0 { + return syscall.UTF16ToString(c[:i]) + } + i++ + } +} + +func newWindowsProcess(e *PROCESSENTRY32) *WindowsProcess { + return &WindowsProcess{ + pid: int(e.ProcessID), + ppid: int(e.ParentProcessID), + exe: ptrToString(e.ExeFile[:]), + } +} + +func findProcess(pid int) (Process, error) { + return findProcessWithFn(processes, pid) +} + +func findProcessWithFn(processesFn processesFn, pid int) (Process, error) { + ps, err := processesFn() + if err != nil { + return nil, fmt.Errorf("Error listing processes: %s", err) + } + + for _, p := range ps { + if p.Pid() == pid { + return p, nil + } + } + + return nil, nil +} + +func processes() ([]Process, error) { + handle, _, _ := procCreateToolhelp32Snapshot.Call( + 0x00000002, + 0) + if handle < 0 { + return nil, syscall.GetLastError() + } + defer procCloseHandle.Call(handle) + + var entry PROCESSENTRY32 + entry.Size = uint32(unsafe.Sizeof(entry)) + ret, _, _ := procProcess32First.Call(handle, uintptr(unsafe.Pointer(&entry))) + if ret == 0 { + return nil, fmt.Errorf("Error retrieving process info.") + } + + results := make([]Process, 0, 50) + for { + results = append(results, newWindowsProcess(&entry)) + + ret, _, _ := procProcess32Next.Call(handle, uintptr(unsafe.Pointer(&entry))) + if ret == 0 { + break + } + } + + return results, nil +} + +// MODULEENTRY32 is the Windows API structure that contains a modules's +// information. +type MODULEENTRY32 struct { + Size uint32 + ModuleID uint32 + ProcessID uint32 + GlblcntUsage uint32 + ProccntUsage uint32 + ModBaseAddr *uint8 + ModBaseSize uint32 + HModule uintptr + SzModule [MAX_MODULE_NAME32 + 1]uint16 + SzExePath [MAX_PATH]uint16 +} + +type windowsModule struct { + name string + path string +} + +func newWindowsModule(e *MODULEENTRY32) windowsModule { + return windowsModule{ + name: ptrToString(e.SzModule[:]), + path: ptrToString(e.SzExePath[:]), + } +} + +func modules(pid int) ([]windowsModule, error) { + handle, _, _ := procCreateToolhelp32Snapshot.Call( + 0x00000008, // TH32CS_SNAPMODULE + uintptr(uint32(pid))) + if handle < 0 { + return nil, syscall.GetLastError() + } + defer procCloseHandle.Call(handle) + + var entry MODULEENTRY32 + entry.Size = uint32(unsafe.Sizeof(entry)) + ret, _, _ := procModule32First.Call(handle, uintptr(unsafe.Pointer(&entry))) + if ret == 0 { + return nil, fmt.Errorf("Error retrieving module info") + } + + results := make([]windowsModule, 0, 50) + for { + results = append(results, newWindowsModule(&entry)) + + ret, _, _ := procModule32Next.Call(handle, uintptr(unsafe.Pointer(&entry))) + if ret == 0 { + break + } + } + + return results, nil +} diff --git a/vendor/github.com/keybase/go-ps/process_windows_test.go b/vendor/github.com/keybase/go-ps/process_windows_test.go new file mode 100644 index 0000000..17f3aef --- /dev/null +++ b/vendor/github.com/keybase/go-ps/process_windows_test.go @@ -0,0 +1,29 @@ +// +build windows + +package ps + +import ( + "fmt" + "os" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestFindProcessWindows(t *testing.T) { + proc := testFindProcess(t, "go-ps.test.exe") + assert.True(t, proc.PPid() > 0) +} + +func TestProcessesWindows(t *testing.T) { + testProcesses(t, "go.exe") +} + +func TestProcessesWindowsError(t *testing.T) { + errFn := func() ([]Process, error) { + return nil, fmt.Errorf("oops") + } + proc, err := findProcessWithFn(errFn, os.Getpid()) + assert.Nil(t, proc) + assert.EqualError(t, err, "Error listing processes: oops") +} diff --git a/vendor/golang.org/x/arch/AUTHORS b/vendor/golang.org/x/arch/AUTHORS new file mode 100644 index 0000000..2b00ddb --- /dev/null +++ b/vendor/golang.org/x/arch/AUTHORS @@ -0,0 +1,3 @@ +# This source code refers to The Go Authors for copyright purposes. +# The master list of authors is in the main Go distribution, +# visible at https://tip.golang.org/AUTHORS. diff --git a/vendor/golang.org/x/arch/CONTRIBUTING.md b/vendor/golang.org/x/arch/CONTRIBUTING.md new file mode 100644 index 0000000..88dff59 --- /dev/null +++ b/vendor/golang.org/x/arch/CONTRIBUTING.md @@ -0,0 +1,31 @@ +# Contributing to Go + +Go is an open source project. + +It is the work of hundreds of contributors. We appreciate your help! + + +## Filing issues + +When [filing an issue](https://golang.org/issue/new), make sure to answer these five questions: + +1. What version of Go are you using (`go version`)? +2. What operating system and processor architecture are you using? +3. What did you do? +4. What did you expect to see? +5. What did you see instead? + +General questions should go to the [golang-nuts mailing list](https://groups.google.com/group/golang-nuts) instead of the issue tracker. +The gophers there will answer or ask you to file an issue if you've tripped over a bug. + +## Contributing code + +Please read the [Contribution Guidelines](https://golang.org/doc/contribute.html) +before sending patches. + +**We do not accept GitHub pull requests** +(we use [Gerrit](https://code.google.com/p/gerrit/) instead for code review). + +Unless otherwise noted, the Go source files are distributed under +the BSD-style license found in the LICENSE file. + diff --git a/vendor/golang.org/x/arch/CONTRIBUTORS b/vendor/golang.org/x/arch/CONTRIBUTORS new file mode 100644 index 0000000..1fbd3e9 --- /dev/null +++ b/vendor/golang.org/x/arch/CONTRIBUTORS @@ -0,0 +1,3 @@ +# This source code was written by the Go contributors. +# The master list of contributors is in the main Go distribution, +# visible at https://tip.golang.org/CONTRIBUTORS. diff --git a/vendor/golang.org/x/arch/LICENSE b/vendor/golang.org/x/arch/LICENSE new file mode 100644 index 0000000..d29b372 --- /dev/null +++ b/vendor/golang.org/x/arch/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2015 The Go Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/golang.org/x/arch/PATENTS b/vendor/golang.org/x/arch/PATENTS new file mode 100644 index 0000000..7330990 --- /dev/null +++ b/vendor/golang.org/x/arch/PATENTS @@ -0,0 +1,22 @@ +Additional IP Rights Grant (Patents) + +"This implementation" means the copyrightable works distributed by +Google as part of the Go project. + +Google 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, +transfer and otherwise run, modify and propagate the contents of this +implementation of Go, where such license applies only to those patent +claims, both currently owned or controlled by Google and acquired in +the future, licensable by Google that are necessarily infringed by this +implementation of Go. This grant does not include claims that would be +infringed only as a consequence of further modification of this +implementation. If you or your agent or exclusive licensee institute or +order or agree to the institution of patent litigation against any +entity (including a cross-claim or counterclaim in a lawsuit) alleging +that this implementation of Go or any code incorporated within this +implementation of Go constitutes direct or contributory patent +infringement, or inducement of patent infringement, then any patent +rights granted to you under this License for this implementation of Go +shall terminate as of the date such litigation is filed. diff --git a/vendor/golang.org/x/arch/README b/vendor/golang.org/x/arch/README new file mode 100644 index 0000000..9563464 --- /dev/null +++ b/vendor/golang.org/x/arch/README @@ -0,0 +1,7 @@ +This repository holds machine architecture information used by the Go toolchain. +The parts needed in the main Go repository are copied in. + +This repository requires Go 1.6, or Go 1.5 with the vendor experiment enabled: + + export GO15VENDOREXPERIMENT=1 + diff --git a/vendor/golang.org/x/arch/arm/arm.csv b/vendor/golang.org/x/arch/arm/arm.csv new file mode 100644 index 0000000..c40ade9 --- /dev/null +++ b/vendor/golang.org/x/arch/arm/arm.csv @@ -0,0 +1,454 @@ +# arm instruction description version 0.01. +# https://golang.org/x/arch/arm +# +# This file contains a block of comment lines, each beginning with #, +# followed by entries in CSV format. All the # comments are at the top +# of the file, so a reader can skip past the comments and hand the +# rest of the file to a standard CSV reader. +# +# Each line in the CSV section contains 5 fields: +# +# mask value mnemonic encoding tags +# +# The mnemonic and encoding correspond to the notation used in the +# ARM Architecture Reference Manual. +# +# A particular instruction word w matches a line if w&mask == value. +# The mask and value are computed from a combination of the encodings +# and the additional pseudocode restrictions given in the manual +# for each instruction. +# +# Multiple lines may match a particular instruction word. +# The tags specify which line takes priority in these cases, +# as a partial order. Eventually the plan is that a tag of the form +# 'name:x' marks a line with the name x, and a tag of the form +# 'except:x' says that the line on which the tag appears is of lower +# priority than the ones marked with name x. +# For now, however, a tag of the form 'SEE XXX' is taken from the +# manual and is like 'except:x' but without a rigorous resolution for +# the x. So far we've been able to just sort instructions into two classes: +# those with SEE and those without. +# +# The tag 'pseudo' indicates that this instruction is an alternate name +# for another encoding and should be ignored during disassembly. +# +# This file was generated by a program reading the PDF version of +# the manual, but it was then hand edited to make corrections. +# The eventual plan is for the generator to write the +# file directly, using the PDF and a list of modifications, but +# no hand editing. Then, when a new version of the manual comes out, +# updating the list should be as easy as downloading the new PDF +# and invoking the generator. However, we are not there yet. +# +"0x0fe00000","0x02a00000","ADC{S} ,,#","cond:4|0|0|1|0|1|0|1|S|Rn:4|Rd:4|imm12:12","SEE SUBS PC, LR and related instructions" +"0x0fe00090","0x00a00010","ADC{S} ,,, ","cond:4|0|0|0|0|1|0|1|S|Rn:4|Rd:4|Rs:4|0|type:2|1|Rm:4","" +"0x0fe00010","0x00a00000","ADC{S} ,,{,}","cond:4|0|0|0|0|1|0|1|S|Rn:4|Rd:4|imm5:5|type:2|0|Rm:4","SEE SUBS PC, LR and related instructions" +"0x0fe00000","0x02800000","ADD{S} ,,#","cond:4|0|0|1|0|1|0|0|S|Rn:4|Rd:4|imm12:12","SEE ADR SEE ADD (SP plus immediate) SEE SUBS PC, LR and related instructions" +"0x0fe00090","0x00800010","ADD{S} ,,, ","cond:4|0|0|0|0|1|0|0|S|Rn:4|Rd:4|Rs:4|0|type:2|1|Rm:4","" +"0x0fe00010","0x00800000","ADD{S} ,,{,}","cond:4|0|0|0|0|1|0|0|S|Rn:4|Rd:4|imm5:5|type:2|0|Rm:4","SEE SUBS PC, LR and related instructions SEE ADD (SP plus register)" +"0x0fef0000","0x028d0000","ADD{S} ,SP,#","cond:4|0|0|1|0|1|0|0|S|1|1|0|1|Rd:4|imm12:12","SEE SUBS PC, LR and related instructions" +"0x0fef0010","0x008d0000","ADD{S} ,SP,{,}","cond:4|0|0|0|0|1|0|0|S|1|1|0|1|Rd:4|imm5:5|type:2|0|Rm:4","SEE SUBS PC, LR and related instructions" +"0x0fff0000","0x028f0000","ADR ,","cond:4|0|0|1|0|1|0|0|0|1|1|1|1|Rd:4|imm12:12","pseudo" +"0x0fff0000","0x024f0000","ADR ,","cond:4|0|0|1|0|0|1|0|0|1|1|1|1|Rd:4|imm12:12","pseudo" +"0x0fe00000","0x02000000","AND{S} ,,#","cond:4|0|0|1|0|0|0|0|S|Rn:4|Rd:4|imm12:12","SEE SUBS PC, LR and related instructions" +"0x0fe00090","0x00000010","AND{S} ,,, ","cond:4|0|0|0|0|0|0|0|S|Rn:4|Rd:4|Rs:4|0|type:2|1|Rm:4","" +"0x0fe00010","0x00000000","AND{S} ,,{,}","cond:4|0|0|0|0|0|0|0|S|Rn:4|Rd:4|imm5:5|type:2|0|Rm:4","SEE SUBS PC, LR and related instructions" +"0x0fef0070","0x01a00040","ASR{S} ,,#","cond:4|0|0|0|1|1|0|1|S|0|0|0|0|Rd:4|imm5:5|1|0|0|Rm:4","" +"0x0fef00f0","0x01a00050","ASR{S} ,,","cond:4|0|0|0|1|1|0|1|S|0|0|0|0|Rd:4|Rm:4|0|1|0|1|Rn:4","" +"0x0f000000","0x0a000000","B ","cond:4|1|0|1|0|imm24:24","" +"0x0fe0007f","0x07c0001f","BFC ,#,#","cond:4|0|1|1|1|1|1|0|msb:5|Rd:4|lsb:5|0|0|1|1|1|1|1","" +"0x0fe00070","0x07c00010","BFI ,,#,#","cond:4|0|1|1|1|1|1|0|msb:5|Rd:4|lsb:5|0|0|1|Rn:4","SEE BFC" +"0x0fe00000","0x03c00000","BIC{S} ,,#","cond:4|0|0|1|1|1|1|0|S|Rn:4|Rd:4|imm12:12","SEE SUBS PC, LR and related instructions" +"0x0fe00090","0x01c00010","BIC{S} ,,, ","cond:4|0|0|0|1|1|1|0|S|Rn:4|Rd:4|Rs:4|0|type:2|1|Rm:4","" +"0x0fe00010","0x01c00000","BIC{S} ,,{,}","cond:4|0|0|0|1|1|1|0|S|Rn:4|Rd:4|imm5:5|type:2|0|Rm:4","SEE SUBS PC, LR and related instructions" +"0x0ff000f0","0x01200070","BKPT #","cond:4|0|0|0|1|0|0|1|0|imm12:12|0|1|1|1|imm4:4","" +"0x0f000000","0x0b000000","BL ","cond:4|1|0|1|1|imm24:24","" +"0xfe000000","0xfa000000","BLX ","1|1|1|1|1|0|1|H|imm24:24","" +"0x0ffffff0","0x012fff30","BLX ","cond:4|0|0|0|1|0|0|1|0|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|0|0|1|1|Rm:4","" +"0x0ffffff0","0x012fff10","BX ","cond:4|0|0|0|1|0|0|1|0|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|0|0|0|1|Rm:4","" +"0x0ffffff0","0x012fff20","BXJ ","cond:4|0|0|0|1|0|0|1|0|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|0|0|1|0|Rm:4","" +"0xffffffff","0xf57ff01f","CLREX","1|1|1|1|0|1|0|1|0|1|1|1|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(0)|(0)|(0)|(0)|0|0|0|1|(1)|(1)|(1)|(1)","" +"0x0fff0ff0","0x016f0f10","CLZ ,","cond:4|0|0|0|1|0|1|1|0|(1)|(1)|(1)|(1)|Rd:4|(1)|(1)|(1)|(1)|0|0|0|1|Rm:4","" +"0x0ff0f000","0x03700000","CMN ,#","cond:4|0|0|1|1|0|1|1|1|Rn:4|(0)|(0)|(0)|(0)|imm12:12","" +"0x0ff0f090","0x01700010","CMN ,, ","cond:4|0|0|0|1|0|1|1|1|Rn:4|(0)|(0)|(0)|(0)|Rs:4|0|type:2|1|Rm:4","" +"0x0ff0f010","0x01700000","CMN ,{,}","cond:4|0|0|0|1|0|1|1|1|Rn:4|(0)|(0)|(0)|(0)|imm5:5|type:2|0|Rm:4","" +"0x0ff0f000","0x03500000","CMP ,#","cond:4|0|0|1|1|0|1|0|1|Rn:4|(0)|(0)|(0)|(0)|imm12:12","" +"0x0ff0f090","0x01500010","CMP ,, ","cond:4|0|0|0|1|0|1|0|1|Rn:4|(0)|(0)|(0)|(0)|Rs:4|0|type:2|1|Rm:4","" +"0x0ff0f010","0x01500000","CMP ,{,}","cond:4|0|0|0|1|0|1|0|1|Rn:4|(0)|(0)|(0)|(0)|imm5:5|type:2|0|Rm:4","" +"0x0ffffff0","0x0320f0f0","DBG #