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 +4 -4
- data/Rakefile +5 -3
- data/asmjit.gemspec +0 -2
- data/ext/asmjit/asmjit.cc +149 -30
- data/ext/asmjit/extconf.rb +9 -9
- data/lib/asmjit/version.rb +1 -1
- data/lib/asmjit.rb +14 -4
- metadata +4 -18
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 841e0bc2866c0dc8be23dc5f79bd4fcf97dba35a516841932e0420beae3c0af2
|
4
|
+
data.tar.gz: b050d3e81b1616d2adc10ccd84d2a767e17102e409dd5fa4d0507ffa4483c9c9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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[
|
22
|
+
task default: %i[test]
|
data/asmjit.gemspec
CHANGED
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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] =
|
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;
|
data/ext/asmjit/extconf.rb
CHANGED
@@ -2,16 +2,16 @@
|
|
2
2
|
|
3
3
|
require "mkmf"
|
4
4
|
|
5
|
-
|
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
|
-
$
|
11
|
+
$VPATH.concat Dir["asmjit/src/**/"].map { |x| "$(srcdir)/#{x}" }
|
12
|
+
end
|
8
13
|
|
9
|
-
|
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")
|
data/lib/asmjit/version.rb
CHANGED
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
|
-
|
48
|
-
|
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.
|
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-
|
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.
|
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'
|