Компиляция без стандартной библиотеки, но с меткой _start (точка входа)

Я создаю свою собственную 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? Должен ли и могу ли я написать это сам и связать его во время компиляции с пользовательской программой?

Добавить свою _start функцию? В любом случае вам нужно это сделать, чтобы настроить стек, сегменты BSS и другие вещи, прежде чем переходить к функции main (которая может называться как угодно). Вы также можете изменить скрипт компоновщика, чтобы использовать любой символ вместо _start. Предлагаю вам просмотреть вики OSDev, там есть вся информация, необходимая для создания собственного ядра ОС.

Some programmer dude 30.04.2024 12:50

@Someprogrammerdude Мое ядро ​​почти готово; Я спрашиваю, как я могу скомпилировать пользовательскую программу C для запуска в моем ядре без stdlib и при этом иметь метку _start.

Eylon 30.04.2024 12:53

Ответ по сути тот же: вам нужна функция _start, которая настраивает стек, BSS, стандартные дескрипторы файлов и т. д., а затем вызывает main. На самом деле в _start нет ничего особенного, это простая функция, почти такая же, как и любая другая. Я думаю, что на вики OSDEv тоже есть информация об этом.

Some programmer dude 30.04.2024 12:56

Также есть опции --entry=ENTRY/-e ENTRY, позволяющие указать собственную точку входа.

Ian Abbott 30.04.2024 13:14

Что вы подразумеваете под «программой пользователя C, которая будет запускаться в моем ядре»? Обычно под «пользовательской программой» я подразумеваю программу, работающую поверх вашей ОС в том, что C называет «размещенной» средой. В такой среде ответственность за посредничество запросов программ к службам ядра лежит на стандартной библиотеке C (будь то ваша собственная или какая-либо другая). Такая программа не запускается «на ядре». Он работает на предоставленной размещенной реализации C, включая стандартную библиотеку C. Это делает стандартную библиотеку прекрасным местом для _start() или подобной функции.

John Bollinger 30.04.2024 16:55

@JohnBollinger О, понятно, я только сейчас понял, что функция _start является частью стандартной библиотеки, а не частью процесса компиляции. То есть вы говорите, что я должен реализовать свою собственную функцию _start в своей библиотеке libc и установить для нее запись при связывании?

Eylon 01.05.2024 08:35
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
6
75
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Мое замешательство было вызвано источником функции _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 в стандартной библиотеке вашей ОС и связать его с пользовательской программой.

Другие вопросы по теме