https://sourceware.org/bugzilla/show_bug.cgi?id=32961

            Bug ID: 32961
           Summary: ".pushsection" may introduce unnecessary section
                    dependency which impacts "--gc-sections"
           Product: binutils
           Version: 2.42
            Status: UNCONFIRMED
          Severity: normal
          Priority: P2
         Component: ld
          Assignee: unassigned at sourceware dot org
          Reporter: zhiyuan.lv at linux dot intel.com
  Target Milestone: ---

While compiling some Linux kernel files with "-ffunction-sections" and linker
parameter "--gc-sections", I found that several unused functions were not
removed as expected, and the root cause is unnecessary section dependencies
introduced by ".pushsection" directive. I simplified the case as below and
would like to get feedback from binutils developers of any existing workable
ways, or we could consider a new feature request to ld. Appreciate all the
input!

The case of test.c:

static inline __attribute__((always_inline)) void test_section(void)
{
        asm goto(
                "jmp 1f\n"
                ".pushsection .alt_section, \"ax\"\n"
                "1:\n"
                " jmp %l[t_label]\n"
                ".popsection\n"
                : :
                : : t_label);
t_label:
        return;
}

void foo1(void)
{
}

void foo2(void)
{
        test_section();
}

void foo3(void)
{
        test_section();
}

void entry_func(void)
{
        foo1();
        foo3();
}

The build command: gcc test.c -ffunction-sections -Wl,-e entry_func
-Wl,--gc-sections -o test -nostdlib -O0

My environment is Ubuntu 24.04, with LD version 2.42.

The expected result is that foo2() is optimized away in generated binary by
linker, but it can still be seen with "objdump -S test".

The root cause is at ".alt_section". If we check the section dependency from
relocation table in test.o generated by "gcc test.c -c -ffunction-sections -o
test.o", foo3 has relocation entry pointing to ".alt_section" and
".alt_section" has relocation try to ".foo2", which prevents LD from removing
foo2.

If I remove the inline attribute of test_section(), the function foo2() can be
removed by linker, because relocation entry of .alt_section will not link to
foo2 or foo3. Also, if there is no "test_section()" call in foo3(), foo2() can
be removed as well.

The linker does not do anything wrong, but in my case of Linux kernel from
"_static_cpu_has()" in arch/x86/include/asm/cpufeature.h, I cannot simply
remove inline and there does not seem to be a good solution.

If all above is correct, could we consider below two options?

1. Add a new type of ".pushsection", say, ".pushnewsection", which will always
create a new section.

2. Let LD be able to ignore some given sections while doing the section
dependency calculation. If a symbol is deleted, simply remove the relocation
entry in the specified "ignored section".

Either one can address above case of test.c. Any comments? Thanks!

-- 
You are receiving this mail because:
You are on the CC list for the bug.

Reply via email to