asmjit 0.2.1 → 0.2.2

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