gcc/ld: Allow Code Placement And Removal of Unused Functions

跟風遠走 提交于 2019-12-11 10:03:19

问题


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

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