mirror of
https://github.com/beego/bee.git
synced 2024-11-01 05:00:55 +00:00
231 lines
5.8 KiB
Go
231 lines
5.8 KiB
Go
|
package proc
|
||
|
|
||
|
import (
|
||
|
"bytes"
|
||
|
"encoding/binary"
|
||
|
"errors"
|
||
|
"fmt"
|
||
|
"math"
|
||
|
"os"
|
||
|
"strings"
|
||
|
)
|
||
|
|
||
|
// 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
|
||
|
CX() uint64
|
||
|
TLS() uint64
|
||
|
Get(int) (uint64, error)
|
||
|
SetPC(*Thread, uint64) error
|
||
|
Slice() []Register
|
||
|
}
|
||
|
|
||
|
type Register struct {
|
||
|
Name string
|
||
|
Value string
|
||
|
}
|
||
|
|
||
|
func appendWordReg(regs []Register, name string, value uint16) []Register {
|
||
|
return append(regs, Register{name, fmt.Sprintf("%#04x", value)})
|
||
|
}
|
||
|
|
||
|
func appendDwordReg(regs []Register, name string, value uint32) []Register {
|
||
|
return append(regs, Register{name, fmt.Sprintf("%#08x", value)})
|
||
|
}
|
||
|
|
||
|
func appendQwordReg(regs []Register, name string, value uint64) []Register {
|
||
|
return append(regs, Register{name, fmt.Sprintf("%#016x", value)})
|
||
|
}
|
||
|
|
||
|
func appendFlagReg(regs []Register, name string, value uint64, descr flagRegisterDescr, size int) []Register {
|
||
|
return append(regs, Register{name, descr.Describe(value, size)})
|
||
|
}
|
||
|
|
||
|
func appendX87Reg(regs []Register, index int, exponent uint16, mantissa uint64) []Register {
|
||
|
var f float64
|
||
|
fset := false
|
||
|
|
||
|
const (
|
||
|
_SIGNBIT = 1 << 15
|
||
|
_EXP_BIAS = (1 << 14) - 1 // 2^(n-1) - 1 = 16383
|
||
|
_SPECIALEXP = (1 << 15) - 1 // all bits set
|
||
|
_HIGHBIT = 1 << 63
|
||
|
_QUIETBIT = 1 << 62
|
||
|
)
|
||
|
|
||
|
sign := 1.0
|
||
|
if exponent&_SIGNBIT != 0 {
|
||
|
sign = -1.0
|
||
|
}
|
||
|
exponent &= ^uint16(_SIGNBIT)
|
||
|
|
||
|
NaN := math.NaN()
|
||
|
Inf := math.Inf(+1)
|
||
|
|
||
|
switch exponent {
|
||
|
case 0:
|
||
|
switch {
|
||
|
case mantissa == 0:
|
||
|
f = sign * 0.0
|
||
|
fset = true
|
||
|
case mantissa&_HIGHBIT != 0:
|
||
|
f = NaN
|
||
|
fset = true
|
||
|
}
|
||
|
case _SPECIALEXP:
|
||
|
switch {
|
||
|
case mantissa&_HIGHBIT == 0:
|
||
|
f = sign * Inf
|
||
|
fset = true
|
||
|
default:
|
||
|
f = NaN // signaling NaN
|
||
|
fset = true
|
||
|
}
|
||
|
default:
|
||
|
if mantissa&_HIGHBIT == 0 {
|
||
|
f = NaN
|
||
|
fset = true
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if !fset {
|
||
|
significand := float64(mantissa) / (1 << 63)
|
||
|
f = sign * math.Ldexp(significand, int(exponent-_EXP_BIAS))
|
||
|
}
|
||
|
|
||
|
return append(regs, Register{fmt.Sprintf("ST(%d)", index), fmt.Sprintf("%#04x%016x\t%g", exponent, mantissa, f)})
|
||
|
}
|
||
|
|
||
|
func appendSSEReg(regs []Register, name string, xmm []byte) []Register {
|
||
|
buf := bytes.NewReader(xmm)
|
||
|
|
||
|
var out bytes.Buffer
|
||
|
var vi [16]uint8
|
||
|
for i := range vi {
|
||
|
binary.Read(buf, binary.LittleEndian, &vi[i])
|
||
|
}
|
||
|
|
||
|
fmt.Fprintf(&out, "0x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", vi[15], vi[14], vi[13], vi[12], vi[11], vi[10], vi[9], vi[8], vi[7], vi[6], vi[5], vi[4], vi[3], vi[2], vi[1], vi[0])
|
||
|
|
||
|
fmt.Fprintf(&out, "\tv2_int={ %02x%02x%02x%02x%02x%02x%02x%02x %02x%02x%02x%02x%02x%02x%02x%02x }", vi[7], vi[6], vi[5], vi[4], vi[3], vi[2], vi[1], vi[0], vi[15], vi[14], vi[13], vi[12], vi[11], vi[10], vi[9], vi[8])
|
||
|
|
||
|
fmt.Fprintf(&out, "\tv4_int={ %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x }", vi[3], vi[2], vi[1], vi[0], vi[7], vi[6], vi[5], vi[4], vi[11], vi[10], vi[9], vi[8], vi[15], vi[14], vi[13], vi[12])
|
||
|
|
||
|
fmt.Fprintf(&out, "\tv8_int={ %02x%02x %02x%02x %02x%02x %02x%02x %02x%02x %02x%02x %02x%02x %02x%02x }", vi[1], vi[0], vi[3], vi[2], vi[5], vi[4], vi[7], vi[6], vi[9], vi[8], vi[11], vi[10], vi[13], vi[12], vi[15], vi[14])
|
||
|
|
||
|
fmt.Fprintf(&out, "\tv16_int={ %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x }", vi[0], vi[1], vi[2], vi[3], vi[4], vi[5], vi[6], vi[7], vi[8], vi[9], vi[10], vi[11], vi[12], vi[13], vi[14], vi[15])
|
||
|
|
||
|
buf.Seek(0, os.SEEK_SET)
|
||
|
var v2 [2]float64
|
||
|
for i := range v2 {
|
||
|
binary.Read(buf, binary.LittleEndian, &v2[i])
|
||
|
}
|
||
|
fmt.Fprintf(&out, "\tv2_float={ %g %g }", v2[0], v2[1])
|
||
|
|
||
|
buf.Seek(0, os.SEEK_SET)
|
||
|
var v4 [4]float32
|
||
|
for i := range v4 {
|
||
|
binary.Read(buf, binary.LittleEndian, &v4[i])
|
||
|
}
|
||
|
fmt.Fprintf(&out, "\tv4_float={ %g %g %g %g }", v4[0], v4[1], v4[2], v4[3])
|
||
|
|
||
|
return append(regs, Register{name, out.String()})
|
||
|
}
|
||
|
|
||
|
var UnknownRegisterError = errors.New("unknown register")
|
||
|
|
||
|
// Registers obtains register values from the debugged process.
|
||
|
func (t *Thread) Registers(floatingPoint bool) (Registers, error) {
|
||
|
return registers(t, floatingPoint)
|
||
|
}
|
||
|
|
||
|
// PC returns the current PC for this thread.
|
||
|
func (t *Thread) PC() (uint64, error) {
|
||
|
regs, err := t.Registers(false)
|
||
|
if err != nil {
|
||
|
return 0, err
|
||
|
}
|
||
|
return regs.PC(), nil
|
||
|
}
|
||
|
|
||
|
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, " "))
|
||
|
}
|