Imbrondir
Imbrondir

Reputation: 686

JITs fundamentals

I understand somewhat how "int a = b+abs(c)" can be translated to simple assembly instructions and then translate that to some binary blob. But how can this be run and be interacted with dynamically in memory?

-- edit --

I know C doesn't have an eval feature. But what it's compiled to does. I mean this is what makes Java like JITs, and for that matter, code injection malware possible no? For instance the abs() function is just a pointer, which could be called following the cdecl protocol. New functions should be able to be exposed through passing cdecl function pointers. What I don't understand is how this new code can be injected at runtime.

I'm asking this more of as a longtime academic curiosity, then to most efficiently solve an actual problem.

-- example --

Say I have a piece of embedded python code which is called from a native program a lot, and which also calls a native binding notify():

def add(a, b):
    notify()
    return a+b

For this to be a point in doing, the function should probably contain quite a bit more code (and way more usefull), but bear with me. A profiler (or hints from the c-bindings) has also identified that all calls are with with integers both with all parameters and return value. This matches:

int add(int a, int b) {
    notify();
    return a + b;
}

Which could be compiled into an x86 cdecl something similar to this:

:_add
push ebp ;setting up scope
mov ebp, esp
call _notify ;or more likely by a pointer reference
mov eax, [ebp + 8]
mov edx, [ebp + 12]
add eax, edx
pop ebp
ret

Then finally assembled into a binary string. Of course one would have to implement a basic compiler for each platform to even get this far. But that problem aside, say I now have a char pointer to this valid binary x86 code. Is it somehow possible to extract a cdecl function pointer useable for the native program from this in any way?

Sorry for the unclear intent about my question

Upvotes: 0

Views: 256

Answers (3)

Cheery
Cheery

Reputation: 25463

The program must be in memory region that allows execution.

On linux you can do this:

void *address;
functype proc;
int prot, flags;

prot = PROT_READ|PROT_WRITE|PROT_EXEC;
flags = MAP_PRIVATE|MAP_ANONYMOUS;
address = mmap(NULL, length, prot, flags, -1, 0);
if (address == NULL) error;

memcpy(address, program, length);
link(address, program_info);

proc = (functype)address;

Upvotes: 1

Kcats
Kcats

Reputation: 884

Assuming you have the code already compiled in a memory block, and you have the address of the block, it can be casted to a function pointer:

typedef int (*func)(int, int);
...
char * compiledCode = ...;
func f = (func) compiledCode;

and then the function can be called:

int x = f(2, 3);

Upvotes: 1

R.. GitHub STOP HELPING ICE
R.. GitHub STOP HELPING ICE

Reputation: 215637

C lacks any sort of "eval" feature, which is both a limitation and one of the things that allows it to be efficient. If all you need to be able to do is evaluate mathematical expressions with a small set of built-in math functions like abs() and not arbitrary C code, it's moderately easy to write such an expression evaluator.

Here's a link to a past SO thread on a similar topic: c expression Evaluator

Upvotes: 1

Related Questions