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]

gcc vs vc++: Calling data as code



A friend of mine is a Microsoft Visual C++ afficionado and is bugging
me with claims that gcc is not as competent a compiler. He basically
means that gcc is a very general compiler but because of its
generality it doesn't give you the same degree of low-level control
that you get from specialized compilers, such as MSVC++.
Of course this is pure bullshit!

Now he has challenged me (actually it's a bet!) with a task that he
says gcc will not cope with: calling data as code. I'm having troubles
making it fully work. Can you help me? Do you know of an easily available
reference describing how gcc will compile simple functions (what
header and footer instructions are inserted, how registers are used etc.)?

Any hints/info greatly appreciated. Thanks in advance. Below you'll find
the challenge and my efforts so far...

/Robert

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

My first try was to have one program write out the code for the
functions then paste that into another one as buffers and calling
them. Program 1 (get_funcs_as_data.c):

/* Code from challenge above inserted */
typedef float(* f1_ptr) (float*);
typedef void(* f2_ptr) (float*, float*);
typedef unsigned char byte;
int main() {
  f1_ptr f1p = f1;
  f2_ptr f2p = f2;
  printf("f1:"); 
  while( *((byte*)f1p) != 0xC3 ) // 0xC3 == RET in intelX86
    printf(",%d", *((byte*)f1p)++);
  printf(",%d\n\nf2:", 0xC3); 
  while( *((byte*)f2p) != 0xC3 ) // 0xC3 == RET in intelX86
    printf(" %d", *((byte*)f2p)++);
  return 1;
}

I compile this and paste the output into program 2 (call_f1_as_data.c):

typedef float(* f1_ptr) (float*);
typedef unsigned char byte;
int main() {
  byte f1[] = {85, 137, 229, 139, 69, 8, 139, 85, 8, 131, 194, 4, 217, 0,
216, 2, 235, 0, 137, 236, 93, 195};
  float in[] = {1.0, 2.0};
  printf( "%f\n", (*((f1_ptr)f1))(in));
}

This works fine and outputs 3.0. However, for f2 I need to substitute
the actual adress of the output array into the code buffer. I guess I
could understand were to insert it by printing out some variations on
the f2 function but instead I'd like a reference describing how gcc
will typically compile simple functions into machine code.

Any other hints on how to do this would be greatly appreciated. Have
you got any ideas how I can do the programs fully platform-independet
so that I can really show him the beauty of gcc? 
Ideas for other ways to do it?


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