diff --git a/plugins/ruby/codegen.pl b/plugins/ruby/codegen.pl index eb9828490..3a9db2c61 100755 --- a/plugins/ruby/codegen.pl +++ b/plugins/ruby/codegen.pl @@ -227,7 +227,7 @@ sub render_global_class { $seen_class{$name}++; local $compound_off = 0; - $compound_off = 4 if ($meta eq 'class-type'); + $compound_off = $SIZEOF_PTR if ($meta eq 'class-type'); $compound_off = sizeof($global_types{$parent}) if $parent; local $current_typename = $rbname; @@ -244,7 +244,7 @@ sub render_global_class { indent_rb { my $sz = sizeof($type); # see comment is sub sizeof ; but gcc has sizeof(cls) aligned - $sz = align_field($sz, 4) if $os eq 'linux' and $meta eq 'class-type'; + $sz = align_field($sz, $SIZEOF_PTR) if $os eq 'linux' and $meta eq 'class-type'; push @lines_rb, "sizeof $sz\n"; push @lines_rb, "rtti_classname :$rtti_name\n" if $rtti_name; @@ -425,8 +425,8 @@ sub render_class_vmethods_voff { for my $meth ($vms->findnodes('child::vmethod')) { - $voff += 4 if $meth->getAttribute('is-destructor') and $os eq 'linux'; - $voff += 4; + $voff += $SIZEOF_PTR if $meth->getAttribute('is-destructor') and $os eq 'linux'; + $voff += $SIZEOF_PTR; } return $voff; @@ -470,8 +470,8 @@ sub render_class_vmethods { } # on linux, the destructor uses 2 entries - $voff += 4 if $meth->getAttribute('is-destructor') and $os eq 'linux'; - $voff += 4; + $voff += $SIZEOF_PTR if $meth->getAttribute('is-destructor') and $os eq 'linux'; + $voff += $SIZEOF_PTR; } } @@ -598,14 +598,14 @@ sub align_field { sub get_field_align { my ($field) = @_; - my $al = 4; + my $al = $SIZEOF_PTR; my $meta = $field->getAttribute('ld:meta'); if ($meta eq 'number') { $al = sizeof($field); - # linux aligns int64_t to 4, windows to 8 + # linux aligns int64_t to $SIZEOF_PTR, windows to 8 # floats are 4 bytes so no pb - $al = 4 if ($al > 4 and ($os eq 'linux' or $al != 8)); + $al = 4 if ($al > 4 and (($os eq 'linux' and $arch == 32) or $al != 8)); } elsif ($meta eq 'global') { $al = get_global_align($field); } elsif ($meta eq 'compound') { @@ -800,11 +800,9 @@ sub sizeof_compound { $sizeof_cache{$typename} = $SIZEOF_LONG if $typename; return $SIZEOF_LONG; } - else { - print "$st type $base\n" if $base !~ /int(\d+)_t/; - $sizeof_cache{$typename} = $1/8 if $typename; - return $1/8; - } + print "$st type $base\n" if $base !~ /int(\d+)_t/; + $sizeof_cache{$typename} = $1/8 if $typename; + return $1/8; } if ($field->getAttribute('is-union')) @@ -820,11 +818,11 @@ sub sizeof_compound { my $parent = $field->getAttribute('inherits-from'); my $off = 0; - $off = 4 if ($meta eq 'class-type'); + $off = $SIZEOF_PTR if ($meta eq 'class-type'); $off = sizeof($global_types{$parent}) if ($parent); my $al = 1; - $al = 4 if ($meta eq 'class-type'); + $al = $SIZEOF_PTR if ($meta eq 'class-type'); for my $f ($field->findnodes('child::ld:field')) { diff --git a/plugins/ruby/ruby-autogen-defs.rb b/plugins/ruby/ruby-autogen-defs.rb index 7e26e93ac..c1fb07ac1 100644 --- a/plugins/ruby/ruby-autogen-defs.rb +++ b/plugins/ruby/ruby-autogen-defs.rb @@ -1,5 +1,32 @@ # definition of classes used by ruby-autogen +$sizeof_ptr = case RUBY_PLATFORM + when /x86_64|x64/i; 64 + else 32 + end + module DFHack + def self.memory_read_int64(addr) + (memory_read_int32(addr) & 0xffffffff) + (memory_read_int32(addr+4) << 32) + end + def self.memory_write_int64(addr, v) + memory_write_int32(addr, v & 0xffffffff) ; memory_write_int32(addr+4, v>>32) + end + if $sizeof_ptr == 64 + def self.memory_read_ptr(addr) + memory_read_int64(addr) & 0xffffffff_ffffffff + end + def self.memory_write_ptr(addr, v) + memory_write_int64(addr, v) + end + else + def self.memory_read_ptr(addr) + memory_read_int32(addr) & 0xffffffff + end + def self.memory_write_ptr(addr, v) + memory_write_int32(addr, v) + end + end + module MemHack INSPECT_SIZE_LIMIT=16384 class MemStruct @@ -62,6 +89,8 @@ module DFHack case tglen when 1; StlVector8.new(tg) when 2; StlVector16.new(tg) + when 4; StlVector32.new(tg) + when 8; StlVector64.new(tg) else StlVector32.new(tg) end end @@ -207,10 +236,10 @@ module DFHack def _get v = case @_bits + when 64; DFHack.memory_read_int64(@_memaddr) when 32; DFHack.memory_read_int32(@_memaddr) when 16; DFHack.memory_read_int16(@_memaddr) when 8; DFHack.memory_read_int8( @_memaddr) - when 64;(DFHack.memory_read_int32(@_memaddr) & 0xffffffff) + (DFHack.memory_read_int32(@_memaddr+4) << 32) end v &= (1 << @_bits) - 1 if not @_signed v = @_enum.sym(v) if @_enum @@ -220,10 +249,10 @@ module DFHack def _set(v) v = @_enum.int(v) if @_enum case @_bits + when 64; DFHack.memory_write_int64(@_memaddr, v) when 32; DFHack.memory_write_int32(@_memaddr, v) when 16; DFHack.memory_write_int16(@_memaddr, v) when 8; DFHack.memory_write_int8( @_memaddr, v) - when 64; DFHack.memory_write_int32(@_memaddr, v & 0xffffffff) ; DFHack.memory_write_int32(@memaddr+4, v>>32) end end @@ -299,11 +328,11 @@ module DFHack end def _getp - DFHack.memory_read_int32(@_memaddr) & 0xffffffff + DFHack.memory_read_ptr(@_memaddr) end def _setp(v) - DFHack.memory_write_int32(@_memaddr, v) + DFHack.memory_write_ptr(@_memaddr, v) end def _get @@ -316,8 +345,8 @@ module DFHack # XXX shaky... def _set(v) case v - when Pointer; DFHack.memory_write_int32(@_memaddr, v._getp) - when MemStruct; DFHack.memory_write_int32(@_memaddr, v._memaddr) + when Pointer; DFHack.memory_write_ptr(@_memaddr, v._getp) + when MemStruct; DFHack.memory_write_ptr(@_memaddr, v._memaddr) when Integer if @_tg and @_tg.kind_of?(MemHack::Number) if _getp == 0 @@ -325,9 +354,9 @@ module DFHack end @_tg._at(_getp)._set(v) else - DFHack.memory_write_int32(@_memaddr, v) + DFHack.memory_write_ptr(@_memaddr, v) end - when nil; DFHack.memory_write_int32(@_memaddr, 0) + when nil; DFHack.memory_write_ptr(@_memaddr, 0) else @_tg._at(_getp)._set(v) end end @@ -353,7 +382,7 @@ module DFHack def _getp(i=0) delta = (i != 0 ? i*@_tglen : 0) - (DFHack.memory_read_int32(@_memaddr) & 0xffffffff) + delta + DFHack.memory_read_ptr(@_memaddr) + delta end def _get @@ -364,10 +393,10 @@ module DFHack def _set(v) case v - when Pointer; DFHack.memory_write_int32(@_memaddr, v._getp) - when MemStruct; DFHack.memory_write_int32(@_memaddr, v._memaddr) - when Integer; DFHack.memory_write_int32(@_memaddr, v) - when nil; DFHack.memory_write_int32(@_memaddr, 0) + when Pointer; DFHack.memory_write_ptr(@_memaddr, v._getp) + when MemStruct; DFHack.memory_write_ptr(@_memaddr, v._memaddr) + when Integer; DFHack.memory_write_ptr(@_memaddr, v) + when nil; DFHack.memory_write_ptr(@_memaddr, 0) else raise "cannot PointerAry._set(#{v.inspect})" end end @@ -557,6 +586,20 @@ module DFHack end end end + class StlVector64 < StlVector32 + def length + DFHack.memory_vector64_length(@_memaddr) + end + def valueptr_at(idx) + DFHack.memory_vector64_ptrat(@_memaddr, idx) + end + def insert_at(idx, val) + DFHack.memory_vector64_insertat(@_memaddr, idx, val) + end + def delete_at(idx) + DFHack.memory_vector64_deleteat(@_memaddr, idx) + end + end class StlVector16 < StlVector32 def length DFHack.memory_vector16_length(@_memaddr) @@ -733,8 +776,8 @@ module DFHack @_tg = tg end - field(:_ptr, 0) { number 32, false } - field(:_length, 4) { number 16, false } + field(:_ptr, 0) { number $sizeof_ptr, false } + field(:_length, $sizeof_ptr/8) { number 16, false } def length ; _length ; end def size ; _length ; end @@ -769,8 +812,8 @@ module DFHack end field(:_ptr, 0) { pointer } - field(:_prev, 4) { pointer } - field(:_next, 8) { pointer } + field(:_prev, $sizeof_ptr/8) { pointer } + field(:_next, 2*$sizeof_ptr/8) { pointer } def item # With the current xml structure, currently _tg designate @@ -946,7 +989,7 @@ module DFHack def self.vmethod_call(obj, voff, a0=0, a1=0, a2=0, a3=0, a4=0, a5=0) this = obj._memaddr vt = df.get_vtable_ptr(this) - fptr = df.memory_read_int32(vt + voff) & 0xffffffff + fptr = df.memory_read_ptr(vt + voff) vmethod_do_call(this, fptr, vmethod_arg(a0), vmethod_arg(a1), vmethod_arg(a2), vmethod_arg(a3), vmethod_arg(a4), vmethod_arg(a5)) end diff --git a/plugins/ruby/ruby.cpp b/plugins/ruby/ruby.cpp index 276e5052b..bb3b7fe30 100644 --- a/plugins/ruby/ruby.cpp +++ b/plugins/ruby/ruby.cpp @@ -284,16 +284,15 @@ static command_result df_rubyeval(color_ostream &out, std::vector // this code should work with ruby1.9, but ruby1.9 doesn't like running // in a dedicated non-main thread, so use ruby1.8 binaries only for now -// these ruby definitions are invalid for windows 64bit (need long long) -typedef unsigned long VALUE; -typedef unsigned long ID; +typedef uintptr_t VALUE; +typedef uintptr_t ID; #define Qfalse ((VALUE)0) #define Qtrue ((VALUE)2) #define Qnil ((VALUE)4) -#define INT2FIX(i) ((VALUE)((((long)i) << 1) | 1)) -#define FIX2INT(i) (((long)i) >> 1) +#define INT2FIX(i) ((VALUE)((((intptr_t)i) << 1) | 1)) +#define FIX2INT(i) (((intptr_t)i) >> 1) #define RUBY_METHOD_FUNC(func) ((VALUE(*)(...))func) void (*ruby_init_stack)(VALUE*); @@ -313,9 +312,9 @@ VALUE (*rb_eval_string_protect)(const char*, int*); VALUE (*rb_ary_shift)(VALUE); VALUE (*rb_float_new)(double); double (*rb_num2dbl)(VALUE); -VALUE (*rb_int2inum)(long); -VALUE (*rb_uint2inum)(unsigned long); -unsigned long (*rb_num2ulong)(VALUE); +VALUE (*rb_int2inum)(intptr_t); // XXX check on win64 long vs intptr_t +VALUE (*rb_uint2inum)(uintptr_t); +uintptr_t (*rb_num2ulong)(VALUE); // end of rip(ruby.h) DFHack::DFLibrary *libruby_handle; @@ -582,14 +581,22 @@ static VALUE rb_dfget_vtable(VALUE self, VALUE name) static VALUE rb_dfget_rtti_classname(VALUE self, VALUE vptr) { char *ptr = (char*)rb_num2ulong(vptr); -#ifdef WIN32 +#if defined(_WIN64) + // win64 + char *rtti = *(char**)(ptr - 0x8); + char *typeinfo = Core::getInstance().p->getBase() + *(uint32_t*)(rtti + 0xC); + // skip the .?AV, trim @@ from end + return rb_str_new(typeinfo+0x14, strlen(typeinfo+0x14)-2); +#elif defined(WIN32) + // win32 char *rtti = *(char**)(ptr - 0x4); char *typeinfo = *(char**)(rtti + 0xC); // skip the .?AV, trim @@ from end return rb_str_new(typeinfo+0xc, strlen(typeinfo+0xc)-2); #else - char *typeinfo = *(char**)(ptr - 0x4); - char *typestring = *(char**)(typeinfo + 0x4); + // linux/osx 32/64 + char *typeinfo = *(char**)(ptr - sizeof(void*)); + char *typestring = *(char**)(typeinfo + sizeof(void*)); while (*typestring >= '0' && *typestring <= '9') typestring++; return rb_str_new(typestring, strlen(typestring)); @@ -598,8 +605,7 @@ static VALUE rb_dfget_rtti_classname(VALUE self, VALUE vptr) static VALUE rb_dfget_vtable_ptr(VALUE self, VALUE objptr) { - // actually, rb_dfmemory_read_int32 - return rb_uint2inum(*(uint32_t*)rb_num2ulong(objptr)); + return rb_uint2inum(*(uintptr_t*)rb_num2ulong(objptr)); } // run a dfhack command, as if typed from the dfhack console @@ -909,6 +915,30 @@ static VALUE rb_dfmemory_vec32_deleteat(VALUE self, VALUE addr, VALUE idx) return Qtrue; } +// vector +static VALUE rb_dfmemory_vec64_length(VALUE self, VALUE addr) +{ + std::vector *v = (std::vector*)rb_num2ulong(addr); + return rb_uint2inum(v->size()); +} +static VALUE rb_dfmemory_vec64_ptrat(VALUE self, VALUE addr, VALUE idx) +{ + std::vector *v = (std::vector*)rb_num2ulong(addr); + return rb_uint2inum((uintptr_t)&v->at(FIX2INT(idx))); +} +static VALUE rb_dfmemory_vec64_insertat(VALUE self, VALUE addr, VALUE idx, VALUE val) +{ + std::vector *v = (std::vector*)rb_num2ulong(addr); + v->insert(v->begin()+FIX2INT(idx), rb_num2ulong(val)); + return Qtrue; +} +static VALUE rb_dfmemory_vec64_deleteat(VALUE self, VALUE addr, VALUE idx) +{ + std::vector *v = (std::vector*)rb_num2ulong(addr); + v->erase(v->begin()+FIX2INT(idx)); + return Qtrue; +} + // vector static VALUE rb_dfmemory_vecbool_new(VALUE self) { @@ -1136,6 +1166,10 @@ static void ruby_bind_dfhack(void) { rb_define_singleton_method(rb_cDFHack, "memory_vector32_ptrat", RUBY_METHOD_FUNC(rb_dfmemory_vec32_ptrat), 2); rb_define_singleton_method(rb_cDFHack, "memory_vector32_insertat", RUBY_METHOD_FUNC(rb_dfmemory_vec32_insertat), 3); rb_define_singleton_method(rb_cDFHack, "memory_vector32_deleteat", RUBY_METHOD_FUNC(rb_dfmemory_vec32_deleteat), 2); + rb_define_singleton_method(rb_cDFHack, "memory_vector64_length", RUBY_METHOD_FUNC(rb_dfmemory_vec64_length), 1); + rb_define_singleton_method(rb_cDFHack, "memory_vector64_ptrat", RUBY_METHOD_FUNC(rb_dfmemory_vec64_ptrat), 2); + rb_define_singleton_method(rb_cDFHack, "memory_vector64_insertat", RUBY_METHOD_FUNC(rb_dfmemory_vec64_insertat), 3); + rb_define_singleton_method(rb_cDFHack, "memory_vector64_deleteat", RUBY_METHOD_FUNC(rb_dfmemory_vec64_deleteat), 2); rb_define_singleton_method(rb_cDFHack, "memory_vectorbool_new", RUBY_METHOD_FUNC(rb_dfmemory_vecbool_new), 0); rb_define_singleton_method(rb_cDFHack, "memory_vectorbool_delete", RUBY_METHOD_FUNC(rb_dfmemory_vecbool_delete), 1); rb_define_singleton_method(rb_cDFHack, "memory_vectorbool_init", RUBY_METHOD_FUNC(rb_dfmemory_vecbool_init), 1); diff --git a/plugins/ruby/ruby.rb b/plugins/ruby/ruby.rb index 850ca0912..7709276c8 100644 --- a/plugins/ruby/ruby.rb +++ b/plugins/ruby/ruby.rb @@ -2,14 +2,24 @@ module Kernel def puts(*a) a.flatten.each { |l| - DFHack.print_str(l.to_s.chomp + "\n") + # XXX looks like print_str crashes with strings longer than 4096... maybe not nullterminated ? + # this workaround fixes it + s = l.to_s.chomp + "\n" + while s.length > 0 + DFHack.print_str(s[0, 4000]) + s[0, 4000] = '' + end } nil end def puts_err(*a) a.flatten.each { |l| - DFHack.print_err(l.to_s.chomp + "\n") + s = l.to_s.chomp + "\n" + while s.length > 0 + DFHack.print_err(s[0, 4000]) + s[0, 4000] = '' + end } nil end