8000 Merge pull request #28 from Shopify/better-disasm · github/ruby@71c6072 · GitHub
[go: up one dir, main page]

Skip to content

Commit 71c6072

Browse files
authored
Merge pull request #28 from Shopify/better-disasm
Directly link libcapstone for easier development
2 parents 2b4f91e + 5b889cc commit 71c6072

File tree

6 files changed

+93
-35
lines changed

6 files changed

+93
-35
lines changed

common.mk

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1037,6 +1037,7 @@ BUILTIN_RB_SRCS = \
10371037
$(srcdir)/timev.rb \
10381038
$(srcdir)/prelude.rb \
10391039
$(srcdir)/gem_prelude.rb \
1040+
$(srcdir)/ujit.rb \
10401041
$(empty)
10411042
BUILTIN_RB_INCS = $(BUILTIN_RB_SRCS:.rb=.rbinc)
10421043

@@ -15409,6 +15410,7 @@ ujit_core.$(OBJEXT): {$(VPATH)}vm_core.h
1540915410
ujit_core.$(OBJEXT): {$(VPATH)}vm_debug.h
1541015411
ujit_core.$(OBJEXT): {$(VPATH)}vm_opts.h
1541115412
ujit_core.$(OBJEXT): {$(VPATH)}vm_sync.h
15413+
ujit_iface.$(OBJEXT): {$(VPATH)}ujit.rbinc
1541215414
ujit_iface.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
1541315415
ujit_iface.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
1541415416
ujit_iface.$(OBJEXT): $(CCAN_DIR)/list/list.h

configure.ac

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1155,6 +1155,15 @@ AC_CHECK_LIB(dl, dlopen) # Dynamic linking for SunOS/Solaris and SYSV
11551155
AC_CHECK_LIB(dld, shl_load) # Dynamic linking for HP-UX
11561156
AC_CHECK_LIB(socket, shutdown) # SunOS/Solaris
11571157

1158+
if pkg-config --exists capstone; then
1159+
CAPSTONE_CFLAGS=`pkg-config --cflags capstone`
1160+
CAPSTONE_LIB_L=`pkg-config --libs-only-L capstone`
1161+
LDFLAGS="$LDFLAGS $CAPSTONE_LIB_L"
1162+
CFLAGS="$CFLAGS $CAPSTONE_CFLAGS"
1163+
fi
1164+
1165+
AC_CHECK_LIB(capstone, cs_open) # Capstone
1166+
11581167
dnl Checks for header files.
11591168
AC_HEADER_DIRENT
11601169
dnl AC_HEADER_STDC has been checked in AC_USE_SYSTEM_EXTENSIONS

inits.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ rb_call_builtin_inits(void)
9797
BUILTIN(array);
9898
BUILTIN(kernel);
9999
BUILTIN(timev);
100+
BUILTIN(ujit);
100101
Init_builtin_prelude();
101102
}
102103
#undef CALL

misc/ujit_disasm.rb

Lines changed: 0 additions & 35 deletions
This file was deleted.

ujit.rb

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
module UJIT
2+
def self.disasm(iseq)
3+
blocks = UJIT.blocks_for(iseq)
4+
return if blocks.empty?
5+
6+
str = ""
7+
8+
cs = UJIT::Disasm.new
9+
10+
str << iseq.disasm
11+
str << "\n"
12+
13+
blocks.sort_by(&:address).reverse.each do |block|
14+
str << "== ISEQ RANGE: #{block.iseq_start_index} -> #{block.iseq_end_index} ".ljust(80, "=")
15+
str << "\n"
16+
17+
cs.disasm(block.code, 0).each do |i|
18+
str << sprintf(
19+
"\t0x%<address>x:\t%<instruction>s\t%<details>s\n",
20+
address: i.address,
21+
instruction: i.mnemonic,
22+
details: i.op_str
23+
)
24+
end
25+
end
26+
str
27+
end if defined?(Disasm)
28+
end

ujit_iface.c

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,15 @@
1313
#include "ujit_codegen.h"
1414
#include "ujit_core.h"
1515
#include "ujit_hooks.inc"
16+
#include "ujit.rbinc"
17+
18+
#if HAVE_LIBCAPSTONE
19+
#include <capstone/capstone.h>
20+
#endif
1621

1722
VALUE cUjitBlock;
23+
VALUE cUjitDisasm;
24+
VALUE cUjitDisasmInsn;
1825

1926
extern st_table * version_tbl;
2027
extern codeblock_t *cb;
@@ -366,6 +373,44 @@ iseq_end_index(VALUE self)
366373
return INT2NUM(block->end_idx);
367374
}
368375

376+
#if HAVE_LIBCAPSTONE
377+
static const rb_data_type_t ujit_disasm_type = {
378+
"UJIT/Disasm",
379+
{0, (void(*)(void *))cs_close, 0, },
380+
0, 0, RUBY_TYPED_FREE_IMMEDIATELY
381+
};
382+
383+
static VALUE
384+
ujit_disasm_init(VALUE klass)
385+
{
386+
csh * handle;
387+
VALUE disasm = TypedData_Make_Struct(klass, csh, &ujit_disasm_type, handle);
388+
cs_open(CS_ARCH_X86, CS_MODE_64, handle);
389+
return disasm;
390+
}
391+
392+
static VALUE
393+
ujit_disasm(VALUE self, VALUE code, VALUE from)
394+
{
395+
size_t count;
396+
csh * handle;
397+
cs_insn *insns;
398+
399+
TypedData_Get_Struct(self, csh, &ujit_disasm_type, handle);
400+
count = cs_disasm(*handle, StringValuePtr(code), RSTRING_LEN(code), NUM2INT(from), 0, &insns);
401+
VALUE insn_list = rb_ary_new_capa(count);
402+
403+
for (size_t i = 0; i < count; i++) {
404+
VALUE vals = rb_ary_new_from_args(3, LONG2NUM(insns[i].address),
405+
rb_str_new2(insns[i].mnemonic),
406+
rb_str_new2(insns[i].op_str));
407+
rb_ary_push(insn_list, rb_struct_alloc(cUjitDisasmInsn, vals));
408+
}
409+
cs_free(insns, count);
410+
return insn_list;
411+
}
412+
#endif
413+
369414
void
370415
rb_ujit_init(void)
371416
{
@@ -389,6 +434,14 @@ rb_ujit_init(void)
389434
rb_define_method(cUjitBlock, "iseq_start_index", iseq_start_index, 0);
390435
rb_define_method(cUjitBlock, "iseq_end_index", iseq_end_index, 0);
391436

437+
#if HAVE_LIBCAPSTONE
438+
cUjitDisasm = rb_define_class_under(mUjit, "Disasm", rb_cObject);
439+
rb_define_alloc_func(cUjitDisasm, ujit_disasm_init);
440+
rb_define_method(cUjitDisasm, "disasm", ujit_disasm, 2);
441+
442+
cUjitDisasmInsn = rb_struct_define_under(cUjitDisasm, "Insn", "address", "mnemonic", "op_str", NULL);
443+
#endif
444+
392445
// Initialize the GC hooks
393446
method_lookup_dependency = st_init_numtable();
394447
struct ujit_root_struct *root;

0 commit comments

Comments
 (0)
0