Currently, when moving symbols from one `InputSection` to another (like
in ICF) we directly update the symbol's `isec`, `unwindEntry` and
`size`. By doing this we lose the original information. This information
will be needed in a future change. Since when moving symbols we always
set the symbol's `wasCoalesced` and `isec-> replacement`, we can just
use this info to conditionally get the information we need at access
time.
The MachO format supports relative offsets for ObjC method lists. This
support is present already in ld64. With this change we implement this
support in lld also.
Relative method lists can be identified by a specific flag (0x80000000)
in the method list header. When this flag is present, the method list
will contain 32-bit relative offsets to the current Program Counter
(PC), instead of absolute pointers.
Additionally, when relative method lists are used, the offset to the
selector name will now be relative and point to the selector reference
(selref) instead of the name itself.
This is also what ld64 does. This will make it easier to compare their
respective map files.
Reviewed By: #lld-macho, thevinster
Differential Revision: https://reviews.llvm.org/D145654
If a symbol is pulled in from an archive, we should include the archive
name in the map file output. This is what ld64 does.
Note that we aren't using `toString(InputFile*)` here because it
includes the install name for dylibs in its output, and ld64's map file
does not contain those.
Reviewed By: #lld-macho, smeenai
Differential Revision: https://reviews.llvm.org/D145623
We now handle the GOT, TLV, and stubs/lazy pointer sections.
Reviewed By: #lld-macho, thevinster, thakis
Differential Revision: https://reviews.llvm.org/D139762
This reverts commit ac3096e1dd77a2687797d38976d5f8c93f7353e5.
The buildbot failure from the earlier patch set has been fixed by 7c7e39db7a.
Differential Revision: https://reviews.llvm.org/D137369
The test added in https://reviews.llvm.org/D137368 has been failing
on our 32 bit arm bots:
https://lab.llvm.org/buildbot/#/builders/178/builds/3460
You get this for the strings:
<<dead>> 0x883255000000003 [ 10] literal string: Hello, it's me
Instead of the expected:
<<dead>> 0x0000000F [ 3] literal string: Hello, it's me
This is because unlike symbols whose size is a uint64_t, strings
use a StringRef whose size is size_t. size_t changes size between
32 and 64 bit platforms.
This fixes the test by using %z to print the size of the strings,
this works for 32 and 64 bit.
The previous map file code left out was modeled after LLD-ELF's
implementation. However, ld64's map file differs quite a bit from
LLD-ELF's. I've revamped our map file implementation so it is better
able to emit ld64-style map files.
Notable differences:
* ld64 doesn't demangle symbols in map files, regardless of whether
`-demangle` is passed. So we don't have to bother with
`getSymbolStrings()`.
* ld64 doesn't emit symbols in cstring sections; it emits just the
literal values. Moreover, it emits these literal values regardless of
whether they are labeled with a symbol.
* ld64 emits map file entries for things that are not strictly symbols,
such as unwind info, GOT entries, etc. That isn't handled in this
diff, but this redesign makes them easy to implement.
Additionally, the previous implementation sorted the symbols so as to
emit them in address order. This was slow and unnecessary -- the symbols
can already be traversed in address order by walking the list of
OutputSections. This brings significant speedups. Here's the numbers
from the chromium_framework_less_dwarf benchmark on my Mac Pro, with the
`-map` argument added to the response file:
base diff difference (95% CI)
sys_time 2.922 ± 0.059 2.950 ± 0.085 [ -0.7% .. +2.5%]
user_time 11.464 ± 0.191 8.290 ± 0.123 [ -28.7% .. -26.7%]
wall_time 11.235 ± 0.175 9.184 ± 0.169 [ -19.3% .. -17.2%]
samples 16 23
(It's worth noting that map files are written in parallel with the
output binary, but they often took longer to write than the binary
itself.)
Finally, I did further cleanups to the map-file.s test -- there was no
real need to have a custom-named section. There were also alt_entry
symbol declarations that had no corresponding definition. Either way,
neither custom-named sections nor alt_entry symbols trigger special code
paths in our map file implementation.
Reviewed By: #lld-macho, Roger
Differential Revision: https://reviews.llvm.org/D137368
ld64 emits them in address order but not in alphabetical order. This
sorting is particularly expensive for dead-stripped symbols (which don't
need to be sorted at all, unlike live symbols that need to be sorted by
address).
Timings for chromium_framework_less_dwarf (with the `-map` flag added to
the response file) on my 16-core Mac Pro:
base diff difference (95% CI)
sys_time 1.997 ± 0.038 2.004 ± 0.028 [ -0.6% .. +1.3%]
user_time 8.698 ± 0.085 8.167 ± 0.070 [ -6.6% .. -5.6%]
wall_time 7.965 ± 0.114 7.715 ± 0.347 [ -5.1% .. -1.2%]
samples 25 23
Reviewed By: #lld-macho, thakis
Differential Revision: https://reviews.llvm.org/D136536
... instead of mapping them to the intermediate object file.
This matches ld64.
Reviewed By: #lld-macho, Roger
Differential Revision: https://reviews.llvm.org/D136380
This matches ld64's behavior.
Additionally, I edited the "Dead Stripped Symbols" header to omit "Address" --
this also matches ld64.
Reviewed By: #lld-macho, oontvoo
Differential Revision: https://reviews.llvm.org/D135883
So @keith observed
[here](https://reviews.llvm.org/D128108#inline-1263900) that the
StringRefs we were returning from `CStringInputSection::getStringRef()`
included the null terminator in their total length, but regular
StringRefs do not. Let's fix that so these StringRefs are less confusing
to use.
Reviewed By: #lld-macho, keith, Roger
Differential Revision: https://reviews.llvm.org/D133728
Patch created by running:
rg -l parallelForEachN | xargs sed -i '' -c 's/parallelForEachN/parallelFor/'
No behavior change.
Differential Revision: https://reviews.llvm.org/D128140
I removed them in rG5de7467e982 but @thakis pointed out that
they were useful to keep, so here they are again. I've also converted
the `!isCoalescedWeak()` asserts into `!shouldOmitFromOutput()` asserts,
since the latter check subsumes the former.
Reviewed By: #lld-macho, thakis
Differential Revision: https://reviews.llvm.org/D104169
D103977 broke a bunch of stuff as I had only tested the release build
which eliminated asserts.
I've retained the asserts where possible, but I also removed a bunch
instead of adding a whole lot of verbose ConcatInputSection casts.
Also adds support for live_support sections, no_dead_strip sections,
.no_dead_strip symbols.
Chromium Framework 345MB unstripped -> 250MB stripped
(vs 290MB unstripped -> 236M stripped with ld64).
Doing dead stripping is a bit faster than not, because so much less
data needs to be processed:
% ministat lld_*
x lld_nostrip.txt
+ lld_strip.txt
N Min Max Median Avg Stddev
x 10 3.929414 4.07692 4.0269079 4.0089678 0.044214794
+ 10 3.8129408 3.9025559 3.8670411 3.8642573 0.024779651
Difference at 95.0% confidence
-0.144711 +/- 0.0336749
-3.60967% +/- 0.839989%
(Student's t, pooled s = 0.0358398)
This interacts with many parts of the linker. I tried to add test coverage
for all added `isLive()` checks, so that some test will fail if any of them
is removed. I checked that the test expectations for the most part match
ld64's behavior (except for live-support-iterations.s, see the comment
in the test). Interacts with:
- debug info
- export tries
- import opcodes
- flags like -exported_symbol(s_list)
- -U / dynamic_lookup
- mod_init_funcs, mod_term_funcs
- weak symbol handling
- unwind info
- stubs
- map files
- -sectcreate
- undefined, dylib, common, defined (both absolute and normal) symbols
It's possible it interacts with more features I didn't think of,
of course.
I also did some manual testing:
- check-llvm check-clang check-lld work with lld with this patch
as host linker and -dead_strip enabled
- Chromium still starts
- Chromium's base_unittests still pass, including unwind tests
Implemenation-wise, this is InputSection-based, so it'll work for
object files with .subsections_via_symbols (which includes all
object files generated by clang). I first based this on the COFF
implementation, but later realized that things are more similar to ELF.
I think it'd be good to refactor MarkLive.cpp to look more like the ELF
part at some point, but I'd like to get a working state checked in first.
Mechanical parts:
- Rename canOmitFromOutput to wasCoalesced (no behavior change)
since it really is for weak coalesced symbols
- Add noDeadStrip to Defined, corresponding to N_NO_DEAD_STRIP
(`.no_dead_strip` in asm)
Fixes PR49276.
Differential Revision: https://reviews.llvm.org/D103324
Before this, if an inline function was defined in several input files,
lld would write each copy of the inline function the output. With this
patch, it only writes one copy.
Reduces the size of Chromium Framework from 378MB to 345MB (compared
to 290MB linked with ld64, which also does dead-stripping, which we
don't do yet), and makes linking it faster:
N Min Max Median Avg Stddev
x 10 3.9957051 4.3496981 4.1411121 4.156837 0.10092097
+ 10 3.908154 4.169318 3.9712729 3.9846753 0.075773012
Difference at 95.0% confidence
-0.172162 +/- 0.083847
-4.14165% +/- 2.01709%
(Student's t, pooled s = 0.0892373)
Implementation-wise, when merging two weak symbols, this sets a
"canOmitFromOutput" on the InputSection belonging to the weak symbol not put in
the symbol table. We then don't write InputSections that have this set, as long
as they are not referenced from other symbols. (This happens e.g. for object
files that don't set .subsections_via_symbols or that use .alt_entry.)
Some restrictions:
- not yet done for bitcode inputs
- no "comdat" handling (`kindNoneGroupSubordinate*` in ld64) --
Frame Descriptor Entries (FDEs), Language Specific Data Areas (LSDAs)
(that is, catch block unwind information) and Personality Routines
associated with weak functions still not stripped. This is wasteful,
but harmless.
- However, this does strip weaks from __unwind_info (which is needed for
correctness and not just for size)
- This nopes out on InputSections that are referenced form more than
one symbol (eg from .alt_entry) for now
Things that work based on symbols Just Work:
- map files (change in MapFile.cpp is no-op and not needed; I just
found it a bit more explicit)
- exports
Things that work with inputSections need to explicitly check if
an inputSection is written (e.g. unwind info).
This patch is useful in itself, but it's also likely also a useful foundation
for dead_strip.
I used to have a "canoncialRepresentative" pointer on InputSection instead of
just the bool, which would be handy for ICF too. But I ended up not needing it
for this patch, so I removed that again for now.
Differential Revision: https://reviews.llvm.org/D102076
This diff adds initial support for the legacy LC_VERSION_MIN_* load commands.
Test plan: make check-lld-macho
Differential revision: https://reviews.llvm.org/D100523
Within `lld/macho/`, only `InputFiles.cpp` and `Symbols.h` require the `macho::` namespace qualifier to disambiguate references to `class Symbol`.
Add braces to outer `for` of a 5-level single-line `if`/`for` nest.
Differential Revision: https://reviews.llvm.org/D99555
I added just enough to allow us to see a top-level breakdown of time taken. This
is the result of loading the time-trace output into `chrome:://tracing`:
ef5e8234f3/tracing.png
Reviewed By: oontvoo
Differential Revision: https://reviews.llvm.org/D99311