asmrepl 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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