github.com/Rookout/GoSDK@v0.1.48/pkg/services/instrumentation/dwarf/op/opcode_executor.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  	"fmt"
    28  
    29  	"github.com/Rookout/GoSDK/pkg/services/instrumentation/dwarf/util"
    30  )
    31  
    32  type ReadMemoryFunc func([]byte, uint64) (int, error)
    33  
    34  type OpcodeExecutorCreator func(opcode Opcode, ctx *OpcodeExecutorCreatorContext) (OpcodeExecutor, error)
    35  type OpcodeExecutorCreatorContext struct {
    36  	buf         *bytes.Buffer
    37  	prog        []byte
    38  	pointerSize int
    39  }
    40  type Registers interface {
    41  	CFA() int64
    42  	StaticBase() uint64
    43  	FrameBase() int64
    44  	Reg(idx uint64) *DwarfRegister
    45  	Uint64Val(idx uint64) uint64
    46  }
    47  
    48  type OpcodeExecutorContext struct {
    49  	Stack      []int64
    50  	Pieces     []Piece
    51  	prog       []byte
    52  	PtrSize    int
    53  	readMemory ReadMemoryFunc
    54  
    55  	Registers Registers
    56  }
    57  type OpcodeExecutor interface {
    58  	Execute(ctx *OpcodeExecutorContext) error
    59  }
    60  
    61  
    62  
    63  
    64  
    65  type CloseLoc struct {
    66  	isLastInstruction bool
    67  	piece             Piece
    68  	size              int
    69  }
    70  
    71  func newCloseLocExecutor(buf *bytes.Buffer, piece Piece) *CloseLoc {
    72  	c := &CloseLoc{piece: piece}
    73  	if buf.Len() == 0 {
    74  		return c
    75  	}
    76  
    77  	b, err := buf.ReadByte()
    78  	if err != nil {
    79  		return nil
    80  	}
    81  
    82  	opcode := Opcode(b)
    83  	switch opcode {
    84  	case DW_OP_piece:
    85  		sz, _ := util.DecodeULEB128(buf)
    86  		c.piece.Size = int(sz)
    87  		return c
    88  
    89  	case DW_OP_bit_piece:
    90  		
    91  		return nil
    92  	default:
    93  		return nil
    94  	}
    95  }
    96  
    97  func (c *CloseLoc) Execute(ctx *OpcodeExecutorContext) error {
    98  	ctx.Pieces = append(ctx.Pieces, c.piece)
    99  	return nil
   100  }
   101  
   102  type callframeCFAExecutor struct {
   103  }
   104  
   105  func newCallframeCFAExecutor(opcode Opcode, ctx *OpcodeExecutorCreatorContext) (OpcodeExecutor, error) {
   106  	return &callframeCFAExecutor{}, nil
   107  }
   108  
   109  func (c *callframeCFAExecutor) Execute(ctx *OpcodeExecutorContext) error {
   110  	if ctx.Registers.CFA() == 0 {
   111  		return fmt.Errorf("could not retrieve CFA for current PC")
   112  	}
   113  	ctx.Stack = append(ctx.Stack, int64(ctx.Registers.CFA()))
   114  	return nil
   115  }
   116  
   117  type addrExecutor struct {
   118  	stack uint64
   119  }
   120  
   121  func newAddrExecutor(opcode Opcode, ctx *OpcodeExecutorCreatorContext) (OpcodeExecutor, error) {
   122  	b := ctx.buf.Next(ctx.pointerSize)
   123  	stack, err := util.ReadUintRaw(bytes.NewReader(b), binary.LittleEndian, ctx.pointerSize)
   124  	if err != nil {
   125  		return nil, err
   126  	}
   127  	return &addrExecutor{stack: stack}, nil
   128  }
   129  
   130  func (a *addrExecutor) Execute(ctx *OpcodeExecutorContext) error {
   131  	ctx.Stack = append(ctx.Stack, int64(a.stack+ctx.Registers.StaticBase()))
   132  	return nil
   133  }
   134  
   135  type plusExecutor struct{}
   136  
   137  func newPlusExector(opcode Opcode, ctx *OpcodeExecutorCreatorContext) (OpcodeExecutor, error) {
   138  	return &plusExecutor{}, nil
   139  }
   140  
   141  func (p *plusExecutor) Execute(ctx *OpcodeExecutorContext) error {
   142  	var (
   143  		slen   = len(ctx.Stack)
   144  		digits = ctx.Stack[slen-2 : slen]
   145  		st     = ctx.Stack[:slen-2]
   146  	)
   147  
   148  	ctx.Stack = append(st, digits[0]+digits[1])
   149  	return nil
   150  }
   151  
   152  type plusUconstsExecutor struct {
   153  	num uint64
   154  }
   155  
   156  func newPlusUconstsExecutor(opcode Opcode, ctx *OpcodeExecutorCreatorContext) (OpcodeExecutor, error) {
   157  	num, _ := util.DecodeULEB128(ctx.buf)
   158  	return &plusUconstsExecutor{num: num}, nil
   159  }
   160  
   161  func (p *plusUconstsExecutor) Execute(ctx *OpcodeExecutorContext) error {
   162  	slen := len(ctx.Stack)
   163  	ctx.Stack[slen-1] = ctx.Stack[slen-1] + int64(p.num)
   164  	return nil
   165  }
   166  
   167  type constsExecutor struct {
   168  	num int64
   169  }
   170  
   171  func newConstsExecutor(opcode Opcode, ctx *OpcodeExecutorCreatorContext) (OpcodeExecutor, error) {
   172  	num, _ := util.DecodeSLEB128(ctx.buf)
   173  	return &constsExecutor{num: num}, nil
   174  }
   175  
   176  func (c *constsExecutor) Execute(ctx *OpcodeExecutorContext) error {
   177  	ctx.Stack = append(ctx.Stack, c.num)
   178  	return nil
   179  }
   180  
   181  type framebaseExecutor struct {
   182  	num int64
   183  }
   184  
   185  func newFramebaseExecutor(opcode Opcode, ctx *OpcodeExecutorCreatorContext) (OpcodeExecutor, error) {
   186  	num, _ := util.DecodeSLEB128(ctx.buf)
   187  	return &framebaseExecutor{num: num}, nil
   188  }
   189  
   190  func (f *framebaseExecutor) Execute(ctx *OpcodeExecutorContext) error {
   191  	ctx.Stack = append(ctx.Stack, ctx.Registers.FrameBase()+f.num)
   192  	return nil
   193  }
   194  
   195  func newRegisterExecutor(opcode Opcode, ctx *OpcodeExecutorCreatorContext) (OpcodeExecutor, error) {
   196  	var regNum uint64
   197  	if opcode == DW_OP_regx {
   198  		n, _ := util.DecodeSLEB128(ctx.buf)
   199  		regNum = uint64(n)
   200  	} else {
   201  		regNum = uint64(opcode - DW_OP_reg0)
   202  	}
   203  
   204  	return newCloseLocExecutor(ctx.buf, Piece{Kind: RegPiece, Val: regNum}), nil
   205  }
   206  
   207  type bRegisterExecutor struct {
   208  	regNum uint64
   209  	offset int64
   210  }
   211  
   212  func newBRegisterExecutor(opcode Opcode, ctx *OpcodeExecutorCreatorContext) (OpcodeExecutor, error) {
   213  	var regnum uint64
   214  	if opcode == DW_OP_bregx {
   215  		regnum, _ = util.DecodeULEB128(ctx.buf)
   216  	} else {
   217  		regnum = uint64(opcode - DW_OP_breg0)
   218  	}
   219  	offset, _ := util.DecodeSLEB128(ctx.buf)
   220  	return &bRegisterExecutor{regNum: regnum, offset: offset}, nil
   221  }
   222  
   223  func (b *bRegisterExecutor) Execute(ctx *OpcodeExecutorContext) error {
   224  	if ctx.Registers.Reg(b.regNum) == nil {
   225  		return fmt.Errorf("register %d not available", b.regNum)
   226  	}
   227  	ctx.Stack = append(ctx.Stack, int64(ctx.Registers.Uint64Val(b.regNum))+b.offset)
   228  	return nil
   229  }
   230  
   231  type pieceExecutor struct {
   232  	size uint64
   233  }
   234  
   235  func newPieceExecutor(opcode Opcode, ctx *OpcodeExecutorCreatorContext) (OpcodeExecutor, error) {
   236  	sz, _ := util.DecodeULEB128(ctx.buf)
   237  	return &pieceExecutor{size: sz}, nil
   238  }
   239  
   240  func (p *pieceExecutor) Execute(ctx *OpcodeExecutorContext) error {
   241  	if len(ctx.Stack) == 0 {
   242  		
   243  		
   244  		ctx.Pieces = append(ctx.Pieces, Piece{Size: int(p.size), Kind: ImmPiece, Val: 0})
   245  		return nil
   246  	}
   247  
   248  	addr := ctx.Stack[len(ctx.Stack)-1]
   249  	ctx.Pieces = append(ctx.Pieces, Piece{Size: int(p.size), Kind: AddrPiece, Val: uint64(addr)})
   250  	ctx.Stack = ctx.Stack[:0]
   251  	return nil
   252  }
   253  
   254  type literalExecutor struct {
   255  	opcode Opcode
   256  }
   257  
   258  func newLiteralExecutor(opcode Opcode, ctx *OpcodeExecutorCreatorContext) (OpcodeExecutor, error) {
   259  	return &literalExecutor{opcode: opcode}, nil
   260  }
   261  
   262  func (l *literalExecutor) Execute(ctx *OpcodeExecutorContext) error {
   263  	ctx.Stack = append(ctx.Stack, int64(l.opcode-DW_OP_lit0))
   264  	return nil
   265  }
   266  
   267  type constnuExecutor struct {
   268  	n uint64
   269  }
   270  
   271  func newConstnuExecutor(opcode Opcode, ctx *OpcodeExecutorCreatorContext) (OpcodeExecutor, error) {
   272  	var (
   273  		n   uint64
   274  		err error
   275  	)
   276  	switch opcode {
   277  	case DW_OP_const1u:
   278  		var b uint8
   279  		b, err = ctx.buf.ReadByte()
   280  		n = uint64(b)
   281  	case DW_OP_const2u:
   282  		n, err = util.ReadUintRaw(ctx.buf, binary.LittleEndian, 2)
   283  	case DW_OP_const4u:
   284  		n, err = util.ReadUintRaw(ctx.buf, binary.LittleEndian, 4)
   285  	case DW_OP_const8u:
   286  		n, err = util.ReadUintRaw(ctx.buf, binary.LittleEndian, 8)
   287  	default:
   288  		err = fmt.Errorf("unknown opcode: %v", opcode)
   289  	}
   290  	if err != nil {
   291  		return nil, err
   292  	}
   293  
   294  	return &constnuExecutor{n: n}, nil
   295  }
   296  
   297  func (c *constnuExecutor) Execute(ctx *OpcodeExecutorContext) error {
   298  	ctx.Stack = append(ctx.Stack, int64(c.n))
   299  	return nil
   300  }
   301  
   302  type constnsExecutor struct {
   303  	n uint64
   304  }
   305  
   306  func newConstnsExecutor(opcode Opcode, ctx *OpcodeExecutorCreatorContext) (OpcodeExecutor, error) {
   307  	var (
   308  		n   uint64
   309  		err error
   310  	)
   311  	switch opcode {
   312  	case DW_OP_const1s:
   313  		var b uint8
   314  		b, err = ctx.buf.ReadByte()
   315  		n = uint64(int64(int8(b)))
   316  	case DW_OP_const2s:
   317  		n, err = util.ReadUintRaw(ctx.buf, binary.LittleEndian, 2)
   318  		n = uint64(int64(int16(n)))
   319  	case DW_OP_const4s:
   320  		n, err = util.ReadUintRaw(ctx.buf, binary.LittleEndian, 4)
   321  		n = uint64(int64(int32(n)))
   322  	case DW_OP_const8s:
   323  		n, err = util.ReadUintRaw(ctx.buf, binary.LittleEndian, 8)
   324  	default:
   325  		err = fmt.Errorf("unknown opcode: %v", opcode)
   326  	}
   327  	if err != nil {
   328  		return nil, err
   329  	}
   330  
   331  	return &constnsExecutor{n: n}, nil
   332  }
   333  
   334  func (c *constnsExecutor) Execute(ctx *OpcodeExecutorContext) error {
   335  	ctx.Stack = append(ctx.Stack, int64(c.n))
   336  	return nil
   337  }
   338  
   339  type constuExecutor struct {
   340  	num uint64
   341  }
   342  
   343  func newConstuExecutor(opcode Opcode, ctx *OpcodeExecutorCreatorContext) (OpcodeExecutor, error) {
   344  	num, _ := util.DecodeULEB128(ctx.buf)
   345  	return &constuExecutor{num: num}, nil
   346  }
   347  
   348  func (c *constuExecutor) Execute(ctx *OpcodeExecutorContext) error {
   349  	ctx.Stack = append(ctx.Stack, int64(c.num))
   350  	return nil
   351  }
   352  
   353  type dupExecutor struct {
   354  }
   355  
   356  func newDupExecutor(opcode Opcode, ctx *OpcodeExecutorCreatorContext) (OpcodeExecutor, error) {
   357  	return &dupExecutor{}, nil
   358  }
   359  
   360  func (d *dupExecutor) Execute(ctx *OpcodeExecutorContext) error {
   361  	if len(ctx.Stack) <= 0 {
   362  		return fmt.Errorf("stack underflow: expected value in context stack")
   363  	}
   364  	ctx.Stack = append(ctx.Stack, ctx.Stack[len(ctx.Stack)-1])
   365  	return nil
   366  }
   367  
   368  type dropExecutor struct {
   369  }
   370  
   371  func newDropExecutor(opcode Opcode, ctx *OpcodeExecutorCreatorContext) (OpcodeExecutor, error) {
   372  	return &dropExecutor{}, nil
   373  }
   374  
   375  func (d *dropExecutor) Execute(ctx *OpcodeExecutorContext) error {
   376  	if len(ctx.Stack) <= 0 {
   377  		return fmt.Errorf("stack underflow: expected value in context stack")
   378  	}
   379  	ctx.Stack = ctx.Stack[:len(ctx.Stack)-1]
   380  	return nil
   381  }
   382  
   383  type pickExecutor struct {
   384  	n byte
   385  }
   386  
   387  func newPickExecutor(opcode Opcode, ctx *OpcodeExecutorCreatorContext) (OpcodeExecutor, error) {
   388  	var n byte
   389  	switch opcode {
   390  	case DW_OP_pick:
   391  		n, _ = ctx.buf.ReadByte()
   392  	case DW_OP_over:
   393  		n = 1
   394  	default:
   395  		return nil, fmt.Errorf("unexpected opcode: %v", opcode)
   396  	}
   397  	return &pickExecutor{n: n}, nil
   398  }
   399  
   400  func (p *pickExecutor) Execute(ctx *OpcodeExecutorContext) error {
   401  	idx := len(ctx.Stack) - 1 - int(uint8(p.n))
   402  	if idx < 0 || idx >= len(ctx.Stack) {
   403  		return fmt.Errorf("stack index out of bounds: %d/%d", idx, len(ctx.Stack))
   404  	}
   405  	ctx.Stack = append(ctx.Stack, ctx.Stack[idx])
   406  	return nil
   407  }
   408  
   409  type swapExecutor struct{}
   410  
   411  func newSwapExecutor(opcode Opcode, ctx *OpcodeExecutorCreatorContext) (OpcodeExecutor, error) {
   412  	return &swapExecutor{}, nil
   413  }
   414  
   415  func (s *swapExecutor) Execute(ctx *OpcodeExecutorContext) error {
   416  	if len(ctx.Stack) < 2 {
   417  		return fmt.Errorf("stack underflow: expected value on stack")
   418  	}
   419  	ctx.Stack[len(ctx.Stack)-1], ctx.Stack[len(ctx.Stack)-2] = ctx.Stack[len(ctx.Stack)-2], ctx.Stack[len(ctx.Stack)-1]
   420  	return nil
   421  }
   422  
   423  type rotExecutor struct {
   424  }
   425  
   426  func newRotExecutor(opcode Opcode, ctx *OpcodeExecutorCreatorContext) (OpcodeExecutor, error) {
   427  	return &rotExecutor{}, nil
   428  }
   429  
   430  func (r *rotExecutor) Execute(ctx *OpcodeExecutorContext) error {
   431  	if len(ctx.Stack) < 3 {
   432  		return fmt.Errorf("stack underflow: expected value on stack")
   433  	}
   434  	ctx.Stack[len(ctx.Stack)-1], ctx.Stack[len(ctx.Stack)-2], ctx.Stack[len(ctx.Stack)-3] = ctx.Stack[len(ctx.Stack)-2], ctx.Stack[len(ctx.Stack)-3], ctx.Stack[len(ctx.Stack)-1]
   435  	return nil
   436  }
   437  
   438  type unaryOpExecutor struct {
   439  	opcode Opcode
   440  }
   441  
   442  func newUnaryOpExecutor(opcode Opcode, ctx *OpcodeExecutorCreatorContext) (OpcodeExecutor, error) {
   443  	return &unaryOpExecutor{opcode: opcode}, nil
   444  }
   445  
   446  func (u *unaryOpExecutor) Execute(ctx *OpcodeExecutorContext) error {
   447  	if len(ctx.Stack) < 1 {
   448  		return fmt.Errorf("stack underflow: expected value on stack")
   449  	}
   450  	operand := ctx.Stack[len(ctx.Stack)-1]
   451  	switch u.opcode {
   452  	case DW_OP_abs:
   453  		if operand < 0 {
   454  			operand = -operand
   455  		}
   456  	case DW_OP_neg:
   457  		operand = -operand
   458  	case DW_OP_not:
   459  		operand = ^operand
   460  	default:
   461  		return fmt.Errorf("unexpected opcode: %v", u.opcode)
   462  	}
   463  	ctx.Stack[len(ctx.Stack)-1] = operand
   464  	return nil
   465  }
   466  
   467  type binaryOpExecutor struct {
   468  	opcode Opcode
   469  }
   470  
   471  func newBinaryOpExecutor(opcode Opcode, ctx *OpcodeExecutorCreatorContext) (OpcodeExecutor, error) {
   472  	return &binaryOpExecutor{opcode: opcode}, nil
   473  }
   474  
   475  func (b *binaryOpExecutor) Execute(ctx *OpcodeExecutorContext) error {
   476  	if len(ctx.Stack) < 2 {
   477  		return fmt.Errorf("stack underflow: expected value on stack")
   478  	}
   479  	second := ctx.Stack[len(ctx.Stack)-2]
   480  	top := ctx.Stack[len(ctx.Stack)-1]
   481  	var r int64
   482  	ctx.Stack = ctx.Stack[:len(ctx.Stack)-2]
   483  	switch b.opcode {
   484  	case DW_OP_and:
   485  		r = second & top
   486  	case DW_OP_div:
   487  		r = second / top
   488  	case DW_OP_minus:
   489  		r = second - top
   490  	case DW_OP_mod:
   491  		r = second % top
   492  	case DW_OP_mul:
   493  		r = second * top
   494  	case DW_OP_or:
   495  		r = second | top
   496  	case DW_OP_plus:
   497  		r = second + top
   498  	case DW_OP_shl:
   499  		r = second << uint64(top)
   500  	case DW_OP_shr:
   501  		r = second >> uint64(top)
   502  	case DW_OP_shra:
   503  		r = int64(uint64(second) >> uint64(top))
   504  	case DW_OP_xor:
   505  		r = second ^ top
   506  	case DW_OP_le:
   507  		r = boolToInt(second <= top)
   508  	case DW_OP_ge:
   509  		r = boolToInt(second >= top)
   510  	case DW_OP_eq:
   511  		r = boolToInt(second == top)
   512  	case DW_OP_lt:
   513  		r = boolToInt(second < top)
   514  	case DW_OP_gt:
   515  		r = boolToInt(second > top)
   516  	case DW_OP_ne:
   517  		r = boolToInt(second != top)
   518  	default:
   519  		return fmt.Errorf("unexpected opcode: %v", b.opcode)
   520  	}
   521  	ctx.Stack = append(ctx.Stack, r)
   522  	return nil
   523  }
   524  
   525  func boolToInt(b bool) int64 {
   526  	if b {
   527  		return 1
   528  	}
   529  	return 0
   530  }
   531  
   532  type skipExecutor struct{}
   533  
   534  func newSkipExecutor(opcode Opcode, ctx *OpcodeExecutorCreatorContext) (OpcodeExecutor, error) {
   535  	var n int16
   536  	err := binary.Read(ctx.buf, binary.LittleEndian, &n)
   537  	if err != nil {
   538  		return nil, err
   539  	}
   540  	if err = ctx.jump(n); err != nil {
   541  		return nil, err
   542  	}
   543  	return &skipExecutor{}, nil
   544  }
   545  
   546  func (c *OpcodeExecutorCreatorContext) jump(n int16) error {
   547  	i := len(c.prog) - c.buf.Len() + int(n)
   548  	if i < 0 {
   549  		return fmt.Errorf("stack underflow")
   550  	}
   551  	if i >= len(c.prog) {
   552  		i = len(c.prog)
   553  	}
   554  	c.buf = bytes.NewBuffer(c.prog[i:])
   555  	return nil
   556  }
   557  
   558  func (s *skipExecutor) Execute(ctx *OpcodeExecutorContext) error {
   559  	return nil
   560  }
   561  
   562  type braExecutor struct {
   563  	n           int16
   564  	withJump    []OpcodeExecutor
   565  	withoutJump []OpcodeExecutor
   566  }
   567  
   568  func newBraExecutor(opcode Opcode, ctx *OpcodeExecutorCreatorContext) (OpcodeExecutor, error) {
   569  	var n int16
   570  	err := binary.Read(ctx.buf, binary.LittleEndian, &n)
   571  	if err != nil {
   572  		return nil, err
   573  	}
   574  
   575  	b := &braExecutor{n: n}
   576  	bufBytes := make([]byte, ctx.buf.Len())
   577  	_, err = ctx.buf.Read(bufBytes)
   578  	if err != nil {
   579  		return nil, err
   580  	}
   581  
   582  	b.withJump, err = b.buildBraExecutors(ctx, bufBytes, true)
   583  	if err != nil {
   584  		return nil, err
   585  	}
   586  
   587  	b.withoutJump, err = b.buildBraExecutors(ctx, bufBytes, false)
   588  	if err != nil {
   589  		return nil, err
   590  	}
   591  
   592  	return b, nil
   593  }
   594  
   595  func (b braExecutor) buildBraExecutors(ctx *OpcodeExecutorCreatorContext, bufBytes []byte, withJump bool) ([]OpcodeExecutor, error) {
   596  	var executors []OpcodeExecutor
   597  	bytesCopy := make([]byte, len(bufBytes))
   598  	copy(bytesCopy, bufBytes)
   599  	ctx.buf = bytes.NewBuffer(bytesCopy)
   600  
   601  	if withJump {
   602  		err := ctx.jump(b.n)
   603  		if err != nil {
   604  			return nil, err
   605  		}
   606  	}
   607  
   608  	for i := 0; i < len(bufBytes); i++ {
   609  		opcodeByte, err := ctx.buf.ReadByte()
   610  		if err != nil {
   611  			break
   612  		}
   613  		opcode := Opcode(opcodeByte)
   614  		if opcode == DW_OP_nop {
   615  			continue
   616  		}
   617  		executorCreator, ok := OpcodeToExecutorCreator(opcode)
   618  		if !ok {
   619  			return nil, fmt.Errorf("invalid instruction %#v", opcode)
   620  		}
   621  
   622  		executor, err := executorCreator(opcode, ctx)
   623  		if err != nil {
   624  			return nil, err
   625  		}
   626  		executors = append(executors, executor)
   627  	}
   628  
   629  	return executors, nil
   630  }
   631  
   632  func (b braExecutor) Execute(ctx *OpcodeExecutorContext) error {
   633  	if len(ctx.Stack) < 1 {
   634  		return fmt.Errorf("stack underflow: expected value on context stack")
   635  	}
   636  
   637  	top := ctx.Stack[len(ctx.Stack)-1]
   638  	ctx.Stack = ctx.Stack[:len(ctx.Stack)-1]
   639  	executors := b.withoutJump
   640  	if top != 0 {
   641  		executors = b.withJump
   642  	}
   643  
   644  	for _, executor := range executors {
   645  		err := executor.Execute(ctx)
   646  		if err != nil {
   647  			return err
   648  		}
   649  	}
   650  
   651  	return nil
   652  }
   653  
   654  type stackValueExecutor struct {
   655  	closeLoc *CloseLoc
   656  }
   657  
   658  func newStackValueExecutor(opcode Opcode, ctx *OpcodeExecutorCreatorContext) (OpcodeExecutor, error) {
   659  	piece := Piece{Kind: ImmPiece}
   660  	closeLoc := newCloseLocExecutor(ctx.buf, piece)
   661  	return &stackValueExecutor{closeLoc: closeLoc}, nil
   662  }
   663  
   664  func (s *stackValueExecutor) Execute(ctx *OpcodeExecutorContext) error {
   665  	if len(ctx.Stack) < 1 {
   666  		return fmt.Errorf("stack underflow: expected value on context stack")
   667  	}
   668  	val := ctx.Stack[len(ctx.Stack)-1]
   669  	ctx.Stack = ctx.Stack[:len(ctx.Stack)-1]
   670  	s.closeLoc.piece.Val = uint64(val)
   671  	return s.closeLoc.Execute(ctx)
   672  }
   673  
   674  func newImplicitValueExecutor(opcode Opcode, ctx *OpcodeExecutorCreatorContext) (OpcodeExecutor, error) {
   675  	sz, _ := util.DecodeULEB128(ctx.buf)
   676  	block := make([]byte, sz)
   677  	n, _ := ctx.buf.Read(block)
   678  	if uint64(n) != sz {
   679  		return nil, fmt.Errorf("insufficient bytes read while reading DW_OP_implicit_value's block %d (expected: %d)", n, sz)
   680  	}
   681  	return newCloseLocExecutor(ctx.buf, Piece{Kind: ImmPiece, Bytes: block, Size: int(sz)}), nil
   682  }
   683  
   684  type derefExecutor struct {
   685  	size   int
   686  	opcode Opcode
   687  }
   688  
   689  func newDerefExecutor(opcode Opcode, ctx *OpcodeExecutorCreatorContext) (OpcodeExecutor, error) {
   690  	size := ctx.pointerSize
   691  	if opcode == DW_OP_deref_size || opcode == DW_OP_xderef_size {
   692  		n, err := ctx.buf.ReadByte()
   693  		if err != nil {
   694  			return nil, err
   695  		}
   696  		size = int(n)
   697  	}
   698  	return &derefExecutor{size: size, opcode: opcode}, nil
   699  }
   700  
   701  func (d *derefExecutor) Execute(ctx *OpcodeExecutorContext) error {
   702  	if ctx.readMemory == nil {
   703  		return fmt.Errorf("memory read is unavailable")
   704  	}
   705  	if len(ctx.Stack) <= 0 {
   706  		return fmt.Errorf("stack underflow: expected a value on context stack")
   707  	}
   708  
   709  	addr := ctx.Stack[len(ctx.Stack)-1]
   710  	ctx.Stack = ctx.Stack[:len(ctx.Stack)-1]
   711  	if d.opcode == DW_OP_xderef || d.opcode == DW_OP_xderef_size {
   712  		if len(ctx.Stack) <= 0 {
   713  			return fmt.Errorf("stack underflow: expected a value on context stack")
   714  		}
   715  		
   716  		ctx.Stack = ctx.Stack[:len(ctx.Stack)-1]
   717  	}
   718  
   719  	buf := make([]byte, d.size)
   720  	_, err := ctx.readMemory(buf, uint64(addr))
   721  	if err != nil {
   722  		return err
   723  	}
   724  	x, err := util.ReadUintRaw(bytes.NewReader(buf), binary.LittleEndian, d.size)
   725  	if err != nil {
   726  		return err
   727  	}
   728  
   729  	ctx.Stack = append(ctx.Stack, int64(x))
   730  	return nil
   731  }
   732  
   733  func OpcodeToExecutorCreator(opcode Opcode) (OpcodeExecutorCreator, bool) {
   734  	switch opcode {
   735  	case DW_OP_addr:
   736  		return newAddrExecutor, true
   737  	case DW_OP_deref, DW_OP_xderef, DW_OP_deref_size, DW_OP_xderef_size:
   738  		return newDerefExecutor, true
   739  	case DW_OP_const1s, DW_OP_const2s, DW_OP_const4s, DW_OP_const8s:
   740  		return newConstnsExecutor, true
   741  	case DW_OP_const1u, DW_OP_const2u, DW_OP_const4u, DW_OP_const8u:
   742  		return newConstnuExecutor, true
   743  	case DW_OP_constu:
   744  		return newConstuExecutor, true
   745  	case DW_OP_consts:
   746  		return newConstsExecutor, true
   747  	case DW_OP_dup:
   748  		return newDupExecutor, true
   749  	case DW_OP_drop:
   750  		return newDropExecutor, true
   751  	case DW_OP_over, DW_OP_pick:
   752  		return newPickExecutor, true
   753  	case DW_OP_swap:
   754  		return newSwapExecutor, true
   755  	case DW_OP_rot:
   756  		return newRotExecutor, true
   757  	case DW_OP_abs:
   758  		return newUnaryOpExecutor, true
   759  	case DW_OP_and, DW_OP_div, DW_OP_minus, DW_OP_mod, DW_OP_mul, DW_OP_or, DW_OP_plus, DW_OP_shl, DW_OP_shr, DW_OP_shra,
   760  		DW_OP_xor, DW_OP_eq, DW_OP_ge, DW_OP_gt, DW_OP_le, DW_OP_lt, DW_OP_ne:
   761  		return newBinaryOpExecutor, true
   762  	case DW_OP_neg, DW_OP_not:
   763  		return newUnaryOpExecutor, true
   764  	case DW_OP_plus_uconst:
   765  		return newPlusUconstsExecutor, true
   766  	case DW_OP_skip:
   767  		return newSkipExecutor, true
   768  	case DW_OP_lit0, DW_OP_lit1, DW_OP_lit2, DW_OP_lit3, DW_OP_lit4, DW_OP_lit5, DW_OP_lit6, DW_OP_lit7, DW_OP_lit8,
   769  		DW_OP_lit9, DW_OP_lit10, DW_OP_lit11, DW_OP_lit12, DW_OP_lit13, DW_OP_lit14, DW_OP_lit15, DW_OP_lit16, DW_OP_lit17,
   770  		DW_OP_lit18, DW_OP_lit19, DW_OP_lit20, DW_OP_lit21, DW_OP_lit22, DW_OP_lit23, DW_OP_lit24, DW_OP_lit25, DW_OP_lit26,
   771  		DW_OP_lit27, DW_OP_lit28, DW_OP_lit29, DW_OP_lit30, DW_OP_lit31:
   772  		return newLiteralExecutor, true
   773  	case DW_OP_reg0, DW_OP_reg1, DW_OP_reg2, DW_OP_reg3, DW_OP_reg4, DW_OP_reg5, DW_OP_reg6, DW_OP_reg7, DW_OP_reg8,
   774  		DW_OP_reg9, DW_OP_reg10, DW_OP_reg11, DW_OP_reg12, DW_OP_reg13, DW_OP_reg14, DW_OP_reg15, DW_OP_reg16, DW_OP_reg17,
   775  		DW_OP_reg18, DW_OP_reg19, DW_OP_reg20, DW_OP_reg21, DW_OP_reg22, DW_OP_reg23, DW_OP_reg24, DW_OP_reg25, DW_OP_reg26,
   776  		DW_OP_reg27, DW_OP_reg28, DW_OP_reg29, DW_OP_reg30, DW_OP_reg31, DW_OP_regx:
   777  		return newRegisterExecutor, true
   778  	case DW_OP_breg0, DW_OP_breg1, DW_OP_breg2, DW_OP_breg3, DW_OP_breg4, DW_OP_breg5, DW_OP_breg6, DW_OP_breg7,
   779  		DW_OP_breg8, DW_OP_breg9, DW_OP_breg10, DW_OP_breg11, DW_OP_breg12, DW_OP_breg13, DW_OP_breg14, DW_OP_breg15,
   780  		DW_OP_breg16, DW_OP_breg17, DW_OP_breg18, DW_OP_breg19, DW_OP_breg20, DW_OP_breg21, DW_OP_breg22, DW_OP_breg23,
   781  		DW_OP_breg24, DW_OP_breg25, DW_OP_breg26, DW_OP_breg27, DW_OP_breg28, DW_OP_breg29, DW_OP_breg30, DW_OP_breg31,
   782  		DW_OP_bregx:
   783  		return newBRegisterExecutor, true
   784  	case DW_OP_fbreg:
   785  		return newFramebaseExecutor, true
   786  	case DW_OP_piece:
   787  		return newPieceExecutor, true
   788  	case DW_OP_call_frame_cfa:
   789  		return newCallframeCFAExecutor, true
   790  	case DW_OP_implicit_value:
   791  		return newImplicitValueExecutor, true
   792  	case DW_OP_stack_value:
   793  		return newStackValueExecutor, true
   794  	case DW_OP_bra:
   795  		return newBraExecutor, true
   796  	default:
   797  		return nil, false
   798  	}
   799  }