how to prevent linker from discarding a function?

我只是一个虾纸丫 提交于 2019-12-23 22:26:32

问题


I have a function in my C code that is being called implicitly, and getting dumped by the linker. how can I prevent this phenomena?

I'm compiling using gcc and the linker flag -gc-sections, and I don't want to exclude the whole file from the flag. I tried using attributes: "used" and "externally_visible" and neither has worked.

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

on map file I can see that the function has compiled but didn't linked. am I using it wrong? is there any other way to do it?


回答1:


You are misunderstanding the used attribute

used

This attribute, attached to a function, means that code must be emitted for the function even if it appears that the function is not referenced...

i.e the compiler must emit the function definition even the function appears to be unreferenced. The compiler will never conclude that a function is unreferenced if it has external linkage. So in this program:

main1.c

static void foo(void){}

int main(void)
{
    return 0;
}

compiled with:

$ gcc -c -O1 main1.c

No definition of foo is emitted at all:

$ nm main1.o
0000000000000000 T main

because foo is not referenced in the translation unit, is not external, and so may be optimised out.

But in this program:

main2.c

static void __attribute__((used)) foo(void){}

int main(void)
{
    return 0;
}

__attribute__((used)) compels the compiler to emit the local definition:

$ gcc -c -O1 main2.c
$ nm main2.o
0000000000000000 t foo
0000000000000001 T main

But this does nothing to inhibit the linker from discarding a section in which foo is defined, in the presence of -gc-sections, even if foo is external, if that section is unused:

main3.c

void foo(void){}

int main(void)
{
    return 0;
}

Compile with function-sections:

$ gcc -c -ffunction-sections -O1 main3.c

The global definition of foo is in the object file:

$ nm main3.o
0000000000000000 T foo
0000000000000000 T main

But after linking:

$ gcc -Wl,-gc-sections,-Map=mapfile main3.o

foo is not defined in the program:

$ nm a.out | grep foo; echo Done
Done

And the function-section defining foo was discarded:

mapfile

...
...
Discarded input sections
 ...
 ...
 .text.foo      0x0000000000000000        0x1 main3.o
 ...
 ...

As per Eric Postpischil's comment, to force the linker to retain an apparently unused function-section you must tell it to assume that the program references the unused function, with linker option {-u|--undefined} foo:

main4.c

void __attribute__((section(".mySec"))) foo(void){}

int main(void)
{
    return 0;
}

If you don't tell it that:

$ gcc -c main4.c
$ gcc -Wl,-gc-sections main4.o
$ nm a.out | grep foo; echo Done
Done

foo is not defined in the program. If you do tell it that:

$ gcc -c main4.c
$ gcc -Wl,-gc-sections,--undefined=foo main4.o
$ nm a.out | grep foo; echo Done
0000000000001191 T foo
Done

it is defined. There's no use for attribute used.



来源:https://stackoverflow.com/questions/53985290/how-to-prevent-linker-from-discarding-a-function

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!