diff --git a/lld/ELF/Arch/RISCV.cpp b/lld/ELF/Arch/RISCV.cpp --- a/lld/ELF/Arch/RISCV.cpp +++ b/lld/ELF/Arch/RISCV.cpp @@ -120,16 +120,24 @@ for (InputFile *f : objectFiles) { uint32_t eflags = getEFlags(f); - if (eflags & EF_RISCV_RVC) - target |= EF_RISCV_RVC; - - if ((eflags & EF_RISCV_FLOAT_ABI) != (target & EF_RISCV_FLOAT_ABI)) - error(toString(f) + - ": cannot link object files with different floating-point ABI"); - - if ((eflags & EF_RISCV_RVE) != (target & EF_RISCV_RVE)) - error(toString(f) + - ": cannot link object files with different EF_RISCV_RVE"); + auto sections = f->getSections(); + + // Only validate for non-empty inputs which contain code sections which are + // loaded. + if (sections.size() && llvm::any_of(sections, [](const auto *section) { + return (section && (section->flags & (SHF_ALLOC | SHF_EXECINSTR))); + })) { + if ((eflags ^ target) & EF_RISCV_FLOAT_ABI) + error(toString(f) + + ": cannot link object files with different floating-point ABI"); + + if ((eflags ^ target) & EF_RISCV_RVE) + error(toString(f) + + ": cannot link object files with different EF_RISCV_RVE"); + + if (eflags & EF_RISCV_RVC) + target |= EF_RISCV_RVC; + } } return target; diff --git a/lld/test/ELF/riscv-abi-mismatch.test b/lld/test/ELF/riscv-abi-mismatch.test new file mode 100644 --- /dev/null +++ b/lld/test/ELF/riscv-abi-mismatch.test @@ -0,0 +1,51 @@ +// RUN: split-file %s %t + +// RUN: llvm-mc -triple riscv64 -filetype obj -o %t/function.o %t/function.s + +// RUN: yaml2obj %t/empty-lp64d.yml -o %t/empty-lp64d.o +// RUN: ld.lld -shared %t/function.o %t/empty-lp64d.o -o %t/libfloatabi.so +// RUN: not ld.lld -shared %t/empty-lp64d.o %t/function.o -o %t/libfloatabi.so 2>&1 | FileCheck %t/function.s -check-prefix CHECK-FLOAT-MISMATCH + +// RUN: yaml2obj %t/empty-rvc.yml -o %t/empty-rvc.o +// RUN: ld.lld -shared %t/function.o %t/empty-rvc.o -o %t/librvc.so +// RUN: llvm-readobj -h %t/librvc.so | FileCheck %t/function.s -check-prefix CHECK-NORVC-FLAGS + +// RUN: yaml2obj %t/empty-rvc.yml -o %t/empty-rvc.o +// RUN: ld.lld -shared %t/empty-rvc.o %t/function.o -o %t/librvc.so +// RUN: llvm-readobj -h %t/librvc.so | FileCheck %t/function.s -check-prefix CHECK-RVC-FLAGS + +// REQUIRES: riscv + +//--- empty-lp64d.yml +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_RISCV + Flags: [ EF_RISCV_FLOAT_ABI_DOUBLE ] + +//--- empty-rvc.yml +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_RISCV + Flags: [ EF_RISCV_RVC ] + +//--- function.s + .text + .global function + .type function,@function +function: + ret + +// CHECK-FLOAT-MISMATCH: function.o: cannot link object files with different floating-point ABI + +// CHECK-NORVC-FLAGS: Flags [ (0x0) +// CHECK-NORVC-FLAGS-NEXT: ] + +// CHECK-RVC-FLAGS: Flags [ (0x1) +// CHECK-RVC-FLAGS-NEXT: EF_RISCV_RVC (0x1) +// CHECK-RVC-FLAGS-NEXT: ]