[lld] [ELF] Reject certain unknown section types (PR #85173)
Fangrui Song via llvm-commits
llvm-commits at lists.llvm.org
Wed Mar 13 20:56:13 PDT 2024
https://github.com/MaskRay created https://github.com/llvm/llvm-project/pull/85173
Unknown section sections may require special linking rule, and rejecting
such sections for older linkers may be desired. For example, if we
introduce a new section type to replace a control structure (e.g.
relocations), it would be nice for older linkers to reject the new
section type. GNU ld allows certain unknown section types:
* [SHT_LOUSER,SHT_HIUSER] and non-SHF_ALLOC
* [SHT_LOOS,SHT_HIOS] and non-SHF_OS_NONCONFORMING
but reports errors and stops linking for others (unless
--no-warn-mismatch is specified). Port its behavior.
Close https://github.com/llvm/llvm-project/issues/84812
>From 2bc0b513bc966ded7692f8a89a523a13ca4f9779 Mon Sep 17 00:00:00 2001
From: Fangrui Song <i at maskray.me>
Date: Wed, 13 Mar 2024 20:56:03 -0700
Subject: [PATCH] =?UTF-8?q?[=F0=9D=98=80=F0=9D=97=BD=F0=9D=97=BF]=20initia?=
=?UTF-8?q?l=20version?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Created using spr 1.3.5-bogner
---
lld/ELF/Config.h | 1 +
lld/ELF/Driver.cpp | 1 +
lld/ELF/InputFiles.cpp | 51 ++++++++++++++++---
lld/ELF/Options.td | 4 +-
lld/test/ELF/incompatible-section-types2.s | 2 +-
.../ELF/linkerscript/custom-section-type.s | 2 +-
lld/test/ELF/unknown-section.test | 50 ++++++++++++++++++
7 files changed, 102 insertions(+), 9 deletions(-)
create mode 100644 lld/test/ELF/unknown-section.test
diff --git a/lld/ELF/Config.h b/lld/ELF/Config.h
index 9ae01eb90fa4a3..6c46249c528718 100644
--- a/lld/ELF/Config.h
+++ b/lld/ELF/Config.h
@@ -273,6 +273,7 @@ struct Config {
bool printGcSections;
bool printIcfSections;
bool printMemoryUsage;
+ bool rejectMismatch;
bool relax;
bool relaxGP;
bool relocatable;
diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp
index 2439d141fb6643..e7160a47bd2142 100644
--- a/lld/ELF/Driver.cpp
+++ b/lld/ELF/Driver.cpp
@@ -1348,6 +1348,7 @@ static void readConfigs(opt::InputArgList &args) {
config->printArchiveStats = args.getLastArgValue(OPT_print_archive_stats);
config->printSymbolOrder =
args.getLastArgValue(OPT_print_symbol_order);
+ config->rejectMismatch = !args.hasArg(OPT_no_warn_mismatch);
config->relax = args.hasFlag(OPT_relax, OPT_no_relax, true);
config->relaxGP = args.hasFlag(OPT_relax_gp, OPT_no_relax_gp, false);
config->rpath = getRpath(args);
diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp
index 00aebb47640e84..ad022c9685f716 100644
--- a/lld/ELF/InputFiles.cpp
+++ b/lld/ELF/InputFiles.cpp
@@ -741,6 +741,31 @@ template <class ELFT> void ObjFile<ELFT>::initializeJustSymbols() {
sections.resize(numELFShdrs);
}
+static bool isKnownSpecificSectionType(uint32_t t, uint32_t flags) {
+ if (SHT_LOUSER <= t && t <= SHT_HIUSER && !(flags & SHF_ALLOC))
+ return true;
+ if (SHT_LOOS <= t && t <= SHT_HIOS && !(flags & SHF_OS_NONCONFORMING))
+ return true;
+ switch (config->emachine) {
+ case EM_ARM:
+ return t == SHT_ARM_EXIDX || t == SHT_ARM_ATTRIBUTES;
+ case EM_AARCH64:
+ return t == SHT_AARCH64_MEMTAG_GLOBALS_STATIC;
+ case EM_MIPS:
+ return is_contained(
+ {SHT_MIPS_REGINFO, SHT_MIPS_OPTIONS, SHT_MIPS_DWARF, SHT_MIPS_ABIFLAGS},
+ t);
+ case EM_MSP430:
+ return t == SHT_MSP430_ATTRIBUTES;
+ case EM_RISCV:
+ return t == SHT_RISCV_ATTRIBUTES;
+ case EM_X86_64:
+ return t == SHT_X86_64_UNWIND;
+ default:
+ return false;
+ }
+}
+
template <class ELFT>
void ObjFile<ELFT>::initializeSections(bool ignoreComdats,
const llvm::object::ELFFile<ELFT> &obj) {
@@ -752,14 +777,15 @@ void ObjFile<ELFT>::initializeSections(bool ignoreComdats,
if (this->sections[i] == &InputSection::discarded)
continue;
const Elf_Shdr &sec = objSections[i];
+ const uint32_t type = sec.sh_type;
// SHF_EXCLUDE'ed sections are discarded by the linker. However,
// if -r is given, we'll let the final link discard such sections.
// This is compatible with GNU.
if ((sec.sh_flags & SHF_EXCLUDE) && !config->relocatable) {
- if (sec.sh_type == SHT_LLVM_CALL_GRAPH_PROFILE)
+ if (type == SHT_LLVM_CALL_GRAPH_PROFILE)
cgProfileSectionIndex = i;
- if (sec.sh_type == SHT_LLVM_ADDRSIG) {
+ if (type == SHT_LLVM_ADDRSIG) {
// We ignore the address-significance table if we know that the object
// file was created by objcopy or ld -r. This is because these tools
// will reorder the symbols in the symbol table, invalidating the data
@@ -778,7 +804,7 @@ void ObjFile<ELFT>::initializeSections(bool ignoreComdats,
continue;
}
- switch (sec.sh_type) {
+ switch (type) {
case SHT_GROUP: {
if (!config->relocatable)
sections[i] = &InputSection::discarded;
@@ -801,12 +827,25 @@ void ObjFile<ELFT>::initializeSections(bool ignoreComdats,
case SHT_RELA:
case SHT_NULL:
break;
- case SHT_LLVM_SYMPART:
- ctx.hasSympart.store(true, std::memory_order_relaxed);
- [[fallthrough]];
+ case SHT_PROGBITS:
+ case SHT_NOTE:
+ case SHT_NOBITS:
+ case SHT_INIT_ARRAY:
+ case SHT_FINI_ARRAY:
+ case SHT_PREINIT_ARRAY:
+ this->sections[i] =
+ createInputSection(i, sec, check(obj.getSectionName(sec, shstrtab)));
+ break;
default:
this->sections[i] =
createInputSection(i, sec, check(obj.getSectionName(sec, shstrtab)));
+ if (type == SHT_LLVM_SYMPART)
+ ctx.hasSympart.store(true, std::memory_order_relaxed);
+ else if (config->rejectMismatch &&
+ !isKnownSpecificSectionType(type, sec.sh_flags))
+ errorOrWarn(toString(this->sections[i]) + ": unknown section type 0x" +
+ Twine::utohexstr(type));
+ break;
}
}
diff --git a/lld/ELF/Options.td b/lld/ELF/Options.td
index 3819b86238ea64..c5e95d0d25c1ae 100644
--- a/lld/ELF/Options.td
+++ b/lld/ELF/Options.td
@@ -312,6 +312,9 @@ def no_dynamic_linker: F<"no-dynamic-linker">,
def noinhibit_exec: F<"noinhibit-exec">,
HelpText<"Retain the executable output file whenever it is still usable">;
+def no_warn_mismatch: F<"no-warn-mismatch">,
+ HelpText<"Suppress errors for certain unknown seciton types">;
+
def no_nmagic: F<"no-nmagic">, MetaVarName<"<magic>">,
HelpText<"Page align sections (default)">;
@@ -753,7 +756,6 @@ def: FF<"no-add-needed">;
def: F<"no-copy-dt-needed-entries">;
def: F<"no-ctors-in-init-array">;
def: F<"no-keep-memory">;
-def: F<"no-warn-mismatch">;
def: Separate<["--", "-"], "rpath-link">;
def: J<"rpath-link=">;
def: F<"secure-plt">;
diff --git a/lld/test/ELF/incompatible-section-types2.s b/lld/test/ELF/incompatible-section-types2.s
index 3e281ce6c5da38..919515fe37e396 100644
--- a/lld/test/ELF/incompatible-section-types2.s
+++ b/lld/test/ELF/incompatible-section-types2.s
@@ -6,5 +6,5 @@
// CHECK-NEXT: >>> <internal>:(.shstrtab): SHT_STRTAB
// CHECK-NEXT: >>> output section .shstrtab: Unknown
-.section .shstrtab,"", at 12345
+.section .shstrtab,"", at 0x60000000
.short 20
diff --git a/lld/test/ELF/linkerscript/custom-section-type.s b/lld/test/ELF/linkerscript/custom-section-type.s
index 68454f4df1c860..8ca0a4db325bda 100644
--- a/lld/test/ELF/linkerscript/custom-section-type.s
+++ b/lld/test/ELF/linkerscript/custom-section-type.s
@@ -76,7 +76,7 @@ SECTIONS {
.section progbits,"a", at note
.byte 0
-.section expr,"a", at 12345
+.section expr,"a", at 0x60000000
.byte 0
#--- unknown1.lds
diff --git a/lld/test/ELF/unknown-section.test b/lld/test/ELF/unknown-section.test
new file mode 100644
index 00000000000000..7cca5e913c3c0f
--- /dev/null
+++ b/lld/test/ELF/unknown-section.test
@@ -0,0 +1,50 @@
+# RUN: rm -rf %t && mkdir %t && cd %t
+# RUN: yaml2obj %s -o a.o
+# RUN: not ld.lld a.o -o /dev/null 2>&1 | FileCheck %s --implicit-check-not=error:
+
+# CHECK: error: a.o:(relr): unknown section type 0x13
+# CHECK-NEXT: error: a.o:(regular): unknown section type 0x15
+# CHECK-NEXT: error: a.o:(loos_nonconforming): unknown section type 0x60000000
+# CHECK-NEXT: error: a.o:(hios_nonconforming): unknown section type 0x6fffffff
+# CHECK-NEXT: error: a.o:(loproc): unknown section type 0x70000000
+# CHECK-NEXT: error: a.o:(hiproc): unknown section type 0x7fffffff
+# CHECK-NEXT: error: a.o:(louser_alloc): unknown section type 0x80000000
+# CHECK-NEXT: error: a.o:(hiuser_alloc): unknown section type 0xffffffff
+
+--- !ELF
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ Type: ET_REL
+ Machine: EM_X86_64
+Sections:
+ - Name: relr
+ Type: 19
+ - Name: regular
+ Type: 21
+ - Name: loos
+ Type: 0x60000000
+ - Name: hios
+ Type: 0x6fffffff
+ - Name: loos_nonconforming
+ Type: 0x60000000
+ Flags: [ SHF_OS_NONCONFORMING ]
+ - Name: hios_nonconforming
+ Type: 0x6fffffff
+ Flags: [ SHF_OS_NONCONFORMING ]
+
+ - Name: loproc
+ Type: 0x70000000
+ - Name: hiproc
+ Type: 0x7fffffff
+
+ - Name: louser
+ Type: 0x80000000
+ - Name: hiuser
+ Type: 0xffffffff
+ - Name: louser_alloc
+ Type: 0x80000000
+ Flags: [ SHF_ALLOC ]
+ - Name: hiuser_alloc
+ Type: 0xffffffff
+ Flags: [ SHF_ALLOC ]
More information about the llvm-commits
mailing list