asmrepl 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/CODE_OF_CONDUCT.md +78 -0
- data/Gemfile +3 -0
- data/LICENSE +201 -0
- data/README.md +83 -0
- data/Rakefile +23 -0
- data/asmrepl.gemspec +24 -0
- data/bin/asmrepl +5 -0
- data/lib/asmrepl/assembler.rb +49 -0
- data/lib/asmrepl/linux.rb +186 -0
- data/lib/asmrepl/macos.rb +205 -0
- data/lib/asmrepl/parser.rb +101 -0
- data/lib/asmrepl/parser.tab.rb +297 -0
- data/lib/asmrepl/parser.y +44 -0
- data/lib/asmrepl/repl.rb +105 -0
- data/lib/asmrepl/version.rb +3 -0
- data/lib/asmrepl.rb +3 -0
- data/test/asmrepl_test.rb +116 -0
- data/test/helper.rb +20 -0
- metadata +120 -0
@@ -0,0 +1,205 @@
|
|
1
|
+
require "fisk/helpers"
|
2
|
+
|
3
|
+
module ASMREPL
|
4
|
+
module MacOS
|
5
|
+
include Fiddle
|
6
|
+
|
7
|
+
def self.make_function name, args, ret
|
8
|
+
ptr = Handle::DEFAULT[name]
|
9
|
+
func = Function.new ptr, args, ret, name: name
|
10
|
+
define_singleton_method name, &func.to_proc
|
11
|
+
end
|
12
|
+
|
13
|
+
# from sys/mman.h on macOS
|
14
|
+
PROT_READ = 0x01
|
15
|
+
PROT_WRITE = 0x02
|
16
|
+
PROT_EXEC = 0x04
|
17
|
+
MAP_PRIVATE = 0x0002
|
18
|
+
MAP_SHARED = 0x0001
|
19
|
+
MAP_ANON = 0x1000
|
20
|
+
|
21
|
+
make_function "ptrace", [TYPE_INT, TYPE_INT, TYPE_VOIDP, TYPE_INT], TYPE_INT
|
22
|
+
make_function "memset", [TYPE_VOIDP, TYPE_INT, TYPE_SIZE_T], TYPE_VOID
|
23
|
+
make_function "strerror", [TYPE_INT], TYPE_CONST_STRING
|
24
|
+
make_function "mach_task_self", [], TYPE_VOIDP
|
25
|
+
make_function "task_threads", [TYPE_VOIDP, TYPE_VOIDP, TYPE_VOIDP], TYPE_VOIDP
|
26
|
+
make_function "task_for_pid", [TYPE_VOIDP, TYPE_INT, TYPE_VOIDP], TYPE_INT
|
27
|
+
make_function "task_threads", [TYPE_VOIDP, TYPE_VOIDP, TYPE_VOIDP], TYPE_INT
|
28
|
+
make_function "thread_get_state", [TYPE_VOIDP, TYPE_INT, TYPE_VOIDP, TYPE_VOIDP], TYPE_INT
|
29
|
+
make_function "mmap", [TYPE_VOIDP,
|
30
|
+
TYPE_SIZE_T,
|
31
|
+
TYPE_INT,
|
32
|
+
TYPE_INT,
|
33
|
+
TYPE_INT,
|
34
|
+
TYPE_INT], TYPE_VOIDP
|
35
|
+
|
36
|
+
def self.mmap_jit size
|
37
|
+
ptr = mmap 0, size, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_SHARED | MAP_ANON, -1, 0
|
38
|
+
ptr.size = size
|
39
|
+
ptr
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.jitbuffer size
|
43
|
+
Fisk::Helpers::JITBuffer.new mmap_jit(size), size
|
44
|
+
end
|
45
|
+
|
46
|
+
def self.traceme
|
47
|
+
raise unless ptrace(PT_TRACE_ME, 0, 0, 0).zero?
|
48
|
+
end
|
49
|
+
|
50
|
+
class ThreadState
|
51
|
+
fields = (<<-eostruct).scan(/uint64_t ([^;]*);/).flatten
|
52
|
+
struct x86_thread_state64_t {
|
53
|
+
uint64_t rax;
|
54
|
+
uint64_t rbx;
|
55
|
+
uint64_t rcx;
|
56
|
+
uint64_t rdx;
|
57
|
+
uint64_t rdi;
|
58
|
+
uint64_t rsi;
|
59
|
+
uint64_t rbp;
|
60
|
+
uint64_t rsp;
|
61
|
+
uint64_t r8;
|
62
|
+
uint64_t r9;
|
63
|
+
uint64_t r10;
|
64
|
+
uint64_t r11;
|
65
|
+
uint64_t r12;
|
66
|
+
uint64_t r13;
|
67
|
+
uint64_t r14;
|
68
|
+
uint64_t r15;
|
69
|
+
uint64_t rip;
|
70
|
+
uint64_t rflags;
|
71
|
+
uint64_t cs;
|
72
|
+
uint64_t fs;
|
73
|
+
uint64_t gs;
|
74
|
+
}
|
75
|
+
eostruct
|
76
|
+
fields.each_with_index do |field, i|
|
77
|
+
define_method(field) do
|
78
|
+
to_ptr[Fiddle::SIZEOF_INT64_T * i, Fiddle::SIZEOF_INT64_T].unpack1("l!")
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
define_singleton_method(:sizeof) do
|
83
|
+
fields.length * Fiddle::SIZEOF_INT64_T
|
84
|
+
end
|
85
|
+
|
86
|
+
def [] name
|
87
|
+
idx = fields.index(name)
|
88
|
+
return unless idx
|
89
|
+
to_ptr[Fiddle::SIZEOF_INT64_T * idx, Fiddle::SIZEOF_INT64_T].unpack1("l!")
|
90
|
+
end
|
91
|
+
|
92
|
+
def self.malloc
|
93
|
+
new Fiddle::Pointer.malloc sizeof
|
94
|
+
end
|
95
|
+
|
96
|
+
attr_reader :to_ptr
|
97
|
+
|
98
|
+
def initialize buffer
|
99
|
+
@to_ptr = buffer
|
100
|
+
end
|
101
|
+
|
102
|
+
define_method(:fields) do
|
103
|
+
fields
|
104
|
+
end
|
105
|
+
|
106
|
+
def to_s
|
107
|
+
buf = ""
|
108
|
+
fields.first(8).zip(fields.drop(8).first(8)).each do |l, r|
|
109
|
+
buf << "#{l.ljust(3)} #{sprintf("%#018x", send(l))}"
|
110
|
+
buf << " "
|
111
|
+
buf << "#{r.ljust(3)} #{sprintf("%#018x", send(r))}\n"
|
112
|
+
end
|
113
|
+
|
114
|
+
buf << "\n"
|
115
|
+
|
116
|
+
fields.drop(16).each do |reg|
|
117
|
+
buf << "#{reg.ljust(6)} #{sprintf("%#018x", send(reg))}\n"
|
118
|
+
end
|
119
|
+
buf
|
120
|
+
end
|
121
|
+
|
122
|
+
FLAGS = [
|
123
|
+
['CF', 'Carry Flag'],
|
124
|
+
[nil, 'Reserved'],
|
125
|
+
['PF', 'Parity Flag'],
|
126
|
+
[nil, 'Reserved'],
|
127
|
+
['AF', 'Adjust Flag'],
|
128
|
+
[nil, 'Reserved'],
|
129
|
+
['ZF', 'Zero Flag'],
|
130
|
+
['SF', 'Sign Flag'],
|
131
|
+
['TF', 'Trap Flag'],
|
132
|
+
['IF', 'Interrupt Enable Flag'],
|
133
|
+
['DF', 'Direction Flag'],
|
134
|
+
['OF', 'Overflow Flag'],
|
135
|
+
['IOPL_H', 'I/O privilege level High bit'],
|
136
|
+
['IOPL_L', 'I/O privilege level Low bit'],
|
137
|
+
['NT', 'Nested Task Flag'],
|
138
|
+
[nil, 'Reserved'],
|
139
|
+
]
|
140
|
+
|
141
|
+
def flags
|
142
|
+
flags = rflags
|
143
|
+
f = []
|
144
|
+
FLAGS.each do |abbrv, _|
|
145
|
+
if abbrv && flags & 1 == 1
|
146
|
+
f << abbrv
|
147
|
+
end
|
148
|
+
flags >>= 1
|
149
|
+
end
|
150
|
+
f
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
PT_TRACE_ME = 0
|
155
|
+
PT_CONTINUE = 7
|
156
|
+
|
157
|
+
class Tracer
|
158
|
+
def initialize pid
|
159
|
+
@pid = pid
|
160
|
+
@target = Fiddle::Pointer.malloc(Fiddle::SIZEOF_VOIDP)
|
161
|
+
|
162
|
+
unless MacOS.task_for_pid(MacOS.mach_task_self, pid, @target.ref).zero?
|
163
|
+
raise "Couldn't get task pid. Did you run with sudo?"
|
164
|
+
end
|
165
|
+
|
166
|
+
@thread_list = Fiddle::Pointer.malloc(Fiddle::SIZEOF_VOIDP)
|
167
|
+
thread_count = Fiddle::Pointer.malloc(Fiddle::SIZEOF_VOIDP)
|
168
|
+
|
169
|
+
raise unless MacOS.task_threads(@target, @thread_list.ref, thread_count).zero?
|
170
|
+
|
171
|
+
@thread = Fiddle::Pointer.new(@thread_list[0, Fiddle::SIZEOF_VOIDP].unpack1("l!"))
|
172
|
+
end
|
173
|
+
|
174
|
+
def wait
|
175
|
+
Process.waitpid @pid
|
176
|
+
end
|
177
|
+
|
178
|
+
def state
|
179
|
+
# Probably should use this for something
|
180
|
+
# count = thread_count[0]
|
181
|
+
|
182
|
+
# I can't remember what header I found this in, but it's from a macOS header
|
183
|
+
# :sweat-smile:
|
184
|
+
x86_THREAD_STATE64_COUNT = ThreadState.sizeof / Fiddle::SIZEOF_INT
|
185
|
+
|
186
|
+
# Same here
|
187
|
+
x86_THREAD_STATE64 = 4
|
188
|
+
|
189
|
+
state_count = Fiddle::Pointer.malloc(Fiddle::SIZEOF_INT64_T)
|
190
|
+
state_count[0, Fiddle::SIZEOF_INT64_T] = [x86_THREAD_STATE64_COUNT].pack("l!")
|
191
|
+
|
192
|
+
state = ThreadState.malloc
|
193
|
+
raise unless MacOS.thread_get_state(@thread, x86_THREAD_STATE64, state, state_count).zero?
|
194
|
+
|
195
|
+
state
|
196
|
+
end
|
197
|
+
|
198
|
+
def continue
|
199
|
+
unless MacOS.ptrace(MacOS::PT_CONTINUE, @pid, 1, 0).zero?
|
200
|
+
raise
|
201
|
+
end
|
202
|
+
end
|
203
|
+
end
|
204
|
+
end
|
205
|
+
end
|
@@ -0,0 +1,101 @@
|
|
1
|
+
require "racc/parser"
|
2
|
+
require "ripper"
|
3
|
+
require "fisk"
|
4
|
+
require "set"
|
5
|
+
require "strscan"
|
6
|
+
|
7
|
+
module ASMREPL
|
8
|
+
class Lexer
|
9
|
+
INTEGER = /(?:[-+]?0b[0-1_,]+ (?# base 2)
|
10
|
+
|[-+]?(?:0(?!x)|[1-9][0-9_,]*) (?# base 10)
|
11
|
+
|[-+]?0x[0-9a-fA-F_,]+ (?# base 16))/x
|
12
|
+
|
13
|
+
def initialize input
|
14
|
+
@input = input
|
15
|
+
@scanner = StringScanner.new input
|
16
|
+
end
|
17
|
+
|
18
|
+
REGISTERS = Set.new Fisk::Registers.constants.map(&:to_s)
|
19
|
+
INSTRUCTIONS = Set.new Fisk::Instructions.constants.map(&:to_s)
|
20
|
+
|
21
|
+
def next_token
|
22
|
+
return if @scanner.eos?
|
23
|
+
|
24
|
+
if @scanner.scan(INTEGER)
|
25
|
+
[:on_int, @scanner.matched]
|
26
|
+
elsif @scanner.scan(/\[/)
|
27
|
+
[:on_lbracket, @scanner.matched]
|
28
|
+
elsif @scanner.scan(/\]/)
|
29
|
+
[:on_rbracket, @scanner.matched]
|
30
|
+
elsif @scanner.scan(/,/)
|
31
|
+
[:on_comma, @scanner.matched]
|
32
|
+
elsif @scanner.scan(/qword/)
|
33
|
+
[:qword, @scanner.matched]
|
34
|
+
elsif @scanner.scan(/dword/)
|
35
|
+
[:dword, @scanner.matched]
|
36
|
+
elsif @scanner.scan(/word/)
|
37
|
+
[:word, @scanner.matched]
|
38
|
+
elsif @scanner.scan(/byte/)
|
39
|
+
[:byte, @scanner.matched]
|
40
|
+
elsif @scanner.scan(/ptr/)
|
41
|
+
[:ptr, @scanner.matched]
|
42
|
+
elsif @scanner.scan(/rip/i)
|
43
|
+
[:on_rip, @scanner.matched]
|
44
|
+
elsif @scanner.scan(/int/i)
|
45
|
+
[:on_instruction, Fisk::Instructions::INT]
|
46
|
+
elsif @scanner.scan(/movabs/i)
|
47
|
+
[:on_instruction, Fisk::Instructions::MOV]
|
48
|
+
elsif @scanner.scan(/\w+/)
|
49
|
+
ident = @scanner.matched
|
50
|
+
if INSTRUCTIONS.include?(ident.upcase)
|
51
|
+
[:on_instruction, Fisk::Instructions.const_get(ident.upcase)]
|
52
|
+
elsif REGISTERS.include?(ident.upcase)
|
53
|
+
[:on_register, Fisk::Registers.const_get(ident.upcase)]
|
54
|
+
else
|
55
|
+
[:on_ident, @scanner.matched]
|
56
|
+
end
|
57
|
+
elsif @scanner.scan(/\s+/)
|
58
|
+
[:on_sp, @scanner.matched]
|
59
|
+
elsif @scanner.scan(/\+/)
|
60
|
+
[:plus, @scanner.matched]
|
61
|
+
elsif @scanner.scan(/-/)
|
62
|
+
[:minus, @scanner.matched]
|
63
|
+
else
|
64
|
+
raise
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
class Parser < Racc::Parser
|
70
|
+
def initialize
|
71
|
+
@registers = Set.new Fisk::Registers.constants.map(&:to_s)
|
72
|
+
@instructions = Set.new Fisk::Instructions.constants.map(&:to_s)
|
73
|
+
end
|
74
|
+
|
75
|
+
def parse input
|
76
|
+
@lexer = Lexer.new input
|
77
|
+
do_parse
|
78
|
+
end
|
79
|
+
|
80
|
+
def new_command mnemonic, arg1, arg2
|
81
|
+
[:command, mnemonic, arg1, arg2]
|
82
|
+
end
|
83
|
+
|
84
|
+
def new_tuple mnemonic, arg1
|
85
|
+
[:command, mnemonic, arg1]
|
86
|
+
end
|
87
|
+
|
88
|
+
def new_single mnemonic
|
89
|
+
[:command, mnemonic]
|
90
|
+
end
|
91
|
+
|
92
|
+
def next_token
|
93
|
+
while tok = @lexer.next_token
|
94
|
+
next if tok.first == :on_sp
|
95
|
+
return tok
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
require "asmrepl/parser.tab"
|
@@ -0,0 +1,297 @@
|
|
1
|
+
#
|
2
|
+
# DO NOT MODIFY!!!!
|
3
|
+
# This file is automatically generated by Racc 1.5.1
|
4
|
+
# from Racc grammar file "".
|
5
|
+
#
|
6
|
+
|
7
|
+
require 'racc/parser.rb'
|
8
|
+
module ASMREPL
|
9
|
+
class Parser < Racc::Parser
|
10
|
+
##### State transition tables begin ###
|
11
|
+
|
12
|
+
racc_action_table = [
|
13
|
+
12, 3, 9, 4, 14, 18, 16, 15, 17, 10,
|
14
|
+
11, 12, 8, 9, 19, 14, 20, 16, 15, 17,
|
15
|
+
10, 11, 9, 8, 21, 35, 9, 37, 9, 10,
|
16
|
+
11, 22, 8, 10, 11, 10, 11, 43, 9, 45,
|
17
|
+
9, 8, 24, 8, 39, 10, 11, 10, 11, 25,
|
18
|
+
26, 27, 28, 29, 41, 42, 47, 48 ]
|
19
|
+
|
20
|
+
racc_action_check = [
|
21
|
+
2, 0, 2, 1, 2, 4, 2, 2, 2, 2,
|
22
|
+
2, 19, 2, 19, 5, 19, 6, 19, 19, 19,
|
23
|
+
19, 19, 20, 19, 10, 23, 23, 24, 24, 20,
|
24
|
+
20, 11, 20, 23, 23, 24, 24, 39, 39, 40,
|
25
|
+
40, 12, 12, 25, 25, 39, 39, 40, 40, 13,
|
26
|
+
14, 15, 16, 17, 36, 38, 44, 46 ]
|
27
|
+
|
28
|
+
racc_action_pointer = [
|
29
|
+
-12, 3, -2, nil, 5, 9, 11, nil, nil, nil,
|
30
|
+
20, 27, 27, 47, 43, 44, 45, 46, nil, 9,
|
31
|
+
18, nil, nil, 22, 24, 29, nil, nil, nil, nil,
|
32
|
+
nil, nil, nil, nil, nil, nil, 51, nil, 52, 34,
|
33
|
+
36, nil, nil, nil, 53, nil, 54, nil, nil ]
|
34
|
+
|
35
|
+
racc_action_default = [
|
36
|
+
-27, -27, -9, -10, -27, -6, -7, -8, -11, -12,
|
37
|
+
-27, -27, -27, -27, -27, -27, -27, -27, 49, -27,
|
38
|
+
-27, -13, -14, -27, -27, -27, -23, -24, -25, -26,
|
39
|
+
-1, -2, -3, -4, -5, -15, -27, -16, -27, -27,
|
40
|
+
-27, -20, -17, -18, -27, -21, -27, -19, -22 ]
|
41
|
+
|
42
|
+
racc_goto_table = [
|
43
|
+
7, 1, 5, 2, nil, nil, 6, nil, nil, nil,
|
44
|
+
nil, nil, 23, nil, nil, nil, nil, 30, 34, 31,
|
45
|
+
33, 36, 38, 32, nil, 40, nil, nil, nil, nil,
|
46
|
+
nil, nil, nil, nil, nil, nil, nil, 44, 46 ]
|
47
|
+
|
48
|
+
racc_goto_check = [
|
49
|
+
4, 1, 3, 2, nil, nil, 5, nil, nil, nil,
|
50
|
+
nil, nil, 3, nil, nil, nil, nil, 4, 4, 3,
|
51
|
+
3, 4, 4, 5, nil, 3, nil, nil, nil, nil,
|
52
|
+
nil, nil, nil, nil, nil, nil, nil, 4, 4 ]
|
53
|
+
|
54
|
+
racc_goto_pointer = [
|
55
|
+
nil, 1, 3, 0, -2, 4, nil ]
|
56
|
+
|
57
|
+
racc_goto_default = [
|
58
|
+
nil, nil, nil, nil, nil, nil, 13 ]
|
59
|
+
|
60
|
+
racc_reduce_table = [
|
61
|
+
0, 0, :racc_error,
|
62
|
+
4, 17, :_reduce_1,
|
63
|
+
4, 17, :_reduce_2,
|
64
|
+
4, 17, :_reduce_3,
|
65
|
+
4, 17, :_reduce_4,
|
66
|
+
4, 17, :_reduce_5,
|
67
|
+
2, 17, :_reduce_6,
|
68
|
+
2, 17, :_reduce_7,
|
69
|
+
2, 17, :_reduce_8,
|
70
|
+
1, 17, :_reduce_9,
|
71
|
+
1, 18, :_reduce_10,
|
72
|
+
1, 19, :_reduce_11,
|
73
|
+
1, 20, :_reduce_12,
|
74
|
+
2, 20, :_reduce_13,
|
75
|
+
2, 20, :_reduce_14,
|
76
|
+
3, 21, :_reduce_15,
|
77
|
+
3, 21, :_reduce_16,
|
78
|
+
4, 21, :_reduce_17,
|
79
|
+
4, 21, :_reduce_18,
|
80
|
+
5, 21, :_reduce_19,
|
81
|
+
4, 21, :_reduce_20,
|
82
|
+
4, 21, :_reduce_21,
|
83
|
+
5, 21, :_reduce_22,
|
84
|
+
2, 22, :_reduce_23,
|
85
|
+
2, 22, :_reduce_24,
|
86
|
+
2, 22, :_reduce_25,
|
87
|
+
2, 22, :_reduce_26 ]
|
88
|
+
|
89
|
+
racc_reduce_n = 27
|
90
|
+
|
91
|
+
racc_shift_n = 49
|
92
|
+
|
93
|
+
racc_token_table = {
|
94
|
+
false => 0,
|
95
|
+
:error => 1,
|
96
|
+
:on_lbracket => 2,
|
97
|
+
:on_rbracket => 3,
|
98
|
+
:on_int => 4,
|
99
|
+
:on_comma => 5,
|
100
|
+
:qword => 6,
|
101
|
+
:ptr => 7,
|
102
|
+
:word => 8,
|
103
|
+
:dword => 9,
|
104
|
+
:byte => 10,
|
105
|
+
:plus => 11,
|
106
|
+
:minus => 12,
|
107
|
+
:on_instruction => 13,
|
108
|
+
:on_register => 14,
|
109
|
+
:on_rip => 15 }
|
110
|
+
|
111
|
+
racc_nt_base = 16
|
112
|
+
|
113
|
+
racc_use_result_var = true
|
114
|
+
|
115
|
+
Racc_arg = [
|
116
|
+
racc_action_table,
|
117
|
+
racc_action_check,
|
118
|
+
racc_action_default,
|
119
|
+
racc_action_pointer,
|
120
|
+
racc_goto_table,
|
121
|
+
racc_goto_check,
|
122
|
+
racc_goto_default,
|
123
|
+
racc_goto_pointer,
|
124
|
+
racc_nt_base,
|
125
|
+
racc_reduce_table,
|
126
|
+
racc_token_table,
|
127
|
+
racc_shift_n,
|
128
|
+
racc_reduce_n,
|
129
|
+
racc_use_result_var ]
|
130
|
+
|
131
|
+
Racc_token_to_s_table = [
|
132
|
+
"$end",
|
133
|
+
"error",
|
134
|
+
"on_lbracket",
|
135
|
+
"on_rbracket",
|
136
|
+
"on_int",
|
137
|
+
"on_comma",
|
138
|
+
"qword",
|
139
|
+
"ptr",
|
140
|
+
"word",
|
141
|
+
"dword",
|
142
|
+
"byte",
|
143
|
+
"plus",
|
144
|
+
"minus",
|
145
|
+
"on_instruction",
|
146
|
+
"on_register",
|
147
|
+
"on_rip",
|
148
|
+
"$start",
|
149
|
+
"command",
|
150
|
+
"instruction",
|
151
|
+
"register",
|
152
|
+
"int",
|
153
|
+
"memory",
|
154
|
+
"memsize" ]
|
155
|
+
|
156
|
+
Racc_debug_parser = false
|
157
|
+
|
158
|
+
##### State transition tables end #####
|
159
|
+
|
160
|
+
# reduce 0 omitted
|
161
|
+
|
162
|
+
def _reduce_1(val, _values, result)
|
163
|
+
result = new_command(val[0], val[1], val[3])
|
164
|
+
result
|
165
|
+
end
|
166
|
+
|
167
|
+
def _reduce_2(val, _values, result)
|
168
|
+
result = new_command(val[0], val[1], val[3])
|
169
|
+
result
|
170
|
+
end
|
171
|
+
|
172
|
+
def _reduce_3(val, _values, result)
|
173
|
+
result = new_command(val[0], val[1], val[3])
|
174
|
+
result
|
175
|
+
end
|
176
|
+
|
177
|
+
def _reduce_4(val, _values, result)
|
178
|
+
result = new_command(val[0], val[1], val[3])
|
179
|
+
result
|
180
|
+
end
|
181
|
+
|
182
|
+
def _reduce_5(val, _values, result)
|
183
|
+
result = new_command(val[0], val[1], val[3])
|
184
|
+
result
|
185
|
+
end
|
186
|
+
|
187
|
+
def _reduce_6(val, _values, result)
|
188
|
+
result = new_tuple(val[0], val[1])
|
189
|
+
result
|
190
|
+
end
|
191
|
+
|
192
|
+
def _reduce_7(val, _values, result)
|
193
|
+
result = new_tuple(val[0], val[1])
|
194
|
+
result
|
195
|
+
end
|
196
|
+
|
197
|
+
def _reduce_8(val, _values, result)
|
198
|
+
result = new_tuple(val[0], val[1])
|
199
|
+
result
|
200
|
+
end
|
201
|
+
|
202
|
+
def _reduce_9(val, _values, result)
|
203
|
+
result = new_single(val[0])
|
204
|
+
result
|
205
|
+
end
|
206
|
+
|
207
|
+
def _reduce_10(val, _values, result)
|
208
|
+
result = [:instruction, val[0]]
|
209
|
+
result
|
210
|
+
end
|
211
|
+
|
212
|
+
def _reduce_11(val, _values, result)
|
213
|
+
result = [:register, val[0]]
|
214
|
+
result
|
215
|
+
end
|
216
|
+
|
217
|
+
def _reduce_12(val, _values, result)
|
218
|
+
result = [:int, Integer(val[0])]
|
219
|
+
result
|
220
|
+
end
|
221
|
+
|
222
|
+
def _reduce_13(val, _values, result)
|
223
|
+
result = [:int, Integer(val[1])]
|
224
|
+
result
|
225
|
+
end
|
226
|
+
|
227
|
+
def _reduce_14(val, _values, result)
|
228
|
+
result = [:int, -Integer(val[1])]
|
229
|
+
result
|
230
|
+
end
|
231
|
+
|
232
|
+
def _reduce_15(val, _values, result)
|
233
|
+
result = [:memory, Fisk::M64.new(val[1].last, 0)]
|
234
|
+
result
|
235
|
+
end
|
236
|
+
|
237
|
+
def _reduce_16(val, _values, result)
|
238
|
+
result = [:memory, Fisk::Registers::Rip.new(0)]
|
239
|
+
result
|
240
|
+
end
|
241
|
+
|
242
|
+
def _reduce_17(val, _values, result)
|
243
|
+
result = [:memory, Fisk::Registers::Rip.new(val[2].last)]
|
244
|
+
result
|
245
|
+
end
|
246
|
+
|
247
|
+
def _reduce_18(val, _values, result)
|
248
|
+
result = [:memory, Fisk::Registers::Rip.new(0)]
|
249
|
+
result
|
250
|
+
end
|
251
|
+
|
252
|
+
def _reduce_19(val, _values, result)
|
253
|
+
result = [:memory, Fisk::Registers::Rip.new(val[3].last)]
|
254
|
+
result
|
255
|
+
end
|
256
|
+
|
257
|
+
def _reduce_20(val, _values, result)
|
258
|
+
result = [:memory, Fisk::M64.new(val[1].last, val[2].last)]
|
259
|
+
result
|
260
|
+
end
|
261
|
+
|
262
|
+
def _reduce_21(val, _values, result)
|
263
|
+
result = [:memory, val[0].new(val[2].last, 0)]
|
264
|
+
result
|
265
|
+
end
|
266
|
+
|
267
|
+
def _reduce_22(val, _values, result)
|
268
|
+
result = [:memory, val[0].new(val[2].last, val[3].last)]
|
269
|
+
result
|
270
|
+
end
|
271
|
+
|
272
|
+
def _reduce_23(val, _values, result)
|
273
|
+
result = Fisk::M64
|
274
|
+
result
|
275
|
+
end
|
276
|
+
|
277
|
+
def _reduce_24(val, _values, result)
|
278
|
+
result = Fisk::M32
|
279
|
+
result
|
280
|
+
end
|
281
|
+
|
282
|
+
def _reduce_25(val, _values, result)
|
283
|
+
result = Fisk::M16
|
284
|
+
result
|
285
|
+
end
|
286
|
+
|
287
|
+
def _reduce_26(val, _values, result)
|
288
|
+
result = Fisk::M8
|
289
|
+
result
|
290
|
+
end
|
291
|
+
|
292
|
+
def _reduce_none(val, _values, result)
|
293
|
+
val[0]
|
294
|
+
end
|
295
|
+
|
296
|
+
end # class Parser
|
297
|
+
end # module ASMREPL
|
@@ -0,0 +1,44 @@
|
|
1
|
+
class ASMREPL::Parser
|
2
|
+
token on_lbracket on_rbracket on_int on_comma qword ptr word dword byte
|
3
|
+
token plus minus on_instruction on_register on_rip
|
4
|
+
|
5
|
+
rule
|
6
|
+
|
7
|
+
command: instruction register on_comma int { result = new_command(val[0], val[1], val[3]) }
|
8
|
+
| instruction register on_comma register { result = new_command(val[0], val[1], val[3]) }
|
9
|
+
| instruction register on_comma memory { result = new_command(val[0], val[1], val[3]) }
|
10
|
+
| instruction memory on_comma register { result = new_command(val[0], val[1], val[3]) }
|
11
|
+
| instruction memory on_comma int { result = new_command(val[0], val[1], val[3]) }
|
12
|
+
| instruction register { result = new_tuple(val[0], val[1]) }
|
13
|
+
| instruction memory { result = new_tuple(val[0], val[1]) }
|
14
|
+
| instruction int { result = new_tuple(val[0], val[1]) }
|
15
|
+
| instruction { result = new_single(val[0]) }
|
16
|
+
;
|
17
|
+
|
18
|
+
instruction: on_instruction { result = [:instruction, val[0]] }
|
19
|
+
;
|
20
|
+
|
21
|
+
register: on_register { result = [:register, val[0]] }
|
22
|
+
;
|
23
|
+
|
24
|
+
int: on_int { result = [:int, Integer(val[0])] }
|
25
|
+
| plus on_int { result = [:int, Integer(val[1])] }
|
26
|
+
| minus on_int { result = [:int, -Integer(val[1])] }
|
27
|
+
;
|
28
|
+
|
29
|
+
memory: on_lbracket register on_rbracket { result = [:memory, Fisk::M64.new(val[1].last, 0)] }
|
30
|
+
| on_lbracket on_rip on_rbracket { result = [:memory, Fisk::Registers::Rip.new(0)] }
|
31
|
+
| on_lbracket on_rip int on_rbracket { result = [:memory, Fisk::Registers::Rip.new(val[2].last)] }
|
32
|
+
| memsize on_lbracket on_rip on_rbracket { result = [:memory, Fisk::Registers::Rip.new(0)] }
|
33
|
+
| memsize on_lbracket on_rip int on_rbracket { result = [:memory, Fisk::Registers::Rip.new(val[3].last)] }
|
34
|
+
| on_lbracket register int on_rbracket { result = [:memory, Fisk::M64.new(val[1].last, val[2].last)] }
|
35
|
+
| memsize on_lbracket register on_rbracket { result = [:memory, val[0].new(val[2].last, 0)] }
|
36
|
+
| memsize on_lbracket register int on_rbracket { result = [:memory, val[0].new(val[2].last, val[3].last)] }
|
37
|
+
;
|
38
|
+
|
39
|
+
memsize: qword ptr { result = Fisk::M64 }
|
40
|
+
| dword ptr { result = Fisk::M32 }
|
41
|
+
| word ptr { result = Fisk::M16 }
|
42
|
+
| byte ptr { result = Fisk::M8 }
|
43
|
+
;
|
44
|
+
end
|