Компиляция без основной функции (MacOS) - PullRequest
1 голос
/ 25 января 2020

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

#include <stdio.h> 
#include <stdlib.h>


int my_main() 
{ 
      printf("Hello world!\n"); 
          return 0; 

} 

void _start() 
{  
      exit(my_main()); 

} 

Попытка скомпилировать с помощью команды: g cc -nostartfiles nomain. c. Хотя он компилируется и создает файл a.out в Debian vm, я не могу скомпилировать его в моей macOS Catalina v10.15.2. Я использую последнюю версию g cc. Сообщение, которое я получаю при попытке компиляции:

Неопределенные символы для архитектуры x86_64: "_main", на которые ссылается: неявная запись / запуск для основного исполняемого файла ld: символ (ы) не найден для архитектуры x86_64 collect2: error: ld вернул 1 состояние выхода

До сих пор я пытался изменить _start на start , но все еще получал тот же результат. Как я понимаю, процесс компиляции отличается в зависимости от ОС.

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

Заранее спасибо

Ответы [ 2 ]

3 голосов
/ 25 января 2020

В macOS 10.14.6 с Xcode 11.3 код в вопросе компилируется и связывается с помощью команды:

clang -Wl,-e, -Wl,__start <Name of Your Source File>

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

Обратите внимание, что необходимы два подчеркивания before start в приведенной выше команде, поскольку исходный код содержит одно и другое, добавляемое компилятором C. Если код был изменен на использование start вместо _start, то команда будет использовать одно подчеркивание:

clang -Wl,-e, -Wl,_start <Name of Your Source File>

Переключатели -Wl,-e, -Wl,_start передают -e _start компоновщику, который сообщает ему: используйте _start в качестве адреса исходного кода для выполнения. Мне не понятно, почему это обходит загрузку по умолчанию объектного модуля C -run-time-startup, который также определяет _start. Я бы предпочел использовать переключатель компоновщика, который говорит ему не загружать этот модуль, но я не нашел его на странице руководства для ld. Эксперимент показывает, что по умолчанию ld загружает объектный модуль по умолчанию и ссылается на main, что приводит к ошибке соединения, но, когда используется -e _start, компоновщик устанавливает символ программы _start как адрес запуска и не загружает объектный модуль по умолчанию.

0 голосов
/ 25 января 2020

Я почти уверен, что вы можете скомпилировать любой C -источник без main ().

Проблема будет в том, что компоновщик попытается создать исполняемый файл, который не будет работать без main () .

...