Самым же, если вы хотите, чтобы это действительно использовалось в реальном мире, вероятно, просто скомпилировать источник как часть вашей программы на каждой платформе, как обычную функцию.
Следующее лучшее - это, вероятно, отдельный процесс, с которым вы говорите, а не слияние.
Полуживой (но все еще не отличный выбор, см. Нашу дискуссию в другом ответе) будет делать общую библиотеку, как сказал Майкл Аарон Сафян.
Но если вы хотите знать, как это работает, потому что, скажем, вы хотите написать свой собственный динамический компоновщик или сделать какое-то генерирование кода времени выполнения, как JIT-компилятор, или если вы просто хотите знать - вы можете сделайте файл необработанного кода.
Чтобы использовать его, то, что нам нужно сделать, похоже на то, что делает компоновщик - загрузить код на определенном адресе, на котором он работает, и запустить его. Существует независимый от позиции код, который может работать и по любому адресу.
Давайте сначала скомпилируем и скомпилируем нашу функцию, а затем выводим исходное изображение для определенного адреса. Предположим, что функция func
в файле func.c
, и мы используем gcc в Linux. (У компилятора Windows были бы аналогичные варианты: gcc на Windows точно так же, я считаю, но что-то вроде компилятора C-файла от Digital Mars делает это по-другому, поскольку команда компоновщика имеет значение /BINARY
)
В любом случае, вот что я побежал:
gcc -c func.C# makes func.o
ld func.o --oformat=binary -e func -o func.binary
Это генерирует файл func.binary. Вы можете легко его дизассемблировать с помощью ndisasm -b 64 func.binary
(или -b 32
, если вы скомпилировали C в 32-битном режиме), чтобы убедиться, что он выглядит правильно - я вижу там инструкцию добавления, поэтому выглядит хорошо для меня.
Если вы загрузили это и mmaped, то назвали его ... он должен работать.
Проблемы будут быстро придумать, хотя:
- Если есть более чем одна функция в этом файле, все они будут сплющенные вместе.
- Адреса, которые они пытаются использовать друг для друга, могут быть совершенно неправильными.
- Глобальные переменные и другие статические данные будут испорчены.
И еще есть. Операционная система использует более сложные форматы файлов для исполняемых файлов и библиотек по какой-либо причине!
Чтобы перейти к следующему шагу, вы можете подумать о написании загрузчика ELF или PE, который считывает эти метаданные из стандартного файла. Конечно, как только вы вникаете в это, вы будете делать именно то, что OS предоставляет с dlopen
и LoadLibrary
.... так что, если только цель состоит в том, чтобы просто узнать о кишках, просто вызовите эти функции и назовите это!
Это не то, как работают скомпилированные языки. –
Я просто хочу, чтобы модуль мог загружаться в Linux и Windows (VirtualAllocEx) –
Алгоритм не зависит от платформы. Поэтому я не хочу, чтобы модуль был скомпилирован 2 раза. –