1
0
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:
Jaana Burcu Dogan 2017-09-04 11:54:34 -07:00
parent d858829db9
commit 08cb2394b4
8 changed files with 959 additions and 1 deletions

8
Gopkg.lock generated
View File

@ -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
View 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
View 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

Binary file not shown.

215
vendor/rsc.io/goversion/main.go generated vendored Normal file
View 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
View 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
View 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
View 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
}