mirror of
https://github.com/google/gops.git
synced 2024-11-24 08:22:25 +02:00
vendor: dep ensure again
This commit is contained in:
parent
d858829db9
commit
08cb2394b4
8
Gopkg.lock
generated
8
Gopkg.lock
generated
@ -19,9 +19,15 @@
|
||||
packages = ["arm/armasm","ppc64/ppc64asm","x86/x86asm"]
|
||||
revision = "f185940480d2c897e1ca8cf2f1be122e1258341b"
|
||||
|
||||
[[projects]]
|
||||
name = "rsc.io/goversion"
|
||||
packages = ["version"]
|
||||
revision = "84cd9d26d7efce780a7aaafd0944961371da741f"
|
||||
version = "v1.0.0"
|
||||
|
||||
[solve-meta]
|
||||
analyzer-name = "dep"
|
||||
analyzer-version = 1
|
||||
inputs-digest = "c464a3d83956b677421b9fc797a6c77aa6e94a28120ee71d2b19860a5ff39c20"
|
||||
inputs-digest = "4b494828d559e89fc1fe70b9bfdd0f5c8ad62ee16258a3b2bcf1028c140faa32"
|
||||
solver-name = "gps-cdcl"
|
||||
solver-version = 1
|
||||
|
27
vendor/rsc.io/goversion/LICENSE
generated
vendored
Normal file
27
vendor/rsc.io/goversion/LICENSE
generated
vendored
Normal file
@ -0,0 +1,27 @@
|
||||
Copyright (c) 2009 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.
|
37
vendor/rsc.io/goversion/README.md
generated
vendored
Normal file
37
vendor/rsc.io/goversion/README.md
generated
vendored
Normal file
@ -0,0 +1,37 @@
|
||||
# rsc.io/goversion
|
||||
|
||||
Goversion scans a directory tree and, for every executable it finds, prints
|
||||
the Go version used to build that executable.
|
||||
|
||||
Usage:
|
||||
|
||||
goversion [-crypto] [-v] path...
|
||||
|
||||
The list of paths can be individual files or directories; if the latter,
|
||||
goversion scans all files in the directory tree, not following symlinks.
|
||||
|
||||
Goversion scans inside of tar or gzipped tar archives that it finds (named
|
||||
`*.tar`, `*.tar.gz`, or `*.tgz`), but not recursively.
|
||||
|
||||
The `-crypto` flag causes goversion to print additional information about the
|
||||
crypto libraries linked into each executable.
|
||||
|
||||
The `-v` flag causes goversion to print information about every file it
|
||||
considers.
|
||||
|
||||
## Example
|
||||
|
||||
Scan /usr/bin for Go binaries and print their versions:
|
||||
|
||||
$ goversion /usr/bin
|
||||
/usr/bin/containerd go1.7.4
|
||||
/usr/bin/containerd-shim go1.7.4
|
||||
/usr/bin/ctr go1.7.4
|
||||
/usr/bin/docker go1.7.4
|
||||
/usr/bin/docker-proxy go1.7.4
|
||||
/usr/bin/dockerd go1.7.4
|
||||
/usr/bin/kbfsfuse go1.8.3
|
||||
/usr/bin/kbnm go1.8.3
|
||||
/usr/bin/keybase go1.8.3
|
||||
/usr/bin/snap go1.7.4
|
||||
/usr/bin/snapctl go1.7.4
|
BIN
vendor/rsc.io/goversion/goversion
generated
vendored
Executable file
BIN
vendor/rsc.io/goversion/goversion
generated
vendored
Executable file
Binary file not shown.
215
vendor/rsc.io/goversion/main.go
generated
vendored
Normal file
215
vendor/rsc.io/goversion/main.go
generated
vendored
Normal file
@ -0,0 +1,215 @@
|
||||
// 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.
|
||||
|
||||
// Goversion scans a directory tree and, for every executable it finds,
|
||||
// prints the Go version used to build that executable.
|
||||
//
|
||||
// Usage:
|
||||
//
|
||||
// goversion [-crypto] [-v] path...
|
||||
//
|
||||
// The list of paths can be individual files or directories; if the latter,
|
||||
// goversion scans all files in the directory tree, not following symlinks.
|
||||
//
|
||||
// Goversion scans inside of tar or gzipped tar archives that it finds
|
||||
// (named *.tar, *.tar.gz, or *.tgz), but not recursively.
|
||||
//
|
||||
// The -crypto flag causes goversion to print additional information
|
||||
// about the crypto libraries linked into each executable.
|
||||
//
|
||||
// The -v flag causes goversion to print information about every
|
||||
// file it considers.
|
||||
//
|
||||
// Example
|
||||
//
|
||||
// Scan /usr/bin for Go binaries and print their versions:
|
||||
//
|
||||
// $ goversion /usr/bin
|
||||
// /usr/bin/containerd go1.7.4
|
||||
// /usr/bin/containerd-shim go1.7.4
|
||||
// /usr/bin/ctr go1.7.4
|
||||
// /usr/bin/docker go1.7.4
|
||||
// /usr/bin/docker-proxy go1.7.4
|
||||
// /usr/bin/dockerd go1.7.4
|
||||
// /usr/bin/kbfsfuse go1.8.3
|
||||
// /usr/bin/kbnm go1.8.3
|
||||
// /usr/bin/keybase go1.8.3
|
||||
// /usr/bin/snap go1.7.4
|
||||
// /usr/bin/snapctl go1.7.4
|
||||
//
|
||||
package main // import "rsc.io/goversion"
|
||||
|
||||
import (
|
||||
"archive/tar"
|
||||
"compress/gzip"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"rsc.io/goversion/version"
|
||||
)
|
||||
|
||||
var (
|
||||
crypto = flag.Bool("crypto", false, "check kind of crypto library")
|
||||
verbose = flag.Bool("v", false, "print verbose information")
|
||||
)
|
||||
|
||||
func usage() {
|
||||
fmt.Fprintf(os.Stderr, "usage: goversion [-crypto] [-v] path...\n")
|
||||
flag.PrintDefaults()
|
||||
os.Exit(2)
|
||||
}
|
||||
|
||||
func main() {
|
||||
log.SetFlags(0)
|
||||
log.SetPrefix("goversion: ")
|
||||
flag.Usage = usage
|
||||
flag.Parse()
|
||||
if flag.NArg() == 0 {
|
||||
usage()
|
||||
}
|
||||
|
||||
for _, file := range flag.Args() {
|
||||
info, err := os.Stat(file)
|
||||
if err != nil {
|
||||
log.Print(err)
|
||||
continue
|
||||
}
|
||||
if info.IsDir() {
|
||||
scandir(file)
|
||||
} else {
|
||||
scanfile(file, file, info, true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func scandir(dir string) {
|
||||
filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
|
||||
if info.Mode().IsRegular() {
|
||||
scanfile(path, path, info, *verbose)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func scanfile(file, diskFile string, info os.FileInfo, mustPrint bool) {
|
||||
if strings.HasSuffix(file, ".tar") {
|
||||
if file != diskFile {
|
||||
fmt.Fprintf(os.Stderr, "%s: not scanning tar recursively\n", file)
|
||||
return
|
||||
}
|
||||
if mustPrint {
|
||||
fmt.Fprintf(os.Stderr, "%s: scanning tar archive\n", file)
|
||||
}
|
||||
scantar(file, info)
|
||||
return
|
||||
}
|
||||
if strings.HasSuffix(file, ".tar.gz") || strings.HasSuffix(file, ".tgz") {
|
||||
if file != diskFile {
|
||||
fmt.Fprintf(os.Stderr, "%s: not scanning tgz recursively\n", file)
|
||||
return
|
||||
}
|
||||
if mustPrint {
|
||||
fmt.Fprintf(os.Stderr, "%s: scanning tgz archive\n", file)
|
||||
}
|
||||
scantar(file, info)
|
||||
return
|
||||
}
|
||||
if info.Mode()&os.ModeSymlink != 0 {
|
||||
if mustPrint {
|
||||
fmt.Fprintf(os.Stderr, "%s: symlink\n", file)
|
||||
}
|
||||
return
|
||||
}
|
||||
if file == diskFile && info.Mode()&0111 == 0 {
|
||||
if mustPrint {
|
||||
fmt.Fprintf(os.Stderr, "%s: not executable\n", file)
|
||||
}
|
||||
return
|
||||
}
|
||||
v, err := version.ReadExe(diskFile)
|
||||
if err != nil {
|
||||
if mustPrint {
|
||||
fmt.Fprintf(os.Stderr, "%s: %v\n", file, err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
buildVersion := v.Release
|
||||
if *crypto {
|
||||
switch {
|
||||
case v.BoringCrypto && v.StandardCrypto:
|
||||
buildVersion += " (boring AND standard crypto!!!)"
|
||||
case v.BoringCrypto:
|
||||
buildVersion += " (boring crypto)"
|
||||
case v.StandardCrypto:
|
||||
buildVersion += " (standard crypto)"
|
||||
}
|
||||
}
|
||||
fmt.Printf("%s %s\n", file, buildVersion)
|
||||
}
|
||||
|
||||
type Version struct {
|
||||
Release string
|
||||
BoringCrypto bool
|
||||
StandardCrypto bool
|
||||
}
|
||||
|
||||
func scantar(file string, info os.FileInfo) {
|
||||
f, err := os.Open(file)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "%s: %v\n", file, err)
|
||||
return
|
||||
}
|
||||
defer f.Close()
|
||||
var r io.Reader = f
|
||||
if strings.HasSuffix(file, "z") {
|
||||
z, err := gzip.NewReader(r)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "%s: %v\n", file, err)
|
||||
return
|
||||
}
|
||||
defer z.Close()
|
||||
r = z
|
||||
}
|
||||
tr := tar.NewReader(r)
|
||||
for {
|
||||
hdr, err := tr.Next()
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
if hdr.Typeflag != tar.TypeReg {
|
||||
if *verbose {
|
||||
fmt.Fprintf(os.Stderr, "%s/%s: not regular file\n", file, hdr.Name)
|
||||
}
|
||||
continue
|
||||
}
|
||||
if hdr.Mode&0111 == 0 {
|
||||
if *verbose {
|
||||
fmt.Fprintf(os.Stderr, "%s/%s: not executable\n", file, hdr.Name)
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
// executable but not special
|
||||
tmp, err := ioutil.TempFile("", "goversion-")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
io.Copy(tmp, tr)
|
||||
tmpName := tmp.Name()
|
||||
info, err := tmp.Stat()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
tmp.Close()
|
||||
scanfile(file+"/"+hdr.Name, tmpName, info, *verbose)
|
||||
os.Remove(tmpName)
|
||||
}
|
||||
}
|
294
vendor/rsc.io/goversion/version/asm.go
generated
vendored
Normal file
294
vendor/rsc.io/goversion/version/asm.go
generated
vendored
Normal file
@ -0,0 +1,294 @@
|
||||
// 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.
|
||||
|
||||
package version
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
)
|
||||
|
||||
type matcher [][]uint32
|
||||
|
||||
const (
|
||||
pWild uint32 = 0xff00
|
||||
pAddr uint32 = 0x10000
|
||||
pEnd uint32 = 0x20000
|
||||
|
||||
opMaybe = 1 + iota
|
||||
opMust
|
||||
opDone
|
||||
opAnchor = 0x100
|
||||
opSub8 = 0x200
|
||||
opFlags = opAnchor | opSub8
|
||||
)
|
||||
|
||||
var amd64Matcher = matcher{
|
||||
{opMaybe,
|
||||
// _rt0_amd64_linux:
|
||||
// lea 0x8(%rsp), %rsi
|
||||
// mov (%rsp), %rdi
|
||||
// lea ADDR(%rip), %rax # main
|
||||
// jmpq *%rax
|
||||
0x48, 0x8d, 0x74, 0x24, 0x08,
|
||||
0x48, 0x8b, 0x3c, 0x24, 0x48,
|
||||
0x8d, 0x05, pWild | pAddr, pWild, pWild, pWild | pEnd,
|
||||
0xff, 0xe0,
|
||||
},
|
||||
{opMaybe,
|
||||
// _rt0_amd64_linux:
|
||||
// lea 0x8(%rsp), %rsi
|
||||
// mov (%rsp), %rdi
|
||||
// mov $ADDR, %eax # main
|
||||
// jmpq *%rax
|
||||
0x48, 0x8d, 0x74, 0x24, 0x08,
|
||||
0x48, 0x8b, 0x3c, 0x24,
|
||||
0xb8, pWild | pAddr, pWild, pWild, pWild,
|
||||
0xff, 0xe0,
|
||||
},
|
||||
{opMaybe,
|
||||
// _start (toward end)
|
||||
// lea __libc_csu_fini(%rip), %r8
|
||||
// lea __libc_csu_init(%rip), %rcx
|
||||
// lea ADDR(%rip), %rdi # main
|
||||
// callq *xxx(%rip)
|
||||
0x4c, 0x8d, 0x05, pWild, pWild, pWild, pWild,
|
||||
0x48, 0x8d, 0x0d, pWild, pWild, pWild, pWild,
|
||||
0x48, 0x8d, 0x3d, pWild | pAddr, pWild, pWild, pWild | pEnd,
|
||||
0xff, 0x15,
|
||||
},
|
||||
{opMaybe,
|
||||
// _start (toward end)
|
||||
// push %rsp (1)
|
||||
// mov $__libc_csu_fini, %r8 (7)
|
||||
// mov $__libc_csu_init, %rcx (7)
|
||||
// mov $ADDR, %rdi # main (7)
|
||||
// callq *xxx(%rip)
|
||||
0x54,
|
||||
0x49, 0xc7, 0xc0, pWild, pWild, pWild, pWild,
|
||||
0x48, 0xc7, 0xc1, pWild, pWild, pWild, pWild,
|
||||
0x48, 0xc7, 0xc7, pAddr | pWild, pWild, pWild, pWild,
|
||||
},
|
||||
{opMaybe | opAnchor,
|
||||
// main:
|
||||
// lea ADDR(%rip), %rax # rt0_go
|
||||
// jmpq *%rax
|
||||
0x48, 0x8d, 0x05, pWild | pAddr, pWild, pWild, pWild | pEnd,
|
||||
0xff, 0xe0,
|
||||
},
|
||||
{opMaybe | opAnchor,
|
||||
// main:
|
||||
// mov $ADDR, %eax
|
||||
// jmpq *%rax
|
||||
0xb8, pWild | pAddr, pWild, pWild, pWild,
|
||||
0xff, 0xe0,
|
||||
},
|
||||
{opMust | opAnchor,
|
||||
// rt0_go:
|
||||
// mov %rdi, %rax
|
||||
// mov %rsi, %rbx
|
||||
// sub %0x27, %rsp
|
||||
// and $0xfffffffffffffff0,%rsp
|
||||
// mov %rax,0x10(%rsp)
|
||||
// mov %rbx,0x18(%rsp)
|
||||
0x48, 0x89, 0xf8,
|
||||
0x48, 0x89, 0xf3,
|
||||
0x48, 0x83, 0xec, 0x27,
|
||||
0x48, 0x83, 0xe4, 0xf0,
|
||||
0x48, 0x89, 0x44, 0x24, 0x10,
|
||||
0x48, 0x89, 0x5c, 0x24, 0x18,
|
||||
},
|
||||
{opMust,
|
||||
// later in rt0_go:
|
||||
// mov %eax, (%rsp)
|
||||
// mov 0x18(%rsp), %rax
|
||||
// mov %rax, 0x8(%rsp)
|
||||
// callq runtime.args
|
||||
// callq runtime.osinit
|
||||
// callq runtime.schedinit (ADDR)
|
||||
// lea mainPC(%rip), %rax
|
||||
0x89, 0x04, 0x24,
|
||||
0x48, 0x8b, 0x44, 0x24, 0x18,
|
||||
0x48, 0x89, 0x44, 0x24, 0x08,
|
||||
0xe8, pWild, pWild, pWild, pWild,
|
||||
0xe8, pWild, pWild, pWild, pWild,
|
||||
0xe8, pWild, pWild, pWild, pWild,
|
||||
},
|
||||
{opMaybe,
|
||||
// later in rt0_go:
|
||||
// mov %eax, (%rsp)
|
||||
// mov 0x18(%rsp), %rax
|
||||
// mov %rax, 0x8(%rsp)
|
||||
// callq runtime.args
|
||||
// callq runtime.osinit
|
||||
// callq runtime.schedinit (ADDR)
|
||||
// lea other(%rip), %rdi
|
||||
0x89, 0x04, 0x24,
|
||||
0x48, 0x8b, 0x44, 0x24, 0x18,
|
||||
0x48, 0x89, 0x44, 0x24, 0x08,
|
||||
0xe8, pWild, pWild, pWild, pWild,
|
||||
0xe8, pWild, pWild, pWild, pWild,
|
||||
0xe8, pWild | pAddr, pWild, pWild, pWild | pEnd,
|
||||
0x48, 0x8d, 0x05,
|
||||
},
|
||||
{opMaybe,
|
||||
// later in rt0_go:
|
||||
// mov %eax, (%rsp)
|
||||
// mov 0x18(%rsp), %rax
|
||||
// mov %rax, 0x8(%rsp)
|
||||
// callq runtime.args
|
||||
// callq runtime.osinit
|
||||
// callq runtime.hashinit
|
||||
// callq runtime.schedinit (ADDR)
|
||||
// pushq $main.main
|
||||
0x89, 0x04, 0x24,
|
||||
0x48, 0x8b, 0x44, 0x24, 0x18,
|
||||
0x48, 0x89, 0x44, 0x24, 0x08,
|
||||
0xe8, pWild, pWild, pWild, pWild,
|
||||
0xe8, pWild, pWild, pWild, pWild,
|
||||
0xe8, pWild, pWild, pWild, pWild,
|
||||
0xe8, pWild | pAddr, pWild, pWild, pWild | pEnd,
|
||||
0x68,
|
||||
},
|
||||
{opDone | opSub8,
|
||||
// schedinit (toward end)
|
||||
// mov ADDR(%rip), %rax
|
||||
// test %rax, %rax
|
||||
// jne <short>
|
||||
// movq $0x7, ADDR(%rip)
|
||||
//
|
||||
0x48, 0x8b, 0x05, pWild, pWild, pWild, pWild,
|
||||
0x48, 0x85, 0xc0,
|
||||
0x75, pWild,
|
||||
0x48, 0xc7, 0x05, pWild | pAddr, pWild, pWild, pWild, 0x07, 0x00, 0x00, 0x00 | pEnd,
|
||||
},
|
||||
{opDone | opSub8,
|
||||
// schedinit (toward end)
|
||||
// mov ADDR(%rip), %rbx
|
||||
// cmp $0x0, %rbx
|
||||
// jne <short>
|
||||
// lea "unknown"(%rip), %rbx
|
||||
// mov %rbx, ADDR(%rip)
|
||||
// movq $7, (ADDR+8)(%rip)
|
||||
0x48, 0x8b, 0x1d, pWild, pWild, pWild, pWild,
|
||||
0x48, 0x83, 0xfb, 0x00,
|
||||
0x75, pWild,
|
||||
0x48, 0x8d, 0x1d, pWild, pWild, pWild, pWild,
|
||||
0x48, 0x89, 0x1d, pWild, pWild, pWild, pWild,
|
||||
0x48, 0xc7, 0x05, pWild | pAddr, pWild, pWild, pWild, 0x07, 0x00, 0x00, 0x00 | pEnd,
|
||||
},
|
||||
{opDone,
|
||||
// schedinit (toward end)
|
||||
// cmpq $0x0, ADDR(%rip)
|
||||
// jne <short>
|
||||
// lea "unknown"(%rip), %rax
|
||||
// mov %rax, ADDR(%rip)
|
||||
// lea ADDR(%rip), %rax
|
||||
// movq $7, 8(%rax)
|
||||
0x48, 0x83, 0x3d, pWild | pAddr, pWild, pWild, pWild, 0x00,
|
||||
0x75, pWild,
|
||||
0x48, 0x8d, 0x05, pWild, pWild, pWild, pWild,
|
||||
0x48, 0x89, 0x05, pWild, pWild, pWild, pWild,
|
||||
0x48, 0x8d, 0x05, pWild | pAddr, pWild, pWild, pWild | pEnd,
|
||||
0x48, 0xc7, 0x40, 0x08, 0x07, 0x00, 0x00, 0x00,
|
||||
},
|
||||
{opDone,
|
||||
// test %eax, %eax
|
||||
// jne <later>
|
||||
// lea "unknown"(RIP), %rax
|
||||
// mov %rax, ADDR(%rip)
|
||||
0x48, 0x85, 0xc0, 0x75, pWild, 0x48, 0x8d, 0x05, pWild, pWild, pWild, pWild, 0x48, 0x89, 0x05, pWild | pAddr, pWild, pWild, pWild | pEnd,
|
||||
},
|
||||
}
|
||||
|
||||
var debugMatch = flag.Bool("d", false, "print debug information")
|
||||
|
||||
func (m matcher) match(f exe, addr uint64) (uint64, bool) {
|
||||
data, err := f.ReadData(addr, 512)
|
||||
if err != nil {
|
||||
return 0, false
|
||||
}
|
||||
Matchers:
|
||||
for pc, p := range m {
|
||||
op := p[0]
|
||||
p = p[1:]
|
||||
Search:
|
||||
for i := 0; i <= len(data)-len(p); i++ {
|
||||
a := -1
|
||||
e := -1
|
||||
if i > 0 && op&opAnchor != 0 {
|
||||
break
|
||||
}
|
||||
for j := 0; j < len(p); j++ {
|
||||
b := byte(p[j])
|
||||
m := byte(p[j] >> 8)
|
||||
if data[i+j]&^m != b {
|
||||
continue Search
|
||||
}
|
||||
if p[j]&pAddr != 0 {
|
||||
a = j
|
||||
}
|
||||
if p[j]&pEnd != 0 {
|
||||
e = j + 1
|
||||
}
|
||||
}
|
||||
// matched
|
||||
if *debugMatch {
|
||||
fmt.Fprintf(os.Stderr, "match (%d) %#x+%d %x %x\n", pc, addr, i, p, data[i:i+len(p)])
|
||||
}
|
||||
if a != -1 {
|
||||
val := uint64(int32(binary.LittleEndian.Uint32(data[i+a:])))
|
||||
if e == -1 {
|
||||
addr = val
|
||||
} else {
|
||||
addr += uint64(i+e) + val
|
||||
}
|
||||
if op&opSub8 != 0 {
|
||||
addr -= 8
|
||||
}
|
||||
}
|
||||
if op&^opFlags == opDone {
|
||||
if *debugMatch {
|
||||
fmt.Fprintf(os.Stderr, "done %x\n", addr)
|
||||
}
|
||||
return addr, true
|
||||
}
|
||||
if a != -1 {
|
||||
// changed addr, so reload
|
||||
data, err = f.ReadData(addr, 512)
|
||||
if err != nil {
|
||||
return 0, false
|
||||
}
|
||||
}
|
||||
continue Matchers
|
||||
}
|
||||
// not matched
|
||||
if *debugMatch {
|
||||
fmt.Fprintf(os.Stderr, "no match (%d) %#x %x %x\n", pc, addr, p, data[:32])
|
||||
}
|
||||
if op&^opFlags == opMust {
|
||||
return 0, false
|
||||
}
|
||||
}
|
||||
// ran off end of matcher
|
||||
return 0, false
|
||||
}
|
||||
|
||||
func readBuildVersionX86Asm(f exe) (isGo bool, buildVersion string) {
|
||||
entry := f.Entry()
|
||||
if entry == 0 {
|
||||
return
|
||||
}
|
||||
addr, ok := amd64Matcher.match(f, entry)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
v, err := readBuildVersion(f, addr, 16)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
return true, v
|
||||
}
|
251
vendor/rsc.io/goversion/version/exe.go
generated
vendored
Normal file
251
vendor/rsc.io/goversion/version/exe.go
generated
vendored
Normal file
@ -0,0 +1,251 @@
|
||||
// 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.
|
||||
|
||||
package version
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"debug/elf"
|
||||
"debug/macho"
|
||||
"debug/pe"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
)
|
||||
|
||||
type sym struct {
|
||||
Name string
|
||||
Addr uint64
|
||||
Size uint64
|
||||
}
|
||||
|
||||
type exe interface {
|
||||
AddrSize() int // bytes
|
||||
ReadData(addr, size uint64) ([]byte, error)
|
||||
Symbols() ([]sym, error)
|
||||
SectionNames() []string
|
||||
Close() error
|
||||
ByteOrder() binary.ByteOrder
|
||||
Entry() uint64
|
||||
}
|
||||
|
||||
func openExe(file string) (exe, error) {
|
||||
f, err := os.Open(file)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
data := make([]byte, 16)
|
||||
if _, err := io.ReadFull(f, data); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
f.Seek(0, 0)
|
||||
if bytes.HasPrefix(data, []byte("\x7FELF")) {
|
||||
e, err := elf.NewFile(f)
|
||||
if err != nil {
|
||||
f.Close()
|
||||
return nil, err
|
||||
}
|
||||
return &elfExe{f, e}, nil
|
||||
}
|
||||
if bytes.HasPrefix(data, []byte("MZ")) {
|
||||
e, err := pe.NewFile(f)
|
||||
if err != nil {
|
||||
f.Close()
|
||||
return nil, err
|
||||
}
|
||||
return &peExe{f, e}, nil
|
||||
}
|
||||
if bytes.HasPrefix(data, []byte("\xFE\xED\xFA")) || bytes.HasPrefix(data[1:], []byte("\xFA\xED\xFE")) {
|
||||
e, err := macho.NewFile(f)
|
||||
if err != nil {
|
||||
f.Close()
|
||||
return nil, err
|
||||
}
|
||||
return &machoExe{f, e}, nil
|
||||
}
|
||||
return nil, fmt.Errorf("unrecognized executable format")
|
||||
}
|
||||
|
||||
type elfExe struct {
|
||||
os *os.File
|
||||
f *elf.File
|
||||
}
|
||||
|
||||
func (x *elfExe) AddrSize() int { return 0 }
|
||||
|
||||
func (x *elfExe) ByteOrder() binary.ByteOrder { return x.f.ByteOrder }
|
||||
|
||||
func (x *elfExe) Close() error {
|
||||
return x.os.Close()
|
||||
}
|
||||
|
||||
func (x *elfExe) Entry() uint64 { return x.f.Entry }
|
||||
|
||||
func (x *elfExe) ReadData(addr, size uint64) ([]byte, error) {
|
||||
data := make([]byte, size)
|
||||
for _, prog := range x.f.Progs {
|
||||
if prog.Vaddr <= addr && addr+size-1 <= prog.Vaddr+prog.Filesz-1 {
|
||||
_, err := prog.ReadAt(data, int64(addr-prog.Vaddr))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return data, nil
|
||||
}
|
||||
}
|
||||
return nil, fmt.Errorf("address not mapped")
|
||||
}
|
||||
|
||||
func (x *elfExe) Symbols() ([]sym, error) {
|
||||
syms, err := x.f.Symbols()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var out []sym
|
||||
for _, s := range syms {
|
||||
out = append(out, sym{s.Name, s.Value, s.Size})
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (x *elfExe) SectionNames() []string {
|
||||
var names []string
|
||||
for _, sect := range x.f.Sections {
|
||||
names = append(names, sect.Name)
|
||||
}
|
||||
return names
|
||||
}
|
||||
|
||||
type peExe struct {
|
||||
os *os.File
|
||||
f *pe.File
|
||||
}
|
||||
|
||||
func (x *peExe) imageBase() uint64 {
|
||||
switch oh := x.f.OptionalHeader.(type) {
|
||||
case *pe.OptionalHeader32:
|
||||
return uint64(oh.ImageBase)
|
||||
case *pe.OptionalHeader64:
|
||||
return oh.ImageBase
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *peExe) AddrSize() int {
|
||||
if x.f.Machine == pe.IMAGE_FILE_MACHINE_AMD64 {
|
||||
return 8
|
||||
}
|
||||
return 4
|
||||
}
|
||||
|
||||
func (x *peExe) ByteOrder() binary.ByteOrder { return binary.LittleEndian }
|
||||
|
||||
func (x *peExe) Close() error {
|
||||
return x.os.Close()
|
||||
}
|
||||
|
||||
func (x *peExe) Entry() uint64 {
|
||||
switch oh := x.f.OptionalHeader.(type) {
|
||||
case *pe.OptionalHeader32:
|
||||
return uint64(oh.ImageBase + oh.AddressOfEntryPoint)
|
||||
case *pe.OptionalHeader64:
|
||||
return oh.ImageBase + uint64(oh.AddressOfEntryPoint)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *peExe) ReadData(addr, size uint64) ([]byte, error) {
|
||||
addr -= x.imageBase()
|
||||
data := make([]byte, size)
|
||||
for _, sect := range x.f.Sections {
|
||||
if uint64(sect.VirtualAddress) <= addr && addr+size-1 <= uint64(sect.VirtualAddress+sect.Size-1) {
|
||||
_, err := sect.ReadAt(data, int64(addr-uint64(sect.VirtualAddress)))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return data, nil
|
||||
}
|
||||
}
|
||||
return nil, fmt.Errorf("address not mapped")
|
||||
}
|
||||
|
||||
func (x *peExe) Symbols() ([]sym, error) {
|
||||
base := x.imageBase()
|
||||
var out []sym
|
||||
for _, s := range x.f.Symbols {
|
||||
if s.SectionNumber <= 0 || int(s.SectionNumber) > len(x.f.Sections) {
|
||||
continue
|
||||
}
|
||||
sect := x.f.Sections[s.SectionNumber-1]
|
||||
out = append(out, sym{s.Name, uint64(s.Value) + base + uint64(sect.VirtualAddress), 0})
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (x *peExe) SectionNames() []string {
|
||||
var names []string
|
||||
for _, sect := range x.f.Sections {
|
||||
names = append(names, sect.Name)
|
||||
}
|
||||
return names
|
||||
}
|
||||
|
||||
type machoExe struct {
|
||||
os *os.File
|
||||
f *macho.File
|
||||
}
|
||||
|
||||
func (x *machoExe) AddrSize() int {
|
||||
if x.f.Cpu&0x01000000 != 0 {
|
||||
return 8
|
||||
}
|
||||
return 4
|
||||
}
|
||||
|
||||
func (x *machoExe) ByteOrder() binary.ByteOrder { return x.f.ByteOrder }
|
||||
|
||||
func (x *machoExe) Close() error {
|
||||
return x.os.Close()
|
||||
}
|
||||
|
||||
func (x *machoExe) Entry() uint64 {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *machoExe) ReadData(addr, size uint64) ([]byte, error) {
|
||||
data := make([]byte, size)
|
||||
for _, load := range x.f.Loads {
|
||||
seg, ok := load.(*macho.Segment)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
if seg.Addr <= addr && addr+size-1 <= seg.Addr+seg.Filesz-1 {
|
||||
if seg.Name == "__PAGEZERO" {
|
||||
continue
|
||||
}
|
||||
_, err := seg.ReadAt(data, int64(addr-seg.Addr))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return data, nil
|
||||
}
|
||||
}
|
||||
return nil, fmt.Errorf("address not mapped")
|
||||
}
|
||||
|
||||
func (x *machoExe) Symbols() ([]sym, error) {
|
||||
var out []sym
|
||||
for _, s := range x.f.Symtab.Syms {
|
||||
out = append(out, sym{s.Name, s.Value, 0})
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (x *machoExe) SectionNames() []string {
|
||||
var names []string
|
||||
for _, sect := range x.f.Sections {
|
||||
names = append(names, sect.Name)
|
||||
}
|
||||
return names
|
||||
}
|
128
vendor/rsc.io/goversion/version/read.go
generated
vendored
Normal file
128
vendor/rsc.io/goversion/version/read.go
generated
vendored
Normal file
@ -0,0 +1,128 @@
|
||||
// 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.
|
||||
|
||||
// Package version reports the Go version used to build program executables.
|
||||
package version
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Version is the information reported by ReadExe.
|
||||
type Version struct {
|
||||
Release string // Go version (runtime.Version in the program)
|
||||
BoringCrypto bool // program uses BoringCrypto
|
||||
StandardCrypto bool // program uses standard crypto (replaced by BoringCrypto)
|
||||
}
|
||||
|
||||
// ReadExe reports information about the Go version used to build
|
||||
// the program executable named by file.
|
||||
func ReadExe(file string) (Version, error) {
|
||||
var v Version
|
||||
f, err := openExe(file)
|
||||
if err != nil {
|
||||
return v, err
|
||||
}
|
||||
defer f.Close()
|
||||
isGo := false
|
||||
for _, name := range f.SectionNames() {
|
||||
if name == ".note.go.buildid" {
|
||||
isGo = true
|
||||
}
|
||||
}
|
||||
syms, symsErr := f.Symbols()
|
||||
isGccgo := false
|
||||
for _, sym := range syms {
|
||||
name := sym.Name
|
||||
if name == "runtime.main" || name == "main.main" {
|
||||
isGo = true
|
||||
}
|
||||
if strings.HasPrefix(name, "runtime.") && strings.HasSuffix(name, "$descriptor") {
|
||||
isGccgo = true
|
||||
}
|
||||
if name == "runtime.buildVersion" {
|
||||
isGo = true
|
||||
release, err := readBuildVersion(f, sym.Addr, sym.Size)
|
||||
if err != nil {
|
||||
return v, err
|
||||
}
|
||||
v.Release = release
|
||||
|
||||
}
|
||||
if strings.Contains(name, "_Cfunc__goboringcrypto_") {
|
||||
v.BoringCrypto = true
|
||||
}
|
||||
for _, s := range standardCryptoNames {
|
||||
if strings.Contains(name, s) {
|
||||
v.StandardCrypto = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if *debugMatch {
|
||||
v.Release = ""
|
||||
}
|
||||
if v.Release == "" {
|
||||
g, release := readBuildVersionX86Asm(f)
|
||||
if g {
|
||||
isGo = true
|
||||
v.Release = release
|
||||
}
|
||||
}
|
||||
if isGccgo && v.Release == "" {
|
||||
isGo = true
|
||||
v.Release = "gccgo (version unknown)"
|
||||
}
|
||||
if !isGo && symsErr != nil {
|
||||
return v, symsErr
|
||||
}
|
||||
|
||||
if !isGo {
|
||||
return v, errors.New("not a Go executable")
|
||||
}
|
||||
if v.Release == "" {
|
||||
v.Release = "unknown Go version"
|
||||
}
|
||||
return v, nil
|
||||
}
|
||||
|
||||
var standardCryptoNames = []string{
|
||||
"crypto/sha1.(*digest)",
|
||||
"crypto/sha256.(*digest)",
|
||||
"crypto/rand.(*devReader)",
|
||||
"crypto/rsa.encrypt",
|
||||
"crypto/rsa.decrypt",
|
||||
}
|
||||
|
||||
func readBuildVersion(f exe, addr, size uint64) (string, error) {
|
||||
if size == 0 {
|
||||
size = uint64(f.AddrSize() * 2)
|
||||
}
|
||||
if size != 8 && size != 16 {
|
||||
return "", fmt.Errorf("invalid size for runtime.buildVersion")
|
||||
}
|
||||
data, err := f.ReadData(addr, size)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("reading runtime.buildVersion: %v", err)
|
||||
}
|
||||
|
||||
if size == 8 {
|
||||
addr = uint64(f.ByteOrder().Uint32(data))
|
||||
size = uint64(f.ByteOrder().Uint32(data[4:]))
|
||||
} else {
|
||||
addr = f.ByteOrder().Uint64(data)
|
||||
size = f.ByteOrder().Uint64(data[8:])
|
||||
}
|
||||
if size > 1000 {
|
||||
return "", fmt.Errorf("implausible string size %d for runtime.buildVersion", size)
|
||||
}
|
||||
|
||||
data, err = f.ReadData(addr, size)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("reading runtime.buildVersion string data: %v", err)
|
||||
}
|
||||
return string(data), nil
|
||||
}
|
Loading…
Reference in New Issue
Block a user