-
Notifications
You must be signed in to change notification settings - Fork 13.6k
[lld][ELF] Demote symbols in discarded sections to Undefined. #68777
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3061,6 +3061,37 @@ void LinkerDriver::link(opt::InputArgList &args) { | |
script->addOrphanSections(); | ||
} | ||
|
||
// Demote symbols defined relative to input sections that are discarded by | ||
// /DISCARD/ so that relocations referencing them will get reported. | ||
if (script->seenDiscard) { | ||
llvm::TimeTraceScope timeScope("Demote symbols in discarded sections"); | ||
parallelForEach(symtab.getSymbols(), [](Symbol *sym) { | ||
Defined *d = dyn_cast<Defined>(sym); | ||
if (!d) | ||
return; | ||
if (d->section && !d->section->isLive()) { | ||
uint32_t secIdx = 0; | ||
if (d->file) { | ||
uint32_t idx = 0; | ||
for (SectionBase *s : d->file->getSections()) { | ||
if (s == d->section) { | ||
secIdx = idx; | ||
break; | ||
} | ||
idx++; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I changed the section index code in both places. It was not giving the right index. I'm not sure why I didn't notice it earlier. I'm pretty sure it worked before. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There is a performance issue. If an object file has many discarded symbols, the quadratic time complexity will not be acceptable. I have fixed this in https://github.com/maskray/llvm-project/tree/lld-symbols-in-discard |
||
} | ||
} | ||
// If we don't change the binding from WEAK to GLOBAL here, the | ||
// undefined symbol reporting will think this is undefined weak and | ||
// not give a warning. | ||
Undefined(d->file, sym->getName(), | ||
sym->isWeak() ? (uint8_t)STB_GLOBAL : sym->binding, | ||
sym->stOther, sym->type, secIdx) | ||
.overwrite(*sym); | ||
} | ||
}); | ||
} | ||
|
||
{ | ||
llvm::TimeTraceScope timeScope("Merge/finalize input sections"); | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -722,6 +722,27 @@ template <class ELFT> void Writer<ELFT>::copyLocalSymbols() { | |
// No reason to keep local undefined symbol in symtab. | ||
if (!dr) | ||
continue; | ||
|
||
// Demote locals which did not end up in any partition. This is similar | ||
// to what we do in Driver.cpp, but that only works on globals. | ||
if (script->seenDiscard && dr->section && !dr->section->isLive()) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We do not need this copy. This can be unified with Driver.cpp. See https://github.com/maskray/llvm-project/tree/lld-symbols-in-discard |
||
uint32_t secIdx = 0; | ||
if (dr->file) { | ||
uint32_t idx = 0; | ||
for (SectionBase *s : dr->file->getSections()) { | ||
if (s == dr->section) { | ||
secIdx = idx; | ||
break; | ||
} | ||
idx++; | ||
} | ||
} | ||
Undefined(dr->file, b->getName(), b->binding, b->stOther, b->type, | ||
secIdx) | ||
.overwrite(*b); | ||
continue; | ||
} | ||
|
||
if (includeInSymtab(*b) && shouldKeepInSymtab(*dr)) | ||
in.symTab->addSymbol(b); | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,9 +4,32 @@ | |
# RUN: rm -rf %t && split-file %s %t && cd %t | ||
# RUN: llvm-mc -filetype=obj -triple=x86_64 a.s -o a.o | ||
# RUN: llvm-mc -filetype=obj -triple=x86_64 b.s -o b.o | ||
# RUN: ld.lld -T a.lds a.o b.o -z undefs -o /dev/null 2>&1 | count 0 | ||
# RUN: ld.lld -T a.lds a.o b.o -o /dev/null 2>&1 | count 0 | ||
# RUN: ld.lld -r -T a.lds a.o b.o -o /dev/null 2>&1 | count 0 | ||
# RUN: not ld.lld --threads=1 -T a.lds a.o b.o -z undefs -o /dev/null 2>&1 | FileCheck %s --check-prefix=SECTION --implicit-check-not=error: | ||
# RUN: not ld.lld --threads=1 -T a.lds a.o b.o -o /dev/null 2>&1 | FileCheck %s --check-prefixes=SECTION,SYMBOL --implicit-check-not=error: | ||
# RUN: ld.lld -r -T a.lds a.o b.o -o /dev/null 2>&1 | FileCheck %s --check-prefix=WARNING --implicit-check-not=error: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
exit code 0 means that there cannot be any error. |
||
|
||
# SECTION: error: relocation refers to a discarded section: .aaa | ||
# SECTION-NEXT: >>> defined in a.o | ||
# SECTION-NEXT: >>> referenced by a.o:(.bbb+0x0) | ||
|
||
# SYMBOL: error: relocation refers to a symbol in a discarded section: global | ||
# SYMBOL-NEXT: >>> defined in a.o | ||
# SYMBOL-NEXT: >>> referenced by b.o:(.data+0x0) | ||
|
||
# SYMBOL: error: relocation refers to a symbol in a discarded section: weak | ||
# SYMBOL-NEXT: >>> defined in a.o | ||
# SYMBOL-NEXT: >>> referenced by b.o:(.data+0x8) | ||
|
||
# SYMBOL: error: relocation refers to a symbol in a discarded section: weakref1 | ||
# SYMBOL-NEXT: >>> defined in a.o | ||
# SYMBOL-NEXT: >>> referenced by b.o:(.data+0x10) | ||
|
||
# SYMBOL: error: relocation refers to a symbol in a discarded section: weakref2 | ||
# SYMBOL-NEXT: >>> defined in a.o | ||
# SYMBOL-NEXT: >>> referenced by b.o:(.data+0x18) | ||
|
||
# WARNING: warning: relocation refers to a discarded section: .aaa | ||
# WARNING-NEXT: >>> referenced by a.o:(.rela.bbb+0x0) | ||
|
||
#--- a.s | ||
.globl _start | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's a corner case but I think is worth testing. The demotion logic applies
--gc-sections
as well but we only run the code when/DISCARD/
is seen, so there will be some behavior differences.I have updated
lld/test/ELF/gc-sections-tls.s
in https://github.com/MaskRay/llvm-project/tree/lld-symbols-in-discard to test this.Actually, we probably should do #69295 so that all non-local symbols in discarded sections are demoted, regardless of whether
/DISCARD/
is seen? @smithp35