-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[ELF] Support NOCROSSREFS and NOCROSSERFS_TO #98773
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 |
---|---|---|
|
@@ -87,6 +87,7 @@ class ScriptParser final : ScriptLexer { | |
void readTarget(); | ||
void readVersion(); | ||
void readVersionScriptCommand(); | ||
void readNoCrossRefs(bool to); | ||
|
||
SymbolAssignment *readSymbolAssignment(StringRef name); | ||
ByteCommand *readByteCommand(StringRef tok); | ||
|
@@ -280,6 +281,10 @@ void ScriptParser::readLinkerScript() { | |
readTarget(); | ||
} else if (tok == "VERSION") { | ||
readVersion(); | ||
} else if (tok == "NOCROSSREFS") { | ||
readNoCrossRefs(/*to=*/false); | ||
} else if (tok == "NOCROSSREFS_TO") { | ||
readNoCrossRefs(/*to=*/true); | ||
} else if (SymbolAssignment *cmd = readAssignment(tok)) { | ||
script->sectionCommands.push_back(cmd); | ||
} else { | ||
|
@@ -299,6 +304,17 @@ void ScriptParser::readDefsym(StringRef name) { | |
script->sectionCommands.push_back(cmd); | ||
} | ||
|
||
void ScriptParser::readNoCrossRefs(bool to) { | ||
expect("("); | ||
NoCrossRefCommand cmd{{}, to}; | ||
while (!errorCount() && !consume(")")) | ||
cmd.outputSections.push_back(unquote(next())); | ||
if (cmd.outputSections.size() < 2) | ||
warn(getCurrentLocation() + ": ignored with fewer than 2 output sections"); | ||
else | ||
script->noCrossRefs.push_back(std::move(cmd)); | ||
} | ||
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. Would it be worth a warning if the 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. Added a warning. |
||
|
||
void ScriptParser::addFile(StringRef s) { | ||
if (isUnderSysroot && s.starts_with("/")) { | ||
SmallString<128> pathData; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
# REQUIRES: x86 | ||
# RUN: rm -rf %t && split-file %s %t && cd %t | ||
|
||
# RUN: llvm-mc --triple=x86_64 -filetype=obj a.s -o a.o | ||
# RUN: llvm-mc --triple=x86_64 -filetype=obj data.s -o data.o | ||
# RUN: ld.lld a.o data.o -T 0.t 2>&1 | FileCheck %s --check-prefix=CHECK0 --implicit-check-not=warning: | ||
|
||
# CHECK0: warning: 0.t:3: ignored with fewer than 2 output sections | ||
# CHECK0-NEXT: warning: 0.t:4: ignored with fewer than 2 output sections | ||
|
||
# RUN: not ld.lld a.o data.o -T 1.t 2>&1 | FileCheck %s --check-prefix=CHECK1 --implicit-check-not=error: | ||
# CHECK1: error: a.o:(.text.start+0x11): prohibited cross reference from '.text' to 'data' in '.data' | ||
|
||
## .text and .text1 are in two NOCROSSREFS commands. Violations are reported twice. | ||
# RUN: not ld.lld --threads=1 a.o data.o -T 2.t 2>&1 | FileCheck %s --check-prefix=CHECK2 --implicit-check-not=error: | ||
# CHECK2: error: a.o:(.text.start+0x6): prohibited cross reference from '.text' to '.text1' in '.text1' | ||
# CHECK2-NEXT: error: a.o:(.text.start+0x6): prohibited cross reference from '.text' to '.text1' in '.text1' | ||
# CHECK2-NEXT: error: a.o:(.text.start+0xb): prohibited cross reference from '.text' to 'foo2' in '.text2' | ||
# CHECK2-NEXT: error: a.o:(.text.start+0x11): prohibited cross reference from '.text' to 'data' in '.data' | ||
# CHECK2-NEXT: error: a.o:(.text.start+0x17): prohibited cross reference from '.text' to 'str1' in '.rodata' | ||
## .data occurs twice in the command, but the violation is only reported once. | ||
# CHECK2-NEXT: error: a.o:(.text1+0x1): prohibited cross reference from '.text1' to '_edata' in '.data' | ||
# CHECK2-NEXT: error: a.o:(.nonalloc+0x0): prohibited cross reference from '.nonalloc' to '.text' in '.text' | ||
# CHECK2-NEXT: error: a.o:(.nonalloc+0x10): prohibited cross reference from '.nonalloc' to 'data' in '.data' | ||
|
||
# RUN: not ld.lld a.o data.o -T 3.t 2>&1 | FileCheck %s --check-prefix=CHECK3 --implicit-check-not=error: | ||
# CHECK3: error: a.o:(.nonalloc+0x0): prohibited cross reference from '.nonalloc' to '.text' in '.text' | ||
|
||
#--- 0.t | ||
## Some cases that do not cause errors. | ||
abs = 42; | ||
NOCROSSREFS() | ||
NOCROSSREFS (.text) | ||
NOCROSSREFS( .text .text3 ); ## ; is ignored | ||
NOCROSSREFS_TO(.text .text2 .text3 .data ); | ||
NOCROSSREFS_TO (.data .text2 .text3) | ||
|
||
#--- 1.t | ||
abs = 42; | ||
NOCROSSREFS(.text ".data") | ||
|
||
#--- 2.t | ||
abs = 42; | ||
NOCROSSREFS(.text ".text1" .text ".text1" ) | ||
NOCROSSREFS(.text .text1 .text2 .data .rodata .data .nonalloc) | ||
|
||
#--- 3.t | ||
abs = 42; | ||
NOCROSSREFS_TO(.text .text .text1 .text2 .data .nonalloc) | ||
|
||
#--- err1.t | ||
NOCROSSREFS ) | ||
|
||
# RUN: not ld.lld a.o data.o -T err1.t 2>&1 | FileCheck %s --check-prefix=ERR1 --implicit-check-not=error: | ||
# ERR1: error: err1.t:1: ( expected, but got ) | ||
|
||
#--- err2.t | ||
NOCROSSREFS(.text | ||
|
||
# RUN: not ld.lld a.o data.o -T err2.t 2>&1 | FileCheck %s --check-prefix=ERR2 --implicit-check-not=error: | ||
# ERR2: error: err2.t:1: unexpected EOF | ||
|
||
#--- a.s | ||
.global _start, foo1, foo2, foo3 | ||
.section .text.start,"ax" | ||
_start: | ||
call _start | ||
call .text1 | ||
call foo2 | ||
movl data(%rip), %eax | ||
movl str1(%rip), %eax | ||
|
||
.section .text1,"ax" | ||
foo1: | ||
call _edata | ||
|
||
.section .text2,"ax" | ||
foo2: | ||
call foo3 | ||
|
||
.section .text3,"ax" | ||
foo3: | ||
call foo2 | ||
|
||
.section .rodata.str1.1,"aMS",@progbits,1 | ||
str1: | ||
.asciz "abc" | ||
|
||
.section .nonalloc,"" | ||
.quad .text | ||
.quad .text3 | ||
.quad data | ||
|
||
#--- data.s | ||
.section .data,"aw" | ||
.globl data | ||
data: | ||
.byte 0 | ||
.quad abs |
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.
For a NoCrossRefCommand cmd with
toFirst == true
can we early exit if osec == cmd.outputSections[0]?This would be the case where we search the relocations from
tosection
.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.
Added an early return to
elf::checkNoCrossRefs
:(noxref.toFirst && noxref.outputSections[0] == osec->name)