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

LTO disrespecting moving the dot in linker scripts for LTO #64573

Open
nickdesaulniers opened this issue Aug 9, 2023 · 1 comment
Open

LTO disrespecting moving the dot in linker scripts for LTO #64573

nickdesaulniers opened this issue Aug 9, 2023 · 1 comment
Labels
lld:ELF LTO Link time optimization (regular/full LTO or ThinLTO)

Comments

@nickdesaulniers
Copy link
Member

nickdesaulniers commented Aug 9, 2023

Consider the following C code:

// x.c
__attribute__((section("foo")))
int bar = 42;

int main () {
  return bar;
}

(So bar is in section foo, while main is in .text).

and poorly written (minimal?) linker script:

# foo.lds
PHDRS {
  text PT_LOAD ;
}
SECTIONS {
  .text : {
    *(.text)
    . = 0x100000;
    *(.foo)
  } : text
}

The goal here is to separate bar from main by 0x100000B.

Let's see what happens with various linkers without LTO first so that we can see clearly that LTO's behavior is quite surprising.

First let's look at GNU ld.bfd:

$ clang x.c -Wl,-T,foo.lds -O0
$ llvm-nm a.out | grep -e bar -e ' main'
00000000001005d8 D bar
00000000000000f0 T main

Well, they're not exactly 0x100000B apart, but they are at least 0x100000B apart. Ok.

And LLVM ld.lld:

$ clang x.c -Wl,-T,foo.lds -O0 -fuse-ld=lld
$ llvm-nm a.out | grep -e bar -e ' main'
0000000000100510 D bar
00000000000000f0 T main

Slightly different address for bar, but again, at least 0x100000B apart.

Now let's see what lld does with LTO:

$ clang x.c -Wl,-T,foo.lds -O0 -fuse-ld=lld -flto
$ llvm-nm a.out | grep -e bar -e ' main'
0000000000100530 d bar
0000000000100030 T main

This is a bit unexpected; suddenly both symbols are offset by 0x100000B. (at least the relative order of symbols hasn't changed, I guess).

This is forked from ClangBuiltLinux/linux#1909 in which Linux kernel security mitigations for AMD SRSO hardware vulnerabilities try to use a linker script to keep two symbols 0x104104 B apart. I don't think this can be done portably via linker script, but "it happened to have worked with ld.bfd" and now such kernel patches are merged in virtually every relevant tree, breaking every x86 build with lld.

It's pretty common in the Linux kernel's linker scripts to realign various sections using:

. = ALIGN(some constant)

if LTO is messing this up, some sections might not have the proper or expected alignment.

Is there another way to specify that a specific section (or symbol) should have an alignment (for ELF objects)? These sections in the kernel sources are defined in the assembler.

cc @MaskRay

@nickdesaulniers nickdesaulniers added lld:ELF LTO Link time optimization (regular/full LTO or ThinLTO) labels Aug 9, 2023
@llvmbot
Copy link
Collaborator

llvmbot commented Aug 9, 2023

@llvm/issue-subscribers-lld-elf

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
lld:ELF LTO Link time optimization (regular/full LTO or ThinLTO)
Projects
None yet
Development

No branches or pull requests

2 participants