This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

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;
}

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]