Как изменить точку входа программы C с помощью gcc?

Как изменить точку входа программы на C, скомпилированной с помощью gcc?
Как в следующем коде

#include<stdio.h>
int entry()  //entry is the entry point instead of main
 {
   return 0;
 }

person asitm9    schedule 21.09.2011    source источник
comment
@iandotkelly Не OP, но мне нужно было использовать библиотеку контрольных точек, которая потребовала от меня изменить main() на что-то другое;)   -  person Nubcake    schedule 18.05.2017
comment
@Nubcake Знаете ли вы вариант компоновщика --wrap=xxx? Он заменяет все ссылки xxx на __wrap_xxx и все определения xxx на __real_xxx. Я успешно использовал его для тестирования main().   -  person the busybee    schedule 29.10.2019


Ответы (4)


Это настройка компоновщика:

-Wl,-eentry

вещь -Wl,... передает аргументы компоновщику, а компоновщик принимает аргумент -e для установки функции входа

person Foo Bah    schedule 21.09.2011
comment
Вот что я получил, когда скомпилировал программу hello world на C с этой опцией: $ gcc -Wl,-emymain t27.c /usr/lib/gcc/i686-redhat-linux/4.8.2/../../../crt1.o: In function '_start': (.text+0x18): undefined reference to 'main' - person Lee Duhem; 08.03.2014
comment
@LeeDuhem, это потому, что вы связываете свою программу со стандартной библиотекой времени выполнения c. Точкой входа в программу, связанную с библиотекой времени выполнения c, является _start. Start имеет ссылку на main() вашей программы (ожидается, что ваша программа будет иметь функцию main() вместо вашей пользовательской функции). Попробуйте не ссылаться на crt и укажите точку входа как your_main и посмотрите, что произойдет. - person PaulD; 01.10.2014
comment
@LeeDuhem, -nostdlibs - это флаг. - person PaulD; 01.10.2014
comment
-nostartfiles - это фактический флаг, который вам нужен, он пропускает файлы crt * .o, содержащие _start, но все же позволяет вам использовать libc (если вы также не используете -nostdlib или -nodefaultlibs, в этом случае вы все равно можете указать их вручную, используя -lc -lgcc и т.д...) - person technosaurus; 17.07.2015
comment
Я считаю, что это опечатка: должно быть -Wl,--entry="MyCutomEntryFunction" или -Wl,-e="MyCutomEntryFunction" - person Romain VIOLLETTE; 22.10.2018
comment
@RomainVIOLLETTE у меня отлично работает: stackoverflow.com/a/58613764/895245 в Ubuntu 20.10. - person Ciro Santilli 新疆再教育营六四事件ۍ 06.01.2021

Вы можете изменить исходный код следующим образом:

#include<stdio.h>

const char my_interp[] __attribute__((section(".interp"))) = "/lib/ld-linux.so.2";

int entry()  //entry is the entry point instead of main
{
   exit(0);
}

Раздел «.interp» позволит вашей программе вызывать внешнюю разделяемую библиотеку. Вызов выхода заставит вашу функцию входа выйти из программы вместо возврата.

Затем создайте программу как общую исполняемую библиотеку:

$ gcc -shared -fPIC -e entry test_main.c -o test_main.so
$ ./test_main
person Sam Liao    schedule 10.08.2014
comment
Каково соглашение о вызовах функции entry? Инициализирована ли C-runtime таким образом? - person harper; 20.10.2014
comment
не могли бы вы объяснить, что означает создать программу как общую библиотеку, которая является исполняемой. Как может быть и то, и другое? - person Nawaz; 18.09.2015
comment
@harper: это не соглашение о вызовах, совместимое с C. Точка входа ELF имеет свой основной аргумент в указателе стека, указывающем на массив, состоящий из указателей argc, argv, null, указателей env, null, вспомогательной таблицы векторов. Некоторые арки имеют дополнительные аргументы в определенных регистрах. - person R.. GitHub STOP HELPING ICE; 06.06.2017
comment
не работает. Я получаю: невозможно выполнить двоичный файл: ошибка формата Exec - person Zibri; 14.03.2020

Если вы работаете в системе, которая предоставляет GNU Binutils (например, Linux), вы можете использовать objcopy команда, чтобы сделать произвольную функцию новой точкой входа.

Предположим, файл с именем program.c содержит функцию entry:

$ cat > program.c
#include <stdio.h>
int entry()
{
    return 0;
}
^D
  1. Сначала вы скомпилируете его, используя -c для создания перемещаемого объектного файла:

    $ gcc -c program.c -o program.o
    
  2. Затем вы переопределяете entry как main:

    $ objcopy --redefine-sym entry=main program.o
    
  3. Теперь используйте gcc для компиляции нового объектного файла:

    $ gcc program.o -o program
    

ПРИМЕЧАНИЕ. Если в вашей программе уже есть функция с именем main, перед шагом 2 вы можете выполнить отдельный вызов objcopy:

objcopy --redefine-sym oldmain=main program.o
person Rudy Matela    schedule 14.12.2015

Минимальный рабочий пример и примечания к другим ответам

main.c

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

int mymain(void) {
    puts("hello");
    exit(0);
}

скомпилировать и запустить:

gcc -nostartfiles -Wl,--entry=mymain -o main.out main.c
# or -Wl,-emymain
./main.out 1 2 3

Записи:

  • без -nostartfiles ссылка не работает с:

    /usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu/Scrt1.o: In function `_start':
    (.text+0x20): undefined reference to `main'
    collect2: error: ld returned 1 exit status
    

    предположительно, потому что код установки glibc, который запускается перед main в _start, обычно вызывает main.

  • Аргументы командной строки не настроены для вас, предположительно, потому что они будут настроены кодом glibc, который запускается перед основным, поэтому попытка их использования выводит неопределенные значения. Я не нашел метод, который работает для них.

Протестировано в Ubuntu 20.10.

person Ciro Santilli 新疆再教育营六四事件ۍ    schedule 29.10.2019
comment
Не работает, видимо предупреждение серьезное. - person Scott Franco; 02.01.2021
comment
@ScottFranco, кстати, какая у вас версия GCC/ОС? - person Ciro Santilli 新疆再教育营六四事件ۍ 02.01.2021
comment
C:\projects\petit_ami›gcc -v ... gcc версии 9.2.0 (MinGW.org GCC Build-2) - person Scott Franco; 04.01.2021
comment
@ScottFranco предупреждение было вызвано небольшой опечаткой -eentry= должно было быть --entry= ; Я отредактировал ответ соответственно. - person Demi-Lune; 05.01.2021
comment
@Demi-Lune хороший улов! Интересно, как это вообще сработало с опечаткой в ​​моем тесте! - person Ciro Santilli 新疆再教育营六四事件ۍ 05.01.2021
comment
@Self: раньше это работало по стечению обстоятельств, потому что это было первым в текстовом разделе - person Ciro Santilli 新疆再教育营六四事件ۍ 04.02.2021