Changes implementations of proc.Registers interface and the op.DwarfRegisters struct so that floating point registers can be loaded only when they are needed. Removes the floatingPoint parameter from proc.Thread.Registers. This accomplishes three things: 1. it simplifies the proc.Thread.Registers interface 2. it makes it impossible to accidentally create a broken set of saved registers or of op.DwarfRegisters by accidentally calling Registers(false) 3. it improves general performance of Delve by avoiding to load floating point registers as much as possible Floating point registers are loaded under two circumstances: 1. When the Slice method is called with floatingPoint == true 2. When the Copy method is called Benchmark before: BenchmarkConditionalBreakpoints-4 1 4327350142 ns/op Benchmark after: BenchmarkConditionalBreakpoints-4 1 3852642917 ns/op Updates #1549
128 lines
3.1 KiB
Go
128 lines
3.1 KiB
Go
package proc
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"math"
|
|
"strings"
|
|
|
|
"github.com/go-delve/delve/pkg/dwarf/op"
|
|
)
|
|
|
|
// Registers is an interface for a generic register type. The
|
|
// interface encapsulates the generic values / actions
|
|
// we need independent of arch. The concrete register types
|
|
// will be different depending on OS/Arch.
|
|
type Registers interface {
|
|
PC() uint64
|
|
SP() uint64
|
|
BP() uint64
|
|
TLS() uint64
|
|
// GAddr returns the address of the G variable if it is known, 0 and false otherwise
|
|
GAddr() (uint64, bool)
|
|
Get(int) (uint64, error)
|
|
Slice(floatingPoint bool) ([]Register, error)
|
|
// Copy returns a copy of the registers that is guaranteed not to change
|
|
// when the registers of the associated thread change.
|
|
Copy() (Registers, error)
|
|
}
|
|
|
|
// Register represents a CPU register.
|
|
type Register struct {
|
|
Name string
|
|
Reg *op.DwarfRegister
|
|
}
|
|
|
|
// AppendUint64Register will create a new Register struct with the name and value
|
|
// specified and append it to the `regs` slice.
|
|
func AppendUint64Register(regs []Register, name string, value uint64) []Register {
|
|
return append(regs, Register{name, op.DwarfRegisterFromUint64(value)})
|
|
}
|
|
|
|
// AppendBytesRegister will create a new Register struct with the name and value
|
|
// specified and append it to the `regs` slice.
|
|
func AppendBytesRegister(regs []Register, name string, value []byte) []Register {
|
|
return append(regs, Register{name, op.DwarfRegisterFromBytes(value)})
|
|
}
|
|
|
|
// ErrUnknownRegister is returned when the value of an unknown
|
|
// register is requested.
|
|
var ErrUnknownRegister = errors.New("unknown register")
|
|
|
|
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, " "))
|
|
}
|