github.com/cnboonhan/delve@v0.0.0-20230908061759-363f2388c2fb/pkg/dwarf/frame/table.go (about)

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