Re: Passing execution to a memory address



polas <nick@xxxxxxxxxxxxx> wrote:
reader=fopen("sample", "r"); /* Open in TEXT mode */

Another reason you might not be able to just read in a binary and jump
to the code is the fact that there is likely to be all kinds of header
on the file "sample" that's not executable. Getting to the code itself
can potentially be extremely complicated, and is certainly
system-dependent.

About a billion years ago, a friend of mine and I did what you're trying
(under MS-DOS). We built a little "a-life" arena where the organisms'
behaviors were written in C, compiled to assembly, and carefully
assembled. We then loaded them up dynamically at runtime and jumped
into them when it was time to execute a particular behavior.

Very extremely non-portable. And it barely worked. For instance
(IIRC), the compiler would emit assembly for switch() statements that
assumed you weren't running in the data segment. And, hey; who can
blame it.

So... I'm probably going to make some people cringe, but here's a
program that illustrates more of what you're trying to see. Instead of
loading a binary off disk, it just copies a function that's already in
memory. At the very least, it's an example of what isn't portable in
code that you might conceivably find in the wild.

I should emphasize that this is really very not-portable. It produced a
"correct" result for me on my system (I was a little surprised I could
execute in that memory, but there we are), but really who knows what
it'll do on your system. Maybe it hangs your system! Maybe it
reformats your hard drive! Your mileage may vary, truly!

Working on the a-life program, once the system froze up and, upon
reboot, I found all my BIOS settings were demolished. That was fun.
Similar experiences sometimes occurred under PalmOS where the
double-secret reset was required.

All this adds up to one thing: in real life, do what everyone said and
use some kind of dynamic loader functionality. In fake life, however,
this kind of underhanded dealing can give you neat insights into how
your particular system and compiler work.

-Beej

========================== 8< ==========================

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/* Some problems with this nonstandard nonportable code:
**
** Line 21: results of unrelated pointer arithmetic undefined
** Line 22: forbidden initialization of function pointer with void pointer
** Line 25: forbidden conversion of function pointers to void pointers
*/

int add1(int x)
{
return x+1;
}

void end_of_add1(void) {}

int main(void)
{
int add1size = (int)end_of_add1 - (int)add1; /* LINE 21 */
int (*newfunc)(int) = malloc(add1size); /* LINE 22 */
int res;

memcpy(newfunc, add1, add1size); /* LINE 25 */

res = newfunc(3);
printf("res = %d\n", res); /* prints "4" (if you're lucky) */

return 0;
}

.



Relevant Pages

  • Re: Is an unsigned integer big enough to store a void *?
    ... any type of int is the same size as a pointer. ... > If I use an unsigned integer to store a void pointer, ...
    (microsoft.public.vc.mfc)
  • Re: Some pointer quiestions again
    ... A function pointer can be converted to a void pointer but ... You can do the conversion with a cast: ... >void pointer reliably, if not then there would appear to be no portable ...
    (comp.lang.c)
  • Re: Pointer to functions
    ... pointer and to allow conversion back to the original pointer. ... You are, however, allowed to convert any function pointer to any other ... cannot be represented by void *, ... void f2(int a, int b); ...
    (comp.lang.c)
  • Re: [C] 2-dimensional arrays and functions
    ... >> following the operator binding direction and precendence rules. ... > takes no parameters and returns function pointer of signature........ ... synonym for int f. ...
    (alt.comp.lang.learn.c-cpp)
  • Re: operator precedence
    ... > - typecast the void pointer into a type pointer ... But since ++ has precedence over the type cast ... I don't see why the result of (int *) wouldn't be an l-value. ...
    (comp.std.c)