This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
Re: gcc vs vc++: Calling data as code
Greetings,
I think the attached source does what you ask. Seems to work on my
linux box.
% gcc -v
Reading specs from /usr/lib/gcc-lib/i386-slackware-linux/egcs-2.91.66/specs
gcc version egcs-2.91.66 19990314/Linux (egcs-1.1.2 release)
% uname -a
Linux 3eye 2.2.13 #3 Sun Dec 26 02:14:38 PST 1999 i686 unknown
* Robert Feldt (feldt@ce.chalmers.se) [20000724 23:42]:
[...]
> My friend has an application were machine code is manipulated in buffers
> and then called as code. Here's the challenge and my first effort to solve
> it:
>
> Challenge: Implement the functions f1 and f2 below without writing
> them in C code, ie. by having their machine code in a buffer and
> calling it. Since his interest is in the Wintel architecture it does
> not need to work on other machines/architectures.
>
> float f1(float* in) {
> return in[0] + in[1];
> }
>
> float out[2];
>
> void f2(float* in1, float* in2) {
> out[0] = in[0] + in2[0];
> out[1] = in[1] - in1[1];
> }
[...]
Best regards,
patrick
--
We've heard that a million monkeys at a million keyboards could
produce the Complete Works of Shakespeare; now, thanks to the
Internet, we know this is not true.
-Robert Wilensky
/*
* struct_as_func.c
*
* $Id: $
*
* patrick keshishian <patrick at boxsoft dot com>
* Tue, 25 Jul 2000 03:48:57 -0700
*
* This code is released under the terms of GPL license.
* See http://www.gnu.org/ for more info.
*
*
* In response to:
*
* From: Robert Feldt <feldt at ce dot chalmers dot se>
* To: gcc at gcc dot gnu dot org
* Subject: gcc vs vc++: Calling data as code
* Date: Tue, 25 Jul 2000 07:26:03 +0200 (MET DST)
* Message-ID: <Pine.GSO.3.96.1000725072336.14639A-100000@explorer.ce.chalmers.se>
*
*
* Enjoy. :>
*
*/
#include <stdlib.h>
#include <stdio.h>
float f1(float* in) {
return in[0] + in[1];
}
float out[2];
void f2(float* in1, float* in2) {
out[0] = in1[0] + in2[0];
out[1] = in1[1] - in2[1];
}
typedef float (* f1_ptr) (float*);
typedef void (* f2_ptr) (float*, float*);
const int ix86_ret = 0xC3;
int main( void )
{
// size of functions
//
int sof1 = 0;
int sof2 = 0;
// the functions represented as an array of unsigned chars (data)
//
unsigned char* f1data = NULL;
unsigned char* f2data = NULL;
unsigned char* p = NULL;
int i = 0;
// our data to pass to the functions
//
float in1[] = { 1.0, 2.0 };
float in2[] = { 5.0, 9.0 };
// find out the amount of memory allocate for each function
//
p = (unsigned char*)f1;
while ( *p++ != ix86_ret ) sof1++;
p = (unsigned char*)f2;
while ( *p++ != ix86_ret ) sof2++;
// lets allocate memory for our data
//
f1data = (unsigned char*) malloc( sof1 );
if ( !f1data ) {
printf( "Failed to allocate memory for f1\n" );
exit(1);
}
f2data = (unsigned char*) malloc( sof2 );
if ( !f2data ) {
printf( "Failed to allocate memory for f2\n" );
exit(1);
}
// copy the actually function's memory layout to our unsigned char
// arrays.
//
i = 0;
p = (unsigned char*)f1;
while ( (f1data[i++] = *p) != ix86_ret ) p++;
i = 0;
p = (unsigned char*)f2;
while ( (f2data[i++] = *p) != ix86_ret ) p++;
// lets see if this werks :>
//
printf( "Calling f1( in1 ). Should get 3.0\n" );
printf( "%f\n\n", (*(f1_ptr)f1data)(in1) );
printf( "Calling f2( in1, in2 ). Should get: out[] = { 6.0, -7.0 }\n" );
(*(f2_ptr)f2data)(in1,in2);
printf( "out[0] = %f\tout[1] = %f\n\n", out[0], out[1] );
// be good and release resources we've used
//
free(f1data);
free(f2data);
return 0;
}