[Bug lto/126841] [LTO][IPA-ICF] -ffunction-sections emits distinct lto_priv functions into the same section

luolongjuna at gmail dot com via Gcc-bugs <[email protected]>
Newsgroups gmane.comp.gcc.bugs
Message-ID <[email protected]/bugzilla/>
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=126841

--- Comment #5 from Longjun Luo <luolongjuna at gmail dot com> ---
One additional observation: this is not limited to identical function bodies
being placed together. The retained section name can also co-locate a
privatized local function with an unrelated exported one.

a.c:
  static int same_fn(int x) { return x * 33 + 7; }
  int (*a_cb)(int) = same_fn;

b.c:
  static int same_fn(int x) { return x * 33 + 7; }
  int (*b_cb)(int) = same_fn;

d.c:
  int same_fn(int x) { return x - 1; }

  gcc -O2 -flto -ffunction-sections -fPIC -c a.c -o a.o
  gcc -O2 -flto -ffunction-sections -fPIC -c b.c -o b.o
  gcc -O2 -flto -ffunction-sections -fPIC -c d.c -o d.o
  gcc -shared -O2 -flto -ffunction-sections -save-temps=obj \
      a.o b.o d.o -o r.so
  gcc -c r.so.ltrans0.ltrans.s -o ltrans-native.o

readelf -Ws ltrans-native.o:

  3: 0000000000000000  10 FUNC LOCAL  DEFAULT 4 same_fn.lto_priv.0
  5: 0000000000000000  10 FUNC LOCAL  DEFAULT 5 same_fn.lto_priv.1
  6: 0000000000000010   4 FUNC GLOBAL DEFAULT 5 same_fn

readelf -SW ltrans-native.o:

  [4] .text.same_fn.lto_priv.0  PROGBITS ... size 0x0a
  [5] .text.same_fn             PROGBITS ... size 0x14

Thus .text.same_fn contains the file-local same_fn.lto_priv.1 at offset 0x0
and the exported same_fn at offset 0x10. They differ in linkage, assembler
name, and implementation. Although the section name exactly matches the
exported function, the private body occupies its beginning. As a result, a
linker script rule such as *(.text.same_fn), or any other section-name based
selection, necessarily selects both functions; they can no longer be placed
or discarded as independent function sections.

For comparison, the analogous variable case behaves differently. Three
translation units, each containing

  static int same_var = 42;
  int *a_ptr = &same_var;        /* b_ptr and c_ptr in the other two */

and built the same way with -fdata-sections added emit

  .data.same_var.lto_priv.0
  .data.same_var.lto_priv.1
  .data.same_var.lto_priv.2

so the emitted data-section names track the privatized assembler names.
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.