Компиляция C ++ под Linux без библиотеки времени выполнения - PullRequest
8 голосов
/ 21 апреля 2011

Я недавно начал исследовать способ использования библиотеки времени выполнения C ++ в сгенерированном коде.

В основном мне очень любопытно, но я также хочу оценить объем работы, необходимый для разработки минимально необходимого материала для запуска ядра на C ++.

Итак, я начал реализовывать свою собственную библиотеку времени выполнения, но у меня небольшая проблема.

int main(int argc, char **argv)
{
  return 0;
}

Компилируем это с помощью следующей команды:

$ g ++ -ffreedтинг -nostdlib -fno-builtin -fno-rtti -fno-exceptions -c main.cpp

Я получаю это предупреждение:

/ usr / bin / ld: предупреждение: не удается найти символ ввода _start; по умолчанию 00000000080480b8

Затем, когда я пытаюсь выполнить созданный двоичный файл, я получаю «Ошибка сегментации». Я попытался скомпилировать "main.cpp" и файл ASM.

[global _start]
[extern main]

_start:
  call main

Связывая объектные файлы вручную с помощью "ld", у меня нет предупреждения, но двоичный файл все еще вызывает "Ошибка сегментации".

Полагаю, я что-то упустил. Возможно, что-то должно быть сделано до и после вызова «main», как это делает системная библиотека C в «__libc_start_main», например.

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

Спасибо

Patrick

Ответы [ 3 ]

5 голосов
/ 22 апреля 2011

Хорошо, благодаря ссылке QuantumMechanic мне удалось найти проблему: http://www.muppetlabs.com/~breadbox/software/tiny/teensy.html

Я просто забыл свои основы программирования на Linux, что более важно, как обрабатывается завершение программы.

По сути, мне нужно было сгенерировать «выход» прерывания системного вызова для обработки конца программы.

[BITS 32]

[global _start]
[extern main]

_start:
  call main
  mov ebx, eax  ; Move the returned value in the register used as argument of exit()
  mov eax, 1    ; Indicates the id of the syscall to execute
  int 0x80      ; Triggers the syscall interrupt

Так что теперь я могу скомпилировать любую программу на C ++ в linux, используя свой собственный RTL, чтобы выполнить несколько тестов.

Обратите внимание, что в ядре он не понадобится, если никогда не будет достигнут конец "основной" функции.

Спасибо!

1 голос
/ 21 апреля 2011

Когда вы собираете ядро, вам нужно подумать о том, как оно запускается. Обычно это ответственность загрузчика, и они далеки от стандартных. Это, конечно, не похоже на запуск приложений для Linux. Поэтому не стоит особо беспокоиться о _start, когда вы все равно будете игнорировать этот способ запуска.

1 голос
/ 21 апреля 2011

Если вы хотите использовать небольшую (200K) часть установки gcc, вы можете создать ссылку на libgcc_s. Это даст вам весь код, необходимый для статической инициализации вашей программы и вызова main.

...