Вы неправильно понимаете атрибут used
используется
Этот атрибут, прикрепленный к функции, означает, что для функции должен быть выдан коддаже если кажется, что на функцию не ссылаются ...
то есть компилятор должен выдать определение функции, даже если функция не имеет ссылки.Компилятор никогда не придет к выводу, что на функцию не ссылаются, если она имеет внешнюю связь.Итак, в этой программе:
main1.c
static void foo(void){}
int main(void)
{
return 0;
}
скомпилировано с:
$ gcc -c -O1 main1.c
Нет определения foo
ввсе:
$ nm main1.o
0000000000000000 T main
, поскольку foo
не указан в блоке перевода, не является внешним и может быть оптимизирован.
Но в этой программе:
main2.c
static void __attribute__((used)) foo(void){}
int main(void)
{
return 0;
}
__attribute__((used))
заставляет компилятор выдавать локальное определение:
$ gcc -c -O1 main2.c
$ nm main2.o
0000000000000000 t foo
0000000000000001 T main
Но это никак не влияет на компоновщик от отбрасывания раздела, в котором определен foo
, при наличии -gc-sections
, даже если foo
является внешним, если этот раздел не используется:
main3.c
void foo(void){}
int main(void)
{
return 0;
}
Компилировать с функциональными разделами:
$ gcc -c -ffunction-sections -O1 main3.c
Глобальное определение foo
находится в объектном файле:
$ nm main3.o
0000000000000000 T foo
0000000000000000 T main
Но после связывания:
$ gcc -Wl,-gc-sections,-Map=mapfile main3.o
foo
не определено в программе :
$ nm a.out | grep foo; echo Done
Done
И определение функционального раздела foo
было отброшено:
mapfile
...
...
Discarded input sections
...
...
.text.foo 0x0000000000000000 0x1 main3.o
...
...
Согласно комментарию Эрика Постпишила, чтобы компоновщик сохранил явно неиспользуемый функциональный раздел, вы должны сообщить , что чтоПрограмма ссылается на неиспользуемую функцию, с опцией компоновщика {-u|--undefined} foo
:
main4.c
void __attribute__((section(".mySec"))) foo(void){}
int main(void)
{
return 0;
}
Если вы этого не скажетечто:
$ gcc -c main4.c
$ gcc -Wl,-gc-sections main4.o
$ nm a.out | grep foo; echo Done
Done
foo
не определено в программе.Если вы скажете ему, что:
$ gcc -c main4.c
$ gcc -Wl,-gc-sections,--undefined=foo main4.o
$ nm a.out | grep foo; echo Done
0000000000001191 T foo
Done
, это определено.Там нет смысла для атрибута used
.