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.



448
449
450
451
452
453
# File 'lib/fisk.rb', line 448

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

Instance Method Details

#encode(buffer, labels) ⇒ Object



467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
# File 'lib/fisk.rb', line 467

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)


455
456
457
# File 'lib/fisk.rb', line 455

def jump?
  true
end

#retry?Boolean

Returns:

  • (Boolean)


463
464
465
# File 'lib/fisk.rb', line 463

def retry?
  true
end

#targetObject



459
460
461
# File 'lib/fisk.rb', line 459

def target
  @operand.name
end