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:
parent
64db3a3251
commit
22b07f5488
3 changed files with 122 additions and 38 deletions
23
ext/dl/dl.h
23
ext/dl/dl.h
|
@ -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;
|
||||||
|
|
|
@ -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"
|
||||||
|
|
124
ext/dl/sym.c
124
ext/dl/sym.c
|
@ -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"
|
||||||
|
|
Loading…
Reference in a new issue