14 Commits

Author SHA1 Message Date
Kyungwoo Lee
391393179a
[lld-macho] icf objc stubs (#79730)
This supports icf for objc stubs.
2024-02-01 14:19:11 -08:00
Kyungwoo Lee
77e204c7b0
[lld-macho][arm64] implement -objc_stubs_small (#78665)
This patch implements `-objc_stubs_small` targeting arm64, aiming to
align with ld64's behavior.
1. `-objc_stubs_fast`: As previously implemented, this always uses the
Global Offset Table (GOT) to invoke `objc_msgSend`. The alignment of the
objc stub is 32 bytes.
2. `-objc_stubs_small`: This behavior depends on whether `objc_msgSend`
is defined. If it is, it directly jumps to `objc_msgSend`. If not, it
creates another stub to indirectly jump to `objc_msgSend`, minimizing
the size. The alignment of the objc stub in this case is 4 bytes.
2024-01-23 07:31:34 -08:00
Daniel Bertalan
0d30e92f59
[lld-macho] Add support for emitting chained fixups
This commit adds support for chained fixups, which were introduced in
Apple's late 2020 OS releases. This format replaces the dyld opcodes
used for supplying rebase and binding information, and encodes most of
that data directly in the memory location that will have the fixup
applied.

This reduces binary size and is a requirement for page-in linking, which
will be available starting with macOS 13.

A high-level overview of the format and my implementation can be found
in SyntheticSections.h.

This feature is currently gated behind the `-fixup_chains` flag, and
will be enabled by default for supported targets in a later commit.

Like in ld64, lazy binding is disabled when chained fixups are in use,
and the `-init_offsets` transformation is performed by default.

Differential Revision: https://reviews.llvm.org/D132560
2022-10-04 11:48:45 +02:00
Keith Smiley
3c24fae398
[lld-macho] Add support for objc_msgSend stubs
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
2022-08-10 17:17:17 -07:00
Daniel Bertalan
1fb9466c6a [lld-macho] Devirtualize TargetInfo::getRelocAttrs
This method is called on each relocation when parsing input files, so
the overhead of using virtual functions ends up being quite large.  We
now have a single non-virtual method, which reads from the appropriate
array of relocation attributes set in the TargetInfo constructor.

This change results in a modest 2.3% reduction in link time for
chromium_framework measured on an x86-64 VPS, and 0.7% on an arm64 Mac.

    N           Min           Max        Median           Avg        Stddev
x  10     11.869417     12.032609     11.935041     11.938268   0.045802324
+  10     11.581526     11.785265     11.649885     11.659507   0.054634834
Difference at 95.0% confidence
	-0.278761 +/- 0.0473673
	-2.33502% +/- 0.396768%
	(Student's t, pooled s = 0.0504124)

Differential Revision: https://reviews.llvm.org/D130000
2022-07-18 19:32:58 +02:00
Jez Ng
e183bf8e15 [lld-macho][reland] Initial support for EH Frames
This reverts commit 942f4e3a7cc9a9f8b2654817cff12907d1276031.

The additional change required to avoid the assertion errors seen
previously is:

  --- a/lld/MachO/ICF.cpp
  +++ b/lld/MachO/ICF.cpp
  @@ -443,7 +443,9 @@ void macho::foldIdenticalSections() {
                                 /*relocVA=*/0);
           isec->data = copy;
         }
  -    } else {
  +    } else if (!isEhFrameSection(isec)) {
  +      // EH frames are gathered as hashables from unwindEntry above; give a
  +      // unique ID to everything else.
         isec->icfEqClass[0] = ++icfUniqueID;
       }
     }

Differential Revision: https://reviews.llvm.org/D123435
2022-06-13 07:45:16 -04:00
Douglas Yung
942f4e3a7c Revert "[lld-macho] Initial support for EH Frames"
This reverts commit 826be330af9c0a8553a5b32718ecd2d97e10438e.

This was causing a test failure on build bots:
  - https://lab.llvm.org/buildbot/#/builders/36/builds/21770
  - https://lab.llvm.org/buildbot/#/builders/58/builds/23913
2022-06-09 05:25:43 -07:00
Jez Ng
826be330af [lld-macho] Initial support for EH Frames
== Background ==

`llvm-mc` generates unwind info in both compact unwind and DWARF
formats. LLD already handles the compact unwind format; this diff gets
us close to handling the DWARF format properly.

== Caveats ==

It's not quite done yet, but I figure it's worth getting this reviewed
and landed first as it's shaping up to be a fairly large code change.

**Known limitations of the current code:**

* Only works for x86_64, for which `llvm-mc` emits "abs-ified"
  relocations as described in 618def651b.
  `llvm-mc` emits regular relocations for ARM EH frames, which we do not
  yet handle correctly.

Since the feature is not ready for real use yet, I've gated it behind a
flag that only gets toggled on during test suite runs. With most of the
new code disabled, we see just a hint of perf regression, so I don't
think it'd be remiss to land this as-is:

             base           diff           difference (95% CI)
  sys_time   1.926 ± 0.168  1.979 ± 0.117  [  -1.2% ..   +6.6%]
  user_time  3.590 ± 0.033  3.606 ± 0.028  [  +0.0% ..   +0.9%]
  wall_time  7.104 ± 0.184  7.179 ± 0.151  [  -0.2% ..   +2.3%]
  samples    30             31

== Design ==

Like compact unwind entries, EH frames are also represented as regular
ConcatInputSections that get pointed to via `Defined::unwindEntry`. This
allows them to be handled generically by e.g. the MarkLive and ICF
code. (But note that unlike compact unwind subsections, EH frame
subsections do end up in the final binary.)

In order to make EH frames "look like" a regular ConcatInputSection,
some processing is required. First, we need to split the `__eh_frame`
section along EH frame boundaries rather than along symbol boundaries.
We do this by decoding the length field of each EH frame. Second, the
abs-ified relocations need to be turned into regular Relocs.

== Next Steps ==

In order to support EH frames on ARM targets, we will either have to
teach LLD how to handle EH frames with explicit relocs, or we can try to
make `llvm-mc` emit abs-ified relocs for ARM as well. I'm hoping to do
the latter as I think it will make the LLD implementation both simpler
and faster to execute.

== Misc ==

The `obj-file-with-stabs.s` test had to be updated as the previous
version would trip assertion errors in the code. It appears that in our
attempt to produce a minimal YAML test input, we created a file with
invalid EH frame data. I've fixed this by re-generating the YAML and not
doing any hand-pruning of it.

Reviewed By: #lld-macho, Roger

Differential Revision: https://reviews.llvm.org/D123435
2022-06-08 23:40:52 -04:00
Jez Ng
7f3ddf8443 [lld-macho][nfc] Allow Defined symbols to be placed in binding sections
Previously, we only allowed this for DylibSymbols. However, in order to
properly support `-flat_namespace` as well as `-interposable`, we need
to allow this for Defined symbols too. Therefore we hoist the
`lazyBindOffset` and the `stubsHelperIndex` into the parent Symbol
class.

The actual change to support interposition under `-flat_namespace` is in
{D119294}; the NFC changes here have been split out for easier review.

Perf regression isn't stat sig on my 3.2 GHz 16-Core Intel Xeon W linking
chromium_framework:

             base           diff           difference (95% CI)
  sys_time   1.227 ± 0.021  1.234 ± 0.031  [  -0.3% ..   +1.5%]
  user_time  3.665 ± 0.036  3.674 ± 0.035  [  -0.2% ..   +0.7%]
  wall_time  4.596 ± 0.055  4.609 ± 0.064  [  -0.3% ..   +0.9%]
  samples    34             47

Max RSS regression is barely stat sig:

           base                           diff                           difference (95% CI)
  time     1003664356.324 ± 15404053.912  1010380403.613 ± 10578309.455  [  +0.0% ..   +1.3%]
  samples  37                             31

Reviewed By: modimo

Differential Revision: https://reviews.llvm.org/D121351
2022-03-14 22:18:32 -04:00
Jez Ng
1aa29dffce [lld-macho] Support subtractor relocations that reference sections
The minuend (but not the subtrahend) can reference a section.

Note that we do not yet properly validate that the subtrahend isn't
referencing a section; I've filed PR50034 to track that.

I've also extended the reloc-subtractor.s test to reorder symbols, to
make sure that the addends are being associated with the minuend (and not
the subtrahend) relocation.

Fixes PR49999.

Reviewed By: #lld-macho, thakis

Differential Revision: https://reviews.llvm.org/D100804
2021-04-20 16:58:57 -04:00
Jez Ng
4938b090cf [lld-macho] Don't use arrays as template parameters
MSVC from VSCode 2017 appears unhappy with it (causes an
internal compiler error.)

This also means that we need to avoid doing `sizeof(stubCode)` as
`sizeof(int[N])` on function array parameters decays into `sizeof(int *)`.

Reviewed By: #lld-macho, gkm

Differential Revision: https://reviews.llvm.org/D100605
2021-04-15 21:16:34 -04:00
Jez Ng
3bc88eb392 [lld-macho] Add support for arm64_32
From what I can tell, it's pretty similar to arm64. The two main differences
are:

1. No 64-bit relocations
2. Stub code writes to 32-bit registers instead of 64-bit

Plus of course the various on-disk structures like `segment_command` are using
the 32-bit instead of the 64-bit variants.

Reviewed By: #lld-macho, gkm

Differential Revision: https://reviews.llvm.org/D99822
2021-04-15 21:16:33 -04:00
Jez Ng
8ca366935b Revert "[lld-macho] Add support for arm64_32" and other stacked diffs
This reverts commits:
* 8914902b01a3f8bdea9c71a0d9d23e4ee0ae80e4
* 35a745d814e1cde3de25d0d959fddc31e1061a41
* 682d1dfe09436857aa3b64365b5cc6fcbf1f043b
2021-04-13 12:40:58 -04:00
Jez Ng
8914902b01 [lld-macho] Add support for arm64_32
From what I can tell, it's pretty similar to arm64. The two main differences
are:

1. No 64-bit relocations
2. Stub code writes to 32-bit registers instead of 64-bit

Plus of course the various on-disk structures like `segment_command` are using
the 32-bit instead of the 64-bit variants.

Reviewed By: #lld-macho, gkm

Differential Revision: https://reviews.llvm.org/D99822
2021-04-13 10:43:28 -04:00