как предотвратить компоновщик от сброса функции? - PullRequest
0 голосов
/ 31 декабря 2018

В моем C-коде есть функция, которая вызывается неявно и выводится компоновщиком.как я могу предотвратить это явление?

Я компилирую, используя gcc и флаг компоновщика -gc-section, и я не хочу исключать весь файл из флага.Я попытался использовать атрибуты: «used» и «externally_visible», и ни один из них не сработал.

void __attribute__((section(".mySec"), nomicromips, used)) func(){
...
}

в файле карты Я вижу, что функция скомпилирована, но не связана.я использую это неправильно?Есть ли другой способ сделать это?

1 Ответ

0 голосов
/ 31 декабря 2018

Вы неправильно понимаете атрибут 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.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...