id_soft 0 17 марта, 2011 Опубликовано 17 марта, 2011 · Жалоба Пытаюсь собрать пустой проект для sam3s. Линковщик ругается на неверную ссылку на функцию _init, которая, в свою очередь, вызывается из __libc_init_array(). cstartup.c взял из softpack от Atmel. Что это за функция _init()? Кто ее должен реализовывать и для чего она нужна? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
klen 1 17 марта, 2011 Опубликовано 17 марта, 2011 · Жалоба Пытаюсь собрать пустой проект для 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++ кода вы сможете обнаружить что не создаются глобальные объекты - как уже наверно понятно, некому будет вызвать их конструкторы. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
id_soft 0 18 марта, 2011 Опубликовано 18 марта, 2011 · Жалоба Спасибо за помощь. Проект собрался без ошибок. Буду пробовать в железе. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Pjotar 0 1 июня, 2011 Опубликовано 1 июня, 2011 · Жалоба Спасибо! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться