Class: ASMREPL::REPL

Inherits:
Object
  • Object
show all
Includes:
Fiddle
Defined in:
lib/asmrepl/repl.rb

Constant Summary collapse

CFuncs =
Linux

Instance Method Summary collapse

Constructor Details

#initializeREPL

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

#display_state(state) ⇒ Object



29
30
31
32
33
34
35
# File 'lib/asmrepl/repl.rb', line 29

def display_state state
  puts " CPU STATE ".center(48, "=")
  puts state
  puts
  puts "FLAGS: #{state.flags.inspect}"
  puts
end

#startObject



37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
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
# File 'lib/asmrepl/repl.rb', line 37

def start
  pid = fork {
    CFuncs.traceme
    @buffer.to_function([], TYPE_INT).call
  }

  tracer = CFuncs::Tracer.new pid
  should_cpu = true
  while tracer.wait
    state = tracer.state

    # Show CPU state once on boot
    if should_cpu
      display_state state
      should_cpu = false
    end

    # Move the JIT buffer to the current instruction pointer
    pos = (state.rip - @buffer.memory.to_i)
    @buffer.seek pos
    use_history = true
    loop do
      cmd = nil
      text = Reline.readmultiline(">> ", 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?
        binary = @assembler.assemble @parser.parse text.chomp
        binary.bytes.each { |byte| @buffer.putc byte }
        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
    tracer.continue
  end
end