Initialize module and dependencies
This commit is contained in:
349
vendor/golang.org/x/vuln/internal/goversion/asm.go
generated
vendored
Normal file
349
vendor/golang.org/x/vuln/internal/goversion/asm.go
generated
vendored
Normal file
@@ -0,0 +1,349 @@
|
||||
// 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 goversion
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"os"
|
||||
)
|
||||
|
||||
type matcher [][]uint32
|
||||
|
||||
const (
|
||||
pWild uint32 = 0xff00
|
||||
pAddr uint32 = 0x10000
|
||||
pEnd uint32 = 0x20000
|
||||
pRelAddr uint32 = 0x30000
|
||||
|
||||
opMaybe = 1 + iota
|
||||
opMust
|
||||
opDone
|
||||
opAnchor = 0x100
|
||||
opSub8 = 0x200
|
||||
opFlags = opAnchor | opSub8
|
||||
)
|
||||
|
||||
var amd64Matcher = matcher{
|
||||
{opMaybe | opAnchor,
|
||||
// __rt0_amd64_darwin:
|
||||
// JMP __rt0_amd64
|
||||
0xe9, pWild | pAddr, pWild, pWild, pWild | pEnd, 0xcc, 0xcc, 0xcc,
|
||||
},
|
||||
{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,
|
||||
// __rt0_amd64:
|
||||
// mov (%rsp), %rdi
|
||||
// lea 8(%rsp), %rsi
|
||||
// jmp runtime.rt0_g0
|
||||
0x48, 0x8b, 0x3c, 0x24,
|
||||
0x48, 0x8d, 0x74, 0x24, 0x08,
|
||||
0xe9, pWild | pAddr, pWild, pWild, pWild | pEnd,
|
||||
0xcc, 0xcc,
|
||||
},
|
||||
{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,
|
||||
},
|
||||
{opMaybe | opAnchor,
|
||||
// main:
|
||||
// JMP runtime.rt0_go(SB)
|
||||
0xe9, pWild | pAddr, pWild, pWild, pWild | pEnd, 0xcc, 0xcc, 0xcc,
|
||||
},
|
||||
{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)
|
||||
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,
|
||||
// schedinit (toward end)
|
||||
// cmpq $0x0, ADDR(%rip)
|
||||
// jne <short>
|
||||
// movq $0x7, ADDR(%rip)
|
||||
0x48, 0x83, 0x3d, pWild | pAddr, pWild, pWild, pWild, 0x00,
|
||||
0x75, pWild,
|
||||
0x48, 0xc7, 0x05 | pEnd, pWild | pAddr, pWild, pWild, pWild, 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,
|
||||
},
|
||||
{opDone,
|
||||
// schedinit (toward end)
|
||||
// mov ADDR(%rip), %rcx
|
||||
// test %rcx, %rcx
|
||||
// jne <short>
|
||||
// movq $0x7, ADDR(%rip)
|
||||
//
|
||||
0x48, 0x8b, 0x0d, pWild, pWild, pWild, pWild,
|
||||
0x48, 0x85, 0xc9,
|
||||
0x75, pWild,
|
||||
0x48, 0xc7, 0x05 | pEnd, pWild | pAddr, pWild, pWild, pWild, 0x07, 0x00, 0x00, 0x00,
|
||||
},
|
||||
}
|
||||
|
||||
var DebugMatch bool
|
||||
|
||||
func (m matcher) match(f exe, addr uint64) (uint64, bool) {
|
||||
data, err := f.ReadData(addr, 512)
|
||||
if DebugMatch {
|
||||
fmt.Fprintf(os.Stderr, "data @%#x: %x\n", addr, data[:16])
|
||||
}
|
||||
if err != nil {
|
||||
if DebugMatch {
|
||||
fmt.Fprintf(os.Stderr, "match: %v\n", err)
|
||||
}
|
||||
return 0, false
|
||||
}
|
||||
if DebugMatch {
|
||||
fmt.Fprintf(os.Stderr, "data: %x\n", data[:32])
|
||||
}
|
||||
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
|
||||
}
|
||||
if DebugMatch {
|
||||
fmt.Fprintf(os.Stderr, "reload @%#x: %x\n", addr, data[:32])
|
||||
}
|
||||
}
|
||||
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 {
|
||||
if DebugMatch {
|
||||
fmt.Fprintf(os.Stderr, "missing entry!\n")
|
||||
}
|
||||
return
|
||||
}
|
||||
addr, ok := amd64Matcher.match(f, entry)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
v, err := readBuildVersion(f, addr, 16)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
return true, v
|
||||
}
|
||||
Reference in New Issue
Block a user