The logic added in r372781 caused ARMExidxSyntheticSection::addSection()
to return false for exidx sections without a link order dep that passed
isValidExidxSectionDep(). This included exidx sections for empty functions. As
a result, such exidx sections would end up treated like ordinary sections and
would end up being laid out before the ARMExidxSyntheticSection, most likely in
the wrong order relative to the exidx entries in the ARMExidxSyntheticSection,
breaking the orderedness invariant relied upon by unwinders. Fix this by
simply discarding such sections.
Differential Revision: https://reviews.llvm.org/D69744
Summary:
Add a flag `F_no_mmap` to `FileOutputBuffer` to support
`--[no-]mmap-output-file` in ELF LLD. LLD currently explicitly ignores
this flag for compatibility with GNU ld and gold.
We need this flag to speed up link time for large binaries in certain
scenarios. When we link some of our larger binaries we find that LLD
takes 50+ GB of memory, which causes memory pressure. The memory
pressure causes the VM to flush dirty pages of the output file to disk.
This is normally okay, since we should be flushing cold pages. However,
when using BtrFS with compression we need to write 128KB at a time when
we flush a page. If any page in that 128KB block is written again, then
it must be flushed a second time, and so on. Since LLD doesn't write
sequentially this causes write amplification. The same 128KB block will
end up being flushed multiple times, causing the linker to many times
more IO than necessary. We've observed 3-5x faster builds with
-no-mmap-output-file when we hit this scenario.
The bad scenario only applies to compressed filesystems, which group
together multiple pages into a single compressed block. I've tested
BtrFS, but the problem will be present for any compressed filesystem
on Linux, since it is caused by the VM.
Silently ignoring --no-mmap-output-file caused a silent regression when
we switched from gold to lld. We pass --no-mmap-output-file to fix this
edge case, but since lld silently ignored the flag we didn't realize it
wasn't being respected.
Benchmark building a 9 GB binary that exposes this edge case. I linked 3
times with --mmap-output-file and 3 times with --no-mmap-output-file and
took the average. The machine has 24 cores @ 2.4 GHz, 112 GB of RAM,
BtrFS mounted with -compress-force=zstd, and an 80% full disk.
| Mode | Time |
|---------|-------|
| mmap | 894 s |
| no mmap | 126 s |
When compression is disabled, BtrFS performs just as well with and
without mmap on this benchmark.
I was unable to reproduce the regression with any binaries in
lld-speed-test.
Reviewed By: ruiu, MaskRay
Differential Revision: https://reviews.llvm.org/D69294
Add a new '-z nognustack' option that suppresses emitting PT_GNU_STACK
segment. This segment is not supported at all on NetBSD (stack is
always non-executable), and the option is meant to be used to disable
emitting it.
Differential Revision: https://reviews.llvm.org/D56554
sections, but the current code misses certain variants. In particular, those
named when clang takes the code path in
clang/lib/Driver/ToolChain.cpp:416, where crtfiles are named:
clang_rt.<component>-<arch>-<env>.<suffix>
Previously, the code only handled:
clang_rt.<component>.<suffix>
<component>.<suffix>
This revision fixes that.
Fix PR43767
In -r mode, when processing a SHT_REL[A] that relocates a SHF_MERGE, sec->getRelocatedSection() is a
MergeInputSection and its parent is an OutputSection but is asserted to
be a SyntheticSection (MergeSyntheticSection) in LinkerScript.cpp:addInputSec().
##
The code path is not exercised in non -r mode because the relocated
section changed from MergeInputSection to InputSection.
Reorder the code to make the non -r logic apply to -r as well, thus fix
the crash.
Reviewed By: peter.smith
Differential Revision: https://reviews.llvm.org/D69364
The only condition that isecLoc becomes null is
Out::bufferStart == nullptr,
isec->getParent()->offset == 0, and
isec->outSecOff == 0.
We can check the first condition only once.
llvm-svn: 374332
isecLoc there can be null, but at the same time isec->getSize() may
be non-null. It is UB to offset a nullptr.The most straight-forward fix
here appears to perform casts+normal integral arithmetics.
FAIL: lld :: ELF/invalid/invalid-relocation-aarch64.test (1158 of 2217)
******************** TEST 'lld :: ELF/invalid/invalid-relocation-aarch64.test' FAILED ********************
Script:
--
: 'RUN: at line 2'; /b/sanitizer-x86_64-linux-bootstrap-ubsan/build/llvm_build_ubsan/bin/yaml2obj /b/sanitizer-x86_64-linux-bootstrap-ubsan/build/llvm-project/lld/test/ELF/invalid/invalid-relocation-aarch64.test -o /b/sanitizer-x86_64-linux-bootstrap-ubsan/build/llvm_build_ubsan/tools/lld/test/ELF/invalid/Output/invalid-relocation-aarch64.test.tmp.o
: 'RUN: at line 3'; not /b/sanitizer-x86_64-linux-bootstrap-ubsan/build/llvm_build_ubsan/bin/ld.lld /b/sanitizer-x86_64-linux-bootstrap-ubsan/build/llvm_build_ubsan/tools/lld/test/ELF/invalid/Output/invalid-relocation-aarch64.test.tmp.o -o /dev/null 2>&1 | /b/sanitizer-x86_64-linux-bootstrap-ubsan/build/llvm_build_ubsan/bin/FileCheck /b/sanitizer-x86_64-linux-bootstrap-ubsan/build/llvm-project/lld/test/ELF/invalid/invalid-relocation-aarch64.test
--
Exit Code: 1
Command Output (stderr):
--
/b/sanitizer-x86_64-linux-bootstrap-ubsan/build/llvm-project/lld/test/ELF/invalid/invalid-relocation-aarch64.test:4:10: error: CHECK: expected string not found in input
# CHECK: error: unknown relocation (1024) against symbol foo
^
<stdin>:1:1: note: scanning from here
/b/sanitizer-x86_64-linux-bootstrap-ubsan/build/llvm-project/lld/ELF/Target.cpp💯41: runtime error: applying non-zero offset 24 to null pointer
^
<stdin>:1:118: note: possible intended match here
/b/sanitizer-x86_64-linux-bootstrap-ubsan/build/llvm-project/lld/ELF/Target.cpp💯41: runtime error: applying non-zero offset 24 to null pointer
^
--
********************
Testing: 0.. 10.. 20.. 30.. 40.. 50.
FAIL: lld :: ELF/invalid/invalid-relocation-x64.test (1270 of 2217)
******************** TEST 'lld :: ELF/invalid/invalid-relocation-x64.test' FAILED ********************
Script:
--
: 'RUN: at line 2'; /b/sanitizer-x86_64-linux-bootstrap-ubsan/build/llvm_build_ubsan/bin/yaml2obj /b/sanitizer-x86_64-linux-bootstrap-ubsan/build/llvm-project/lld/test/ELF/invalid/invalid-relocation-x64.test -o /b/sanitizer-x86_64-linux-bootstrap-ubsan/build/llvm_build_ubsan/tools/lld/test/ELF/invalid/Output/invalid-relocation-x64.test.tmp1.o
: 'RUN: at line 3'; echo ".global foo; foo:" > /b/sanitizer-x86_64-linux-bootstrap-ubsan/build/llvm_build_ubsan/tools/lld/test/ELF/invalid/Output/invalid-relocation-x64.test.tmp2.s
: 'RUN: at line 4'; /b/sanitizer-x86_64-linux-bootstrap-ubsan/build/llvm_build_ubsan/bin/llvm-mc /b/sanitizer-x86_64-linux-bootstrap-ubsan/build/llvm_build_ubsan/tools/lld/test/ELF/invalid/Output/invalid-relocation-x64.test.tmp2.s -o /b/sanitizer-x86_64-linux-bootstrap-ubsan/build/llvm_build_ubsan/tools/lld/test/ELF/invalid/Output/invalid-relocation-x64.test.tmp2.o -filetype=obj -triple x86_64-pc-linux
: 'RUN: at line 5'; not /b/sanitizer-x86_64-linux-bootstrap-ubsan/build/llvm_build_ubsan/bin/ld.lld /b/sanitizer-x86_64-linux-bootstrap-ubsan/build/llvm_build_ubsan/tools/lld/test/ELF/invalid/Output/invalid-relocation-x64.test.tmp1.o /b/sanitizer-x86_64-linux-bootstrap-ubsan/build/llvm_build_ubsan/tools/lld/test/ELF/invalid/Output/invalid-relocation-x64.test.tmp2.o -o /dev/null 2>&1 | /b/sanitizer-x86_64-linux-bootstrap-ubsan/build/llvm_build_ubsan/bin/FileCheck /b/sanitizer-x86_64-linux-bootstrap-ubsan/build/llvm-project/lld/test/ELF/invalid/invalid-relocation-x64.test
--
Exit Code: 1
Command Output (stderr):
--
/b/sanitizer-x86_64-linux-bootstrap-ubsan/build/llvm-project/lld/test/ELF/invalid/invalid-relocation-x64.test:6:10: error: CHECK: expected string not found in input
# CHECK: error: unknown relocation (152) against symbol foo
^
<stdin>:1:1: note: scanning from here
/b/sanitizer-x86_64-linux-bootstrap-ubsan/build/llvm-project/lld/ELF/Target.cpp💯41: runtime error: applying non-zero offset 24 to null pointer
^
<stdin>:1:118: note: possible intended match here
/b/sanitizer-x86_64-linux-bootstrap-ubsan/build/llvm-project/lld/ELF/Target.cpp💯41: runtime error: applying non-zero offset 24 to null pointer
^
--
********************
Testing: 0.. 10.. 20.. 30.. 40.. 50.. 60.. 70.. 80.. 90..
Testing Time: 20.73s
********************
Failing Tests (2):
lld :: ELF/invalid/invalid-relocation-aarch64.test
lld :: ELF/invalid/invalid-relocation-x64.test
llvm-svn: 374329
The combination of the two flags doesn't make sense. And other linkers
seem to just ignore --export-dynamic if --relocatable is given, but
we probably should report it as an error to let users know that is
an invalid combination.
Fixes https://bugs.llvm.org/show_bug.cgi?id=43552
Differential Revision: https://reviews.llvm.org/D68441
llvm-svn: 374022
This makes it clear `ELF/**/*.cpp` files define things in the `lld::elf`
namespace and simplifies `elf::foo` to `foo`.
Reviewed By: atanasyan, grimar, ruiu
Differential Revision: https://reviews.llvm.org/D68323
llvm-svn: 373885
This allows us to delete `using namespace llvm::support::endian` and
simplify D68323. This change adds runtime config->endianness check but
the overhead should be negligible.
Reviewed By: ruiu
Differential Revision: https://reviews.llvm.org/D68561
llvm-svn: 373884
Before, SecToClusters[*] was used to track the belonged cluster.
During a merge (From -> Into), every element of From has to be updated.
Use a union-find set to speed up this use case.
Also, replace `std::vector<int> Sections;` with a doubly-linked
pointers: int Next, Prev;
Reviewed By: Bigcheese
Differential Revision: https://reviews.llvm.org/D46228
llvm-svn: 373708
Our .interp section is not a SyntheticSection. As a result, it terminates the
loop in removeUnusedSyntheticSections(). This has at least two consequences:
- The synthetic .bss and .bss.rel.ro sections are always present in
dynamically linked executables, even when they are not needed.
- The synthetic .ARM.exidx (and possibly other) sections are always present
in partitions other than the last one, even when not needed.
.ARM.exidx in particular is problematic because it assumes that its
list of code sections is non-empty in getLinkOrderDep(), which can
lead to a crash if the partition does not have any code sections.
Fix these problems by moving the creation of the .interp sections to the
top of createSyntheticSections(). While here, make the code a little less
error-prone by changing the add() lambdas to take a SyntheticSection instead
of an InputSectionBase.
Differential Revision: https://reviews.llvm.org/D68256
llvm-svn: 373347
Merging SHF_LINK_ORDER sections can affect semantics if the sh_link
fields point to different sections.
Specifically, for SHF_LINK_ORDER sections, the sh_link field acts as a reverse
dependency from the linked section, causing the SHF_LINK_ORDER section to
be included if the linked section is included. Merging sections with different
sh_link fields will cause the entire contents of the SHF_LINK_ORDER section
to be associated with a single (arbitrarily chosen) output section, whereas the
correct semantics are for the individual pieces of the SHF_LINK_ORDER section
to be associated with their linked output sections. As a result we can end up
incorrectly dropping SHF_LINK_ORDER section contents or including the wrong
section contents, depending on which linked sections were chosen.
Differential Revision: https://reviews.llvm.org/D68094
llvm-svn: 373255
Instead of returning an optional, just return the input string if
demangling fails, as that's what all callers use anyway.
Differential Revision: https://reviews.llvm.org/D68015
llvm-svn: 373077
Fixes PR43461 (regression caused by D67504)
The partition field of a SECTIONS-specified section is not set after
D67504. The 0 value affects findSection() which checks if the partition
field is 1.
So `Out::initArray = findSection(".init_array")` is null, and
DT_INIT_ARRAYSZ is not set.
Reviewed By: peter.smith
Differential Revision: https://reviews.llvm.org/D68087
llvm-svn: 372996
The R_MIPS_JALR relocation denotes jalr/jr instructions in position
independent code. Both these instructions take a target's address from
the $25 register. If offset to the target symbol fits into the 18-bits,
it's more efficient to replace jalr/jr by bal/b instructions.
Differential Revision: https://reviews.llvm.org/D68057
llvm-svn: 372951
D64906 allows PT_LOAD to have overlapping p_offset ranges. In the
default R RX RW RW layout + -z noseparate-code case, we do not tail pad
segments when transiting to another segment. This can save at most
3*maxPageSize bytes.
a) Before D64906, we tail pad R, RX and the first RW.
b) With -z separate-code, we tail pad R and RX, but not the first RW (RELRO).
In some cases, b) saves one file page. In some cases, b) wastes one
virtual memory page. The waste is a concern on Fuchsia. Because it uses
compressed binaries, it doesn't benefit from the saved file page.
This patch adds -z separate-loadable-segments to restore the behavior before
D64906. It can affect section addresses and can thus be used as a
debugging mechanism (see PR43214 and ld.so partition bug in
crbug.com/998712).
Reviewed By: jakehehrlich, ruiu
Differential Revision: https://reviews.llvm.org/D67481
llvm-svn: 372807
Summary:
When support for ThinLTO was first added to lld, the options that
control it were prefixed with --plugin-opt= for compatibility with
an existing implementation as a linker plugin. This change enables
shorter versions of the options to be used, as follows:
New Existing
-thinlto-emit-imports-files --plugin-opt=thinlto-emit-imports-files
-thinlto-index-only --plugin-opt=thinlto-index-only
-thinlto-index-only= --plugin-opt=thinlto-index-only=
-thinlto-object-suffix-replace= --plugin-opt=thinlto-object-suffix-replace=
-thinlto-prefix-replace= --plugin-opt=thinlto-prefix-replace=
-lto-obj-path= --plugin-opt=obj-path=
The options with the --plugin-opt= prefix have been retained as aliases
for the shorter variants so that they continue to be accepted.
Reviewers: tejohnson, ruiu, espindola
Reviewed By: ruiu
Subscribers: emaste, arichardson, MaskRay, steven_wu, dexonsmith, arphaman, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D67782
llvm-svn: 372798
When /DISCARD/ is used on an input section, that input section may have
a .ARM.exidx metadata section that depends on it. As the discard handling
comes after the .ARM.exidx synthetic section is created we need to make
sure that we account for the case where the .ARM.exidx output section
should be removed because there are no more live input sections.
Differential Revision: https://reviews.llvm.org/D67848
llvm-svn: 372781
D67504 removed uses of `assigned` from OutputSection::addSection, which
makes `assigned` purely used in processSectionCommands() and its
callees. By replacing its references with `parent`, we can remove
`assigned`.
Reviewed By: grimar
Differential Revision: https://reviews.llvm.org/D67531
llvm-svn: 372735
Fixes PR38748
mergeSections() calls getOutputSectionName() to get output section
names. Two MergeInputSections may be merged even if they are made
different by SECTIONS commands.
This patch moves mergeSections() after processSectionCommands() and
addOrphanSections() to fix the issue. The new pass is renamed to
OutputSection::finalizeInputSections().
processSectionCommands() and addorphanSections() are changed to add
sections to InputSectionDescription::sectionBases.
finalizeInputSections() merges MergeInputSections and migrates
`sectionBases` to `sections`.
For the -r case, we drop an optimization that tries keeping sh_entsize
non-zero. This is for the simplicity of addOrphanSections(). The
updated merge-entsize2.s reflects the change.
Reviewed By: grimar
Differential Revision: https://reviews.llvm.org/D67504
llvm-svn: 372734
In case of linking binary blobs which do not have any ELF headers, we can
deduce MIPS ABI ELF header flags from an `emulation` option.
Patch by Kyle Evans.
llvm-svn: 372513
Summary:
If st_link(A)=B, and A has the SHF_LINK_ORDER flag, we may dereference
a null pointer if B is garbage collected (PR43147):
1. In Wrter.cpp:compareByFilePosition, `aOut->sectionIndex` or `bOut->sectionIndex`
2. In OutputSections::finalize, `d->getParent()->sectionIndex`
Simply error and bail out to avoid null pointer dereferences. ld.bfd has
a similar error:
sh_link of section `.bar' points to discarded section `.foo0' of `a.o'
ld.bfd is more permissive in that it just checks whether the linked-to
section of the first input section is discarded. This is likely because
it sets sh_link of the output section according to the first input
section.
Reviewed By: grimar
Differential Revision: https://reviews.llvm.org/D67761
llvm-svn: 372400
D67284 introduced ARMErrataFix.cpp which was derived from
AArch64ErrataFix.cpp. There were some useful refactoring changes made to
ARMErrataFix.cpp made as part of the review. This change applies the
relevant changes back to AArch64ErrataFix.cpp.
Main changes are:
- Old style variable names in comments like IS, are now new style isec.
- Simplify init() collection of mappingSymbols to always start with a code
mapping symbol.
- Simplify logic in mergeCmp().
- Fix one 80 column overflow caused by IS -> isec transformation.
Differential Revision: https://reviews.llvm.org/D67622
llvm-svn: 372094
Provide a missing initializer to get rid of warning provoking buildbot
failures.
error: missing field 'rel' initializer
[-Werror,-Wmissing-field-initializers]
llvm-svn: 371970
The --fix-cortex-a8 option implements a linker workaround for the
coretex-a8 erratum 657417. A summary of the erratum conditions is:
- A 32-bit Thumb-2 branch instruction B.w, Bcc.w, BL, BLX spans two
4KiB regions.
- The destination of the branch is to the first 4KiB region.
- The instruction before the branch is a 32-bit Thumb-2 non-branch
instruction.
The linker fix is to redirect the branch to a patch not in the first
4KiB region. The patch forwards the branch on to its target.
The cortex-a8, is an old CPU, with the first implementation of this
workaround in ld.bfd appearing in 2009. The cortex-a8 has been used in
early Android Phones and there are some critical applications that still
need to run on a cortex-a8 that have the erratum. The patch is applied
roughly 10 times on LLD and 20 on Clang when they are built with
--fix-cortex-a8 on an Arm system.
The formal erratum description is avaliable in the ARM Core Cortex-A8
(AT400/AT401) Errata Notice document. This is available from Arm on
request but it seems to be findable via a web search.
Differential Revision: https://reviews.llvm.org/D67284
llvm-svn: 371965
If there is no readonly section, we map:
* The ELF header at imageBase+maxPageSize
* Program headers at imageBase+maxPageSize+sizeof(Ehdr)
* The first section .text at imageBase+maxPageSize+sizeof(Ehdr)+sizeof(program headers)
Due to the interaction between Writer<ELFT>::fixSectionAlignments and
LinkerScript::allocateHeaders,
`alignDown(p_vaddr(R PT_LOAD)) = alignDown(p_vaddr(RX PT_LOAD))`.
The RX PT_LOAD will override the R PT_LOAD at runtime, which is not ideal:
```
// PHDR at 0x401034, should be 0x400034
PHDR 0x000034 0x00401034 0x00401034 0x000a0 0x000a0 R 0x4
// R PT_LOAD contains just Ehdr and program headers.
// At 0x401000, should be 0x400000
LOAD 0x000000 0x00401000 0x00401000 0x000d4 0x000d4 R 0x1000
LOAD 0x0000d4 0x004010d4 0x004010d4 0x00001 0x00001 R E 0x1000
```
* createPhdrs allocates the headers to the R PT_LOAD.
* fixSectionAlignments assigns `imageBase+maxPageSize+sizeof(Ehdr)+sizeof(program headers)` (formula: `alignTo(dot, maxPageSize) + dot % config->maxPageSize`) to addrExpr of .text
* allocateHeaders computes the minimum address among SHF_ALLOC sections, i.e. addr(.text)
* allocateHeaders sets address of ELF header to `addr(.text)-sizeof(Ehdr)-sizeof(program headers) = imageBase+maxPageSize`
The main observation is that when the SECTIONS command is not used, we
don't have to call allocateHeaders. This requires an assumption that
the presence of PT_PHDR and addresses of headers can be decided
regardless of address information.
This may seem natural because dot is not manipulated by a linker script.
The other thing is that we have to drop the special rule for -T<section>
in `getInitialDot`. If -Ttext is smaller than the image base, the headers
will not be allocated with the old behavior (allocateHeaders is called)
but always allocated with the new behavior.
The behavior change is not a problem. Whether and where headers are
allocated can vary among linkers, or ld.bfd across different versions
(--enable-separate-code or not). It is thus advised to use a linker
script with the PHDRS command to have a consistent behavior across
linkers. If PT_PHDR is needed, an explicit --image-base can be a simpler
alternative.
Differential Revision: https://reviews.llvm.org/D67325
llvm-svn: 371957
ICF is performed after EhInputSections and MergeInputSections were
eliminated from inputSections. Every element of inputSections is an
InputSection.
llvm-svn: 371744
-z undefs is the inverse of -z defs. It allows unresolved references
from object files. This can be used to cancel --no-undefined or -z defs.
Reviewed By: ruiu
Differential Revision: https://reviews.llvm.org/D67479
llvm-svn: 371715
```
part.phdrs = script->hasPhdrsCommands() ? script->createPhdrs() : createPhdrs(part);
```
createPhdrs() allocates a PT_PHDR and a PF_R PT_LOAD, which will be
deleted later in LinkerScript::allocateHeaders, but leave a gap between
the program headers and the first section. Don't allocate the segments
to avoid the gap. PT_INTERP is likely not needed as well.
Reviewed By: ruiu
Differential Revision: https://reviews.llvm.org/D67324
llvm-svn: 371398