mirror of
https://github.com/go-delve/delve.git
synced 2026-05-09 14:16:16 +02:00
dwarf/op,proc: implement more DWARF expression opcodes (#2606)
This commit is contained in:
parent
229fcf1559
commit
fdb5189e8c
@ -18,21 +18,25 @@ type Opcode byte
|
||||
|
||||
type stackfn func(Opcode, *context) error
|
||||
|
||||
type ReadMemoryFunc func([]byte, uint64) (int, error)
|
||||
|
||||
type context struct {
|
||||
buf *bytes.Buffer
|
||||
prog []byte
|
||||
stack []int64
|
||||
pieces []Piece
|
||||
reg bool
|
||||
ptrSize int
|
||||
|
||||
DwarfRegisters
|
||||
readMemory ReadMemoryFunc
|
||||
}
|
||||
|
||||
// Piece is a piece of memory stored either at an address or in a register.
|
||||
type Piece struct {
|
||||
Size int
|
||||
Kind PieceKind
|
||||
Val uint64
|
||||
Size int
|
||||
Kind PieceKind
|
||||
Val uint64
|
||||
Bytes []byte
|
||||
}
|
||||
|
||||
// PieceKind describes the kind of a piece.
|
||||
@ -41,32 +45,37 @@ type PieceKind uint8
|
||||
const (
|
||||
AddrPiece PieceKind = iota // The piece is stored in memory, Val is the address
|
||||
RegPiece // The piece is stored in a register, Val is the register number
|
||||
ImmPiece // The piece is an immediate value, Val is the value
|
||||
ImmPiece // The piece is an immediate value, Val or Bytes is the value
|
||||
)
|
||||
|
||||
var (
|
||||
ErrStackUnderflow = errors.New("DWARF stack underflow")
|
||||
ErrStackIndexOutOfBounds = errors.New("DWARF stack index out of bounds")
|
||||
ErrMemoryReadUnavailable = errors.New("memory read unavailable")
|
||||
)
|
||||
|
||||
const arbitraryExecutionLimitFactor = 10
|
||||
|
||||
// ExecuteStackProgram executes a DWARF location expression and returns
|
||||
// either an address (int64), or a slice of Pieces for location expressions
|
||||
// that don't evaluate to an address (such as register and composite expressions).
|
||||
func ExecuteStackProgram(regs DwarfRegisters, instructions []byte, ptrSize int) (int64, []Piece, error) {
|
||||
func ExecuteStackProgram(regs DwarfRegisters, instructions []byte, ptrSize int, readMemory ReadMemoryFunc) (int64, []Piece, error) {
|
||||
ctxt := &context{
|
||||
buf: bytes.NewBuffer(instructions),
|
||||
prog: instructions,
|
||||
stack: make([]int64, 0, 3),
|
||||
DwarfRegisters: regs,
|
||||
ptrSize: ptrSize,
|
||||
}
|
||||
|
||||
for {
|
||||
for tick := 0; tick < len(instructions)*arbitraryExecutionLimitFactor; tick++ {
|
||||
opcodeByte, err := ctxt.buf.ReadByte()
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
opcode := Opcode(opcodeByte)
|
||||
if ctxt.reg && opcode != DW_OP_piece {
|
||||
// last opcode was DW_OP_regN and next one isn't DW_OP_piece so convert
|
||||
// the register piece into a stack value.
|
||||
ctxt.stack = append(ctxt.stack, int64(regs.Uint64Val(ctxt.pieces[len(ctxt.pieces)-1].Val)))
|
||||
ctxt.pieces = ctxt.pieces[:len(ctxt.pieces)-1]
|
||||
ctxt.reg = false
|
||||
if opcode == DW_OP_nop {
|
||||
continue
|
||||
}
|
||||
fn, ok := oplut[opcode]
|
||||
if !ok {
|
||||
@ -143,6 +152,41 @@ func PrettyPrint(out io.Writer, instructions []byte) {
|
||||
}
|
||||
}
|
||||
|
||||
// closeLoc is called by opcodes that can only appear at the end of a
|
||||
// location expression (DW_OP_regN, DW_OP_regx, DW_OP_stack_value...).
|
||||
// It checks that we are at the end of the program or that the following
|
||||
// opcode is DW_OP_piece or DW_OP_bit_piece and processes them.
|
||||
func (ctxt *context) closeLoc(opcode0 Opcode, piece Piece) error {
|
||||
if ctxt.buf.Len() == 0 {
|
||||
ctxt.pieces = append(ctxt.pieces, piece)
|
||||
return nil
|
||||
}
|
||||
|
||||
// DWARF doesn't say what happens to the operand stack at the end of a
|
||||
// location expression, resetting it here.
|
||||
ctxt.stack = ctxt.stack[:0]
|
||||
|
||||
b, err := ctxt.buf.ReadByte()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
opcode := Opcode(b)
|
||||
|
||||
switch opcode {
|
||||
case DW_OP_piece:
|
||||
sz, _ := util.DecodeULEB128(ctxt.buf)
|
||||
piece.Size = int(sz)
|
||||
ctxt.pieces = append(ctxt.pieces, piece)
|
||||
return nil
|
||||
|
||||
case DW_OP_bit_piece:
|
||||
// not supported
|
||||
return fmt.Errorf("invalid instruction %#v", opcode)
|
||||
default:
|
||||
return fmt.Errorf("invalid instruction %#v after %#v", opcode, opcode0)
|
||||
}
|
||||
}
|
||||
|
||||
func callframecfa(opcode Opcode, ctxt *context) error {
|
||||
if ctxt.CFA == 0 {
|
||||
return errors.New("could not retrieve CFA for current PC")
|
||||
@ -161,17 +205,6 @@ func addr(opcode Opcode, ctxt *context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func plus(opcode Opcode, ctxt *context) error {
|
||||
var (
|
||||
slen = len(ctxt.stack)
|
||||
digits = ctxt.stack[slen-2 : slen]
|
||||
st = ctxt.stack[:slen-2]
|
||||
)
|
||||
|
||||
ctxt.stack = append(st, digits[0]+digits[1])
|
||||
return nil
|
||||
}
|
||||
|
||||
func plusuconsts(opcode Opcode, ctxt *context) error {
|
||||
slen := len(ctxt.stack)
|
||||
num, _ := util.DecodeULEB128(ctxt.buf)
|
||||
@ -192,23 +225,32 @@ func framebase(opcode Opcode, ctxt *context) error {
|
||||
}
|
||||
|
||||
func register(opcode Opcode, ctxt *context) error {
|
||||
ctxt.reg = true
|
||||
var regnum uint64
|
||||
if opcode == DW_OP_regx {
|
||||
n, _ := util.DecodeSLEB128(ctxt.buf)
|
||||
ctxt.pieces = append(ctxt.pieces, Piece{Kind: RegPiece, Val: uint64(n)})
|
||||
regnum, _ = util.DecodeULEB128(ctxt.buf)
|
||||
} else {
|
||||
ctxt.pieces = append(ctxt.pieces, Piece{Kind: RegPiece, Val: uint64(opcode - DW_OP_reg0)})
|
||||
regnum = uint64(opcode - DW_OP_reg0)
|
||||
}
|
||||
return ctxt.closeLoc(opcode, Piece{Kind: RegPiece, Val: regnum})
|
||||
}
|
||||
|
||||
func bregister(opcode Opcode, ctxt *context) error {
|
||||
var regnum uint64
|
||||
if opcode == DW_OP_bregx {
|
||||
regnum, _ = util.DecodeULEB128(ctxt.buf)
|
||||
} else {
|
||||
regnum = uint64(opcode - DW_OP_breg0)
|
||||
}
|
||||
offset, _ := util.DecodeSLEB128(ctxt.buf)
|
||||
if ctxt.Reg(regnum) == nil {
|
||||
return fmt.Errorf("register %d not available", regnum)
|
||||
}
|
||||
ctxt.stack = append(ctxt.stack, int64(ctxt.Uint64Val(regnum))+offset)
|
||||
return nil
|
||||
}
|
||||
|
||||
func piece(opcode Opcode, ctxt *context) error {
|
||||
sz, _ := util.DecodeULEB128(ctxt.buf)
|
||||
if ctxt.reg {
|
||||
ctxt.reg = false
|
||||
ctxt.pieces[len(ctxt.pieces)-1].Size = int(sz)
|
||||
return nil
|
||||
}
|
||||
|
||||
if len(ctxt.stack) == 0 {
|
||||
// nothing on the stack means this piece is unavailable (padding,
|
||||
@ -222,3 +264,293 @@ func piece(opcode Opcode, ctxt *context) error {
|
||||
ctxt.stack = ctxt.stack[:0]
|
||||
return nil
|
||||
}
|
||||
|
||||
func literal(opcode Opcode, ctxt *context) error {
|
||||
ctxt.stack = append(ctxt.stack, int64(opcode-DW_OP_lit0))
|
||||
return nil
|
||||
}
|
||||
|
||||
func constnu(opcode Opcode, ctxt *context) error {
|
||||
var (
|
||||
n uint64
|
||||
err error
|
||||
)
|
||||
switch opcode {
|
||||
case DW_OP_const1u:
|
||||
var b uint8
|
||||
b, err = ctxt.buf.ReadByte()
|
||||
n = uint64(b)
|
||||
case DW_OP_const2u:
|
||||
n, err = util.ReadUintRaw(ctxt.buf, binary.LittleEndian, 2)
|
||||
case DW_OP_const4u:
|
||||
n, err = util.ReadUintRaw(ctxt.buf, binary.LittleEndian, 4)
|
||||
case DW_OP_const8u:
|
||||
n, err = util.ReadUintRaw(ctxt.buf, binary.LittleEndian, 8)
|
||||
default:
|
||||
panic("internal error")
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ctxt.stack = append(ctxt.stack, int64(n))
|
||||
return nil
|
||||
}
|
||||
|
||||
func constns(opcode Opcode, ctxt *context) error {
|
||||
var (
|
||||
n uint64
|
||||
err error
|
||||
)
|
||||
switch opcode {
|
||||
case DW_OP_const1s:
|
||||
var b uint8
|
||||
b, err = ctxt.buf.ReadByte()
|
||||
n = uint64(int64(int8(b)))
|
||||
case DW_OP_const2s:
|
||||
n, err = util.ReadUintRaw(ctxt.buf, binary.LittleEndian, 2)
|
||||
n = uint64(int64(int16(n)))
|
||||
case DW_OP_const4s:
|
||||
n, err = util.ReadUintRaw(ctxt.buf, binary.LittleEndian, 4)
|
||||
n = uint64(int64(int32(n)))
|
||||
case DW_OP_const8s:
|
||||
n, err = util.ReadUintRaw(ctxt.buf, binary.LittleEndian, 8)
|
||||
default:
|
||||
panic("internal error")
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ctxt.stack = append(ctxt.stack, int64(n))
|
||||
return nil
|
||||
}
|
||||
|
||||
func constu(opcode Opcode, ctxt *context) error {
|
||||
num, _ := util.DecodeULEB128(ctxt.buf)
|
||||
ctxt.stack = append(ctxt.stack, int64(num))
|
||||
return nil
|
||||
}
|
||||
|
||||
func dup(_ Opcode, ctxt *context) error {
|
||||
if len(ctxt.stack) <= 0 {
|
||||
return ErrStackUnderflow
|
||||
}
|
||||
ctxt.stack = append(ctxt.stack, ctxt.stack[len(ctxt.stack)-1])
|
||||
return nil
|
||||
}
|
||||
|
||||
func drop(_ Opcode, ctxt *context) error {
|
||||
if len(ctxt.stack) <= 0 {
|
||||
return ErrStackUnderflow
|
||||
}
|
||||
ctxt.stack = ctxt.stack[:len(ctxt.stack)-1]
|
||||
return nil
|
||||
}
|
||||
|
||||
func pick(opcode Opcode, ctxt *context) error {
|
||||
var n byte
|
||||
switch opcode {
|
||||
case DW_OP_pick:
|
||||
n, _ = ctxt.buf.ReadByte()
|
||||
case DW_OP_over:
|
||||
n = 1
|
||||
default:
|
||||
panic("internal error")
|
||||
}
|
||||
idx := len(ctxt.stack) - 1 - int(uint8(n))
|
||||
if idx < 0 || idx >= len(ctxt.stack) {
|
||||
return ErrStackIndexOutOfBounds
|
||||
}
|
||||
ctxt.stack = append(ctxt.stack, ctxt.stack[idx])
|
||||
return nil
|
||||
}
|
||||
|
||||
func swap(_ Opcode, ctxt *context) error {
|
||||
if len(ctxt.stack) < 2 {
|
||||
return ErrStackUnderflow
|
||||
}
|
||||
ctxt.stack[len(ctxt.stack)-1], ctxt.stack[len(ctxt.stack)-2] = ctxt.stack[len(ctxt.stack)-2], ctxt.stack[len(ctxt.stack)-1]
|
||||
return nil
|
||||
}
|
||||
|
||||
func rot(_ Opcode, ctxt *context) error {
|
||||
if len(ctxt.stack) < 3 {
|
||||
return ErrStackUnderflow
|
||||
}
|
||||
ctxt.stack[len(ctxt.stack)-1], ctxt.stack[len(ctxt.stack)-2], ctxt.stack[len(ctxt.stack)-3] = ctxt.stack[len(ctxt.stack)-2], ctxt.stack[len(ctxt.stack)-3], ctxt.stack[len(ctxt.stack)-1]
|
||||
return nil
|
||||
}
|
||||
|
||||
func unaryop(opcode Opcode, ctxt *context) error {
|
||||
if len(ctxt.stack) < 1 {
|
||||
return ErrStackUnderflow
|
||||
}
|
||||
operand := ctxt.stack[len(ctxt.stack)-1]
|
||||
switch opcode {
|
||||
case DW_OP_abs:
|
||||
if operand < 0 {
|
||||
operand = -operand
|
||||
}
|
||||
case DW_OP_neg:
|
||||
operand = -operand
|
||||
case DW_OP_not:
|
||||
operand = ^operand
|
||||
default:
|
||||
panic("internal error")
|
||||
}
|
||||
ctxt.stack[len(ctxt.stack)-1] = operand
|
||||
return nil
|
||||
}
|
||||
|
||||
func binaryop(opcode Opcode, ctxt *context) error {
|
||||
if len(ctxt.stack) < 2 {
|
||||
return ErrStackUnderflow
|
||||
}
|
||||
second := ctxt.stack[len(ctxt.stack)-2]
|
||||
top := ctxt.stack[len(ctxt.stack)-1]
|
||||
var r int64
|
||||
ctxt.stack = ctxt.stack[:len(ctxt.stack)-2]
|
||||
switch opcode {
|
||||
case DW_OP_and:
|
||||
r = second & top
|
||||
case DW_OP_div:
|
||||
r = second / top
|
||||
case DW_OP_minus:
|
||||
r = second - top
|
||||
case DW_OP_mod:
|
||||
r = second % top
|
||||
case DW_OP_mul:
|
||||
r = second * top
|
||||
case DW_OP_or:
|
||||
r = second | top
|
||||
case DW_OP_plus:
|
||||
r = second + top
|
||||
case DW_OP_shl:
|
||||
r = second << uint64(top)
|
||||
case DW_OP_shr:
|
||||
r = second >> uint64(top)
|
||||
case DW_OP_shra:
|
||||
r = int64(uint64(second) >> uint64(top))
|
||||
case DW_OP_xor:
|
||||
r = second ^ top
|
||||
case DW_OP_le:
|
||||
r = bool2int(second <= top)
|
||||
case DW_OP_ge:
|
||||
r = bool2int(second >= top)
|
||||
case DW_OP_eq:
|
||||
r = bool2int(second == top)
|
||||
case DW_OP_lt:
|
||||
r = bool2int(second < top)
|
||||
case DW_OP_gt:
|
||||
r = bool2int(second > top)
|
||||
case DW_OP_ne:
|
||||
r = bool2int(second != top)
|
||||
default:
|
||||
panic("internal error")
|
||||
}
|
||||
ctxt.stack = append(ctxt.stack, r)
|
||||
return nil
|
||||
}
|
||||
|
||||
func bool2int(b bool) int64 {
|
||||
if b {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (ctxt *context) jump(n int16) error {
|
||||
i := len(ctxt.prog) - ctxt.buf.Len() + int(n)
|
||||
if i < 0 {
|
||||
return ErrStackUnderflow
|
||||
}
|
||||
if i >= len(ctxt.prog) {
|
||||
i = len(ctxt.prog)
|
||||
}
|
||||
ctxt.buf = bytes.NewBuffer(ctxt.prog[i:])
|
||||
return nil
|
||||
}
|
||||
|
||||
func skip(_ Opcode, ctxt *context) error {
|
||||
var n int16
|
||||
binary.Read(ctxt.buf, binary.LittleEndian, &n)
|
||||
return ctxt.jump(n)
|
||||
}
|
||||
|
||||
func bra(_ Opcode, ctxt *context) error {
|
||||
var n int16
|
||||
binary.Read(ctxt.buf, binary.LittleEndian, &n)
|
||||
|
||||
if len(ctxt.stack) < 1 {
|
||||
return ErrStackUnderflow
|
||||
}
|
||||
top := ctxt.stack[len(ctxt.stack)-1]
|
||||
ctxt.stack = ctxt.stack[:len(ctxt.stack)-1]
|
||||
if top != 0 {
|
||||
return ctxt.jump(n)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func stackvalue(_ Opcode, ctxt *context) error {
|
||||
if len(ctxt.stack) < 1 {
|
||||
return ErrStackUnderflow
|
||||
}
|
||||
val := ctxt.stack[len(ctxt.stack)-1]
|
||||
ctxt.stack = ctxt.stack[:len(ctxt.stack)-1]
|
||||
return ctxt.closeLoc(DW_OP_stack_value, Piece{Kind: ImmPiece, Val: uint64(val)})
|
||||
}
|
||||
|
||||
func implicitvalue(_ Opcode, ctxt *context) error {
|
||||
sz, _ := util.DecodeULEB128(ctxt.buf)
|
||||
block := make([]byte, sz)
|
||||
n, _ := ctxt.buf.Read(block)
|
||||
if uint64(n) != sz {
|
||||
return fmt.Errorf("insufficient bytes read while reading DW_OP_implicit_value's block %d (expected: %d)", n, sz)
|
||||
}
|
||||
return ctxt.closeLoc(DW_OP_implicit_value, Piece{Kind: ImmPiece, Bytes: block, Size: int(sz)})
|
||||
}
|
||||
|
||||
func deref(op Opcode, ctxt *context) error {
|
||||
if ctxt.readMemory == nil {
|
||||
return ErrMemoryReadUnavailable
|
||||
}
|
||||
|
||||
sz := ctxt.ptrSize
|
||||
if op == DW_OP_deref_size || op == DW_OP_xderef_size {
|
||||
n, err := ctxt.buf.ReadByte()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
sz = int(n)
|
||||
}
|
||||
|
||||
if len(ctxt.stack) <= 0 {
|
||||
return ErrStackUnderflow
|
||||
}
|
||||
|
||||
addr := ctxt.stack[len(ctxt.stack)-1]
|
||||
ctxt.stack = ctxt.stack[:len(ctxt.stack)-1]
|
||||
|
||||
if op == DW_OP_xderef || op == DW_OP_xderef_size {
|
||||
if len(ctxt.stack) <= 0 {
|
||||
return ErrStackUnderflow
|
||||
}
|
||||
// the second element on the stack is the "address space identifier" which we don't do anything with
|
||||
ctxt.stack = ctxt.stack[:len(ctxt.stack)-1]
|
||||
}
|
||||
|
||||
buf := make([]byte, sz)
|
||||
_, err := ctxt.readMemory(buf, uint64(addr))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
x, err := util.ReadUintRaw(bytes.NewReader(buf), binary.LittleEndian, sz)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ctxt.stack = append(ctxt.stack, int64(x))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -1,25 +1,58 @@
|
||||
package op
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
func ptrSizeByRuntimeArch() int {
|
||||
return int(unsafe.Sizeof(uintptr(0)))
|
||||
func assertExprResult(t *testing.T, expected int64, instructions []byte) {
|
||||
t.Helper()
|
||||
actual, _, err := ExecuteStackProgram(DwarfRegisters{}, instructions, 8, nil)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if actual != expected {
|
||||
buf := new(strings.Builder)
|
||||
PrettyPrint(buf, instructions)
|
||||
t.Errorf("actual %d != expected %d (in %s)", actual, expected, buf.String())
|
||||
}
|
||||
}
|
||||
|
||||
func TestExecuteStackProgram(t *testing.T) {
|
||||
var (
|
||||
instructions = []byte{byte(DW_OP_consts), 0x1c, byte(DW_OP_consts), 0x1c, byte(DW_OP_plus)}
|
||||
expected = int64(56)
|
||||
)
|
||||
actual, _, err := ExecuteStackProgram(DwarfRegisters{}, instructions, ptrSizeByRuntimeArch())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if actual != expected {
|
||||
t.Fatalf("actual %d != expected %d", actual, expected)
|
||||
}
|
||||
assertExprResult(t, 56, []byte{byte(DW_OP_consts), 0x1c, byte(DW_OP_consts), 0x1c, byte(DW_OP_plus)})
|
||||
}
|
||||
|
||||
func TestSignExtension(t *testing.T) {
|
||||
var tgt uint64 = 0xffffffffffffff88
|
||||
assertExprResult(t, int64(tgt), []byte{byte(DW_OP_const1s), 0x88})
|
||||
tgt = 0xffffffffffff8888
|
||||
assertExprResult(t, int64(tgt), []byte{byte(DW_OP_const2s), 0x88, 0x88})
|
||||
}
|
||||
|
||||
func TestStackOps(t *testing.T) {
|
||||
assertExprResult(t, 1, []byte{byte(DW_OP_lit1), byte(DW_OP_lit2), byte(DW_OP_drop)})
|
||||
assertExprResult(t, 0, []byte{byte(DW_OP_lit1), byte(DW_OP_lit0), byte(DW_OP_pick), 0})
|
||||
assertExprResult(t, 1, []byte{byte(DW_OP_lit1), byte(DW_OP_lit0), byte(DW_OP_pick), 1})
|
||||
}
|
||||
|
||||
func TestBra(t *testing.T) {
|
||||
assertExprResult(t, 32, []byte{
|
||||
byte(DW_OP_lit1),
|
||||
byte(DW_OP_lit5),
|
||||
|
||||
byte(DW_OP_dup),
|
||||
byte(DW_OP_lit0),
|
||||
byte(DW_OP_eq),
|
||||
byte(DW_OP_bra), 9, 0x0,
|
||||
|
||||
byte(DW_OP_swap),
|
||||
byte(DW_OP_dup),
|
||||
byte(DW_OP_plus),
|
||||
byte(DW_OP_swap),
|
||||
byte(DW_OP_lit1),
|
||||
byte(DW_OP_minus),
|
||||
byte(DW_OP_skip), 0xf1, 0xff,
|
||||
|
||||
byte(DW_OP_drop),
|
||||
})
|
||||
}
|
||||
|
||||
@ -473,9 +473,79 @@ var opcodeArgs = map[Opcode]string{
|
||||
}
|
||||
var oplut = map[Opcode]stackfn{
|
||||
DW_OP_addr: addr,
|
||||
DW_OP_deref: deref,
|
||||
DW_OP_const1u: constnu,
|
||||
DW_OP_const1s: constns,
|
||||
DW_OP_const2u: constnu,
|
||||
DW_OP_const2s: constns,
|
||||
DW_OP_const4u: constnu,
|
||||
DW_OP_const4s: constns,
|
||||
DW_OP_const8u: constnu,
|
||||
DW_OP_const8s: constns,
|
||||
DW_OP_constu: constu,
|
||||
DW_OP_consts: consts,
|
||||
DW_OP_plus: plus,
|
||||
DW_OP_dup: dup,
|
||||
DW_OP_drop: drop,
|
||||
DW_OP_over: pick,
|
||||
DW_OP_pick: pick,
|
||||
DW_OP_swap: swap,
|
||||
DW_OP_rot: rot,
|
||||
DW_OP_xderef: deref,
|
||||
DW_OP_abs: unaryop,
|
||||
DW_OP_and: binaryop,
|
||||
DW_OP_div: binaryop,
|
||||
DW_OP_minus: binaryop,
|
||||
DW_OP_mod: binaryop,
|
||||
DW_OP_mul: binaryop,
|
||||
DW_OP_neg: unaryop,
|
||||
DW_OP_not: unaryop,
|
||||
DW_OP_or: binaryop,
|
||||
DW_OP_plus: binaryop,
|
||||
DW_OP_plus_uconst: plusuconsts,
|
||||
DW_OP_shl: binaryop,
|
||||
DW_OP_shr: binaryop,
|
||||
DW_OP_shra: binaryop,
|
||||
DW_OP_xor: binaryop,
|
||||
DW_OP_bra: bra,
|
||||
DW_OP_eq: binaryop,
|
||||
DW_OP_ge: binaryop,
|
||||
DW_OP_gt: binaryop,
|
||||
DW_OP_le: binaryop,
|
||||
DW_OP_lt: binaryop,
|
||||
DW_OP_ne: binaryop,
|
||||
DW_OP_skip: skip,
|
||||
DW_OP_lit0: literal,
|
||||
DW_OP_lit1: literal,
|
||||
DW_OP_lit2: literal,
|
||||
DW_OP_lit3: literal,
|
||||
DW_OP_lit4: literal,
|
||||
DW_OP_lit5: literal,
|
||||
DW_OP_lit6: literal,
|
||||
DW_OP_lit7: literal,
|
||||
DW_OP_lit8: literal,
|
||||
DW_OP_lit9: literal,
|
||||
DW_OP_lit10: literal,
|
||||
DW_OP_lit11: literal,
|
||||
DW_OP_lit12: literal,
|
||||
DW_OP_lit13: literal,
|
||||
DW_OP_lit14: literal,
|
||||
DW_OP_lit15: literal,
|
||||
DW_OP_lit16: literal,
|
||||
DW_OP_lit17: literal,
|
||||
DW_OP_lit18: literal,
|
||||
DW_OP_lit19: literal,
|
||||
DW_OP_lit20: literal,
|
||||
DW_OP_lit21: literal,
|
||||
DW_OP_lit22: literal,
|
||||
DW_OP_lit23: literal,
|
||||
DW_OP_lit24: literal,
|
||||
DW_OP_lit25: literal,
|
||||
DW_OP_lit26: literal,
|
||||
DW_OP_lit27: literal,
|
||||
DW_OP_lit28: literal,
|
||||
DW_OP_lit29: literal,
|
||||
DW_OP_lit30: literal,
|
||||
DW_OP_lit31: literal,
|
||||
DW_OP_reg0: register,
|
||||
DW_OP_reg1: register,
|
||||
DW_OP_reg2: register,
|
||||
@ -508,8 +578,45 @@ var oplut = map[Opcode]stackfn{
|
||||
DW_OP_reg29: register,
|
||||
DW_OP_reg30: register,
|
||||
DW_OP_reg31: register,
|
||||
DW_OP_breg0: bregister,
|
||||
DW_OP_breg1: bregister,
|
||||
DW_OP_breg2: bregister,
|
||||
DW_OP_breg3: bregister,
|
||||
DW_OP_breg4: bregister,
|
||||
DW_OP_breg5: bregister,
|
||||
DW_OP_breg6: bregister,
|
||||
DW_OP_breg7: bregister,
|
||||
DW_OP_breg8: bregister,
|
||||
DW_OP_breg9: bregister,
|
||||
DW_OP_breg10: bregister,
|
||||
DW_OP_breg11: bregister,
|
||||
DW_OP_breg12: bregister,
|
||||
DW_OP_breg13: bregister,
|
||||
DW_OP_breg14: bregister,
|
||||
DW_OP_breg15: bregister,
|
||||
DW_OP_breg16: bregister,
|
||||
DW_OP_breg17: bregister,
|
||||
DW_OP_breg18: bregister,
|
||||
DW_OP_breg19: bregister,
|
||||
DW_OP_breg20: bregister,
|
||||
DW_OP_breg21: bregister,
|
||||
DW_OP_breg22: bregister,
|
||||
DW_OP_breg23: bregister,
|
||||
DW_OP_breg24: bregister,
|
||||
DW_OP_breg25: bregister,
|
||||
DW_OP_breg26: bregister,
|
||||
DW_OP_breg27: bregister,
|
||||
DW_OP_breg28: bregister,
|
||||
DW_OP_breg29: bregister,
|
||||
DW_OP_breg30: bregister,
|
||||
DW_OP_breg31: bregister,
|
||||
DW_OP_regx: register,
|
||||
DW_OP_fbreg: framebase,
|
||||
DW_OP_bregx: bregister,
|
||||
DW_OP_piece: piece,
|
||||
DW_OP_deref_size: deref,
|
||||
DW_OP_xderef_size: deref,
|
||||
DW_OP_call_frame_cfa: callframecfa,
|
||||
DW_OP_implicit_value: implicitvalue,
|
||||
DW_OP_stack_value: stackvalue,
|
||||
}
|
||||
|
||||
@ -20,79 +20,79 @@
|
||||
|
||||
|
||||
DW_OP_addr 0x03 "8" addr
|
||||
DW_OP_deref 0x06 ""
|
||||
DW_OP_const1u 0x08 "1"
|
||||
DW_OP_const1s 0x09 "1"
|
||||
DW_OP_const2u 0x0a "2"
|
||||
DW_OP_const2s 0x0b "2"
|
||||
DW_OP_const4u 0x0c "4"
|
||||
DW_OP_const4s 0x0d "4"
|
||||
DW_OP_const8u 0x0e "8"
|
||||
DW_OP_const8s 0x0f "8"
|
||||
DW_OP_constu 0x10 "u"
|
||||
DW_OP_deref 0x06 "" deref
|
||||
DW_OP_const1u 0x08 "1" constnu
|
||||
DW_OP_const1s 0x09 "1" constns
|
||||
DW_OP_const2u 0x0a "2" constnu
|
||||
DW_OP_const2s 0x0b "2" constns
|
||||
DW_OP_const4u 0x0c "4" constnu
|
||||
DW_OP_const4s 0x0d "4" constns
|
||||
DW_OP_const8u 0x0e "8" constnu
|
||||
DW_OP_const8s 0x0f "8" constns
|
||||
DW_OP_constu 0x10 "u" constu
|
||||
DW_OP_consts 0x11 "s" consts
|
||||
DW_OP_dup 0x12 ""
|
||||
DW_OP_drop 0x13 ""
|
||||
DW_OP_over 0x14 ""
|
||||
DW_OP_pick 0x15 ""
|
||||
DW_OP_swap 0x16 ""
|
||||
DW_OP_rot 0x17 ""
|
||||
DW_OP_xderef 0x18 ""
|
||||
DW_OP_abs 0x19 ""
|
||||
DW_OP_and 0x1a ""
|
||||
DW_OP_div 0x1b ""
|
||||
DW_OP_minus 0x1c ""
|
||||
DW_OP_mod 0x1d ""
|
||||
DW_OP_mul 0x1e ""
|
||||
DW_OP_neg 0x1f ""
|
||||
DW_OP_not 0x20 ""
|
||||
DW_OP_or 0x21 ""
|
||||
DW_OP_plus 0x22 "" plus
|
||||
DW_OP_dup 0x12 "" dup
|
||||
DW_OP_drop 0x13 "" drop
|
||||
DW_OP_over 0x14 "" pick
|
||||
DW_OP_pick 0x15 "" pick
|
||||
DW_OP_swap 0x16 "" swap
|
||||
DW_OP_rot 0x17 "" rot
|
||||
DW_OP_xderef 0x18 "" deref
|
||||
DW_OP_abs 0x19 "" unaryop
|
||||
DW_OP_and 0x1a "" binaryop
|
||||
DW_OP_div 0x1b "" binaryop
|
||||
DW_OP_minus 0x1c "" binaryop
|
||||
DW_OP_mod 0x1d "" binaryop
|
||||
DW_OP_mul 0x1e "" binaryop
|
||||
DW_OP_neg 0x1f "" unaryop
|
||||
DW_OP_not 0x20 "" unaryop
|
||||
DW_OP_or 0x21 "" binaryop
|
||||
DW_OP_plus 0x22 "" binaryop
|
||||
DW_OP_plus_uconst 0x23 "u" plusuconsts
|
||||
DW_OP_shl 0x24 ""
|
||||
DW_OP_shr 0x25 ""
|
||||
DW_OP_shra 0x26 ""
|
||||
DW_OP_xor 0x27 ""
|
||||
DW_OP_bra 0x28 "2"
|
||||
DW_OP_eq 0x29 ""
|
||||
DW_OP_ge 0x2a ""
|
||||
DW_OP_gt 0x2b ""
|
||||
DW_OP_le 0x2c ""
|
||||
DW_OP_lt 0x2d ""
|
||||
DW_OP_ne 0x2e ""
|
||||
DW_OP_skip 0x2f "2"
|
||||
DW_OP_lit0 0x30 ""
|
||||
DW_OP_lit1 0x31 ""
|
||||
DW_OP_lit2 0x32 ""
|
||||
DW_OP_lit3 0x33 ""
|
||||
DW_OP_lit4 0x34 ""
|
||||
DW_OP_lit5 0x35 ""
|
||||
DW_OP_lit6 0x36 ""
|
||||
DW_OP_lit7 0x37 ""
|
||||
DW_OP_lit8 0x38 ""
|
||||
DW_OP_lit9 0x39 ""
|
||||
DW_OP_lit10 0x3a ""
|
||||
DW_OP_lit11 0x3b ""
|
||||
DW_OP_lit12 0x3c ""
|
||||
DW_OP_lit13 0x3d ""
|
||||
DW_OP_lit14 0x3e ""
|
||||
DW_OP_lit15 0x3f ""
|
||||
DW_OP_lit16 0x40 ""
|
||||
DW_OP_lit17 0x41 ""
|
||||
DW_OP_lit18 0x42 ""
|
||||
DW_OP_lit19 0x43 ""
|
||||
DW_OP_lit20 0x44 ""
|
||||
DW_OP_lit21 0x45 ""
|
||||
DW_OP_lit22 0x46 ""
|
||||
DW_OP_lit23 0x47 ""
|
||||
DW_OP_lit24 0x48 ""
|
||||
DW_OP_lit25 0x49 ""
|
||||
DW_OP_lit26 0x4a ""
|
||||
DW_OP_lit27 0x4b ""
|
||||
DW_OP_lit28 0x4c ""
|
||||
DW_OP_lit29 0x4d ""
|
||||
DW_OP_lit30 0x4e ""
|
||||
DW_OP_lit31 0x4f ""
|
||||
DW_OP_shl 0x24 "" binaryop
|
||||
DW_OP_shr 0x25 "" binaryop
|
||||
DW_OP_shra 0x26 "" binaryop
|
||||
DW_OP_xor 0x27 "" binaryop
|
||||
DW_OP_bra 0x28 "2" bra
|
||||
DW_OP_eq 0x29 "" binaryop
|
||||
DW_OP_ge 0x2a "" binaryop
|
||||
DW_OP_gt 0x2b "" binaryop
|
||||
DW_OP_le 0x2c "" binaryop
|
||||
DW_OP_lt 0x2d "" binaryop
|
||||
DW_OP_ne 0x2e "" binaryop
|
||||
DW_OP_skip 0x2f "2" skip
|
||||
DW_OP_lit0 0x30 "" literal
|
||||
DW_OP_lit1 0x31 "" literal
|
||||
DW_OP_lit2 0x32 "" literal
|
||||
DW_OP_lit3 0x33 "" literal
|
||||
DW_OP_lit4 0x34 "" literal
|
||||
DW_OP_lit5 0x35 "" literal
|
||||
DW_OP_lit6 0x36 "" literal
|
||||
DW_OP_lit7 0x37 "" literal
|
||||
DW_OP_lit8 0x38 "" literal
|
||||
DW_OP_lit9 0x39 "" literal
|
||||
DW_OP_lit10 0x3a "" literal
|
||||
DW_OP_lit11 0x3b "" literal
|
||||
DW_OP_lit12 0x3c "" literal
|
||||
DW_OP_lit13 0x3d "" literal
|
||||
DW_OP_lit14 0x3e "" literal
|
||||
DW_OP_lit15 0x3f "" literal
|
||||
DW_OP_lit16 0x40 "" literal
|
||||
DW_OP_lit17 0x41 "" literal
|
||||
DW_OP_lit18 0x42 "" literal
|
||||
DW_OP_lit19 0x43 "" literal
|
||||
DW_OP_lit20 0x44 "" literal
|
||||
DW_OP_lit21 0x45 "" literal
|
||||
DW_OP_lit22 0x46 "" literal
|
||||
DW_OP_lit23 0x47 "" literal
|
||||
DW_OP_lit24 0x48 "" literal
|
||||
DW_OP_lit25 0x49 "" literal
|
||||
DW_OP_lit26 0x4a "" literal
|
||||
DW_OP_lit27 0x4b "" literal
|
||||
DW_OP_lit28 0x4c "" literal
|
||||
DW_OP_lit29 0x4d "" literal
|
||||
DW_OP_lit30 0x4e "" literal
|
||||
DW_OP_lit31 0x4f "" literal
|
||||
DW_OP_reg0 0x50 "" register
|
||||
DW_OP_reg1 0x51 "" register
|
||||
DW_OP_reg2 0x52 "" register
|
||||
@ -125,44 +125,44 @@ DW_OP_reg28 0x6c "" register
|
||||
DW_OP_reg29 0x6d "" register
|
||||
DW_OP_reg30 0x6e "" register
|
||||
DW_OP_reg31 0x6f "" register
|
||||
DW_OP_breg0 0x70 "s"
|
||||
DW_OP_breg1 0x71 "s"
|
||||
DW_OP_breg2 0x72 "s"
|
||||
DW_OP_breg3 0x73 "s"
|
||||
DW_OP_breg4 0x74 "s"
|
||||
DW_OP_breg5 0x75 "s"
|
||||
DW_OP_breg6 0x76 "s"
|
||||
DW_OP_breg7 0x77 "s"
|
||||
DW_OP_breg8 0x78 "s"
|
||||
DW_OP_breg9 0x79 "s"
|
||||
DW_OP_breg10 0x7a "s"
|
||||
DW_OP_breg11 0x7b "s"
|
||||
DW_OP_breg12 0x7c "s"
|
||||
DW_OP_breg13 0x7d "s"
|
||||
DW_OP_breg14 0x7e "s"
|
||||
DW_OP_breg15 0x7f "s"
|
||||
DW_OP_breg16 0x80 "s"
|
||||
DW_OP_breg17 0x81 "s"
|
||||
DW_OP_breg18 0x82 "s"
|
||||
DW_OP_breg19 0x83 "s"
|
||||
DW_OP_breg20 0x84 "s"
|
||||
DW_OP_breg21 0x85 "s"
|
||||
DW_OP_breg22 0x86 "s"
|
||||
DW_OP_breg23 0x87 "s"
|
||||
DW_OP_breg24 0x88 "s"
|
||||
DW_OP_breg25 0x89 "s"
|
||||
DW_OP_breg26 0x8a "s"
|
||||
DW_OP_breg27 0x8b "s"
|
||||
DW_OP_breg28 0x8c "s"
|
||||
DW_OP_breg29 0x8d "s"
|
||||
DW_OP_breg30 0x8e "s"
|
||||
DW_OP_breg31 0x8f "s"
|
||||
DW_OP_breg0 0x70 "s" bregister
|
||||
DW_OP_breg1 0x71 "s" bregister
|
||||
DW_OP_breg2 0x72 "s" bregister
|
||||
DW_OP_breg3 0x73 "s" bregister
|
||||
DW_OP_breg4 0x74 "s" bregister
|
||||
DW_OP_breg5 0x75 "s" bregister
|
||||
DW_OP_breg6 0x76 "s" bregister
|
||||
DW_OP_breg7 0x77 "s" bregister
|
||||
DW_OP_breg8 0x78 "s" bregister
|
||||
DW_OP_breg9 0x79 "s" bregister
|
||||
DW_OP_breg10 0x7a "s" bregister
|
||||
DW_OP_breg11 0x7b "s" bregister
|
||||
DW_OP_breg12 0x7c "s" bregister
|
||||
DW_OP_breg13 0x7d "s" bregister
|
||||
DW_OP_breg14 0x7e "s" bregister
|
||||
DW_OP_breg15 0x7f "s" bregister
|
||||
DW_OP_breg16 0x80 "s" bregister
|
||||
DW_OP_breg17 0x81 "s" bregister
|
||||
DW_OP_breg18 0x82 "s" bregister
|
||||
DW_OP_breg19 0x83 "s" bregister
|
||||
DW_OP_breg20 0x84 "s" bregister
|
||||
DW_OP_breg21 0x85 "s" bregister
|
||||
DW_OP_breg22 0x86 "s" bregister
|
||||
DW_OP_breg23 0x87 "s" bregister
|
||||
DW_OP_breg24 0x88 "s" bregister
|
||||
DW_OP_breg25 0x89 "s" bregister
|
||||
DW_OP_breg26 0x8a "s" bregister
|
||||
DW_OP_breg27 0x8b "s" bregister
|
||||
DW_OP_breg28 0x8c "s" bregister
|
||||
DW_OP_breg29 0x8d "s" bregister
|
||||
DW_OP_breg30 0x8e "s" bregister
|
||||
DW_OP_breg31 0x8f "s" bregister
|
||||
DW_OP_regx 0x90 "s" register
|
||||
DW_OP_fbreg 0x91 "s" framebase
|
||||
DW_OP_bregx 0x92 "us"
|
||||
DW_OP_bregx 0x92 "us" bregister
|
||||
DW_OP_piece 0x93 "u" piece
|
||||
DW_OP_deref_size 0x94 "1"
|
||||
DW_OP_xderef_size 0x95 "1"
|
||||
DW_OP_deref_size 0x94 "1" deref
|
||||
DW_OP_xderef_size 0x95 "1" deref
|
||||
DW_OP_nop 0x96 ""
|
||||
DW_OP_push_object_address 0x97 ""
|
||||
DW_OP_call2 0x98 "2"
|
||||
@ -171,5 +171,5 @@ DW_OP_call_ref 0x9a "4"
|
||||
DW_OP_form_tls_address 0x9b ""
|
||||
DW_OP_call_frame_cfa 0x9c "" callframecfa
|
||||
DW_OP_bit_piece 0x9d "uu"
|
||||
DW_OP_implicit_value 0x9e "B"
|
||||
DW_OP_stack_value 0x9f ""
|
||||
DW_OP_implicit_value 0x9e "B" implicitvalue
|
||||
DW_OP_stack_value 0x9f "" stackvalue
|
||||
|
||||
@ -43,7 +43,7 @@ func (reader *Reader) AddrFor(name string, staticBase uint64, ptrSize int) (uint
|
||||
if !ok {
|
||||
return 0, fmt.Errorf("type assertion failed")
|
||||
}
|
||||
addr, _, err := op.ExecuteStackProgram(op.DwarfRegisters{StaticBase: staticBase}, instructions, ptrSize)
|
||||
addr, _, err := op.ExecuteStackProgram(op.DwarfRegisters{StaticBase: staticBase}, instructions, ptrSize, nil)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
@ -69,7 +69,7 @@ func (reader *Reader) AddrForMember(member string, initialInstructions []byte, p
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
addr, _, err := op.ExecuteStackProgram(op.DwarfRegisters{}, append(initialInstructions, instructions...), ptrSize)
|
||||
addr, _, err := op.ExecuteStackProgram(op.DwarfRegisters{}, append(initialInstructions, instructions...), ptrSize, nil)
|
||||
return uint64(addr), err
|
||||
}
|
||||
}
|
||||
|
||||
@ -140,6 +140,12 @@ func ParseString(data *bytes.Buffer) (string, error) {
|
||||
// ReadUintRaw reads an integer of ptrSize bytes, with the specified byte order, from reader.
|
||||
func ReadUintRaw(reader io.Reader, order binary.ByteOrder, ptrSize int) (uint64, error) {
|
||||
switch ptrSize {
|
||||
case 2:
|
||||
var n uint16
|
||||
if err := binary.Read(reader, order, &n); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return uint64(n), nil
|
||||
case 4:
|
||||
var n uint32
|
||||
if err := binary.Read(reader, order, &n); err != nil {
|
||||
@ -153,7 +159,7 @@ func ReadUintRaw(reader io.Reader, order binary.ByteOrder, ptrSize int) (uint64,
|
||||
}
|
||||
return n, nil
|
||||
}
|
||||
return 0, fmt.Errorf("not supprted ptr size %d", ptrSize)
|
||||
return 0, fmt.Errorf("pointer size %d not supported", ptrSize)
|
||||
}
|
||||
|
||||
// WriteUint writes an integer of ptrSize bytes to writer, in the specified byte order.
|
||||
@ -164,7 +170,7 @@ func WriteUint(writer io.Writer, order binary.ByteOrder, ptrSize int, data uint6
|
||||
case 8:
|
||||
return binary.Write(writer, order, data)
|
||||
}
|
||||
return fmt.Errorf("not support prt size %d", ptrSize)
|
||||
return fmt.Errorf("pointer size %d not supported", ptrSize)
|
||||
}
|
||||
|
||||
// ReadDwarfLength reads a DWARF length field followed by a version field
|
||||
|
||||
@ -936,12 +936,16 @@ func (bi *BinaryInfo) LocationCovers(entry *dwarf.Entry, attr dwarf.Attr) ([][2]
|
||||
// This will either be an int64 address or a slice of Pieces for locations
|
||||
// that don't correspond to a single memory address (registers, composite
|
||||
// locations).
|
||||
func (bi *BinaryInfo) Location(entry godwarf.Entry, attr dwarf.Attr, pc uint64, regs op.DwarfRegisters) (int64, []op.Piece, *locationExpr, error) {
|
||||
func (bi *BinaryInfo) Location(entry godwarf.Entry, attr dwarf.Attr, pc uint64, regs op.DwarfRegisters, mem MemoryReadWriter) (int64, []op.Piece, *locationExpr, error) {
|
||||
instr, descr, err := bi.locationExpr(entry, attr, pc)
|
||||
if err != nil {
|
||||
return 0, nil, nil, err
|
||||
}
|
||||
addr, pieces, err := op.ExecuteStackProgram(regs, instr, bi.Arch.PtrSize())
|
||||
readMemory := op.ReadMemoryFunc(nil)
|
||||
if mem != nil {
|
||||
readMemory = mem.ReadMemory
|
||||
}
|
||||
addr, pieces, err := op.ExecuteStackProgram(regs, instr, bi.Arch.PtrSize(), readMemory)
|
||||
return addr, pieces, descr, err
|
||||
}
|
||||
|
||||
|
||||
@ -661,7 +661,7 @@ func funcCallArgOldABI(fn *Function, bi *BinaryInfo, entry reader.Variable, argn
|
||||
err = fmt.Errorf("could not get argument location of %s: %v", argname, err)
|
||||
} else {
|
||||
var pieces []op.Piece
|
||||
off, pieces, err = op.ExecuteStackProgram(op.DwarfRegisters{CFA: CFA, FrameBase: CFA}, locprog, bi.Arch.PtrSize())
|
||||
off, pieces, err = op.ExecuteStackProgram(op.DwarfRegisters{CFA: CFA, FrameBase: CFA}, locprog, bi.Arch.PtrSize(), nil)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("unsupported location expression for argument %s: %v", argname, err)
|
||||
}
|
||||
@ -962,7 +962,7 @@ func fakeFunctionEntryScope(scope *EvalScope, fn *Function, cfa int64, sp uint64
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
scope.Regs.FrameBase, _, _, _ = scope.BinInfo.Location(e, dwarf.AttrFrameBase, scope.PC, scope.Regs)
|
||||
scope.Regs.FrameBase, _, _, _ = scope.BinInfo.Location(e, dwarf.AttrFrameBase, scope.PC, scope.Regs, nil)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@ -115,7 +115,7 @@ func newCompositeMemory(mem MemoryReadWriter, arch *Arch, regs op.DwarfRegisters
|
||||
switch piece.Kind {
|
||||
case op.RegPiece:
|
||||
reg := regs.Bytes(piece.Val)
|
||||
if piece.Size == 0 && len(pieces) == 1 {
|
||||
if piece.Size == 0 && i == len(pieces)-1 {
|
||||
piece.Size = len(reg)
|
||||
}
|
||||
if piece.Size > len(reg) {
|
||||
@ -130,12 +130,18 @@ func newCompositeMemory(mem MemoryReadWriter, arch *Arch, regs op.DwarfRegisters
|
||||
mem.ReadMemory(buf, uint64(piece.Val))
|
||||
cmem.data = append(cmem.data, buf...)
|
||||
case op.ImmPiece:
|
||||
sz := 8
|
||||
if piece.Size > sz {
|
||||
sz = piece.Size
|
||||
buf := piece.Bytes
|
||||
if buf == nil {
|
||||
sz := 8
|
||||
if piece.Size > sz {
|
||||
sz = piece.Size
|
||||
}
|
||||
if piece.Size == 0 && i == len(pieces)-1 {
|
||||
piece.Size = arch.PtrSize() // DWARF doesn't say what this should be
|
||||
}
|
||||
buf = make([]byte, sz)
|
||||
binary.LittleEndian.PutUint64(buf, piece.Val)
|
||||
}
|
||||
buf := make([]byte, sz)
|
||||
binary.LittleEndian.PutUint64(buf, piece.Val)
|
||||
cmem.data = append(cmem.data, buf[:piece.Size]...)
|
||||
default:
|
||||
panic("unsupported piece kind")
|
||||
|
||||
@ -259,7 +259,7 @@ func (it *stackIterator) frameBase(fn *Function) int64 {
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
fb, _, _, _ := it.bi.Location(dwarfTree.Entry, dwarf.AttrFrameBase, it.pc, it.regs)
|
||||
fb, _, _, _ := it.bi.Location(dwarfTree.Entry, dwarf.AttrFrameBase, it.pc, it.regs, it.mem)
|
||||
return fb
|
||||
}
|
||||
|
||||
@ -459,13 +459,13 @@ func (it *stackIterator) executeFrameRegRule(regnum uint64, rule frame.DWRule, c
|
||||
case frame.RuleRegister:
|
||||
return it.regs.Reg(rule.Reg), nil
|
||||
case frame.RuleExpression:
|
||||
v, _, err := op.ExecuteStackProgram(it.regs, rule.Expression, it.bi.Arch.PtrSize())
|
||||
v, _, err := op.ExecuteStackProgram(it.regs, rule.Expression, it.bi.Arch.PtrSize(), it.mem.ReadMemory)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return it.readRegisterAt(regnum, uint64(v))
|
||||
case frame.RuleValExpression:
|
||||
v, _, err := op.ExecuteStackProgram(it.regs, rule.Expression, it.bi.Arch.PtrSize())
|
||||
v, _, err := op.ExecuteStackProgram(it.regs, rule.Expression, it.bi.Arch.PtrSize(), it.mem.ReadMemory)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -671,7 +671,7 @@ func (d *Defer) EvalScope(t *Target, thread Thread) (*EvalScope, error) {
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not read DWARF function entry: %v", err)
|
||||
}
|
||||
scope.Regs.FrameBase, _, _, _ = bi.Location(e, dwarf.AttrFrameBase, scope.PC, scope.Regs)
|
||||
scope.Regs.FrameBase, _, _, _ = bi.Location(e, dwarf.AttrFrameBase, scope.PC, scope.Regs, scope.Mem)
|
||||
scope.Mem = cacheMemory(scope.Mem, uint64(scope.Regs.CFA), int(d.argSz))
|
||||
|
||||
return scope, nil
|
||||
|
||||
@ -1140,7 +1140,7 @@ func extractVarInfoFromEntry(tgt *Target, bi *BinaryInfo, image *Image, regs op.
|
||||
return nil, err
|
||||
}
|
||||
|
||||
addr, pieces, descr, err := bi.Location(entry, dwarf.AttrLocation, regs.PC(), regs)
|
||||
addr, pieces, descr, err := bi.Location(entry, dwarf.AttrLocation, regs.PC(), regs, mem)
|
||||
if pieces != nil {
|
||||
var cmem *compositeMemory
|
||||
if tgt != nil {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user