
A significant amount of time is spent generating the string representation for the proc.Registers object of each thread, since this field is rarely used (only when the Registers API is called) it should be generated on demand. Also by changing the internal representation of proc.Register to be closer to that of op.DwarfRegister it will help us implement #1838 (when Delve will need to be able to display the registers of an internal frame, which we currently represent using op.DwarfRegister objects). Benchmark before: BenchmarkConditionalBreakpoints-4 1 22292554301 ns/op Benchmark after: BenchmarkConditionalBreakpoints-4 1 17326345671 ns/op Reduces conditional breakpoint latency from 2.2ms to 1.7ms. Updates #1549, #1838
135 lines
3.4 KiB
Go
135 lines
3.4 KiB
Go
package linutil
|
|
|
|
import (
|
|
"fmt"
|
|
"golang.org/x/arch/arm64/arm64asm"
|
|
|
|
"github.com/go-delve/delve/pkg/proc"
|
|
)
|
|
|
|
// Regs is a wrapper for sys.PtraceRegs.
|
|
type ARM64Registers struct {
|
|
Regs *ARM64PtraceRegs //general-purpose registers
|
|
Fpregs []proc.Register //Formatted floating point registers
|
|
Fpregset []byte //holding all floating point register values
|
|
}
|
|
|
|
// ARM64PtraceRegs is the struct used by the linux kernel to return the
|
|
// general purpose registers for ARM64 CPUs.
|
|
// copy from sys/unix/ztypes_linux_arm64.go:735
|
|
type ARM64PtraceRegs struct {
|
|
Regs [31]uint64
|
|
Sp uint64
|
|
Pc uint64
|
|
Pstate uint64
|
|
}
|
|
|
|
// Slice returns the registers as a list of (name, value) pairs.
|
|
func (r *ARM64Registers) Slice(floatingPoint bool) []proc.Register {
|
|
var regs64 = []struct {
|
|
k string
|
|
v uint64
|
|
}{
|
|
{"X0", r.Regs.Regs[0]},
|
|
{"X1", r.Regs.Regs[1]},
|
|
{"X2", r.Regs.Regs[2]},
|
|
{"X3", r.Regs.Regs[3]},
|
|
{"X4", r.Regs.Regs[4]},
|
|
{"X5", r.Regs.Regs[5]},
|
|
{"X6", r.Regs.Regs[6]},
|
|
{"X7", r.Regs.Regs[7]},
|
|
{"X8", r.Regs.Regs[8]},
|
|
{"X9", r.Regs.Regs[9]},
|
|
{"X10", r.Regs.Regs[10]},
|
|
{"X11", r.Regs.Regs[11]},
|
|
{"X12", r.Regs.Regs[12]},
|
|
{"X13", r.Regs.Regs[13]},
|
|
{"X14", r.Regs.Regs[14]},
|
|
{"X15", r.Regs.Regs[15]},
|
|
{"X16", r.Regs.Regs[16]},
|
|
{"X17", r.Regs.Regs[17]},
|
|
{"X18", r.Regs.Regs[18]},
|
|
{"X19", r.Regs.Regs[19]},
|
|
{"X20", r.Regs.Regs[20]},
|
|
{"X21", r.Regs.Regs[21]},
|
|
{"X22", r.Regs.Regs[22]},
|
|
{"X23", r.Regs.Regs[23]},
|
|
{"X24", r.Regs.Regs[24]},
|
|
{"X25", r.Regs.Regs[25]},
|
|
{"X26", r.Regs.Regs[26]},
|
|
{"X27", r.Regs.Regs[27]},
|
|
{"X28", r.Regs.Regs[28]},
|
|
{"X29", r.Regs.Regs[29]},
|
|
{"X30", r.Regs.Regs[30]},
|
|
{"SP", r.Regs.Sp},
|
|
{"PC", r.Regs.Pc},
|
|
{"PSTATE", r.Regs.Pstate},
|
|
}
|
|
out := make([]proc.Register, 0, len(regs64)+len(r.Fpregs))
|
|
for _, reg := range regs64 {
|
|
out = proc.AppendUint64Register(out, reg.k, reg.v)
|
|
}
|
|
out = append(out, r.Fpregs...)
|
|
return out
|
|
}
|
|
|
|
// PC returns the value of RIP register.
|
|
func (r *ARM64Registers) PC() uint64 {
|
|
return r.Regs.Pc
|
|
}
|
|
|
|
// SP returns the value of RSP register.
|
|
func (r *ARM64Registers) SP() uint64 {
|
|
return r.Regs.Sp
|
|
}
|
|
|
|
func (r *ARM64Registers) BP() uint64 {
|
|
return r.Regs.Regs[29]
|
|
}
|
|
|
|
// TLS returns the address of the thread local storage memory segment.
|
|
func (r *ARM64Registers) TLS() uint64 {
|
|
return 0
|
|
}
|
|
|
|
// GAddr returns the address of the G variable if it is known, 0 and false
|
|
// otherwise.
|
|
func (r *ARM64Registers) GAddr() (uint64, bool) {
|
|
return r.Regs.Regs[28], true
|
|
}
|
|
|
|
// Get returns the value of the n-th register (in arm64asm order).
|
|
func (r *ARM64Registers) Get(n int) (uint64, error) {
|
|
reg := arm64asm.Reg(n)
|
|
|
|
if reg >= arm64asm.X0 && reg <= arm64asm.X30 {
|
|
return r.Regs.Regs[reg-arm64asm.X0], nil
|
|
}
|
|
|
|
return 0, proc.ErrUnknownRegister
|
|
}
|
|
|
|
// Copy returns a copy of these registers that is guarenteed not to change.
|
|
func (r *ARM64Registers) Copy() proc.Registers {
|
|
var rr ARM64Registers
|
|
rr.Regs = &ARM64PtraceRegs{}
|
|
*(rr.Regs) = *(r.Regs)
|
|
if r.Fpregs != nil {
|
|
rr.Fpregs = make([]proc.Register, len(r.Fpregs))
|
|
copy(rr.Fpregs, r.Fpregs)
|
|
}
|
|
if r.Fpregset != nil {
|
|
rr.Fpregset = make([]byte, len(r.Fpregset))
|
|
copy(rr.Fpregset, r.Fpregset)
|
|
}
|
|
return &rr
|
|
}
|
|
|
|
// Decode decodes an XSAVE area to a list of name/value pairs of registers.
|
|
func Decode(fpregs []byte) (regs []proc.Register) {
|
|
for i := 0; i < len(fpregs); i += 16 {
|
|
regs = proc.AppendBytesRegister(regs, fmt.Sprintf("V%d", i/16), fpregs[i:i+16])
|
|
}
|
|
return
|
|
}
|