For calloc, the variable denoting the of elements comes first,
then the variable denoting the size of each element. However, both
arguments are swapped when calling this function in many places in this codebase.
When possible, decode the DrainLock/ExecutionLock fields of tasks and actors in concurrency runtimes built with priority escalation, and show the corresponding thread info in swift-inspect output.
We weren't properly decoding actor flags previously, so fix that up as well and have Remote Mirror split them out into separate fields so clients don't have to. We were missing the Job Storage field from the definition of DefaultActorImpl in RuntimeInternals.h, fix that so we actually read the right data.
rdar://88598003
Have RemoteMirror internally decode these flags fields and return them as separate fields in the task/actor info. Handle the structures both with and without task escalation support.
Also show when a task is the current task on a thread in swift-inspect's task listing.
rdar://88598003
This adds a new reflection record type carrying spare bit information for multi-payload enums.
The compiler includes this for any type that might need it in order to accurately reflect the contents of the enum. The RemoteMirror library will use this if present to determine how to project the contents of the enum. If not present (for example, in older binaries), the RemoteMirror library falls back on an internal calculation of the spare bitmask.
A few notes:
* The internal calculation is not perfect. In particular, it does not support MPEs that contain other enums (e.g., optionals). It should accurately refuse to project any MPE that it does not correctly support.
* The new reflection field is designed to be expandable; this might someday avoid the need for a new section.
Resolves rdar://61158214
Most of the new inspection logic is in Remote Mirror. New code in swift-inspect calls the new Remote Mirror functions and formats the resulting information for display.
Specific Remote Mirror changes:
* Add a call to check if a given metadata is an actor.
* Add calls to get information about actors and tasks.
* Add a `readObj` call to MemoryReader that combines the read and the cast, greatly simplifying code chasing pointers in the remote process.
* Add a generalized facility to the C shims that can allocate a temporary object that remains valid until at least the next call, which is used to return various temporary arrays from the new calls. Remove the existing `lastString` and `lastChunks` member variables in favor of this new facility.
Swift-inspect changes:
* Add a new dump-concurrency command.
* Add a new `ConcurrencyDumper.swift` file with the implementation. The dumper needs to do some additional work with the results from Remote Mirror to build up the task tree and this keeps it all organized.
* Extend `Inspector` to query the target's threads and fetch each thread's current task.
Concurrency runtime changes:
* Add `_swift_concurrency_debug` variables pointing to the various future adapters. Remote Mirror uses these to provide a better view of a tasks's resume pointer.
rdar://85231338
We remove the existing `swift_reflection_iterateAsyncTaskAllocations` API that attempts to provide all necessary information about a tasks's allocations starting from the task. Instead, we split it into two pieces: `swift_reflection_asyncTaskSlabPointer` to get the first slab for a task, and `+swift_reflection_asyncTaskSlabAllocations` to get the allocations in a slab, and a pointer to the next slab.
We also add a dummy metadata pointer to the beginning of each slab. This allows tools to identify slab allocations on the heap without needing to locate every single async task object. They can then use `swift_reflection_asyncTaskSlabAllocations` on such allocations to find out about the contents.
rdar://82549631
We remove the existing `swift_reflection_iterateAsyncTaskAllocations` API that attempts to provide all necessary information about a tasks's allocations starting from the task. Instead, we split it into two pieces: `swift_reflection_asyncTaskSlabPointer` to get the first slab for a task, and `+swift_reflection_asyncTaskSlabAllocations` to get the allocations in a slab, and a pointer to the next slab.
We also add a dummy metadata pointer to the beginning of each slab. This allows tools to identify slab allocations on the heap without needing to locate every single async task object. They can then use `swift_reflection_asyncTaskSlabAllocations` on such allocations to find out about the contents.
rdar://82549631
We were missing a Status field. The reflect_task test didn't catch this becasue it was reading LastAllocation as FirstSlab, which still worked well enough in that context.
rdar://81427584
Added a counterpart to the swift_reflection_projectEnumValue() API for the
legacy interop support in SwiftRemoteMirrorLegacyInterop.h.
Also updated the test to use it to extract information from an enum.
rdar://62128103
Fix the declaration of AsyncTask and add a test for iterateAsyncTaskAllocations. Reflection's declaration of AsyncTask had fallen out of sync with the real thing. The test that was supposed to catch this was never actually committed, oops.
Add a swift_reflection_libraryVersion variable to Remote Mirror to indicate the presence of this fix. In the future, the value can be incremented to signal the presence of other changes that can't otherwise be detected.
rdar://80035307
This will allow the heap tool to work out which binary a dynamically allocated
class comes from, by looking up its nominal type descriptor address and then
seeing which binary contains that.
Fixes rdar://65742351.
Implement a version of projectExistential tailored for LLDB. There are 2
differences when projecting existentials for LLDB:
1 - When it comes to existentials, LLDB stores the address of the error
pointer, which must be dereferenced.
2 - When the existential wraps a class type, LLDB expects the address
returned is the class instance itself and not the address of the
reference.
This patch also adapts the swift reflection test machinery to test
projectExistentialAndUnwrapClass as well. This is done by exposing
the new functionality from swift reflection test. It is tested in
existentials.swift, and ensures that the typeref information is
exactly the same as what is expected from projectExistential,
except the out address.
(cherry picked from commit 55e971e06750c3ba29722d558cc5400298f6bdaf)
This code rearchitects and simplifies the projectEnumValue support by
introducing a new `TypeInfo` subclass for each kind of enum, including trivial,
no-payload, single-payload, and three different classes for multi-payload enums:
* "UnsupportedEnum" that we don't understand. This returns "don't know" answers for all requests in cases where the runtime lacks enough information to accurately handle a particular enum.
* MP Enums that only use a separate tag value. This includes generic enums and other dynamic layouts, as well as enums whose payloads have no spare bits.
* MP Enums that use spare bits, possibly in addition to a separate tag. This logic can only be used, of course, if we can in fact compute a spare bit mask that agrees with the compiler.
The final challenge is to choose one of the above three handlings for every MPE. Currently, we do not have an accurate source of information for the spare bit mask, so we never choose the third option above. We use the second option for dynamic MPE layouts (including generics) and the first for everything else.
TODO: Once we can arrange for the compiler to expose spare bit mask data, we'll be able to use that to drive more MPE cases.
ownsAddress was a simple range check on images, but that won't find Metadatas that get allocated on the heap. If an address isn't found, try reading it as a Metadata and doing a range check on the type context descriptor too.
rdar://problem/60981575
Teach RemoteMirror how to project enum values
This adds two new functions to the SwiftRemoteMirror
facility that support inspecting enum values.
Currently, these support non-payload enums and
single-payload enums, including nested enums and
payloads with struct, tuple, and reference payloads.
In particular, it handles nested `Optional` types.
TODO: Multi-payload enums use different strategies for
encoding the cases that aren't yet supported by this
code.
Note: This relies on information from dataLayoutQuery
to correctly decode invalid pointer values that are used
to encode enums. Existing clients will need to augment
their DLQ functions before using these new APIs.
Resolves rdar://59961527
```
/// Projects the value of an enum.
///
/// Takes the address and typeref for an enum and determines the
/// index of the currently-selected case within the enum.
///
/// Returns true iff the enum case could be successfully determined.
/// In particular, note that this code may fail for valid in-memory data
/// if the compiler is using a strategy we do not yet understand.
SWIFT_REMOTE_MIRROR_LINKAGE
int swift_reflection_projectEnumValue(SwiftReflectionContextRef ContextRef,
swift_addr_t EnumAddress,
swift_typeref_t EnumTypeRef,
uint64_t *CaseIndex);
/// Finds information about a particular enum case.
///
/// Given an enum typeref and index of a case, returns:
/// * Typeref of the associated payload or zero if there is no payload
/// * Name of the case if known.
///
/// The Name points to a freshly-allocated C string on the heap. You
/// are responsible for freeing the string (via `free()`) when you are finished.
SWIFT_REMOTE_MIRROR_LINKAGE
int swift_reflection_getEnumCaseTypeRef(SwiftReflectionContextRef ContextRef,
swift_typeref_t EnumTypeRef,
unsigned CaseIndex,
char **CaseName,
swift_typeref_t *PayloadTypeRef);
```
Co-authored-by: Mike Ash <mikeash@apple.com>