Подтвердить что ты не робот

Компиляция без libc

Я хочу скомпилировать свой C-код без (g) libc. Как его деактивировать и какие функции зависят от него?

Я попробовал -nostdlib, но это не помогает: код компилируется и запускается, но я все еще могу найти имя libc в hexdump моего исполняемого файла.

4b9b3361

Ответ 1

Если вы скомпилируете свой код с помощью -nostdlib, вы не сможете называть какие-либо функции библиотеки C (конечно), но вы также не получите обычный загрузочный код C. В частности, реальная точка входа в программу на linux не является основной(), а скорее функцией, называемой _start(). Стандартные библиотеки обычно предоставляют версию этого, которая запускает некоторый код инициализации, а затем вызывает main().

Попробуйте выполнить компиляцию с помощью gcc -nostdlib:

void _start() {

    /* main body of program: call main(), etc */

    /* exit system call */
    asm("movl $1,%eax;"
        "xorl %ebx,%ebx;"
        "int  $0x80"
    );
}

Функция _start() всегда должна заканчиваться вызовом для выхода (или другим неотправляемым системным вызовом, таким как exec). Вышеприведенный пример вызывает системный вызов непосредственно с встроенной сборкой, поскольку обычный выход() недоступен.

Ответ 2

http://blog.ksplice.com/2010/03/libc-free-world/ имеет очень хорошее описание точного управления программным выходом gcc.

Изменить: они (ksplice) просто выставляют часть 2 вышеупомянутого учебника/руководства. См. Здесь: http://blog.ksplice.com/2010/04/libc-free-world-2/ В основном это касается настроек компоновщика, чтобы удалить ненужный пух из файлов.

Ответ 4

Самый простой способ - скомпилировать C-код для объектных файлов (gcc -c, чтобы получить некоторые файлы *.o), а затем связать их напрямую с компоновщиком (ld). Вам нужно будет связать ваши объектные файлы с несколькими дополнительными объектными файлами, такими как /usr/lib/crt1.o, чтобы получить рабочий исполняемый файл (между точкой входа, как видно из ядра, и функцией main(), есть немного работа, которую нужно сделать). Чтобы узнать, с чем нужно связываться, попробуйте установить связь с glibc, используя gcc -v: это должно показать вам, что обычно входит в исполняемый файл.

Вы обнаружите, что gcc генерирует код, который может иметь некоторые зависимости к нескольким скрытым функциям. Большинство из них находятся в libgcc.a. Также могут быть скрытые вызовы memcpy(), memmove(), memset() и memcmp(), которые находятся в libc, поэтому вам, возможно, придется предоставить свои собственные версии (что не сложно, по крайней мере, до тех пор, пока вы не слишком придирчивы к производительности).

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