Re: Passing execution to a memory address
- From: Beej Jorgensen <beej@xxxxxxx>
- Date: Thu, 1 Mar 2007 20:20:59 +0100 (CET)
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;
}
.
- Follow-Ups:
- Re: Passing execution to a memory address
- From: Keith Thompson
- Re: Passing execution to a memory address
- References:
- Passing execution to a memory address
- From: polas
- Passing execution to a memory address
- Prev by Date: Re: structure layout question
- Next by Date: Re: structure layout question
- Previous by thread: Re: Passing execution to a memory address
- Next by thread: Re: Passing execution to a memory address
- Index(es):
Relevant Pages
|