2015-06-12 19:49:23 +00:00
|
|
|
package proc
|
2015-04-28 14:01:28 +00:00
|
|
|
|
2016-11-15 16:16:33 +00:00
|
|
|
import (
|
|
|
|
|
"errors"
|
|
|
|
|
"fmt"
|
|
|
|
|
"math"
|
|
|
|
|
"strings"
|
2020-02-12 21:31:48 +00:00
|
|
|
|
|
|
|
|
"github.com/go-delve/delve/pkg/dwarf/op"
|
2016-11-15 16:16:33 +00:00
|
|
|
)
|
2015-04-28 14:01:28 +00:00
|
|
|
|
2016-01-10 08:57:52 +00:00
|
|
|
// Registers is an interface for a generic register type. The
|
2015-04-28 14:01:28 +00:00
|
|
|
// interface encapsulates the generic values / actions
|
2016-05-29 19:44:10 +00:00
|
|
|
// we need independent of arch. The concrete register types
|
2015-04-28 14:01:28 +00:00
|
|
|
// will be different depending on OS/Arch.
|
|
|
|
|
type Registers interface {
|
|
|
|
|
PC() uint64
|
|
|
|
|
SP() uint64
|
2017-02-16 13:16:00 +00:00
|
|
|
BP() uint64
|
2015-07-28 05:33:07 +00:00
|
|
|
TLS() uint64
|
2017-02-10 14:11:40 +00:00
|
|
|
// GAddr returns the address of the G variable if it is known, 0 and false otherwise
|
|
|
|
|
GAddr() (uint64, bool)
|
2020-05-13 18:56:50 +00:00
|
|
|
Slice(floatingPoint bool) ([]Register, error)
|
2018-08-29 18:30:37 +00:00
|
|
|
// Copy returns a copy of the registers that is guaranteed not to change
|
2018-08-03 15:17:01 +00:00
|
|
|
// when the registers of the associated thread change.
|
2020-05-13 18:56:50 +00:00
|
|
|
Copy() (Registers, error)
|
2016-11-15 16:16:33 +00:00
|
|
|
}
|
|
|
|
|
|
2018-08-31 18:08:18 +00:00
|
|
|
// Register represents a CPU register.
|
2016-11-15 16:16:33 +00:00
|
|
|
type Register struct {
|
2020-02-12 21:31:48 +00:00
|
|
|
Name string
|
|
|
|
|
Reg *op.DwarfRegister
|
2016-11-15 16:16:33 +00:00
|
|
|
}
|
|
|
|
|
|
2020-03-28 17:39:32 +00:00
|
|
|
// AppendUint64Register will create a new Register struct with the name and value
|
|
|
|
|
// specified and append it to the `regs` slice.
|
2020-02-12 21:31:48 +00:00
|
|
|
func AppendUint64Register(regs []Register, name string, value uint64) []Register {
|
|
|
|
|
return append(regs, Register{name, op.DwarfRegisterFromUint64(value)})
|
2015-04-28 14:01:28 +00:00
|
|
|
}
|
|
|
|
|
|
2020-03-28 17:39:32 +00:00
|
|
|
// AppendBytesRegister will create a new Register struct with the name and value
|
|
|
|
|
// specified and append it to the `regs` slice.
|
2020-02-12 21:31:48 +00:00
|
|
|
func AppendBytesRegister(regs []Register, name string, value []byte) []Register {
|
|
|
|
|
return append(regs, Register{name, op.DwarfRegisterFromBytes(value)})
|
2019-10-25 13:22:33 +00:00
|
|
|
}
|
|
|
|
|
|
2018-08-31 18:08:18 +00:00
|
|
|
// ErrUnknownRegister is returned when the value of an unknown
|
|
|
|
|
// register is requested.
|
|
|
|
|
var ErrUnknownRegister = errors.New("unknown register")
|
2016-02-06 06:00:48 +00:00
|
|
|
|
2016-11-15 16:16:33 +00:00
|
|
|
type flagRegisterDescr []flagDescr
|
|
|
|
|
type flagDescr struct {
|
|
|
|
|
name string
|
|
|
|
|
mask uint64
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var mxcsrDescription flagRegisterDescr = []flagDescr{
|
|
|
|
|
{"FZ", 1 << 15},
|
|
|
|
|
{"RZ/RN", 1<<14 | 1<<13},
|
|
|
|
|
{"PM", 1 << 12},
|
|
|
|
|
{"UM", 1 << 11},
|
|
|
|
|
{"OM", 1 << 10},
|
|
|
|
|
{"ZM", 1 << 9},
|
|
|
|
|
{"DM", 1 << 8},
|
|
|
|
|
{"IM", 1 << 7},
|
|
|
|
|
{"DAZ", 1 << 6},
|
|
|
|
|
{"PE", 1 << 5},
|
|
|
|
|
{"UE", 1 << 4},
|
|
|
|
|
{"OE", 1 << 3},
|
|
|
|
|
{"ZE", 1 << 2},
|
|
|
|
|
{"DE", 1 << 1},
|
|
|
|
|
{"IE", 1 << 0},
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var eflagsDescription flagRegisterDescr = []flagDescr{
|
|
|
|
|
{"CF", 1 << 0},
|
|
|
|
|
{"", 1 << 1},
|
|
|
|
|
{"PF", 1 << 2},
|
|
|
|
|
{"AF", 1 << 4},
|
|
|
|
|
{"ZF", 1 << 6},
|
|
|
|
|
{"SF", 1 << 7},
|
|
|
|
|
{"TF", 1 << 8},
|
|
|
|
|
{"IF", 1 << 9},
|
|
|
|
|
{"DF", 1 << 10},
|
|
|
|
|
{"OF", 1 << 11},
|
|
|
|
|
{"IOPL", 1<<12 | 1<<13},
|
|
|
|
|
{"NT", 1 << 14},
|
|
|
|
|
{"RF", 1 << 16},
|
|
|
|
|
{"VM", 1 << 17},
|
|
|
|
|
{"AC", 1 << 18},
|
|
|
|
|
{"VIF", 1 << 19},
|
|
|
|
|
{"VIP", 1 << 20},
|
|
|
|
|
{"ID", 1 << 21},
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (descr flagRegisterDescr) Mask() uint64 {
|
|
|
|
|
var r uint64
|
|
|
|
|
for _, f := range descr {
|
|
|
|
|
r = r | f.mask
|
|
|
|
|
}
|
|
|
|
|
return r
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (descr flagRegisterDescr) Describe(reg uint64, bitsize int) string {
|
|
|
|
|
var r []string
|
|
|
|
|
for _, f := range descr {
|
|
|
|
|
if f.name == "" {
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
// rbm is f.mask with only the right-most bit set:
|
|
|
|
|
// 0001 1100 -> 0000 0100
|
|
|
|
|
rbm := f.mask & -f.mask
|
|
|
|
|
if rbm == f.mask {
|
|
|
|
|
if reg&f.mask != 0 {
|
|
|
|
|
r = append(r, f.name)
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
x := (reg & f.mask) >> uint64(math.Log2(float64(rbm)))
|
|
|
|
|
r = append(r, fmt.Sprintf("%s=%x", f.name, x))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if reg & ^descr.Mask() != 0 {
|
|
|
|
|
r = append(r, fmt.Sprintf("unknown_flags=%x", reg&^descr.Mask()))
|
|
|
|
|
}
|
|
|
|
|
return fmt.Sprintf("%#0*x\t[%s]", bitsize/4, reg, strings.Join(r, " "))
|
|
|
|
|
}
|