Как заставить gcc генерировать только машинный код, который может быть загружен непосредственно в память и выполнен? - PullRequest
17 голосов
/ 01 сентября 2010

Я хотел бы создать файл, который можно загрузить в память (например, с помощью mmap), а затем перейти к началу этой памяти, чтобы выполнить код.

В идеале, я хотел бывозможность либо сделать код перемещаемым (что может быть неэффективно), либо указать явный адрес, по которому код должен быть загружен (что очень неприятно), но любой из них, вероятно, будет работать самостоятельно.

Ответы [ 2 ]

16 голосов
/ 01 сентября 2010

Вы можете сделать это, но вам нужно будет пройти через формат объектного файла.В частности, команда objcopy может преобразовать исполняемый файл в «плоский» двоичный файл (в зависимости от вашей целевой платформы).Возможно, что-то вроде этого:

gcc -o test test.c
objcopy -O binary test test.bin

См. man objcopy на вашей платформе для более подробной информации.

7 голосов
/ 01 сентября 2010

Вы хотите узнать об утилите objcopy, которая обычно доступна вместе с GCC.Он является компонентом пакета инструментов binutils , наиболее заметным членом которого является компоновщик ld.

. Процесс состоит в том, что вы компилируете исходные файлы исвязать их, как правило, как обычно.Это дает вам готовый исполняемый файл в эльфийском (или другом перемещаемом платформенно-зависимом двоичном формате).Затем вы используете objcopy для преобразования исполняемого файла в плоский двоичный образ.

Это наиболее полезно для подготовки кода к запуску из ПЗУ, где вы захотите убедиться, что используете подходящую библиотеку времени выполнения C для своегоцелевой платформе, и, вероятно, потребуется настроить файл сценария компоновщика, а также предоставить собственный код запуска среды выполнения C.

Если ваша цель - получить что-то вроде файла .so для загрузки всуществующего процесса, затем имейте в виду, что часть работы загрузчика разделяемой библиотеки заключается в том, чтобы фактически завершить компоновку, чтобы символы в файле .so, которые ссылаются на адреса в основном исполняемом файле (или других файлах .so), разрешались во время загрузки,Использование objcopy этого не сделает, и поэтому загруженным таким образом функциям может быть сложно правильно использовать существующую библиотеку времени выполнения C и объекты, которые она поддерживает, такие как открытые файлы.

Независимо от ваших целей, вы собираетесьчтобы захватить контроль над компоновщиком, чтобы найти ваш бинарный файл по известному адресу.Для этого вам нужно будет создать скрипт компоновщика.Документация к языку сценариев содержится в руководстве по binutils .В первую очередь вас заинтересуют разделы ".text *" и, возможно, разделы ".rodata *", если вы планируете иметь какие-либо инициализированные глобальные переменные.Собственно, организация этой инициализации оставлена ​​читателю в качестве упражнения.

В целом, это только вершина очень большого айсберга.Я бы посоветовал потратить некоторое время на кросс-компиляцию, чтобы увидеть, как эти вещи используются на практике.Сообщества AVR и MSP430 используют GCC, имеют активное участие и недорогие (и часто даже с открытым исходным кодом) аппаратные средства для начала работы.

...