class Fisk::UnresolvedJumpInstruction

Public Class Methods

new(insn, form, operand) click to toggle source
# File lib/fisk.rb, line 361
def initialize insn, form, operand
  @insn       = insn
  @form       = form
  @operand    = operand
  @must_retry = false
end

Public Instance Methods

encode(buffer, labels) click to toggle source
# File lib/fisk.rb, line 380
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
    @must_retry = true
    encoding.encode buffer, [operand_klass.new(0x0CAFE)]
  end
end
jump?() click to toggle source
# File lib/fisk.rb, line 368
def jump?
  true
end
retry?() click to toggle source
# File lib/fisk.rb, line 376
def retry?
  true
end
target() click to toggle source
# File lib/fisk.rb, line 372
def target
  @operand.name
end

Private Instance Methods

find_form(form_type) click to toggle source
# File lib/fisk.rb, line 415
def find_form form_type
  @insn.forms.find { |form| form.operands.first.type == form_type }
end