github.com/undoio/delve@v1.9.0/pkg/proc/native/registers_windows_amd64.go (about)

     1  package native
     2  
     3  import (
     4  	"fmt"
     5  	"unsafe"
     6  
     7  	"github.com/undoio/delve/pkg/dwarf/op"
     8  	"github.com/undoio/delve/pkg/dwarf/regnum"
     9  	"github.com/undoio/delve/pkg/proc"
    10  	"github.com/undoio/delve/pkg/proc/winutil"
    11  )
    12  
    13  // SetPC sets the RIP register to the value specified by `pc`.
    14  func (thread *nativeThread) setPC(pc uint64) error {
    15  	context := winutil.NewCONTEXT()
    16  	context.ContextFlags = _CONTEXT_ALL
    17  
    18  	err := _GetThreadContext(thread.os.hThread, context)
    19  	if err != nil {
    20  		return err
    21  	}
    22  
    23  	context.Rip = pc
    24  
    25  	return _SetThreadContext(thread.os.hThread, context)
    26  }
    27  
    28  // SetReg changes the value of the specified register.
    29  func (thread *nativeThread) SetReg(regNum uint64, reg *op.DwarfRegister) error {
    30  	context := winutil.NewCONTEXT()
    31  	context.ContextFlags = _CONTEXT_ALL
    32  
    33  	err := _GetThreadContext(thread.os.hThread, context)
    34  	if err != nil {
    35  		return err
    36  	}
    37  
    38  	var p *uint64
    39  
    40  	switch regNum {
    41  	case regnum.AMD64_Rax:
    42  		p = &context.Rax
    43  	case regnum.AMD64_Rbx:
    44  		p = &context.Rbx
    45  	case regnum.AMD64_Rcx:
    46  		p = &context.Rcx
    47  	case regnum.AMD64_Rdx:
    48  		p = &context.Rdx
    49  	case regnum.AMD64_Rsi:
    50  		p = &context.Rsi
    51  	case regnum.AMD64_Rdi:
    52  		p = &context.Rdi
    53  	case regnum.AMD64_Rbp:
    54  		p = &context.Rbp
    55  	case regnum.AMD64_Rsp:
    56  		p = &context.Rsp
    57  	case regnum.AMD64_R8:
    58  		p = &context.R8
    59  	case regnum.AMD64_R9:
    60  		p = &context.R9
    61  	case regnum.AMD64_R10:
    62  		p = &context.R10
    63  	case regnum.AMD64_R11:
    64  		p = &context.R11
    65  	case regnum.AMD64_R12:
    66  		p = &context.R12
    67  	case regnum.AMD64_R13:
    68  		p = &context.R13
    69  	case regnum.AMD64_R14:
    70  		p = &context.R14
    71  	case regnum.AMD64_R15:
    72  		p = &context.R15
    73  	case regnum.AMD64_Rip:
    74  		p = &context.Rip
    75  	}
    76  
    77  	if p != nil {
    78  		if reg.Bytes != nil && len(reg.Bytes) != 8 {
    79  			return fmt.Errorf("wrong number of bytes for register %s (%d)", regnum.AMD64ToName(regNum), len(reg.Bytes))
    80  		}
    81  		*p = reg.Uint64Val
    82  	} else if regNum == regnum.AMD64_Rflags {
    83  		context.EFlags = uint32(reg.Uint64Val)
    84  	} else {
    85  		if regNum < regnum.AMD64_XMM0 || regNum > regnum.AMD64_XMM0+15 {
    86  			return fmt.Errorf("can not set register %s", regnum.AMD64ToName(regNum))
    87  		}
    88  		reg.FillBytes()
    89  		if len(reg.Bytes) > 16 {
    90  			return fmt.Errorf("too many bytes when setting register %s", regnum.AMD64ToName(regNum))
    91  		}
    92  		copy(context.FltSave.XmmRegisters[(regNum-regnum.AMD64_XMM0)*16:], reg.Bytes)
    93  	}
    94  
    95  	return _SetThreadContext(thread.os.hThread, context)
    96  }
    97  
    98  func registers(thread *nativeThread) (proc.Registers, error) {
    99  	context := winutil.NewCONTEXT()
   100  
   101  	context.ContextFlags = _CONTEXT_ALL
   102  	err := _GetThreadContext(thread.os.hThread, context)
   103  	if err != nil {
   104  		return nil, err
   105  	}
   106  
   107  	var threadInfo _THREAD_BASIC_INFORMATION
   108  	status := _NtQueryInformationThread(thread.os.hThread, _ThreadBasicInformation, uintptr(unsafe.Pointer(&threadInfo)), uint32(unsafe.Sizeof(threadInfo)), nil)
   109  	if !_NT_SUCCESS(status) {
   110  		return nil, fmt.Errorf("NtQueryInformationThread failed: it returns 0x%x", status)
   111  	}
   112  
   113  	return winutil.NewAMD64Registers(context, uint64(threadInfo.TebBaseAddress)), nil
   114  }