mirror of
				https://github.com/go-delve/delve.git
				synced 2025-11-01 03:42:59 +08:00 
			
		
		
		
	 5372588c61
			
		
	
	5372588c61
	
	
	
		
			
			When creating a stack trace we should switch between the goroutine stack and the system stack (where cgo code is executed) as appropriate to reconstruct the logical stacktrace. Goroutines that are currently executing on the system stack will have the SystemStack flag set, frames of the goroutine stack will have a negative FrameOffset (like always) and frames of the system stack will have a positive FrameOffset (which is actually just the CFA value for the frame). Updates #935
		
			
				
	
	
		
			101 lines
		
	
	
		
			2.0 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			101 lines
		
	
	
		
			2.0 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package op
 | |
| 
 | |
| import (
 | |
| 	"bytes"
 | |
| 	"encoding/binary"
 | |
| )
 | |
| 
 | |
| type DwarfRegisters struct {
 | |
| 	CFA       int64
 | |
| 	FrameBase int64
 | |
| 	ObjBase   int64
 | |
| 	Regs      []*DwarfRegister
 | |
| 
 | |
| 	ByteOrder binary.ByteOrder
 | |
| 	PCRegNum  uint64
 | |
| 	SPRegNum  uint64
 | |
| 	BPRegNum  uint64
 | |
| }
 | |
| 
 | |
| type DwarfRegister struct {
 | |
| 	Uint64Val uint64
 | |
| 	Bytes     []byte
 | |
| }
 | |
| 
 | |
| // Uint64Val returns the uint64 value of register idx.
 | |
| func (regs *DwarfRegisters) Uint64Val(idx uint64) uint64 {
 | |
| 	reg := regs.Reg(idx)
 | |
| 	if reg == nil {
 | |
| 		return 0
 | |
| 	}
 | |
| 	return regs.Regs[idx].Uint64Val
 | |
| }
 | |
| 
 | |
| // Bytes returns the bytes value of register idx, nil if the register is not
 | |
| // defined.
 | |
| func (regs *DwarfRegisters) Bytes(idx uint64) []byte {
 | |
| 	reg := regs.Reg(idx)
 | |
| 	if reg == nil {
 | |
| 		return nil
 | |
| 	}
 | |
| 	if reg.Bytes == nil {
 | |
| 		var buf bytes.Buffer
 | |
| 		binary.Write(&buf, regs.ByteOrder, reg.Uint64Val)
 | |
| 		reg.Bytes = buf.Bytes()
 | |
| 	}
 | |
| 	return reg.Bytes
 | |
| }
 | |
| 
 | |
| // Reg returns register idx or nil if the register is not defined.
 | |
| func (regs *DwarfRegisters) Reg(idx uint64) *DwarfRegister {
 | |
| 	if idx >= uint64(len(regs.Regs)) {
 | |
| 		return nil
 | |
| 	}
 | |
| 	return regs.Regs[idx]
 | |
| }
 | |
| 
 | |
| func (regs *DwarfRegisters) PC() uint64 {
 | |
| 	return regs.Uint64Val(regs.PCRegNum)
 | |
| }
 | |
| 
 | |
| func (regs *DwarfRegisters) SP() uint64 {
 | |
| 	return regs.Uint64Val(regs.SPRegNum)
 | |
| }
 | |
| 
 | |
| func (regs *DwarfRegisters) BP() uint64 {
 | |
| 	return regs.Uint64Val(regs.BPRegNum)
 | |
| }
 | |
| 
 | |
| // AddReg adds register idx to regs.
 | |
| func (regs *DwarfRegisters) AddReg(idx uint64, reg *DwarfRegister) {
 | |
| 	if idx >= uint64(len(regs.Regs)) {
 | |
| 		newRegs := make([]*DwarfRegister, idx+1)
 | |
| 		copy(newRegs, regs.Regs)
 | |
| 		regs.Regs = newRegs
 | |
| 	}
 | |
| 	regs.Regs[idx] = reg
 | |
| }
 | |
| 
 | |
| func DwarfRegisterFromUint64(v uint64) *DwarfRegister {
 | |
| 	return &DwarfRegister{Uint64Val: v}
 | |
| }
 | |
| 
 | |
| func DwarfRegisterFromBytes(bytes []byte) *DwarfRegister {
 | |
| 	var v uint64
 | |
| 	switch len(bytes) {
 | |
| 	case 1:
 | |
| 		v = uint64(bytes[0])
 | |
| 	case 2:
 | |
| 		x := binary.LittleEndian.Uint16(bytes)
 | |
| 		v = uint64(x)
 | |
| 	case 4:
 | |
| 		x := binary.LittleEndian.Uint32(bytes)
 | |
| 		v = uint64(x)
 | |
| 	default:
 | |
| 		if len(bytes) >= 8 {
 | |
| 			v = binary.LittleEndian.Uint64(bytes[:8])
 | |
| 		}
 | |
| 	}
 | |
| 	return &DwarfRegister{Uint64Val: v, Bytes: bytes}
 | |
| }
 |