github.com/undoio/delve@v1.9.0/pkg/proc/winutil/regs.go (about)

     1  package winutil
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/binary"
     6  	"fmt"
     7  	"unsafe"
     8  
     9  	"github.com/undoio/delve/pkg/proc"
    10  )
    11  
    12  // AMD64Registers represents CPU registers on an AMD64 processor.
    13  type AMD64Registers struct {
    14  	rax     uint64
    15  	rbx     uint64
    16  	rcx     uint64
    17  	rdx     uint64
    18  	rdi     uint64
    19  	rsi     uint64
    20  	rbp     uint64
    21  	rsp     uint64
    22  	r8      uint64
    23  	r9      uint64
    24  	r10     uint64
    25  	r11     uint64
    26  	r12     uint64
    27  	r13     uint64
    28  	r14     uint64
    29  	r15     uint64
    30  	rip     uint64
    31  	eflags  uint64
    32  	cs      uint64
    33  	fs      uint64
    34  	gs      uint64
    35  	tls     uint64
    36  	Context *CONTEXT
    37  	fltSave *XMM_SAVE_AREA32
    38  }
    39  
    40  // NewAMD64Registers creates a new AMD64Registers struct from a CONTEXT
    41  // struct and the TEB base address of the thread.
    42  func NewAMD64Registers(context *CONTEXT, TebBaseAddress uint64) *AMD64Registers {
    43  	regs := &AMD64Registers{
    44  		rax:    uint64(context.Rax),
    45  		rbx:    uint64(context.Rbx),
    46  		rcx:    uint64(context.Rcx),
    47  		rdx:    uint64(context.Rdx),
    48  		rdi:    uint64(context.Rdi),
    49  		rsi:    uint64(context.Rsi),
    50  		rbp:    uint64(context.Rbp),
    51  		rsp:    uint64(context.Rsp),
    52  		r8:     uint64(context.R8),
    53  		r9:     uint64(context.R9),
    54  		r10:    uint64(context.R10),
    55  		r11:    uint64(context.R11),
    56  		r12:    uint64(context.R12),
    57  		r13:    uint64(context.R13),
    58  		r14:    uint64(context.R14),
    59  		r15:    uint64(context.R15),
    60  		rip:    uint64(context.Rip),
    61  		eflags: uint64(context.EFlags),
    62  		cs:     uint64(context.SegCs),
    63  		fs:     uint64(context.SegFs),
    64  		gs:     uint64(context.SegGs),
    65  		tls:    TebBaseAddress,
    66  	}
    67  
    68  	regs.fltSave = &context.FltSave
    69  	regs.Context = context
    70  
    71  	return regs
    72  }
    73  
    74  // Slice returns the registers as a list of (name, value) pairs.
    75  func (r *AMD64Registers) Slice(floatingPoint bool) ([]proc.Register, error) {
    76  	var regs = []struct {
    77  		k string
    78  		v uint64
    79  	}{
    80  		{"Rip", r.rip},
    81  		{"Rsp", r.rsp},
    82  		{"Rax", r.rax},
    83  		{"Rbx", r.rbx},
    84  		{"Rcx", r.rcx},
    85  		{"Rdx", r.rdx},
    86  		{"Rdi", r.rdi},
    87  		{"Rsi", r.rsi},
    88  		{"Rbp", r.rbp},
    89  		{"R8", r.r8},
    90  		{"R9", r.r9},
    91  		{"R10", r.r10},
    92  		{"R11", r.r11},
    93  		{"R12", r.r12},
    94  		{"R13", r.r13},
    95  		{"R14", r.r14},
    96  		{"R15", r.r15},
    97  		{"Rflags", r.eflags},
    98  		{"Cs", r.cs},
    99  		{"Fs", r.fs},
   100  		{"Gs", r.gs},
   101  		{"TLS", r.tls},
   102  	}
   103  	outlen := len(regs)
   104  	if r.fltSave != nil && floatingPoint {
   105  		outlen += 6 + 8 + 2 + 16
   106  	}
   107  	out := make([]proc.Register, 0, outlen)
   108  	for _, reg := range regs {
   109  		out = proc.AppendUint64Register(out, reg.k, reg.v)
   110  	}
   111  	if r.fltSave != nil && floatingPoint {
   112  		out = proc.AppendUint64Register(out, "CW", uint64(r.fltSave.ControlWord))
   113  		out = proc.AppendUint64Register(out, "SW", uint64(r.fltSave.StatusWord))
   114  		out = proc.AppendUint64Register(out, "TW", uint64(uint16(r.fltSave.TagWord)))
   115  		out = proc.AppendUint64Register(out, "FOP", uint64(r.fltSave.ErrorOpcode))
   116  		out = proc.AppendUint64Register(out, "FIP", uint64(r.fltSave.ErrorSelector)<<32|uint64(r.fltSave.ErrorOffset))
   117  		out = proc.AppendUint64Register(out, "FDP", uint64(r.fltSave.DataSelector)<<32|uint64(r.fltSave.DataOffset))
   118  
   119  		for i := range r.fltSave.FloatRegisters {
   120  			var buf bytes.Buffer
   121  			binary.Write(&buf, binary.LittleEndian, r.fltSave.FloatRegisters[i].Low)
   122  			binary.Write(&buf, binary.LittleEndian, r.fltSave.FloatRegisters[i].High)
   123  			out = proc.AppendBytesRegister(out, fmt.Sprintf("ST(%d)", i), buf.Bytes())
   124  		}
   125  
   126  		out = proc.AppendUint64Register(out, "MXCSR", uint64(r.fltSave.MxCsr))
   127  		out = proc.AppendUint64Register(out, "MXCSR_MASK", uint64(r.fltSave.MxCsr_Mask))
   128  
   129  		for i := 0; i < len(r.fltSave.XmmRegisters); i += 16 {
   130  			out = proc.AppendBytesRegister(out, fmt.Sprintf("XMM%d", i/16), r.fltSave.XmmRegisters[i:i+16])
   131  		}
   132  	}
   133  	return out, nil
   134  }
   135  
   136  // PC returns the current program counter
   137  // i.e. the RIP CPU register.
   138  func (r *AMD64Registers) PC() uint64 {
   139  	return r.rip
   140  }
   141  
   142  // SP returns the stack pointer location,
   143  // i.e. the RSP register.
   144  func (r *AMD64Registers) SP() uint64 {
   145  	return r.rsp
   146  }
   147  
   148  func (r *AMD64Registers) BP() uint64 {
   149  	return r.rbp
   150  }
   151  
   152  // LR returns the link register.
   153  func (r *AMD64Registers) LR() uint64 {
   154  	return 0
   155  }
   156  
   157  // TLS returns the value of the register
   158  // that contains the location of the thread
   159  // local storage segment.
   160  func (r *AMD64Registers) TLS() uint64 {
   161  	return r.tls
   162  }
   163  
   164  // GAddr returns the address of the G variable if it is known, 0 and false
   165  // otherwise.
   166  func (r *AMD64Registers) GAddr() (uint64, bool) {
   167  	return 0, false
   168  }
   169  
   170  // Copy returns a copy of these registers that is guaranteed not to change.
   171  func (r *AMD64Registers) Copy() (proc.Registers, error) {
   172  	var rr AMD64Registers
   173  	rr = *r
   174  	rr.Context = NewCONTEXT()
   175  	*(rr.Context) = *(r.Context)
   176  	rr.fltSave = &rr.Context.FltSave
   177  	return &rr, nil
   178  }
   179  
   180  // M128A tracks the _M128A windows struct.
   181  type M128A struct {
   182  	Low  uint64
   183  	High int64
   184  }
   185  
   186  // XMM_SAVE_AREA32 tracks the _XMM_SAVE_AREA32 windows struct.
   187  type XMM_SAVE_AREA32 struct {
   188  	ControlWord    uint16
   189  	StatusWord     uint16
   190  	TagWord        byte
   191  	Reserved1      byte
   192  	ErrorOpcode    uint16
   193  	ErrorOffset    uint32
   194  	ErrorSelector  uint16
   195  	Reserved2      uint16
   196  	DataOffset     uint32
   197  	DataSelector   uint16
   198  	Reserved3      uint16
   199  	MxCsr          uint32
   200  	MxCsr_Mask     uint32
   201  	FloatRegisters [8]M128A
   202  	XmmRegisters   [256]byte
   203  	Reserved4      [96]byte
   204  }
   205  
   206  // CONTEXT tracks the _CONTEXT of windows.
   207  type CONTEXT struct {
   208  	P1Home uint64
   209  	P2Home uint64
   210  	P3Home uint64
   211  	P4Home uint64
   212  	P5Home uint64
   213  	P6Home uint64
   214  
   215  	ContextFlags uint32
   216  	MxCsr        uint32
   217  
   218  	SegCs  uint16
   219  	SegDs  uint16
   220  	SegEs  uint16
   221  	SegFs  uint16
   222  	SegGs  uint16
   223  	SegSs  uint16
   224  	EFlags uint32
   225  
   226  	Dr0 uint64
   227  	Dr1 uint64
   228  	Dr2 uint64
   229  	Dr3 uint64
   230  	Dr6 uint64
   231  	Dr7 uint64
   232  
   233  	Rax uint64
   234  	Rcx uint64
   235  	Rdx uint64
   236  	Rbx uint64
   237  	Rsp uint64
   238  	Rbp uint64
   239  	Rsi uint64
   240  	Rdi uint64
   241  	R8  uint64
   242  	R9  uint64
   243  	R10 uint64
   244  	R11 uint64
   245  	R12 uint64
   246  	R13 uint64
   247  	R14 uint64
   248  	R15 uint64
   249  
   250  	Rip uint64
   251  
   252  	FltSave XMM_SAVE_AREA32
   253  
   254  	VectorRegister [26]M128A
   255  	VectorControl  uint64
   256  
   257  	DebugControl         uint64
   258  	LastBranchToRip      uint64
   259  	LastBranchFromRip    uint64
   260  	LastExceptionToRip   uint64
   261  	LastExceptionFromRip uint64
   262  }
   263  
   264  // NewCONTEXT allocates Windows CONTEXT structure aligned to 16 bytes.
   265  func NewCONTEXT() *CONTEXT {
   266  	var c *CONTEXT
   267  	buf := make([]byte, unsafe.Sizeof(*c)+15)
   268  	return (*CONTEXT)(unsafe.Pointer((uintptr(unsafe.Pointer(&buf[15]))) &^ 15))
   269  }