github.com/Rookout/GoSDK@v0.1.48/pkg/services/instrumentation/dwarf/frame/table.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 frame
    23  
    24  import (
    25  	"bytes"
    26  	"encoding/binary"
    27  	"fmt"
    28  
    29  	"github.com/Rookout/GoSDK/pkg/services/instrumentation/dwarf/util"
    30  )
    31  
    32  
    33  type DWRule struct {
    34  	Rule       Rule
    35  	Offset     int64
    36  	Reg        uint64
    37  	Expression []byte
    38  }
    39  
    40  
    41  type FrameContext struct {
    42  	loc           uint64
    43  	order         binary.ByteOrder
    44  	address       uint64
    45  	CFA           DWRule
    46  	Regs          map[uint64]DWRule
    47  	initialRegs   map[uint64]DWRule
    48  	prevRegs      map[uint64]DWRule
    49  	buf           *bytes.Buffer
    50  	cie           *CommonInformationEntry
    51  	RetAddrReg    uint64
    52  	codeAlignment uint64
    53  	dataAlignment int64
    54  }
    55  
    56  
    57  const (
    58  	DW_CFA_nop                = 0x0      
    59  	DW_CFA_set_loc            = 0x01     
    60  	DW_CFA_advance_loc1       = iota     
    61  	DW_CFA_advance_loc2                  
    62  	DW_CFA_advance_loc4                  
    63  	DW_CFA_offset_extended               
    64  	DW_CFA_restore_extended              
    65  	DW_CFA_undefined                     
    66  	DW_CFA_same_value                    
    67  	DW_CFA_register                      
    68  	DW_CFA_remember_state                
    69  	DW_CFA_restore_state                 
    70  	DW_CFA_def_cfa                       
    71  	DW_CFA_def_cfa_register              
    72  	DW_CFA_def_cfa_offset                
    73  	DW_CFA_def_cfa_expression            
    74  	DW_CFA_expression                    
    75  	DW_CFA_offset_extended_sf            
    76  	DW_CFA_def_cfa_sf                    
    77  	DW_CFA_def_cfa_offset_sf             
    78  	DW_CFA_val_offset                    
    79  	DW_CFA_val_offset_sf                 
    80  	DW_CFA_val_expression                
    81  	DW_CFA_lo_user            = 0x1c     
    82  	DW_CFA_hi_user            = 0x3f     
    83  	DW_CFA_advance_loc        = 0x1 << 6 
    84  	DW_CFA_offset             = 0x2 << 6 
    85  	DW_CFA_restore            = 0x3 << 6 
    86  )
    87  
    88  
    89  type Rule byte
    90  
    91  const (
    92  	RuleUndefined Rule = iota
    93  	RuleSameVal
    94  	RuleOffset
    95  	RuleValOffset
    96  	RuleRegister
    97  	RuleExpression
    98  	RuleValExpression
    99  	RuleArchitectural
   100  	RuleCFA          
   101  	RuleFramePointer 
   102  )
   103  
   104  const low_6_offset = 0x3f
   105  
   106  type instruction func(frame *FrameContext)
   107  
   108  
   109  var fnlookup = map[byte]instruction{
   110  	DW_CFA_advance_loc:        advanceloc,
   111  	DW_CFA_offset:             offset,
   112  	DW_CFA_restore:            restore,
   113  	DW_CFA_set_loc:            setloc,
   114  	DW_CFA_advance_loc1:       advanceloc1,
   115  	DW_CFA_advance_loc2:       advanceloc2,
   116  	DW_CFA_advance_loc4:       advanceloc4,
   117  	DW_CFA_offset_extended:    offsetextended,
   118  	DW_CFA_restore_extended:   restoreextended,
   119  	DW_CFA_undefined:          undefined,
   120  	DW_CFA_same_value:         samevalue,
   121  	DW_CFA_register:           register,
   122  	DW_CFA_remember_state:     rememberstate,
   123  	DW_CFA_restore_state:      restorestate,
   124  	DW_CFA_def_cfa:            defcfa,
   125  	DW_CFA_def_cfa_register:   defcfaregister,
   126  	DW_CFA_def_cfa_offset:     defcfaoffset,
   127  	DW_CFA_def_cfa_expression: defcfaexpression,
   128  	DW_CFA_expression:         expression,
   129  	DW_CFA_offset_extended_sf: offsetextendedsf,
   130  	DW_CFA_def_cfa_sf:         defcfasf,
   131  	DW_CFA_def_cfa_offset_sf:  defcfaoffsetsf,
   132  	DW_CFA_val_offset:         valoffset,
   133  	DW_CFA_val_offset_sf:      valoffsetsf,
   134  	DW_CFA_val_expression:     valexpression,
   135  	DW_CFA_lo_user:            louser,
   136  	DW_CFA_hi_user:            hiuser,
   137  }
   138  
   139  func executeCIEInstructions(cie *CommonInformationEntry) *FrameContext {
   140  	initialInstructions := make([]byte, len(cie.InitialInstructions))
   141  	copy(initialInstructions, cie.InitialInstructions)
   142  	frame := &FrameContext{
   143  		cie:           cie,
   144  		Regs:          make(map[uint64]DWRule),
   145  		RetAddrReg:    cie.ReturnAddressRegister,
   146  		initialRegs:   make(map[uint64]DWRule),
   147  		prevRegs:      make(map[uint64]DWRule),
   148  		codeAlignment: cie.CodeAlignmentFactor,
   149  		dataAlignment: cie.DataAlignmentFactor,
   150  		buf:           bytes.NewBuffer(initialInstructions),
   151  	}
   152  
   153  	frame.executeDwarfProgram()
   154  	return frame
   155  }
   156  
   157  
   158  func executeDwarfProgramUntilPC(fde *FrameDescriptionEntry, pc uint64) *FrameContext {
   159  	frame := executeCIEInstructions(fde.CIE)
   160  	frame.order = fde.order
   161  	frame.loc = fde.Begin()
   162  	frame.address = pc
   163  	frame.ExecuteUntilPC(fde.Instructions)
   164  
   165  	return frame
   166  }
   167  
   168  func (frame *FrameContext) executeDwarfProgram() {
   169  	for frame.buf.Len() > 0 {
   170  		executeDwarfInstruction(frame)
   171  	}
   172  }
   173  
   174  
   175  func (frame *FrameContext) ExecuteUntilPC(instructions []byte) {
   176  	frame.buf.Truncate(0)
   177  	frame.buf.Write(instructions)
   178  
   179  	
   180  	
   181  	
   182  	for frame.address >= frame.loc && frame.buf.Len() > 0 {
   183  		executeDwarfInstruction(frame)
   184  	}
   185  }
   186  
   187  func executeDwarfInstruction(frame *FrameContext) {
   188  	instruction, err := frame.buf.ReadByte()
   189  	if err != nil {
   190  		panic("Could not read from instruction buffer")
   191  	}
   192  
   193  	if instruction == DW_CFA_nop {
   194  		return
   195  	}
   196  
   197  	fn := lookupFunc(instruction, frame.buf)
   198  
   199  	fn(frame)
   200  }
   201  
   202  func lookupFunc(instruction byte, buf *bytes.Buffer) instruction {
   203  	const high_2_bits = 0xc0
   204  	var restore bool
   205  
   206  	
   207  	switch instruction & high_2_bits {
   208  	case DW_CFA_advance_loc:
   209  		instruction = DW_CFA_advance_loc
   210  		restore = true
   211  
   212  	case DW_CFA_offset:
   213  		instruction = DW_CFA_offset
   214  		restore = true
   215  
   216  	case DW_CFA_restore:
   217  		instruction = DW_CFA_restore
   218  		restore = true
   219  	}
   220  
   221  	if restore {
   222  		
   223  		err := buf.UnreadByte()
   224  		if err != nil {
   225  			panic("Could not unread byte")
   226  		}
   227  	}
   228  
   229  	fn, ok := fnlookup[instruction]
   230  	if !ok {
   231  		panic(fmt.Sprintf("Encountered an unexpected DWARF CFA opcode: %#v", instruction))
   232  	}
   233  
   234  	return fn
   235  }
   236  
   237  func advanceloc(frame *FrameContext) {
   238  	b, err := frame.buf.ReadByte()
   239  	if err != nil {
   240  		panic("Could not read byte")
   241  	}
   242  
   243  	delta := b & low_6_offset
   244  	frame.loc += uint64(delta) * frame.codeAlignment
   245  }
   246  
   247  func advanceloc1(frame *FrameContext) {
   248  	delta, err := frame.buf.ReadByte()
   249  	if err != nil {
   250  		panic("Could not read byte")
   251  	}
   252  
   253  	frame.loc += uint64(delta) * frame.codeAlignment
   254  }
   255  
   256  func advanceloc2(frame *FrameContext) {
   257  	var delta uint16
   258  	binary.Read(frame.buf, frame.order, &delta)
   259  
   260  	frame.loc += uint64(delta) * frame.codeAlignment
   261  }
   262  
   263  func advanceloc4(frame *FrameContext) {
   264  	var delta uint32
   265  	binary.Read(frame.buf, frame.order, &delta)
   266  
   267  	frame.loc += uint64(delta) * frame.codeAlignment
   268  }
   269  
   270  func offset(frame *FrameContext) {
   271  	b, err := frame.buf.ReadByte()
   272  	if err != nil {
   273  		panic(err)
   274  	}
   275  
   276  	var (
   277  		reg       = b & low_6_offset
   278  		offset, _ = util.DecodeULEB128(frame.buf)
   279  	)
   280  
   281  	frame.Regs[uint64(reg)] = DWRule{Offset: int64(offset) * frame.dataAlignment, Rule: RuleOffset}
   282  }
   283  
   284  func restore(frame *FrameContext) {
   285  	b, err := frame.buf.ReadByte()
   286  	if err != nil {
   287  		panic(err)
   288  	}
   289  
   290  	reg := uint64(b & low_6_offset)
   291  	oldrule, ok := frame.initialRegs[reg]
   292  	if ok {
   293  		frame.Regs[reg] = DWRule{Offset: oldrule.Offset, Rule: RuleOffset}
   294  	} else {
   295  		frame.Regs[reg] = DWRule{Rule: RuleUndefined}
   296  	}
   297  }
   298  
   299  func setloc(frame *FrameContext) {
   300  	var loc uint64
   301  	binary.Read(frame.buf, frame.order, &loc)
   302  
   303  	frame.loc = loc + frame.cie.staticBase
   304  }
   305  
   306  func offsetextended(frame *FrameContext) {
   307  	var (
   308  		reg, _    = util.DecodeULEB128(frame.buf)
   309  		offset, _ = util.DecodeULEB128(frame.buf)
   310  	)
   311  
   312  	frame.Regs[reg] = DWRule{Offset: int64(offset) * frame.dataAlignment, Rule: RuleOffset}
   313  }
   314  
   315  func undefined(frame *FrameContext) {
   316  	reg, _ := util.DecodeULEB128(frame.buf)
   317  	frame.Regs[reg] = DWRule{Rule: RuleUndefined}
   318  }
   319  
   320  func samevalue(frame *FrameContext) {
   321  	reg, _ := util.DecodeULEB128(frame.buf)
   322  	frame.Regs[reg] = DWRule{Rule: RuleSameVal}
   323  }
   324  
   325  func register(frame *FrameContext) {
   326  	reg1, _ := util.DecodeULEB128(frame.buf)
   327  	reg2, _ := util.DecodeULEB128(frame.buf)
   328  	frame.Regs[reg1] = DWRule{Reg: reg2, Rule: RuleRegister}
   329  }
   330  
   331  func rememberstate(frame *FrameContext) {
   332  	frame.prevRegs = frame.Regs
   333  }
   334  
   335  func restorestate(frame *FrameContext) {
   336  	frame.Regs = frame.prevRegs
   337  }
   338  
   339  func restoreextended(frame *FrameContext) {
   340  	reg, _ := util.DecodeULEB128(frame.buf)
   341  
   342  	oldrule, ok := frame.initialRegs[reg]
   343  	if ok {
   344  		frame.Regs[reg] = DWRule{Offset: oldrule.Offset, Rule: RuleOffset}
   345  	} else {
   346  		frame.Regs[reg] = DWRule{Rule: RuleUndefined}
   347  	}
   348  }
   349  
   350  func defcfa(frame *FrameContext) {
   351  	reg, _ := util.DecodeULEB128(frame.buf)
   352  	offset, _ := util.DecodeULEB128(frame.buf)
   353  
   354  	frame.CFA.Rule = RuleCFA
   355  	frame.CFA.Reg = reg
   356  	frame.CFA.Offset = int64(offset)
   357  }
   358  
   359  func defcfaregister(frame *FrameContext) {
   360  	reg, _ := util.DecodeULEB128(frame.buf)
   361  	frame.CFA.Reg = reg
   362  }
   363  
   364  func defcfaoffset(frame *FrameContext) {
   365  	offset, _ := util.DecodeULEB128(frame.buf)
   366  	frame.CFA.Offset = int64(offset)
   367  }
   368  
   369  func defcfasf(frame *FrameContext) {
   370  	reg, _ := util.DecodeULEB128(frame.buf)
   371  	offset, _ := util.DecodeSLEB128(frame.buf)
   372  
   373  	frame.CFA.Rule = RuleCFA
   374  	frame.CFA.Reg = reg
   375  	frame.CFA.Offset = offset * frame.dataAlignment
   376  }
   377  
   378  func defcfaoffsetsf(frame *FrameContext) {
   379  	offset, _ := util.DecodeSLEB128(frame.buf)
   380  	offset *= frame.dataAlignment
   381  	frame.CFA.Offset = offset
   382  }
   383  
   384  func defcfaexpression(frame *FrameContext) {
   385  	var (
   386  		l, _ = util.DecodeULEB128(frame.buf)
   387  		expr = frame.buf.Next(int(l))
   388  	)
   389  
   390  	frame.CFA.Expression = expr
   391  	frame.CFA.Rule = RuleExpression
   392  }
   393  
   394  func expression(frame *FrameContext) {
   395  	var (
   396  		reg, _ = util.DecodeULEB128(frame.buf)
   397  		l, _   = util.DecodeULEB128(frame.buf)
   398  		expr   = frame.buf.Next(int(l))
   399  	)
   400  
   401  	frame.Regs[reg] = DWRule{Rule: RuleExpression, Expression: expr}
   402  }
   403  
   404  func offsetextendedsf(frame *FrameContext) {
   405  	var (
   406  		reg, _    = util.DecodeULEB128(frame.buf)
   407  		offset, _ = util.DecodeSLEB128(frame.buf)
   408  	)
   409  
   410  	frame.Regs[reg] = DWRule{Offset: offset * frame.dataAlignment, Rule: RuleOffset}
   411  }
   412  
   413  func valoffset(frame *FrameContext) {
   414  	var (
   415  		reg, _    = util.DecodeULEB128(frame.buf)
   416  		offset, _ = util.DecodeULEB128(frame.buf)
   417  	)
   418  
   419  	frame.Regs[reg] = DWRule{Offset: int64(offset), Rule: RuleValOffset}
   420  }
   421  
   422  func valoffsetsf(frame *FrameContext) {
   423  	var (
   424  		reg, _    = util.DecodeULEB128(frame.buf)
   425  		offset, _ = util.DecodeSLEB128(frame.buf)
   426  	)
   427  
   428  	frame.Regs[reg] = DWRule{Offset: offset * frame.dataAlignment, Rule: RuleValOffset}
   429  }
   430  
   431  func valexpression(frame *FrameContext) {
   432  	var (
   433  		reg, _ = util.DecodeULEB128(frame.buf)
   434  		l, _   = util.DecodeULEB128(frame.buf)
   435  		expr   = frame.buf.Next(int(l))
   436  	)
   437  
   438  	frame.Regs[reg] = DWRule{Rule: RuleValExpression, Expression: expr}
   439  }
   440  
   441  func louser(frame *FrameContext) {
   442  	frame.buf.Next(1)
   443  }
   444  
   445  func hiuser(frame *FrameContext) {
   446  	frame.buf.Next(1)
   447  }