Ответ 1
Большинство из них представляют собой различные методы для выполнения кода до или после самой "основной" программы и большинство из них живут в crtstuff.c
(https://github.com/gcc-mirror/gcc/blob/master/libgcc/crtstuff.c).
Они существуют для поддержки функций различных C-подобных языков программирования, но к ним также можно получить доступ на C. Возможно, это кажется сложным, потому что некоторые из них представляют собой устаревший багаж и некоторые изменения, необходимые для поддержки различных архитектур, на которых работает GCC.
Из списка, один за другим (или два на два):
00000000004003f0 t deregister_tm_clones
0000000000400430 t register_tm_clones
Транзакционная память предназначена для упрощения программирования с потоками. Это альтернатива синхронизации на основе блокировки. Эти подпрограммы сбрасывают и устанавливают, соответственно, таблицу, используемую библиотекой (libitm), которая поддерживает эти функции. Подробнее о ТМ здесь https://gcc.gnu.org/wiki/TransactionalMemory и здесь http://pmarlier.free.fr/gcc-tm-tut.html
0000000000400470 t __do_global_dtors_aux
Запускает все глобальные деструкторы при выходе из программы в системах, где .fini_array
недоступен.
0000000000400490 t frame_dummy
Эта функция находится в разделе .init
. Он определяется как void frame_dummy ( void )
, и вся его точка в жизни - это вызов __register_frame_info_bases
, который имеет аргументы. Очевидно, что вызов функций с аргументами из раздела .init
может быть ненадежным, поэтому эта функция так __register_frame_info_bases
не вызывается непосредственно из .init section
.
Информационные базы .eh_frame
используются для обработки исключений и аналогичных функций (например, функций, объявленных с помощью __attribute__((cleanup(..)))
).
00000000004004e0 T __libc_csu_init
0000000000400550 T __libc_csu_fini
Они запускают любые инициализаторы и финализаторы на уровне программ (вроде конструкторов/деструкторов для всей вашей программы). Если вы определяете такие функции, как:
void __attribute__ ((constructor)) mefirst () {
/* ... do something here ... */
}
void __attribute__ ((destructor)) melast () {
/* ... do something here ... */
}
они будут вызываться до и после main()
соответственно этими подпрограммами.
См. Также https://gcc.gnu.org/onlinedocs/gccint/Initialization.html
0000000000400554 T _fini
Это устаревший способ запуска деструктора на уровне уровня файла (на самом деле) (немного информации об этом можно найти в man dlclose
).
Соответствующая устаревшая функция для конструкторов __init
.
0000000000600668 t __frame_dummy_init_array_entry
0000000000600668 t __init_array_start
Они отмечают конец и начало раздела .init_array
, который содержит указатели на все инициализаторы уровня программы (см. выше __libc_csu_init).
0000000000600670 t __do_global_dtors_aux_fini_array_entry
0000000000600670 t __init_array_end
Они отмечают конец и начало раздела .fini_array
, который содержит указатели на все финализаторы уровня программы (см. выше __libc_csu_fini).
[EDIT] Некоторые дополнительные примечания:
-
Ссылка http://dbp-consulting.com/tutorials/debugging/linuxProgramStartup.html из комментария комментария Jester содержит хорошую диаграмму и небольшую выборку программа, иллюстрирующая общий порядок выполнения этих действий, а также для доступа к некоторым из этих функций из C.
-
Термины 'ctors' и 'dtors' являются аббревиатурами для "конструкторы" и "деструкторы" соответственно.
-
Разница между глобальными конструкторами/деструкторами и объектным файлом конструкторы/деструкторы наиболее очевидны, когда ваша программа построенный из нескольких объектных файлов.
-
Символы, отмеченные ' T' (__libc_csu_init, __libc_csu_fini, _fini) являются "глобальными" (внешне видимыми), остальные (отмеченные " t" ).