delve/pkg/dwarf/op/op.go

111 lines
2.2 KiB
Go
Raw Normal View History

2014-07-30 00:00:24 +00:00
package op
import (
"bytes"
"encoding/binary"
2015-05-07 21:55:06 +00:00
"errors"
2014-07-30 00:00:24 +00:00
"fmt"
2017-02-08 16:00:44 +00:00
"github.com/derekparker/delve/pkg/dwarf/util"
2014-07-30 00:00:24 +00:00
)
const (
DW_OP_addr = 0x3
2014-07-30 00:00:24 +00:00
DW_OP_call_frame_cfa = 0x9c
DW_OP_plus = 0x22
DW_OP_consts = 0x11
DW_OP_plus_uconsts = 0x23
2014-07-30 00:00:24 +00:00
)
type stackfn func(byte, *context) error
type context struct {
buf *bytes.Buffer
stack []int64
DwarfRegisters
}
2014-07-30 00:00:24 +00:00
type Opcode byte
var oplut = map[Opcode]stackfn{
2014-07-30 00:00:24 +00:00
DW_OP_call_frame_cfa: callframecfa,
DW_OP_plus: plus,
DW_OP_consts: consts,
DW_OP_addr: addr,
DW_OP_plus_uconst: plusuconsts,
2014-07-30 00:00:24 +00:00
}
func ExecuteStackProgram(regs DwarfRegisters, instructions []byte) (int64, error) {
ctxt := &context{
buf: bytes.NewBuffer(instructions),
stack: make([]int64, 0, 3),
DwarfRegisters: regs,
}
2014-07-30 00:00:24 +00:00
for {
opcode, err := ctxt.buf.ReadByte()
if err != nil {
break
}
fn, ok := oplut[opcode]
2014-07-30 00:00:24 +00:00
if !ok {
return 0, fmt.Errorf("invalid instruction %#v", opcode)
2014-07-30 00:00:24 +00:00
}
err = fn(opcode, ctxt)
2014-07-30 00:00:24 +00:00
if err != nil {
return 0, err
}
}
if len(ctxt.stack) == 0 {
2015-05-07 21:55:06 +00:00
return 0, errors.New("empty OP stack")
}
return ctxt.stack[len(ctxt.stack)-1], nil
2014-07-30 00:00:24 +00:00
}
func callframecfa(opcode byte, ctxt *context) error {
if ctxt.CFA == 0 {
return fmt.Errorf("Could not retrieve call frame CFA for current PC")
}
ctxt.stack = append(ctxt.stack, int64(ctxt.CFA))
return nil
2014-07-30 00:00:24 +00:00
}
func addr(opcode byte, ctxt *context) error {
ctxt.stack = append(ctxt.stack, int64(binary.LittleEndian.Uint64(ctxt.buf.Next(8))))
return nil
}
func plus(opcode byte, ctxt *context) error {
2014-07-30 00:00:24 +00:00
var (
slen = len(ctxt.stack)
digits = ctxt.stack[slen-2 : slen]
st = ctxt.stack[:slen-2]
2014-07-30 00:00:24 +00:00
)
ctxt.stack = append(st, digits[0]+digits[1])
return nil
}
func plusuconsts(opcode byte, ctxt *context) error {
slen := len(ctxt.stack)
num, _ := util.DecodeULEB128(ctxt.buf)
ctxt.stack[slen-1] = ctxt.stack[slen-1] + int64(num)
return nil
2014-07-30 00:00:24 +00:00
}
func consts(opcode byte, ctxt *context) error {
num, _ := util.DecodeSLEB128(ctxt.buf)
ctxt.stack = append(ctxt.stack, num)
return nil
}
func framebase(opcode byte, ctxt *context) error {
num, _ := util.DecodeSLEB128(ctxt.buf)
ctxt.stack = append(ctxt.stack, ctxt.FrameBase+num)
return nil
2014-07-30 00:00:24 +00:00
}