github.com/cnboonhan/delve@v0.0.0-20230908061759-363f2388c2fb/pkg/proc/winutil/regs_amd64_arch.go (about)

     1  package winutil
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/binary"
     6  	"fmt"
     7  	"unsafe"
     8  
     9  	"github.com/go-delve/delve/pkg/dwarf/op"
    10  	"github.com/go-delve/delve/pkg/dwarf/regnum"
    11  	"github.com/go-delve/delve/pkg/proc"
    12  )
    13  
    14  // AMD64Registers represents CPU registers on an AMD64 processor.
    15  type AMD64Registers struct {
    16  	rax     uint64
    17  	rbx     uint64
    18  	rcx     uint64
    19  	rdx     uint64
    20  	rdi     uint64
    21  	rsi     uint64
    22  	rbp     uint64
    23  	rsp     uint64
    24  	r8      uint64
    25  	r9      uint64
    26  	r10     uint64
    27  	r11     uint64
    28  	r12     uint64
    29  	r13     uint64
    30  	r14     uint64
    31  	r15     uint64
    32  	rip     uint64
    33  	eflags  uint64
    34  	cs      uint64
    35  	fs      uint64
    36  	gs      uint64
    37  	tls     uint64
    38  	Context *AMD64CONTEXT
    39  	fltSave *XMM_SAVE_AREA32
    40  }
    41  
    42  // NewAMD64Registers creates a new AMD64Registers struct from a CONTEXT
    43  // struct and the TEB base address of the thread.
    44  func NewAMD64Registers(context *AMD64CONTEXT, TebBaseAddress uint64) *AMD64Registers {
    45  	regs := &AMD64Registers{
    46  		rax:    uint64(context.Rax),
    47  		rbx:    uint64(context.Rbx),
    48  		rcx:    uint64(context.Rcx),
    49  		rdx:    uint64(context.Rdx),
    50  		rdi:    uint64(context.Rdi),
    51  		rsi:    uint64(context.Rsi),
    52  		rbp:    uint64(context.Rbp),
    53  		rsp:    uint64(context.Rsp),
    54  		r8:     uint64(context.R8),
    55  		r9:     uint64(context.R9),
    56  		r10:    uint64(context.R10),
    57  		r11:    uint64(context.R11),
    58  		r12:    uint64(context.R12),
    59  		r13:    uint64(context.R13),
    60  		r14:    uint64(context.R14),
    61  		r15:    uint64(context.R15),
    62  		rip:    uint64(context.Rip),
    63  		eflags: uint64(context.EFlags),
    64  		cs:     uint64(context.SegCs),
    65  		fs:     uint64(context.SegFs),
    66  		gs:     uint64(context.SegGs),
    67  		tls:    TebBaseAddress,
    68  	}
    69  
    70  	regs.fltSave = &context.FltSave
    71  	regs.Context = context
    72  
    73  	return regs
    74  }
    75  
    76  // Slice returns the registers as a list of (name, value) pairs.
    77  func (r *AMD64Registers) Slice(floatingPoint bool) ([]proc.Register, error) {
    78  	var regs = []struct {
    79  		k string
    80  		v uint64
    81  	}{
    82  		{"Rip", r.rip},
    83  		{"Rsp", r.rsp},
    84  		{"Rax", r.rax},
    85  		{"Rbx", r.rbx},
    86  		{"Rcx", r.rcx},
    87  		{"Rdx", r.rdx},
    88  		{"Rdi", r.rdi},
    89  		{"Rsi", r.rsi},
    90  		{"Rbp", r.rbp},
    91  		{"R8", r.r8},
    92  		{"R9", r.r9},
    93  		{"R10", r.r10},
    94  		{"R11", r.r11},
    95  		{"R12", r.r12},
    96  		{"R13", r.r13},
    97  		{"R14", r.r14},
    98  		{"R15", r.r15},
    99  		{"Rflags", r.eflags},
   100  		{"Cs", r.cs},
   101  		{"Fs", r.fs},
   102  		{"Gs", r.gs},
   103  		{"TLS", r.tls},
   104  	}
   105  	outlen := len(regs)
   106  	if r.fltSave != nil && floatingPoint {
   107  		outlen += 6 + 8 + 2 + 16
   108  	}
   109  	out := make([]proc.Register, 0, outlen)
   110  	for _, reg := range regs {
   111  		out = proc.AppendUint64Register(out, reg.k, reg.v)
   112  	}
   113  	if r.fltSave != nil && floatingPoint {
   114  		out = proc.AppendUint64Register(out, "CW", uint64(r.fltSave.ControlWord))
   115  		out = proc.AppendUint64Register(out, "SW", uint64(r.fltSave.StatusWord))
   116  		out = proc.AppendUint64Register(out, "TW", uint64(uint16(r.fltSave.TagWord)))
   117  		out = proc.AppendUint64Register(out, "FOP", uint64(r.fltSave.ErrorOpcode))
   118  		out = proc.AppendUint64Register(out, "FIP", uint64(r.fltSave.ErrorSelector)<<32|uint64(r.fltSave.ErrorOffset))
   119  		out = proc.AppendUint64Register(out, "FDP", uint64(r.fltSave.DataSelector)<<32|uint64(r.fltSave.DataOffset))
   120  
   121  		for i := range r.fltSave.FloatRegisters {
   122  			var buf bytes.Buffer
   123  			binary.Write(&buf, binary.LittleEndian, r.fltSave.FloatRegisters[i].Low)
   124  			binary.Write(&buf, binary.LittleEndian, r.fltSave.FloatRegisters[i].High)
   125  			out = proc.AppendBytesRegister(out, fmt.Sprintf("ST(%d)", i), buf.Bytes())
   126  		}
   127  
   128  		out = proc.AppendUint64Register(out, "MXCSR", uint64(r.fltSave.MxCsr))
   129  		out = proc.AppendUint64Register(out, "MXCSR_MASK", uint64(r.fltSave.MxCsr_Mask))
   130  
   131  		for i := 0; i < len(r.fltSave.XmmRegisters); i += 16 {
   132  			out = proc.AppendBytesRegister(out, fmt.Sprintf("XMM%d", i/16), r.fltSave.XmmRegisters[i:i+16])
   133  		}
   134  	}
   135  	return out, nil
   136  }
   137  
   138  // PC returns the current program counter
   139  // i.e. the RIP CPU register.
   140  func (r *AMD64Registers) PC() uint64 {
   141  	return r.rip
   142  }
   143  
   144  // SP returns the stack pointer location,
   145  // i.e. the RSP register.
   146  func (r *AMD64Registers) SP() uint64 {
   147  	return r.rsp
   148  }
   149  
   150  func (r *AMD64Registers) BP() uint64 {
   151  	return r.rbp
   152  }
   153  
   154  // LR returns the link register.
   155  func (r *AMD64Registers) LR() uint64 {
   156  	return 0
   157  }
   158  
   159  // TLS returns the value of the register
   160  // that contains the location of the thread
   161  // local storage segment.
   162  func (r *AMD64Registers) TLS() uint64 {
   163  	return r.tls
   164  }
   165  
   166  // GAddr returns the address of the G variable if it is known, 0 and false
   167  // otherwise.
   168  func (r *AMD64Registers) GAddr() (uint64, bool) {
   169  	return 0, false
   170  }
   171  
   172  // Copy returns a copy of these registers that is guaranteed not to change.
   173  func (r *AMD64Registers) Copy() (proc.Registers, error) {
   174  	var rr AMD64Registers
   175  	rr = *r
   176  	rr.Context = NewAMD64CONTEXT()
   177  	*(rr.Context) = *(r.Context)
   178  	rr.fltSave = &rr.Context.FltSave
   179  	return &rr, nil
   180  }
   181  
   182  // M128A tracks the _M128A windows struct.
   183  type M128A struct {
   184  	Low  uint64
   185  	High int64
   186  }
   187  
   188  // XMM_SAVE_AREA32 tracks the _XMM_SAVE_AREA32 windows struct.
   189  type XMM_SAVE_AREA32 struct {
   190  	ControlWord    uint16
   191  	StatusWord     uint16
   192  	TagWord        byte
   193  	Reserved1      byte
   194  	ErrorOpcode    uint16
   195  	ErrorOffset    uint32
   196  	ErrorSelector  uint16
   197  	Reserved2      uint16
   198  	DataOffset     uint32
   199  	DataSelector   uint16
   200  	Reserved3      uint16
   201  	MxCsr          uint32
   202  	MxCsr_Mask     uint32
   203  	FloatRegisters [8]M128A
   204  	XmmRegisters   [256]byte
   205  	Reserved4      [96]byte
   206  }
   207  
   208  // AMD64CONTEXT tracks the _CONTEXT of windows.
   209  type AMD64CONTEXT struct {
   210  	P1Home uint64
   211  	P2Home uint64
   212  	P3Home uint64
   213  	P4Home uint64
   214  	P5Home uint64
   215  	P6Home uint64
   216  
   217  	ContextFlags uint32
   218  	MxCsr        uint32
   219  
   220  	SegCs  uint16
   221  	SegDs  uint16
   222  	SegEs  uint16
   223  	SegFs  uint16
   224  	SegGs  uint16
   225  	SegSs  uint16
   226  	EFlags uint32
   227  
   228  	Dr0 uint64
   229  	Dr1 uint64
   230  	Dr2 uint64
   231  	Dr3 uint64
   232  	Dr6 uint64
   233  	Dr7 uint64
   234  
   235  	Rax uint64
   236  	Rcx uint64
   237  	Rdx uint64
   238  	Rbx uint64
   239  	Rsp uint64
   240  	Rbp uint64
   241  	Rsi uint64
   242  	Rdi uint64
   243  	R8  uint64
   244  	R9  uint64
   245  	R10 uint64
   246  	R11 uint64
   247  	R12 uint64
   248  	R13 uint64
   249  	R14 uint64
   250  	R15 uint64
   251  
   252  	Rip uint64
   253  
   254  	FltSave XMM_SAVE_AREA32
   255  
   256  	VectorRegister [26]M128A
   257  	VectorControl  uint64
   258  
   259  	DebugControl         uint64
   260  	LastBranchToRip      uint64
   261  	LastBranchFromRip    uint64
   262  	LastExceptionToRip   uint64
   263  	LastExceptionFromRip uint64
   264  }
   265  
   266  // NewAMD64CONTEXT allocates Windows CONTEXT structure aligned to 16 bytes.
   267  func NewAMD64CONTEXT() *AMD64CONTEXT {
   268  	var c *AMD64CONTEXT
   269  	buf := make([]byte, unsafe.Sizeof(*c)+15)
   270  	return (*AMD64CONTEXT)(unsafe.Pointer((uintptr(unsafe.Pointer(&buf[15]))) &^ 15))
   271  }
   272  
   273  func (ctx *AMD64CONTEXT) SetFlags(flags uint32) {
   274  	ctx.ContextFlags = flags
   275  }
   276  
   277  func (ctx *AMD64CONTEXT) SetPC(pc uint64) {
   278  	ctx.Rip = pc
   279  }
   280  
   281  func (ctx *AMD64CONTEXT) SetTrap(trap bool) {
   282  	const v = 0x100
   283  	if trap {
   284  		ctx.EFlags |= v
   285  	} else {
   286  		ctx.EFlags &= ^uint32(v)
   287  	}
   288  }
   289  
   290  func (ctx *AMD64CONTEXT) SetReg(regNum uint64, reg *op.DwarfRegister) error {
   291  	var p *uint64
   292  
   293  	switch regNum {
   294  	case regnum.AMD64_Rax:
   295  		p = &ctx.Rax
   296  	case regnum.AMD64_Rbx:
   297  		p = &ctx.Rbx
   298  	case regnum.AMD64_Rcx:
   299  		p = &ctx.Rcx
   300  	case regnum.AMD64_Rdx:
   301  		p = &ctx.Rdx
   302  	case regnum.AMD64_Rsi:
   303  		p = &ctx.Rsi
   304  	case regnum.AMD64_Rdi:
   305  		p = &ctx.Rdi
   306  	case regnum.AMD64_Rbp:
   307  		p = &ctx.Rbp
   308  	case regnum.AMD64_Rsp:
   309  		p = &ctx.Rsp
   310  	case regnum.AMD64_R8:
   311  		p = &ctx.R8
   312  	case regnum.AMD64_R9:
   313  		p = &ctx.R9
   314  	case regnum.AMD64_R10:
   315  		p = &ctx.R10
   316  	case regnum.AMD64_R11:
   317  		p = &ctx.R11
   318  	case regnum.AMD64_R12:
   319  		p = &ctx.R12
   320  	case regnum.AMD64_R13:
   321  		p = &ctx.R13
   322  	case regnum.AMD64_R14:
   323  		p = &ctx.R14
   324  	case regnum.AMD64_R15:
   325  		p = &ctx.R15
   326  	case regnum.AMD64_Rip:
   327  		p = &ctx.Rip
   328  	}
   329  
   330  	if p != nil {
   331  		if reg.Bytes != nil && len(reg.Bytes) != 8 {
   332  			return fmt.Errorf("wrong number of bytes for register %s (%d)", regnum.AMD64ToName(regNum), len(reg.Bytes))
   333  		}
   334  		*p = reg.Uint64Val
   335  	} else if regNum == regnum.AMD64_Rflags {
   336  		ctx.EFlags = uint32(reg.Uint64Val)
   337  	} else {
   338  		if regNum < regnum.AMD64_XMM0 || regNum > regnum.AMD64_XMM0+15 {
   339  			return fmt.Errorf("can not set register %s", regnum.AMD64ToName(regNum))
   340  		}
   341  		reg.FillBytes()
   342  		if len(reg.Bytes) > 16 {
   343  			return fmt.Errorf("too many bytes when setting register %s", regnum.AMD64ToName(regNum))
   344  		}
   345  		copy(ctx.FltSave.XmmRegisters[(regNum-regnum.AMD64_XMM0)*16:], reg.Bytes)
   346  	}
   347  	return nil
   348  }