evoasm 0.0.2.pre7
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.
- checksums.yaml +7 -0
- data/.gemrelease +2 -0
- data/.gitignore +16 -0
- data/Gemfile +4 -0
- data/Gemfile.rake +8 -0
- data/Gemfile.rake.lock +51 -0
- data/LICENSE.txt +373 -0
- data/Makefile +6 -0
- data/README.md +43 -0
- data/Rakefile +128 -0
- data/bin/gdb +2 -0
- data/data/tables/README.md +19 -0
- data/data/tables/x64.csv +1684 -0
- data/data/templates/evoasm-x64.c.erb +319 -0
- data/data/templates/evoasm-x64.h.erb +126 -0
- data/evoasm.gemspec +30 -0
- data/examples/abs.yml +20 -0
- data/examples/popcnt.yml +17 -0
- data/examples/sym_reg.yml +26 -0
- data/exe/evoasm-search +13 -0
- data/ext/evoasm_ext/evoasm-alloc.c +145 -0
- data/ext/evoasm_ext/evoasm-alloc.h +59 -0
- data/ext/evoasm_ext/evoasm-arch.c +44 -0
- data/ext/evoasm_ext/evoasm-arch.h +161 -0
- data/ext/evoasm_ext/evoasm-bitmap.h +114 -0
- data/ext/evoasm_ext/evoasm-buf.c +130 -0
- data/ext/evoasm_ext/evoasm-buf.h +47 -0
- data/ext/evoasm_ext/evoasm-error.c +31 -0
- data/ext/evoasm_ext/evoasm-error.h +75 -0
- data/ext/evoasm_ext/evoasm-free-list.c.tmpl +121 -0
- data/ext/evoasm_ext/evoasm-free-list.h.tmpl +86 -0
- data/ext/evoasm_ext/evoasm-log.c +108 -0
- data/ext/evoasm_ext/evoasm-log.h +69 -0
- data/ext/evoasm_ext/evoasm-misc.c +23 -0
- data/ext/evoasm_ext/evoasm-misc.h +282 -0
- data/ext/evoasm_ext/evoasm-param.h +37 -0
- data/ext/evoasm_ext/evoasm-search.c +2145 -0
- data/ext/evoasm_ext/evoasm-search.h +214 -0
- data/ext/evoasm_ext/evoasm-util.h +40 -0
- data/ext/evoasm_ext/evoasm-x64.c +275624 -0
- data/ext/evoasm_ext/evoasm-x64.h +5436 -0
- data/ext/evoasm_ext/evoasm.c +7 -0
- data/ext/evoasm_ext/evoasm.h +23 -0
- data/ext/evoasm_ext/evoasm_ext.c +1757 -0
- data/ext/evoasm_ext/extconf.rb +31 -0
- data/lib/evoasm/cli/search.rb +127 -0
- data/lib/evoasm/cli.rb +6 -0
- data/lib/evoasm/core_ext/array.rb +9 -0
- data/lib/evoasm/core_ext/integer.rb +10 -0
- data/lib/evoasm/core_ext/kwstruct.rb +13 -0
- data/lib/evoasm/core_ext/range.rb +5 -0
- data/lib/evoasm/core_ext.rb +1 -0
- data/lib/evoasm/error.rb +20 -0
- data/lib/evoasm/examples.rb +27 -0
- data/lib/evoasm/gen/enum.rb +169 -0
- data/lib/evoasm/gen/name_util.rb +80 -0
- data/lib/evoasm/gen/state.rb +176 -0
- data/lib/evoasm/gen/state_dsl.rb +152 -0
- data/lib/evoasm/gen/strio.rb +27 -0
- data/lib/evoasm/gen/translator.rb +1102 -0
- data/lib/evoasm/gen/version.rb +5 -0
- data/lib/evoasm/gen/x64/funcs.rb +495 -0
- data/lib/evoasm/gen/x64/inst.rb +781 -0
- data/lib/evoasm/gen/x64.rb +237 -0
- data/lib/evoasm/gen.rb +8 -0
- data/lib/evoasm/program.rb +23 -0
- data/lib/evoasm/search.rb +40 -0
- data/lib/evoasm/tasks/gen_task.rb +86 -0
- data/lib/evoasm/tasks/template_task.rb +52 -0
- data/lib/evoasm/version.rb +3 -0
- data/lib/evoasm.rb +22 -0
- data/test/test_helper.rb +1 -0
- data/test/x64/test_helper.rb +19 -0
- data/test/x64/x64_test.rb +87 -0
- metadata +221 -0
@@ -0,0 +1,1757 @@
|
|
1
|
+
#include <ruby.h>
|
2
|
+
|
3
|
+
static VALUE mEvoasm;
|
4
|
+
static VALUE cX64;
|
5
|
+
VALUE evoasm_cX64Instruction;
|
6
|
+
static VALUE cInstruction;
|
7
|
+
static VALUE cParameters;
|
8
|
+
static VALUE cX64Parameters;
|
9
|
+
static VALUE cParameter;
|
10
|
+
static VALUE cRegister;
|
11
|
+
static VALUE cX64Register;
|
12
|
+
static VALUE cOperand;
|
13
|
+
static VALUE cX64Operand;
|
14
|
+
static VALUE cArchitecture;
|
15
|
+
static VALUE cBuffer;
|
16
|
+
static VALUE cSearch;
|
17
|
+
static VALUE cProgram;
|
18
|
+
static VALUE cKernel;
|
19
|
+
static VALUE eError;
|
20
|
+
static VALUE eArchitectureError;
|
21
|
+
|
22
|
+
static VALUE domains_cache;
|
23
|
+
static VALUE instructions_cache;
|
24
|
+
|
25
|
+
static ID rb_id_brute_force;
|
26
|
+
static ID rb_id_genetic;
|
27
|
+
static ID rb_id_id;
|
28
|
+
|
29
|
+
#include "evoasm-x64.h"
|
30
|
+
#include "evoasm-buf.h"
|
31
|
+
#include "evoasm-search.h"
|
32
|
+
|
33
|
+
void evoasm_raise_last_error();
|
34
|
+
|
35
|
+
static void
|
36
|
+
buf_free(void *p) {
|
37
|
+
evoasm_buf *buf = (evoasm_buf *)p;
|
38
|
+
EVOASM_TRY(raise, evoasm_buf_destroy, buf);
|
39
|
+
xfree(p);
|
40
|
+
return;
|
41
|
+
|
42
|
+
raise:
|
43
|
+
xfree(p);
|
44
|
+
evoasm_raise_last_error();
|
45
|
+
}
|
46
|
+
|
47
|
+
static const rb_data_type_t rb_buf_type = {
|
48
|
+
"Evoasm::Buffer",
|
49
|
+
{NULL, buf_free, NULL,},
|
50
|
+
NULL, NULL,
|
51
|
+
RUBY_TYPED_FREE_IMMEDIATELY,
|
52
|
+
};
|
53
|
+
|
54
|
+
static void
|
55
|
+
x64_free(void *p) {
|
56
|
+
evoasm_x64 *x64 = (evoasm_x64 *) p;
|
57
|
+
evoasm_x64_destroy(x64);
|
58
|
+
xfree(p);
|
59
|
+
}
|
60
|
+
|
61
|
+
static void
|
62
|
+
x64_mark(void *p) {
|
63
|
+
evoasm_x64 *x64 = (evoasm_x64 *) p;
|
64
|
+
(void) x64;
|
65
|
+
}
|
66
|
+
|
67
|
+
static const rb_data_type_t rb_arch_type = {
|
68
|
+
"Evoasm::Architecture",
|
69
|
+
{NULL, NULL, NULL,},
|
70
|
+
NULL, NULL,
|
71
|
+
RUBY_TYPED_FREE_IMMEDIATELY,
|
72
|
+
};
|
73
|
+
|
74
|
+
static const rb_data_type_t rb_x64_type = {
|
75
|
+
"Evoasm::X64",
|
76
|
+
{x64_mark, x64_free, NULL,},
|
77
|
+
&rb_arch_type, NULL,
|
78
|
+
RUBY_TYPED_FREE_IMMEDIATELY,
|
79
|
+
};
|
80
|
+
|
81
|
+
static VALUE
|
82
|
+
rb_buffer_alloc(VALUE klass) {
|
83
|
+
evoasm_buf *buf = ALLOC(evoasm_buf);
|
84
|
+
|
85
|
+
return TypedData_Wrap_Struct(klass, &rb_buf_type, buf);
|
86
|
+
}
|
87
|
+
|
88
|
+
static VALUE
|
89
|
+
rb_buffer_initialize(int argc, VALUE *argv, VALUE self) {
|
90
|
+
evoasm_buf *buf;
|
91
|
+
VALUE rb_size;
|
92
|
+
VALUE rb_malloc = Qtrue;
|
93
|
+
|
94
|
+
TypedData_Get_Struct(self, evoasm_buf, &rb_buf_type, buf);
|
95
|
+
|
96
|
+
rb_scan_args(argc, argv, "11", &rb_size, &rb_malloc);
|
97
|
+
|
98
|
+
EVOASM_TRY(failed, evoasm_buf_init, buf,
|
99
|
+
RTEST(rb_malloc) ? EVOASM_BUF_TYPE_MALLOC : EVOASM_BUF_TYPE_MMAP, NUM2SIZET(rb_size));
|
100
|
+
|
101
|
+
return self;
|
102
|
+
|
103
|
+
failed:
|
104
|
+
return Qnil;
|
105
|
+
}
|
106
|
+
|
107
|
+
#ifdef HAVE_CAPSTONE_CAPSTONE_H
|
108
|
+
#include <capstone/capstone.h>
|
109
|
+
|
110
|
+
static VALUE
|
111
|
+
x64_disassemble(unsigned char *data, size_t len, bool addr) {
|
112
|
+
csh handle;
|
113
|
+
cs_insn *insn;
|
114
|
+
size_t count;
|
115
|
+
VALUE rb_result;
|
116
|
+
|
117
|
+
/* FIXME: check arch */
|
118
|
+
if(cs_open(CS_ARCH_X86, CS_MODE_64, &handle) != CS_ERR_OK) {
|
119
|
+
return Qnil;
|
120
|
+
}
|
121
|
+
|
122
|
+
count = cs_disasm(handle, data, len, (uintptr_t) data, 0, &insn);
|
123
|
+
rb_result = rb_ary_new2((long) count);
|
124
|
+
if(count > 0) {
|
125
|
+
size_t j;
|
126
|
+
|
127
|
+
for(j = 0; j < count; j++) {
|
128
|
+
VALUE line;
|
129
|
+
if(addr) {
|
130
|
+
line = rb_sprintf("0x%"PRIx64": %s %s", insn[j].address, insn[j].mnemonic, insn[j].op_str);
|
131
|
+
} else {
|
132
|
+
line = rb_sprintf("%s %s", insn[j].mnemonic, insn[j].op_str);
|
133
|
+
}
|
134
|
+
rb_ary_push(rb_result, line);
|
135
|
+
}
|
136
|
+
cs_free(insn, count);
|
137
|
+
}
|
138
|
+
|
139
|
+
cs_close(&handle);
|
140
|
+
return rb_result;
|
141
|
+
}
|
142
|
+
|
143
|
+
static VALUE
|
144
|
+
rb_buffer_disassemble(VALUE self) {
|
145
|
+
evoasm_buf *buf;
|
146
|
+
TypedData_Get_Struct(self, evoasm_buf, &rb_buf_type, buf);
|
147
|
+
|
148
|
+
return x64_disassemble(buf->data, buf->pos, true);
|
149
|
+
}
|
150
|
+
|
151
|
+
static VALUE
|
152
|
+
rb_x64_s_disassemble(VALUE self, VALUE as_str) {
|
153
|
+
unsigned char *data = (unsigned char *) RSTRING_PTR(as_str);
|
154
|
+
size_t len = (size_t)RSTRING_LEN(as_str);
|
155
|
+
|
156
|
+
return x64_disassemble(data, len, false);
|
157
|
+
}
|
158
|
+
#endif
|
159
|
+
|
160
|
+
static VALUE
|
161
|
+
rb_buffer_size(VALUE self) {
|
162
|
+
evoasm_buf *buf;
|
163
|
+
TypedData_Get_Struct(self, evoasm_buf, &rb_buf_type, buf);
|
164
|
+
|
165
|
+
return SIZET2NUM(buf->capa);
|
166
|
+
}
|
167
|
+
|
168
|
+
static VALUE
|
169
|
+
rb_buffer_reset(VALUE self) {
|
170
|
+
evoasm_buf *buf;
|
171
|
+
TypedData_Get_Struct(self, evoasm_buf, &rb_buf_type, buf);
|
172
|
+
|
173
|
+
evoasm_buf_reset(buf);
|
174
|
+
|
175
|
+
return Qnil;
|
176
|
+
}
|
177
|
+
|
178
|
+
static VALUE
|
179
|
+
rb_buffer_to_s(VALUE self) {
|
180
|
+
evoasm_buf *buf;
|
181
|
+
TypedData_Get_Struct(self, evoasm_buf, &rb_buf_type, buf);
|
182
|
+
|
183
|
+
return rb_usascii_str_new((char *)buf->data, (long) buf->pos);
|
184
|
+
}
|
185
|
+
|
186
|
+
#if 0
|
187
|
+
static VALUE
|
188
|
+
rb_buffer_protect(VALUE self, evoasm_buf_prot mode) {
|
189
|
+
evoasm_buf *buf;
|
190
|
+
|
191
|
+
TypedData_Get_Struct(self, evoasm_buf, &rb_buf_type, buf);
|
192
|
+
return evoasm_buf_protect(buf, mode) ? Qtrue : Qfalse;
|
193
|
+
}
|
194
|
+
|
195
|
+
static VALUE
|
196
|
+
rb_buffer_rx(VALUE self) {
|
197
|
+
return rb_buffer_protect(self, EVOASM_BUF_PROT_RX);
|
198
|
+
}
|
199
|
+
|
200
|
+
static VALUE
|
201
|
+
rb_buffer_rw(VALUE self) {
|
202
|
+
return rb_buffer_protect(self, EVOASM_BUF_PROT_RW);
|
203
|
+
}
|
204
|
+
#endif
|
205
|
+
|
206
|
+
|
207
|
+
//evoasm_inst *evoasm_population_inst_seed_random(uint32_t sol_idx, uint32_t inst_idx, void *insts, uint16_t, void *) {
|
208
|
+
// return NULL
|
209
|
+
//}
|
210
|
+
|
211
|
+
static void
|
212
|
+
search_free(void *p) {
|
213
|
+
evoasm_search *search = (evoasm_search *)p;
|
214
|
+
evoasm_search_destroy(search);
|
215
|
+
xfree(p);
|
216
|
+
}
|
217
|
+
|
218
|
+
static void
|
219
|
+
search_mark(void *p) {
|
220
|
+
//evoasm_search *search = (evoasm_search *)p;
|
221
|
+
}
|
222
|
+
|
223
|
+
static const rb_data_type_t rb_search_type = {
|
224
|
+
"Evoasm::Search",
|
225
|
+
{search_mark, search_free, NULL,},
|
226
|
+
NULL, NULL,
|
227
|
+
RUBY_TYPED_FREE_IMMEDIATELY,
|
228
|
+
};
|
229
|
+
|
230
|
+
static VALUE
|
231
|
+
rb_search_alloc(VALUE klass) {
|
232
|
+
evoasm_search *search = ZALLOC(evoasm_search);
|
233
|
+
return TypedData_Wrap_Struct(klass, &rb_search_type, search);
|
234
|
+
}
|
235
|
+
|
236
|
+
typedef struct {
|
237
|
+
evoasm_kernel kernel;
|
238
|
+
VALUE params;
|
239
|
+
VALUE insts;
|
240
|
+
VALUE program;
|
241
|
+
} rb_evoasm_kernel;
|
242
|
+
|
243
|
+
typedef struct {
|
244
|
+
evoasm_program program;
|
245
|
+
//VALUE params;
|
246
|
+
VALUE buffer;
|
247
|
+
VALUE body_buffer;
|
248
|
+
VALUE insts;
|
249
|
+
VALUE arch;
|
250
|
+
VALUE kernels;
|
251
|
+
} rb_evoasm_program;
|
252
|
+
|
253
|
+
static void
|
254
|
+
kernel_free(void *p) {
|
255
|
+
rb_evoasm_kernel *kernel = (rb_evoasm_kernel *)p;
|
256
|
+
xfree(kernel->kernel.params);
|
257
|
+
xfree(p);
|
258
|
+
}
|
259
|
+
|
260
|
+
static void
|
261
|
+
program_free(void *p) {
|
262
|
+
rb_evoasm_program *program = (rb_evoasm_program *)p;
|
263
|
+
xfree(program->program.params);
|
264
|
+
xfree(p);
|
265
|
+
}
|
266
|
+
|
267
|
+
|
268
|
+
static void
|
269
|
+
kernel_mark(void *p) {
|
270
|
+
rb_evoasm_kernel *kernel = (rb_evoasm_kernel *)p;
|
271
|
+
rb_gc_mark(kernel->params);
|
272
|
+
rb_gc_mark(kernel->insts);
|
273
|
+
rb_gc_mark(kernel->program);
|
274
|
+
}
|
275
|
+
|
276
|
+
static void
|
277
|
+
program_mark(void *p) {
|
278
|
+
rb_evoasm_program *program = (rb_evoasm_program *)p;
|
279
|
+
rb_gc_mark(program->buffer);
|
280
|
+
rb_gc_mark(program->body_buffer);
|
281
|
+
rb_gc_mark(program->buffer);
|
282
|
+
rb_gc_mark(program->kernels);
|
283
|
+
}
|
284
|
+
|
285
|
+
static const rb_data_type_t rb_program_type = {
|
286
|
+
"Evoasm::Program",
|
287
|
+
{program_mark, program_free, NULL,},
|
288
|
+
NULL, NULL,
|
289
|
+
RUBY_TYPED_FREE_IMMEDIATELY,
|
290
|
+
};
|
291
|
+
|
292
|
+
static const rb_data_type_t rb_kernel_type = {
|
293
|
+
"Evoasm::Kernel",
|
294
|
+
{kernel_mark, kernel_free, NULL,},
|
295
|
+
NULL, NULL,
|
296
|
+
RUBY_TYPED_FREE_IMMEDIATELY,
|
297
|
+
};
|
298
|
+
|
299
|
+
static const rb_data_type_t rb_inst_type = {
|
300
|
+
"Evoasm::Instruction",
|
301
|
+
{NULL, NULL, NULL,},
|
302
|
+
NULL, NULL,
|
303
|
+
RUBY_TYPED_FREE_IMMEDIATELY,
|
304
|
+
};
|
305
|
+
|
306
|
+
typedef struct {
|
307
|
+
evoasm_inst *inst;
|
308
|
+
VALUE arch;
|
309
|
+
} rb_evoasm_inst;
|
310
|
+
|
311
|
+
typedef struct {
|
312
|
+
evoasm_x64_inst *inst;
|
313
|
+
VALUE arch;
|
314
|
+
} rb_evoasm_x64_inst;
|
315
|
+
|
316
|
+
static void
|
317
|
+
x64_inst_free(void *p) {
|
318
|
+
//rb_evoasm_x64_inst *inst = (rb_evoasm_x64_inst *)p;
|
319
|
+
xfree(p);
|
320
|
+
}
|
321
|
+
|
322
|
+
static void
|
323
|
+
x64_inst_mark(void *p) {
|
324
|
+
rb_evoasm_x64_inst *inst = (rb_evoasm_x64_inst *)p;
|
325
|
+
rb_gc_mark(inst->arch);
|
326
|
+
}
|
327
|
+
|
328
|
+
static const rb_data_type_t rb_x64_inst_type = {
|
329
|
+
"Evoasm::X64::Instruction",
|
330
|
+
{x64_inst_mark, x64_inst_free, NULL,},
|
331
|
+
&rb_inst_type, NULL,
|
332
|
+
RUBY_TYPED_FREE_IMMEDIATELY,
|
333
|
+
};
|
334
|
+
|
335
|
+
static VALUE
|
336
|
+
rb_program_buffer(int argc, VALUE *argv, VALUE self) {
|
337
|
+
rb_evoasm_program *program;
|
338
|
+
VALUE buffer;
|
339
|
+
VALUE rb_sandbox = Qfalse;
|
340
|
+
|
341
|
+
rb_scan_args(argc, argv, "01", &rb_sandbox);
|
342
|
+
|
343
|
+
TypedData_Get_Struct(self, rb_evoasm_program, &rb_program_type, program);
|
344
|
+
|
345
|
+
if(RTEST(rb_sandbox)) {
|
346
|
+
buffer = program->buffer;
|
347
|
+
} else {
|
348
|
+
buffer = program->body_buffer;
|
349
|
+
}
|
350
|
+
|
351
|
+
return buffer;
|
352
|
+
}
|
353
|
+
|
354
|
+
static VALUE
|
355
|
+
rb_program_kernels(VALUE self) {
|
356
|
+
rb_evoasm_program *program;
|
357
|
+
TypedData_Get_Struct(self, rb_evoasm_program, &rb_program_type, program);
|
358
|
+
|
359
|
+
return program->kernels;
|
360
|
+
}
|
361
|
+
|
362
|
+
static void
|
363
|
+
rb_examples_to_c(VALUE rb_examples, VALUE rb_arity, evoasm_program_io *examples) {
|
364
|
+
unsigned i;
|
365
|
+
long examples_len;
|
366
|
+
|
367
|
+
Check_Type(rb_examples, T_ARRAY);
|
368
|
+
|
369
|
+
examples_len = RARRAY_LEN(rb_examples);
|
370
|
+
if(examples_len == 0) {
|
371
|
+
rb_raise(rb_eArgError, "examples must not be empty");
|
372
|
+
return;
|
373
|
+
}
|
374
|
+
|
375
|
+
examples->vals = evoasm_calloc((size_t) examples_len, sizeof(evoasm_example_val));
|
376
|
+
examples->len = (uint16_t) examples_len;
|
377
|
+
examples->arity = (uint8_t) NUM2CHR(rb_arity);
|
378
|
+
|
379
|
+
for(i = 0; i < EVOASM_PROGRAM_IO_MAX_ARITY; i++) {
|
380
|
+
examples->types[i] = EVOASM_EXAMPLE_TYPE_I64;
|
381
|
+
}
|
382
|
+
|
383
|
+
for(i = 0; i < examples->len; i++) {
|
384
|
+
VALUE elem = RARRAY_AREF(rb_examples, i);
|
385
|
+
if(RB_FLOAT_TYPE_P(elem)) {
|
386
|
+
examples->types[i % examples->arity] = EVOASM_EXAMPLE_TYPE_F64;
|
387
|
+
}
|
388
|
+
}
|
389
|
+
|
390
|
+
for(i = 0; i < examples->len; i++) {
|
391
|
+
VALUE elem = RARRAY_AREF(rb_examples, i);
|
392
|
+
switch(examples->types[i % examples->arity]) {
|
393
|
+
case EVOASM_EXAMPLE_TYPE_F64:
|
394
|
+
examples->vals[i].f64 = NUM2DBL(elem);
|
395
|
+
break;
|
396
|
+
case EVOASM_EXAMPLE_TYPE_I64:
|
397
|
+
examples->vals[i].i64 = NUM2LL(elem);
|
398
|
+
break;
|
399
|
+
default:
|
400
|
+
evoasm_assert_not_reached();
|
401
|
+
}
|
402
|
+
}
|
403
|
+
}
|
404
|
+
|
405
|
+
static VALUE
|
406
|
+
example_val_to_rb(evoasm_example_val val, evoasm_example_type type) {
|
407
|
+
switch(type) {
|
408
|
+
case EVOASM_EXAMPLE_TYPE_U64: return ULL2NUM(val.u64);
|
409
|
+
case EVOASM_EXAMPLE_TYPE_I64: return LL2NUM(val.i64);
|
410
|
+
case EVOASM_EXAMPLE_TYPE_F64: return rb_float_new((double) val.f64);
|
411
|
+
default:
|
412
|
+
evoasm_assert_not_reached();
|
413
|
+
return Qnil;
|
414
|
+
}
|
415
|
+
}
|
416
|
+
|
417
|
+
static VALUE
|
418
|
+
rb_program_eliminate_introns_bang(VALUE self) {
|
419
|
+
rb_evoasm_program *program;
|
420
|
+
|
421
|
+
TypedData_Get_Struct(self, rb_evoasm_program, &rb_program_type, program);
|
422
|
+
|
423
|
+
EVOASM_TRY(raise, evoasm_program_eliminate_introns, &program->program);
|
424
|
+
|
425
|
+
return self;
|
426
|
+
raise:
|
427
|
+
evoasm_raise_last_error();
|
428
|
+
return Qnil;
|
429
|
+
}
|
430
|
+
|
431
|
+
static VALUE
|
432
|
+
rb_program_output_registers(VALUE self) {
|
433
|
+
rb_evoasm_program *program;
|
434
|
+
VALUE ary = rb_ary_new();
|
435
|
+
size_t i;
|
436
|
+
|
437
|
+
TypedData_Get_Struct(self, rb_evoasm_program, &rb_program_type, program);
|
438
|
+
|
439
|
+
for(i = 0; i < program->program._output.arity; i++) {
|
440
|
+
switch(program->program.arch->cls->id) {
|
441
|
+
case EVOASM_ARCH_X64:
|
442
|
+
rb_ary_push(ary, ID2SYM(rb_x64_reg_ids[program->program.output_regs[i]]));
|
443
|
+
break;
|
444
|
+
default: evoasm_assert_not_reached();
|
445
|
+
}
|
446
|
+
}
|
447
|
+
return ary;
|
448
|
+
}
|
449
|
+
|
450
|
+
static VALUE
|
451
|
+
rb_program_run(VALUE self, VALUE rb_input, VALUE rb_arity) {
|
452
|
+
rb_evoasm_program *program;
|
453
|
+
unsigned i, j;
|
454
|
+
VALUE rb_ary;
|
455
|
+
evoasm_program_input input;
|
456
|
+
evoasm_program_output output = {0};
|
457
|
+
|
458
|
+
TypedData_Get_Struct(self, rb_evoasm_program, &rb_program_type, program);
|
459
|
+
|
460
|
+
rb_examples_to_c(rb_input, rb_arity, &input);
|
461
|
+
|
462
|
+
if(!evoasm_program_run(&program->program,
|
463
|
+
&input,
|
464
|
+
&output)) {
|
465
|
+
return Qnil;
|
466
|
+
}
|
467
|
+
|
468
|
+
rb_ary = rb_ary_new2(EVOASM_PROGRAM_OUTPUT_N(&output));
|
469
|
+
|
470
|
+
for(i = 0; i < EVOASM_PROGRAM_OUTPUT_N(&output); i++) {
|
471
|
+
VALUE rb_output = rb_ary_new2(output.arity);
|
472
|
+
for(j = 0; j < output.arity; j++) {
|
473
|
+
VALUE val = example_val_to_rb(output.vals[i * output.arity + j],
|
474
|
+
output.types[j]);
|
475
|
+
rb_ary_push(rb_output, val);
|
476
|
+
}
|
477
|
+
rb_ary_push(rb_ary, rb_output);
|
478
|
+
}
|
479
|
+
// rb_ary_push(rb_ary, example_val_to_rb(vals[i], examples.types[i]));
|
480
|
+
//}
|
481
|
+
|
482
|
+
evoasm_program_output_destroy((evoasm_program_io *) &output);
|
483
|
+
|
484
|
+
return rb_ary;
|
485
|
+
}
|
486
|
+
|
487
|
+
static void
|
488
|
+
params_free(void *p) {
|
489
|
+
xfree(p);
|
490
|
+
}
|
491
|
+
|
492
|
+
static const rb_data_type_t rb_params_type = {
|
493
|
+
"Evoasm::Parameters",
|
494
|
+
{NULL, NULL, NULL,},
|
495
|
+
NULL, NULL,
|
496
|
+
RUBY_TYPED_FREE_IMMEDIATELY,
|
497
|
+
};
|
498
|
+
|
499
|
+
static const rb_data_type_t rb_x64_params_type = {
|
500
|
+
"Evoasm::X64::Parameters",
|
501
|
+
{NULL, params_free, NULL,},
|
502
|
+
&rb_params_type, NULL,
|
503
|
+
RUBY_TYPED_FREE_IMMEDIATELY,
|
504
|
+
};
|
505
|
+
|
506
|
+
static VALUE
|
507
|
+
rb_x64_parameters_alloc(VALUE klass) {
|
508
|
+
evoasm_x64_params *x64_params = ZALLOC(evoasm_x64_params);
|
509
|
+
return TypedData_Wrap_Struct(klass, &rb_x64_params_type, x64_params);
|
510
|
+
}
|
511
|
+
|
512
|
+
static VALUE
|
513
|
+
rb_kernel_parameters(VALUE self) {
|
514
|
+
rb_evoasm_kernel *kernel;
|
515
|
+
rb_evoasm_program *program;
|
516
|
+
|
517
|
+
TypedData_Get_Struct(self, rb_evoasm_kernel, &rb_kernel_type, kernel);
|
518
|
+
TypedData_Get_Struct(kernel->program, rb_evoasm_program, &rb_program_type, program);
|
519
|
+
|
520
|
+
if(kernel->params != Qnil) return kernel->params;
|
521
|
+
|
522
|
+
{
|
523
|
+
unsigned i;
|
524
|
+
kernel->params = rb_ary_new2(kernel->kernel.params->size);
|
525
|
+
for(i = 0; i < kernel->kernel.params->size; i++) {
|
526
|
+
VALUE rb_params;
|
527
|
+
|
528
|
+
switch(program->program.arch->cls->id) {
|
529
|
+
case EVOASM_ARCH_X64: {
|
530
|
+
evoasm_x64_params *params;
|
531
|
+
rb_params = rb_x64_parameters_alloc(cX64Parameters);
|
532
|
+
TypedData_Get_Struct(rb_params, evoasm_x64_params, &rb_x64_params_type, params);
|
533
|
+
MEMCPY(params->vals, kernel->kernel.params->params[i].param_vals, evoasm_arch_param_val, EVOASM_X64_N_PARAMS);
|
534
|
+
params->set = kernel->kernel.params->params[i].set_params;
|
535
|
+
break;
|
536
|
+
}
|
537
|
+
default: evoasm_assert_not_reached();
|
538
|
+
}
|
539
|
+
rb_ary_push(kernel->params, rb_params);
|
540
|
+
}
|
541
|
+
}
|
542
|
+
|
543
|
+
return kernel->params;
|
544
|
+
}
|
545
|
+
|
546
|
+
static VALUE
|
547
|
+
rb_kernel_instructions(VALUE self) {
|
548
|
+
rb_evoasm_kernel *kernel;
|
549
|
+
rb_evoasm_program *program;
|
550
|
+
|
551
|
+
TypedData_Get_Struct(self, rb_evoasm_kernel, &rb_kernel_type, kernel);
|
552
|
+
TypedData_Get_Struct(kernel->program, rb_evoasm_program, &rb_program_type, program);
|
553
|
+
|
554
|
+
if(kernel->insts != Qnil) return kernel->insts;
|
555
|
+
|
556
|
+
{
|
557
|
+
unsigned i;
|
558
|
+
kernel->insts = rb_ary_new2(kernel->kernel.params->size);
|
559
|
+
for(i = 0; i < kernel->kernel.params->size; i++) {
|
560
|
+
VALUE rb_inst;
|
561
|
+
|
562
|
+
switch(program->program.arch->cls->id) {
|
563
|
+
case EVOASM_ARCH_X64: {
|
564
|
+
rb_evoasm_x64_inst *inst = ALLOC(rb_evoasm_x64_inst);
|
565
|
+
inst->arch = program->arch;
|
566
|
+
inst->inst = (evoasm_x64_inst *) kernel->kernel.params->params[i].inst;
|
567
|
+
rb_inst = TypedData_Wrap_Struct(evoasm_cX64Instruction, &rb_x64_inst_type, inst);
|
568
|
+
break;
|
569
|
+
}
|
570
|
+
default: evoasm_assert_not_reached();
|
571
|
+
}
|
572
|
+
rb_ary_push(kernel->insts, rb_inst);
|
573
|
+
}
|
574
|
+
}
|
575
|
+
|
576
|
+
return kernel->insts;
|
577
|
+
}
|
578
|
+
|
579
|
+
static VALUE
|
580
|
+
rb_program_alloc(VALUE klass) {
|
581
|
+
rb_evoasm_program *program = ALLOC(rb_evoasm_program);
|
582
|
+
//program->params = Qnil;
|
583
|
+
program->buffer = Qnil;
|
584
|
+
program->kernels = Qnil;
|
585
|
+
return TypedData_Wrap_Struct(klass, &rb_program_type, program);
|
586
|
+
}
|
587
|
+
|
588
|
+
static VALUE
|
589
|
+
rb_kernel_alloc(VALUE klass) {
|
590
|
+
rb_evoasm_kernel *kernel = ALLOC(rb_evoasm_kernel);
|
591
|
+
kernel->params = Qnil;
|
592
|
+
kernel->program = Qnil;
|
593
|
+
return TypedData_Wrap_Struct(klass, &rb_kernel_type, kernel);
|
594
|
+
}
|
595
|
+
|
596
|
+
|
597
|
+
static evoasm_arch_param_id
|
598
|
+
x64_param_sym_to_id(VALUE sym) {
|
599
|
+
int i;
|
600
|
+
ID id = SYM2ID(sym);
|
601
|
+
for(i = 0; i < EVOASM_X64_N_PARAMS; i++) {
|
602
|
+
if(rb_x64_param_ids[i] == id) {
|
603
|
+
return (evoasm_x64_param_id) i;
|
604
|
+
}
|
605
|
+
}
|
606
|
+
evoasm_assert_not_reached();
|
607
|
+
}
|
608
|
+
|
609
|
+
struct arch_with_params {
|
610
|
+
evoasm_arch *arch;
|
611
|
+
evoasm_search_params *params;
|
612
|
+
};
|
613
|
+
|
614
|
+
static evoasm_arch_param_id
|
615
|
+
param_sym_to_c(VALUE rb_key, unsigned n_params) {
|
616
|
+
unsigned i;
|
617
|
+
ID id = SYM2ID(rb_key);
|
618
|
+
|
619
|
+
for(i = 0; i < n_params; i++) {
|
620
|
+
if(rb_x64_param_ids[i] == id) {
|
621
|
+
return (evoasm_arch_param_id) i;
|
622
|
+
}
|
623
|
+
}
|
624
|
+
|
625
|
+
rb_raise(rb_eKeyError, "invalid key");
|
626
|
+
return 0;
|
627
|
+
}
|
628
|
+
|
629
|
+
static evoasm_arch_param_val
|
630
|
+
param_val_to_c(VALUE rb_value) {
|
631
|
+
switch(TYPE(rb_value)) {
|
632
|
+
case T_SYMBOL: {
|
633
|
+
unsigned i;
|
634
|
+
ID id = SYM2ID(rb_value);
|
635
|
+
for(i = 0; i < EVOASM_X64_N_REGS; i++) {
|
636
|
+
if(rb_x64_reg_ids[i] == id) {
|
637
|
+
return (evoasm_arch_param_val) i;
|
638
|
+
}
|
639
|
+
}
|
640
|
+
rb_raise(rb_eArgError, "invalid value");
|
641
|
+
break;
|
642
|
+
}
|
643
|
+
case T_FIXNUM:
|
644
|
+
case T_BIGNUM:
|
645
|
+
return NUM2LL(rb_value);
|
646
|
+
case T_OBJECT:
|
647
|
+
return NUM2LL(rb_funcall(rb_value, rb_id_id, 0, NULL));
|
648
|
+
case T_TRUE:
|
649
|
+
case T_FALSE:
|
650
|
+
return (rb_value == Qtrue ? 1 : 0);
|
651
|
+
default:
|
652
|
+
rb_raise(rb_eArgError, "invalid key type");
|
653
|
+
return 0;
|
654
|
+
}
|
655
|
+
}
|
656
|
+
|
657
|
+
static evoasm_domain *
|
658
|
+
rb_domain_to_c(VALUE rb_domain) {
|
659
|
+
if(rb_obj_is_kind_of(rb_domain, rb_cRange)) {
|
660
|
+
VALUE rb_beg;
|
661
|
+
VALUE rb_end;
|
662
|
+
int exclp;
|
663
|
+
|
664
|
+
evoasm_interval *interval = ALLOC(evoasm_interval);
|
665
|
+
interval->type = EVOASM_DOMAIN_TYPE_INTERVAL;
|
666
|
+
|
667
|
+
if(rb_range_values(rb_domain, &rb_beg, &rb_end, &exclp) == Qtrue) {
|
668
|
+
interval->min = NUM2LL(rb_beg);
|
669
|
+
interval->max = NUM2LL(rb_end);
|
670
|
+
if(exclp) interval->max--;
|
671
|
+
}
|
672
|
+
else {
|
673
|
+
evoasm_assert_not_reached();
|
674
|
+
}
|
675
|
+
return (evoasm_domain *) interval;
|
676
|
+
} else {
|
677
|
+
Check_Type(rb_domain, T_ARRAY);
|
678
|
+
|
679
|
+
{
|
680
|
+
unsigned i;
|
681
|
+
long len = RARRAY_LEN(rb_domain);
|
682
|
+
evoasm_enum *enm;
|
683
|
+
|
684
|
+
if(len > EVOASM_ENUM_MAX_LEN) {
|
685
|
+
rb_raise(rb_eArgError, "array exceeds maximum length of %d", EVOASM_ENUM_MAX_LEN);
|
686
|
+
return NULL;
|
687
|
+
}
|
688
|
+
|
689
|
+
enm = xmalloc(EVOASM_ENUM_SIZE(RARRAY_LEN(rb_domain)));
|
690
|
+
enm->type = EVOASM_DOMAIN_TYPE_ENUM;
|
691
|
+
enm->len = (uint16_t) len;
|
692
|
+
|
693
|
+
for(i = 0; i < RARRAY_LEN(rb_domain); i++) {
|
694
|
+
enm->vals[i] = param_val_to_c(RARRAY_AREF(rb_domain, i));
|
695
|
+
}
|
696
|
+
return (evoasm_domain *) enm;
|
697
|
+
}
|
698
|
+
}
|
699
|
+
}
|
700
|
+
|
701
|
+
static int
|
702
|
+
set_domain(VALUE key, VALUE val, VALUE user_data) {
|
703
|
+
struct arch_with_params *arch_with_params = (struct arch_with_params *) user_data;
|
704
|
+
evoasm_search_params *search_params = arch_with_params->params;
|
705
|
+
evoasm_arch_param_id param_id = param_sym_to_c(key, arch_with_params->arch->cls->n_params);
|
706
|
+
search_params->domains[param_id] = rb_domain_to_c(val);
|
707
|
+
return ST_CONTINUE;
|
708
|
+
}
|
709
|
+
|
710
|
+
static void
|
711
|
+
set_size_param(VALUE rb_size, evoasm_search_params *params, int id) {
|
712
|
+
unsigned min_size, max_size;
|
713
|
+
|
714
|
+
if(FIXNUM_P(rb_size)) {
|
715
|
+
min_size = (evoasm_program_size) FIX2UINT(rb_size);
|
716
|
+
max_size = min_size;
|
717
|
+
} else {
|
718
|
+
VALUE rb_beg;
|
719
|
+
VALUE rb_end;
|
720
|
+
int exclp;
|
721
|
+
if(rb_range_values(rb_size, &rb_beg, &rb_end, &exclp) == Qtrue) {
|
722
|
+
min_size = FIX2UINT(rb_beg);
|
723
|
+
max_size = FIX2UINT(rb_end);
|
724
|
+
if(exclp) max_size--;
|
725
|
+
} else {
|
726
|
+
rb_raise(rb_eArgError, "invalid program size");
|
727
|
+
}
|
728
|
+
}
|
729
|
+
|
730
|
+
if(id == 0) {
|
731
|
+
params->min_kernel_size = (evoasm_kernel_size) min_size;
|
732
|
+
params->max_kernel_size = (evoasm_kernel_size) max_size;
|
733
|
+
} else if(id == 1) {
|
734
|
+
params->min_program_size = (evoasm_program_size) min_size;
|
735
|
+
params->max_program_size = (evoasm_program_size) max_size;
|
736
|
+
} else {
|
737
|
+
evoasm_assert_not_reached();
|
738
|
+
}
|
739
|
+
}
|
740
|
+
|
741
|
+
static VALUE
|
742
|
+
rb_search_initialize(int argc, VALUE* argv, VALUE self) {
|
743
|
+
VALUE rb_arch, rb_pop_size, rb_kernel_size, rb_program_size, rb_insts, rb_input, rb_output;
|
744
|
+
VALUE rb_input_arity, rb_output_arity, rb_params, rb_mutation_rate;
|
745
|
+
VALUE rb_seed, rb_domains, rb_recur_limit;
|
746
|
+
|
747
|
+
evoasm_search *search;
|
748
|
+
evoasm_arch *arch;
|
749
|
+
evoasm_search_params search_params;
|
750
|
+
evoasm_arch_param_id *params;
|
751
|
+
evoasm_inst **insts;
|
752
|
+
unsigned i;
|
753
|
+
long insts_len;
|
754
|
+
long params_len;
|
755
|
+
uint32_t pop_size;
|
756
|
+
uint32_t mutation_rate;
|
757
|
+
uint32_t recur_limit;
|
758
|
+
|
759
|
+
evoasm_program_input input;
|
760
|
+
evoasm_program_input output;
|
761
|
+
|
762
|
+
VALUE *args[] = {
|
763
|
+
&rb_input,
|
764
|
+
&rb_input_arity,
|
765
|
+
&rb_output,
|
766
|
+
&rb_output_arity,
|
767
|
+
&rb_arch,
|
768
|
+
&rb_pop_size,
|
769
|
+
&rb_kernel_size,
|
770
|
+
&rb_program_size,
|
771
|
+
&rb_insts,
|
772
|
+
&rb_params,
|
773
|
+
&rb_mutation_rate,
|
774
|
+
&rb_seed,
|
775
|
+
&rb_domains,
|
776
|
+
&rb_recur_limit
|
777
|
+
};
|
778
|
+
|
779
|
+
if(argc != EVOASM_ARY_LEN(args)) {
|
780
|
+
rb_error_arity(argc, EVOASM_ARY_LEN(args), EVOASM_ARY_LEN(args));
|
781
|
+
return Qnil;
|
782
|
+
}
|
783
|
+
|
784
|
+
for(i = 0; i < (unsigned) argc; i++) {
|
785
|
+
*args[i] = argv[i];
|
786
|
+
}
|
787
|
+
|
788
|
+
Check_Type(rb_insts, T_ARRAY);
|
789
|
+
Check_Type(rb_params, T_ARRAY);
|
790
|
+
Check_Type(rb_seed, T_ARRAY);
|
791
|
+
Check_Type(rb_domains, T_HASH);
|
792
|
+
|
793
|
+
TypedData_Get_Struct(self, evoasm_search, &rb_search_type, search);
|
794
|
+
TypedData_Get_Struct(rb_arch, evoasm_arch, &rb_arch_type, arch);
|
795
|
+
|
796
|
+
insts_len = RARRAY_LEN(rb_insts);
|
797
|
+
params_len = RARRAY_LEN(rb_params);
|
798
|
+
pop_size = (uint32_t) FIX2UINT(rb_pop_size);
|
799
|
+
mutation_rate = (uint32_t)(UINT32_MAX * NUM2DBL(rb_mutation_rate));
|
800
|
+
recur_limit = (uint32_t)(FIX2UINT(rb_recur_limit));
|
801
|
+
|
802
|
+
|
803
|
+
if(RARRAY_LEN(rb_seed) < 64) {
|
804
|
+
rb_raise(rb_eArgError, "seed must be an array of size at least 64");
|
805
|
+
}
|
806
|
+
|
807
|
+
if(pop_size % 2) {
|
808
|
+
rb_raise(rb_eArgError, "poulation size must be even");
|
809
|
+
return Qnil;
|
810
|
+
}
|
811
|
+
|
812
|
+
if(insts_len == 0) {
|
813
|
+
rb_raise(rb_eArgError, "instructions must not be empty");
|
814
|
+
return Qnil;
|
815
|
+
}
|
816
|
+
|
817
|
+
if(params_len == 0) {
|
818
|
+
rb_raise(rb_eArgError, "parameters must not be empty");
|
819
|
+
return Qnil;
|
820
|
+
}
|
821
|
+
|
822
|
+
rb_examples_to_c(rb_input, rb_input_arity, &input);
|
823
|
+
rb_examples_to_c(rb_output, rb_output_arity, &output);
|
824
|
+
|
825
|
+
insts = ZALLOC_N(evoasm_inst *, (size_t) insts_len);
|
826
|
+
for(i = 0; i < insts_len; i++) {
|
827
|
+
VALUE elem = RARRAY_AREF(rb_insts, i);
|
828
|
+
rb_evoasm_inst *inst;
|
829
|
+
TypedData_Get_Struct(elem, rb_evoasm_inst, &rb_inst_type, inst);
|
830
|
+
insts[i] = inst->inst;
|
831
|
+
}
|
832
|
+
|
833
|
+
params = ZALLOC_N(evoasm_arch_param_id, (size_t) params_len);
|
834
|
+
for(i = 0; i < params_len; i++) {
|
835
|
+
switch(arch->cls->id) {
|
836
|
+
case EVOASM_ARCH_X64:
|
837
|
+
params[i] = (evoasm_arch_param_id) x64_param_sym_to_id(RARRAY_AREF(rb_params, i));
|
838
|
+
break;
|
839
|
+
default: evoasm_assert_not_reached();
|
840
|
+
}
|
841
|
+
}
|
842
|
+
|
843
|
+
search_params = (evoasm_search_params) {
|
844
|
+
.pop_size = pop_size,
|
845
|
+
.insts = insts,
|
846
|
+
.program_input = input,
|
847
|
+
.program_output = output,
|
848
|
+
.insts_len = (uint16_t) insts_len,
|
849
|
+
.params = params,
|
850
|
+
.params_len = (uint8_t) params_len,
|
851
|
+
.mutation_rate = mutation_rate,
|
852
|
+
.recur_limit = recur_limit
|
853
|
+
};
|
854
|
+
|
855
|
+
for(i = 0; i < EVOASM_ARY_LEN(search_params.seed32.data); i++) {
|
856
|
+
search_params.seed32.data[i] = (uint32_t) FIX2UINT(RARRAY_AREF(rb_seed, i));
|
857
|
+
}
|
858
|
+
|
859
|
+
for(i = 0; i < EVOASM_ARY_LEN(search_params.seed64.data); i++) {
|
860
|
+
search_params.seed64.data[i] = (uint64_t) NUM2ULL(RARRAY_AREF(rb_seed, i));
|
861
|
+
}
|
862
|
+
|
863
|
+
set_size_param(rb_kernel_size, &search_params, 0);
|
864
|
+
set_size_param(rb_program_size, &search_params, 1);
|
865
|
+
|
866
|
+
{
|
867
|
+
struct arch_with_params user_data = {arch, &search_params};
|
868
|
+
rb_hash_foreach(rb_domains, set_domain, (VALUE) &user_data);
|
869
|
+
}
|
870
|
+
|
871
|
+
EVOASM_TRY(raise, evoasm_search_init, search, arch, &search_params);
|
872
|
+
|
873
|
+
return self;
|
874
|
+
|
875
|
+
raise:
|
876
|
+
evoasm_raise_last_error();
|
877
|
+
return Qnil;
|
878
|
+
}
|
879
|
+
|
880
|
+
static const rb_data_type_t rb_op_type = {
|
881
|
+
"Evoasm::Operand",
|
882
|
+
{NULL, NULL, NULL,},
|
883
|
+
NULL, NULL,
|
884
|
+
RUBY_TYPED_FREE_IMMEDIATELY,
|
885
|
+
};
|
886
|
+
|
887
|
+
static const rb_data_type_t rb_x64_op_type = {
|
888
|
+
"Evoasm::X64::Operand",
|
889
|
+
{NULL, NULL, NULL,},
|
890
|
+
&rb_op_type, NULL,
|
891
|
+
RUBY_TYPED_FREE_IMMEDIATELY,
|
892
|
+
};
|
893
|
+
|
894
|
+
static const rb_data_type_t rb_param_type = {
|
895
|
+
"Evoasm::Parameter",
|
896
|
+
{NULL, NULL, NULL,},
|
897
|
+
NULL, NULL,
|
898
|
+
RUBY_TYPED_FREE_IMMEDIATELY,
|
899
|
+
};
|
900
|
+
|
901
|
+
static const rb_data_type_t rb_reg_type = {
|
902
|
+
"Evoasm::Register",
|
903
|
+
{NULL, NULL, NULL,},
|
904
|
+
NULL, NULL,
|
905
|
+
RUBY_TYPED_FREE_IMMEDIATELY,
|
906
|
+
};
|
907
|
+
|
908
|
+
static const rb_data_type_t rb_x64_reg_type = {
|
909
|
+
"Evoasm::::X64::Register",
|
910
|
+
{NULL, NULL, NULL,},
|
911
|
+
&rb_reg_type, NULL,
|
912
|
+
RUBY_TYPED_FREE_IMMEDIATELY,
|
913
|
+
};
|
914
|
+
|
915
|
+
static void
|
916
|
+
x64_parameters_aset(evoasm_x64_params *params, VALUE rb_key, VALUE rb_value) {
|
917
|
+
evoasm_arch_param_id key;
|
918
|
+
evoasm_arch_param_val param_val = 0;
|
919
|
+
|
920
|
+
key = param_sym_to_c(rb_key, EVOASM_X64_N_PARAMS);
|
921
|
+
param_val = param_val_to_c(rb_value);
|
922
|
+
|
923
|
+
evoasm_arch_params_set(params->vals, (evoasm_bitmap *) ¶ms->set, key, param_val);
|
924
|
+
return;
|
925
|
+
}
|
926
|
+
|
927
|
+
static VALUE
|
928
|
+
rb_x64_parameters_aset(VALUE self, VALUE rb_key, VALUE rb_value) {
|
929
|
+
evoasm_x64_params *params;
|
930
|
+
TypedData_Get_Struct(self, evoasm_x64_params, &rb_x64_params_type, params);
|
931
|
+
|
932
|
+
x64_parameters_aset(params, rb_key, rb_value);
|
933
|
+
return Qnil;
|
934
|
+
}
|
935
|
+
|
936
|
+
static VALUE
|
937
|
+
rb_x64_parameters_aref(VALUE self, VALUE rb_key) {
|
938
|
+
evoasm_x64_params *params;
|
939
|
+
evoasm_arch_param_id key = (evoasm_arch_param_id) FIX2UINT(rb_key);
|
940
|
+
TypedData_Get_Struct(self, evoasm_x64_params, &rb_x64_params_type, params);
|
941
|
+
|
942
|
+
if((unsigned)key >= (unsigned)EVOASM_X64_N_PARAMS) {
|
943
|
+
rb_raise(rb_eKeyError, "invalid key");
|
944
|
+
return Qnil;
|
945
|
+
}
|
946
|
+
|
947
|
+
if(!evoasm_bitmap_get((evoasm_bitmap *) ¶ms->set, key)) {
|
948
|
+
return Qnil;
|
949
|
+
} else {
|
950
|
+
return LL2NUM(params->vals[key]);
|
951
|
+
}
|
952
|
+
}
|
953
|
+
|
954
|
+
static int
|
955
|
+
x64_params_set_kv(VALUE key, VALUE val, VALUE params) {
|
956
|
+
x64_parameters_aset((evoasm_x64_params *) params, key, val);
|
957
|
+
return ST_CONTINUE;
|
958
|
+
}
|
959
|
+
|
960
|
+
static void
|
961
|
+
x64_params_set_from_hash(evoasm_x64_params *params, VALUE hash) {
|
962
|
+
rb_hash_foreach(hash, x64_params_set_kv, (VALUE) params);
|
963
|
+
}
|
964
|
+
|
965
|
+
static VALUE
|
966
|
+
rb_x64_parameters_initialize(int argc, VALUE *argv, VALUE self) {
|
967
|
+
evoasm_x64_params *params;
|
968
|
+
VALUE rb_params;
|
969
|
+
|
970
|
+
TypedData_Get_Struct(self, evoasm_x64_params, &rb_x64_params_type, params);
|
971
|
+
rb_scan_args(argc, argv, "01", &rb_params);
|
972
|
+
|
973
|
+
if(!NIL_P(rb_params)) {
|
974
|
+
x64_params_set_from_hash(params, rb_params);
|
975
|
+
}
|
976
|
+
|
977
|
+
return self;
|
978
|
+
}
|
979
|
+
|
980
|
+
static void
|
981
|
+
error_free(void *p) {
|
982
|
+
evoasm_error *error = (evoasm_error *)p;
|
983
|
+
(void) error;
|
984
|
+
xfree(p);
|
985
|
+
}
|
986
|
+
|
987
|
+
void *realloc_func(void *ptr, size_t size) {
|
988
|
+
return ruby_xrealloc(ptr, size);
|
989
|
+
}
|
990
|
+
|
991
|
+
|
992
|
+
static ID error_code_unknown;
|
993
|
+
static ID error_code_not_encodable;
|
994
|
+
static ID error_code_missing_param;
|
995
|
+
static ID error_code_invalid_access;
|
996
|
+
static ID error_code_missing_feature;
|
997
|
+
|
998
|
+
struct result_func_data {
|
999
|
+
evoasm_program *program;
|
1000
|
+
evoasm_loss loss;
|
1001
|
+
evoasm_search *search;
|
1002
|
+
int tag;
|
1003
|
+
VALUE block;
|
1004
|
+
};
|
1005
|
+
|
1006
|
+
static VALUE
|
1007
|
+
result_func(VALUE user_data) {
|
1008
|
+
|
1009
|
+
struct result_func_data *data = (struct result_func_data *) user_data;
|
1010
|
+
|
1011
|
+
evoasm_loss loss = data->loss;
|
1012
|
+
evoasm_program tmp_program = *data->program;
|
1013
|
+
|
1014
|
+
/*VALUE proc = (VALUE) user_data;*/
|
1015
|
+
VALUE rb_program = rb_program_alloc(cProgram);
|
1016
|
+
VALUE rb_buffer = rb_buffer_alloc(cBuffer);
|
1017
|
+
VALUE rb_body_buffer = rb_buffer_alloc(cBuffer);
|
1018
|
+
VALUE rb_kernels = rb_ary_new2(tmp_program.params->size);
|
1019
|
+
|
1020
|
+
assert(data->program->body_buf->pos > 0);
|
1021
|
+
|
1022
|
+
{
|
1023
|
+
evoasm_buf *buf;
|
1024
|
+
TypedData_Get_Struct(rb_buffer, evoasm_buf, &rb_buf_type, buf);
|
1025
|
+
EVOASM_TRY(raise, evoasm_buf_clone, data->program->buf, buf);
|
1026
|
+
tmp_program.buf = buf;
|
1027
|
+
}
|
1028
|
+
|
1029
|
+
{
|
1030
|
+
evoasm_buf *buf;
|
1031
|
+
TypedData_Get_Struct(rb_body_buffer, evoasm_buf, &rb_buf_type, buf);
|
1032
|
+
EVOASM_TRY(raise, evoasm_buf_clone, data->program->body_buf, buf);
|
1033
|
+
tmp_program.body_buf = buf;
|
1034
|
+
}
|
1035
|
+
|
1036
|
+
{
|
1037
|
+
unsigned i;
|
1038
|
+
for(i = 0; i < data->program->params->size; i++) {
|
1039
|
+
evoasm_kernel *orig_kernel = &data->program->kernels[i];
|
1040
|
+
rb_evoasm_kernel *kernel;
|
1041
|
+
size_t params_size;
|
1042
|
+
|
1043
|
+
VALUE rb_kernel = rb_kernel_alloc(cKernel);
|
1044
|
+
TypedData_Get_Struct(rb_kernel, rb_evoasm_kernel, &rb_kernel_type, kernel);
|
1045
|
+
|
1046
|
+
params_size = sizeof(evoasm_kernel_params) + orig_kernel->params->size * sizeof(evoasm_kernel_param);
|
1047
|
+
kernel->kernel.params = xmalloc(params_size);
|
1048
|
+
kernel->params = Qnil;
|
1049
|
+
kernel->insts = Qnil;
|
1050
|
+
kernel->program = rb_program;
|
1051
|
+
memcpy(kernel->kernel.params, data->program->params, params_size);
|
1052
|
+
|
1053
|
+
rb_ary_push(rb_kernels, rb_kernel);
|
1054
|
+
}
|
1055
|
+
}
|
1056
|
+
|
1057
|
+
{
|
1058
|
+
size_t params_size = sizeof(evoasm_program_params);
|
1059
|
+
|
1060
|
+
tmp_program.index = 0;
|
1061
|
+
tmp_program._signal_ctx = NULL;
|
1062
|
+
tmp_program.reset_rflags = false;
|
1063
|
+
tmp_program._input.vals = NULL;
|
1064
|
+
tmp_program._output.vals = NULL;
|
1065
|
+
tmp_program.output_vals = NULL;
|
1066
|
+
|
1067
|
+
tmp_program.params = xmalloc(params_size);
|
1068
|
+
memcpy(tmp_program.params, data->program->params, params_size);
|
1069
|
+
}
|
1070
|
+
|
1071
|
+
{
|
1072
|
+
rb_evoasm_program *program;
|
1073
|
+
TypedData_Get_Struct(rb_program, rb_evoasm_program, &rb_program_type, program);
|
1074
|
+
|
1075
|
+
program->kernels = rb_kernels;
|
1076
|
+
program->buffer = rb_buffer;
|
1077
|
+
program->body_buffer = rb_body_buffer;
|
1078
|
+
program->arch = (VALUE) data->program->arch->user_data;
|
1079
|
+
program->program = tmp_program;
|
1080
|
+
|
1081
|
+
assert(program->program.body_buf->pos > 0);
|
1082
|
+
}
|
1083
|
+
|
1084
|
+
{
|
1085
|
+
VALUE yield_vals[] = {rb_program, rb_float_new(loss)};
|
1086
|
+
return rb_proc_call(data->block, rb_ary_new_from_values(2, yield_vals));
|
1087
|
+
}
|
1088
|
+
|
1089
|
+
raise:
|
1090
|
+
evoasm_raise_last_error();
|
1091
|
+
return Qnil;
|
1092
|
+
}
|
1093
|
+
|
1094
|
+
|
1095
|
+
static bool
|
1096
|
+
_result_func(evoasm_program *program, evoasm_loss loss, void *user_data) {
|
1097
|
+
struct result_func_data *result_data = (struct result_func_data *) user_data;
|
1098
|
+
VALUE retval;
|
1099
|
+
|
1100
|
+
result_data->loss = loss;
|
1101
|
+
result_data->program = program;
|
1102
|
+
result_data->tag = 0;
|
1103
|
+
|
1104
|
+
retval = rb_protect(result_func, (VALUE) result_data, &result_data->tag);
|
1105
|
+
|
1106
|
+
if(result_data->tag != 0 || retval == Qfalse) {
|
1107
|
+
return false;
|
1108
|
+
}
|
1109
|
+
|
1110
|
+
return true;
|
1111
|
+
}
|
1112
|
+
|
1113
|
+
|
1114
|
+
static VALUE
|
1115
|
+
rb_search_start(VALUE self, VALUE rb_max_loss) {
|
1116
|
+
evoasm_search *search;
|
1117
|
+
VALUE block;
|
1118
|
+
struct result_func_data result_data;
|
1119
|
+
rb_need_block();
|
1120
|
+
|
1121
|
+
TypedData_Get_Struct(self, evoasm_search, &rb_search_type, search);
|
1122
|
+
|
1123
|
+
block = rb_block_proc();
|
1124
|
+
result_data.block = block;
|
1125
|
+
result_data.search = search;
|
1126
|
+
|
1127
|
+
evoasm_search_start(search, (evoasm_loss) NUM2DBL(rb_max_loss), _result_func, &result_data);
|
1128
|
+
if(result_data.tag) {
|
1129
|
+
rb_jump_tag(result_data.tag);
|
1130
|
+
}
|
1131
|
+
return Qnil;
|
1132
|
+
}
|
1133
|
+
|
1134
|
+
|
1135
|
+
static const rb_data_type_t rb_error_type = {
|
1136
|
+
"Evoasm::Error",
|
1137
|
+
{NULL, error_free, NULL,},
|
1138
|
+
NULL, NULL,
|
1139
|
+
RUBY_TYPED_FREE_IMMEDIATELY,
|
1140
|
+
};
|
1141
|
+
|
1142
|
+
static const rb_data_type_t rb_arch_error_type = {
|
1143
|
+
"Evoasm::Architecture::Error",
|
1144
|
+
{NULL, error_free, NULL,},
|
1145
|
+
&rb_error_type, NULL,
|
1146
|
+
RUBY_TYPED_FREE_IMMEDIATELY,
|
1147
|
+
};
|
1148
|
+
|
1149
|
+
|
1150
|
+
void
|
1151
|
+
evoasm_raise_last_error() {
|
1152
|
+
VALUE exc;
|
1153
|
+
|
1154
|
+
evoasm_error *error = &evoasm_last_error;
|
1155
|
+
|
1156
|
+
switch(error->type) {
|
1157
|
+
case EVOASM_ERROR_TYPE_ARCH: {
|
1158
|
+
evoasm_arch_error *arch_error = ALLOC(evoasm_arch_error);
|
1159
|
+
*arch_error = *((evoasm_arch_error *)error);
|
1160
|
+
exc = TypedData_Wrap_Struct(eArchitectureError, &rb_arch_error_type, arch_error);
|
1161
|
+
break;
|
1162
|
+
}
|
1163
|
+
default: {
|
1164
|
+
evoasm_error *_error = ALLOC(evoasm_error);
|
1165
|
+
*_error = *error;
|
1166
|
+
exc = TypedData_Wrap_Struct(eError, &rb_error_type, _error);
|
1167
|
+
break;
|
1168
|
+
}
|
1169
|
+
}
|
1170
|
+
rb_obj_call_init(exc, 0, NULL);
|
1171
|
+
rb_exc_raise(exc);
|
1172
|
+
}
|
1173
|
+
|
1174
|
+
|
1175
|
+
static VALUE
|
1176
|
+
rb_error_code(VALUE self) {
|
1177
|
+
evoasm_error *error;
|
1178
|
+
TypedData_Get_Struct(self, evoasm_error, &rb_error_type, error);
|
1179
|
+
|
1180
|
+
switch(error->code) {
|
1181
|
+
case EVOASM_ERROR_CODE_NONE: return ID2SYM(error_code_unknown);
|
1182
|
+
default: return Qnil;
|
1183
|
+
}
|
1184
|
+
}
|
1185
|
+
|
1186
|
+
|
1187
|
+
static VALUE
|
1188
|
+
rb_error_message(VALUE self) {
|
1189
|
+
evoasm_error *error;
|
1190
|
+
size_t len;
|
1191
|
+
TypedData_Get_Struct(self, evoasm_error, &rb_error_type, error);
|
1192
|
+
|
1193
|
+
if(error->msg[0] == '\0') {
|
1194
|
+
return Qnil;
|
1195
|
+
}
|
1196
|
+
|
1197
|
+
len = strnlen(error->msg, EVOASM_ERROR_MAX_MSG_LEN);
|
1198
|
+
return rb_str_new(error->msg, (long) len);
|
1199
|
+
}
|
1200
|
+
|
1201
|
+
static VALUE
|
1202
|
+
rb_architecture_error_code(VALUE self) {
|
1203
|
+
evoasm_arch_error *error;
|
1204
|
+
TypedData_Get_Struct(self, evoasm_arch_error, &rb_arch_error_type, error);
|
1205
|
+
|
1206
|
+
switch(error->code) {
|
1207
|
+
case EVOASM_ARCH_ERROR_CODE_NOT_ENCODABLE: return ID2SYM(error_code_not_encodable);
|
1208
|
+
case EVOASM_ARCH_ERROR_CODE_MISSING_PARAM: return ID2SYM(error_code_missing_param);
|
1209
|
+
case EVOASM_ARCH_ERROR_CODE_INVALID_ACCESS: return ID2SYM(error_code_invalid_access);
|
1210
|
+
case EVOASM_ARCH_ERROR_CODE_MISSING_FEATURE: return ID2SYM(error_code_missing_feature);
|
1211
|
+
default: return rb_error_code(self);
|
1212
|
+
}
|
1213
|
+
}
|
1214
|
+
|
1215
|
+
static VALUE
|
1216
|
+
rb_architecture_error_parameter(VALUE self) {
|
1217
|
+
evoasm_arch_error *error;
|
1218
|
+
TypedData_Get_Struct(self, evoasm_arch_error, &rb_arch_error_type, error);
|
1219
|
+
|
1220
|
+
if(error->code == EVOASM_ARCH_ERROR_CODE_MISSING_PARAM) {
|
1221
|
+
switch(error->data.arch->cls->id) {
|
1222
|
+
case EVOASM_ARCH_X64: return ID2SYM(rb_x64_param_ids[error->data.param]);
|
1223
|
+
default: evoasm_assert_not_reached();
|
1224
|
+
}
|
1225
|
+
}
|
1226
|
+
else {
|
1227
|
+
return Qnil;
|
1228
|
+
}
|
1229
|
+
}
|
1230
|
+
|
1231
|
+
static VALUE
|
1232
|
+
rb_architecture_error_register(VALUE self) {
|
1233
|
+
evoasm_arch_error *error;
|
1234
|
+
TypedData_Get_Struct(self, evoasm_arch_error, &rb_arch_error_type, error);
|
1235
|
+
|
1236
|
+
if(error->code == EVOASM_ARCH_ERROR_CODE_INVALID_ACCESS) {
|
1237
|
+
switch(error->data.arch->cls->id) {
|
1238
|
+
case EVOASM_ARCH_X64: return ID2SYM(rb_x64_reg_ids[error->data.reg]);
|
1239
|
+
default: evoasm_assert_not_reached();
|
1240
|
+
}
|
1241
|
+
}
|
1242
|
+
else {
|
1243
|
+
return Qnil;
|
1244
|
+
}
|
1245
|
+
}
|
1246
|
+
|
1247
|
+
static VALUE
|
1248
|
+
rb_architecture_error_instruction(VALUE self) {
|
1249
|
+
evoasm_arch_error *error;
|
1250
|
+
TypedData_Get_Struct(self, evoasm_arch_error, &rb_arch_error_type, error);
|
1251
|
+
|
1252
|
+
if(error->code == EVOASM_ARCH_ERROR_CODE_INVALID_ACCESS) {
|
1253
|
+
switch(error->data.arch->cls->id) {
|
1254
|
+
case EVOASM_ARCH_X64: return ID2SYM(rb_x64_inst_ids[error->data.inst]);
|
1255
|
+
default: evoasm_assert_not_reached();
|
1256
|
+
}
|
1257
|
+
}
|
1258
|
+
else {
|
1259
|
+
return Qnil;
|
1260
|
+
}
|
1261
|
+
}
|
1262
|
+
|
1263
|
+
static VALUE
|
1264
|
+
rb_architecture_error_architecture(VALUE self) {
|
1265
|
+
evoasm_arch_error *error;
|
1266
|
+
TypedData_Get_Struct(self, evoasm_arch_error, &rb_arch_error_type, error);
|
1267
|
+
|
1268
|
+
if(error->data.arch->user_data != NULL) {
|
1269
|
+
return (VALUE) error->data.arch->user_data;
|
1270
|
+
}
|
1271
|
+
else {
|
1272
|
+
evoasm_assert_not_reached();
|
1273
|
+
}
|
1274
|
+
}
|
1275
|
+
|
1276
|
+
static VALUE
|
1277
|
+
rb_x64_alloc(VALUE klass) {
|
1278
|
+
evoasm_x64 *x64 = xmalloc(sizeof(evoasm_x64));
|
1279
|
+
|
1280
|
+
return TypedData_Wrap_Struct(klass, &rb_x64_type, x64);
|
1281
|
+
}
|
1282
|
+
|
1283
|
+
static VALUE
|
1284
|
+
rb_x64_initialize(VALUE self) {
|
1285
|
+
evoasm_x64 *x64;
|
1286
|
+
TypedData_Get_Struct(self, evoasm_x64, &rb_x64_type, x64);
|
1287
|
+
|
1288
|
+
EVOASM_TRY(raise, evoasm_x64_init, x64);
|
1289
|
+
((evoasm_arch *)x64)->user_data = (void *) self;
|
1290
|
+
|
1291
|
+
return self;
|
1292
|
+
|
1293
|
+
raise:
|
1294
|
+
evoasm_raise_last_error();
|
1295
|
+
return Qnil;
|
1296
|
+
}
|
1297
|
+
|
1298
|
+
static VALUE
|
1299
|
+
x64_instruction_encode(evoasm_x64_inst *inst, evoasm_x64 *x64, VALUE rb_params) {
|
1300
|
+
evoasm_x64_params *params;
|
1301
|
+
evoasm_x64_params _params = {0};
|
1302
|
+
evoasm_arch *arch = (evoasm_arch *) x64;
|
1303
|
+
VALUE rb_str;
|
1304
|
+
|
1305
|
+
switch(TYPE(rb_params)) {
|
1306
|
+
case T_DATA:
|
1307
|
+
TypedData_Get_Struct(rb_params, evoasm_x64_params, &rb_x64_params_type, params);
|
1308
|
+
break;
|
1309
|
+
case T_HASH:
|
1310
|
+
x64_params_set_from_hash(&_params, rb_params);
|
1311
|
+
params = &_params;
|
1312
|
+
break;
|
1313
|
+
default:
|
1314
|
+
rb_raise(rb_eArgError, "parameters must be hash or Evoasm::X64::Parameters");
|
1315
|
+
return Qnil;
|
1316
|
+
}
|
1317
|
+
|
1318
|
+
EVOASM_TRY(raise, evoasm_inst_encode, (evoasm_inst *)inst, arch, params->vals, (evoasm_bitmap *) ¶ms->set);
|
1319
|
+
|
1320
|
+
rb_str = rb_usascii_str_new((char *)(arch->buf + arch->buf_start),
|
1321
|
+
(long) (arch->buf_end - arch->buf_start));
|
1322
|
+
evoasm_arch_reset(arch);
|
1323
|
+
return rb_str;
|
1324
|
+
|
1325
|
+
raise:
|
1326
|
+
evoasm_raise_last_error();
|
1327
|
+
return Qnil;
|
1328
|
+
|
1329
|
+
}
|
1330
|
+
|
1331
|
+
static VALUE
|
1332
|
+
rb_x64_encode(int argc, VALUE *argv, VALUE self) {
|
1333
|
+
evoasm_x64 *x64;
|
1334
|
+
unsigned i;
|
1335
|
+
ID id;
|
1336
|
+
VALUE rb_params;
|
1337
|
+
VALUE rb_inst_name;
|
1338
|
+
evoasm_x64_inst *inst = NULL;
|
1339
|
+
|
1340
|
+
rb_scan_args(argc, argv, "2", &rb_inst_name, &rb_params);
|
1341
|
+
|
1342
|
+
Check_Type(rb_inst_name, T_SYMBOL);
|
1343
|
+
Check_Type(rb_params, T_HASH);
|
1344
|
+
id = SYM2ID(rb_inst_name);
|
1345
|
+
|
1346
|
+
TypedData_Get_Struct(self, evoasm_x64, &rb_x64_type, x64);
|
1347
|
+
|
1348
|
+
for(i = 0; i < EVOASM_X64_N_INSTS; i++) {
|
1349
|
+
if(rb_x64_inst_ids[i] == id) {
|
1350
|
+
inst = (evoasm_x64_inst *) evoasm_x64_get_inst(x64, i, true);
|
1351
|
+
break;
|
1352
|
+
}
|
1353
|
+
}
|
1354
|
+
|
1355
|
+
if(inst == NULL) {
|
1356
|
+
rb_raise(rb_eArgError, "unknown instruction");
|
1357
|
+
return Qnil;
|
1358
|
+
}
|
1359
|
+
|
1360
|
+
return x64_instruction_encode(inst, x64, rb_params);
|
1361
|
+
}
|
1362
|
+
|
1363
|
+
static VALUE
|
1364
|
+
rb_x64_register_id(VALUE self) {
|
1365
|
+
evoasm_x64_operand *op;
|
1366
|
+
TypedData_Get_Struct(self, evoasm_x64_operand, &rb_x64_reg_type, op);
|
1367
|
+
return UINT2NUM(op->reg_id);
|
1368
|
+
}
|
1369
|
+
|
1370
|
+
static VALUE
|
1371
|
+
rb_x64_register_name(VALUE self) {
|
1372
|
+
evoasm_x64_operand *op;
|
1373
|
+
TypedData_Get_Struct(self, evoasm_x64_operand, &rb_x64_reg_type, op);
|
1374
|
+
if(op->reg_id < EVOASM_X64_N_REGS) {
|
1375
|
+
return ID2SYM(rb_x64_reg_ids[op->reg_id]);
|
1376
|
+
}
|
1377
|
+
else {
|
1378
|
+
return Qnil;
|
1379
|
+
}
|
1380
|
+
}
|
1381
|
+
|
1382
|
+
static VALUE
|
1383
|
+
rb_x64_register_type(VALUE self) {
|
1384
|
+
evoasm_x64_operand *op;
|
1385
|
+
TypedData_Get_Struct(self, evoasm_x64_operand, &rb_x64_reg_type, op);
|
1386
|
+
return ID2SYM(rb_x64_reg_type_ids[op->reg_type]);
|
1387
|
+
}
|
1388
|
+
|
1389
|
+
static VALUE
|
1390
|
+
rb_x64_operand_type(VALUE self) {
|
1391
|
+
evoasm_x64_operand *op;
|
1392
|
+
TypedData_Get_Struct(self, evoasm_x64_operand, &rb_x64_op_type, op);
|
1393
|
+
|
1394
|
+
return ID2SYM(rb_x64_operand_type_ids[op->type]);
|
1395
|
+
}
|
1396
|
+
|
1397
|
+
static VALUE
|
1398
|
+
rb_x64_operand_written_p(VALUE self) {
|
1399
|
+
evoasm_x64_operand *op;
|
1400
|
+
TypedData_Get_Struct(self, evoasm_x64_operand, &rb_x64_op_type, op);
|
1401
|
+
|
1402
|
+
return op->acc_w ? Qtrue : Qfalse;
|
1403
|
+
}
|
1404
|
+
|
1405
|
+
static VALUE
|
1406
|
+
rb_x64_operand_read_p(VALUE self) {
|
1407
|
+
evoasm_x64_operand *op;
|
1408
|
+
TypedData_Get_Struct(self, evoasm_x64_operand, &rb_x64_op_type, op);
|
1409
|
+
|
1410
|
+
return op->acc_r ? Qtrue : Qfalse;
|
1411
|
+
}
|
1412
|
+
|
1413
|
+
static VALUE
|
1414
|
+
rb_x64_operand_register(VALUE self) {
|
1415
|
+
evoasm_x64_operand *op;
|
1416
|
+
TypedData_Get_Struct(self, evoasm_x64_operand, &rb_x64_op_type, op);
|
1417
|
+
|
1418
|
+
if(op->type == EVOASM_X64_OPERAND_TYPE_REG ||
|
1419
|
+
op->type == EVOASM_X64_OPERAND_TYPE_RM) {
|
1420
|
+
VALUE rb_reg = TypedData_Wrap_Struct(cX64Register, &rb_x64_reg_type, op);
|
1421
|
+
return rb_reg;
|
1422
|
+
}
|
1423
|
+
|
1424
|
+
return Qnil;
|
1425
|
+
}
|
1426
|
+
|
1427
|
+
static VALUE
|
1428
|
+
rb_x64_operand_size(VALUE self) {
|
1429
|
+
evoasm_x64_operand *op;
|
1430
|
+
TypedData_Get_Struct(self, evoasm_x64_operand, &rb_x64_op_type, op);
|
1431
|
+
|
1432
|
+
switch(op->size) {
|
1433
|
+
case EVOASM_OPERAND_SIZE_1: return INT2FIX(1);
|
1434
|
+
case EVOASM_OPERAND_SIZE_8: return INT2FIX(8);
|
1435
|
+
case EVOASM_OPERAND_SIZE_16: return INT2FIX(16);
|
1436
|
+
case EVOASM_OPERAND_SIZE_32: return INT2FIX(32);
|
1437
|
+
case EVOASM_OPERAND_SIZE_64: return INT2FIX(64);
|
1438
|
+
case EVOASM_OPERAND_SIZE_128: return INT2FIX(128);
|
1439
|
+
case EVOASM_OPERAND_SIZE_256: return INT2FIX(256);
|
1440
|
+
case EVOASM_OPERAND_SIZE_512: return INT2FIX(512);
|
1441
|
+
default: return Qnil;
|
1442
|
+
}
|
1443
|
+
return Qnil;
|
1444
|
+
}
|
1445
|
+
|
1446
|
+
static VALUE
|
1447
|
+
rb_parameter_name(VALUE self) {
|
1448
|
+
evoasm_arch_param *param;
|
1449
|
+
TypedData_Get_Struct(self, evoasm_arch_param, &rb_param_type, param);
|
1450
|
+
return ID2SYM(rb_x64_param_ids[param->id]);
|
1451
|
+
}
|
1452
|
+
|
1453
|
+
static VALUE
|
1454
|
+
rb_parameter_id(VALUE self) {
|
1455
|
+
evoasm_arch_param *param;
|
1456
|
+
TypedData_Get_Struct(self, evoasm_arch_param, &rb_param_type, param);
|
1457
|
+
return UINT2NUM(param->id);
|
1458
|
+
}
|
1459
|
+
|
1460
|
+
static VALUE
|
1461
|
+
rb_domain_to_rb(evoasm_domain *domain) {
|
1462
|
+
VALUE rb_domain;
|
1463
|
+
|
1464
|
+
switch(domain->type) {
|
1465
|
+
case EVOASM_DOMAIN_TYPE_INTERVAL: {
|
1466
|
+
evoasm_interval *interval = (evoasm_interval *) domain;
|
1467
|
+
rb_domain = rb_range_new(LL2NUM(interval->min), LL2NUM(interval->max), false);
|
1468
|
+
break;
|
1469
|
+
}
|
1470
|
+
case EVOASM_DOMAIN_TYPE_ENUM: {
|
1471
|
+
evoasm_enum *enm = (evoasm_enum *) domain;
|
1472
|
+
uint16_t j;
|
1473
|
+
VALUE *enm_vals = ALLOCA_N(VALUE, enm->len);
|
1474
|
+
for(j = 0; j < enm->len; j++) {
|
1475
|
+
enm_vals[j] = LL2NUM(enm->vals[j]);
|
1476
|
+
}
|
1477
|
+
rb_domain = rb_ary_new_from_values(enm->len, enm_vals);
|
1478
|
+
break;
|
1479
|
+
}
|
1480
|
+
default: evoasm_assert_not_reached();
|
1481
|
+
}
|
1482
|
+
|
1483
|
+
return rb_domain;
|
1484
|
+
}
|
1485
|
+
|
1486
|
+
static VALUE
|
1487
|
+
rb_parameter_domain(VALUE self) {
|
1488
|
+
evoasm_arch_param *param;
|
1489
|
+
evoasm_domain *domain;
|
1490
|
+
VALUE rb_domain;
|
1491
|
+
|
1492
|
+
TypedData_Get_Struct(self, evoasm_arch_param, &rb_param_type, param);
|
1493
|
+
|
1494
|
+
domain = param->domain;
|
1495
|
+
rb_domain = RARRAY_AREF(domains_cache, domain->index);
|
1496
|
+
|
1497
|
+
if(NIL_P(rb_domain)) {
|
1498
|
+
rb_domain = rb_domain_to_rb(domain);
|
1499
|
+
rb_obj_freeze(rb_domain);
|
1500
|
+
}
|
1501
|
+
RARRAY_ASET(domains_cache, domain->index, rb_domain);
|
1502
|
+
return rb_domain;
|
1503
|
+
}
|
1504
|
+
|
1505
|
+
|
1506
|
+
static VALUE
|
1507
|
+
rb_architecture_instructions(VALUE self) {
|
1508
|
+
evoasm_arch *arch;
|
1509
|
+
evoasm_inst **insts;
|
1510
|
+
uint16_t len, i;
|
1511
|
+
VALUE *vals;
|
1512
|
+
|
1513
|
+
TypedData_Get_Struct(self, evoasm_arch, &rb_arch_type, arch);
|
1514
|
+
insts = ALLOCA_N(evoasm_inst *, arch->cls->n_insts);
|
1515
|
+
len = evoasm_arch_insts(arch, (const evoasm_inst **) insts);
|
1516
|
+
if(len == 0) return Qnil;
|
1517
|
+
|
1518
|
+
vals = ALLOCA_N(VALUE, len);
|
1519
|
+
|
1520
|
+
for(i = 0; i < len; i++) {
|
1521
|
+
switch(arch->cls->id) {
|
1522
|
+
case EVOASM_ARCH_X64: {
|
1523
|
+
rb_evoasm_x64_inst *inst = ALLOC(rb_evoasm_x64_inst);
|
1524
|
+
inst->arch = self;
|
1525
|
+
inst->inst = (evoasm_x64_inst *) insts[i];
|
1526
|
+
vals[i] = TypedData_Wrap_Struct(evoasm_cX64Instruction, &rb_x64_inst_type, inst);
|
1527
|
+
break;
|
1528
|
+
}
|
1529
|
+
default: evoasm_assert_not_reached();
|
1530
|
+
}
|
1531
|
+
}
|
1532
|
+
|
1533
|
+
return rb_ary_new_from_values(len, vals);
|
1534
|
+
}
|
1535
|
+
|
1536
|
+
static VALUE
|
1537
|
+
rb_instruction_id(VALUE self) {
|
1538
|
+
rb_evoasm_inst *inst;
|
1539
|
+
TypedData_Get_Struct(self, rb_evoasm_inst, &rb_inst_type, inst);
|
1540
|
+
|
1541
|
+
return UINT2NUM(inst->inst->id);
|
1542
|
+
}
|
1543
|
+
|
1544
|
+
static VALUE
|
1545
|
+
rb_x64_instruction_flags(VALUE self) {
|
1546
|
+
rb_evoasm_x64_inst *inst;
|
1547
|
+
TypedData_Get_Struct(self, rb_evoasm_x64_inst, &rb_x64_inst_type, inst);
|
1548
|
+
|
1549
|
+
return ULL2NUM(inst->inst->flags);
|
1550
|
+
}
|
1551
|
+
|
1552
|
+
|
1553
|
+
static VALUE
|
1554
|
+
rb_x64_instruction_operands(VALUE self) {
|
1555
|
+
rb_evoasm_x64_inst *inst;
|
1556
|
+
unsigned i;
|
1557
|
+
VALUE *vals;
|
1558
|
+
|
1559
|
+
TypedData_Get_Struct(self, rb_evoasm_x64_inst, &rb_x64_inst_type, inst);
|
1560
|
+
|
1561
|
+
if(inst->inst->n_operands == 0) {
|
1562
|
+
return rb_ary_new();
|
1563
|
+
}
|
1564
|
+
|
1565
|
+
vals = ALLOC_N(VALUE, inst->inst->n_operands);
|
1566
|
+
|
1567
|
+
for(i = 0; i < inst->inst->n_operands; i++) {
|
1568
|
+
vals[i] = TypedData_Wrap_Struct(cX64Operand, &rb_x64_op_type, (void *)&inst->inst->operands[i]);
|
1569
|
+
}
|
1570
|
+
return rb_ary_new_from_values(inst->inst->n_operands, vals);
|
1571
|
+
}
|
1572
|
+
|
1573
|
+
static VALUE
|
1574
|
+
rb_x64_instruction_features(VALUE self) {
|
1575
|
+
rb_evoasm_x64_inst *inst;
|
1576
|
+
TypedData_Get_Struct(self, rb_evoasm_x64_inst, &rb_x64_inst_type, inst);
|
1577
|
+
|
1578
|
+
return ULL2NUM(inst->inst->features);
|
1579
|
+
}
|
1580
|
+
|
1581
|
+
static VALUE
|
1582
|
+
rb_x64_instruction_name(VALUE self) {
|
1583
|
+
rb_evoasm_x64_inst *inst;
|
1584
|
+
TypedData_Get_Struct(self, rb_evoasm_x64_inst, &rb_inst_type, inst);
|
1585
|
+
|
1586
|
+
return ID2SYM(rb_x64_inst_ids[((evoasm_inst *)inst->inst)->id]);
|
1587
|
+
}
|
1588
|
+
|
1589
|
+
static VALUE
|
1590
|
+
rb_x64_instruction_encode(VALUE self, VALUE rb_params) {
|
1591
|
+
rb_evoasm_x64_inst *inst;
|
1592
|
+
evoasm_x64 *x64;
|
1593
|
+
|
1594
|
+
TypedData_Get_Struct(self, rb_evoasm_x64_inst, &rb_x64_inst_type, inst);
|
1595
|
+
TypedData_Get_Struct(inst->arch, evoasm_x64, &rb_x64_type, x64);
|
1596
|
+
|
1597
|
+
return x64_instruction_encode(inst->inst, x64, rb_params);
|
1598
|
+
}
|
1599
|
+
|
1600
|
+
static VALUE
|
1601
|
+
rb_instruction_parameters(VALUE self) {
|
1602
|
+
rb_evoasm_inst *inst;
|
1603
|
+
uint16_t i;
|
1604
|
+
VALUE *vals;
|
1605
|
+
|
1606
|
+
TypedData_Get_Struct(self, rb_evoasm_inst, &rb_inst_type, inst);
|
1607
|
+
|
1608
|
+
if(inst->inst->params_len == 0) {
|
1609
|
+
return rb_ary_new();
|
1610
|
+
}
|
1611
|
+
|
1612
|
+
vals = ALLOC_N(VALUE, inst->inst->params_len);
|
1613
|
+
|
1614
|
+
for(i = 0; i < inst->inst->params_len; i++) {
|
1615
|
+
vals[i] = TypedData_Wrap_Struct(cParameter, &rb_param_type, (void *)&inst->inst->params[i]);
|
1616
|
+
}
|
1617
|
+
return rb_ary_new_from_values(inst->inst->params_len, vals);
|
1618
|
+
}
|
1619
|
+
|
1620
|
+
VALUE rb_evoasm_log_level;
|
1621
|
+
|
1622
|
+
static VALUE
|
1623
|
+
rb_evoasm_log_level_set(VALUE self, VALUE level) {
|
1624
|
+
evoasm_log_level prev_level = evoasm_min_log_level;
|
1625
|
+
evoasm_min_log_level = (evoasm_log_level)
|
1626
|
+
EVOASM_CLAMP(FIX2INT(level),
|
1627
|
+
EVOASM_MIN_LOG_LEVEL, EVOASM_N_LOG_LEVELS - 1);
|
1628
|
+
|
1629
|
+
fprintf(stderr, "%d\n", evoasm_min_log_level);
|
1630
|
+
return INT2FIX(prev_level);
|
1631
|
+
}
|
1632
|
+
|
1633
|
+
extern const uint16_t evoasm_n_domains;
|
1634
|
+
|
1635
|
+
void Init_evoasm_ext() {
|
1636
|
+
mEvoasm = rb_define_module("Evoasm");
|
1637
|
+
|
1638
|
+
cArchitecture = rb_define_class_under(mEvoasm, "Architecture", rb_cData);
|
1639
|
+
cX64 = rb_define_class_under(mEvoasm, "X64", cArchitecture);
|
1640
|
+
cParameter = rb_define_class_under(mEvoasm, "Parameter", rb_cData);
|
1641
|
+
cRegister = rb_define_class_under(mEvoasm, "Register", rb_cData);
|
1642
|
+
cX64Register = rb_define_class_under(cX64, "Register", cRegister);
|
1643
|
+
cOperand = rb_define_class_under(mEvoasm, "Operand", rb_cData);
|
1644
|
+
cX64Operand = rb_define_class_under(cX64, "Operand", cOperand);
|
1645
|
+
cBuffer = rb_define_class_under(mEvoasm, "Buffer", rb_cData);
|
1646
|
+
cSearch = rb_define_class_under(mEvoasm, "Search", rb_cData);
|
1647
|
+
cProgram = rb_define_class_under(mEvoasm, "Program", rb_cData);
|
1648
|
+
cKernel = rb_define_class_under(mEvoasm, "Kernel", rb_cData);
|
1649
|
+
cParameters = rb_define_class_under(mEvoasm, "Parameters", rb_cData);
|
1650
|
+
cX64Parameters = rb_define_class_under(cX64, "Parameters", cParameters);
|
1651
|
+
cInstruction = rb_define_class_under(mEvoasm, "Instruction", rb_cData);
|
1652
|
+
evoasm_cX64Instruction = rb_define_class_under(cX64, "Instruction", cInstruction);
|
1653
|
+
|
1654
|
+
rb_define_singleton_method(mEvoasm, "log_level=", rb_evoasm_log_level_set, 1);
|
1655
|
+
|
1656
|
+
eError = rb_define_class_under(mEvoasm, "Error", rb_eStandardError);
|
1657
|
+
eArchitectureError = rb_define_class_under(cArchitecture, "Error", eError);
|
1658
|
+
rb_define_method(eError, "code", RUBY_METHOD_FUNC(rb_error_code), 0);
|
1659
|
+
rb_define_method(eError, "__message", RUBY_METHOD_FUNC(rb_error_message), 0);
|
1660
|
+
rb_define_method(eArchitectureError, "code", RUBY_METHOD_FUNC(rb_architecture_error_code), 0);
|
1661
|
+
rb_define_method(eArchitectureError, "parameter", RUBY_METHOD_FUNC(rb_architecture_error_parameter), 0);
|
1662
|
+
rb_define_method(eArchitectureError, "register", RUBY_METHOD_FUNC(rb_architecture_error_register), 0);
|
1663
|
+
rb_define_method(eArchitectureError, "instruction", RUBY_METHOD_FUNC(rb_architecture_error_instruction), 0);
|
1664
|
+
rb_define_method(eArchitectureError, "architecture", RUBY_METHOD_FUNC(rb_architecture_error_architecture), 0);
|
1665
|
+
|
1666
|
+
evoasm_x64_ruby_define_consts();
|
1667
|
+
|
1668
|
+
error_code_unknown = rb_intern("unknown");
|
1669
|
+
error_code_not_encodable = rb_intern("not_encodable");
|
1670
|
+
error_code_missing_param = rb_intern("missing_param");
|
1671
|
+
error_code_invalid_access = rb_intern("invalid_access");
|
1672
|
+
error_code_missing_feature = rb_intern("missing_feature");
|
1673
|
+
|
1674
|
+
rb_define_alloc_func(cBuffer, rb_buffer_alloc);
|
1675
|
+
rb_define_method(cBuffer, "initialize", rb_buffer_initialize, -1);
|
1676
|
+
rb_define_method(cBuffer, "size", RUBY_METHOD_FUNC(rb_buffer_size), 0);
|
1677
|
+
rb_define_method(cBuffer, "reset!", RUBY_METHOD_FUNC(rb_buffer_reset), 0);
|
1678
|
+
rb_define_method(cBuffer, "to_s", RUBY_METHOD_FUNC(rb_buffer_to_s), 0);
|
1679
|
+
#ifdef HAVE_CAPSTONE_CAPSTONE_H
|
1680
|
+
rb_define_method(cBuffer, "disassemble", rb_buffer_disassemble, 0);
|
1681
|
+
#endif
|
1682
|
+
|
1683
|
+
rb_define_alloc_func(cSearch, rb_search_alloc);
|
1684
|
+
rb_define_private_method(cSearch, "__initialize__", rb_search_initialize, -1);
|
1685
|
+
rb_define_method(cSearch, "start!", rb_search_start, 1);
|
1686
|
+
|
1687
|
+
#if 0
|
1688
|
+
rb_define_method(cX64, "rw!", RUBY_METHOD_FUNC(rb_buffer_rw), 0);
|
1689
|
+
rb_define_method(cX64, "rx!", RUBY_METHOD_FUNC(rb_buffer_rx), 0);
|
1690
|
+
#endif
|
1691
|
+
|
1692
|
+
rb_define_alloc_func(cProgram, rb_program_alloc);
|
1693
|
+
rb_define_method(cProgram, "buffer", rb_program_buffer, -1);
|
1694
|
+
rb_define_method(cProgram, "kernels", rb_program_kernels, 0);
|
1695
|
+
rb_define_private_method(cProgram, "__run__", rb_program_run, 2);
|
1696
|
+
rb_define_method(cProgram, "eliminate_introns!", rb_program_eliminate_introns_bang, 0);
|
1697
|
+
rb_define_method(cProgram, "output_registers", rb_program_output_registers, 0);
|
1698
|
+
|
1699
|
+
rb_define_alloc_func(cKernel, rb_kernel_alloc);
|
1700
|
+
rb_define_method(cKernel, "parameters", rb_kernel_parameters, 0);
|
1701
|
+
rb_define_method(cKernel, "instructions", rb_kernel_instructions, 0);
|
1702
|
+
|
1703
|
+
rb_define_method(cParameter, "domain", rb_parameter_domain, 0);
|
1704
|
+
rb_define_method(cParameter, "name", rb_parameter_name, 0);
|
1705
|
+
rb_define_method(cParameter, "id", rb_parameter_id, 0);
|
1706
|
+
|
1707
|
+
rb_define_method(cX64Register, "id", rb_x64_register_id, 0);
|
1708
|
+
rb_define_method(cX64Register, "name", rb_x64_register_name, 0);
|
1709
|
+
rb_define_method(cX64Register, "type", rb_x64_register_type, 0);
|
1710
|
+
|
1711
|
+
rb_define_method(cX64Operand, "type", rb_x64_operand_type, 0);
|
1712
|
+
rb_define_method(cX64Operand, "written?", rb_x64_operand_written_p, 0);
|
1713
|
+
rb_define_method(cX64Operand, "read?", rb_x64_operand_read_p, 0);
|
1714
|
+
rb_define_method(cX64Operand, "register", rb_x64_operand_register, 0);
|
1715
|
+
rb_define_method(cX64Operand, "size", rb_x64_operand_size, 0);
|
1716
|
+
|
1717
|
+
rb_define_method(cInstruction, "id", rb_instruction_id, 0);
|
1718
|
+
rb_define_method(cInstruction, "parameters", rb_instruction_parameters, 0);
|
1719
|
+
|
1720
|
+
rb_define_method(evoasm_cX64Instruction, "encode", rb_x64_instruction_encode, 0);
|
1721
|
+
rb_define_method(evoasm_cX64Instruction, "name", rb_x64_instruction_name, 0);
|
1722
|
+
rb_define_method(evoasm_cX64Instruction, "flags", rb_x64_instruction_flags, 0);
|
1723
|
+
rb_define_method(evoasm_cX64Instruction, "features", rb_x64_instruction_features, 0);
|
1724
|
+
rb_define_method(evoasm_cX64Instruction, "operands", rb_x64_instruction_operands, 0);
|
1725
|
+
|
1726
|
+
rb_define_alloc_func(cX64, rb_x64_alloc);
|
1727
|
+
rb_define_method(cX64, "initialize", rb_x64_initialize, 0);
|
1728
|
+
rb_define_method(cX64, "encode", rb_x64_encode, -1);
|
1729
|
+
#ifdef HAVE_CAPSTONE_CAPSTONE_H
|
1730
|
+
rb_define_singleton_method(cX64, "disassemble", rb_x64_s_disassemble, 1);
|
1731
|
+
#endif
|
1732
|
+
|
1733
|
+
rb_define_method(cArchitecture, "instructions", RUBY_METHOD_FUNC(rb_architecture_instructions), 0);
|
1734
|
+
|
1735
|
+
rb_define_alloc_func(cX64Parameters, rb_x64_parameters_alloc);
|
1736
|
+
rb_define_method(cX64Parameters, "initialize", rb_x64_parameters_initialize, -1);
|
1737
|
+
|
1738
|
+
rb_define_method(cX64Parameters, "[]=", RUBY_METHOD_FUNC(rb_x64_parameters_aset), 2);
|
1739
|
+
rb_define_method(cX64Parameters, "[]", RUBY_METHOD_FUNC(rb_x64_parameters_aref), 1);
|
1740
|
+
|
1741
|
+
rb_define_const(mEvoasm,
|
1742
|
+
"ARCH_X64", UINT2NUM(EVOASM_ARCH_X64));
|
1743
|
+
|
1744
|
+
domains_cache = rb_ary_new2(evoasm_n_domains);
|
1745
|
+
rb_ary_resize(domains_cache, evoasm_n_domains);
|
1746
|
+
rb_gc_register_address(&domains_cache);
|
1747
|
+
|
1748
|
+
instructions_cache = rb_ary_new2(EVOASM_X64_N_INSTS);
|
1749
|
+
rb_ary_resize(instructions_cache, EVOASM_X64_N_INSTS);
|
1750
|
+
rb_gc_register_address(&instructions_cache);
|
1751
|
+
|
1752
|
+
rb_id_brute_force = rb_intern("brute_force");
|
1753
|
+
rb_id_genetic = rb_intern("genetic");
|
1754
|
+
rb_id_id = rb_intern("id");
|
1755
|
+
|
1756
|
+
evoasm_init(0, NULL, stderr);
|
1757
|
+
}
|