Re-enables compact-unwind support in JITLink, which was reverted in b04847b427
due to buildbot failures.
The underlying cause for the failures on the buildbots was the lack of
compact-unwind registration support on older Darwin OSes. Since the
CompactUnwindManager pass now removes eh-frames by default we were left with
unwind-info that could not be registered. On x86-64, where eh-frame info is
produced by default the solution is to fall back to using eh-frames. On arm64
we simply can't support exceptions on older OSes.
This patch updates the EHFrameRegistrationPlugin to remove the compact-unwind
section (__LD,__compact_unwind) when installed, forcing use of eh-frames when
the EHFrameRegistrationPlugin is used. In LLJIT, the EHFrameRegistrationPlugin
continues to be used for all non-Darwin platform, and will be added on Darwin
platforms when the a CompactUnwindRegistrationPlugin instance can't be created
(e.g. due to missing support for compact-unwind info registration).
The lit.cfg.py script is updated to check whether the host OSes default unwind
info supports JIT registration, allowing tests to be disabled for older Darwin
OSes on arm64.
This reverts 4f0325873f and follow-up patches
(see below) while I investigate some ongoing failures on the buildbots.
---
Revert "[clang-repl] Try to XFAIL testcase on arm32 without affecting arm64
darwin."
This reverts commit fd174f0ff3.
Revert "[clang-repl] The simple-exception test now passes on arm64-darwin."
This reverts commit c9bc242e38.
Revert "[ORC] Destroy defunct MaterializationUnits outside the session lock."
This reverts commit a001cc0e6c.
Revert "[ORC] Add explicit narrowing casts to fix build errors."
This reverts commit 26fc07d5d8.
Revert "[ORC] Enable JIT support for the compact-unwind frame info format on
Darwin."
This reverts commit 4f0325873f.
For Darwin/arm64 (including Apple Silicon Macs) this will enable exception
handling and stack unwinding in JIT'd code.
Darwin supports two unwind-info formats: DWARF eh-frames and compact-unwind. On
Darwin/x86-64 compilers usually produce both by default, and ORC supported
exceptions and unwinding via eh-frames (same as on Linux), discarding the
redundant compact-unwind info. On Darwin/arm64 compilers typically default to
producing compact-unwind only, with DWARF eh-frames as a fallback for functions
that can't be described in compact-unwind. Since ORC did not previously support
the compact-unwind format and eh-frames were not present ORC was unable to
handle exceptions or unwinding by default in Darwin/arm64 JIT'd code.
This patch enables support for the compact-unwind-info format, and contains
three major moving parts:
(1) The JITLink CompactUnwindManager class is responsible for transforming the
__compact_unwind records produced by the linker into the __unwind_info
tables that libunwind parses during unwinding. To enable this the
CompactUnwindManager class provides three JITLink passes: The
prepareForPrune pass that splits the __compact_unwind section into
single-record blocks, allowing unused records to be dead-stripped; the
processAndReserveUnwindInfo pass that reserves space for the final
__unwind_info section, and the writeUnwindInfo pass that writes the
__unwind_info section.
(2) The OrcTargetProcess UnwindInfoManager class maintains a table of
registered JIT'd __unwind_info and __eh_frame sections, and handles
requests from libunwind for unwind info sections (by registering a callback
with libunwind's __unw_add_find_dynamic_unwind_sections function).
(3) The Orc UnwindInfoRegistrationPlugin, which scans LinkGraphs for
__unwind_info and __eh_frame sections to register with the
UnwindInfoManager.
This commit adds the CompactUnwindManager passes to the default JITLink
pipelines for Darwin/arm64 and Darwin/x86-64, and UnwindInfoManager intances to
the SelfExecutorProcessControl class (when built for apple platforms) and the
llvm-jitlink-executor tool.
The LLJIT class will now create an UnwindInfoRegistrationPlugin when targeting
a process running on Darwin if it detects that an UnwindInfoManager is
available to handle the registrations.
The ORC runtime macho_platform class already supported libunwind callbacks, so
out-of-process execution and unwinding support will work when loading the ORC
runtime.
The llvm-jitlink tool will only support compact-unwind when the orc-runtime is
loaded, as the UnwindInfoRegistrationPlugin requires access to an IR compiler
to load a helper module and llvm-jitlink does not provide an IR compiler.
With the help of @lhames, this PR introduces a push-request model to manage
initializers in the runtime state for each `JITDylib`, similar to how `MachO`
and `COFF` handle it. Previously, the ELF runtime lacked the ability to
register, deregister, or retain initializers, causing issues when re-running
`dlopen`. Initializers were erased after `rt_getInitializers` was used.
To address this, we introduce `__orc_rt_elfnix_register_init_sections` and
`__orc_rt_elfnix_register_jitdylib` (and corresponding deregister functions).
This model allows the runtime to request the push of initializers for the
`JITDylib`, with the platform handling this via a record method. Additionally,
we leverage `MachO`'s `RecordSectionsTracker` to store initializers, ensuring
only newly updated initializers are executed using `processNewSections`,
improving the runtime's efficiency and reliability.
With the help of @lhames, This pull request introduces the `dlupdate`
function in the ORC runtime. `dlupdate` enables incremental execution of
new initializers introduced in the REPL environment. Unlike traditional
`dlopen`, which manages initializers, code mapping, and library
reference counts, `dlupdate` focuses exclusively on running new
initializers.
This reapplies commits 462251b80b and 9b67c99dc5, which were reverted in
53d35c4e86 due to bot failures for the wrapper_function_utils_test.cpp unit
test.
This decouples function argument serialization / deserialization from the
function call dispatch mechanism. This will eventually allow us to replace the
existing __orc_rt_jit_dispatch function with a system that supports pre-linking
parts of the ORC runtime into the executor.
We should use `orc_rt` as the public C++ API namespace for the ORC runtime and
control symbol visibility to hide implementation details, rather than rely on
the '__' prefix.
Similar to what was already done for static initializers, we need to
unlock the state mutext when calling out to libobjc to run +load methods
in case they cause us to reenter the runtime, which was previously
deadlocking. No test for now, because we don't have any code paths in
llvm-jitlink itself that could lead to this deadlock. If we interpose
calls to dlopen to go back to the JIT in the future then calling dlopen
from a +load is the easiest way to reproduce this.
rdar://133430490
MachOPlatformRuntimeState::lookupSymbols encapsulates the approach used in
dlsym in bb41fc682e, but generalizes it to multiple symbols:
1. try to resolve symbols locally
2. issue a push-request for any unresolved symbols
3. re-try local resolution
In the future lookupSymbols can serve as the basis for a public bulk lookup
API in the ORC runtime.
1. Prevent deadlock by unlocking JDStatesMutex when calling back to the
controller to request a push of new symbols. (If JDStatesMutex is locked
then the push operation can't register the new symbols, and so can't
complete).
2. Record MachOPlatform runtime symbols during bootstrap and attach their
registration to the bootstrap-completion graph, similar to the way that
deferred allocation actions are handled. We can't register the symbols
the normal way during bootstrap since the symbol registration function is
itself in the process of being materialized.
3. Add dlsym testcases to exercise these fixes.
Adds symbol tables to the JITDylibState struct in the ORC runtime
MachOPlatformRuntimeState class. This table will hold the addresses of
materialized symbols (registered by a new JITLink pass in MachOPlatform),
allowing these to be looked up in the executor without an IPC request to the
controller.
The old lookup-symbols callback (made by the runtime in response to dlsym
lookups) is replaced with a push-symbols callback that can trigger
materialization of requested symbols.
Holding a symbol table on the executor side should make repeat calls to dlsym
(and other symbol lookup operations) cheaper since the IPC to trigger
materialization happens at most once per symbol. It should also enable us (at
some point in the future) to symbolicate backtraces in JIT'd code even if the
controller process is gone (e.g. detached or crashed). The trade-off for this
is increased memory consumption in the executor and larger JIT'd data transfers
(since symbol names are now transferred to the executor unconditionally, even
though they may never be used).
In f448d44663 we switched to calling _objc_map_images and _objc_load_images
for MachO language metadata registration. This patch fixes some bugs arising
from that change:
(1) __objc_imageinfo processing was moved to a post-allocation pass, but this
prevents us from discarding the redundant copies. This commit moves
processing back to a pre-prune pass and inserts a symbol for the uniqued
__objc_image section. Runtime objects use an edge pointing to this symbol
to access the address.
(2) We were assuming that _objc_map_images & _objc_load_images were available
in the Objective-C runtime on 10.15, but these functions didn't become
available until later. This commit bumps the macOS version requirement to
13.1 where the functions should be available.
(3) The ORC-RT trivial-swift-types-section.S test was missing an
__objc_unwindinfo section, which triggered an assert that should have
been an error. The assert has been turned into an error, and the testcase
has been updated to include an __objc_imageinfo.
rdar://107846455
This patch drops the individual registration calls to the ObjC and Swift
runtimes (for selectors, classes, etc.), and instead creates a Mach header and
load commands that can be passed to _objc_map_images and _objc_load_images to
trigger registration and execution of +load methods. This approach supports
categories (for which there is no current registration API), and more closely
follows dyld's ObjC & Swift registration path.
The '__' prefix should only be used for the parts of the ORC runtime that
implement compiler / loader runtime details (e.g. ORC-RT's __tlv_get_addr
implementations).
This patch only fixes the public API. Future changes will fix internal names.
The UseCallbackStyleUnwindInfo flag already captures the original conditional,
and using the flag everywhere makes it easier to switch registration styles
when debugging.
In LLVM the MachOPlatform class is modified to identify unwind info sections
and the address ranges of the functions these sections cover. These address
ranges are then communicated to the ORC runtime by attaching them to the
register-object-platform-sections allocation action.
In the ORC runtime the unwind-info section addresses are recorded and used to
support lookup of unwind info via the new `findDynamicUnwindSections` function.
At bootstrap time the ORC runtime checks for the presence of new
unwind-info-lookup-registration functions in libunwind (see
https://reviews.llvm.org/D142176), and if available uses them to register the
`findDynamicUnwindSections` function with libunwind to enable callback-based
lookup. If the new unwind-info-lookup-registration functions are not available
then the ORC runtime falls back to using the existing libunwind registration
APIs.
The callback-based scheme is intended to address three shortcomings in the
current registration scheme for JIT'd unwind info on Darwin: (1) Lack of
compact-unwind support, (2) inability to describe the subarchitecture of JIT'd
frames, and (3) lack of efficient address-based lookup data structures in
libunwind.
For more details see the proposed libunwind changes in
https://reviews.llvm.org/D142176.
IntervalMap is an optionally-coalescing map -- it uses half-open ranges as keys,
allows lookups based on elements of the ranges (returning an iterator to the
containing range) and optionally coalesces adjacent ranges that have the same
value.
IntervalSet is an optionally-coalescing set based on IntervalMap.
These collections will be used to store and lookup metadata section ranges,
e.g. unwind-info ranges.
This patch modifies the MachOPlatform bootstrap process to record allocation
actions for ORC runtime platform support code in a "deferred actions" vector
rather than attaching it to the corresponding LinkGraphs up-front. The deferred
allocation-actions are run after all the platform support code has been loaded
by attaching them to a separate "bootstrap-complete" graph.
This change should allow the mach-o platform support code in the ORC runtime to
use advanced mach-o platform features (e.g. static inits, TLVs), provided that
the support code does not use these features at runtime before the bootstrap
process completes, or after the shutdown process starts. This is a nice
improvement in and of itself but is motivated by specific future plans: we
want to start recording unwind info in the mach-o platform state object*, and
the recording functions will have their own frame info that needs registering.
The deferred allocation-actions scheme allows for this.
* The plan is to add a new unwind-info-lookup path to libunwind to allow it to
call back to the ORC runtime to find unwind sections. This will simplify the
implementation of support for JIT'd compact-unwind info.
During __orc_rt_macho_jit_dlopen the ORC runtime will make a request to the JIT
to push any new initializers. Since this call may add new JD-state to the
runtime (and is expected to in general) we need to unlock the JDStatesMutex
during this operation (and similarly when running initializers and atexits, as
these may call trigger push-initializers recursively).
No testcase yet: I haven't been able to reproduce the deadlock when running
llvm-jitlink in in-process mode, and we don't support out-of-process mode in
regression tests yet.
Newly added sections can be processed by calling processNewSections. Calling
reset moves all sections back to the "new" state for reprocessing (expected to
be used by dlclose).
If we want to be able to close and then re-open a library then we need to reset
the data section states when the library is closed. This commit updates
MachOPlatform and the ORC runtime to track __data and __common sections, and
reset the state in MachOPlatformRuntimeState::dlcloseDeinitialize.
This is only a first step to full support -- there are other data sections that
we're not capturing, and we'll probably want a more efficient representation
for the sections (rather than passing their string name over IPC), but this is
a reasonable first step.
This commit also contains a fix to MapperJITLinkMemoryManager that prevents it
from calling OnDeallocated twice in the case of an error.
1dcff823db updated the ORC runtime to use std::string_view, rather than its
own placeholder class (__orc_rt::string_view), but failed to add these
includes.
b1356504e6 enabled the use of c++17 features in LLVM, which means that we can
drop the ORC runtime's placeholder string_view implemention in favor of
std::string_view.
The __swif5_proto and __swift5_protos sections had their meaning
inverted. Fix, and rename the arrays so it is more obvious which is
which.
Differential Revision: https://reviews.llvm.org/D131206
This patch updates the MachO platform (both the ORC MachOPlatform class and the
ORC-Runtime macho_platform.* files) to use allocation actions, rather than EPC
calls, to transfer the initializer information scraped from each linked object.
Interactions between the ORC and ORC-Runtime sides of the platform are
substantially redesigned to accomodate the change.
The high-level changes in this patch are:
1. The MachOPlatform::setupJITDylib method now calls into the runtime to set up
a dylib name <-> header mapping, and a dylib state object (JITDylibState).
2. The MachOPlatformPlugin builds an allocation action that calls the
__orc_rt_macho_register_object_platform_sections and
__orc_rt_macho_deregister_object_platform_sections functions in the runtime
to register the address ranges for all "interesting" sections in the object
being allocated (TLS data sections, initializers, language runtime metadata
sections, etc.).
3. The MachOPlatform::rt_getInitializers method (the entry point in the
controller for requests from the runtime for initializer information) is
replaced by MachOPlatform::rt_pushInitializers. The former returned a data
structure containing the "interesting" section address ranges, but these are
now handled by __orc_rt_macho_register_object_platform_sections. The new
rt_pushInitializers method first issues a lookup to trigger materialization
of the "interesting" sections, then returns the dylib dependence tree rooted
at the requested dylib for dlopen to consume. (The dylib dependence tree is
returned by rt_pushInitializers, rather than being handled by some dedicated
call, because rt_pushInitializers can alter the dependence tree).
The advantage of these changes (beyond the performance advantages of using
allocation actions) is that it moves more information about the materialized
portions of the JITDylib into the executor. This tends to make the runtime
easier to reason about, e.g. the implementation of dlopen in the runtime is now
recursive, rather than relying on recursive calls in the controller to build a
linear data structure for consumption by the runtime. This change can also make
some operations more efficient, e.g. JITDylibs can be dlclosed and then
re-dlopened without having to pull all initializers over from the controller
again.
In addition to the high-level changes, there are some low-level changes to ORC
and the runtime:
* In ORC, at ExecutionSession teardown time JITDylibs are now destroyed in
reverse creation order. This is on the assumption that the ORC runtime will be
loaded into an earlier dylib that will be used by later JITDylibs. This is a
short-term solution to crashes that arose during testing when the runtime was
torn down before its users. Longer term we will likely destroy dylibs in
dependence order.
* toSPSSerializable(Expected<T> E) is updated to explicitly initialize the T
value, allowing it to be used by Ts that have explicit constructors.
* The ORC runtime now (1) attempts to track ref-counts, and (2) distinguishes
not-yet-processed "interesting" sections from previously processed ones. (1)
is necessary for standard dlopen/dlclose emulation. (2) is intended as a step
towards better REPL support -- it should enable future runtime calls that
run only newly registered initializers ("dlopen_more", "dlopen_additions",
...?).
089acf2522 updated WrapperFunctionCall to carry arbitrary argument payloads
(rather than plain address ranges). This commit implements the corresponding
update for the ORC runtime.
Similar to how the other swift sections are registered by the ORC
runtime's macho platform, add the __swift5_types section, which contains
type metadata. Add a simple test that demonstrates that the swift
runtime recognized the registered types.
rdar://85358530
Differential Revision: https://reviews.llvm.org/D113811
The check was failing because it was matching against the end of the range, not
the start.
This bug wasn't causing the ORC-RT MachO TLV regression test to fail because
we were only logging deallocation errors (including TLV deregistration errors)
and not actually returning a failure code. This commit updates llvm-jitlink to
report the errors properly.
MachOPlatform used to make an EPC-call (registerObjectSections) to register the
eh-frame and thread-data sections for each linked object with the ORC runtime.
Now that JITLinkMemoryManager supports allocation actions we can use these
instead of an EPC call. This saves us one EPC-call per object linked, and
manages registration/deregistration in the executor, rather than the controller
process. In the future we may use this to allow JIT'd code in the executor to
outlive the controller object while still being able to be cleanly destroyed.
Since the code for allocation actions must be available when the actions are
run, and since the eh-frame registration code lives in the ORC runtime itself,
this change required that MachO eh-frame support be split out of
macho_platform.cpp and into its own macho_ehframe_registration.cpp file that has
no other dependencies. During bootstrap we start by forcing emission of
macho_ehframe_registration.cpp so that eh-frame registration is guaranteed to be
available for the rest of the bootstrap process. Then we load the rest of the
MachO-platform runtime support, erroring out if there is any attempt to use
TLVs. Once the bootstrap process is complete all subsequent code can use all
features.
We were writing a pointer to a selector string into the contents of a
string instead of overwriting the pointer to the string, leading to
corruption. This was causing non-deterministic failures of the
'trivial-objc-methods' test case.
Differential Revision: https://reviews.llvm.org/D112671
Renames StartAddress and EndAddress members to Start and End.
Adds contains and overlap methods.
Adds a constructor from an address and size.
These changes are counterparts to LLVM commits ef391df2b6, c0d889995e, and
37f1b7a3f3.
This is an ORC-runtime counterpart to LLVM commit ef391df2b6, and the
motivation is the same: to move to a shorter name to improve the ergonomics of
this type before it's more widely adopted.