1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

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
This commit is contained in:
ttate 2002-05-11 23:13:34 +00:00
parent 64db3a3251
commit 22b07f5488
3 changed files with 122 additions and 38 deletions

View file

@ -142,8 +142,8 @@
#if defined(USE_INLINE_ASM) #if defined(USE_INLINE_ASM)
# if defined(__i386__) && defined(__GNUC__) # if defined(__i386__) && defined(__GNUC__)
# define ASM_START(type) # define ASM_START(sym)
# define ASM_END(type) # define ASM_END(sym)
# define ASM_PUSH_C(x) asm volatile ("pushl %0" :: "g" (x)); # 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_H(x) asm volatile ("pushl %0" :: "g" (x));
# define ASM_PUSH_I(x) asm volatile ("pushl %0" :: "g" (x)); # define ASM_PUSH_I(x) asm volatile ("pushl %0" :: "g" (x));
@ -158,15 +158,16 @@
# else # else
# error --with-asm is not supported on this machine # error --with-asm is not supported on this machine
# endif # endif
#else #elif defined(USE_DLSTACK)
# define ASM_START(type) # define ASM_START(sym)
# define ASM_END(type) # define ASM_END(sym)
# define ASM_PUSH_C(x) # define ASM_PUSH_C(x) memcpy(sp,&x,1); sp++;
# define ASM_PUSH_I(x) # define ASM_PUSH_H(x) memcpy(sp,&x,sizeof(short)); sp++;
# define ASM_PUSH_L(x) # define ASM_PUSH_I(x) memcpy(sp,&x,sizeof(int)); sp++;
# define ASM_PUSH_P(x) # define ASM_PUSH_L(x) memcpy(sp,&x,sizeof(long)); sp++;
# define ASM_PUSH_F(x) # define ASM_PUSH_P(x) memcpy(sp,&x,sizeof(void*)); sp++;
# define ASM_PUSH_D(x) # 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 #endif
extern VALUE rb_mDL; extern VALUE rb_mDL;

View file

@ -13,6 +13,7 @@ if( ARGV.include?("--help") )
--with-type-float strictly use type 'float' --with-type-float strictly use type 'float'
--with-asm use the embedded assembler for passing arguments. --with-asm use the embedded assembler for passing arguments.
(this option is available for i386 machine now.) (this option is available for i386 machine now.)
--with-dlstack use a stack emulation for constructing function call. [experimental]
--with-args=<max_arg>,<max_cbarg>,<max_cbent> --with-args=<max_arg>,<max_cbarg>,<max_cbent>
<max_arg>: maximum number of arguments of the function <max_arg>: maximum number of arguments of the function
<max_cbarg>: maximum number of arguments of the callback <max_cbarg>: maximum number of arguments of the callback
@ -32,6 +33,7 @@ if (Config::CONFIG['CC'] =~ /gcc/) && (Config::CONFIG['arch'] =~ /i.86/)
else else
$with_asm = false $with_asm = false
end end
$with_dlstack = false
$with_type_int = try_run(<<EOF) $with_type_int = try_run(<<EOF)
int main(){ return sizeof(int) == sizeof(long); } int main(){ return sizeof(int) == sizeof(long); }
@ -63,10 +65,11 @@ $with_type_short = enable_config("type-short", $with_type_short)
$with_type_float = enable_config("type-float", $with_type_float) $with_type_float = enable_config("type-float", $with_type_float)
$with_asm = enable_config("asm", $with_asm) $with_asm = enable_config("asm", $with_asm)
$with_dlstack = enable_config("dlstack", $with_dlstack)
args = with_config("args") args = with_config("args")
max_arg = max_cbarg = max_cbent = nil max_arg = max_cbarg = max_cbent = nil
if( $with_asm ) if( $with_asm || $with_dlstack )
$with_type_char = true $with_type_char = true
$with_type_short = true $with_type_short = true
$with_type_float = true $with_type_float = true
@ -106,8 +109,12 @@ def dlc_define(const)
"#endif\n" "#endif\n"
end end
if( $with_asm ) if( $with_dlstack )
$dlconfig_h << "#define USE_INLINE_ASM\n" $dlconfig_h << "#define USE_DLSTACK\n"
else
if( $with_asm )
$dlconfig_h << "#define USE_INLINE_ASM\n"
end
end end
if( $with_type_char ) if( $with_type_char )
$dlconfig_h << "#define WITH_TYPE_CHAR\n" $dlconfig_h << "#define WITH_TYPE_CHAR\n"

View file

@ -101,7 +101,7 @@ rb_dlsym_new(void (*func)(), const char *name, const char *type)
data->name = name ? strdup(name) : NULL; data->name = name ? strdup(name) : NULL;
data->type = type ? strdup(type) : NULL; data->type = type ? strdup(type) : NULL;
data->len = type ? strlen(type) : 0; data->len = type ? strlen(type) : 0;
#ifndef USE_INLINE_ASM #if !(defined(USE_INLINE_ASM) || defined(USE_DLSTACK))
if( data->len - 1 > MAX_ARG ){ if( data->len - 1 > MAX_ARG ){
rb_raise(rb_eDLError, "maximum number of arguments is %d.", 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; 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 VALUE
rb_dlsym_call(int argc, VALUE argv[], VALUE self) 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; func = sym->func;
#ifdef USE_INLINE_ASM #if defined(USE_INLINE_ASM) || defined(USE_DLSTACK)
ASM_START(sym->type); {
for( i = sym->len - 2; i >= 0; i-- ){ #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] ){ switch( sym->type[i+1] ){
case 'p': case 'p':
case 'P': case 'P':
@ -538,71 +613,72 @@ rb_dlsym_call(int argc, VALUE argv[], VALUE self)
switch( sym->type[0] ){ switch( sym->type[0] ){
case '0': case '0':
{ {
void (*f)() = func; void (*f)(DLSTACK_PROTO) = func;
f(); f(DLSTACK_ARGS);
}; };
break; break;
case 'P': case 'P':
case 'p': case 'p':
{ {
void * (*f)() = func; void * (*f)(DLSTACK_PROTO) = func;
ret.p = f(); ret.p = f(DLSTACK_ARGS);
}; };
break; break;
case 'C': case 'C':
case 'c': case 'c':
{ {
char (*f)() = func; char (*f)(DLSTACK_PROTO) = func;
ret.c = f(); ret.c = f(DLSTACK_ARGS);
}; };
break; break;
case 'H': case 'H':
case 'h': case 'h':
{ {
short (*f)() = func; short (*f)(DLSTACK_PROTO) = func;
ret.h = f(); ret.h = f(DLSTACK_ARGS);
}; };
break; break;
case 'I': case 'I':
case 'i': case 'i':
{ {
int (*f)() = func; int (*f)(DLSTACK_PROTO) = func;
ret.i = f(); ret.i = f(DLSTACK_ARGS);
}; };
break; break;
case 'L': case 'L':
case 'l': case 'l':
{ {
long (*f)() = func; long (*f)(DLSTACK_PROTO) = func;
ret.l = f(); ret.l = f(DLSTACK_ARGS);
}; };
break; break;
case 'F': case 'F':
case 'f': case 'f':
{ {
float (*f)() = func; float (*f)(DLSTACK_PROTO) = func;
ret.f = f(); ret.f = f(DLSTACK_ARGS);
}; };
break; break;
case 'D': case 'D':
case 'd': case 'd':
{ {
double (*f)() = func; double (*f)(DLSTACK_PROTO) = func;
ret.d = f(); ret.d = f(DLSTACK_ARGS);
}; };
break; break;
case 'S': case 'S':
case 's': case 's':
{ {
char * (*f)() = func; char * (*f)(DLSTACK_PROTO) = func;
ret.s = f(); ret.s = f(DLSTACK_ARGS);
}; };
break; break;
default: default:
FREE_ARGS; FREE_ARGS;
rb_raise(rb_eDLTypeError, "unknown type `%c'", sym->type[0]); rb_raise(rb_eDLTypeError, "unknown type `%c'", sym->type[0]);
}; }
}; }
}
#else #else
switch(ftype){ switch(ftype){
#include "call.func" #include "call.func"