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.

Reply via email to