In https://reviews.llvm.org/D137982 we found that on Mach-O private
aliases could trigger an assert in lld when the aliasee was a
weak_def_can_be_hidden symbol.
This appears to be incorrect, and should be allowed in Mach-O.
Disallowing this behavior is also inconsistent with how ld64 handles
a private alias to weak_def_can_be_hidden symbols.
This patch removes the assert and tests that LLD handles such aliases
gracefully.
Reviewed By: #lld-macho, int3
Differential Revision: https://reviews.llvm.org/D141082
We can technically handle them, but since they shouldn't come up in any
real-world programs (since ld64 dedups strings unconditionally), there's
no reason to support them.
It's a thoroughly untested code path too -- as evidenced by the fact
that the only test this change breaks is one that verifies that we
reject relocations when dedup'ing. There is no test that covers the case
where we handle relocations in cstring sections when dedup is disabled.
Reviewed By: #lld-macho, oontvoo, keith, thakis
Differential Revision: https://reviews.llvm.org/D141025
Errors / warnings that originate from a particular file should be of the
form `$file: $message`.
Reviewed By: #lld-macho, keith
Differential Revision: https://reviews.llvm.org/D140634
This will enable us to re-land {D139069}.
The issue with the original diff was that we were folding all
private-label symbols. We were not merging the symbol flags during this
folding; instead we just made all references to the folded symbol point
to its aliasee. This caused some flags to be incorrectly discarded. This
surfaced as code that was incorrectly stripped due to LLD dropping the
`.no_dead_strip` flag.
This diff fixes things by only folding flag-less private-label aliases.
Most (maybe all) of the `ltmp<N>` symbols that are generated by the MC
aarch64 backend are flag-less, so this conservative folding behavior
does the job.
Reviewed By: #lld-macho, thakis
Differential Revision: https://reviews.llvm.org/D140606
Previously by default, when not using `--ifc=`, lld would not
deduplicate string literals. This reveals reliance on undefined behavior
where string literal addresses are compared instead of using string
equality checks. While ideally you would be able to easily identify and
eliminate the reliance on this UB, this can be difficult, especially for
third party code, and increases the friction and risk of users migrating
to lld. This flips the default to deduplicate strings unless
`--no-deduplicate-strings` is passed, matching ld64's behavior.
Differential Revision: https://reviews.llvm.org/D140517
This reverts commit 09c5aab7f8.
New changes:
Temporarily skip checking the output bundle's cpu/cpu-subtype
Suspected there's a bug in selecting targets which caused the produced bundle
to be arm64 bundle (even though it was specifically linked with -arch x86_64).
The current test that link succeeded should be sufficient, because
it would have failed with "unable to find matching tagets" prior to this patch.
Differential Revision: https://reviews.llvm.org/D139572
This reverts commit 52a118d08f.
New changes:
Fix tests to dump both slices in the fat-archive because otool
isn't deterministic about which slice it prints across different archs.
(It printed x86 on x86 machines but arm64 on arm64, this was why
the test failed on arm64)
Differential Revision: https://reviews.llvm.org/D139572
This reverts commit 66692c822a.
New changes:
- update test to require aarch64
- update test to not hard-code cpu[sub] type values (since they could change)
- update test to temporarily skip windows (because llvm-mc on windows doesn't seem to work with triple arm64-apple-macos)
Differential Revision: https://reviews.llvm.org/D139572
Fixes#59162. The test has a comment explaining what's going on.
See also Symbol::extract() in lld/ELF/Symbols.cpp.
The included test sadly also passes if I pass just bd448f01a6,
while doing that isn't enough to make my bigger repro case work
(if I port just that, something else asserts later on, but with
this fix here everything's fine in my bigger repro).
Differential Revision: https://reviews.llvm.org/D139199
This patch mechanically replaces None with std::nullopt where the
compiler would warn if None were deprecated. The intent is to reduce
the amount of manual work required in migrating from Optional to
std::optional.
This is part of an effort to migrate from llvm::Optional to
std::optional:
https://discourse.llvm.org/t/deprecating-llvm-optional-x-hasvalue-getvalue-getvalueor/63716
If we have two files with the same weak symbol like so:
```
ltmp0:
_weak:
<contents>
```
and
```
ltmp1:
_weak:
<contents>
```
Linking them together should leave only one copy of `<contents>`, not
two. Previously, we would keep around both copies because of the
private-label `ltmp<N>` symbols (i.e. symbols that start with `l`) -- we
would not coalesce those, so we would treat them as retaining the
contents.
This matters for more than just size -- we are depending upon this
behavior internally for emitting a certain file format. This file
format's header is repeated in each object file, but we want it to
appear just once in our output.
Why can't we not emit those aliases to `_weak`, or reference the
`ltmp<N>` symbols instead of `_weak`? Well, MC actually adds `ltmp<N>`
symbols as part of the assembly-to-binary translation step. So any
codegen at the clang level can't access them.
All that said... this solution is actually kind of hacky. Here, we avoid
creating the private-label symbols at parse time. This is acceptable
since we never emit those symbols in our output. However, in ld64, any
aliasing temporary symbols (ignored or otherwise) won't retain coalesced
data. But implementing this is harder -- we would have to create those
symbols first (so we can emit their names later), but we would have to
ensure the linker correctly shuffles them around when their aliasees get
coalesced.
Additionally, ld64 treats these temporary symbols as functionally
equivalent to the weak symbols themselves -- that is, it will emit weak
binds when those non-weak temporary aliases are referenced. We have
imitated this behavior for private-label symbols, but implementing it for
local aliases in general seems substantially more difficult. I'm not
sure if any programs actually depend on this behavior though, so maybe
it's a moot point.
Finally, ld64 does all this regardless of whether
`.subsections_via_symbols` is specified. We don't. But again, given how
rare the lack of that directive is (I've only seen it from hand-written
assembly inputs), I don't think we need to worry about it.
Reviewed By: #lld-macho, oontvoo
Differential Revision: https://reviews.llvm.org/D139069
While extending the map file to cover unwind info, I realized we had two
issues with our EH_Frame symbols:
1. Their size was not set
2. We would create two EH_Frame symbols per frame when we only needed
one. This was because the Defined constructor would add the symbol
itself to InputSection::symbols, but we were also manually appending
the symbol to that same vector.
Note that ld64 prints "CIE" and "FDE for: <function>" instead of just
"EH_Frame", but I'm punting on that for now unless we discover that
users really depend upon it.
Reviewed By: #lld-macho, Roger
Differential Revision: https://reviews.llvm.org/D137370
I love C++17!
chromium_framework_less_dwarf on my 16-core Mac Pro shows no stat sig change in wall time but a slight decrease in user time:
```
base diff difference (95% CI)
sys_time 1.759 ± 0.037 1.761 ± 0.033 [ -0.9% .. +1.1%]
user_time 4.920 ± 0.043 4.886 ± 0.051 [ -1.2% .. -0.2%]
wall_time 5.950 ± 0.117 5.900 ± 0.116 [ -1.8% .. +0.2%]
samples 26 37
```
Reviewed By: #lld-macho, thakis
Differential Revision: https://reviews.llvm.org/D136518
Symbols occur at non-zero offsets in a subsection if they are
`.alt_entry` symbols, or if `.subsections_via_symbols` is omitted.
It doesn't seem like ld64 supports folding those subsections either.
Moreover, supporting this it makes `foldIdentical` a lot more
complicated to implement. The existing implementation has some
questionable behavior around STABS omission -- if a section with an
non-zero offset symbol was folded into one without, we would omit the
STABS entry for the non-zero offset symbol.
I will be following up with a diff that makes `foldIdentical` zero out
the symbol sizes for folded symbols. Again, this is much easier to
implement if we don't have to worry about non-zero offsets.
Reviewed By: #lld-macho, oontvoo
Differential Revision: https://reviews.llvm.org/D136000
The previous form is currently "harmless" and happened to work but may not in the future:
Consider the struct: (for x86-64, but same issue can be said for the ARM/64 families):
```
UNWIND_X86_64_MODE_MASK = 0x0F000000,
UNWIND_X86_64_MODE_RBP_FRAME = 0x01000000,
UNWIND_X86_64_MODE_STACK_IMMD = 0x02000000,
UNWIND_X86_64_MODE_STACK_IND = 0x03000000,
UNWIND_X86_64_MODE_DWARF = 0x04000000,
```
Previously, we were doing: `(encoding & MODE_DWARF) == MODE_DWARF`
As soon as a new `UNWIND_X86_64_MODE_FOO = 0x05000000` is defined, then the check above would always return true for encoding=MODE_FOO (because `(0b0101 & 0b0100) == 0b0100` )
Differential Revision: https://reviews.llvm.org/D135359
While reading this code, I was wondering if we change these variables in the
loop. We don't, so make them const to make this easier to see next time.
No behavior change.
Differential Revision: https://reviews.llvm.org/D135877
This commit moves the parsing of linker optimization hints into
`ARM64::applyOptimizationHints`. This lets us avoid allocating memory
for holding the parsed information, and moves work out of
`ObjFile::parse`, which is not parallelized at the moment.
This change reduces the overhead of processing LOHs to 25-30 ms when
linking Chromium Framework on my M1 machine; previously it took close to
100 ms.
There's no statistically significant change in runtime for a --threads=1
link.
Performance figures with all 8 cores utilized:
N Min Max Median Avg Stddev
x 20 3.8027232 3.8760762 3.8505335 3.8454145 0.026352574
+ 20 3.7019017 3.8660538 3.7546209 3.7620371 0.032680043
Difference at 95.0% confidence
-0.0833775 +/- 0.019
-2.16823% +/- 0.494094%
(Student's t, pooled s = 0.0296854)
Differential Revision: https://reviews.llvm.org/D133439
This is similar to the `-alias` CLI option, but it gives finer-grained
control in that it allows the aliased symbols to be treated as private
externs.
While working on this, I realized that our `-alias` handling did not
cover the cases where the aliased symbol is a common or dylib symbol,
nor the case where we have an undefined that gets treated specially and
converted to a defined later on. My N_INDR handling neglects this too
for now; I've added checks and TODO messages for these.
`N_INDR` symbols cropped up as part of our attempt to link swift-stdlib.
Reviewed By: #lld-macho, thakis, thevinster
Differential Revision: https://reviews.llvm.org/D133825
This is similar to the `-alias` CLI option, but it gives finer-grained
control in that it allows the aliased symbols to be treated as private
externs.
While working on this, I realized that our `-alias` handling did not
cover the cases where the aliased symbol is a common or dylib symbol,
nor the case where we have an undefined that gets treated specially and
converted to a defined later on. My N_INDR handling neglects this too
for now; I've added checks and TODO messages for these.
`N_INDR` symbols cropped up as part of our attempt to link swift-stdlib.
Reviewed By: #lld-macho, thakis, thevinster
Differential Revision: https://reviews.llvm.org/D133825
This is what ld64 does (though it doesn't use ICF to do this; instead it
always dedups selrefs by default).
We'll want to dedup implicitly-defined selrefs as well, but I will leave
that for future work.
Additionally, I'm not *super* happy with the current LLD implementation
because I think it is rather janky and inefficient. But at least it
moves us toward the goal of closing the size gap with ld64. I've
described ideas for cleaning up our implementation here:
https://github.com/llvm/llvm-project/issues/57714
Differential Revision: https://reviews.llvm.org/D133780
This section is marked S_ATTR_LIVE_SUPPORT in input files, which meant
that on arm64, we were unnecessarily preserving FDEs if we e.g. had
multiple weak definitions for a function. Worse, we would actually
produce an invalid `__eh_frame` section in that case, because the CIE
associated with the unnecessary FDE would still get dead-stripped and
we'd end up with a dangling FDE. We set up associations from functions
to their FDEs, so dead-stripping will just work naturally, and we can
clear S_ATTR_LIVE_SUPPORT from our input `__eh_frame` sections to fix
dead-stripping.
Reviewed By: #lld-macho, int3
Differential Revision: https://reviews.llvm.org/D132489
Apple Clang in Xcode 14 introduced a new feature for reducing the
overhead of objc_msgSend calls by deduplicating the setup calls for each
individual selector. This works by clang adding undefined symbols for
each selector called in a translation unit, such as `_objc_msgSend$foo`
for calling the `foo` method on any `NSObject`. There are 2
different modes for this behavior, the default directly does the setup
for `_objc_msgSend` and calls it, and the smaller option does the
selector setup, and then calls the standard `_objc_msgSend` stub
function.
The general overview of how this works is:
- Undefined symbols with the given prefix are collected
- The suffix of each matching undefined symbol is added as a string to
`__objc_methname`
- A pointer is added for every method name in the `__objc_selrefs`
section
- A `got` entry is emitted for `_objc_msgSend`
- Stubs are emitting pointing to the synthesized locations
Notes:
- Both `__objc_methname` and `__objc_selrefs` can also exist from object
files, so their contents are merged with our synthesized contents
- The compiler emits method names for defined methods, but not for
undefined symbols you call, but stubs are used for both
- This only implements the default "fast" mode currently just to reduce
the diff, I also doubt many folks will care to swap modes
- This only implements this for arm64 and x86_64, we don't need to
implement this for 32 bit iOS archs, but we should implement it for
watchOS archs in a later diff
Differential Revision: https://reviews.llvm.org/D128108
Normally we'd use LLVM_FALLTHROUGH, or now, [[fallthrough]].
But for case labels followed directly by other case labels, we
use neither.
No behavior change.
Previously we only supporting using the system pointer size (aka the
`absptr` encoding) because `llvm-mc`'s CFI directives always generate EH
frames with that encoding. But libffi uses 4-byte-encoded, hand-rolled
EH frames, so this patch adds support for it.
Fixes#56576.
Reviewed By: #lld-macho, oontvoo
Differential Revision: https://reviews.llvm.org/D130804
A symbol `$ld$previous$/Another$1.2.3$1$3.0$14.0$_xxx$` means
"pretend symbol `_xxx` is in dylib `/Another` with version `1.2.3`
if the deployment target is between `3.0` and `14.0` and we're
targeting platform `1` (ie macOS)".
This means dylibs can now inject synthetic dylibs into the link, so
DylibFile needs to grow a 3rd constructor.
The only other interesting thing is that such an injected dylib
counts as a use of the original dylib. This patch gets this mostly
right (if _only_ `$ld$previous` symbols are used from a dylib,
we don't add a dep on the dylib itself, matching ld64), but one case
where we don't match ld64 yet is that ld64 even omits the original
dylib when linking it with `-needed-l`. Lld currently still adds a load
command for the original dylib in that case. (That's for a future
patch.)
Fixes#56074.
Differential Revision: https://reviews.llvm.org/D130725
Linking fails when targeting `x86_64-apple-darwin` for runtimes. The issue
is that LLD strictly assumes the target architecture be present in the tbd
files (which isn't always true). For example, when targeting `x86_64h`, it should
work with `x86_64` because they are ABI compatible. This is also inline with what
ld64 does.
An environment variable (which ld64 also supports) is also added to preserve the
existing behavior of strict architecture matching.
Reviewed By: #lld-macho, int3
Differential Revision: https://reviews.llvm.org/D130683
This flag was introduced in ld64-609. It instructs the linker to link to
a static library while treating its symbols as if they had hidden
visibility. This is useful when building a dylib that links to static
libraries but we don't want the symbols from those to be exported.
Closes#51505
This reland adds bitcode file handling, so we won't get any compile
errors due to BitcodeFile::forceHidden being unused.
Differential Revision: https://reviews.llvm.org/D130473
This flag was introduced in ld64-609. It instructs the linker to link to
a static library while treating its symbols as if they had hidden
visibility. This is useful when building a dylib that links to static
libraries but we don't want the symbols from those to be exported.
Closes#51505
Differential Revision: https://reviews.llvm.org/D130473
Previously, we treated it as a regular ConcatInputSection. However, ld64
actually parses its contents and uses that to synthesize a single image
info struct, generating one 8-byte section instead of `8 * number of
object files with ObjC code`.
I'm not entirely sure what impact this section has on the runtime, so I
just tried to follow ld64's semantics as closely as possible in this
diff. My main motivation though was to reduce binary size.
No significant perf change on chromium_framework on my 16-core Mac Pro:
base diff difference (95% CI)
sys_time 1.764 ± 0.062 1.748 ± 0.032 [ -2.4% .. +0.5%]
user_time 5.112 ± 0.104 5.106 ± 0.046 [ -0.9% .. +0.7%]
wall_time 6.111 ± 0.184 6.085 ± 0.076 [ -1.6% .. +0.8%]
samples 30 32
Reviewed By: #lld-macho, thakis
Differential Revision: https://reviews.llvm.org/D130125
which occurs when there are EH frames present in the object file's weak
def.
Reviewed By: abrachet
Differential Revision: https://reviews.llvm.org/D130409