Commit Graph

780 Commits

Author SHA1 Message Date
Daniel Bertalan 2028fe6fbc [lld-macho] Handle LOH_ARM64_ADRP_LDR_GOT optimization hints
This hint instructs the linker to perform the AdrpLdr or AdrpAdd
transformation depending on whether the GOT load has been relaxed to
load a local symbol's address.

Differential Revision: https://reviews.llvm.org/D129059
2022-07-05 07:33:13 +02:00
Daniel Bertalan 73b659ff55 [lld-macho] Fix left shift of negative value UB
I introduced this mistake in 573c7e6b3c.

Fixes the failure on this UBSan bot:
https://lab.llvm.org/buildbot/#/builders/5/builds/25537
2022-07-01 12:00:16 +02:00
Daniel Bertalan 573c7e6b3c [lld-macho] Handle LOH_ARM64_ADRP_LDR linker optimization hints
This linker optimization hint transforms a pair of adrp+ldr (immediate)
instructions into an ldr (literal) load from a PC-relative address if
it is 4-byte aligned and within +/- 1 MiB, as ldr can encode a signed
19-bit offset that gets multiplied by 4.

In the wild, only a small number of these hints are applicable because
not many loads end up close enough to the data segment. However, the
added helper functions will be useful in implementing the rest of the
LOH types.

Differential Revision: https://reviews.llvm.org/D128942
2022-07-01 09:44:24 +02:00
Daniel Bertalan a3f67f0920 [lld-macho] Initial support for Linker Optimization Hints
Linker optimization hints mark a sequence of instructions used for
synthesizing an address, like ADRP+ADD. If the referenced symbol ends up
close enough, it can be replaced by a faster sequence of instructions
like ADR+NOP.

This commit adds support for 2 of the 7 defined ARM64 optimization
hints:
- LOH_ARM64_ADRP_ADD, which transforms a pair of ADRP+ADD into ADR+NOP
  if the referenced address is within +/- 1 MiB
- LOH_ARM64_ADRP_ADRP, which transforms two ADRP instructions into
  ADR+NOP if they reference the same page

These two kinds already cover more than 50% of all LOHs in
chromium_framework.

Differential Review: https://reviews.llvm.org/D128093
2022-06-30 06:28:42 +02:00
Daniel Bertalan 8d29f0fdb9 [lld-macho] Emit REBASE_OPCODE_ADD_ADDR_IMM_SCALED if possible
An ADD_ADDR rebase opcode's argument can be encoded as an immediate if
the offset is less than 15 * word size. This change reduces the size of
chromium_framework by 100+ KiB.

Differential Revision: https://reviews.llvm.org/D128798
2022-06-29 22:28:39 +02:00
Kazu Hirata 586fb81eee [lld] Don't use Optional::hasValue (NFC)
This patch replaces x.hasValue() with x where x is contextually
convertible to bool.
2022-06-26 19:37:14 -07:00
Kazu Hirata 3b7c3a654c Revert "Don't use Optional::hasValue (NFC)"
This reverts commit aa8feeefd3.
2022-06-25 11:56:50 -07:00
Kazu Hirata aa8feeefd3 Don't use Optional::hasValue (NFC) 2022-06-25 11:55:57 -07:00
Nico Weber a2c1f7c90d [lld, ELF and mac] Add --time-trace=<file>, remove --time-trace-file=<file>
`--time-trace=foo` has the same behavior as `--time-trace --time-trace-file=<file>`
had previously.

Also, for mac, make --time-trace-granularity *not* imply --time-trace, to match
behavior of the ELF port.

Differential Revision: https://reviews.llvm.org/D128451
2022-06-23 15:46:22 -04:00
Nico Weber 0ec87addb7 [lld/mac] Add a few TimeTraceScopes
Identical literal folding takes ~1.4% of the time, and was missing
from the trace.

Signature computation still needs ~2.2% of the time, so probably worth
explicitly marking its contribution to "Write output file" (9.1%)

Differential Revision: https://reviews.llvm.org/D128343
2022-06-23 11:46:57 -04:00
Daniel Bertalan ed39fd515a [lld-macho] Use source information in duplicate symbol errors
Similarly to how undefined symbol diagnostics were changed in D128184,
we now show where in the source file duplicate symbols are defined at:

  ld64.lld: error: duplicate symbol: _foo
  >> defined in bar.c:42
  >>            /path/to/bar.o
  >> defined in baz.c:1
  >>            /path/to/libbaz.a(baz.o)

For objects that don't contain DWARF data, the format is unchanged.

A slight difference to undefined symbol diagnostics is that we don't
print the name of the symbol on the third line, as it's already
contained on the first line.

Differential Revision: https://reviews.llvm.org/D128425
2022-06-23 11:07:15 -04:00
Fangrui Song 20b2d3260d [lld-macho] Work around odr-use of const non-inline static data member to fix -O0 build after D128298
```
ld.lld: error: undefined symbol: lld::macho::CodeSignatureSection::blockSize
>>> referenced by SyntheticSections.cpp:1253 (/home/maskray/llvm/lld/MachO/SyntheticSections.cpp:1253)
>>>               tools/lld/MachO/CMakeFiles/lldMachO.dir/SyntheticSections.cpp.o:(lld::macho::CodeSignatureSection::writeHashes(unsigned char*) const::$_7::operator()(unsigned long) const)
```
2022-06-21 19:22:28 -07:00
Nico Weber 0baf13e282 [lld/mac] Parallelize code signature computation
According to ministat, this is a small but measurable speedup
(using the repro in PR56121):

    N           Min           Max        Median           Avg        Stddev
x  10     3.7439518     3.7783802     3.7730219     3.7655502   0.012375226
+  10     3.6149218      3.692198     3.6519327     3.6502951   0.025905601
Difference at 95.0% confidence
	-0.115255 +/- 0.0190746
	-3.06078% +/- 0.506554%
	(Student's t, pooled s = 0.0203008)

(Without 858e8b17f7, this change here to use parallelFor is an 18% speedup,
and doing 858e8b17f7 on top of this change is just a 2.55% +/- 0.58% win.
Doing both results in a total speedup of 20.85% +/- 0.44%.)

Differential Revision: https://reviews.llvm.org/D128298
2022-06-21 20:41:35 -04:00
Daniel Bertalan 5792797c5b Reland "[lld-macho] Show source information for undefined references"
The error used to look like this:

  ld64.lld: error: undefined symbol: _foo
  >>> referenced by /path/to/bar.o:(symbol _baz+0x4)

If DWARF line information is available, we now show where in the source
the references are coming from:

  ld64.lld: error: unreferenced symbol: _foo
  >>> referenced by: bar.cpp:42 (/path/to/bar.cpp:42)
  >>>                /path/to/bar.o:(symbol _baz+0x4)

The reland is identical to the first time this landed. The fix was in D128294.
This reverts commit 0cc7ad4175.

Differential Revision: https://reviews.llvm.org/D128184
2022-06-21 18:50:06 -04:00
Daniel Bertalan 77b6efbd82 [ADT] [lld-macho] Check for end iterator deref in filter_iterator_base
If ld64.lld was supplied an object file that had a `__debug_abbrev` or
`__debug_str` section, but didn't have any compile unit DIEs in
`__debug_info`, it would dereference an iterator pointing to the empty
array of DIEs. This underlying issue started causing segmentation faults
when parsing for `__debug_info` was addded in D128184. That commit was
reverted, and this one fixes the invalid dereference to allow relanding
it.

This commit adds an assertion to `filter_iterator_base`'s dereference
operators to catch bugs like this one.

Ran check-llvm, check-clang and check-lld.

Differential Revision: https://reviews.llvm.org/D128294
2022-06-21 15:47:45 -04:00
Nico Weber 3ade3d3724 [lld/mac] Replace while loop with for loop
No behavior change. In preparation for using a parallelFor() here.

Differential Revision: https://reviews.llvm.org/D128295
2022-06-21 15:42:06 -04:00
Nico Weber 858e8b17f7 [lld/mac] On Apple systems, call CC_SHA256 from libSystem
It's in libSystem, so it doesn't bring in any new deps, and it's
currently much faster than LLVM's current SHA256 implementation.

Makes linking (arm64) Chromium Framework with ld64.lld 17% faster.
See also PR56121.

No behavior change.

Differential Revision: https://reviews.llvm.org/D128290
2022-06-21 14:58:04 -04:00
Nico Weber ca25baee7e [lld/mac] Extract a sha256() function
No behavior change.

Differential Revision: https://reviews.llvm.org/D128289
2022-06-21 14:02:42 -04:00
Nico Weber 0cc7ad4175 Revert "[lld-macho] Show source information for undefined references"
This reverts commit cd7624f153.
See https://reviews.llvm.org/D128184#3597534
2022-06-20 19:15:57 -04:00
Daniel Bertalan cd7624f153 [lld-macho] Show source information for undefined references
The error used to look like this:

  ld64.lld: error: undefined symbol: _foo
  >>> referenced by /path/to/bar.o:(symbol _baz+0x4)

If DWARF line information is available, we now show where in the source
the references are coming from:

  ld64.lld: error: unreferenced symbol: _foo
  >>> referenced by: bar.cpp:42 (/path/to/bar.cpp:42)
  >>>                /path/to/bar.o:(symbol _baz+0x4)

Differential Revision: https://reviews.llvm.org/D128184
2022-06-20 18:49:42 -04:00
Nico Weber 7effcbda49 Rename parallelForEachN to just parallelFor
Patch created by running:

  rg -l parallelForEachN | xargs sed -i '' -c 's/parallelForEachN/parallelFor/'

No behavior change.

Differential Revision: https://reviews.llvm.org/D128140
2022-06-19 17:49:00 -04:00
Kazu Hirata 757d9d22cd [lld] Use value_or instead of getValueOr (NFC) 2022-06-19 00:29:41 -07:00
Corentin Jabot b62e3a73e1 Replace to_hexString by touhexstr [NFC]
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-06-16 17:29:50 +02:00
Daniel Bertalan 0eec7e2a89 Reland "[lld-macho] Group undefined symbol diagnostics by symbol".
This reverts commit 36e7c9a450.

This relands d61341768c with the fix described in
https://reviews.llvm.org/D127753#3587390
2022-06-15 19:22:39 -04:00
Stella Stamenova 36e7c9a450 Revert "[lld-macho] Group undefined symbol diagnostics by symbol"
This reverts commit d61341768c.

This change broke multiple lld tests, including some sanitizer builds: https://lab.llvm.org/buildbot/#/builders/5/builds/24787/steps/19/logs/stdio
2022-06-15 15:42:26 -07:00
Keith Smiley 272bf0fc41
[lld-macho] Add support for exporting no symbols
As an optimization for ld64 sometimes it can be useful to not export any
symbols for top level binaries that don't need any exports, to do this
you can pass `-exported_symbols_list /dev/null`, or new with Xcode 14
(ld64 816) there is a `-no_exported_symbols` flag for the same behavior.
This reproduces this behavior where previously an empty exported symbols
list file would have been ignored.

Differential Revision: https://reviews.llvm.org/D127562
2022-06-15 15:07:27 -07:00
Daniel Bertalan d61341768c [lld-macho] Group undefined symbol diagnostics by symbol
ld64.lld used to print the "undefined symbol" line for each reference to
an undefined symbol previously:

  ld64.lld: error: undefined symbol: _foo
  >>> referenced by /path/to/bar.o:(symbol _baz+0x0)

  ld64.lld: error: undefined symbol: _foo
  >>> referenced by /path/to/bar.o:(symbol _quux+0x1)

Now they are deduplicated:

  ld64.lld: error: undefined symbol: _foo
  >>> referenced by /path/to/bar.o:(symbol _baz+0x0)
  >>> referenced by /path/to/bar.o:(symbol _quux+0x1)

As with the other lld ports, only the first 3 references are printed.

Differential Revision: https://reviews.llvm.org/D127753
2022-06-14 16:38:11 -04:00
Daniel Bertalan f2e92cf60e [lld-macho] Print the name of functions containing undefined references
The error used to look like this:

  ld64.lld: error: undefined symbol: _foo
  >>> referenced by /path/to/bar.o

Now it displays the name of the function that contains the undefined
reference as well:

  ld64.lld: error: undefined symbol: _foo
  >>> referenced by /path/to/bar.o:(symbol _baz+0x4)

Differential Revision: https://reviews.llvm.org/D127696
2022-06-14 09:41:28 -04:00
Daniel Bertalan 5f627cc225 [lld-macho] Fix symbol name returned from InputSection::getLocation
This commit fixes the issue that getLocation always printed the name of
the first symbol in the section.

For clarity, upper_bound is used instead of a linear search for finding
the closest symbol name. Note that this change does not affect
performance: this function is only called when printing errors and
`symbols` typically contains a single symbol because of
.subsections_via_symbols.

Differential Revision: https://reviews.llvm.org/D127670
2022-06-13 15:49:27 -04:00
Jez Ng b422dac240 [lld-macho][reland] Support EH frames under arm64
This reverts commit 10641a42e2.

Differential Revision: https://reviews.llvm.org/D124561
2022-06-13 07:45:27 -04:00
Jez Ng e183bf8e15 [lld-macho][reland] Initial support for EH Frames
This reverts commit 942f4e3a7c.

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
Jez Ng d378268ead [lld-macho] Make `--icf=safe` work with LTO
Just matter of enabling the config option.

(Also changed the platform of the input test file to macOS, since that's
the default that we specify in the `%lld` substitution. The conflict was
causing errors when linking with LTO.)

Reviewed By: #lld-macho, thakis

Differential Revision: https://reviews.llvm.org/D127600
2022-06-12 17:26:08 -04:00
Keith Smiley 7d57c69826
[lld-macho] Add support for -w
This flag suppresses warnings produced by the linker. In ld64 this has
an interesting interaction with -fatal_warnings, it silences the
warnings but the link still fails. Instead of doing that here we still
print the warning and eagerly fail the link in case both are passed,
this seems more reasonable so users can understand why the link fails.

Differential Revision: https://reviews.llvm.org/D127564
2022-06-11 17:38:50 -07:00
Douglas Yung 942f4e3a7c Revert "[lld-macho] Initial support for EH Frames"
This reverts commit 826be330af.

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
Douglas Yung 10641a42e2 Revert "[lld-macho] Support EH frames under arm64"
This reverts commit 977d62c33e.

This change was causing crashes in 2 tests on the buildbots:
  - https://lab.llvm.org/buildbot/#/builders/58/builds/23914
  - https://lab.llvm.org/buildbot/#/builders/36/builds/21771
2022-06-09 05:24:28 -07:00
Jez Ng 977d62c33e [lld-macho] Support EH frames under arm64
For arm64, llvm-mc emits relocations for the target function
address like so:

  ltmp:
    <CIE start>
    ...
    <CIE end>
    ... multiple FDEs ...
    <FDE start>
    <target function address - (ltmp + pcrel offset)>
    ...

If any of the FDEs in `multiple FDEs` get dead-stripped, then `FDE start`
will move to an earlier address, and `ltmp + pcrel offset` will no longer
reflect an accurate pcrel value. To avoid this problem, we "canonicalize"
our relocation by adding an `EH_Frame` symbol at `FDE start`, and updating
the reloc to be `target function address - (EH_Frame + new pcrel offset)`.

Reviewed By: #lld-macho, Roger

Differential Revision: https://reviews.llvm.org/D124561
2022-06-08 23:41:29 -04: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
Michael Eisel 44978a234b [lld/mac] Write output sections in parallel
This reduces linking time by ~8% for my project (1.19s -> 0.53s for
writeSections()). writeTo is const, which bodes well for it being
parallelizable, and I've looked through the different overridden versions and
can't see any race conditions. It produces the same byte-for-byte output for my
project.

Differential Revision: https://reviews.llvm.org/D126800
2022-06-08 20:11:50 -04:00
Vy Nguyen 66bd14697b [lld-macho] Demangle symbol names in duplicate-symbol error when -demangle is specified
Differential Revision: https://reviews.llvm.org/D127110
2022-06-06 15:12:26 -04:00
Vy Nguyen 82de9bb66b [lld-macho] Addressed additional post-commit comments from D126046
- fixed newlines
- renamed helper function for clarity
- added additional comment

Differential Revision: https://reviews.llvm.org/D126792
2022-06-03 15:48:11 -04:00
Nico Weber 815825f442 [lld/mac] clang-format after f5709066e3 2022-06-01 14:53:08 -04:00
Michael Eisel f5709066e3 [lld/mac] Cache file IDs of symbols in emitStabs for faster sorting
This reduces the time emitStabs() takes by about 275ms, or 3% of overall
linking time for the project I'm on. Although the parent function is run in
parallel, it's one of the slowest tasks in that concurrent batch (I have
another optimization for another slow task as well).

Differential Revision: https://reviews.llvm.org/D126785
2022-06-01 14:51:34 -04:00
Vy Nguyen fae6bd7563 [lld-macho] Support -non_global_symbols_strip_list, -non_global_symbols_no_strip_list, -x
PR/55600

Differential Revision: https://reviews.llvm.org/D126046
2022-05-25 19:22:04 +07:00
Vy Nguyen c0ec1036d6 [lld-macho][nfc] Run clang-format on lld/MachO/*.{h,cpp}
- fixed inconsistent indents and spaces
- prevent extraneous formatting changes in other patches

Differential Revision: https://reviews.llvm.org/D126262
2022-05-24 08:36:20 +07:00
Alex Brachet 190b0f42cf [lld-macho] Stop crash when emitting personalities with -dead_strip
The <internal> symbol was tripping an assertion in getVA() because it
was not marked as used. Per the comment above that symbols creation,
dead stripping has already occurred so marking this symbol as used is
accurate.

Fixes https://github.com/llvm/llvm-project/issues/55565

Differential revision: https://reviews.llvm.org/D126072
2022-05-20 21:40:47 +00:00
Vy Nguyen 4c5b187f2c [lld-macho] Demangle symbol names in export-symbol error messages when -demangle is specified.
PR/55512

Reviewed By: keith

Differential Revision: https://reviews.llvm.org/D125732
2022-05-16 19:48:03 -04:00
Tapan Thaker d64bad8ff1
[lld/macho] Fixes the -ObjC flag
When checking the segment name for Swift symbols, we should be checking that they start with `__swift` instead of checking for equality

Fixes the issue https://github.com/llvm/llvm-project/issues/55355

Reviewed By: #lld-macho, keith, thevinster

Differential Revision: https://reviews.llvm.org/D125250
2022-05-11 17:00:39 -07:00
Nico Weber 895a72111b [lld/mac] Support writing zippered dylibs and bundles
With -platform_version flags for two distinct platforms,
this writes a LC_BUILD_VERSION header for each.

The motivation is that this is needed for self-hosting with lld as linker
after D124059.

To create a zippered output at the clang driver level, pass

    -target arm64-apple-macos -darwin-target-variant arm64-apple-ios-macabi

to create a zippered dylib.

(In Xcode's clang, `-darwin-target-variant` is spelled just `-target-variant`.)

(If you pass `-target arm64-apple-ios-macabi -target-variant arm64-apple-macos`
instead, ld64 crashes!)

This results in two -platform_version flags being passed to the linker.

ld64 also verifies that the iOS SDK version is at least 13.1. We don't do that
yet. But ld64 also does that for other platforms and we don't. So we need to
do that at some point, but not in this patch.

Only dylib and bundle outputs can be zippered.

I verified that a Catalyst app linked against a dylib created with

    clang -shared foo.cc -o libfoo.dylib \
          -target arm64-apple-macos \
          -target-variant arm64-apple-ios-macabi \
          -Wl,-install_name,@rpath/libfoo.dylib \
          -fuse-ld=$PWD/out/gn/bin/ld64.lld

runs successfully. (The app calls a function `f()` in libfoo.dylib
that returns a const char* "foo", and NSLog(@"%s")s it.)

ld64 is a bit more permissive when writing zippered outputs,
see references to "unzippered twins". That's not implemented yet.
(If anybody wants to implement that, D124275 is a good start.)

Differential Revision: https://reviews.llvm.org/D124887
2022-05-04 19:23:35 -04:00
Alex Borcan e29dc0c6fd [lld] Implement safe icf for MachO
This change implements --icf=safe for MachO based on addrsig section that is implemented in D123751.

Reviewed By: int3, #lld-macho

Differential Revision: https://reviews.llvm.org/D123752
2022-05-03 21:01:03 -04:00
Nico Weber 010acc52a8 [lld/mac] Revert libcompiler_rt.dylib version check change
This reverts D117925 since it's no longer needed after D124336.

Differential Revision: https://reviews.llvm.org/D124354
2022-04-25 06:55:49 -04:00