Skip to content

LLD fails to link a kernel with LTO and DYNAMIC_FTRACE_WITH_REGS #953

@samitolvanen

Description

@samitolvanen

DYNAMIC_FTRACE_WITH_REGS turns on -fpatchable-function-entry=2, which results in the following errors from LLD during the final linking steps of vmlinux:

ld.lld: error: incompatible section flags for .init.data
>>> vmlinux.o:(__patchable_function_entries): 0x83
>>> output section .init.data: 0x3

ld.lld: error: incompatible section flags for .init.data
>>> <internal>:(.init.rodata.cst16): 0x12
>>> output section .init.data: 0x83

ld.lld: error: incompatible section flags for .init.data
>>> <internal>:(.init.rodata.str1.1): 0x32
>>> output section .init.data: 0x93

ld.lld: error: incompatible section flags for .init.data
>>> vmlinux.o:(.init.rodata): 0x12
>>> output section .init.data: 0xB3

ld.lld: error: incompatible section flags for .init.data
>>> vmlinux.o:(_ftrace_events): 0x3
>>> output section .init.data: 0xB3
...

Looking at the flags, __patchable_function_entries sections have the LINK ORDER flag set while it's not set for the other sections the kernel merges to .init.data in include/asm-generic/vmlinux.lds.h:

#define MCOUNT_REC()    . = ALIGN(8);                           \
                        __start_mcount_loc = .;                 \
                        KEEP(*(__mcount_loc))                   \
                        KEEP(*(__patchable_function_entries))   \
                        __stop_mcount_loc = .;                  \
                        ftrace_stub_graph = ftrace_stub;
...
#define INIT_DATA                                                       \
        KEEP(*(SORT(___kentry+*)))                                      \
        *(.init.data init.data.*)                                       \
        MEM_DISCARD(init.data*)                                         \
        KERNEL_CTORS()                                                  \
        MCOUNT_REC()                                                    \
...

I can reproduce the error with the following trivial example:

$ cat main.c
#define __section(S)    __attribute__((__section__(#S)))
#define __initdata      __section(.init.data)

static int a __initdata = 1;

int main()
{
        a = a - 1;
        return a;
}
$ cat init.lds 
SECTIONS {
        .init.data : {
                *(.init.data)
                *(__patchable_function_entries)
        }
}
$ clang -flto=thin -fvisibility=default -fpatchable-function-entry=2 \
-fuse-ld=lld -Wl,-T init.lds main.c
ld.lld: error: incompatible section flags for .init.data
>>> lto.tmp:(__patchable_function_entries): 0x83
>>> output section .init.data: 0x3
clang-11: error: linker command failed with exit code 1 (use -v to see invocation)

@nickdesaulniers @MaskRay Does this look like the kernel is doing something wrong, or is this a bug in LLVM?

Metadata

Metadata

Assignees

No one assigned

    Labels

    [BUG] llvmA bug that should be fixed in upstream LLVM[FEATURE] LTORelated to building the kernel with LLVM Link Time Optimization[FIXED][LLVM] 10This bug was fixed in LLVM 10.0[FIXED][LLVM] 11This bug was fixed in LLVM 11.0[TOOL] lldThe issue is relevant to LLD linker

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions