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.
Files changed (75) hide show
  1. checksums.yaml +7 -0
  2. data/.gemrelease +2 -0
  3. data/.gitignore +16 -0
  4. data/Gemfile +4 -0
  5. data/Gemfile.rake +8 -0
  6. data/Gemfile.rake.lock +51 -0
  7. data/LICENSE.txt +373 -0
  8. data/Makefile +6 -0
  9. data/README.md +43 -0
  10. data/Rakefile +128 -0
  11. data/bin/gdb +2 -0
  12. data/data/tables/README.md +19 -0
  13. data/data/tables/x64.csv +1684 -0
  14. data/data/templates/evoasm-x64.c.erb +319 -0
  15. data/data/templates/evoasm-x64.h.erb +126 -0
  16. data/evoasm.gemspec +30 -0
  17. data/examples/abs.yml +20 -0
  18. data/examples/popcnt.yml +17 -0
  19. data/examples/sym_reg.yml +26 -0
  20. data/exe/evoasm-search +13 -0
  21. data/ext/evoasm_ext/evoasm-alloc.c +145 -0
  22. data/ext/evoasm_ext/evoasm-alloc.h +59 -0
  23. data/ext/evoasm_ext/evoasm-arch.c +44 -0
  24. data/ext/evoasm_ext/evoasm-arch.h +161 -0
  25. data/ext/evoasm_ext/evoasm-bitmap.h +114 -0
  26. data/ext/evoasm_ext/evoasm-buf.c +130 -0
  27. data/ext/evoasm_ext/evoasm-buf.h +47 -0
  28. data/ext/evoasm_ext/evoasm-error.c +31 -0
  29. data/ext/evoasm_ext/evoasm-error.h +75 -0
  30. data/ext/evoasm_ext/evoasm-free-list.c.tmpl +121 -0
  31. data/ext/evoasm_ext/evoasm-free-list.h.tmpl +86 -0
  32. data/ext/evoasm_ext/evoasm-log.c +108 -0
  33. data/ext/evoasm_ext/evoasm-log.h +69 -0
  34. data/ext/evoasm_ext/evoasm-misc.c +23 -0
  35. data/ext/evoasm_ext/evoasm-misc.h +282 -0
  36. data/ext/evoasm_ext/evoasm-param.h +37 -0
  37. data/ext/evoasm_ext/evoasm-search.c +2145 -0
  38. data/ext/evoasm_ext/evoasm-search.h +214 -0
  39. data/ext/evoasm_ext/evoasm-util.h +40 -0
  40. data/ext/evoasm_ext/evoasm-x64.c +275624 -0
  41. data/ext/evoasm_ext/evoasm-x64.h +5436 -0
  42. data/ext/evoasm_ext/evoasm.c +7 -0
  43. data/ext/evoasm_ext/evoasm.h +23 -0
  44. data/ext/evoasm_ext/evoasm_ext.c +1757 -0
  45. data/ext/evoasm_ext/extconf.rb +31 -0
  46. data/lib/evoasm/cli/search.rb +127 -0
  47. data/lib/evoasm/cli.rb +6 -0
  48. data/lib/evoasm/core_ext/array.rb +9 -0
  49. data/lib/evoasm/core_ext/integer.rb +10 -0
  50. data/lib/evoasm/core_ext/kwstruct.rb +13 -0
  51. data/lib/evoasm/core_ext/range.rb +5 -0
  52. data/lib/evoasm/core_ext.rb +1 -0
  53. data/lib/evoasm/error.rb +20 -0
  54. data/lib/evoasm/examples.rb +27 -0
  55. data/lib/evoasm/gen/enum.rb +169 -0
  56. data/lib/evoasm/gen/name_util.rb +80 -0
  57. data/lib/evoasm/gen/state.rb +176 -0
  58. data/lib/evoasm/gen/state_dsl.rb +152 -0
  59. data/lib/evoasm/gen/strio.rb +27 -0
  60. data/lib/evoasm/gen/translator.rb +1102 -0
  61. data/lib/evoasm/gen/version.rb +5 -0
  62. data/lib/evoasm/gen/x64/funcs.rb +495 -0
  63. data/lib/evoasm/gen/x64/inst.rb +781 -0
  64. data/lib/evoasm/gen/x64.rb +237 -0
  65. data/lib/evoasm/gen.rb +8 -0
  66. data/lib/evoasm/program.rb +23 -0
  67. data/lib/evoasm/search.rb +40 -0
  68. data/lib/evoasm/tasks/gen_task.rb +86 -0
  69. data/lib/evoasm/tasks/template_task.rb +52 -0
  70. data/lib/evoasm/version.rb +3 -0
  71. data/lib/evoasm.rb +22 -0
  72. data/test/test_helper.rb +1 -0
  73. data/test/x64/test_helper.rb +19 -0
  74. data/test/x64/x64_test.rb +87 -0
  75. 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 *) &params->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 *) &params->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 *) &params->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
+ }