mirror of
https://github.com/beego/bee.git
synced 2024-12-01 20:21:29 +00:00
85 lines
1.9 KiB
Go
85 lines
1.9 KiB
Go
package op
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/binary"
|
|
"errors"
|
|
"fmt"
|
|
|
|
"github.com/derekparker/delve/pkg/dwarf/util"
|
|
)
|
|
|
|
const (
|
|
DW_OP_addr = 0x3
|
|
DW_OP_call_frame_cfa = 0x9c
|
|
DW_OP_plus = 0x22
|
|
DW_OP_consts = 0x11
|
|
DW_OP_plus_uconsts = 0x23
|
|
)
|
|
|
|
type stackfn func(*bytes.Buffer, []int64, int64) ([]int64, error)
|
|
|
|
var oplut = map[byte]stackfn{
|
|
DW_OP_call_frame_cfa: callframecfa,
|
|
DW_OP_plus: plus,
|
|
DW_OP_consts: consts,
|
|
DW_OP_addr: addr,
|
|
DW_OP_plus_uconsts: plusuconsts,
|
|
}
|
|
|
|
func ExecuteStackProgram(cfa int64, instructions []byte) (int64, error) {
|
|
stack := make([]int64, 0, 3)
|
|
buf := bytes.NewBuffer(instructions)
|
|
|
|
for opcode, err := buf.ReadByte(); err == nil; opcode, err = buf.ReadByte() {
|
|
fn, ok := oplut[opcode]
|
|
if !ok {
|
|
return 0, fmt.Errorf("invalid instruction %#v", opcode)
|
|
}
|
|
|
|
stack, err = fn(buf, stack, cfa)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
}
|
|
|
|
if len(stack) == 0 {
|
|
return 0, errors.New("empty OP stack")
|
|
}
|
|
|
|
return stack[len(stack)-1], nil
|
|
}
|
|
|
|
func callframecfa(buf *bytes.Buffer, stack []int64, cfa int64) ([]int64, error) {
|
|
if cfa == 0 {
|
|
return stack, fmt.Errorf("Could not retrieve CFA for current PC")
|
|
}
|
|
return append(stack, int64(cfa)), nil
|
|
}
|
|
|
|
func addr(buf *bytes.Buffer, stack []int64, cfa int64) ([]int64, error) {
|
|
return append(stack, int64(binary.LittleEndian.Uint64(buf.Next(8)))), nil
|
|
}
|
|
|
|
func plus(buf *bytes.Buffer, stack []int64, cfa int64) ([]int64, error) {
|
|
var (
|
|
slen = len(stack)
|
|
digits = stack[slen-2 : slen]
|
|
st = stack[:slen-2]
|
|
)
|
|
|
|
return append(st, digits[0]+digits[1]), nil
|
|
}
|
|
|
|
func plusuconsts(buf *bytes.Buffer, stack []int64, cfa int64) ([]int64, error) {
|
|
slen := len(stack)
|
|
num, _ := util.DecodeULEB128(buf)
|
|
stack[slen-1] = stack[slen-1] + int64(num)
|
|
return stack, nil
|
|
}
|
|
|
|
func consts(buf *bytes.Buffer, stack []int64, cfa int64) ([]int64, error) {
|
|
num, _ := util.DecodeSLEB128(buf)
|
|
return append(stack, num), nil
|
|
}
|