Цитата(id_soft @ Mar 17 2011, 15:15)

Пытаюсь собрать пустой проект для sam3s. Линковщик ругается на неверную ссылку на функцию _init, которая, в свою очередь, вызывается из __libc_init_array(). cstartup.c взял из softpack от Atmel.
Что это за функция _init()? Кто ее должен реализовывать и для чего она нужна?
это не ошибка. у вас нормальная полная реализация CRT кода по стандарту.
работает это так:
1 в crt имеется конструкция вида
Код
....
extern void __libc_init_array(void);
__libc_init_array();
....
2. в скрипте линкера должны быть определены подсекции
Код
_image_start_ = .;
_vec_start_ = .;
KEEP(*(.flash_vec_table*))
_vec_end_ = ALIGN( . , 8);
_text_start_ = _vec_end_;[b]
/* вызов статических конструкторов */
__preinit_array_start = .;
KEEP(*(.preinit_array*))
__preinit_array_end = .;
__init_array_start = .;
KEEP(*(.init_array*))
__init_array_end = .;[/b]
*(.text)
*(.text*) /*
это говорит линкеру куда складывать указатели функции помеченные атрибутами как конструкторы. получается вектор угазателей по адресу __init_array_start
3. при выполнении кода CRT вызывается __libc_init_array(), в newlib она определяется так :
Код
/* These magic symbols are provided by the linker. */
extern void (*__preinit_array_start []) (void) __attribute__((weak));
extern void (*__preinit_array_end []) (void) __attribute__((weak));
extern void (*__init_array_start []) (void) __attribute__((weak));
extern void (*__init_array_end []) (void) __attribute__((weak));
extern void (*__fini_array_start []) (void) __attribute__((weak));
extern void (*__fini_array_end []) (void) __attribute__((weak));
extern void _init (void);
extern void _fini (void);
[b]
/* Iterate over all the init routines. */
void
__libc_init_array (void)
{
size_t count;
size_t i;
count = __preinit_array_end - __preinit_array_start;
for (i = 0; i < count; i++)
__preinit_array_start[i] ();
_init ();
count = __init_array_end - __init_array_start;
for (i = 0; i < count; i++)
__init_array_start[i] ();
}
[/b]
/* Run all the cleanup routines. */
void
__libc_fini_array (void)
{
size_t count;
size_t i;
count = __fini_array_end - __fini_array_start;
for (i = count; i > 0; i--)
__fini_array_start[i-1] ();
_fini ();
}
видно что она идет по алресам и вызывет поочереди все фукции из ветрора "preinit" . далее далее вызывает _init () - эта функция должна быть определена пользователем если нада вмешатся в инииализацию. после нее вызываются конструкторы из вектора "init" - соственно сюда линкер складывает все функции с атрибутом __attribute__((constructor))
4. обычно в коде libc _init определена как "слабосвязанная" заглушка
Код
void __attribute__ ((weak)) _init(void) {}
но в newlib почемуто отсутствует. я добавил это в свой crt код.
теперь она не будет бкспокоить ликер - тело определено (пустое).
5. Самое последнее что обычно влияет на пользователя - Вы определеяет свою версию _init и Ваша реализация подменяется компиллером вместо заглушки. иначе вы ничего не видите и неподозреваете про нее и линкет ставит заглушку.
ps. если вышеприведенная хренатень не будет работать, то в случае компиляции C++ кода вы сможете обнаружить что не создаются глобальные объекты - как уже наверно понятно, некому будет вызвать их конструкторы.