[lld] e115c00 - [ELF] Reject certain unknown section types (#85173)
via llvm-commits
llvm-commits at lists.llvm.org
Fri Mar 15 09:50:27 PDT 2024
Author: Fangrui Song
Date: 2024-03-15T09:50:23-07:00
New Revision: e115c00565be88677e8b7fe021a3e242249c67b8
URL: https://github.com/llvm/llvm-project/commit/e115c00565be88677e8b7fe021a3e242249c67b8
DIFF: https://github.com/llvm/llvm-project/commit/e115c00565be88677e8b7fe021a3e242249c67b8.diff
LOG: [ELF] Reject certain unknown section types (#85173)
Unknown section sections may require special linking rules, 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. For convenience, we
additionally allow all [SHT_LOPROC,SHT_HIPROC] types so that we don't
have to hard code all known types for each processor.
Close https://github.com/llvm/llvm-project/issues/84812
Added:
lld/test/ELF/unknown-section.test
Modified:
lld/ELF/Config.h
lld/ELF/Driver.cpp
lld/ELF/InputFiles.cpp
lld/ELF/Options.td
lld/docs/ld.lld.1
lld/test/ELF/incompatible-section-types2.s
lld/test/ELF/linkerscript/custom-section-type.s
Removed:
################################################################################
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..e6bf39b6b0bfe5 100644
--- a/lld/ELF/InputFiles.cpp
+++ b/lld/ELF/InputFiles.cpp
@@ -741,6 +741,15 @@ 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;
+ // Allow all processor-specific types. This is
diff erent from GNU ld.
+ return SHT_LOPROC <= t && t <= SHT_HIPROC;
+}
+
template <class ELFT>
void ObjFile<ELFT>::initializeSections(bool ignoreComdats,
const llvm::object::ELFFile<ELFT> &obj) {
@@ -752,14 +761,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 +788,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 +811,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/docs/ld.lld.1 b/lld/docs/ld.lld.1
index e759776c8d55a6..65e50e349c8cc0 100644
--- a/lld/docs/ld.lld.1
+++ b/lld/docs/ld.lld.1
@@ -378,6 +378,8 @@ Do not put read-only non-executable sections in their own segment.
Do not report version scripts that refer to undefined symbols.
.It Fl -no-undefined
Report unresolved symbols even if the linker is creating a shared library.
+.It Fl -no-warn-mismatch
+Do not reject unknown section types.
.It Fl -no-warn-symbol-ordering
Do not warn about problems with the symbol ordering file or call graph profile.
.It Fl -no-warnings , Fl w
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..f6ecca29a22aed
--- /dev/null
+++ b/lld/test/ELF/unknown-section.test
@@ -0,0 +1,48 @@
+# 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:(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