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

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

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

17
задан Ciro Santilli 新疆改造中心法轮功六四事件 23 May 2015 в 13:26
поделиться

2 ответа

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

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

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

16
ответ дан 30 November 2019 в 13:27
поделиться

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

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

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

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

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

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

7
ответ дан 30 November 2019 в 13:27
поделиться
Другие вопросы по тегам:

Похожие вопросы: