Я создаю свою собственную 32-битную ОС x86, в которую загружаю пользовательские программы из файлов ELF. При компиляции пользовательских программ на C я использую -nostdlib, чтобы исключить GLIBC и вместо этого связать свой собственный LIBC. Проблема в том, что при этом программа компилируется без метки _start, в результате чего метка entry (определенная в заголовке ELF) указывает на первый фрагмент кода в файле, а не на фактическую запись программы.
Я не уверен, как я могу скомпилировать без стандартной библиотеки, но при этом иметь действительную точку входа для программы.
При компиляции с флагом -nostdlib я получаю:
/usr/bin/ld: warning: cannot find entry symbol _start; defaulting to 0000000008049000
ELF-файл:
Entry point address: 0x8049000
Как можно сгенерировать _start без stdlib?
Должен ли и могу ли я написать это сам и связать его во время компиляции с пользовательской программой?
@Someprogrammerdude Мое ядро почти готово; Я спрашиваю, как я могу скомпилировать пользовательскую программу C для запуска в моем ядре без stdlib и при этом иметь метку _start.
Ответ по сути тот же: вам нужна функция _start, которая настраивает стек, BSS, стандартные дескрипторы файлов и т. д., а затем вызывает main. На самом деле в _start нет ничего особенного, это простая функция, почти такая же, как и любая другая. Я думаю, что на вики OSDEv тоже есть информация об этом.
Также есть опции --entry=ENTRY/-e ENTRY, позволяющие указать собственную точку входа.
Что вы подразумеваете под «программой пользователя C, которая будет запускаться в моем ядре»? Обычно под «пользовательской программой» я подразумеваю программу, работающую поверх вашей ОС в том, что C называет «размещенной» средой. В такой среде ответственность за посредничество запросов программ к службам ядра лежит на стандартной библиотеке C (будь то ваша собственная или какая-либо другая). Такая программа не запускается «на ядре». Он работает на предоставленной размещенной реализации C, включая стандартную библиотеку C. Это делает стандартную библиотеку прекрасным местом для _start() или подобной функции.
@JohnBollinger О, понятно, я только сейчас понял, что функция _start является частью стандартной библиотеки, а не частью процесса компиляции. То есть вы говорите, что я должен реализовать свою собственную функцию _start в своей библиотеке libc и установить для нее запись при связывании?





Мое замешательство было вызвано источником функции _start. Судя по всему, функция _start является частью стандартной библиотеки, расположенной в файле crt0.S.
crt0 (также известный как c0) — это набор процедур запуска выполнения, связанных с программой C, который выполняет любую работу по инициализации, необходимую перед вызовом основной функции программы.
При компиляции с флагом -nostdlib GCC удаляет GLIBC из программы вместе со своей подпрограммой _start, в результате чего компоновщик выдает ошибку, сообщающую, что не удалось найти символ для установки записи.
/usr/bin/ld: warning: cannot find entry symbol _start; defaulting to 0000000008049000
Я исправил это, создав свой собственный crt0.S файл в моей libc и в нем специальную _start функцию, которая будет связана с пользовательской программой.
Итак, на свои вопросы я бы ответил:
Как можно сгенерировать
_startбез stdlib? Должен ли и могу ли я написать это сам и связать его во время компиляции с пользовательской программой?
Вам следует предоставить собственное определение функции _start в стандартной библиотеке вашей ОС и связать его с пользовательской программой.
Добавить свою
_startфункцию? В любом случае вам нужно это сделать, чтобы настроить стек, сегменты BSS и другие вещи, прежде чем переходить к функцииmain(которая может называться как угодно). Вы также можете изменить скрипт компоновщика, чтобы использовать любой символ вместо_start. Предлагаю вам просмотреть вики OSDev, там есть вся информация, необходимая для создания собственного ядра ОС.