Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to store and call a compiled function in C / C++?

For very low level optimization purposes it would be useful to me if I could store a compiled function inside a variable directly, not a pointer to a function. That is, if I have a function foo, I want to make a char buffer large enough to hold the machine instructions generated for foo, and then be able to in effect call foo by somehow telling C to jump execution to the contents of that buffer (assume that I have a compiler intrinsic to make sure the char buffer is aligned properly for my architecture). Ideally, I'd like to do this keeping assembly usage to a minimum (I realize some might be required).

My best solution so far would be to compile a program that has just the function I want to assembly with GCC, then compile to machine code, then use the addresses from the outputted assembly to extract the desired machine code from the executable, then manually fill the buffer with that in my program, then use inline assembly to jump to the starting address of the buffer. That's more hackish and manual work than I would like though.

I don't need to compile new functions at runtime, just have the buffer contain instructions corresponding to different already compiled functions during runtime. E.g. I might have 3 compiled functions, and 1 buffer. The 3 functions are known at compile time, but at runtime the buffer may correspond to any one of the 3 at different times.

Edit: To clarify what there would be to gain: I have a struct of which this buffer will be a member, and various pointers to instances of that struct. Each struct's buffer may contain a different compiled function. If I were to use a function pointer instead of the buffer, I would have to load the struct's function pointer, then deref the function pointer. With the buffer, I can just jump the program counter to an offset (the buffer's relative location) of the base of the struct. It's one less level of indirection. For very tiny functions, this can be a savings.

Edit 2: Further clarifying:

With a function pointer:

  1. Load pointer from &struct+offsetof(pointer)
  2. Jump to location contained in pointer

With a buffer that contains machine code:

  1. Jump to &struct+offsetof(buffer)

The second one is less steps.

like image 220
Joseph Garvin Avatar asked Jul 20 '09 16:07

Joseph Garvin


People also ask

How function is compiled in C?

The c compilation process converts the source code taken as input into the object code or machine code. The compilation process can be divided into four steps, i.e., Pre-processing, Compiling, Assembling, and Linking.

How do I call a function from one file to another in C?

You must declare int add(int a, int b); (note to the semicolon) in a header file and include the file into both files. Including it into Main. c will tell compiler how the function should be called.

How do you call a C++ function that is compiled with C++ compiler in C?

Just declare the C++ function extern "C" (in your C++ code) and call it (from your C or C++ code). For example: // C++ code: extern "C" void f(int);

What happens when a .C file is compiled?

c file it first go through the pre-processor, then compiler compiles it into assembler and creates object file (main.o). Then linker link the main.o with required header objects and libraries and creates a executable file (program.exe).


2 Answers

Be aware that most modern architectures support no-execute protection for memory pages, and OSes with a bit of sense take advantage of it for security. That means that you can't use e.g. stack memory or random malloc'd memory to store this code; you need to adjust the permissions using e.g. VirtualProtect on Windows or mprotect on Unices.

like image 95
Barry Kelly Avatar answered Oct 20 '22 08:10

Barry Kelly


I'm not sure why you are excluding function pointers - if you aren't modifying the code at runtime, then I can't think of anything that a buffer containing a function could do that a function pointer couldn't.

That being said, one you have a pointer to a buffer containing your function, just cast a pointer to that buffer to the right function pointer type and call that. Of course if your operating system / CPU supports it, you'll also have to clear the NX flag that prevent you from running non-executable code.

Also, you can't assume that you can copy buffers containing executable data around as if they contained regular data - you'll have to fix up branches and jumps and other memory accesses.

EDIT: I see what you're getting at, but I don't think you'll be able to find a standard-compliant way to get a function into a buffer - C++ says very little about memory structure and where functions are stored is a rather abstract concept. You may be stuck with a bunch of hacks, or else using separate assembly files that can be assembled at compile time and loaded from the files at run-time.

On another note - I think that you may find that it is faster to do the double dereferencing of storing the function pointer (4-8 bytes likely) than suffer the cache misses of storing a buffer capable of holding the largest function you will need. Your struct with an attached function has many similarities with virtual functions on classes. There are reasons why most (all?) C++ compilers implement virtual functions with a vtable rather than store the entire function definition for every instance of the class. That's not to say it's not possible that you'll get a performance increase out of storing the whole function in a buffer, it's just not as straight-forward as it may seem to be.

like image 29
Eclipse Avatar answered Oct 20 '22 08:10

Eclipse