vendor: Add golang.org/x/net/bpf
This commit is contained in:
27
vendor/golang.org/x/net/bpf/LICENSE
generated
vendored
Normal file
27
vendor/golang.org/x/net/bpf/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.
|
||||||
41
vendor/golang.org/x/net/bpf/asm.go
generated
vendored
Normal file
41
vendor/golang.org/x/net/bpf/asm.go
generated
vendored
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
// Copyright 2016 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 bpf
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
// Assemble converts insts into raw instructions suitable for loading
|
||||||
|
// into a BPF virtual machine.
|
||||||
|
//
|
||||||
|
// Currently, no optimization is attempted, the assembled program flow
|
||||||
|
// is exactly as provided.
|
||||||
|
func Assemble(insts []Instruction) ([]RawInstruction, error) {
|
||||||
|
ret := make([]RawInstruction, len(insts))
|
||||||
|
var err error
|
||||||
|
for i, inst := range insts {
|
||||||
|
ret[i], err = inst.Assemble()
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("assembling instruction %d: %s", i+1, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Disassemble attempts to parse raw back into
|
||||||
|
// Instructions. Unrecognized RawInstructions are assumed to be an
|
||||||
|
// extension not implemented by this package, and are passed through
|
||||||
|
// unchanged to the output. The allDecoded value reports whether insts
|
||||||
|
// contains no RawInstructions.
|
||||||
|
func Disassemble(raw []RawInstruction) (insts []Instruction, allDecoded bool) {
|
||||||
|
insts = make([]Instruction, len(raw))
|
||||||
|
allDecoded = true
|
||||||
|
for i, r := range raw {
|
||||||
|
insts[i] = r.Disassemble()
|
||||||
|
if _, ok := insts[i].(RawInstruction); ok {
|
||||||
|
allDecoded = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return insts, allDecoded
|
||||||
|
}
|
||||||
215
vendor/golang.org/x/net/bpf/constants.go
generated
vendored
Normal file
215
vendor/golang.org/x/net/bpf/constants.go
generated
vendored
Normal file
@@ -0,0 +1,215 @@
|
|||||||
|
// Copyright 2016 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 bpf
|
||||||
|
|
||||||
|
// A Register is a register of the BPF virtual machine.
|
||||||
|
type Register uint16
|
||||||
|
|
||||||
|
const (
|
||||||
|
// RegA is the accumulator register. RegA is always the
|
||||||
|
// destination register of ALU operations.
|
||||||
|
RegA Register = iota
|
||||||
|
// RegX is the indirection register, used by LoadIndirect
|
||||||
|
// operations.
|
||||||
|
RegX
|
||||||
|
)
|
||||||
|
|
||||||
|
// An ALUOp is an arithmetic or logic operation.
|
||||||
|
type ALUOp uint16
|
||||||
|
|
||||||
|
// ALU binary operation types.
|
||||||
|
const (
|
||||||
|
ALUOpAdd ALUOp = iota << 4
|
||||||
|
ALUOpSub
|
||||||
|
ALUOpMul
|
||||||
|
ALUOpDiv
|
||||||
|
ALUOpOr
|
||||||
|
ALUOpAnd
|
||||||
|
ALUOpShiftLeft
|
||||||
|
ALUOpShiftRight
|
||||||
|
aluOpNeg // Not exported because it's the only unary ALU operation, and gets its own instruction type.
|
||||||
|
ALUOpMod
|
||||||
|
ALUOpXor
|
||||||
|
)
|
||||||
|
|
||||||
|
// A JumpTest is a comparison operator used in conditional jumps.
|
||||||
|
type JumpTest uint16
|
||||||
|
|
||||||
|
// Supported operators for conditional jumps.
|
||||||
|
const (
|
||||||
|
// K == A
|
||||||
|
JumpEqual JumpTest = iota
|
||||||
|
// K != A
|
||||||
|
JumpNotEqual
|
||||||
|
// K > A
|
||||||
|
JumpGreaterThan
|
||||||
|
// K < A
|
||||||
|
JumpLessThan
|
||||||
|
// K >= A
|
||||||
|
JumpGreaterOrEqual
|
||||||
|
// K <= A
|
||||||
|
JumpLessOrEqual
|
||||||
|
// K & A != 0
|
||||||
|
JumpBitsSet
|
||||||
|
// K & A == 0
|
||||||
|
JumpBitsNotSet
|
||||||
|
)
|
||||||
|
|
||||||
|
// An Extension is a function call provided by the kernel that
|
||||||
|
// performs advanced operations that are expensive or impossible
|
||||||
|
// within the BPF virtual machine.
|
||||||
|
//
|
||||||
|
// Extensions are only implemented by the Linux kernel.
|
||||||
|
//
|
||||||
|
// TODO: should we prune this list? Some of these extensions seem
|
||||||
|
// either broken or near-impossible to use correctly, whereas other
|
||||||
|
// (len, random, ifindex) are quite useful.
|
||||||
|
type Extension int
|
||||||
|
|
||||||
|
// Extension functions available in the Linux kernel.
|
||||||
|
const (
|
||||||
|
// ExtLen returns the length of the packet.
|
||||||
|
ExtLen Extension = 1
|
||||||
|
// ExtProto returns the packet's L3 protocol type.
|
||||||
|
ExtProto = 0
|
||||||
|
// ExtType returns the packet's type (skb->pkt_type in the kernel)
|
||||||
|
//
|
||||||
|
// TODO: better documentation. How nice an API do we want to
|
||||||
|
// provide for these esoteric extensions?
|
||||||
|
ExtType = 4
|
||||||
|
// ExtPayloadOffset returns the offset of the packet payload, or
|
||||||
|
// the first protocol header that the kernel does not know how to
|
||||||
|
// parse.
|
||||||
|
ExtPayloadOffset = 52
|
||||||
|
// ExtInterfaceIndex returns the index of the interface on which
|
||||||
|
// the packet was received.
|
||||||
|
ExtInterfaceIndex = 8
|
||||||
|
// ExtNetlinkAttr returns the netlink attribute of type X at
|
||||||
|
// offset A.
|
||||||
|
ExtNetlinkAttr = 12
|
||||||
|
// ExtNetlinkAttrNested returns the nested netlink attribute of
|
||||||
|
// type X at offset A.
|
||||||
|
ExtNetlinkAttrNested = 16
|
||||||
|
// ExtMark returns the packet's mark value.
|
||||||
|
ExtMark = 20
|
||||||
|
// ExtQueue returns the packet's assigned hardware queue.
|
||||||
|
ExtQueue = 24
|
||||||
|
// ExtLinkLayerType returns the packet's hardware address type
|
||||||
|
// (e.g. Ethernet, Infiniband).
|
||||||
|
ExtLinkLayerType = 28
|
||||||
|
// ExtRXHash returns the packets receive hash.
|
||||||
|
//
|
||||||
|
// TODO: figure out what this rxhash actually is.
|
||||||
|
ExtRXHash = 32
|
||||||
|
// ExtCPUID returns the ID of the CPU processing the current
|
||||||
|
// packet.
|
||||||
|
ExtCPUID = 36
|
||||||
|
// ExtVLANTag returns the packet's VLAN tag.
|
||||||
|
ExtVLANTag = 44
|
||||||
|
// ExtVLANTagPresent returns non-zero if the packet has a VLAN
|
||||||
|
// tag.
|
||||||
|
//
|
||||||
|
// TODO: I think this might be a lie: it reads bit 0x1000 of the
|
||||||
|
// VLAN header, which changed meaning in recent revisions of the
|
||||||
|
// spec - this extension may now return meaningless information.
|
||||||
|
ExtVLANTagPresent = 48
|
||||||
|
// ExtVLANProto returns 0x8100 if the frame has a VLAN header,
|
||||||
|
// 0x88a8 if the frame has a "Q-in-Q" double VLAN header, or some
|
||||||
|
// other value if no VLAN information is present.
|
||||||
|
ExtVLANProto = 60
|
||||||
|
// ExtRand returns a uniformly random uint32.
|
||||||
|
ExtRand = 56
|
||||||
|
)
|
||||||
|
|
||||||
|
// The following gives names to various bit patterns used in opcode construction.
|
||||||
|
|
||||||
|
const (
|
||||||
|
opMaskCls uint16 = 0x7
|
||||||
|
// opClsLoad masks
|
||||||
|
opMaskLoadDest = 0x01
|
||||||
|
opMaskLoadWidth = 0x18
|
||||||
|
opMaskLoadMode = 0xe0
|
||||||
|
// opClsALU
|
||||||
|
opMaskOperandSrc = 0x08
|
||||||
|
opMaskOperator = 0xf0
|
||||||
|
// opClsJump
|
||||||
|
opMaskJumpConst = 0x0f
|
||||||
|
opMaskJumpCond = 0xf0
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// +---------------+-----------------+---+---+---+
|
||||||
|
// | AddrMode (3b) | LoadWidth (2b) | 0 | 0 | 0 |
|
||||||
|
// +---------------+-----------------+---+---+---+
|
||||||
|
opClsLoadA uint16 = iota
|
||||||
|
// +---------------+-----------------+---+---+---+
|
||||||
|
// | AddrMode (3b) | LoadWidth (2b) | 0 | 0 | 1 |
|
||||||
|
// +---------------+-----------------+---+---+---+
|
||||||
|
opClsLoadX
|
||||||
|
// +---+---+---+---+---+---+---+---+
|
||||||
|
// | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 |
|
||||||
|
// +---+---+---+---+---+---+---+---+
|
||||||
|
opClsStoreA
|
||||||
|
// +---+---+---+---+---+---+---+---+
|
||||||
|
// | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 |
|
||||||
|
// +---+---+---+---+---+---+---+---+
|
||||||
|
opClsStoreX
|
||||||
|
// +---------------+-----------------+---+---+---+
|
||||||
|
// | Operator (4b) | OperandSrc (1b) | 1 | 0 | 0 |
|
||||||
|
// +---------------+-----------------+---+---+---+
|
||||||
|
opClsALU
|
||||||
|
// +-----------------------------+---+---+---+---+
|
||||||
|
// | TestOperator (4b) | 0 | 1 | 0 | 1 |
|
||||||
|
// +-----------------------------+---+---+---+---+
|
||||||
|
opClsJump
|
||||||
|
// +---+-------------------------+---+---+---+---+
|
||||||
|
// | 0 | 0 | 0 | RetSrc (1b) | 0 | 1 | 1 | 0 |
|
||||||
|
// +---+-------------------------+---+---+---+---+
|
||||||
|
opClsReturn
|
||||||
|
// +---+-------------------------+---+---+---+---+
|
||||||
|
// | 0 | 0 | 0 | TXAorTAX (1b) | 0 | 1 | 1 | 1 |
|
||||||
|
// +---+-------------------------+---+---+---+---+
|
||||||
|
opClsMisc
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
opAddrModeImmediate uint16 = iota << 5
|
||||||
|
opAddrModeAbsolute
|
||||||
|
opAddrModeIndirect
|
||||||
|
opAddrModeScratch
|
||||||
|
opAddrModePacketLen // actually an extension, not an addressing mode.
|
||||||
|
opAddrModeMemShift
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
opLoadWidth4 uint16 = iota << 3
|
||||||
|
opLoadWidth2
|
||||||
|
opLoadWidth1
|
||||||
|
)
|
||||||
|
|
||||||
|
// Operator defined by ALUOp*
|
||||||
|
|
||||||
|
const (
|
||||||
|
opALUSrcConstant uint16 = iota << 3
|
||||||
|
opALUSrcX
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
opJumpAlways = iota << 4
|
||||||
|
opJumpEqual
|
||||||
|
opJumpGT
|
||||||
|
opJumpGE
|
||||||
|
opJumpSet
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
opRetSrcConstant uint16 = iota << 4
|
||||||
|
opRetSrcA
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
opMiscTAX = 0x00
|
||||||
|
opMiscTXA = 0x80
|
||||||
|
)
|
||||||
82
vendor/golang.org/x/net/bpf/doc.go
generated
vendored
Normal file
82
vendor/golang.org/x/net/bpf/doc.go
generated
vendored
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
// Copyright 2016 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 bpf implements marshaling and unmarshaling of programs for the
|
||||||
|
Berkeley Packet Filter virtual machine, and provides a Go implementation
|
||||||
|
of the virtual machine.
|
||||||
|
|
||||||
|
BPF's main use is to specify a packet filter for network taps, so that
|
||||||
|
the kernel doesn't have to expensively copy every packet it sees to
|
||||||
|
userspace. However, it's been repurposed to other areas where running
|
||||||
|
user code in-kernel is needed. For example, Linux's seccomp uses BPF
|
||||||
|
to apply security policies to system calls. For simplicity, this
|
||||||
|
documentation refers only to packets, but other uses of BPF have their
|
||||||
|
own data payloads.
|
||||||
|
|
||||||
|
BPF programs run in a restricted virtual machine. It has almost no
|
||||||
|
access to kernel functions, and while conditional branches are
|
||||||
|
allowed, they can only jump forwards, to guarantee that there are no
|
||||||
|
infinite loops.
|
||||||
|
|
||||||
|
The virtual machine
|
||||||
|
|
||||||
|
The BPF VM is an accumulator machine. Its main register, called
|
||||||
|
register A, is an implicit source and destination in all arithmetic
|
||||||
|
and logic operations. The machine also has 16 scratch registers for
|
||||||
|
temporary storage, and an indirection register (register X) for
|
||||||
|
indirect memory access. All registers are 32 bits wide.
|
||||||
|
|
||||||
|
Each run of a BPF program is given one packet, which is placed in the
|
||||||
|
VM's read-only "main memory". LoadAbsolute and LoadIndirect
|
||||||
|
instructions can fetch up to 32 bits at a time into register A for
|
||||||
|
examination.
|
||||||
|
|
||||||
|
The goal of a BPF program is to produce and return a verdict (uint32),
|
||||||
|
which tells the kernel what to do with the packet. In the context of
|
||||||
|
packet filtering, the returned value is the number of bytes of the
|
||||||
|
packet to forward to userspace, or 0 to ignore the packet. Other
|
||||||
|
contexts like seccomp define their own return values.
|
||||||
|
|
||||||
|
In order to simplify programs, attempts to read past the end of the
|
||||||
|
packet terminate the program execution with a verdict of 0 (ignore
|
||||||
|
packet). This means that the vast majority of BPF programs don't need
|
||||||
|
to do any explicit bounds checking.
|
||||||
|
|
||||||
|
In addition to the bytes of the packet, some BPF programs have access
|
||||||
|
to extensions, which are essentially calls to kernel utility
|
||||||
|
functions. Currently, the only extensions supported by this package
|
||||||
|
are the Linux packet filter extensions.
|
||||||
|
|
||||||
|
Examples
|
||||||
|
|
||||||
|
This packet filter selects all ARP packets.
|
||||||
|
|
||||||
|
bpf.Assemble([]bpf.Instruction{
|
||||||
|
// Load "EtherType" field from the ethernet header.
|
||||||
|
bpf.LoadAbsolute{Off: 12, Size: 2},
|
||||||
|
// Skip over the next instruction if EtherType is not ARP.
|
||||||
|
bpf.JumpIf{Cond: bpf.JumpNotEqual, Val: 0x0806, SkipTrue: 1},
|
||||||
|
// Verdict is "send up to 4k of the packet to userspace."
|
||||||
|
bpf.RetConstant{Val: 4096},
|
||||||
|
// Verdict is "ignore packet."
|
||||||
|
bpf.RetConstant{Val: 0},
|
||||||
|
})
|
||||||
|
|
||||||
|
This packet filter captures a random 1% sample of traffic.
|
||||||
|
|
||||||
|
bpf.Assemble([]bpf.Instruction{
|
||||||
|
// Get a 32-bit random number from the Linux kernel.
|
||||||
|
bpf.LoadExtension{Num: bpf.ExtRand},
|
||||||
|
// 1% dice roll?
|
||||||
|
bpf.JumpIf{Cond: bpf.JumpLessThan, Val: 2^32/100, SkipFalse: 1},
|
||||||
|
// Capture.
|
||||||
|
bpf.RetConstant{Val: 4096},
|
||||||
|
// Ignore.
|
||||||
|
bpf.RetConstant{Val: 0},
|
||||||
|
})
|
||||||
|
|
||||||
|
*/
|
||||||
|
package bpf // import "golang.org/x/net/bpf"
|
||||||
434
vendor/golang.org/x/net/bpf/instructions.go
generated
vendored
Normal file
434
vendor/golang.org/x/net/bpf/instructions.go
generated
vendored
Normal file
@@ -0,0 +1,434 @@
|
|||||||
|
// Copyright 2016 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 bpf
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
// An Instruction is one instruction executed by the BPF virtual
|
||||||
|
// machine.
|
||||||
|
type Instruction interface {
|
||||||
|
// Assemble assembles the Instruction into a RawInstruction.
|
||||||
|
Assemble() (RawInstruction, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// A RawInstruction is a raw BPF virtual machine instruction.
|
||||||
|
type RawInstruction struct {
|
||||||
|
// Operation to execute.
|
||||||
|
Op uint16
|
||||||
|
// For conditional jump instructions, the number of instructions
|
||||||
|
// to skip if the condition is true/false.
|
||||||
|
Jt uint8
|
||||||
|
Jf uint8
|
||||||
|
// Constant parameter. The meaning depends on the Op.
|
||||||
|
K uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assemble implements the Instruction Assemble method.
|
||||||
|
func (ri RawInstruction) Assemble() (RawInstruction, error) { return ri, nil }
|
||||||
|
|
||||||
|
// Disassemble parses ri into an Instruction and returns it. If ri is
|
||||||
|
// not recognized by this package, ri itself is returned.
|
||||||
|
func (ri RawInstruction) Disassemble() Instruction {
|
||||||
|
switch ri.Op & opMaskCls {
|
||||||
|
case opClsLoadA, opClsLoadX:
|
||||||
|
reg := Register(ri.Op & opMaskLoadDest)
|
||||||
|
sz := 0
|
||||||
|
switch ri.Op & opMaskLoadWidth {
|
||||||
|
case opLoadWidth4:
|
||||||
|
sz = 4
|
||||||
|
case opLoadWidth2:
|
||||||
|
sz = 2
|
||||||
|
case opLoadWidth1:
|
||||||
|
sz = 1
|
||||||
|
default:
|
||||||
|
return ri
|
||||||
|
}
|
||||||
|
switch ri.Op & opMaskLoadMode {
|
||||||
|
case opAddrModeImmediate:
|
||||||
|
if sz != 4 {
|
||||||
|
return ri
|
||||||
|
}
|
||||||
|
return LoadConstant{Dst: reg, Val: ri.K}
|
||||||
|
case opAddrModeScratch:
|
||||||
|
if sz != 4 || ri.K > 15 {
|
||||||
|
return ri
|
||||||
|
}
|
||||||
|
return LoadScratch{Dst: reg, N: int(ri.K)}
|
||||||
|
case opAddrModeAbsolute:
|
||||||
|
return LoadAbsolute{Size: sz, Off: ri.K}
|
||||||
|
case opAddrModeIndirect:
|
||||||
|
return LoadIndirect{Size: sz, Off: ri.K}
|
||||||
|
case opAddrModePacketLen:
|
||||||
|
if sz != 4 {
|
||||||
|
return ri
|
||||||
|
}
|
||||||
|
return LoadExtension{Num: ExtLen}
|
||||||
|
case opAddrModeMemShift:
|
||||||
|
return LoadMemShift{Off: ri.K}
|
||||||
|
default:
|
||||||
|
return ri
|
||||||
|
}
|
||||||
|
|
||||||
|
case opClsStoreA:
|
||||||
|
if ri.Op != opClsStoreA || ri.K > 15 {
|
||||||
|
return ri
|
||||||
|
}
|
||||||
|
return StoreScratch{Src: RegA, N: int(ri.K)}
|
||||||
|
|
||||||
|
case opClsStoreX:
|
||||||
|
if ri.Op != opClsStoreX || ri.K > 15 {
|
||||||
|
return ri
|
||||||
|
}
|
||||||
|
return StoreScratch{Src: RegX, N: int(ri.K)}
|
||||||
|
|
||||||
|
case opClsALU:
|
||||||
|
switch op := ALUOp(ri.Op & opMaskOperator); op {
|
||||||
|
case ALUOpAdd, ALUOpSub, ALUOpMul, ALUOpDiv, ALUOpOr, ALUOpAnd, ALUOpShiftLeft, ALUOpShiftRight, ALUOpMod, ALUOpXor:
|
||||||
|
if ri.Op&opMaskOperandSrc != 0 {
|
||||||
|
return ALUOpX{Op: op}
|
||||||
|
}
|
||||||
|
return ALUOpConstant{Op: op, Val: ri.K}
|
||||||
|
case aluOpNeg:
|
||||||
|
return NegateA{}
|
||||||
|
default:
|
||||||
|
return ri
|
||||||
|
}
|
||||||
|
|
||||||
|
case opClsJump:
|
||||||
|
if ri.Op&opMaskJumpConst != opClsJump {
|
||||||
|
return ri
|
||||||
|
}
|
||||||
|
switch ri.Op & opMaskJumpCond {
|
||||||
|
case opJumpAlways:
|
||||||
|
return Jump{Skip: ri.K}
|
||||||
|
case opJumpEqual:
|
||||||
|
return JumpIf{
|
||||||
|
Cond: JumpEqual,
|
||||||
|
Val: ri.K,
|
||||||
|
SkipTrue: ri.Jt,
|
||||||
|
SkipFalse: ri.Jf,
|
||||||
|
}
|
||||||
|
case opJumpGT:
|
||||||
|
return JumpIf{
|
||||||
|
Cond: JumpGreaterThan,
|
||||||
|
Val: ri.K,
|
||||||
|
SkipTrue: ri.Jt,
|
||||||
|
SkipFalse: ri.Jf,
|
||||||
|
}
|
||||||
|
case opJumpGE:
|
||||||
|
return JumpIf{
|
||||||
|
Cond: JumpGreaterOrEqual,
|
||||||
|
Val: ri.K,
|
||||||
|
SkipTrue: ri.Jt,
|
||||||
|
SkipFalse: ri.Jf,
|
||||||
|
}
|
||||||
|
case opJumpSet:
|
||||||
|
return JumpIf{
|
||||||
|
Cond: JumpBitsSet,
|
||||||
|
Val: ri.K,
|
||||||
|
SkipTrue: ri.Jt,
|
||||||
|
SkipFalse: ri.Jf,
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return ri
|
||||||
|
}
|
||||||
|
|
||||||
|
case opClsReturn:
|
||||||
|
switch ri.Op {
|
||||||
|
case opClsReturn | opRetSrcA:
|
||||||
|
return RetA{}
|
||||||
|
case opClsReturn | opRetSrcConstant:
|
||||||
|
return RetConstant{Val: ri.K}
|
||||||
|
default:
|
||||||
|
return ri
|
||||||
|
}
|
||||||
|
|
||||||
|
case opClsMisc:
|
||||||
|
switch ri.Op {
|
||||||
|
case opClsMisc | opMiscTAX:
|
||||||
|
return TAX{}
|
||||||
|
case opClsMisc | opMiscTXA:
|
||||||
|
return TXA{}
|
||||||
|
default:
|
||||||
|
return ri
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
panic("unreachable") // switch is exhaustive on the bit pattern
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// LoadConstant loads Val into register Dst.
|
||||||
|
type LoadConstant struct {
|
||||||
|
Dst Register
|
||||||
|
Val uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assemble implements the Instruction Assemble method.
|
||||||
|
func (a LoadConstant) Assemble() (RawInstruction, error) {
|
||||||
|
return assembleLoad(a.Dst, 4, opAddrModeImmediate, a.Val)
|
||||||
|
}
|
||||||
|
|
||||||
|
// LoadScratch loads scratch[N] into register Dst.
|
||||||
|
type LoadScratch struct {
|
||||||
|
Dst Register
|
||||||
|
N int // 0-15
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assemble implements the Instruction Assemble method.
|
||||||
|
func (a LoadScratch) Assemble() (RawInstruction, error) {
|
||||||
|
if a.N < 0 || a.N > 15 {
|
||||||
|
return RawInstruction{}, fmt.Errorf("invalid scratch slot %d", a.N)
|
||||||
|
}
|
||||||
|
return assembleLoad(a.Dst, 4, opAddrModeScratch, uint32(a.N))
|
||||||
|
}
|
||||||
|
|
||||||
|
// LoadAbsolute loads packet[Off:Off+Size] as an integer value into
|
||||||
|
// register A.
|
||||||
|
type LoadAbsolute struct {
|
||||||
|
Off uint32
|
||||||
|
Size int // 1, 2 or 4
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assemble implements the Instruction Assemble method.
|
||||||
|
func (a LoadAbsolute) Assemble() (RawInstruction, error) {
|
||||||
|
return assembleLoad(RegA, a.Size, opAddrModeAbsolute, a.Off)
|
||||||
|
}
|
||||||
|
|
||||||
|
// LoadIndirect loads packet[X+Off:X+Off+Size] as an integer value
|
||||||
|
// into register A.
|
||||||
|
type LoadIndirect struct {
|
||||||
|
Off uint32
|
||||||
|
Size int // 1, 2 or 4
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assemble implements the Instruction Assemble method.
|
||||||
|
func (a LoadIndirect) Assemble() (RawInstruction, error) {
|
||||||
|
return assembleLoad(RegA, a.Size, opAddrModeIndirect, a.Off)
|
||||||
|
}
|
||||||
|
|
||||||
|
// LoadMemShift multiplies the first 4 bits of the byte at packet[Off]
|
||||||
|
// by 4 and stores the result in register X.
|
||||||
|
//
|
||||||
|
// This instruction is mainly useful to load into X the length of an
|
||||||
|
// IPv4 packet header in a single instruction, rather than have to do
|
||||||
|
// the arithmetic on the header's first byte by hand.
|
||||||
|
type LoadMemShift struct {
|
||||||
|
Off uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assemble implements the Instruction Assemble method.
|
||||||
|
func (a LoadMemShift) Assemble() (RawInstruction, error) {
|
||||||
|
return assembleLoad(RegX, 1, opAddrModeMemShift, a.Off)
|
||||||
|
}
|
||||||
|
|
||||||
|
// LoadExtension invokes a linux-specific extension and stores the
|
||||||
|
// result in register A.
|
||||||
|
type LoadExtension struct {
|
||||||
|
Num Extension
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assemble implements the Instruction Assemble method.
|
||||||
|
func (a LoadExtension) Assemble() (RawInstruction, error) {
|
||||||
|
if a.Num == ExtLen {
|
||||||
|
return assembleLoad(RegA, 4, opAddrModePacketLen, 0)
|
||||||
|
}
|
||||||
|
return assembleLoad(RegA, 4, opAddrModeAbsolute, uint32(-0x1000+a.Num))
|
||||||
|
}
|
||||||
|
|
||||||
|
// StoreScratch stores register Src into scratch[N].
|
||||||
|
type StoreScratch struct {
|
||||||
|
Src Register
|
||||||
|
N int // 0-15
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assemble implements the Instruction Assemble method.
|
||||||
|
func (a StoreScratch) Assemble() (RawInstruction, error) {
|
||||||
|
if a.N < 0 || a.N > 15 {
|
||||||
|
return RawInstruction{}, fmt.Errorf("invalid scratch slot %d", a.N)
|
||||||
|
}
|
||||||
|
var op uint16
|
||||||
|
switch a.Src {
|
||||||
|
case RegA:
|
||||||
|
op = opClsStoreA
|
||||||
|
case RegX:
|
||||||
|
op = opClsStoreX
|
||||||
|
default:
|
||||||
|
return RawInstruction{}, fmt.Errorf("invalid source register %v", a.Src)
|
||||||
|
}
|
||||||
|
|
||||||
|
return RawInstruction{
|
||||||
|
Op: op,
|
||||||
|
K: uint32(a.N),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ALUOpConstant executes A = A <Op> Val.
|
||||||
|
type ALUOpConstant struct {
|
||||||
|
Op ALUOp
|
||||||
|
Val uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assemble implements the Instruction Assemble method.
|
||||||
|
func (a ALUOpConstant) Assemble() (RawInstruction, error) {
|
||||||
|
return RawInstruction{
|
||||||
|
Op: opClsALU | opALUSrcConstant | uint16(a.Op),
|
||||||
|
K: a.Val,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ALUOpX executes A = A <Op> X
|
||||||
|
type ALUOpX struct {
|
||||||
|
Op ALUOp
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assemble implements the Instruction Assemble method.
|
||||||
|
func (a ALUOpX) Assemble() (RawInstruction, error) {
|
||||||
|
return RawInstruction{
|
||||||
|
Op: opClsALU | opALUSrcX | uint16(a.Op),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// NegateA executes A = -A.
|
||||||
|
type NegateA struct{}
|
||||||
|
|
||||||
|
// Assemble implements the Instruction Assemble method.
|
||||||
|
func (a NegateA) Assemble() (RawInstruction, error) {
|
||||||
|
return RawInstruction{
|
||||||
|
Op: opClsALU | uint16(aluOpNeg),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Jump skips the following Skip instructions in the program.
|
||||||
|
type Jump struct {
|
||||||
|
Skip uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assemble implements the Instruction Assemble method.
|
||||||
|
func (a Jump) Assemble() (RawInstruction, error) {
|
||||||
|
return RawInstruction{
|
||||||
|
Op: opClsJump | opJumpAlways,
|
||||||
|
K: a.Skip,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// JumpIf skips the following Skip instructions in the program if A
|
||||||
|
// <Cond> Val is true.
|
||||||
|
type JumpIf struct {
|
||||||
|
Cond JumpTest
|
||||||
|
Val uint32
|
||||||
|
SkipTrue uint8
|
||||||
|
SkipFalse uint8
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assemble implements the Instruction Assemble method.
|
||||||
|
func (a JumpIf) Assemble() (RawInstruction, error) {
|
||||||
|
var (
|
||||||
|
cond uint16
|
||||||
|
flip bool
|
||||||
|
)
|
||||||
|
switch a.Cond {
|
||||||
|
case JumpEqual:
|
||||||
|
cond = opJumpEqual
|
||||||
|
case JumpNotEqual:
|
||||||
|
cond, flip = opJumpEqual, true
|
||||||
|
case JumpGreaterThan:
|
||||||
|
cond = opJumpGT
|
||||||
|
case JumpLessThan:
|
||||||
|
cond, flip = opJumpGE, true
|
||||||
|
case JumpGreaterOrEqual:
|
||||||
|
cond = opJumpGE
|
||||||
|
case JumpLessOrEqual:
|
||||||
|
cond, flip = opJumpGT, true
|
||||||
|
case JumpBitsSet:
|
||||||
|
cond = opJumpSet
|
||||||
|
case JumpBitsNotSet:
|
||||||
|
cond, flip = opJumpSet, true
|
||||||
|
default:
|
||||||
|
return RawInstruction{}, fmt.Errorf("unknown JumpTest %v", a.Cond)
|
||||||
|
}
|
||||||
|
jt, jf := a.SkipTrue, a.SkipFalse
|
||||||
|
if flip {
|
||||||
|
jt, jf = jf, jt
|
||||||
|
}
|
||||||
|
return RawInstruction{
|
||||||
|
Op: opClsJump | cond,
|
||||||
|
Jt: jt,
|
||||||
|
Jf: jf,
|
||||||
|
K: a.Val,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// RetA exits the BPF program, returning the value of register A.
|
||||||
|
type RetA struct{}
|
||||||
|
|
||||||
|
// Assemble implements the Instruction Assemble method.
|
||||||
|
func (a RetA) Assemble() (RawInstruction, error) {
|
||||||
|
return RawInstruction{
|
||||||
|
Op: opClsReturn | opRetSrcA,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// RetConstant exits the BPF program, returning a constant value.
|
||||||
|
type RetConstant struct {
|
||||||
|
Val uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assemble implements the Instruction Assemble method.
|
||||||
|
func (a RetConstant) Assemble() (RawInstruction, error) {
|
||||||
|
return RawInstruction{
|
||||||
|
Op: opClsReturn | opRetSrcConstant,
|
||||||
|
K: a.Val,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// TXA copies the value of register X to register A.
|
||||||
|
type TXA struct{}
|
||||||
|
|
||||||
|
// Assemble implements the Instruction Assemble method.
|
||||||
|
func (a TXA) Assemble() (RawInstruction, error) {
|
||||||
|
return RawInstruction{
|
||||||
|
Op: opClsMisc | opMiscTXA,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// TAX copies the value of register A to register X.
|
||||||
|
type TAX struct{}
|
||||||
|
|
||||||
|
// Assemble implements the Instruction Assemble method.
|
||||||
|
func (a TAX) Assemble() (RawInstruction, error) {
|
||||||
|
return RawInstruction{
|
||||||
|
Op: opClsMisc | opMiscTAX,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func assembleLoad(dst Register, loadSize int, mode uint16, k uint32) (RawInstruction, error) {
|
||||||
|
var (
|
||||||
|
cls uint16
|
||||||
|
sz uint16
|
||||||
|
)
|
||||||
|
switch dst {
|
||||||
|
case RegA:
|
||||||
|
cls = opClsLoadA
|
||||||
|
case RegX:
|
||||||
|
cls = opClsLoadX
|
||||||
|
default:
|
||||||
|
return RawInstruction{}, fmt.Errorf("invalid target register %v", dst)
|
||||||
|
}
|
||||||
|
switch loadSize {
|
||||||
|
case 1:
|
||||||
|
sz = opLoadWidth1
|
||||||
|
case 2:
|
||||||
|
sz = opLoadWidth2
|
||||||
|
case 4:
|
||||||
|
sz = opLoadWidth4
|
||||||
|
default:
|
||||||
|
return RawInstruction{}, fmt.Errorf("invalid load byte length %d", sz)
|
||||||
|
}
|
||||||
|
return RawInstruction{
|
||||||
|
Op: cls | sz | mode,
|
||||||
|
K: k,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
140
vendor/golang.org/x/net/bpf/vm.go
generated
vendored
Normal file
140
vendor/golang.org/x/net/bpf/vm.go
generated
vendored
Normal file
@@ -0,0 +1,140 @@
|
|||||||
|
// Copyright 2016 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 bpf
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
// A VM is an emulated BPF virtual machine.
|
||||||
|
type VM struct {
|
||||||
|
filter []Instruction
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewVM returns a new VM using the input BPF program.
|
||||||
|
func NewVM(filter []Instruction) (*VM, error) {
|
||||||
|
if len(filter) == 0 {
|
||||||
|
return nil, errors.New("one or more Instructions must be specified")
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, ins := range filter {
|
||||||
|
check := len(filter) - (i + 1)
|
||||||
|
switch ins := ins.(type) {
|
||||||
|
// Check for out-of-bounds jumps in instructions
|
||||||
|
case Jump:
|
||||||
|
if check <= int(ins.Skip) {
|
||||||
|
return nil, fmt.Errorf("cannot jump %d instructions; jumping past program bounds", ins.Skip)
|
||||||
|
}
|
||||||
|
case JumpIf:
|
||||||
|
if check <= int(ins.SkipTrue) {
|
||||||
|
return nil, fmt.Errorf("cannot jump %d instructions in true case; jumping past program bounds", ins.SkipTrue)
|
||||||
|
}
|
||||||
|
if check <= int(ins.SkipFalse) {
|
||||||
|
return nil, fmt.Errorf("cannot jump %d instructions in false case; jumping past program bounds", ins.SkipFalse)
|
||||||
|
}
|
||||||
|
// Check for division or modulus by zero
|
||||||
|
case ALUOpConstant:
|
||||||
|
if ins.Val != 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
switch ins.Op {
|
||||||
|
case ALUOpDiv, ALUOpMod:
|
||||||
|
return nil, errors.New("cannot divide by zero using ALUOpConstant")
|
||||||
|
}
|
||||||
|
// Check for unknown extensions
|
||||||
|
case LoadExtension:
|
||||||
|
switch ins.Num {
|
||||||
|
case ExtLen:
|
||||||
|
default:
|
||||||
|
return nil, fmt.Errorf("extension %d not implemented", ins.Num)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure last instruction is a return instruction
|
||||||
|
switch filter[len(filter)-1].(type) {
|
||||||
|
case RetA, RetConstant:
|
||||||
|
default:
|
||||||
|
return nil, errors.New("BPF program must end with RetA or RetConstant")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Though our VM works using disassembled instructions, we
|
||||||
|
// attempt to assemble the input filter anyway to ensure it is compatible
|
||||||
|
// with an operating system VM.
|
||||||
|
_, err := Assemble(filter)
|
||||||
|
|
||||||
|
return &VM{
|
||||||
|
filter: filter,
|
||||||
|
}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run runs the VM's BPF program against the input bytes.
|
||||||
|
// Run returns the number of bytes accepted by the BPF program, and any errors
|
||||||
|
// which occurred while processing the program.
|
||||||
|
func (v *VM) Run(in []byte) (int, error) {
|
||||||
|
var (
|
||||||
|
// Registers of the virtual machine
|
||||||
|
regA uint32
|
||||||
|
regX uint32
|
||||||
|
regScratch [16]uint32
|
||||||
|
|
||||||
|
// OK is true if the program should continue processing the next
|
||||||
|
// instruction, or false if not, causing the loop to break
|
||||||
|
ok = true
|
||||||
|
)
|
||||||
|
|
||||||
|
// TODO(mdlayher): implement:
|
||||||
|
// - NegateA:
|
||||||
|
// - would require a change from uint32 registers to int32
|
||||||
|
// registers
|
||||||
|
|
||||||
|
// TODO(mdlayher): add interop tests that check signedness of ALU
|
||||||
|
// operations against kernel implementation, and make sure Go
|
||||||
|
// implementation matches behavior
|
||||||
|
|
||||||
|
for i := 0; i < len(v.filter) && ok; i++ {
|
||||||
|
ins := v.filter[i]
|
||||||
|
|
||||||
|
switch ins := ins.(type) {
|
||||||
|
case ALUOpConstant:
|
||||||
|
regA = aluOpConstant(ins, regA)
|
||||||
|
case ALUOpX:
|
||||||
|
regA, ok = aluOpX(ins, regA, regX)
|
||||||
|
case Jump:
|
||||||
|
i += int(ins.Skip)
|
||||||
|
case JumpIf:
|
||||||
|
jump := jumpIf(ins, regA)
|
||||||
|
i += jump
|
||||||
|
case LoadAbsolute:
|
||||||
|
regA, ok = loadAbsolute(ins, in)
|
||||||
|
case LoadConstant:
|
||||||
|
regA, regX = loadConstant(ins, regA, regX)
|
||||||
|
case LoadExtension:
|
||||||
|
regA = loadExtension(ins, in)
|
||||||
|
case LoadIndirect:
|
||||||
|
regA, ok = loadIndirect(ins, in, regX)
|
||||||
|
case LoadMemShift:
|
||||||
|
regX, ok = loadMemShift(ins, in)
|
||||||
|
case LoadScratch:
|
||||||
|
regA, regX = loadScratch(ins, regScratch, regA, regX)
|
||||||
|
case RetA:
|
||||||
|
return int(regA), nil
|
||||||
|
case RetConstant:
|
||||||
|
return int(ins.Val), nil
|
||||||
|
case StoreScratch:
|
||||||
|
regScratch = storeScratch(ins, regScratch, regA, regX)
|
||||||
|
case TAX:
|
||||||
|
regX = regA
|
||||||
|
case TXA:
|
||||||
|
regA = regX
|
||||||
|
default:
|
||||||
|
return 0, fmt.Errorf("unknown Instruction at index %d: %T", i, ins)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0, nil
|
||||||
|
}
|
||||||
174
vendor/golang.org/x/net/bpf/vm_instructions.go
generated
vendored
Normal file
174
vendor/golang.org/x/net/bpf/vm_instructions.go
generated
vendored
Normal file
@@ -0,0 +1,174 @@
|
|||||||
|
// Copyright 2016 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 bpf
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/binary"
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
func aluOpConstant(ins ALUOpConstant, regA uint32) uint32 {
|
||||||
|
return aluOpCommon(ins.Op, regA, ins.Val)
|
||||||
|
}
|
||||||
|
|
||||||
|
func aluOpX(ins ALUOpX, regA uint32, regX uint32) (uint32, bool) {
|
||||||
|
// Guard against division or modulus by zero by terminating
|
||||||
|
// the program, as the OS BPF VM does
|
||||||
|
if regX == 0 {
|
||||||
|
switch ins.Op {
|
||||||
|
case ALUOpDiv, ALUOpMod:
|
||||||
|
return 0, false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return aluOpCommon(ins.Op, regA, regX), true
|
||||||
|
}
|
||||||
|
|
||||||
|
func aluOpCommon(op ALUOp, regA uint32, value uint32) uint32 {
|
||||||
|
switch op {
|
||||||
|
case ALUOpAdd:
|
||||||
|
return regA + value
|
||||||
|
case ALUOpSub:
|
||||||
|
return regA - value
|
||||||
|
case ALUOpMul:
|
||||||
|
return regA * value
|
||||||
|
case ALUOpDiv:
|
||||||
|
// Division by zero not permitted by NewVM and aluOpX checks
|
||||||
|
return regA / value
|
||||||
|
case ALUOpOr:
|
||||||
|
return regA | value
|
||||||
|
case ALUOpAnd:
|
||||||
|
return regA & value
|
||||||
|
case ALUOpShiftLeft:
|
||||||
|
return regA << value
|
||||||
|
case ALUOpShiftRight:
|
||||||
|
return regA >> value
|
||||||
|
case ALUOpMod:
|
||||||
|
// Modulus by zero not permitted by NewVM and aluOpX checks
|
||||||
|
return regA % value
|
||||||
|
case ALUOpXor:
|
||||||
|
return regA ^ value
|
||||||
|
default:
|
||||||
|
return regA
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func jumpIf(ins JumpIf, value uint32) int {
|
||||||
|
var ok bool
|
||||||
|
inV := uint32(ins.Val)
|
||||||
|
|
||||||
|
switch ins.Cond {
|
||||||
|
case JumpEqual:
|
||||||
|
ok = value == inV
|
||||||
|
case JumpNotEqual:
|
||||||
|
ok = value != inV
|
||||||
|
case JumpGreaterThan:
|
||||||
|
ok = value > inV
|
||||||
|
case JumpLessThan:
|
||||||
|
ok = value < inV
|
||||||
|
case JumpGreaterOrEqual:
|
||||||
|
ok = value >= inV
|
||||||
|
case JumpLessOrEqual:
|
||||||
|
ok = value <= inV
|
||||||
|
case JumpBitsSet:
|
||||||
|
ok = (value & inV) != 0
|
||||||
|
case JumpBitsNotSet:
|
||||||
|
ok = (value & inV) == 0
|
||||||
|
}
|
||||||
|
|
||||||
|
if ok {
|
||||||
|
return int(ins.SkipTrue)
|
||||||
|
}
|
||||||
|
|
||||||
|
return int(ins.SkipFalse)
|
||||||
|
}
|
||||||
|
|
||||||
|
func loadAbsolute(ins LoadAbsolute, in []byte) (uint32, bool) {
|
||||||
|
offset := int(ins.Off)
|
||||||
|
size := int(ins.Size)
|
||||||
|
|
||||||
|
return loadCommon(in, offset, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func loadConstant(ins LoadConstant, regA uint32, regX uint32) (uint32, uint32) {
|
||||||
|
switch ins.Dst {
|
||||||
|
case RegA:
|
||||||
|
regA = ins.Val
|
||||||
|
case RegX:
|
||||||
|
regX = ins.Val
|
||||||
|
}
|
||||||
|
|
||||||
|
return regA, regX
|
||||||
|
}
|
||||||
|
|
||||||
|
func loadExtension(ins LoadExtension, in []byte) uint32 {
|
||||||
|
switch ins.Num {
|
||||||
|
case ExtLen:
|
||||||
|
return uint32(len(in))
|
||||||
|
default:
|
||||||
|
panic(fmt.Sprintf("unimplemented extension: %d", ins.Num))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func loadIndirect(ins LoadIndirect, in []byte, regX uint32) (uint32, bool) {
|
||||||
|
offset := int(ins.Off) + int(regX)
|
||||||
|
size := int(ins.Size)
|
||||||
|
|
||||||
|
return loadCommon(in, offset, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
func loadMemShift(ins LoadMemShift, in []byte) (uint32, bool) {
|
||||||
|
offset := int(ins.Off)
|
||||||
|
|
||||||
|
if !inBounds(len(in), offset, 0) {
|
||||||
|
return 0, false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mask off high 4 bits and multiply low 4 bits by 4
|
||||||
|
return uint32(in[offset]&0x0f) * 4, true
|
||||||
|
}
|
||||||
|
|
||||||
|
func inBounds(inLen int, offset int, size int) bool {
|
||||||
|
return offset+size <= inLen
|
||||||
|
}
|
||||||
|
|
||||||
|
func loadCommon(in []byte, offset int, size int) (uint32, bool) {
|
||||||
|
if !inBounds(len(in), offset, size) {
|
||||||
|
return 0, false
|
||||||
|
}
|
||||||
|
|
||||||
|
switch size {
|
||||||
|
case 1:
|
||||||
|
return uint32(in[offset]), true
|
||||||
|
case 2:
|
||||||
|
return uint32(binary.BigEndian.Uint16(in[offset : offset+size])), true
|
||||||
|
case 4:
|
||||||
|
return uint32(binary.BigEndian.Uint32(in[offset : offset+size])), true
|
||||||
|
default:
|
||||||
|
panic(fmt.Sprintf("invalid load size: %d", size))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func loadScratch(ins LoadScratch, regScratch [16]uint32, regA uint32, regX uint32) (uint32, uint32) {
|
||||||
|
switch ins.Dst {
|
||||||
|
case RegA:
|
||||||
|
regA = regScratch[ins.N]
|
||||||
|
case RegX:
|
||||||
|
regX = regScratch[ins.N]
|
||||||
|
}
|
||||||
|
|
||||||
|
return regA, regX
|
||||||
|
}
|
||||||
|
|
||||||
|
func storeScratch(ins StoreScratch, regScratch [16]uint32, regA uint32, regX uint32) [16]uint32 {
|
||||||
|
switch ins.Src {
|
||||||
|
case RegA:
|
||||||
|
regScratch[ins.N] = regA
|
||||||
|
case RegX:
|
||||||
|
regScratch[ins.N] = regX
|
||||||
|
}
|
||||||
|
|
||||||
|
return regScratch
|
||||||
|
}
|
||||||
8
vendor/manifest
vendored
8
vendor/manifest
vendored
@@ -239,6 +239,14 @@
|
|||||||
"branch": "master",
|
"branch": "master",
|
||||||
"path": "/blowfish"
|
"path": "/blowfish"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"importpath": "golang.org/x/net/bpf",
|
||||||
|
"repository": "https://go.googlesource.com/net",
|
||||||
|
"revision": "749a502dd1eaf3e5bfd4f8956748c502357c0bbe",
|
||||||
|
"branch": "master",
|
||||||
|
"path": "/bpf",
|
||||||
|
"notests": true
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"importpath": "golang.org/x/net/context",
|
"importpath": "golang.org/x/net/context",
|
||||||
"repository": "https://go.googlesource.com/net",
|
"repository": "https://go.googlesource.com/net",
|
||||||
|
|||||||
Reference in New Issue
Block a user