Я хочу, чтобы gcc скомпилировал для меня c-код в двоичный код Linux x86-32, но без каких-либо библиотек или около того.
Это означает, что вы пишете Отдельно стоящий C код.(Когда стандартная библиотека доступна, у вас есть размещенная среда; когда нет, автономная одна.)
Для компиляции, например, foo.c в исполняемый файл,foo, убедитесь, что у него есть функция _start()
, и используйте
gcc -march=i686 -mtune=generic -m32 -ffreestanding -nostdlib -nostartfiles foo.c -o foo
В цепочке инструментов GNU используется адрес символа _start
для кодирования начального адреса исполняемого файла в файле ELF.
Этот ответ является реальным реальным примером для x86-64.Для x86-32 (или любой другой архитектуры) вам нужно настроить макросы SYSCALL_
.
В комментарии OP объясняет, что им нужен двоичный двоичный объект вместо исполняемого файла ELF.
В этом случае лучше всего сказать компилятору сгенерировать независимый от позиции исполняемый файл .Например, 'blob.c':
void do_something(int arg)
{
/* Do something with arg, perhaps a syscall,
or inline assembly? */
}
void loop_something(int from, int to)
{
int arg;
if (from <= to)
for (arg = from; arg <= to; arg++)
do_something(arg);
else
for (arg = from; arg <= to; arg--)
do_something(arg);
}
void _start(void)
{
loop_something(2, 5);
do_something(6);
loop_something(5, 2);
do_something(1);
}
Я рекомендую объявлять все функции, кроме _start
, как static
, чтобы избежать любых ссылок на глобальную таблицу смещений (GOT) или таблицы связей процедур (PLT)(например, <__x86.get_pc_thunk.bx>
звонки).
Скомпилируйте это в независимый от позиции исполняемый файл, используя, например,
gcc -march=i686 -mtune=generic -m32 -O2 -fPIE -ffreestanding -nostdlib -nostartfiles blob.c -o blob
, удалите его,
strip --strip-all blob
и выгрузите содержимоеДвоичный файл:
objdump -fd blob
В этом выводе есть две важные строки:
start address 0x08048120
, который сообщает адрес символа _start
, и
080480e0 <.text>:
который сообщает смещение кода в шестнадцатеричном формате.Вычтите первое из последнего (0x08048120 - 0x080480e0 = 0x40 = 64), чтобы получить смещение начального символа.
Наконец, выведите код в необработанный двоичный файл 'blob.raw', используя
objcopy -O binary -j .text blob blob.raw