summaryrefslogtreecommitdiff
path: root/lld/MachO/ConcatOutputSection.cpp
AgeCommit message (Collapse)Author
2025-05-25[lld] Remove unused includes (NFC) (#141421)Kazu Hirata
2025-05-01[lld-macho] Fix branch extension logic compatibility with __objc_stubs (#137913)alx32
Enhance branch extension logic to handle __objc_stubs identically to __stubs The branch extension algorithm currently has specific handling for the `__stubs` section: 1. It ensures all `__stubs` content is directly reachable via branches from the text section. 2. It calculates the latest text section address that might require thunks to reach the end of `__stubs`. The `__objc_stubs` section requires precisely the same handling due to its similar nature, but this was not implemented. This commit generalizes the existing logic so it applies consistently to both the `__stubs` and `__objc_stubs` sections, ensuring correct reachability and thunk placement for both. Without this change it's possible to get relocation errors during linking in scenarios where the `__objc_stubs` section is large enough.
2025-01-09[lld-macho] Fix branch extension thunk estimation logic (#120529)alx32
This patch improves the linker’s ability to estimate stub reachability in the `TextOutputSection::estimateStubsInRangeVA` function. It does so by including thunks that have already been placed ahead of the current call site address when calculating the threshold for direct stub calls. Before this fix, the estimation process overlooked existing forward thunks. This could result in some thunks not being inserted where needed. In rare situations, particularly with large and specially arranged codebases, this might lead to branch instructions being out of range, causing linking errors. Although this patch successfully addresses the problem, it is not feasible to create a test for this issue. The specific layout and order of thunk creation required to reproduce the corner case are too complex, making test creation impractical. Example error messages the issue could generate: ``` ld64.lld: error: banana.o:(symbol OUTLINED_FUNCTION_24949_3875): relocation BRANCH26 is out of range: 134547892 is not in [-134217728, 134217727]; references objc_autoreleaseReturnValue ld64.lld: error: main.o:(symbol _main+0xc): relocation BRANCH26 is out of range: 134544132 is not in [-134217728, 134217727]; references objc_release ```
2024-12-14[lld] Migrate away from PointerUnion::{is,get} (NFC) (#119993)Kazu Hirata
Note that PointerUnion::{is,get} have been soft deprecated in PointerUnion.h: // FIXME: Replace the uses of is(), get() and dyn_cast() with // isa<T>, cast<T> and the llvm::dyn_cast<T> I'm not touching PointerUnion::dyn_cast for now because it's a bit complicated; we could blindly migrate it to dyn_cast_if_present, but we should probably use dyn_cast when the operand is known to be non-null.
2024-07-23[lld-macho] Fix thunks for non-__text TEXT sections (#99052)Leonard Grey
This supersedes https://github.com/llvm/llvm-project/pull/87818 and fixes https://github.com/llvm/llvm-project/issues/52767 When calculating arm64 thunks, we make a few assumptions that may not hold when considering code sections outside of `__text`: 1. That a section needs thunks only if its size is larger than the branch range. 2. That any calls into `__stubs` are necessarily forward jumps (that is, the section with the jump is ordered before `__stubs`) Sections like this exist in the wild, most prominently the `__lcxx_overrides` section introduced in https://github.com/llvm/llvm-project/pull/69498 This change: - Ensures that if one section in `__TEXT` gets thunks, all of them do. - Makes all code sections in `__TEXT` contiguous (and guaranteed to be placed before `__stubs`)
2024-03-27[lld-macho] Fix bug in makeSyntheticInputSection when -dead_strip flag is ↵alx32
specified (#86878) Previously, `makeSyntheticInputSection` would create a new `ConcatInputSection` without setting `live` explicitly for it. Without `-dead_strip` this would be OK since `live` would default to `true`. However, with `-dead_strip`, `live` would default to false, and it would remain set to `false`. This hasn't resulted in any issues so far since no code paths that exposed this issue were present. However a recent change - ObjC relative method lists (https://github.com/llvm/llvm-project/pull/86231) exposes this issue by creating relocations to the `SyntheticInputSection`. When these relocations are attempted to be written, this ends up with a crash(assert), since the `SyntheticInputSection` they refer to is marked as dead (`live` = `false`). With this change, we set the correct behavior - `live` will always be `true`. We add a test case that before this change would trigger an assert in the linker.
2023-05-20[lld-macho] Remove partially supported 32-bit ARM archVincent Lee
We never really supported 32-bit ARM arch entirely, and partial support was added for very specific features. Regardless, it fails to even link the most basic applications that at this point, it might be better to move this arch as unsupported. Given that Apple will be moving towards arm64 long term, I don't see any reason for anyone to invest time in supporting this either, and for those who still need it should use apple's ld64 linker. Fixes #62691 Reviewed By: #lld-macho, int3 Differential Revision: https://reviews.llvm.org/D150544
2023-03-07[lld-macho][nfc] Convert more alignTo() to alignToPowerOf2()Jez Ng
Reviewed By: #lld-macho, smeenai Differential Revision: https://reviews.llvm.org/D145261
2023-02-16[lld-macho] Use uint64_t instead of size_t to fix 32 bit test failuresDavid Spickett
Our bot has been failing https://lab.llvm.org/buildbot/#/builders/178/builds/3967: Assertion `isecEnd - isecVA <= forwardBranchRange && "should only finalize sections in jump range"' failed. I think this is due to the use of size_t, which is 32 bit on 32 bit, for a value used in some 64 bit address calculations. Which was added in https://reviews.llvm.org/D144029. Switching to uint64_t fixes the issues.
2023-02-14[lld-macho] Account for alignment in thunk insertion algorithmJez Ng
We previously neglected this, leading us to underestimate the maximum possible branch address offset. Fixing this should allow us to reduce `slop` to more reasonable levels. I've lowered it to 256 for now, though I suspect we could go lower. Fixes https://github.com/llvm/llvm-project/issues/59259. Reviewed By: serge-sans-paille Differential Revision: https://reviews.llvm.org/D144029
2022-11-16[lld-macho] Increase slop to prevent thunk out of range again.Mike Hommey
Building Firefox with -O0 on arm64 mac recently hit the "FIXME: thunk range overrun" error on multiple occasions. Doubling or tripling slop was not sufficient in some cases, so quadruple it. Reviewed By: #lld-macho, int3 Differential Revision: https://reviews.llvm.org/D138174
2022-06-16Replace to_hexString by touhexstr [NFC]Corentin Jabot
LLVM had 2 methods to convert a number to an hexa string, this remove one of them. Differential Revision: https://reviews.llvm.org/D127958
2022-05-24[lld-macho][nfc] Run clang-format on lld/MachO/*.{h,cpp}Vy Nguyen
- fixed inconsistent indents and spaces - prevent extraneous formatting changes in other patches Differential Revision: https://reviews.llvm.org/D126262
2022-04-22[lld-macho] Remove stray debug printfJez Ng
Accidentally committed as part of b440c25742.
2022-04-11[lld-macho][nfc] Use includeInSymtab for all symtab-skipping logicJez Ng
{D123302} got me looking deeper at `includeInSymtab`. I thought it was a little odd that there were excluded (live) symbols for which `includeInSymtab` was false; we shouldn't have so many different ways to exclude a symbol. As such, this diff makes the `L`-prefixed-symbol exclusion code use `includeInSymtab` too. (Note that as part of our support for `__eh_frame`, we will also be excluding all `__eh_frame` symbols from the symtab in a future diff.) Another thing I noticed is that the `emitStabs` code never has to deal with excluded symbols because `SymtabSection::finalize()` already filters them out. As such, I've updated the comments and asserts from {D123302} to reflect this. Reviewed By: #lld-macho, thakis Differential Revision: https://reviews.llvm.org/D123433
2022-04-07Fix format specifier. NFCI.Jorge Gorbe Moya
Using a portable format specifier avoids a "format specifies type 'unsigned long long' but the argument has type 'uint64_t' (aka 'unsigned long') [-Werror,-Wformat]" error depending on the exact definition of `uint64_t`.
2022-04-07[lld-macho][nfc] Give non-text ConcatOutputSections order-independent ↵Jez Ng
finalization This diff is motivated by my work to add proper DWARF unwind support. As detailed in PR50956 functions that need DWARF unwind need to have compact unwind entries synthesized for them. These CU entries encode an offset within `__eh_frame` that points to the corresponding DWARF FDE. In order to encode this offset during `UnwindInfoSectionImpl::finalize()`, we need to first assign values to `InputSection::outSecOff` for each `__eh_frame` subsection. But `__eh_frame` is ordered after `__unwind_info` (according to ld64 at least), which puts us in a bit of a bind: `outSecOff` gets assigned during finalization, but `__eh_frame` is being finalized after `__unwind_info`. But it occurred to me that there's no real need for most ConcatOutputSections to be finalized sequentially. It's only necessary for text-containing ConcatOutputSections that may contain branch relocs which may need thunks. ConcatOutputSections containing other types of data can be finalized in any order. This diff moves the finalization logic for non-text sections into a separate `finalizeContents()` method. This method is called before section address assignment & unwind info finalization takes place. In theory we could call these `finalizeContents()` methods in parallel, but in practice it seems to be faster to do it all on the main thread. Reviewed By: #lld-macho, oontvoo Differential Revision: https://reviews.llvm.org/D123279
2022-04-01[lld/mac] Tweak a few commentsNico Weber
Addresses review feedback I had missed on https://reviews.llvm.org/D122624 No behavior change. Differential Revision: https://reviews.llvm.org/D122904
2022-03-30[lld/mac] Give range extension thunks for local symbols local visibilityNico Weber
When two local symbols (think: file-scope static functions, or functions in unnamed namespaces) with the same name in two different translation units both needed thunks, ld64.lld previously created external thunks for both of them. These thunks ended up with the same name, leading to a duplicate symbol error for the thunk symbols. Instead, give thunks for local symbols local visibility. (Hitting this requires a jump to a local symbol from over 128 MiB away. It's unlikely that a single .o file is 128 MiB large, but with ICF you can end up with a situation where the local symbol is ICF'd with a symbol in a separate translation unit. And that can introduce a large enough jump to require a thunk.) Fixes PR54599. Differential Revision: https://reviews.llvm.org/D122624
2022-02-03[lld-macho][nfc] Eliminate InputSection::SharedJez Ng
Earlier in LLD's evolution, I tried to create the illusion that subsections were indistinguishable from "top-level" sections. Thus, even though the subsections shared many common field values, I hid those common values away in a private Shared struct (see D105305). More recently, however, @gkm added a public `Section` struct in D113241 that served as an explicit way to store values that are common to an entire set of subsections (aka InputSections). Now that we have another "common value" struct, `Shared` has been rendered redundant. All its fields can be moved into `Section` instead, and the pointer to `Shared` can be replaced with a pointer to `Section`. This `Section` pointer also has the advantage of letting us inspect other subsections easily, simplifying the implementation of {D118798}. P.S. I do think that having both `Section` and `InputSection` makes for a slightly confusing naming scheme. I considered renaming `InputSection` to `Subsection`, but that would break the symmetry with `OutputSection`. It would also make us deviate from LLD-ELF's naming scheme. This change is perf-neutral on my 3.2 GHz 16-Core Intel Xeon W machine: base diff difference (95% CI) sys_time 1.258 ± 0.031 1.248 ± 0.023 [ -1.6% .. +0.1%] user_time 3.659 ± 0.047 3.658 ± 0.041 [ -0.5% .. +0.4%] wall_time 4.640 ± 0.085 4.625 ± 0.063 [ -1.0% .. +0.3%] samples 49 61 There's also no stat sig change in RSS (as measured by `time -l`): base diff difference (95% CI) time 998038627.097 ± 13567305.958 1003327715.556 ± 15210451.236 [ -0.2% .. +1.2%] samples 31 36 Reviewed By: #lld-macho, oontvoo Differential Revision: https://reviews.llvm.org/D118797
2022-01-20Re-land [LLD] Remove global state in lldCommonAlexandre Ganea
Move all variables at file-scope or function-static-scope into a hosting structure (lld::CommonLinkerContext) that lives at lldMain()-scope. Drivers will inherit from this structure and add their own global state, in the same way as for the existing COFFLinkerContext. See discussion in https://lists.llvm.org/pipermail/llvm-dev/2021-June/151184.html The previous land f860fe362282ed69b9d4503a20e5d20b9a041189 caused issues in https://lab.llvm.org/buildbot/#/builders/123/builds/8383, fixed by 22ee510dac9440a74b2e5b3fe3ff13ccdbf55af3. Differential Revision: https://reviews.llvm.org/D108850
2022-01-16Revert [LLD] Remove global state in lldCommonAlexandre Ganea
It seems to be causing issues on https://lab.llvm.org/buildbot/#/builders/123/builds/8383
2022-01-16[LLD] Remove global state in lldCommonAlexandre Ganea
Move all variables at file-scope or function-static-scope into a hosting structure (lld::CommonLinkerContext) that lives at lldMain()-scope. Drivers will inherit from this structure and add their own global state, in the same way as for the existing COFFLinkerContext. See discussion in https://lists.llvm.org/pipermail/llvm-dev/2021-June/151184.html Differential Revision: https://reviews.llvm.org/D108850
2022-01-06[lld-macho] Increase slops to prevent thunk out of rangeVincent Lee
One of our internal arm64 apps hit a thunk out of range error when building with LLD. Per the comment, I'm arbitrarily increasing slop size to 256. Reviewed By: #lld-macho, thakis Differential Revision: https://reviews.llvm.org/D116705
2021-12-11[lld-macho][nfc] InputSections don't need to track their total # of callsitesJez Ng
... only whether they have more than zero. This simplifies the code slightly. I've also moved the field into the ConcatInputSection subclass since it doesn't actually get used by the other InputSections. Reviewed By: #lld-macho, oontvoo Differential Revision: https://reviews.llvm.org/D115539
2021-11-12[lld-macho] Allow exporting weak_def_can_be_hidden(AKA "autohide") symbolsVy Nguyen
autohide symbols behaves similarly to private_extern symbols. However, LD64 allows exporting autohide symbols. LLD currently does not. This patch allows LLD to export them. Differential Revision: https://reviews.llvm.org/D113167
2021-11-02[lld-macho][nfc][cleanup] Fix a few code style lints and clang-tidy findingsVy Nguyen
- Use .empty() instead of `size() == 0` when possible. - Use const-ref to avoid copying Differential Revision: https://reviews.llvm.org/D112978
2021-10-26[lld-macho] Associate compact unwind entries with function symbolsJez Ng
Compact unwind entries (CUEs) contain pointers to their respective function symbols. However, during the link process, it's far more useful to have pointers from the function symbol to the CUE than vice versa. This diff adds that pointer in the form of `Defined::compactUnwind`. In particular, when doing dead-stripping, we want to mark CUEs live when their function symbol is live; and when doing ICF, we want to dedup sections iff the symbols in that section have identical CUEs. In both cases, we want to be able to locate the symbols within a given section, as well as locate the CUEs belonging to those symbols. So this diff also adds `InputSection::symbols`. The ultimate goal of this refactor is to have ICF support dedup'ing functions with unwind info, but that will be handled in subsequent diffs. This diff focuses on simplifying `-dead_strip` -- `findFunctionsWithUnwindInfo` is no longer necessary, and `Defined::isLive()` is now a lot simpler. Moreover, UnwindInfoSection no longer has to check for dead CUEs -- we simply avoid adding them in the first place. Additionally, we now support stripping of dead LSDAs, which follows quite naturally since `markLive()` can now reach them via the CUEs. Reviewed By: #lld-macho, gkm Differential Revision: https://reviews.llvm.org/D109944
2021-09-18[lld/mac] Fix comment typo to cycle botsNico Weber
2021-08-30[lld/mac] Leave more room for thunks in thunk placement codeNico Weber
Fixes PR51578 in practice. Currently there's only enough room for a single thunk, which for real-life code isn't enough. The error case only happens when there are many branch statements very close to each other (0 or 1 instructions apart), with the function at the finalization barrier small. There's a FIXME on what to do if we hit this case, but that suggestion sounds complicated to me (see end of PR51578 comment 5 for why). Instead, just leave more room for thunks. Chromium's unit_tests links fine with room for 3 thunks. Leave room for 100, which should fix this for most cases in practice. There's little cost for leaving lots of room: This slop value only determines when we finalize sections, and we insert thunks for forward jumps into unfinalized sections. So leaving room means we'll need a few more thunks, but the thunk jump range is 128 MiB while a single thunk is just 12 bytes. For Chromium's unit_tests: With a slop of 3: thunk calls = 355418, thunks = 10903 With a slop of 100: thunk calls = 355426, thunks = 10904 Chances are 100 is enough for all use cases we'll hit in practice, but even bumping it to 1000 would probably be fine. Differential Revision: https://reviews.llvm.org/D108930
2021-08-30[lld/mac] Tweak estimateStubsInRangeVA a bitNico Weber
- Move a few variables closer to their uses, remove some completely (no behavior change) - Add some comments - Make maxPotentialThunks include calls to stubs. It's possible that an earlier call to a stub late in the stub table will need a thunk, and that inserted thunk could push a stub earlier in the stub table out of range. This is unlikely to happen, but usually there are way fewer stub calls than non-stub calls, so if we're doing a conservative approximation here we might as well do it correctly. (For chromium's unit_tests target, 134421/242639 stub calls are direct calls without this change, compared to 134408/242639 with this change) No real, meaningful behavior difference. Differential Revision: https://reviews.llvm.org/D108924
2021-08-30[lld/mac] Set branchRange a bit more carefullyNico Weber
- Don't subtract thunkSize from branchRange. Most places care about the actual maximal branch range. Subtract thunkSize in the one place that wants to leave room for a thunk. - Set it to 0x800_0000 instead of 0xFF_FFFF - Subtract 4 for the positive branch direction since it's a two's complement 24bit number sign-extended mutiplied by 4, so its range is -0x800_0000..+0x7FF_FFFC - Make boundary checks include the boundary values This doesn't make a huge difference in practice. It's preparation for a "real" fix for PR51578 -- but it also lets the repro in comment 0 in that bug place one more thunk before hitting the TODO. Differential Revision: https://reviews.llvm.org/D108897
2021-08-27[lld/mac] Don't assert on -dead_strip + arm64 range extension thunksNico Weber
The assert is harmless and thinks worked fine in builds with asserts enabled, but it's still nice to fix the assert. Differential Revision: https://reviews.llvm.org/D108853
2021-07-25[lld/mac] Move output segment rename logic into OutputSegmentNico Weber
Fixes the output segment name if both -rename_section and -rename_segment are used and the post-section-rename segment name is the same as the pre-segment-rename segment name to match ld64's behavior. The motivation is that segment$start$ can create section-less segments, and this makes a corner case in the interaction between segment$start and -rename_segment in the upcoming segment$start patch. Differential Revision: https://reviews.llvm.org/D106766
2021-07-17[lld-macho] Have ICF operate on all sections at onceJez Ng
ICF previously operated only within a given OutputSection. We would merge all CFStrings first, then merge all regular code sections in a second phase. This worked fine since CFStrings would never reference regular `__text` sections. However, I would like to expand ICF to merge functions that reference unwind info. Unwind info references the LSDA section, which can in turn reference the `__text` section, so we cannot perform ICF in phases. In order to have ICF operate on InputSections spanning multiple OutputSections, we need a way to distinguish InputSections that are destined for different OutputSections, so that we don't fold across section boundaries. We achieve this by creating OutputSections early, and setting `InputSection::parent` to point to them. This is what LLD-ELF does. (This change should also make it easier to implement the `section$start$` symbols.) This diff also folds InputSections w/o checking their flags, which I think is the right behavior -- if they are destined for the same OutputSection, they will have the same flags in the output (even if their input flags differ). I.e. the `parent` pointer check subsumes the `flags` check. In practice this has nearly no effect (ICF did not become any more effective on chromium_framework). I've also updated ICF.cpp's block comment to better reflect its current status. Reviewed By: #lld-macho, smeenai Differential Revision: https://reviews.llvm.org/D105641
2021-07-05[lld-macho] Parse relocations quickly by assuming sorted orderJez Ng
clang and gcc both seem to emit relocations in reverse order of address. That means we can match relocations to their containing subsections in `O(relocs + subsections)` rather than the `O(relocs * log(subsections))` that our previous binary search implementation required. Unfortunately, `ld -r` can still emit unsorted relocations, so we have a fallback code path for that (less common) case. Numbers for linking chromium_framework on my 3.2 GHz 16-Core Intel Xeon W: N Min Max Median Avg Stddev x 20 4.04 4.11 4.075 4.0775 0.018027756 + 20 3.95 4.02 3.98 3.985 0.020900768 Difference at 95.0% confidence -0.0925 +/- 0.0124919 -2.26855% +/- 0.306361% (Student's t, pooled s = 0.0195172) Reviewed By: #lld-macho, thakis Differential Revision: https://reviews.llvm.org/D105410
2021-07-01[lld-macho] Factor out common InputSection membersJez Ng
We have been creating many ConcatInputSections with identical values due to .subsections_via_symbols. This diff factors out the identical values into a Shared struct, to reduce memory consumption and make copying cheaper. I also changed `callSiteCount` from a uint32_t to a 31-bit field to save an extra word. All in all, this takes InputSection from 120 to 72 bytes (and ConcatInputSection from 160 to 112 bytes), i.e. 30% size reduction in ConcatInputSection. Numbers for linking chromium_framework on my 3.2 GHz 16-Core Intel Xeon W: N Min Max Median Avg Stddev x 20 4.14 4.24 4.18 4.183 0.027548999 + 20 4.04 4.11 4.075 4.0775 0.018027756 Difference at 95.0% confidence -0.1055 +/- 0.0149005 -2.52211% +/- 0.356215% (Student's t, pooled s = 0.0232803) Reviewed By: #lld-macho, thakis Differential Revision: https://reviews.llvm.org/D105305
2021-07-01[lld-macho] Move ICF earlier to avoid emitting redundant bindsJez Ng
This is a pretty big refactoring diff, so here are the motivations: Previously, ICF ran after scanRelocations(), where we emitting bind/rebase opcodes etc. So we had a bunch of redundant leftovers after ICF. Having ICF run before Writer seems like a better design, and is what LLD-ELF does, so this diff refactors it accordingly. However, ICF had two dependencies on things occurring in Writer: 1) it needs literals to be deduplicated beforehand and 2) it needs to know which functions have unwind info, which was being handled by `UnwindInfoSection::prepareRelocations()`. In order to do literal deduplication earlier, we need to add literal input sections to their corresponding output sections. So instead of putting all input sections into the big `inputSections` vector, and then filtering them by type later on, I've changed things so that literal sections get added directly to their output sections during the 'gather' phase. Likewise for compact unwind sections -- they get added directly to the UnwindInfoSection now. This latter change is not strictly necessary, but makes it easier for ICF to determine which functions have unwind info. Adding literal sections directly to their output sections means that we can no longer determine `inputOrder` from iterating over `inputSections`. Instead, we store that order explicitly on InputSection. Bloating the size of InputSection for this purpose would be unfortunate -- but LLD-ELF has already solved this problem: it reuses `outSecOff` to store this order value. One downside of this refactor is that we now make an additional pass over the unwind info relocations to figure out which functions have unwind info, since want to know that before `processRelocations()`. I've made sure to run that extra loop only if ICF is enabled, so there should be no overhead in non-optimizing runs of the linker. The upside of all this is that the `inputSections` vector now contains only ConcatInputSections that are destined for ConcatOutputSections, so we can clean up a bunch of code that just existed to filter out other elements from that vector. I will test for the lack of redundant binds/rebases in the upcoming cfstring deduplication diff. While binds/rebases can also happen in the regular `.text` section, they're more common in `.data` sections, so it seems more natural to test it that way. This change is perf-neutral when linking chromium_framework. Reviewed By: oontvoo Differential Revision: https://reviews.llvm.org/D105044
2021-06-17[lld-macho] Rework mergeFlag to behave closer to what ld64 does.Vy Nguyen
Details: I've been getting a few weird errors similar to the following from our internal tests: ``` ld64.lld.darwinnew: error: Cannot merge section __eh_frame (type=0x0) into __eh_frame (type=0xB): inconsistent types ld64.lld.darwinnew: error: Cannot merge section __eh_frame (flags=0x0) into __eh_frame (flags=0x6800000B): strict flags differ ld64.lld.darwinnew: error: Cannot merge section __eh_frame (type=0x0) into __eh_frame (type=0xB): inconsistent types ld64.lld.darwinnew: error: Cannot merge section __eh_frame (flags=0x0) into __eh_frame (flags=0x6800000B): strict flags differ ``` Differential Revision: https://reviews.llvm.org/D103971
2021-06-17[lld-macho] Implement ICFGreg McGary
ICF = Identical C(ode|OMDAT) Folding This is the LLD ELF/COFF algorithm, adapted for MachO. So far, only `-icf all` is supported. In order to support `-icf safe`, we will need to port address-significance tables (`.addrsig` directives) to MachO, which will come in later diffs. `check-{llvm,clang,lld}` have 0 regressions for `lld -icf all` vs. baseline ld64. We only run ICF on `__TEXT,__text` for reasons explained in the block comment in `ConcatOutputSection.cpp`. Here is the perf impact for linking `chromium_framekwork` on a Mac Pro (16-core Xeon W) for the non-ICF case vs. pre-ICF: ``` N Min Max Median Avg Stddev x 20 4.27 4.44 4.34 4.349 0.043029977 + 20 4.37 4.46 4.405 4.4115 0.025188761 Difference at 95.0% confidence 0.0625 +/- 0.0225658 1.43711% +/- 0.518873% (Student's t, pooled s = 0.0352566) ``` Reviewed By: #lld-macho, int3 Differential Revision: https://reviews.llvm.org/D103292
2021-06-13[lld-macho][nfc] Remove InputSection::outSecFileOffJez Ng
`outSecFileOff` and the associated `getFileOffset()` accessors were unnecessary. For all the cases we care about, `outSecFileOff` is the same as `outSecOff`. The only time they deviate is if there are zerofill sections within a given segment. But since zerofill sections are always at the end of a segment, the only sections where the two values deviate are zerofill sections themselves. And we never actually query the outSecFileOff of zerofill sections. As for `getFileOffset()`, the only place it was being used was to calculate the offset of the entry symbol. However, we can compute that value by just taking the difference between the address of the entry symbol and the address of the Mach-O header. In fact, this appears to be what ld64 itself does. This difference is the same as the file offset as long as there are no intervening zerofill sections, but since `__text` is the first section in `__TEXT`, this never happens, so our previous use of `getFileOffset()` was not wrong -- just inefficient. Reviewed By: #lld-macho, thakis Differential Revision: https://reviews.llvm.org/D104177
2021-06-11[lld-macho][nfc] Have InputSection ctors take some parametersJez Ng
This is motivated by an upcoming diff in which the WordLiteralInputSection ctor sets itself up based on the value of its section flags. As such, it needs to be passed the `flags` value as part of its ctor parameters, instead of having them assigned after the fact in `parseSection()`. While refactoring code to make that possible, I figured it would make sense for the other InputSections to also take their initial values as ctor parameters. Reviewed By: #lld-macho, thakis Differential Revision: https://reviews.llvm.org/D103978
2021-06-11[lld/mac] Use sectionType() moreNico Weber
Not sure sectionType() carries its weight, but while we have it we should use it consistently. No behavior change. Differential Revision: https://reviews.llvm.org/D104027
2021-06-07[lld-macho] Implement cstring deduplicationJez Ng
Our implementation draws heavily from LLD-ELF's, which in turn delegates its string deduplication to llvm-mc's StringTableBuilder. The messiness of this diff is largely due to the fact that we've previously assumed that all InputSections get concatenated together to form the output. This is no longer true with CStringInputSections, which split their contents into StringPieces. StringPieces are much more lightweight than InputSections, which is important as we create a lot of them. They may also overlap in the output, which makes it possible for strings to be tail-merged. In fact, the initial version of this diff implemented tail merging, but I've dropped it for reasons I'll explain later. **Alignment Issues** Mergeable cstring literals are found under the `__TEXT,__cstring` section. In contrast to ELF, which puts strings that need different alignments into different sections, clang's Mach-O backend puts them all in one section. Strings that need to be aligned have the `.p2align` directive emitted before them, which simply translates into zero padding in the object file. I *think* ld64 extracts the desired per-string alignment from this data by preserving each string's offset from the last section-aligned address. I'm not entirely certain since it doesn't seem consistent about doing this; but perhaps this can be chalked up to cases where ld64 has to deduplicate strings with different offset/alignment combos -- it seems to pick one of their alignments to preserve. This doesn't seem correct in general; we can in fact can induce ld64 to produce a crashing binary just by linking in an additional object file that only contains cstrings and no code. See PR50563 for details. Moreover, this scheme seems rather inefficient: since unaligned and aligned strings are all put in the same section, which has a single alignment value, it doesn't seem possible to tell whether a given string doesn't have any alignment requirements. Preserving offset+alignments for strings that don't need it is wasteful. In practice, the crashes seen so far seem to stem from x86_64 SIMD operations on cstrings. X86_64 requires SIMD accesses to be 16-byte-aligned. So for now, I'm thinking of just aligning all strings to 16 bytes on x86_64. This is indeed wasteful, but implementation-wise it's simpler than preserving per-string alignment+offsets. It also avoids the aforementioned crash after deduplication of differently-aligned strings. Finally, the overhead is not huge: using 16-byte alignment (vs no alignment) is only a 0.5% size overhead when linking chromium_framework. With these alignment requirements, it doesn't make sense to attempt tail merging -- most strings will not be eligible since their overlaps aren't likely to start at a 16-byte boundary. Tail-merging (with alignment) for chromium_framework only improves size by 0.3%. It's worth noting that LLD-ELF only does tail merging at `-O2`. By default (at `-O1`), it just deduplicates w/o tail merging. @thakis has also mentioned that they saw it regress compressed size in some cases and therefore turned it off. `ld64` does not seem to do tail merging at all. **Performance Numbers** CString deduplication reduces chromium_framework from 250MB to 242MB, or about a 3.2% reduction. Numbers for linking chromium_framework on my 3.2 GHz 16-Core Intel Xeon W: N Min Max Median Avg Stddev x 20 3.91 4.03 3.935 3.95 0.034641016 + 20 3.99 4.14 4.015 4.0365 0.0492336 Difference at 95.0% confidence 0.0865 +/- 0.027245 2.18987% +/- 0.689746% (Student's t, pooled s = 0.0425673) As expected, cstring merging incurs some non-trivial overhead. When passing `--no-literal-merge`, it seems that performance is the same, i.e. the refactoring in this diff didn't cost us. N Min Max Median Avg Stddev x 20 3.91 4.03 3.935 3.95 0.034641016 + 20 3.89 4.02 3.935 3.9435 0.043197831 No difference proven at 95.0% confidence Reviewed By: #lld-macho, gkm Differential Revision: https://reviews.llvm.org/D102964
2021-06-02[lld/mac] Implement -dead_stripNico Weber
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
2021-05-25[lld-macho][nfc] Rename MergedOutputSection to ConcatOutputSectionJez Ng
The ELF format has the concept of merge sections (marked by SHF_MERGE), which contain data that can be safely deduplicated. The Mach-O equivalents are called literal sections (marked by S_CSTRING_LITERALS or S_{4,8,16}BYTE_LITERALS). While the Mach-O format doesn't use the word 'merge', to avoid confusion, I've renamed our MergedOutputSection to ConcatOutputSection. I believe it's a more descriptive name too. This renaming sets the stage for {D102964}. Reviewed By: #lld-macho, alexshap Differential Revision: https://reviews.llvm.org/D102971