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.



470
471
472
473
474
475
# File 'lib/fisk.rb', line 470

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

Instance Method Details

#encode(buffer, labels) ⇒ Object



489
490
491
492
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
# File 'lib/fisk.rb', line 489

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)


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

def jump?
  true
end

#retry?Boolean

Returns:

  • (Boolean)


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

def retry?
  true
end

#targetObject



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

def target
  @operand.name
end