Merged branch develop into develop

develop
Japa 2016-10-21 22:55:38 +05:30
commit 25a64a2102
4 changed files with 134 additions and 49 deletions

@ -227,7 +227,7 @@ sub render_global_class {
$seen_class{$name}++; $seen_class{$name}++;
local $compound_off = 0; 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; $compound_off = sizeof($global_types{$parent}) if $parent;
local $current_typename = $rbname; local $current_typename = $rbname;
@ -244,7 +244,7 @@ sub render_global_class {
indent_rb { indent_rb {
my $sz = sizeof($type); my $sz = sizeof($type);
# see comment is sub sizeof ; but gcc has sizeof(cls) aligned # 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, "sizeof $sz\n";
push @lines_rb, "rtti_classname :$rtti_name\n" if $rtti_name; 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')) for my $meth ($vms->findnodes('child::vmethod'))
{ {
$voff += 4 if $meth->getAttribute('is-destructor') and $os eq 'linux'; $voff += $SIZEOF_PTR if $meth->getAttribute('is-destructor') and $os eq 'linux';
$voff += 4; $voff += $SIZEOF_PTR;
} }
return $voff; return $voff;
@ -470,8 +470,8 @@ sub render_class_vmethods {
} }
# on linux, the destructor uses 2 entries # on linux, the destructor uses 2 entries
$voff += 4 if $meth->getAttribute('is-destructor') and $os eq 'linux'; $voff += $SIZEOF_PTR if $meth->getAttribute('is-destructor') and $os eq 'linux';
$voff += 4; $voff += $SIZEOF_PTR;
} }
} }
@ -598,14 +598,14 @@ sub align_field {
sub get_field_align { sub get_field_align {
my ($field) = @_; my ($field) = @_;
my $al = 4; my $al = $SIZEOF_PTR;
my $meta = $field->getAttribute('ld:meta'); my $meta = $field->getAttribute('ld:meta');
if ($meta eq 'number') { if ($meta eq 'number') {
$al = sizeof($field); $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 # 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') { } elsif ($meta eq 'global') {
$al = get_global_align($field); $al = get_global_align($field);
} elsif ($meta eq 'compound') { } elsif ($meta eq 'compound') {
@ -800,11 +800,9 @@ sub sizeof_compound {
$sizeof_cache{$typename} = $SIZEOF_LONG if $typename; $sizeof_cache{$typename} = $SIZEOF_LONG if $typename;
return $SIZEOF_LONG; return $SIZEOF_LONG;
} }
else { print "$st type $base\n" if $base !~ /int(\d+)_t/;
print "$st type $base\n" if $base !~ /int(\d+)_t/; $sizeof_cache{$typename} = $1/8 if $typename;
$sizeof_cache{$typename} = $1/8 if $typename; return $1/8;
return $1/8;
}
} }
if ($field->getAttribute('is-union')) if ($field->getAttribute('is-union'))
@ -820,11 +818,11 @@ sub sizeof_compound {
my $parent = $field->getAttribute('inherits-from'); my $parent = $field->getAttribute('inherits-from');
my $off = 0; 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); $off = sizeof($global_types{$parent}) if ($parent);
my $al = 1; 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')) for my $f ($field->findnodes('child::ld:field'))
{ {

@ -1,5 +1,32 @@
# definition of classes used by ruby-autogen # definition of classes used by ruby-autogen
$sizeof_ptr = case RUBY_PLATFORM
when /x86_64|x64/i; 64
else 32
end
module DFHack 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 module MemHack
INSPECT_SIZE_LIMIT=16384 INSPECT_SIZE_LIMIT=16384
class MemStruct class MemStruct
@ -62,6 +89,8 @@ module DFHack
case tglen case tglen
when 1; StlVector8.new(tg) when 1; StlVector8.new(tg)
when 2; StlVector16.new(tg) when 2; StlVector16.new(tg)
when 4; StlVector32.new(tg)
when 8; StlVector64.new(tg)
else StlVector32.new(tg) else StlVector32.new(tg)
end end
end end
@ -207,10 +236,10 @@ module DFHack
def _get def _get
v = case @_bits v = case @_bits
when 64; DFHack.memory_read_int64(@_memaddr)
when 32; DFHack.memory_read_int32(@_memaddr) when 32; DFHack.memory_read_int32(@_memaddr)
when 16; DFHack.memory_read_int16(@_memaddr) when 16; DFHack.memory_read_int16(@_memaddr)
when 8; DFHack.memory_read_int8( @_memaddr) when 8; DFHack.memory_read_int8( @_memaddr)
when 64;(DFHack.memory_read_int32(@_memaddr) & 0xffffffff) + (DFHack.memory_read_int32(@_memaddr+4) << 32)
end end
v &= (1 << @_bits) - 1 if not @_signed v &= (1 << @_bits) - 1 if not @_signed
v = @_enum.sym(v) if @_enum v = @_enum.sym(v) if @_enum
@ -220,10 +249,10 @@ module DFHack
def _set(v) def _set(v)
v = @_enum.int(v) if @_enum v = @_enum.int(v) if @_enum
case @_bits case @_bits
when 64; DFHack.memory_write_int64(@_memaddr, v)
when 32; DFHack.memory_write_int32(@_memaddr, v) when 32; DFHack.memory_write_int32(@_memaddr, v)
when 16; DFHack.memory_write_int16(@_memaddr, v) when 16; DFHack.memory_write_int16(@_memaddr, v)
when 8; DFHack.memory_write_int8( @_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
end end
@ -299,11 +328,11 @@ module DFHack
end end
def _getp def _getp
DFHack.memory_read_int32(@_memaddr) & 0xffffffff DFHack.memory_read_ptr(@_memaddr)
end end
def _setp(v) def _setp(v)
DFHack.memory_write_int32(@_memaddr, v) DFHack.memory_write_ptr(@_memaddr, v)
end end
def _get def _get
@ -316,8 +345,8 @@ module DFHack
# XXX shaky... # XXX shaky...
def _set(v) def _set(v)
case v case v
when Pointer; DFHack.memory_write_int32(@_memaddr, v._getp) when Pointer; DFHack.memory_write_ptr(@_memaddr, v._getp)
when MemStruct; DFHack.memory_write_int32(@_memaddr, v._memaddr) when MemStruct; DFHack.memory_write_ptr(@_memaddr, v._memaddr)
when Integer when Integer
if @_tg and @_tg.kind_of?(MemHack::Number) if @_tg and @_tg.kind_of?(MemHack::Number)
if _getp == 0 if _getp == 0
@ -325,9 +354,9 @@ module DFHack
end end
@_tg._at(_getp)._set(v) @_tg._at(_getp)._set(v)
else else
DFHack.memory_write_int32(@_memaddr, v) DFHack.memory_write_ptr(@_memaddr, v)
end end
when nil; DFHack.memory_write_int32(@_memaddr, 0) when nil; DFHack.memory_write_ptr(@_memaddr, 0)
else @_tg._at(_getp)._set(v) else @_tg._at(_getp)._set(v)
end end
end end
@ -353,7 +382,7 @@ module DFHack
def _getp(i=0) def _getp(i=0)
delta = (i != 0 ? i*@_tglen : 0) delta = (i != 0 ? i*@_tglen : 0)
(DFHack.memory_read_int32(@_memaddr) & 0xffffffff) + delta DFHack.memory_read_ptr(@_memaddr) + delta
end end
def _get def _get
@ -364,10 +393,10 @@ module DFHack
def _set(v) def _set(v)
case v case v
when Pointer; DFHack.memory_write_int32(@_memaddr, v._getp) when Pointer; DFHack.memory_write_ptr(@_memaddr, v._getp)
when MemStruct; DFHack.memory_write_int32(@_memaddr, v._memaddr) when MemStruct; DFHack.memory_write_ptr(@_memaddr, v._memaddr)
when Integer; DFHack.memory_write_int32(@_memaddr, v) when Integer; DFHack.memory_write_ptr(@_memaddr, v)
when nil; DFHack.memory_write_int32(@_memaddr, 0) when nil; DFHack.memory_write_ptr(@_memaddr, 0)
else raise "cannot PointerAry._set(#{v.inspect})" else raise "cannot PointerAry._set(#{v.inspect})"
end end
end end
@ -557,6 +586,20 @@ module DFHack
end end
end 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 class StlVector16 < StlVector32
def length def length
DFHack.memory_vector16_length(@_memaddr) DFHack.memory_vector16_length(@_memaddr)
@ -733,8 +776,8 @@ module DFHack
@_tg = tg @_tg = tg
end end
field(:_ptr, 0) { number 32, false } field(:_ptr, 0) { number $sizeof_ptr, false }
field(:_length, 4) { number 16, false } field(:_length, $sizeof_ptr/8) { number 16, false }
def length ; _length ; end def length ; _length ; end
def size ; _length ; end def size ; _length ; end
@ -769,8 +812,8 @@ module DFHack
end end
field(:_ptr, 0) { pointer } field(:_ptr, 0) { pointer }
field(:_prev, 4) { pointer } field(:_prev, $sizeof_ptr/8) { pointer }
field(:_next, 8) { pointer } field(:_next, 2*$sizeof_ptr/8) { pointer }
def item def item
# With the current xml structure, currently _tg designate # 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) def self.vmethod_call(obj, voff, a0=0, a1=0, a2=0, a3=0, a4=0, a5=0)
this = obj._memaddr this = obj._memaddr
vt = df.get_vtable_ptr(this) 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_do_call(this, fptr, vmethod_arg(a0), vmethod_arg(a1), vmethod_arg(a2),
vmethod_arg(a3), vmethod_arg(a4), vmethod_arg(a5)) vmethod_arg(a3), vmethod_arg(a4), vmethod_arg(a5))
end end

@ -284,16 +284,15 @@ static command_result df_rubyeval(color_ostream &out, std::vector <std::string>
// this code should work with ruby1.9, but ruby1.9 doesn't like running // 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 // 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 uintptr_t VALUE;
typedef unsigned long VALUE; typedef uintptr_t ID;
typedef unsigned long ID;
#define Qfalse ((VALUE)0) #define Qfalse ((VALUE)0)
#define Qtrue ((VALUE)2) #define Qtrue ((VALUE)2)
#define Qnil ((VALUE)4) #define Qnil ((VALUE)4)
#define INT2FIX(i) ((VALUE)((((long)i) << 1) | 1)) #define INT2FIX(i) ((VALUE)((((intptr_t)i) << 1) | 1))
#define FIX2INT(i) (((long)i) >> 1) #define FIX2INT(i) (((intptr_t)i) >> 1)
#define RUBY_METHOD_FUNC(func) ((VALUE(*)(...))func) #define RUBY_METHOD_FUNC(func) ((VALUE(*)(...))func)
void (*ruby_init_stack)(VALUE*); void (*ruby_init_stack)(VALUE*);
@ -313,9 +312,9 @@ VALUE (*rb_eval_string_protect)(const char*, int*);
VALUE (*rb_ary_shift)(VALUE); VALUE (*rb_ary_shift)(VALUE);
VALUE (*rb_float_new)(double); VALUE (*rb_float_new)(double);
double (*rb_num2dbl)(VALUE); double (*rb_num2dbl)(VALUE);
VALUE (*rb_int2inum)(long); VALUE (*rb_int2inum)(intptr_t); // XXX check on win64 long vs intptr_t
VALUE (*rb_uint2inum)(unsigned long); VALUE (*rb_uint2inum)(uintptr_t);
unsigned long (*rb_num2ulong)(VALUE); uintptr_t (*rb_num2ulong)(VALUE);
// end of rip(ruby.h) // end of rip(ruby.h)
DFHack::DFLibrary *libruby_handle; 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) static VALUE rb_dfget_rtti_classname(VALUE self, VALUE vptr)
{ {
char *ptr = (char*)rb_num2ulong(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 *rtti = *(char**)(ptr - 0x4);
char *typeinfo = *(char**)(rtti + 0xC); char *typeinfo = *(char**)(rtti + 0xC);
// skip the .?AV, trim @@ from end // skip the .?AV, trim @@ from end
return rb_str_new(typeinfo+0xc, strlen(typeinfo+0xc)-2); return rb_str_new(typeinfo+0xc, strlen(typeinfo+0xc)-2);
#else #else
char *typeinfo = *(char**)(ptr - 0x4); // linux/osx 32/64
char *typestring = *(char**)(typeinfo + 0x4); char *typeinfo = *(char**)(ptr - sizeof(void*));
char *typestring = *(char**)(typeinfo + sizeof(void*));
while (*typestring >= '0' && *typestring <= '9') while (*typestring >= '0' && *typestring <= '9')
typestring++; typestring++;
return rb_str_new(typestring, strlen(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) static VALUE rb_dfget_vtable_ptr(VALUE self, VALUE objptr)
{ {
// actually, rb_dfmemory_read_int32 return rb_uint2inum(*(uintptr_t*)rb_num2ulong(objptr));
return rb_uint2inum(*(uint32_t*)rb_num2ulong(objptr));
} }
// run a dfhack command, as if typed from the dfhack console // 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; return Qtrue;
} }
// vector<uint64>
static VALUE rb_dfmemory_vec64_length(VALUE self, VALUE addr)
{
std::vector<uint64_t> *v = (std::vector<uint64_t>*)rb_num2ulong(addr);
return rb_uint2inum(v->size());
}
static VALUE rb_dfmemory_vec64_ptrat(VALUE self, VALUE addr, VALUE idx)
{
std::vector<uint64_t> *v = (std::vector<uint64_t>*)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<uint64_t> *v = (std::vector<uint64_t>*)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<uint64_t> *v = (std::vector<uint64_t>*)rb_num2ulong(addr);
v->erase(v->begin()+FIX2INT(idx));
return Qtrue;
}
// vector<bool> // vector<bool>
static VALUE rb_dfmemory_vecbool_new(VALUE self) 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_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_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_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_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_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); rb_define_singleton_method(rb_cDFHack, "memory_vectorbool_init", RUBY_METHOD_FUNC(rb_dfmemory_vecbool_init), 1);

@ -2,14 +2,24 @@
module Kernel module Kernel
def puts(*a) def puts(*a)
a.flatten.each { |l| 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 nil
end end
def puts_err(*a) def puts_err(*a)
a.flatten.each { |l| 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 nil
end end