Skip to content

Commit e115c00

Browse files
authored
[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 #84812
1 parent 58f7251 commit e115c00

File tree

8 files changed

+86
-9
lines changed

8 files changed

+86
-9
lines changed

lld/ELF/Config.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,7 @@ struct Config {
273273
bool printGcSections;
274274
bool printIcfSections;
275275
bool printMemoryUsage;
276+
bool rejectMismatch;
276277
bool relax;
277278
bool relaxGP;
278279
bool relocatable;

lld/ELF/Driver.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1348,6 +1348,7 @@ static void readConfigs(opt::InputArgList &args) {
13481348
config->printArchiveStats = args.getLastArgValue(OPT_print_archive_stats);
13491349
config->printSymbolOrder =
13501350
args.getLastArgValue(OPT_print_symbol_order);
1351+
config->rejectMismatch = !args.hasArg(OPT_no_warn_mismatch);
13511352
config->relax = args.hasFlag(OPT_relax, OPT_no_relax, true);
13521353
config->relaxGP = args.hasFlag(OPT_relax_gp, OPT_no_relax_gp, false);
13531354
config->rpath = getRpath(args);

lld/ELF/InputFiles.cpp

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -741,6 +741,15 @@ template <class ELFT> void ObjFile<ELFT>::initializeJustSymbols() {
741741
sections.resize(numELFShdrs);
742742
}
743743

744+
static bool isKnownSpecificSectionType(uint32_t t, uint32_t flags) {
745+
if (SHT_LOUSER <= t && t <= SHT_HIUSER && !(flags & SHF_ALLOC))
746+
return true;
747+
if (SHT_LOOS <= t && t <= SHT_HIOS && !(flags & SHF_OS_NONCONFORMING))
748+
return true;
749+
// Allow all processor-specific types. This is different from GNU ld.
750+
return SHT_LOPROC <= t && t <= SHT_HIPROC;
751+
}
752+
744753
template <class ELFT>
745754
void ObjFile<ELFT>::initializeSections(bool ignoreComdats,
746755
const llvm::object::ELFFile<ELFT> &obj) {
@@ -752,14 +761,15 @@ void ObjFile<ELFT>::initializeSections(bool ignoreComdats,
752761
if (this->sections[i] == &InputSection::discarded)
753762
continue;
754763
const Elf_Shdr &sec = objSections[i];
764+
const uint32_t type = sec.sh_type;
755765

756766
// SHF_EXCLUDE'ed sections are discarded by the linker. However,
757767
// if -r is given, we'll let the final link discard such sections.
758768
// This is compatible with GNU.
759769
if ((sec.sh_flags & SHF_EXCLUDE) && !config->relocatable) {
760-
if (sec.sh_type == SHT_LLVM_CALL_GRAPH_PROFILE)
770+
if (type == SHT_LLVM_CALL_GRAPH_PROFILE)
761771
cgProfileSectionIndex = i;
762-
if (sec.sh_type == SHT_LLVM_ADDRSIG) {
772+
if (type == SHT_LLVM_ADDRSIG) {
763773
// We ignore the address-significance table if we know that the object
764774
// file was created by objcopy or ld -r. This is because these tools
765775
// will reorder the symbols in the symbol table, invalidating the data
@@ -778,7 +788,7 @@ void ObjFile<ELFT>::initializeSections(bool ignoreComdats,
778788
continue;
779789
}
780790

781-
switch (sec.sh_type) {
791+
switch (type) {
782792
case SHT_GROUP: {
783793
if (!config->relocatable)
784794
sections[i] = &InputSection::discarded;
@@ -801,12 +811,25 @@ void ObjFile<ELFT>::initializeSections(bool ignoreComdats,
801811
case SHT_RELA:
802812
case SHT_NULL:
803813
break;
804-
case SHT_LLVM_SYMPART:
805-
ctx.hasSympart.store(true, std::memory_order_relaxed);
806-
[[fallthrough]];
814+
case SHT_PROGBITS:
815+
case SHT_NOTE:
816+
case SHT_NOBITS:
817+
case SHT_INIT_ARRAY:
818+
case SHT_FINI_ARRAY:
819+
case SHT_PREINIT_ARRAY:
820+
this->sections[i] =
821+
createInputSection(i, sec, check(obj.getSectionName(sec, shstrtab)));
822+
break;
807823
default:
808824
this->sections[i] =
809825
createInputSection(i, sec, check(obj.getSectionName(sec, shstrtab)));
826+
if (type == SHT_LLVM_SYMPART)
827+
ctx.hasSympart.store(true, std::memory_order_relaxed);
828+
else if (config->rejectMismatch &&
829+
!isKnownSpecificSectionType(type, sec.sh_flags))
830+
errorOrWarn(toString(this->sections[i]) + ": unknown section type 0x" +
831+
Twine::utohexstr(type));
832+
break;
810833
}
811834
}
812835

lld/ELF/Options.td

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -312,6 +312,9 @@ def no_dynamic_linker: F<"no-dynamic-linker">,
312312
def noinhibit_exec: F<"noinhibit-exec">,
313313
HelpText<"Retain the executable output file whenever it is still usable">;
314314

315+
def no_warn_mismatch: F<"no-warn-mismatch">,
316+
HelpText<"Suppress errors for certain unknown seciton types">;
317+
315318
def no_nmagic: F<"no-nmagic">, MetaVarName<"<magic>">,
316319
HelpText<"Page align sections (default)">;
317320

@@ -753,7 +756,6 @@ def: FF<"no-add-needed">;
753756
def: F<"no-copy-dt-needed-entries">;
754757
def: F<"no-ctors-in-init-array">;
755758
def: F<"no-keep-memory">;
756-
def: F<"no-warn-mismatch">;
757759
def: Separate<["--", "-"], "rpath-link">;
758760
def: J<"rpath-link=">;
759761
def: F<"secure-plt">;

lld/docs/ld.lld.1

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -378,6 +378,8 @@ Do not put read-only non-executable sections in their own segment.
378378
Do not report version scripts that refer to undefined symbols.
379379
.It Fl -no-undefined
380380
Report unresolved symbols even if the linker is creating a shared library.
381+
.It Fl -no-warn-mismatch
382+
Do not reject unknown section types.
381383
.It Fl -no-warn-symbol-ordering
382384
Do not warn about problems with the symbol ordering file or call graph profile.
383385
.It Fl -no-warnings , Fl w

lld/test/ELF/incompatible-section-types2.s

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,5 @@
66
// CHECK-NEXT: >>> <internal>:(.shstrtab): SHT_STRTAB
77
// CHECK-NEXT: >>> output section .shstrtab: Unknown
88

9-
.section .shstrtab,"",@12345
9+
.section .shstrtab,"",@0x60000000
1010
.short 20

lld/test/ELF/linkerscript/custom-section-type.s

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ SECTIONS {
7676
.section progbits,"a",@note
7777
.byte 0
7878

79-
.section expr,"a",@12345
79+
.section expr,"a",@0x60000000
8080
.byte 0
8181

8282
#--- unknown1.lds

lld/test/ELF/unknown-section.test

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
# RUN: rm -rf %t && mkdir %t && cd %t
2+
# RUN: yaml2obj %s -o a.o
3+
# RUN: not ld.lld a.o -o /dev/null 2>&1 | FileCheck %s --implicit-check-not=error:
4+
5+
# CHECK: error: a.o:(relr): unknown section type 0x13
6+
# CHECK-NEXT: error: a.o:(regular): unknown section type 0x15
7+
# CHECK-NEXT: error: a.o:(loos_nonconforming): unknown section type 0x60000000
8+
# CHECK-NEXT: error: a.o:(hios_nonconforming): unknown section type 0x6fffffff
9+
# CHECK-NEXT: error: a.o:(louser_alloc): unknown section type 0x80000000
10+
# CHECK-NEXT: error: a.o:(hiuser_alloc): unknown section type 0xffffffff
11+
12+
--- !ELF
13+
FileHeader:
14+
Class: ELFCLASS64
15+
Data: ELFDATA2LSB
16+
Type: ET_REL
17+
Machine: EM_X86_64
18+
Sections:
19+
- Name: relr
20+
Type: 19
21+
- Name: regular
22+
Type: 21
23+
- Name: loos
24+
Type: 0x60000000
25+
- Name: hios
26+
Type: 0x6fffffff
27+
- Name: loos_nonconforming
28+
Type: 0x60000000
29+
Flags: [ SHF_OS_NONCONFORMING ]
30+
- Name: hios_nonconforming
31+
Type: 0x6fffffff
32+
Flags: [ SHF_OS_NONCONFORMING ]
33+
34+
- Name: loproc
35+
Type: 0x70000000
36+
- Name: hiproc
37+
Type: 0x7fffffff
38+
39+
- Name: louser
40+
Type: 0x80000000
41+
- Name: hiuser
42+
Type: 0xffffffff
43+
- Name: louser_alloc
44+
Type: 0x80000000
45+
Flags: [ SHF_ALLOC ]
46+
- Name: hiuser_alloc
47+
Type: 0xffffffff
48+
Flags: [ SHF_ALLOC ]

0 commit comments

Comments
 (0)