MachOPlatformRuntimeState::lookupSymbols encapsulates the approach used in
dlsym in bb41fc682ee, 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 f448d44663a 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.
1dcff823db9 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.
b1356504e63 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",
...?).
089acf25223 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 ef391df2b6332, c0d889995e708, and
37f1b7a3f35fd.
This is an ORC-runtime counterpart to LLVM commit ef391df2b63, 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.
This reverts commit 6b2a96285b9bbe92d2c5e21830f21458f8be976d.
The ccache builders are still failing. Looks like they need to be updated to
get the llvm-zorg config change in 490633945677656ba75d42ff1ca9d4a400b7b243.
I'll re-apply this as soon as the builders are updated.
This reapplies commit a7733e9556b5a6334c910f88bcd037e84e17e3fc ("Re-apply
[ORC][ORC-RT] Add initial native-TLV support to MachOPlatform."), and
d4abdefc998a1ee19d5edc79ec233774cbf64f6a ("[ORC-RT] Rename macho_tlv.x86-64.s
to macho_tlv.x86-64.S (uppercase suffix)").
These patches were reverted in 48aa82cacbff10e1c5395a03f86488bf449ba4da while I
investigated bot failures (e.g.
https://lab.llvm.org/buildbot/#/builders/109/builds/18981). The fix was to
disable building of the ORC runtime on buliders using ccache (which is the same
fix used for other compiler-rt projects containing assembly code). This fix was
commited to llvm-zorg in 490633945677656ba75d42ff1ca9d4a400b7b243.
This reverts commit d4abdefc998a1ee19d5edc79ec233774cbf64f6a ("[ORC-RT] Rename
macho_tlv.x86-64.s to macho_tlv.x86-64.S (uppercase suffix)", and
a7733e9556b5a6334c910f88bcd037e84e17e3fc ("Re-apply "[ORC][ORC-RT] Add initial
native-TLV support to MachOPlatform."), while I investigate failures on
ccache builders (e.g. https://lab.llvm.org/buildbot/#/builders/109/builds/18981)
Reapplies fe1fa43f16beac1506a2e73a9f7b3c81179744eb, which was reverted in
6d8c63946cc259c0af02584b7cc690dde11dea35, with fixes:
1. Remove .subsections_via_symbols directive from macho_tlv.x86-64.s (it's
not needed here anyway).
2. Return error from pthread_key_create to the MachOPlatform to silence unused
variable warning.
Adds code to LLVM (MachOPlatform) and the ORC runtime to support native MachO
thread local variables. Adding new TLVs to a JITDylib at runtime is supported.
On the LLVM side MachOPlatform is updated to:
1. Identify thread local variables in the LinkGraph and lower them to GOT
accesses to data in the __thread_data or __thread_bss sections.
2. Merge and report the address range of __thread_data and thread_bss sections
to the runtime.
On the ORC runtime a MachOTLVManager class introduced which records the address
range of thread data/bss sections, and creates thread-local instances from the
initial data on demand. An orc-runtime specific tlv_get_addr implementation is
included which saves all register state then calls the MachOTLVManager to get
the address of the requested variable for the current thread.
Adds support for MachO static initializers/deinitializers and eh-frame
registration via the ORC runtime.
This commit introduces cooperative support code into the ORC runtime and ORC
LLVM libraries (especially the MachOPlatform class) to support macho runtime
features for JIT'd code. This commit introduces support for static
initializers, static destructors (via cxa_atexit interposition), and eh-frame
registration. Near-future commits will add support for MachO native
thread-local variables, and language runtime registration (e.g. for Objective-C
and Swift).
The llvm-jitlink tool is updated to use the ORC runtime where available, and
regression tests for the new MachOPlatform support are added to compiler-rt.
Notable changes on the ORC runtime side:
1. The new macho_platform.h / macho_platform.cpp files contain the bulk of the
runtime-side support. This includes eh-frame registration; jit versions of
dlopen, dlsym, and dlclose; a cxa_atexit interpose to record static destructors,
and an '__orc_rt_macho_run_program' function that defines running a JIT'd MachO
program in terms of the jit- dlopen/dlsym/dlclose functions.
2. Replaces JITTargetAddress (and casting operations) with ExecutorAddress
(copied from LLVM) to improve type-safety of address management.
3. Adds serialization support for ExecutorAddress and unordered_map types to
the runtime-side Simple Packed Serialization code.
4. Adds orc-runtime regression tests to ensure that static initializers and
cxa-atexit interposes work as expected.
Notable changes on the LLVM side:
1. The MachOPlatform class is updated to:
1.1. Load the ORC runtime into the ExecutionSession.
1.2. Set up standard aliases for macho-specific runtime functions. E.g.
___cxa_atexit -> ___orc_rt_macho_cxa_atexit.
1.3. Install the MachOPlatformPlugin to scrape LinkGraphs for information
needed to support MachO features (e.g. eh-frames, mod-inits), and
communicate this information to the runtime.
1.4. Provide entry-points that the runtime can call to request initializers,
perform symbol lookup, and request deinitialiers (the latter is
implemented as an empty placeholder as macho object deinits are rarely
used).
1.5. Create a MachO header object for each JITDylib (defining the __mh_header
and __dso_handle symbols).
2. The llvm-jitlink tool (and llvm-jitlink-executor) are updated to use the
runtime when available.
3. A `lookupInitSymbolsAsync` method is added to the Platform base class. This
can be used to issue an async lookup for initializer symbols. The existing
`lookupInitSymbols` method is retained (the GenericIRPlatform code is still
using it), but is deprecated and will be removed soon.
4. JIT-dispatch support code is added to ExecutorProcessControl.
The JIT-dispatch system allows handlers in the JIT process to be associated with
'tag' symbols in the executor, and allows the executor to make remote procedure
calls back to the JIT process (via __orc_rt_jit_dispatch) using those tags.
The primary use case is ORC runtime code that needs to call bakc to handlers in
orc::Platform subclasses. E.g. __orc_rt_macho_jit_dlopen calling back to
MachOPlatform::rt_getInitializers using __orc_rt_macho_get_initializers_tag.
(The system is generic however, and could be used by non-runtime code).
The new ExecutorProcessControl::JITDispatchInfo struct provides the address
(in the executor) of the jit-dispatch function and a jit-dispatch context
object, and implementations of the dispatch function are added to
SelfExecutorProcessControl and OrcRPCExecutorProcessControl.
5. OrcRPCTPCServer is updated to support JIT-dispatch calls over ORC-RPC.
6. Serialization support for StringMap is added to the LLVM-side Simple Packed
Serialization code.
7. A JITLink::allocateBuffer operation is introduced to allocate writable memory
attached to the graph. This is used by the MachO header synthesis code, and will
be generically useful for other clients who want to create new graph content
from scratch.