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

lld uses blx instruction, no object with architecture supporting feature detected #964

Closed
nickdesaulniers opened this issue Apr 1, 2020 · 15 comments
Labels
[ARCH] arm32 This bug impacts ARCH=arm [BUG] llvm A bug that should be fixed in upstream LLVM [FIXED][LLVM] 16 This bug was fixed in LLVM 16.0 Reported upstream This bug was filed on LLVM’s issue tracker, Phabricator, or the kernel mailing list. [Reported-by] kbuild test robot Reported-by: kbuild test robot <lkp@intel.com> [TOOL] lld The issue is relevant to LLD linker

Comments

@nickdesaulniers
Copy link
Member

0day bot reported this arm randconfig: https://groups.google.com/g/clang-built-linux/c/n7DXLyrlo-0/m/GTTaxotDBwAJ

>> ld.lld: warning: lld uses blx instruction, no object with architecture supporting feature detected
@nickdesaulniers nickdesaulniers added [BUG] Untriaged Something isn't working [TOOL] lld The issue is relevant to LLD linker [ARCH] arm32 This bug impacts ARCH=arm [Reported-by] kbuild test robot Reported-by: kbuild test robot <lkp@intel.com> labels Apr 1, 2020
@nathanchance
Copy link
Member

$ curl -LSs 'https://lore.kernel.org/lkml/202004010505.30nygaXZ%25lkp@intel.com/2-a.bin' | gzip -d > out/arm32/.config

$ make -j$(nproc) -s ARCH=arm CC=clang CROSS_COMPILE=arm-linux-gnueabi- LD=ld.lld O=out/arm32 olddefconfig all
/home/nathan/src/linux/arch/arm/mach-sa1100/generic.c:380:24: warning: unused variable 'standard_io_desc' [-Wunused-variable]
static struct map_desc standard_io_desc[] __initdata = {
                       ^
1 warning generated.
/home/nathan/src/linux/arch/arm/mm/copypage-v4mc.c:70:3: error: implicit declaration of function '__flush_dcache_page' [-Werror,-Wimplicit-function-declaration]
                __flush_dcache_page(page_mapping_file(from), from);
                ^
/home/nathan/src/linux/arch/arm/mm/copypage-v4mc.c:70:3: note: did you mean 'flush_dcache_page'?
/home/nathan/src/linux/arch/arm/include/asm/cacheflush.h:292:13: note: 'flush_dcache_page' declared here
extern void flush_dcache_page(struct page *);
            ^
/home/nathan/src/linux/arch/arm/mm/copypage-v4mc.c:74:2: error: implicit declaration of function 'set_top_pte' [-Werror,-Wimplicit-function-declaration]
        set_top_pte(COPYPAGE_MINICACHE, mk_pte(from, minicache_pgprot));
        ^
/home/nathan/src/linux/arch/arm/mm/copypage-v4mc.c:74:34: error: implicit declaration of function 'mk_pte' [-Werror,-Wimplicit-function-declaration]
        set_top_pte(COPYPAGE_MINICACHE, mk_pte(from, minicache_pgprot));
                                        ^
/home/nathan/src/linux/arch/arm/mm/copypage-v4mc.c:74:47: error: use of undeclared identifier 'L_PTE_PRESENT'
        set_top_pte(COPYPAGE_MINICACHE, mk_pte(from, minicache_pgprot));
                                                     ^
/home/nathan/src/linux/arch/arm/mm/copypage-v4mc.c:23:35: note: expanded from macro 'minicache_pgprot'
#define minicache_pgprot __pgprot(L_PTE_PRESENT | L_PTE_YOUNG | \
                                  ^
/home/nathan/src/linux/arch/arm/mm/copypage-v4mc.c:74:47: error: use of undeclared identifier 'L_PTE_YOUNG'
/home/nathan/src/linux/arch/arm/mm/copypage-v4mc.c:23:51: note: expanded from macro 'minicache_pgprot'
#define minicache_pgprot __pgprot(L_PTE_PRESENT | L_PTE_YOUNG | \
                                                  ^
/home/nathan/src/linux/arch/arm/mm/copypage-v4mc.c:74:47: error: use of undeclared identifier 'L_PTE_MT_MINICACHE'
/home/nathan/src/linux/arch/arm/mm/copypage-v4mc.c:24:7: note: expanded from macro 'minicache_pgprot'
                                  L_PTE_MT_MINICACHE)
                                  ^
/home/nathan/src/linux/arch/arm/mm/copypage-v4mc.c:74:14: error: use of undeclared identifier 'COPYPAGE_MINICACHE'
        set_top_pte(COPYPAGE_MINICACHE, mk_pte(from, minicache_pgprot));
                    ^
/home/nathan/src/linux/arch/arm/mm/copypage-v4mc.c:76:28: error: use of undeclared identifier 'COPYPAGE_MINICACHE'
        mc_copy_user_page((void *)COPYPAGE_MINICACHE, kto);
                                  ^
/home/nathan/src/linux/arch/arm/mm/copypage-v4mc.c:109:21: error: variable has incomplete type 'struct cpu_user_fns'
struct cpu_user_fns v4_mc_user_fns __initdata = {
                    ^
/home/nathan/src/linux/arch/arm/mm/copypage-v4mc.c:109:8: note: forward declaration of 'struct cpu_user_fns'
struct cpu_user_fns v4_mc_user_fns __initdata = {
       ^
9 errors generated.
make[3]: *** [/home/nathan/src/linux/scripts/Makefile.build:267: arch/arm/mm/copypage-v4mc.o] Error 1
make[2]: *** [/home/nathan/src/linux/Makefile:1702: arch/arm/mm] Error 2
make[2]: *** Waiting for unfinished jobs....
/home/nathan/src/linux/arch/arm/mach-sa1100/assabet.c:631:38: error: use of undeclared identifier 'PMD_MASK'
        unsigned long phys = __PREG(GPLR) & PMD_MASK;
                                            ^
/home/nathan/src/linux/arch/arm/mach-sa1100/assabet.c:633:13: error: use of undeclared identifier 'pmdval_t'
        int prot = PMD_TYPE_SECT | PMD_SECT_AP_WRITE | PMD_DOMAIN(DOMAIN_IO);
                   ^
/home/nathan/src/linux/arch/arm/include/asm/pgtable-2level-hwdef.h:19:29: note: expanded from macro 'PMD_TYPE_SECT'
#define PMD_TYPE_SECT           (_AT(pmdval_t, 2) << 0)
                                     ^
/home/nathan/src/linux/arch/arm/mach-sa1100/assabet.c:633:29: error: use of undeclared identifier 'pmdval_t'
        int prot = PMD_TYPE_SECT | PMD_SECT_AP_WRITE | PMD_DOMAIN(DOMAIN_IO);
                                   ^
/home/nathan/src/linux/arch/arm/include/asm/pgtable-2level-hwdef.h:32:32: note: expanded from macro 'PMD_SECT_AP_WRITE'
#define PMD_SECT_AP_WRITE       (_AT(pmdval_t, 1) << 10)
                                     ^
/home/nathan/src/linux/arch/arm/mach-sa1100/assabet.c:633:49: error: use of undeclared identifier 'pmdval_t'
        int prot = PMD_TYPE_SECT | PMD_SECT_AP_WRITE | PMD_DOMAIN(DOMAIN_IO);
                                                       ^
/home/nathan/src/linux/arch/arm/include/asm/pgtable-2level-hwdef.h:22:29: note: expanded from macro 'PMD_DOMAIN'
#define PMD_DOMAIN(x)           (_AT(pmdval_t, (x)) << 5)
                                     ^
/home/nathan/src/linux/arch/arm/mach-sa1100/assabet.c:638:2: error: implicit declaration of function 'flush_pmd_entry' [-Werror,-Wimplicit-function-declaration]
        flush_pmd_entry(pmd);
        ^
5 errors generated.
make[3]: *** [/home/nathan/src/linux/scripts/Makefile.build:267: arch/arm/mach-sa1100/assabet.o] Error 1
make[2]: *** [/home/nathan/src/linux/Makefile:1702: arch/arm/mach-sa1100] Error 2
ld.lld: warning: lld uses blx instruction, no object with architecture supporting feature detected
ld.lld: warning: lld uses blx instruction, no object with architecture supporting feature detected
ld.lld: warning: lld uses blx instruction, no object with architecture supporting feature detected
ld.lld: warning: lld uses blx instruction, no object with architecture supporting feature detected
ld.lld: warning: lld uses blx instruction, no object with architecture supporting feature detected
ld.lld: warning: lld uses blx instruction, no object with architecture supporting feature detected
ld.lld: warning: lld uses blx instruction, no object with architecture supporting feature detected
ld.lld: warning: lld uses blx instruction, no object with architecture supporting feature detected
ld.lld: warning: lld uses blx instruction, no object with architecture supporting feature detected
ld.lld: warning: lld uses blx instruction, no object with architecture supporting feature detected
ld.lld: warning: lld uses blx instruction, no object with architecture supporting feature detected
ld.lld: warning: lld uses blx instruction, no object with architecture supporting feature detected
ld.lld: warning: lld uses blx instruction, no object with architecture supporting feature detected
ld.lld: warning: lld uses blx instruction, no object with architecture supporting feature detected
ld.lld: warning: lld uses blx instruction, no object with architecture supporting feature detected
ld.lld: warning: lld uses blx instruction, no object with architecture supporting feature detected
ld.lld: warning: lld uses blx instruction, no object with architecture supporting feature detected
make[1]: *** [/home/nathan/src/linux/Makefile:328: __build_one_by_one] Error 2
make: *** [Makefile:180: sub-make] Error 2

https://github.com/llvm/llvm-project/blob/f203100ebe22bf97a4268a562cdbef22d14db915/lld/ELF/Driver.cpp#L1996-L2003

https://github.com/llvm/llvm-project/blob/f203100ebe22bf97a4268a562cdbef22d14db915/lld/test/ELF/arm-blx-v4t.s

$ rg CPU_32 out/arm32/.config
259:CONFIG_CPU_32v4=y

Seems expected given the config. If we had a config for ld.lld, we could just avoid selecting CPU__32v4 or CPU_32v4T if using ld.lld.

@nickdesaulniers
Copy link
Member Author

yes, maybe a way forward is to upstream Android's CONFIG_LD_IS_ patches (cc @samitolvanen ) then we can disable certain configs when it's selected. cc @masahir0y for thoughts on that.

We could also just mark CONFIG_CPU_32v4 disabled for Clang. I think your report above is the furthest anyone's testing Linux ARMv4 w/ Clang.

@masahir0y
Copy link

I am fine with LD_IS_LLD if it is useful.

@MaskRay
Copy link
Member

MaskRay commented Apr 2, 2020

LD_IS_LLD looks fine with me. The upstream tends to not support rarely used/obsoleted/error-prone features/ABI variants. Some CONFIG_* may never make sense for lld.

I wonder whether this can also benefit big-endian powerpc64 #602. There is no interest to support elfv1. If we enable elfv2 ("Power Architecture 64-Bit ELF V2 ABI Specification") via some config, then this config should always to y if linked with lld.

@nathanchance
Copy link
Member

Hmmm, looking over this, fixing this up is going to be rather invasive. Reason being is that CONFIG_CPU_32v4{,T} are not user selectable, they are only selected by configs that need them. As a result, we can't make CONFIG_CPU_32v4{,T} depend on CONFIG_LD_IS_LLD otherwise we'll get some Kconfig warnings because select overrides depends on.

WARNING: unmet direct dependencies detected for CPU_32v4
  Depends on [n]: !LD_IS_LLD [=y]
  Selected by [y]:
  - CPU_SA1100 [=y]

We could just never select CONFIG_CPU_32v4{,T} when using CONFIG_LD_IS_LLD but that just blows up the config in another way because __LINUX_ARM_ARCH__ is unset and evaluates to zero.

The real solution it seems is to avoid selecting the machines that select these configs in arch/arm/Kconfig but it gets reallllly messy from there.

@nickdesaulniers
Copy link
Member Author

updateSupportedARMFeatures in llvm-project/lld/ELF/InputFiles.cpp has a comment:

    // Architectures prior to v5 do not support BLX instruction

but there's also a FIXME in llvm-project/lld/ELF/Driver.cpp:

    // FIXME: These warnings can be removed when lld only uses these features
    // when the input objects have been compiled with an architecture that
    // supports them.

Indeed, it looks like a Kconfig fix is going to be quite invasive to disable LLD pre-ARMv5.

@nickdesaulniers
Copy link
Member Author

because select overrides depends on

That's kind of frustrating. That means then that we have to add depends on !LD_IS_LLD to many leaf configs, rather than root configs.

@nickdesaulniers
Copy link
Member Author

Easily reproducible with shannon_defconfig.

llvm commit 57eb0469847b ("[ELF] Read ARM BuildAttributes section to determine supported features.") has more context.

To silence any warning for shannon_defconfig:

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index e6e08d8a45fc..3379ae750a84 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -459,6 +459,7 @@ config ARCH_RPC
 
 config ARCH_SA1100
        bool "SA1100-based"
+       depends on !LD_IS_LLD
        select ARCH_MTD_XIP
        select ARCH_SPARSEMEM_ENABLE
        select CLKSRC_MMIO

It builds but it's obviously going to not boot/work properly, since that disables CPU_SA1100 and CPU_32v4. Perhaps that's an improvement for randconfig testing though?

@nickdesaulniers
Copy link
Member Author

nickdesaulniers commented Aug 9, 2021

reported upstream: https://llvm.org/pr51422

@nickdesaulniers nickdesaulniers added [BUG] llvm A bug that should be fixed in upstream LLVM Reported upstream This bug was filed on LLVM’s issue tracker, Phabricator, or the kernel mailing list. and removed [BUG] Untriaged Something isn't working labels Aug 9, 2021
intel-lab-lkp pushed a commit to intel-lab-lkp/linux that referenced this issue Dec 19, 2022
lld cannot build for ARMv4/v4T targets because it inserts 'blx' instructions
that are unsupported there:

  ld.lld: warning: lld uses blx instruction, no object with architecture supporting feature detected

Add a Kconfig time dependency to prevent those targets from being
selected in randconfig builds.

Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Reviewed-by: Nathan Chancellor <nathan@kernel.org>
Link: llvm/llvm-project#50764
Link: ClangBuiltLinux#964
Link: https://lore.kernel.org/r/20221215162635.3750763-1-arnd@kernel.org
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
@nickdesaulniers
Copy link
Member Author

I wonder if https://reviews.llvm.org/rG62c605771a30 is relevant?

@nickdesaulniers
Copy link
Member Author

llvm/llvm-project#50764 was just closed out. We should see if we can update intel-lab-lkp@6a7ee50 for lld-16.

cc @arndb @stuij

@nathanchance
Copy link
Member

intel-lab-lkp pushed a commit to intel-lab-lkp/linux that referenced this issue Jan 18, 2023
Commit 6a7ee50 ("ARM: disallow pre-ARMv5 builds with ld.lld")
prevented v4 or v4t kernels when ld.lld will link the kernel due to
inserting unsupported blx instructions.

ld.lld has been fixed in current main (16.0.0) to avoid inserting these
instructions by inserting position independent thunks instead. Allow
these configurations to be enabled when ld.lld 16.0.0 is used to link
the kernel.

Additionally, add a link to the upstream LLVM issue so that the reason
for this dependency is clearly documented.

Link: ClangBuiltLinux#964
Link: llvm/llvm-project@6f9ff1b
Suggested-by: Nick Desaulniers <ndesaulniers@google.com>
Signed-off-by: Nathan Chancellor <nathan@kernel.org>
@nathanchance nathanchance added [PATCH] Submitted A patch has been submitted for review [FIXED][LLVM] 16 This bug was fixed in LLVM 16.0 labels Jan 18, 2023
@nathanchance
Copy link
Member

Patch submitted to Russell's patch tracker: https://www.armlinux.org.uk/developer/patches/viewpatch.php?id=9289/1

@nathanchance
Copy link
Member

@nathanchance nathanchance added [PATCH] Accepted A submitted patch has been accepted upstream and removed [PATCH] Submitted A patch has been submitted for review labels Jan 31, 2023
roxell pushed a commit to roxell/linux that referenced this issue Feb 1, 2023
Commit 6a7ee50 ("ARM: disallow pre-ARMv5 builds with ld.lld")
prevented v4 or v4t kernels when ld.lld will link the kernel due to
inserting unsupported blx instructions.

ld.lld has been fixed in current main (16.0.0) to avoid inserting these
instructions by inserting position independent thunks instead. Allow
these configurations to be enabled when ld.lld 16.0.0 is used to link
the kernel.

Additionally, add a link to the upstream LLVM issue so that the reason
for this dependency is clearly documented.

Link: ClangBuiltLinux#964
Link: llvm/llvm-project@6f9ff1b

Suggested-by: Nick Desaulniers <ndesaulniers@google.com>
Tested-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Nathan Chancellor <nathan@kernel.org>
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
@nathanchance
Copy link
Member

Patch is now available in mainline: https://git.kernel.org/linus/5eb6e280432ddc9b755193552f3a070da8d7455c

@nathanchance nathanchance added [FIXED][LINUX] 6.3 This bug was fixed in Linux 6.3 and removed [PATCH] Accepted A submitted patch has been accepted upstream [FIXED][LINUX] 6.3 This bug was fixed in Linux 6.3 labels Feb 22, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[ARCH] arm32 This bug impacts ARCH=arm [BUG] llvm A bug that should be fixed in upstream LLVM [FIXED][LLVM] 16 This bug was fixed in LLVM 16.0 Reported upstream This bug was filed on LLVM’s issue tracker, Phabricator, or the kernel mailing list. [Reported-by] kbuild test robot Reported-by: kbuild test robot <lkp@intel.com> [TOOL] lld The issue is relevant to LLD linker
Projects
None yet
Development

No branches or pull requests

4 participants