TL; DR: не помещайте __weak__
, ни __alias__
в .h
файл. Поместите __weak__
и __alias__
в .c
файл.
Слабые символы теоретически работают следующим образом:
- Существует один файл
.o
с символом __weak__
. - Существует еще один
.o
файл с нормальным символом. - Компоновщик видит оба символа и выбирает неслабый символ.
Объектные файлы .o
генерируются из .c
файлов. Определение символа внутри .c
должно быть слабым.
Атрибуты, применяемые к объявлению, применяются к определениям, которые его видят. Выполнение __weak__
в заголовке в объявлении помечает все определения, которые видят, что объявление этого символа как __weak__
.
alias
работает так, как если бы вы делали:
static inline void NMI_Handler(void) {
Default_Handler();
}
Работает как-будто так же, но без ветки (и меньше набирает). И в любом случае, поскольку alias
создает символ, он действует как определение - он также принадлежит файлу .c
. По этой причине вы получаете многократную ошибку определения - __alias__
определяет символ NMI_Handler
, и вы позже определяете void NMI_Handler(void) {}
снова.
То, что вы хотите сделать, я думаю, это:
// vector_table.h
void __attribute__((noreturn)) Default_Handler (void);
void NMI_Handler(void);
// startup.c
void Default_Handler(void){
for(;;);
}
__attribute__((__weak__, __alias__("NMI_Handler")))
void NMI_Handler(void);
То же, что и в примере использования, как описано в gcc документации по атрибутам функций . В документации говорится, что другой символ с псевдонимом должен быть определен в той же единице транзакции (читается как: в том же файле .c
).
Помните, что объявление символа как слабого не означаетэтот компоновщик выделит сильный символ - при компиляции со статическими библиотеками иногда происходят странные вещи. Компилируйте только с объектами или используйте опции компоновщика -Wl,-start-group
. Я думаю, что infocenter.arm имеет лучшее объяснение этому.