github.com/undoio/delve@v1.9.0/pkg/dwarf/frame/table.go (about)

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