evoasm 0.0.2.pre7

Sign up to get free protection for your applications and to get access to all the features.
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
+ }