From 22b07f548866252372cb0b4a705ee9c6daf8807d Mon Sep 17 00:00:00 2001 From: ttate Date: Sat, 11 May 2002 23:13:34 +0000 Subject: enable dl's stack emulation for constructing function call. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@2450 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ext/dl/dl.h | 23 +++++----- ext/dl/extconf.rb | 13 ++++-- ext/dl/sym.c | 124 +++++++++++++++++++++++++++++++++++++++++++----------- 3 files changed, 122 insertions(+), 38 deletions(-) (limited to 'ext/dl') diff --git a/ext/dl/dl.h b/ext/dl/dl.h index a88e95d66f..ceee8c5384 100644 --- a/ext/dl/dl.h +++ b/ext/dl/dl.h @@ -142,8 +142,8 @@ #if defined(USE_INLINE_ASM) # if defined(__i386__) && defined(__GNUC__) -# define ASM_START(type) -# define ASM_END(type) +# define ASM_START(sym) +# define ASM_END(sym) # define ASM_PUSH_C(x) asm volatile ("pushl %0" :: "g" (x)); # define ASM_PUSH_H(x) asm volatile ("pushl %0" :: "g" (x)); # define ASM_PUSH_I(x) asm volatile ("pushl %0" :: "g" (x)); @@ -158,15 +158,16 @@ # else # error --with-asm is not supported on this machine # endif -#else -# define ASM_START(type) -# define ASM_END(type) -# define ASM_PUSH_C(x) -# define ASM_PUSH_I(x) -# define ASM_PUSH_L(x) -# define ASM_PUSH_P(x) -# define ASM_PUSH_F(x) -# define ASM_PUSH_D(x) +#elif defined(USE_DLSTACK) +# define ASM_START(sym) +# define ASM_END(sym) +# define ASM_PUSH_C(x) memcpy(sp,&x,1); sp++; +# define ASM_PUSH_H(x) memcpy(sp,&x,sizeof(short)); sp++; +# define ASM_PUSH_I(x) memcpy(sp,&x,sizeof(int)); sp++; +# define ASM_PUSH_L(x) memcpy(sp,&x,sizeof(long)); sp++; +# define ASM_PUSH_P(x) memcpy(sp,&x,sizeof(void*)); sp++; +# define ASM_PUSH_F(x) memcpy(sp,&x,sizeof(float)); sp+=sizeof(float)/sizeof(long); +# define ASM_PUSH_D(x) memcpy(sp,&x,sizeof(double)); sp+=sizeof(double)/sizeof(long); #endif extern VALUE rb_mDL; diff --git a/ext/dl/extconf.rb b/ext/dl/extconf.rb index d119ed1d6d..6dc6abca4e 100644 --- a/ext/dl/extconf.rb +++ b/ext/dl/extconf.rb @@ -13,6 +13,7 @@ if( ARGV.include?("--help") ) --with-type-float strictly use type 'float' --with-asm use the embedded assembler for passing arguments. (this option is available for i386 machine now.) + --with-dlstack use a stack emulation for constructing function call. [experimental] --with-args=,, : maximum number of arguments of the function : maximum number of arguments of the callback @@ -32,6 +33,7 @@ if (Config::CONFIG['CC'] =~ /gcc/) && (Config::CONFIG['arch'] =~ /i.86/) else $with_asm = false end +$with_dlstack = false $with_type_int = try_run(<name = name ? strdup(name) : NULL; data->type = type ? strdup(type) : NULL; data->len = type ? strlen(type) : 0; -#ifndef USE_INLINE_ASM +#if !(defined(USE_INLINE_ASM) || defined(USE_DLSTACK)) if( data->len - 1 > MAX_ARG ){ rb_raise(rb_eDLError, "maximum number of arguments is %d.", MAX_ARG); }; @@ -268,6 +268,47 @@ rb_dlsym_inspect(VALUE self) return val; } +static int +stack_size(struct sym_data *sym) +{ + int i; + int size; + + size = 0; + for( i=1; i < sym->len; i++ ){ + switch(sym->type[i]){ + case 'C': + case 'H': + case 'I': + case 'L': + size += sizeof(long); + break; + case 'F': + size += sizeof(float); + break; + case 'D': + size += sizeof(double); + break; + case 'c': + case 'h': + case 'i': + case 'l': + case 'f': + case 'd': + case 'p': + case 'P': + case 's': + case 'S': + case 'a': + case 'A': + size += sizeof(void*); + break; + default: + return -(sym->type[i]); + } + } + return size; +} VALUE rb_dlsym_call(int argc, VALUE argv[], VALUE self) @@ -478,9 +519,43 @@ rb_dlsym_call(int argc, VALUE argv[], VALUE self) func = sym->func; -#ifdef USE_INLINE_ASM - ASM_START(sym->type); - for( i = sym->len - 2; i >= 0; i-- ){ +#if defined(USE_INLINE_ASM) || defined(USE_DLSTACK) + { +#if defined(USE_DLSTACK) +#define DLSTACK_PROTO long,long,long,long,long,\ + long,long,long,long,long,\ + long,long,long,long,long +#define DLSTACK_ARGS stack[0],stack[1],stack[2],stack[3],stack[4],\ + stack[5],stack[6],stack[7],stack[8],stack[9],\ + stack[10],stack[11],stack[12],stack[13],stack[14] + int stk_size; + long *stack, *sp; + + stk_size = stack_size(sym); + if( stk_size < 0 ){ + FREE_ARGS; + rb_raise(rb_eDLTypeError, "unknown type '%c'.", -stk_size); + } + else if( stk_size > (int)(sizeof(long) * 15) ){ + FREE_ARGS; + rb_raise(rb_eArgError, "too many arguments."); + stk_size = sizeof(long) * 15; + } + stack = (long*)alloca(stk_size); + sp = stack; +#elif defined(USE_INLINE_ASM) +#define DLSTACK_PROTO +#define DLSTACK_ARGS +#endif + + ASM_START(sym); + +#if defined(USE_DLSTACK) + for( i = 0; i <= sym->len -2; i++ ) +#else + for( i = sym->len - 2; i >= 0; i-- ) +#endif + { switch( sym->type[i+1] ){ case 'p': case 'P': @@ -538,71 +613,72 @@ rb_dlsym_call(int argc, VALUE argv[], VALUE self) switch( sym->type[0] ){ case '0': { - void (*f)() = func; - f(); + void (*f)(DLSTACK_PROTO) = func; + f(DLSTACK_ARGS); }; break; case 'P': case 'p': { - void * (*f)() = func; - ret.p = f(); + void * (*f)(DLSTACK_PROTO) = func; + ret.p = f(DLSTACK_ARGS); }; break; case 'C': case 'c': { - char (*f)() = func; - ret.c = f(); + char (*f)(DLSTACK_PROTO) = func; + ret.c = f(DLSTACK_ARGS); }; break; case 'H': case 'h': { - short (*f)() = func; - ret.h = f(); + short (*f)(DLSTACK_PROTO) = func; + ret.h = f(DLSTACK_ARGS); }; break; case 'I': case 'i': { - int (*f)() = func; - ret.i = f(); + int (*f)(DLSTACK_PROTO) = func; + ret.i = f(DLSTACK_ARGS); }; break; case 'L': case 'l': { - long (*f)() = func; - ret.l = f(); + long (*f)(DLSTACK_PROTO) = func; + ret.l = f(DLSTACK_ARGS); }; break; case 'F': case 'f': { - float (*f)() = func; - ret.f = f(); + float (*f)(DLSTACK_PROTO) = func; + ret.f = f(DLSTACK_ARGS); }; break; case 'D': case 'd': { - double (*f)() = func; - ret.d = f(); + double (*f)(DLSTACK_PROTO) = func; + ret.d = f(DLSTACK_ARGS); }; break; case 'S': case 's': { - char * (*f)() = func; - ret.s = f(); + char * (*f)(DLSTACK_PROTO) = func; + ret.s = f(DLSTACK_ARGS); }; break; default: FREE_ARGS; rb_raise(rb_eDLTypeError, "unknown type `%c'", sym->type[0]); - }; - }; + } + } + } #else switch(ftype){ #include "call.func" -- cgit v1.2.3