ЛИНУКС: Можно ли написать работающую программу, которая не зависит от библиотеки libc? - PullRequest
7 голосов
/ 08 февраля 2009

Интересно, мог бы я написать программу на языке программирования C, которая была бы исполняемой, хотя и без использования одного библиотечного вызова, например даже не выход ()?

Если это так, то это, очевидно, вообще не будет зависеть от библиотек (libc, ld-linux).

Ответы [ 6 ]

7 голосов
/ 08 февраля 2009

Я подозреваю, что вы могли бы написать такую ​​вещь, но в конце должен был бы быть бесконечный цикл, потому что вы не можете попросить операционную систему выйти из вашего процесса. И ты не мог сделать ничего полезного.

Хорошо начните с компиляции программы ELF, изучите спецификацию ELF и соберите вместе заголовок, сегменты программы и другие части, необходимые для программы. Ядро загрузит ваш код и перейдет на некоторый начальный адрес. Вы могли бы поставить бесконечный цикл там. Но без знания ассемблера это все равно безнадежно с самого начала.

Файл start.S, используемый glibc, может быть полезен в качестве начальной точки. Попробуйте изменить его так, чтобы вы могли собрать из него автономный исполняемый файл. Этот файл start.S является точкой входа всех приложений ELF и вызывает __libc_start_main, что, в свою очередь, вызывает main. Вы просто измените его так, чтобы он соответствовал вашим потребностям.

Хорошо, это было теоретически. Но теперь, какое практическое применение это имеет?

Ответ на обновленный вопрос

Хорошо. Существует библиотека под названием libgloss, которая обеспечивает минимальный интерфейс для программ, предназначенных для работы во встроенных системах. Библиотека newlib C использует ее в качестве интерфейса системных вызовов. Общая идея заключается в том, что libgloss - это слой между библиотекой C и операционной системой. Таким образом, он также содержит файлы запуска, в которые загружается операционная система. Обе эти библиотеки являются частью проекта GNU binutils. Я использовал их для создания интерфейса для другой ОС и другого процессора, но, похоже, нет порта libgloss для Linux, поэтому, если вы вызываете системные вызовы, вам придется делать это самостоятельно, как уже заявили другие .

Абсолютно возможно писать программы на языке программирования Си. ядро ​​Linux является хорошим примером такой программы. Но также возможны пользовательские программы. Но минимально требуется библиотека времени выполнения (если вы хотите сделать что-то серьезное). Такой содержит действительно базовые функции, такие как memcpy, базовые макросы и так далее. Стандарт C имеет специальный режим соответствия, называемый freestanding , для которого требуется только очень ограниченный набор функций, подходящий также для ядер. На самом деле, у меня нет понятия о ассемблере x86, но я попытал счастья для очень простой программы на C:

/* gcc -nostdlib start.c */
int main(int, char**, char**);

void _start(int args)
{
    /* we do not care about arguments for main. start.S in 
     * glibc documents how the kernel passes them though.
     */
    int c = main(0,0,0);

    /* do the system-call for exit. */
    asm("movl   %0,%%ebx\n" /* first argument */
        "movl   $1,%%eax\n" /* syscall 1 */
        "int    $0x80"      /* fire interrupt */
        : : "r"(c) :"%eax", "%ebx");
}

int main(int argc, char** argv, char** env) {
    /* yeah here we can do some stuff */
    return 42;
}

Мы счастливы, он на самом деле компилируется и запускается:)

5 голосов
/ 08 февраля 2009

Да, это возможно, однако вам придется совершать системные вызовы и настраивать точку входа вручную.

Пример минимальной программы с точкой входа:

.globl _start
.text
_start:
    xorl %eax,%eax
    incl %eax
    movb $42, %bl
    int $0x80

Или в простой C (без выхода):

void __attribute__((noreturn)) _start() {
    while(1);
}

Составлено с:

gcc -nostdlib -o example example.s
gcc -nostdlib -o example example.c
2 голосов
/ 08 февраля 2009

Вам понадобится способ запретить компилятору C генерировать код, который зависит от libc, что с gcc можно сделать с -fno-hosted. И вам понадобится одна подпрограмма на ассемблере для реализации syscall(2). Их не сложно написать, если вы можете получить подходящий OS DOCO. После этого вы отправитесь на гонки.

2 голосов
/ 08 февраля 2009

в чистом виде? Как уже говорили другие, вам все еще нужен способ сделать системные вызовы, поэтому вам может потребоваться перейти к встроенному asm для этого. Тем не менее, если вы используете gcc, проверьте -ffreestanding.

0 голосов
/ 08 февраля 2009

Да, можно, но это довольно сложно.

В этом нет абсолютно никакого смысла.

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

Вы можете полностью обойтись без библиотеки C, и в этом случае вам нужно совершать системные вызовы, используя соответствующий низкоуровневый интерфейс, который зависит от архитектуры и не обязательно int 0x80.

Если ваша цель - создать очень маленький автономный бинарный файл, вам лучше использовать статические ссылки на что-то вроде uclibc.

0 голосов
/ 08 февраля 2009

Что ж, вам нужно было бы использовать некоторые системные вызовы для загрузки всей этой информации в память, поэтому я сомневаюсь в этом.

И вам почти придется использовать exit () только из-за того, как работает Linux.

...