У меня есть идея скомпилировать C ++ в двоичный файл, сохранить двоичный файл в куче и выполнить его. Я рассматривал одну из реализаций компиляции для конкретных архитектур, как это делает Google Native Client, и затем знал, для какой архитектуры я скомпилирован, во время выполнения - использую тот же или другой компилятор в моей программе для компиляции «фрагмента» или «скрипт» и вывод машинного кода в память, выделенную в куче. Затем наведите указатель на нужное место и запустите его. Мой вопрос, независимо от компиляторов, если C ++ скомпилирован в одну и ту же архитектуру, будет ли полученный двоичный файл иметь одинаковый ABI и, следовательно, иметь вызываемую функцию (соглашение о вызовах) / точку входа любого вида? Придет какое-то вдохновение из таких проектов, как this , но я хочу сделать это в некоторой степени независимой от платформы (я имею в виду, что могу компилировать в архитектуру и знаю, на какой архитектуре я работаю), независимым от компилятора способом, который работает при запуске -время.
Возможная реализация, которую я имел в виду, была связана с ИК-кодом LLVM, другими словами, просто взять ИК-код, собрать его (в правильный набор команд / архитектуру) и записать двоичный файл в кучу, точка входа, на которую указывает указатель функции, например (псевдокод):
typedef unsigned short( * )( int ) ENTRY_POINT_T;
ENTRY_POINT_T Inject( Binary code )
{
void* block = malloc( sizeof( code ) );
*( ( Binary* ) block ) = code;
ENTRY_POINT_T entryPoint = ( ENTRY_POINT_T* ) block;
return entryPoint;
}
#ifdef x86
#define ARC "x86"
#endif
#ifdef PowerPC
#defnie ARC "PowerPC"
#endif
int main()
{
Binary executableCode = llvm.assemble( irCodeString, "-" + ARC );
auto entry = Inject( executableCode );
int result = entry( 0 );
std::cout << result << "\n";
return 0;
}
Обратите внимание, что модуль compiler-rt в llvm выглядит потенциально полезным (также как и анализатор).