Class: Fisk::UnresolvedJumpInstruction

Inherits:
Object
  • Object
show all
Includes:
InstructionPredicates
Defined in:
lib/fisk.rb

Instance Method Summary collapse

Methods included from InstructionPredicates

#comment?, #has_temp_registers?, #label?, #lazy?

Constructor Details

#initialize(insn, form, operand) ⇒ UnresolvedJumpInstruction

Returns a new instance of UnresolvedJumpInstruction.



474
475
476
477
478
479
# File 'lib/fisk.rb', line 474

def initialize insn, form, operand
  @insn       = insn
  @form       = form
  @operand    = operand
  @must_retry = false
end

Instance Method Details

#encode(buffer, labels) ⇒ Object



493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
# File 'lib/fisk.rb', line 493

def encode buffer, labels
  # Estimate by using a rel32 offset
  form              = find_form "rel32"
  encoding          = form.encodings.first
  operand_klass     = Rel32

  if labels.key? target
    unless @must_retry
      estimated_offset = labels[target] - (buffer.pos + 6) # 6 seems like a good length

      if estimated_offset >= -128 && estimated_offset <= 127
        # fits in a rel8
        operand_klass     = Rel8
        form              = find_form "rel8"
        encoding          = form.encodings.first
      end
    end

    # We don't know what the size of the jump will be, so just write
    # it out with some dummy data and keep track of the buffer position.
    # Calculate the real jump offset, then rewind and patch the jump with
    # the right location. 😩
    pos = buffer.pos
    encoding.encode buffer, [operand_klass.new(0xFE)]
    jump_len = -(buffer.pos - labels[target])
    buffer.seek pos, IO::SEEK_SET
    encoding.encode buffer, [operand_klass.new(jump_len)]
  else
    if @must_retry
      # We retried once, but the label wasn't defined
      raise Errors::MissingLabel, "Label `#{target}` was used, but not defined"
    end
    @must_retry = true
    encoding.encode buffer, [operand_klass.new(0x0CAFE)]
  end
end

#jump?Boolean

Returns:

  • (Boolean)


481
482
483
# File 'lib/fisk.rb', line 481

def jump?
  true
end

#retry?Boolean

Returns:

  • (Boolean)


489
490
491
# File 'lib/fisk.rb', line 489

def retry?
  true
end

#targetObject



485
486
487
# File 'lib/fisk.rb', line 485

def target
  @operand.name
end