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 }