简体   繁体   中英

Writing functions to binary files?

Something that made me fairly curious was that since it's possible in C++ to pass a function as an argument under the right circumstances, that would suggest that whatever internal code handles that function can be pointed to and otherwise written and read into a binary as its executable code.

This is obviously coming from someone while I may have a strong background in C++, I'm not familiar with the intricate internals in just how memory is managed in the heap and especially how the executable machine code fits into the picture.

I assume since it's possible to pass around the reference to a function, it's possible to get the data pointed to by it and write it somewhere. I don't know.

Anyone want to tell me if this is possible? If so, can you give an example? If not, please tell me why! I love learning more in-depth about how C++ actually works internally.

20 years ago your suggestions could be fresh and usable. People were saving memory by loading code from file on demand , then calling it, then unloading. That was called overlays. To certain level it IS usable, but in form that is standardized in platform and platform's API is what manages it. Mechanism behind shared libraries (.so in POSIX system, .dll in Windows) is that library's file contains labels where certain functions are , what their name is, as well as data about how stack and data segment should be initialized. It can be done by system automatically, when program is loaded. Otherwise you can load library manually and load pointer to function. Eg on Windows that would be by LoadLibrary() and GetProcAddress(), dlopen() and dlsym() on Linux.

Reason why it isn't possible now in high level language: security, protection from malicious code in data segment. Run-time library usually handles it. It is still possible using assembler, but you will challenge antivirus and system security measures. With careful programming you may create own "linker" be able to create your own library and load , I suppose.

No, you can't really do this. There are a whole lot of reasons, but here's a simple and intuitive one: functions may call other functions. If you were able to write a function to disk, and restore it, this would not account for its dependencies (functions it calls, global variables it updates, etc.). It won't work.

If you want to read functions from disk, it is better to express them in a scripting language like Lua. This is a proven solution which is used in many commercial products such as video games and Adobe Lightroom.

While a function pointer is the entry point of a function, and that memory can be read and therefore copied, the first problem is that there is no reliable means of determining the length of that code, so you cannot determine for certain how much to copy to get the entire function and only that.

The other issue is to what practical end? Depending on the platform the code may not be relocatable and will have links to other code. The binary contains no symbolic information; the best you can do is disassemble it, but out of the context of the entire linked executable it may not be very useful to do so.

If your aim is to separate functions from the primary executable, and to be able to later load and run them, then that is what DLLs and shared libraries are for.

If you just want to observe the binary relating to a function, then that is best done in a debugger - it will have a disassembly view mode that will show the raw binary (in hexadecimal), assembly code with symbolic links and the corresponding C source. This makes a lot more sense if your aim is merely to investigate how source code relates to binary machine code.

Below is how you could possibly do what you are asking - even if there is no practical reason for doing it. It makes assumptions about the behaviour of the compiler that may not be valid in some cases. It assumes for example that the compiler will place adjacent functions contiguously in memory and in increasing memory address, so that function2 is immediately after function1 in memory. Here function2 serves only as an end marker for function1 and may be dummy.

int function1()
{
    ...

    return 0 ;
}

void function2() 
{
}

#include <stddef.h>

int main()
{
    ptrdiff_t function1_length = (char*)function2 - (char*)function1 ;

    FILE* fp = fopen( "function1.bin", "wb" ) ;
    fwrite( function1, function1_length, 1, fp ) ;
    fclose( fp ) ;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM