Skip to content

[lld] Wrong folding of .data.rel.ro section in ICF for armv7a-linux-gnueabihf #138764

Open
@sergio-gdr

Description

@sergio-gdr

This is from the latest clang+llvm version available in ChromiumOS, but I think it is easily reproducible upstream also.

$ clang --version
Chromium OS 20.0_pre547379 clang version 20.0.0git
$ llvm-config --version
20.0.0git

To reproduce: icf-bug.zip

$ unzip icf-bug.zip

Compile object files:

/usr/bin/clang -O0 -ffunction-sections -fdata-sections -o main_arm.o -c main.c -target armv7a-linux-gnueabihf
/usr/bin/clang -O0 -ffunction-sections -fdata-sections -o foo_arm.o -c foo.c -target armv7a-linux-gnueabihf
/usr/bin/clang -O0 -ffunction-sections -fdata-sections -o bar_arm.o -c bar.c -target armv7a-linux-gnueabihf

Link them:

/usr/bin/clang -o test main_arm.o bar_arm.o foo_arm.o -O0 -ffunction-sections -fdata-sections -Wl,--icf=all -Wl,--print-icf-sections -target armv7a-linux-gnueabihf

Linker output for ICF:

selected section bar_arm.o:(.data.rel.ro..L__const.bar.icf2)                                                                                                  
  removing identical section foo_arm.o:(.data.rel.ro..L__const.foo.icf1)

These symbols are actually not identical,

struct foo icf1 = {
     .paths = { "/dev/", "/dev/i2c-254" },
};
struct bar icf2 = {
     .paths = { "/dev/", "/dev/null" },
};
                                                                                                                    };

and so the test program (incorrectly) prints

main function
icf1 /dev/null
icf2 /dev/null

The same sample on aarch64 (and amd64) does not perform this folding, and it (correctly) prints

main function
icf1 /dev/i2c-254
icf2 /dev/null

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions