Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ELF COMDAT needed for templates to enable linker data culling #3589

Closed
JohanEngelen opened this issue Oct 19, 2020 · 2 comments
Closed

ELF COMDAT needed for templates to enable linker data culling #3589

JohanEngelen opened this issue Oct 19, 2020 · 2 comments

Comments

@JohanEngelen
Copy link
Member

PR #3424 disabled COMDAT for ELF, which had an (obscure) side-effect that hurts a particular use case at Weka: it prevents unused data culling in a section when that section is accessed using the magic __start_* and __stop_* linker symbols.

The test case (4 files):

// File:  templ.d
import ldc.attributes;
auto get(int I)() {
    @(section("test_section")) @assumeUsed static __gshared int getInfo = I;
    return &getInfo;
}
// File: b.d and c.d (identical content, just to get more data into the test_section section)
import templ;
auto get() { return templ.get!(0)(); }
// File: a.d
import templ;
import b;
import c;

auto get() { return templ.get!(0)(); }

extern extern(C) __gshared {
  // Magic symbols to refer to the start and end of test_section.
    byte __start_test_section;
    byte __stop_test_section;
}

int main() {
    version(none) {
        import std.stdio;
        auto a = get();
        auto b = b.get();
        auto c = c.get();
        writeln(a != b, " (expected = false)");
        writeln(b != c, " (expected = false)");
        writeln(cast(size_t) (&__stop_test_section - &__start_test_section), " section size");
    }

    // The referal to the magic symbols prevents removal of the symbols inside test_section
    // if the program doesn't refer to those symbols otherwise (@assumeUsed prevents the compiler
    // from stripping the symbols, but not prevent the linker from doing so).
    size_t size = &__stop_test_section - &__start_test_section;
    return size > 0;
}

Build steps:

ldc2 -c b.d -of=b.o
ldc2 -c c.d -of=c.o
ldc2 -c templ.d -of=templ.o
ldc2 a.d b.o c.o templ.o -of=test

Objdump shows the problem. This is the output with and without COMDAT for the symbols in ELF (objdump --section-headers --section test_section test):

Without COMDAT:
Sections:
Idx Name          Size      VMA               LMA               File off  Algn
 28 test_section  0000000c  0000000000444ea8  0000000000444ea8  00043ea8  2**2

With COMDAT:
Sections:
Idx Name          Size      VMA               LMA               File off  Algn
 28 test_section  00000004  0000000000444ea8  0000000000444ea8  00043ea8  2**2

Without COMDAT: the symbols are merged, the pointers a, b, and c are all the same, but the unused pre-merge data remains and the size of test_section is 0xc = 3 integers.
With COMDAT: the symbols are merged, the pointers a, b, and c are all the same, and the unused data is removed and the size of test_section is 0x4 = 1 integers.

I don't know of another way to prevent the linker from stripping unreferenced symbols other than __start_/__stop_.

@kinke
Copy link
Member

kinke commented Sep 7, 2024

I've quickly tested the testcase on Ubuntu 22, with the bfd/gold/lld linkers (default distro versions). Differences:

  • The section size of 12 does not depend on accessing the magic start/stop linker symbols.
  • When removing @assumeUsed (but uncommenting the main body which accesses all symbols), lld (v14) correctly merges the symbols, yielding the expected section size of 4. bfd and gold yield 12. Edit: I've also checked mold v2.33 now; it also yields 12. :/

kinke added a commit to kinke/ldc that referenced this issue Sep 7, 2024
kinke added a commit to kinke/ldc that referenced this issue Sep 7, 2024
@kinke
Copy link
Member

kinke commented Sep 9, 2024

Fixed by #4748.

@kinke kinke closed this as completed Sep 9, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants