Class: ASMREPL::REPL
Constant Summary collapse
- CFuncs =
Linux
Constants included from Fiddle
Instance Method Summary collapse
- #bold(string) ⇒ Object
- #display_state(state) ⇒ Object
- #display_state_change(last_state, state) ⇒ Object
-
#initialize ⇒ REPL
constructor
A new instance of REPL.
- #start ⇒ Object
Constructor Details
#initialize ⇒ REPL
Returns a new instance of REPL.
21 22 23 24 25 26 27 |
# File 'lib/asmrepl/repl.rb', line 21 def initialize size = 1024 * 16 # 16k is enough for anyone! @buffer = CFuncs.jitbuffer(size) CFuncs.memset(@buffer.memory, 0xCC, size) @parser = ASMREPL::Parser.new @assembler = ASMREPL::Assembler.new end |
Instance Method Details
#bold(string) ⇒ Object
60 61 62 |
# File 'lib/asmrepl/repl.rb', line 60 def bold string "\e[1m#{string}\e[0m" end |
#display_state(state) ⇒ Object
29 30 31 32 33 34 35 |
# File 'lib/asmrepl/repl.rb', line 29 def display_state state puts bold(" CPU STATE ".center(48, "=")) puts state puts puts "FLAGS: #{state.flags.inspect}" puts end |
#display_state_change(last_state, state) ⇒ Object
37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
# File 'lib/asmrepl/repl.rb', line 37 def display_state_change last_state, state puts bold(" REGISTER CHANGES ".center(48, "=")) show_flags = false state.fields.each do |field| next if field == "rip" if last_state[field] != state[field] print "#{field.ljust(6)} " print sprintf("%#018x", last_state[field]) print " => " puts bold(sprintf("%#018x", state[field])) end end if last_state.flags != state.flags puts puts "FLAGS: #{state.flags.inspect}" end puts end |
#start ⇒ Object
64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 |
# File 'lib/asmrepl/repl.rb', line 64 def start pid = fork { CFuncs.traceme @buffer.to_function([], TYPE_INT).call } tracer = CFuncs::Tracer.new pid should_cpu = true last_state = nil while tracer.wait state = tracer.state # Show CPU state once on boot if last_state.nil? display_state state last_state = state else display_state_change last_state, state last_state = state end # Move the JIT buffer to the current instruction pointer pos = (state.rip - @buffer.memory.to_i) @buffer.seek pos use_history = true begin loop do cmd = nil prompt = sprintf("(rip %#018x)> ", state.rip) text = Reline.readmultiline(prompt, use_history) do |multiline_input| if multiline_input =~ /\A\s*(\w+)\s*\Z/ register = $1 cmd = [:read, register] else cmd = :run end true end case cmd in :run break if text.chomp.empty? begin parser_result = @parser.parse text.chomp rescue puts "Invalid intruction" next end begin binary = @assembler.assemble parser_result binary.bytes.each { |byte| @buffer.putc byte } rescue Fisk::Errors::InvalidInstructionError => e # Print an error message when the instruction is invalid puts e. next end break in [:read, "cpu"] display_state state in [:read, reg] val = state[reg] if val puts sprintf("%#018x", state[reg]) else puts "Unknown command: " puts " " + text end else end end rescue Interrupt puts "" exit 0 end tracer.continue end end |