Class: OneGadget::Emulators::Riscv64

Inherits:
Processor
  • Object
show all
Defined in:
lib/one_gadget/emulators/riscv64.rb

Overview

Emulator of RISC-V (RV64).

Constant Summary collapse

COND =

A conditional branch of this arch compares its operands itself -- there is no flag register and no compare instruction -- so each mnemonic names the relation the operands must stand in for the branch to be taken. The assembler's spellings against zero (+beqz+, blez, ...) name one register and the reversed ones (+bgt+, ble, ...) read a relation the other way round; each is listed as the relation it states, so a constraint reads as the comparison was written.

{
  'beq' => :eq, 'bne' => :ne,
  'blt' => :slt, 'bge' => :sge, 'bltu' => :ult, 'bgeu' => :uge,
  'bgt' => :sgt, 'ble' => :sle, 'bgtu' => :ugt, 'bleu' => :ule,
  'beqz' => :eq, 'bnez' => :ne,
  'bltz' => :slt, 'bgez' => :sge, 'blez' => :sle, 'bgtz' => :sgt
}.freeze

Constants inherited from Processor

Processor::TERMINAL_CALL_RE

Constants included from Constraints

Constraints::ADDRESS_TYPES, Constraints::CLOBBERED, Constraints::NULLABLE_REQUIREMENTS, Constraints::POINTER_REQUIREMENTS

Constants included from Conditional

Conditional::COMPARE_OPS, Conditional::NEGATE, Conditional::RELATION, Conditional::ZERO

Instance Attribute Summary

Attributes inherited from Processor

#bp, #pc, #refused_line, #registers, #sp

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Processor

instruction_table, line_memo, #parse, #process, #reach_terminal_call, #terminal_call?

Methods included from TrackedMemory

#bp_based_stack, #get_corresponding_stack, #resolve_address, #setup_frame_pointer, #sp_based_stack, #writes_through

Methods included from Constraints

#address_deref0?, #closed_fds, #constraint_key, #constraints, #drop_implied_nonzero, #drop_restated_null, #render_constraint

Methods included from Conditional

#branch_on_bit, #branch_on_compare, #branch_on_zero, #comparisons_on, #handle_compare, #mnemonic, #operand_str, #record_compare, #resolve_pending_branch, #satisfiable?, #value_str

Constructor Details

#initializeRiscv64

Instantiate a OneGadget::Emulators::Riscv64 object.



12
13
14
15
16
17
# File 'lib/one_gadget/emulators/riscv64.rb', line 12

def initialize
  super(OneGadget::ABI.riscv64, 'sp')
  @registers['zero'] = 0 # hardwired
  @pc = 'pc'
  setup_frame_pointer('s0') # track argv/data staged off the frame pointer
end

Class Method Details

.bitsInteger

RV64 is 64-bit.

Returns:

  • (Integer)


259
260
261
# File 'lib/one_gadget/emulators/riscv64.rb', line 259

def bits
  64
end

Instance Method Details

#argument(idx) ⇒ Lambda, Integer

Return the argument value of calling a function.

Parameters:

  • idx (Integer)

    The 0-based index of the argument.

Returns:

  • (Lambda, Integer)

    The value held in register a<idx>, used for the +idx+-th argument.



93
94
95
# File 'lib/one_gadget/emulators/riscv64.rb', line 93

def argument(idx)
  registers["a#{idx}"]
end

#instructionsArray<Instruction>

Supported instruction set. Anything not listed aborts the candidate.

Returns:



74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
# File 'lib/one_gadget/emulators/riscv64.rb', line 74

def instructions
  [
    Instruction.new('add', 3),
    Instruction.new('addi', 3),
    Instruction.new('auipc', 2),
    Instruction.new('jal', 1..2),
    Instruction.new('li', 2),
    Instruction.new('lui', 2),
    Instruction.new('mv', 2),
    Instruction.new('nop', 0),
    Instruction.new('sub', 3),
    Instruction.new('not', 2)
  ] + (LOADS.keys + STORES.keys).map { |mnem| Instruction.new(mnem, 2) } +
    DATA_OPS.keys.map { |mnem| Instruction.new(mnem, 3) }
end

#process!(cmd) ⇒ Boolean

Returns If successfully processed.

Parameters:

  • cmd (String)

    One line from result of objdump.

Returns:

  • (Boolean)

    If successfully processed.

See Also:



22
23
24
25
26
27
28
29
30
31
# File 'lib/one_gadget/emulators/riscv64.rb', line 22

def process!(cmd)
  resolve_pending_branch(cmd)
  @cur_addr = cmd[/\A\s*([0-9a-f]+):/, 1]&.to_i(16)

  mnem = mnemonic(cmd)
  return handle_branch(mnem, cmd) != :fail if branch_mnem?(mnem)

  inst, args = parse(cmd)
  __send__(inst.handler, *args) != :fail
end