github.com/Rookout/GoSDK@v0.1.48/pkg/services/instrumentation/dwarf/op/regs.go (about)

     1  // The MIT License (MIT)
     2  
     3  // Copyright (c) 2014 Derek Parker
     4  
     5  // Permission is hereby granted, free of charge, to any person obtaining a copy of
     6  // this software and associated documentation files (the "Software"), to deal in
     7  // the Software without restriction, including without limitation the rights to
     8  // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
     9  // the Software, and to permit persons to whom the Software is furnished to do so,
    10  // subject to the following conditions:
    11  
    12  // The above copyright notice and this permission notice shall be included in all
    13  // copies or substantial portions of the Software.
    14  
    15  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    16  // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
    17  // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
    18  // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
    19  // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
    20  // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    21  
    22  package op
    23  
    24  import (
    25  	"bytes"
    26  	"encoding/binary"
    27  )
    28  
    29  
    30  type DwarfRegisters struct {
    31  	staticBase uint64
    32  
    33  	cfa       int64
    34  	frameBase int64
    35  	ObjBase   int64
    36  	regs      []*DwarfRegister
    37  
    38  	ByteOrder binary.ByteOrder
    39  	PCRegNum  uint64
    40  	SPRegNum  uint64
    41  	BPRegNum  uint64
    42  	LRRegNum  uint64
    43  
    44  	FloatLoadError   error 
    45  	loadMoreCallback func()
    46  }
    47  
    48  type DwarfRegister struct {
    49  	Uint64Val uint64
    50  	Bytes     []byte
    51  }
    52  
    53  
    54  func NewDwarfRegisters(staticBase uint64, regs []*DwarfRegister, byteOrder binary.ByteOrder, pcRegNum, spRegNum, bpRegNum, lrRegNum uint64) *DwarfRegisters {
    55  	return &DwarfRegisters{
    56  		staticBase: staticBase,
    57  		regs:       regs,
    58  		ByteOrder:  byteOrder,
    59  		PCRegNum:   pcRegNum,
    60  		SPRegNum:   spRegNum,
    61  		BPRegNum:   bpRegNum,
    62  		LRRegNum:   lrRegNum,
    63  	}
    64  }
    65  
    66  func (regs *DwarfRegisters) CFA() int64                      { return regs.cfa }
    67  func (regs *DwarfRegisters) StaticBase() uint64              { return regs.staticBase }
    68  func (regs *DwarfRegisters) FrameBase() int64                { return regs.frameBase }
    69  func (regs *DwarfRegisters) SetCFA(cfa int64)                { regs.cfa = cfa }
    70  func (regs *DwarfRegisters) SetStaticBase(staticBase uint64) { regs.staticBase = staticBase }
    71  func (regs *DwarfRegisters) SetFrameBase(frameBase int64)    { regs.frameBase = frameBase }
    72  
    73  
    74  
    75  func (regs *DwarfRegisters) SetLoadMoreCallback(fn func()) {
    76  	regs.loadMoreCallback = fn
    77  }
    78  
    79  
    80  
    81  func (regs *DwarfRegisters) CurrentSize() int {
    82  	return len(regs.regs)
    83  }
    84  
    85  
    86  func (regs *DwarfRegisters) Uint64Val(idx uint64) uint64 {
    87  	reg := regs.Reg(idx)
    88  	if reg == nil {
    89  		return 0
    90  	}
    91  	return regs.regs[idx].Uint64Val
    92  }
    93  
    94  
    95  
    96  func (regs *DwarfRegisters) Bytes(idx uint64) []byte {
    97  	reg := regs.Reg(idx)
    98  	if reg == nil {
    99  		return nil
   100  	}
   101  	if reg.Bytes == nil {
   102  		var buf bytes.Buffer
   103  		binary.Write(&buf, regs.ByteOrder, reg.Uint64Val)
   104  		reg.Bytes = buf.Bytes()
   105  	}
   106  	return reg.Bytes
   107  }
   108  
   109  func (regs *DwarfRegisters) loadMore() {
   110  	if regs.loadMoreCallback == nil {
   111  		return
   112  	}
   113  	regs.loadMoreCallback()
   114  	regs.loadMoreCallback = nil
   115  }
   116  
   117  
   118  func (regs *DwarfRegisters) Reg(idx uint64) *DwarfRegister {
   119  	if idx >= uint64(len(regs.regs)) {
   120  		regs.loadMore()
   121  		if idx >= uint64(len(regs.regs)) {
   122  			return nil
   123  		}
   124  	}
   125  	if regs.regs[idx] == nil {
   126  		regs.loadMore()
   127  	}
   128  	return regs.regs[idx]
   129  }
   130  
   131  func (regs *DwarfRegisters) PC() uint64 {
   132  	return regs.Uint64Val(regs.PCRegNum)
   133  }
   134  
   135  func (regs *DwarfRegisters) SP() uint64 {
   136  	return regs.Uint64Val(regs.SPRegNum)
   137  }
   138  
   139  func (regs *DwarfRegisters) BP() uint64 {
   140  	return regs.Uint64Val(regs.BPRegNum)
   141  }
   142  
   143  
   144  func (regs *DwarfRegisters) AddReg(idx uint64, reg *DwarfRegister) {
   145  	if idx >= uint64(len(regs.regs)) {
   146  		newRegs := make([]*DwarfRegister, idx+1)
   147  		copy(newRegs, regs.regs)
   148  		regs.regs = newRegs
   149  	}
   150  	regs.regs[idx] = reg
   151  }
   152  
   153  
   154  func (regs *DwarfRegisters) ClearRegisters() {
   155  	regs.loadMoreCallback = nil
   156  	for regnum := range regs.regs {
   157  		regs.regs[regnum] = nil
   158  	}
   159  }
   160  
   161  func DwarfRegisterFromUint64(v uint64) *DwarfRegister {
   162  	return &DwarfRegister{Uint64Val: v}
   163  }
   164  
   165  func DwarfRegisterFromBytes(bytes []byte) *DwarfRegister {
   166  	var v uint64
   167  	switch len(bytes) {
   168  	case 1:
   169  		v = uint64(bytes[0])
   170  	case 2:
   171  		x := binary.LittleEndian.Uint16(bytes)
   172  		v = uint64(x)
   173  	case 4:
   174  		x := binary.LittleEndian.Uint32(bytes)
   175  		v = uint64(x)
   176  	default:
   177  		if len(bytes) >= 8 {
   178  			v = binary.LittleEndian.Uint64(bytes[:8])
   179  		}
   180  	}
   181  	return &DwarfRegister{Uint64Val: v, Bytes: bytes}
   182  }