asmjit 0.2.1 → 0.2.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: de98dc21826687ba3eaf5dab23f2b223f87018bdede78fd6ba3d08c2e9378cac
4
- data.tar.gz: 25f0372836707935c0dd32aa4ee711fd3a30823187c698cfdcc00a0918b1f847
3
+ metadata.gz: 841e0bc2866c0dc8be23dc5f79bd4fcf97dba35a516841932e0420beae3c0af2
4
+ data.tar.gz: b050d3e81b1616d2adc10ccd84d2a767e17102e409dd5fa4d0507ffa4483c9c9
5
5
  SHA512:
6
- metadata.gz: b9827a4879f31537e28860448be8d042fc87a3018f4c1efdac2c2ba60484f2a42d10dfede47c79abddd4ccdbd4766db943421718c26ecba9d353bcb8b6b25f4c
7
- data.tar.gz: 0ebbb002f38caa880aed25d78d592d08959923b614ddc0e9d33f951b47f508289462857c19e64295a7fffcdf47446ab19f4d027084c27a8c31d3c9839c9177bf
6
+ metadata.gz: fa3d2263a8a05e7420e1fa5c36b3af14aee7ee1bda312fa46cb866c5b6bafa5d14e7d0960cd8d4c20ef5c4771bb47dfa3505ab377a06dbb377317fe5edda03d7
7
+ data.tar.gz: ce9a931463e08ea916edc7b627bf4b41a56c538217fe659e0b9ebc864277d71799b4347efd9b0c8304435329b779c20c95c19b932f5915660cbcf8db4f608c12
data/Rakefile CHANGED
@@ -4,10 +4,12 @@ require "bundler/gem_tasks"
4
4
  require "rake/testtask"
5
5
 
6
6
  Rake::TestTask.new(:test) do |t|
7
- t.libs << "test"
8
- t.libs << "lib"
7
+ t.libs << "test" << "lib"
9
8
  t.test_files = FileList["test/**/test_*.rb"]
9
+ t.verbose = true
10
+ t.warning = true
10
11
  end
12
+ task test: :compile
11
13
 
12
14
  require "rake/extensiontask"
13
15
 
@@ -17,4 +19,4 @@ Rake::ExtensionTask.new("asmjit") do |ext|
17
19
  ext.lib_dir = "lib/asmjit"
18
20
  end
19
21
 
20
- task default: %i[clobber compile test]
22
+ task default: %i[test]
data/asmjit.gemspec CHANGED
@@ -28,6 +28,4 @@ Gem::Specification.new do |spec|
28
28
  spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
29
29
  spec.require_paths = ["lib"]
30
30
  spec.extensions = ["ext/asmjit/extconf.rb"]
31
-
32
- spec.add_development_dependency "hatstone"
33
31
  end
data/ext/asmjit/asmjit.cc CHANGED
@@ -7,10 +7,14 @@ using namespace std;
7
7
 
8
8
  using namespace asmjit;
9
9
 
10
+ static BaseEmitter *get_emitter(VALUE self);
11
+
10
12
  static VALUE rb_mAsmjit;
11
13
  static VALUE rb_eAsmJITError;
12
14
  static VALUE rb_cOperand;
13
15
  static VALUE cX86Reg;
16
+ static VALUE cLabel;
17
+ static VALUE cImm;
14
18
  static VALUE cX86Mem;
15
19
 
16
20
  static JitRuntime jit_runtime;
@@ -23,13 +27,32 @@ class RubyErrorHandler : public ErrorHandler {
23
27
  };
24
28
  RubyErrorHandler rubyErrorHandler;
25
29
 
30
+ class RubyLogger : public Logger {
31
+ public:
32
+ RubyLogger(VALUE obj) : obj(obj) {}
33
+ VALUE obj;
34
+
35
+ Error _log(const char* data, size_t size) noexcept override {
36
+ VALUE string;
37
+ if (size == SIZE_MAX) {
38
+ string = rb_str_new_cstr(data);
39
+ } else {
40
+ string = rb_str_new(data, size);
41
+ }
42
+ rb_funcall(obj, rb_intern("<<"), 1, string);
43
+ return kErrorOk;
44
+ }
45
+ };
46
+
26
47
  struct CodeHolderWrapper {
27
48
  CodeHolder *code;
49
+ RubyLogger *logger;
28
50
  };
29
51
 
30
52
  void code_holder_free(void *data) {
31
53
  CodeHolderWrapper *wrapper = static_cast<CodeHolderWrapper *>(data);
32
54
  delete wrapper->code;
55
+ delete wrapper->logger;
33
56
  xfree(wrapper);
34
57
  }
35
58
 
@@ -47,11 +70,41 @@ static const rb_data_type_t code_holder_type = {
47
70
  VALUE code_holder_alloc(VALUE self) {
48
71
  CodeHolderWrapper *wrapper = static_cast<CodeHolderWrapper *>(xmalloc(sizeof(CodeHolderWrapper)));
49
72
  wrapper->code = new CodeHolder();
73
+ wrapper->logger = NULL;
50
74
  wrapper->code->setErrorHandler(&rubyErrorHandler);
51
75
 
52
76
  return TypedData_Wrap_Struct(self, &code_holder_type, wrapper);
53
77
  }
54
78
 
79
+ VALUE code_holder_set_logger(VALUE self, VALUE object) {
80
+ CodeHolderWrapper *wrapper;
81
+ TypedData_Get_Struct(self, CodeHolderWrapper, &code_holder_type, wrapper);
82
+
83
+ if (wrapper->logger) {
84
+ wrapper->code->resetLogger();
85
+ delete wrapper->logger;
86
+ }
87
+
88
+ if (RTEST(object)) {
89
+ wrapper->logger = new RubyLogger(object);
90
+ wrapper->logger->setFlags(FormatFlags::kHexImms);
91
+ wrapper->code->setLogger(wrapper->logger);
92
+ }
93
+
94
+ return object;
95
+ }
96
+
97
+ VALUE code_holder_get_logger(VALUE self) {
98
+ CodeHolderWrapper *wrapper;
99
+ TypedData_Get_Struct(self, CodeHolderWrapper, &code_holder_type, wrapper);
100
+
101
+ if (wrapper->logger) {
102
+ return wrapper->logger->obj;
103
+ } else {
104
+ return Qnil;
105
+ }
106
+ }
107
+
55
108
  VALUE code_holder_initialize(VALUE self) {
56
109
  CodeHolderWrapper *wrapper;
57
110
  TypedData_Get_Struct(self, CodeHolderWrapper, &code_holder_type, wrapper);
@@ -133,21 +186,29 @@ static VALUE build_register(const char *c_name, x86::Reg reg) {
133
186
  return obj;
134
187
  }
135
188
 
136
- static VALUE build_label(Label label) {
137
- OperandWrapper *wrapper = static_cast<OperandWrapper *>(xmalloc(sizeof(OperandWrapper)));
138
- wrapper->opnd = label;
139
-
140
- VALUE obj = TypedData_Wrap_Struct(cX86Reg, &operand_type, wrapper);
141
- return obj;
142
- }
143
-
144
-
145
189
  static Operand opnd_get(VALUE val) {
146
190
  OperandWrapper *wrapper;
147
191
  TypedData_Get_Struct(val, OperandWrapper, &operand_type, wrapper);
148
192
  return wrapper->opnd;
149
193
  }
150
194
 
195
+ static VALUE operand_to_s(VALUE obj) {
196
+ Operand opnd = opnd_get(obj);
197
+ Arch arch = jit_runtime.arch();
198
+
199
+ const BaseEmitter *emitter = NULL;
200
+
201
+ VALUE emitterv = rb_iv_get(obj, "@emitter");
202
+ if (RTEST(emitterv)) {
203
+ emitter = get_emitter(emitterv);
204
+ }
205
+
206
+ String s;
207
+ Formatter::formatOperand(s, FormatFlags::kNone, emitter, arch, opnd);
208
+
209
+ return rb_str_new(s.data(), s.size());
210
+ }
211
+
151
212
  static Label label_get(VALUE val) {
152
213
  Operand opnd = opnd_get(val);
153
214
  if (!opnd.isLabel()) {
@@ -188,17 +249,68 @@ static VALUE x86_ptr(VALUE _self, VALUE regv, VALUE offsetv, VALUE sizev) {
188
249
  return obj;
189
250
  }
190
251
 
252
+ static VALUE imm_new(VALUE _self, VALUE val) {
253
+ Imm imm = Imm(NUM2LL(val));
254
+
255
+ OperandWrapper *wrapper = static_cast<OperandWrapper *>(xmalloc(sizeof(OperandWrapper)));
256
+ wrapper->opnd = imm;
257
+ return TypedData_Wrap_Struct(_self, &operand_type, wrapper);
258
+ }
259
+
191
260
  static VALUE build_registers_hash() {
192
261
  VALUE hash = rb_hash_new();
193
262
 
194
263
  #define REGISTER(name) rb_hash_aset(hash, ID2SYM(rb_intern(#name)), build_register((#name), x86::name))
195
264
 
265
+ REGISTER(ah);
266
+ REGISTER(bh);
267
+ REGISTER(ch);
268
+ REGISTER(dh);
269
+
270
+ REGISTER(al);
271
+ REGISTER(bl);
272
+ REGISTER(cl);
273
+ REGISTER(dl);
274
+ REGISTER(dil);
275
+ REGISTER(sil);
276
+ REGISTER(spl);
277
+ REGISTER(bpl);
278
+
279
+ REGISTER(r8b);
280
+ REGISTER(r9b);
281
+ REGISTER(r10b);
282
+ REGISTER(r11b);
283
+ REGISTER(r12b);
284
+ REGISTER(r13b);
285
+ REGISTER(r14b);
286
+ REGISTER(r15b);
287
+
288
+ REGISTER(ax);
289
+ REGISTER(bx);
290
+ REGISTER(cx);
291
+ REGISTER(dx);
292
+ REGISTER(di);
293
+ REGISTER(si);
294
+ REGISTER(sp);
295
+ REGISTER(bp);
296
+
297
+ REGISTER(r8w);
298
+ REGISTER(r9w);
299
+ REGISTER(r10w);
300
+ REGISTER(r11w);
301
+ REGISTER(r12w);
302
+ REGISTER(r13w);
303
+ REGISTER(r14w);
304
+ REGISTER(r15w);
305
+
196
306
  REGISTER(eax);
197
307
  REGISTER(ebx);
198
308
  REGISTER(ecx);
199
309
  REGISTER(edx);
200
310
  REGISTER(edi);
201
311
  REGISTER(esi);
312
+ REGISTER(esp);
313
+ REGISTER(ebp);
202
314
 
203
315
  REGISTER(r8d);
204
316
  REGISTER(r9d);
@@ -215,6 +327,8 @@ static VALUE build_registers_hash() {
215
327
  REGISTER(rdx);
216
328
  REGISTER(rdi);
217
329
  REGISTER(rsi);
330
+ REGISTER(rsp);
331
+ REGISTER(rbp);
218
332
 
219
333
  REGISTER(r8);
220
334
  REGISTER(r9);
@@ -257,6 +371,12 @@ static const rb_data_type_t base_emitter_type = {
257
371
  .flags = RUBY_TYPED_FREE_IMMEDIATELY,
258
372
  };
259
373
 
374
+ static BaseEmitter *get_emitter(VALUE self) {
375
+ BaseEmitterWrapper *wrapper;
376
+ TypedData_Get_Struct(self, BaseEmitterWrapper, &base_emitter_type, wrapper);
377
+ return wrapper->emitter;
378
+ }
379
+
260
380
  VALUE x86_assembler_new(VALUE self, VALUE code_holder) {
261
381
  BaseEmitterWrapper *wrapper = static_cast<BaseEmitterWrapper *>(xmalloc(sizeof(CodeHolderWrapper)));
262
382
 
@@ -272,28 +392,21 @@ VALUE x86_assembler_new(VALUE self, VALUE code_holder) {
272
392
  return TypedData_Wrap_Struct(self, &base_emitter_type, wrapper);
273
393
  }
274
394
 
275
- Operand parse_operand(VALUE val) {
276
- if (FIXNUM_P(val)) {
277
- return Imm(NUM2LL(val));
278
- } else if (rb_obj_is_kind_of(val, rb_cOperand)) {
279
- return opnd_get(val);
280
- }
281
- rb_raise(rb_eAsmJITError, "bad operand: %" PRIsVALUE, val);
282
- }
283
-
284
395
  VALUE base_emitter_new_label(VALUE self) {
285
- BaseEmitterWrapper *wrapper;
286
- TypedData_Get_Struct(self, BaseEmitterWrapper, &base_emitter_type, wrapper);
287
- BaseEmitter *emitter = wrapper->emitter;
396
+ BaseEmitter *emitter = get_emitter(self);
288
397
 
289
398
  Label label = emitter->newLabel();
290
- return build_label(label);
399
+
400
+ OperandWrapper *opnd_wrapper = static_cast<OperandWrapper *>(xmalloc(sizeof(OperandWrapper)));
401
+ opnd_wrapper->opnd = label;
402
+
403
+ VALUE obj = TypedData_Wrap_Struct(cLabel, &operand_type, opnd_wrapper);
404
+ rb_iv_set(obj, "@emitter", self);
405
+ return obj;
291
406
  }
292
407
 
293
408
  VALUE base_emitter_bind(VALUE self, VALUE labelv) {
294
- BaseEmitterWrapper *wrapper;
295
- TypedData_Get_Struct(self, BaseEmitterWrapper, &base_emitter_type, wrapper);
296
- BaseEmitter *emitter = wrapper->emitter;
409
+ BaseEmitter *emitter = get_emitter(self);
297
410
 
298
411
  Label label = label_get(labelv);
299
412
 
@@ -306,10 +419,7 @@ VALUE base_emitter_bind(VALUE self, VALUE labelv) {
306
419
  }
307
420
 
308
421
  VALUE base_emitter_emit(int argc, VALUE* argv, VALUE self) {
309
- BaseEmitterWrapper *wrapper;
310
- TypedData_Get_Struct(self, BaseEmitterWrapper, &base_emitter_type, wrapper);
311
-
312
- BaseEmitter *emitter = wrapper->emitter;
422
+ BaseEmitter *emitter = get_emitter(self);
313
423
 
314
424
  if (argc < 1) return Qnil;
315
425
  if (argc > 7) return Qnil;
@@ -320,7 +430,7 @@ VALUE base_emitter_emit(int argc, VALUE* argv, VALUE self) {
320
430
 
321
431
  Operand operands[6];
322
432
  for (int i = 0; i < argc - 1; i++) {
323
- operands[i] = parse_operand(argv[i + 1]);
433
+ operands[i] = opnd_get(argv[i + 1]);
324
434
  }
325
435
 
326
436
  emitter->emitOpArray(inst_id, &operands[0], argc - 1);
@@ -348,6 +458,9 @@ Init_asmjit(void)
348
458
  rb_define_method(cCodeHolder, "def_method", code_holder_define_method, 3);
349
459
  rb_define_method(cCodeHolder, "binary", code_holder_binary, 0);
350
460
 
461
+ rb_define_method(cCodeHolder, "logger", code_holder_get_logger, 0);
462
+ rb_define_method(cCodeHolder, "logger=", code_holder_set_logger, 1);
463
+
351
464
  VALUE rb_mX86 = rb_define_module_under(rb_mAsmjit, "X86");
352
465
 
353
466
  VALUE rb_cBaseEmitter = rb_define_class_under(rb_mAsmjit, "BaseEmitter", rb_cObject);
@@ -361,6 +474,7 @@ Init_asmjit(void)
361
474
 
362
475
  rb_cOperand = rb_define_class_under(rb_mAsmjit, "Operand", rb_cObject);
363
476
  rb_undef_alloc_func(rb_cOperand);
477
+ rb_define_method(rb_cOperand, "to_s", operand_to_s, 0);
364
478
 
365
479
  cX86Reg = rb_define_class_under(rb_mX86, "Reg", rb_cOperand);
366
480
  rb_define_attr(cX86Reg, "name", 1, 0);
@@ -368,6 +482,11 @@ Init_asmjit(void)
368
482
  cX86Mem = rb_define_class_under(rb_mX86, "Mem", rb_cOperand);
369
483
  rb_define_singleton_method(cX86Mem, "new", x86_ptr, 3);
370
484
 
485
+ cImm = rb_define_class_under(rb_mAsmjit, "Imm", rb_cOperand);
486
+ rb_define_singleton_method(cImm, "new", imm_new, 1);
487
+
488
+ cLabel = rb_define_class_under(rb_mAsmjit, "Label", rb_cOperand);
489
+
371
490
  VALUE instructions = rb_ary_new();
372
491
 
373
492
  auto instid = x86::Inst::kIdNone;
@@ -2,16 +2,16 @@
2
2
 
3
3
  require "mkmf"
4
4
 
5
- asmjit_dir = File.expand_path("asmjit/src/", __dir__)
5
+ Dir.chdir __dir__ do
6
+ $srcs = [
7
+ Dir["*.cc"],
8
+ Dir["asmjit/src/**/*.cpp"]
9
+ ].flatten.map { |f| File.basename f }
6
10
 
7
- $INCFLAGS << " -I#{asmjit_dir} "
11
+ $VPATH.concat Dir["asmjit/src/**/"].map { |x| "$(srcdir)/#{x}" }
12
+ end
8
13
 
9
- $CXXFLAGS << " -DASMJIT_EMBED "
10
-
11
- $srcs = []
12
- $srcs.concat Dir[File.join(__dir__, "*.cc")]
13
- $srcs.concat Dir[File.join(asmjit_dir, "**/*.cpp")]
14
-
15
- $objs = $srcs.map{|x| x.gsub(/\.(cc|cpp)\z/, ".o") }
14
+ append_cppflags("-I$(srcdir)/asmjit/src")
15
+ append_cppflags("-DASMJIT_EMBED")
16
16
 
17
17
  create_makefile("asmjit/asmjit")
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module AsmJIT
4
- VERSION = "0.2.1"
4
+ VERSION = "0.2.2"
5
5
  end
data/lib/asmjit.rb CHANGED
@@ -5,8 +5,7 @@ require_relative "asmjit/asmjit"
5
5
 
6
6
  AsmJit = AsmJIT
7
7
  module AsmJIT
8
- def self.assemble
9
- code = CodeHolder.new
8
+ def self.assemble(code = CodeHolder.new)
10
9
  yield code.assembler
11
10
  code
12
11
  end
@@ -39,13 +38,24 @@ module AsmJIT
39
38
  end
40
39
  end
41
40
 
41
+ class Operand
42
+ def inspect
43
+ "#<#{self.class} #{to_s}>"
44
+ end
45
+ end
46
+
42
47
  module X86
43
48
  module Helpers
44
49
  extend self
45
50
 
46
51
  def parse_operand(arg)
47
- if Symbol === arg && reg = REGISTERS[arg]
48
- reg
52
+ case arg
53
+ when Operand
54
+ arg
55
+ when Symbol
56
+ REGISTERS.fetch(arg)
57
+ when Integer
58
+ Imm.new(arg)
49
59
  else
50
60
  arg
51
61
  end
metadata CHANGED
@@ -1,29 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: asmjit
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.2.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - John Hawthorn
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-09-12 00:00:00.000000000 Z
12
- dependencies:
13
- - !ruby/object:Gem::Dependency
14
- name: hatstone
15
- requirement: !ruby/object:Gem::Requirement
16
- requirements:
17
- - - ">="
18
- - !ruby/object:Gem::Version
19
- version: '0'
20
- type: :development
21
- prerelease: false
22
- version_requirements: !ruby/object:Gem::Requirement
23
- requirements:
24
- - - ">="
25
- - !ruby/object:Gem::Version
26
- version: '0'
11
+ date: 2022-10-22 00:00:00.000000000 Z
12
+ dependencies: []
27
13
  description: 'Ruby wrapper for asmjit: a lightweight library for machine code generation'
28
14
  email:
29
15
  - john@hawthorn.email
@@ -262,7 +248,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
262
248
  - !ruby/object:Gem::Version
263
249
  version: '0'
264
250
  requirements: []
265
- rubygems_version: 3.4.0.dev
251
+ rubygems_version: 3.3.7
266
252
  signing_key:
267
253
  specification_version: 4
268
254
  summary: 'Ruby wrapper for asmjit: a lightweight library for machine code generation'