Как создать программу на C, включающую точку входа в Mac OS X?

Как создать программу на C, включающую точку входа в Mac OS X?

Я хочу построить:

start() {
    /* exit system call */
    asm("movl $1,%eax;"
        "xorl %ebx,%ebx;"
        "int  $0x80"
    );
}

но когда я бегу:

gcc -nostdlib min.c

Я всегда получаю:

ld: could not find entry point "start" (perhaps missing crt1.o)
collect2: ld returned 1 exit status

Еще одна попытка, которую я предпринял, просто чтобы посмотреть, что она делает, была запущена:

gcc -nostdlib -c min.c && otool -tV min.o

И выход был:

(__TEXT,__text) section
_start:
0000000000000000    pushq   %rbp
0000000000000001    movq    %rsp,%rbp
0000000000000004    leave
0000000000000005    ret

Так откуда взялось это подчеркивание перед функцией «старт»? Как предотвратить это? Или проще:

Как создать программу на C, включающую точку входа в Mac OS X?

Спасибо, CrazyChenz


person Crazy Chenz    schedule 04.12.2010    source источник
comment
_start, вероятно, искаженное имя. Прежде чем создать начало, имейте в виду, что необходимо выполнить много предварительной обработки, иначе возникнут всевозможные проблемы. Чтобы получить представление о символах, вам нужно определить try nm crt1.o. gcc -e main делает main точкой входа вместо start. Вы можете определить любую функцию, которую хотите, таким образом. Я не знаю, как установить эту опцию для Xcode. Кто-то другой может.   -  person jim mcnamara    schedule 04.12.2010
comment
IIRC, номера вызовов MacOS отличаются от Linux, поэтому eax=1/int 0x80 может не быть sys_exit. И 32-битные системные вызовы MacOS принимают свои аргументы в стеке в стиле FreeBSD, а не EBX, ECX, EDX, .... И, конечно, при создании 64-битного исполняемого файла вы захотите использовать syscall с соответствующими номерами вызовов / регистры передачи аргументов для этого.   -  person Peter Cordes    schedule 20.02.2020


Ответы (2)


Параметр gcc -e определяет точку входа, если вы хотите, чтобы точка входа была чем-то отличным от start. Таким образом, вы можете создать mystart() в качестве точки входа.

gcc -e mystart mycode.c -o mycode

Я не знаю, как установить параметр -e в Xcode.

person jim mcnamara    schedule 04.12.2010
comment
MacOS искажает имена с ведущим _, поэтому я думаю, вам понадобится gcc -e _mystart. - person Peter Cordes; 20.02.2020

Вы можете управлять символом, который gcc дает функции, объявив его отдельно с помощью asm:

void start() asm ("start");

Убедитесь, что это отдельное объявление, отдельное от определения функции.

Вы можете прочитать более подробную информацию об управлении сгенерированным символом здесь: https://stackoverflow.com/a/1035937/12928775

Кроме того, как указывает Питер Кордес, вам, вероятно, следует включить __attribute__((naked)) в определение функции, чтобы gcc не генерировал кадр стека при входе.

Полный код будет таким:

void start() asm ("start");

__attribute__((naked)) void start() {
    /* exit system call */
    asm("movl $1,%eax;"
        "xorl %ebx,%ebx;"
        "int  $0x80"
    );
}
person Sofia Faro    schedule 20.02.2020
comment
Вам не нужно extern в прототипе. godbolt.org/z/Vz77nS показывает, что void start(void) asm("_mystart"); создает указанное имя. Кроме того, вы, вероятно, захотите void вместо использования устаревшего C implicit-int. И __attribute__((naked)) было бы хорошей идеей для определения; start не является функцией, поэтому вы не хотите, чтобы -O0 создавал кадр стека при входе. - person Peter Cordes; 20.02.2020
comment
Для получения дополнительных бонусных баллов помните, что () в C (в отличие от C++) оставляет типы аргументов неопределенными, в отличие от (void). Можно также уточнить, что он не принимает никаких аргументов. - person Peter Cordes; 20.02.2020