Class: OneGadget::Emulators::Mips

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

Overview

Emulator of MIPS (32-bit, o32).

Constant Summary collapse

COND =

This arch compares and branches in one instruction -- there is no flag register -- so each mnemonic names the relation its operands must stand in for the branch to be taken. The spellings against zero name one operand; zero is the other, and reads as the 0x0 it holds.

Returns:

  • (Hash{String => Symbol})
{
  'beq' => :eq, 'bne' => :ne,
  'beqz' => :eq, 'bnez' => :ne,
  'blez' => :sle, 'bgtz' => :sgt, 'bltz' => :slt, 'bgez' => :sge
}.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

#initializeMips

Instantiate a OneGadget::Emulators::Mips object.



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

def initialize
  super(OneGadget::ABI.mips, 'sp')
  @registers['zero'] = 0 # hardwired
  @pc = 'pc'
end

Class Method Details

.bitsInteger

o32 is 32-bit.

Returns:

  • (Integer)


283
284
285
# File 'lib/one_gadget/emulators/mips.rb', line 283

def bits
  32
end

Instance Method Details

#argument(idx) ⇒ Lambda, Integer

The value of a call's +idx+-th argument. o32 states the first four in registers, and reserves a stack slot for every argument including those -- so an argument's slot is its index however it is passed, and the ones past the registers are read from there.

Parameters:

  • idx (Integer)

    The 0-based index of the argument.

Returns:



74
75
76
77
78
79
# File 'lib/one_gadget/emulators/mips.rb', line 74

def argument(idx)
  return registers["a#{idx}"] if idx < ARG_REGISTERS

  top = registers['sp'].evaluate('sp' => 0)
  sp_based_stack[top + (idx * size_t)]
end

#instructionsArray<Instruction>

Supported instruction set. Anything not listed aborts the candidate.

Returns:



52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
# File 'lib/one_gadget/emulators/mips.rb', line 52

def instructions
  [
    Instruction.new('addiu', 3),
    Instruction.new('addu', 3),
    Instruction.new('bal', 1),
    Instruction.new('jal', 1),
    Instruction.new('jalr', 1..2),
    Instruction.new('li', 2),
    Instruction.new('lui', 2),
    Instruction.new('move', 2),
    Instruction.new('nop', 0),
    Instruction.new('subu', 3)
  ] + (LOADS.keys + STORES.keys).map { |mnem| Instruction.new(mnem, 2) } +
    DATA_OPS.keys.map { |mnem| Instruction.new(mnem, 3) }
end

#process!(cmd) ⇒ Boolean

Emulate one instruction, holding back any transfer of control.

This arch delays every transfer by one instruction: whatever follows a branch or a call runs before it takes effect. So a transfer is held back here and applied once that instruction has run, which is the order they really happen in -- and it leaves both addresses of the pair meaning what they say, since entering at the transfer runs both, while entering at the instruction after it runs only that one.

Parameters:

  • cmd (String)

    One line from result of objdump.

Returns:

  • (Boolean)

    If successfully processed.

See Also:



92
93
94
95
96
97
98
99
100
101
102
103
104
105
# File 'lib/one_gadget/emulators/mips.rb', line 92

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

  @got_value = cmd[GOT_VALUE, 1]&.to_i(16)

  mnem = mnemonic(cmd)
  if transfer?(mnem)
    @delayed = [mnem, cmd]
    return true
  end

  dispatch(cmd) && apply_delayed
end