问题
I am trying to allow specifying the location of particular symbols in my output binary without giving up the garbage collection feature of ld. For example: if I have in MyInclude.h
#ifndef MY_INCLUDE_H_
#define MY_INCLUDE_H_
void CalledFunc(void);
void UncalledFunc(void);
#endif
and a main program:
#include "MyInclude.h"
int main(void)
{
CalledFunc();
return 0;
}
compiling with gcc with ffunction-sections -fdata-sections
and linking with --gc-sections
shows in the map file that .text.UncalledFunc
has been removed.
I now have a need where I have to place certain functions in different sections. In this example if UncalledFunc()
did happen to be called, I want it to be in a special section. I have a linker parameter file that looks something like:
MEMORY
{
FLASH (rx) : ORIGIN = 0x10000000, LENGTH = 512K
}
SECTIONS
{
.text.myregion ORIGIN(FLASH):
{
*(.text.myregion)
*(.text.myregion*)
} >FLASH
ASSERT ( . <= 0x10010000, "Too much stuff in myregion!")
.text :
{
*(.text)
*(.text*)
} >FLASH
}
And UncalledFunc()
and CalledFunc()
defined as:
void CalledFunc(void) __attribute__ ((section (".text.myregion")))
{
/* ... */
}
void UncalledFunc(void) __attribute__ ((section (".text.myregion")))
{
/* ... */
}
In this case, it seems the function attribute overrides the per function section parameter sent to GCC. As such since both functions are in the same input section, they both appear in the output image. Is there a way to tell the linker to place UncalledFunc()
in .text.myregion
if it is called but still remove it if it is not? As shown above, myregion
has limited space and it would optimal to not place anything there that wasn't necessary.
回答1:
The compiler is just doing what it's told; you asked it to put that function in that section, so what else should it do?
The linker then sees all the functions in one section, and so garbage collection is not very helpful.
I've not tried this, but I would imagine that simply assigning different manual names to each function will solve the problem:
void CalledFunc(void) __attribute__ ((section (".text.myregion.CalledFunc")))
{
/* ... */
}
void UncalledFunc(void) __attribute__ ((section (".text.myregion.UncalledFunc")))
{
/* ... */
}
However, if that's a lot of typing (or if you use a macro to apply the attribute), then it might be better like this:
#define STRINGIFY(S) #S
#define TOSTRING(S) STRINGIFY(S)
#define NAME __FILE__ "." TOSTRING(__LINE__)
void CalledFunc(void) __attribute__ ((section (".text.myregion." NAME)))
{
/* ... */
}
That way you can do it with search-and-replace and still have each function have a unique section name. (It is necessary to use the macro because __LINE__
is an integer value, but we need a string here, and the #
"stringify" operator is only available inside macros. The apparently pointless levels of indirection cause __LINE__
to be evaluated into the actual line number.)
It might be that the __FUNCTION__
macro works, but I'm not confident given that this is outside the function body.
回答2:
If you use link time optimization, compiler should be able to remove unused functions, even if you put all of them into common section.
So keep modules (let's say include.c include.h test.c), but build like this:
gcc -c -Os -flto include.c -o include.o
gcc -c -Os -flto test.c -o test.o
gcc -flto -Os test.o include.o -o test
This will probably (depends on actual code) inline used function and remove unused one (unless you use attribute noinline.
来源:https://stackoverflow.com/questions/25428032/gcc-ld-allow-code-placement-and-removal-of-unused-functions