-
Notifications
You must be signed in to change notification settings - Fork 10.5k
Adds entry points to the runtime that exposes metadata #32339
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Adds entry points to the runtime that exposes metadata #32339
Conversation
e92f1af
to
8dd2754
Compare
@augusto2112 per our discussion on the forums, do we need to extend the swift_reflection_addReflectionInfo interface to handle non-contiguous section layouts? |
@vedantk I think we have two possibilities:
What do you think? Maybe we should consult Joe and Slava on which way to go? |
To summarize our video chat conversation:
|
Also: cc'ing @jckarter @slavapestov for visibility. |
8dd2754
to
3598e7d
Compare
@vedantk I've updated the PR to support the non-contiguous reflection info 🎉
Edit: So now, we actually get to print the type info! Although the output is a bit different from what is expected in the test.
Expected output:
So the class_instance size is 18 instead of 20. |
fab79de
to
86545d9
Compare
@jckarter Does it look plausible to you that the class would be 2 bytes larger on Linux, or do you suspect a bug? |
@augusto2112 Can you dump the LLVM IR for the Darwin and the Linux version of the class? I'm not sure if this is static enough to show the difference, but if it does allow us to see the fields, we could probably figure out where the difference comes from and whether it's plausible. |
@adrian-prantl Here's the relevant IR for the class on Linux:
I believe the the instance size field in the metadata is 18.
I'm having trouble compiling the class for darwin, it seems that I need the standard library for the OS, which I don't have... I'd be grateful if someone could compile it for me so we can check compare them |
@vedantk, @adrian-prantl I'm thinking that I'm returning the wrong thing in |
Be sure to try this with classes of different sizes. |
I think this is it. I adapted the algorithm to work with This is the current status of the tests:
I think we can divide them in 3 camps:
|
You should be able to mark up the Objective-C ones with |
Really nice work! Yes, we're quite close now. I suggest working backwards from where we dump |
86545d9
to
528293d
Compare
@vedantk I believe I figured this one out. I just pushed a change that gives us the correct output. Basically, I think that |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Awesome, then I think it's time to push this PR out of the work-in-progress stage :).
Should I push enabling all the test cases? It won't work yet, but it would nice to see what's still failing on the CI. |
Go for it 👍 |
528293d
to
66e903a
Compare
@@ -80,6 +80,12 @@ void | |||
swift_reflection_addReflectionInfo(SwiftReflectionContextRef ContextRef, | |||
swift_reflection_info_t Info); | |||
|
|||
/// Add reflection sections that may not be contiguous from a loaded Swift image. | |||
SWIFT_REMOTE_MIRROR_LINKAGE | |||
void swift_reflection_addNonContiguousReflectionInfo( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a conflicting interface for swift_reflection_addReflectionInfo
? I'm not sure I see the value in the NonContiguous
here. Or was there some other reason that you opted to add that?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The difference is that this receives a swift_non_contiguous_reflection_info_t
instead of a swift_reflection_info_t
. I needed to change the data structure because swift_reflection_info_t
expects the offset of the local and remote sections to be the same (because it assumed the sections were contiguous, which isn't true).
swift_reflection_addReflectionInfo
already exists, and @vedantk asked me to not change it since it's part of the API.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe swift_reflection_info_t
isn't sufficiently general to describe a non-contiguous section layout.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Under what circumstances are you seeing a non-contiguous metadata section?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jckarter in my tests on Linux, they always appear to be non-contiguous. Maybe it's OS related?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, I see what you mean, the subsections are contiguous, but the mapping from remote to local addresses between them may not be 1:1. That's reasonable. As the comments note, swift_reflection_addReflectionInfo
is deprecated and only exists for legacy ABI reasons on Apple platforms, because it's unable to accurately express this reality. We could probably remove it entirely on non-Apple platforms. It would be great if we could name this new API in a way that makes it more apparent it should be the preferred API for new code using Remote Mirror that wants to manually register images.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I might be wrong, but from my tests I believe the subsections really weren't contiguous. I'll re-check this to see if I'm correct.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jckarter here is what swift-reflection-test.c
logs in my machine (I just added the End field, so it's easier to visualize):
makeRemoteSection: Making remote section with Start = 0x7f22a7aee7b0 End = 0x7f22a7af285c and Size = 16556
makeRemoteSection: Making remote section with Start = 0x7f22a7ae99a8 End = 0x7f22a7aee7b0 and Size = 19976
makeRemoteSection: Making remote section with Start = 0x7f22a7a13f1c End = 0x7f22a7a14a98 and Size = 2940
makeRemoteSection: Making remote section with Start = 0x7f22a7ae8f40 End = 0x7f22a7ae99a8 and Size = 2664
makeRemoteSection: Making remote section with Start = 0x7f22a7a0d864 End = 0x7f22a7a12e43 and Size = 21983
makeRemoteSection: Making remote section with Start = 0x7f22a7a12e50 End = 0x7f22a7a13f19 and Size = 4297
makeRemoteSection: Making remote section with Start = 0x7f22a7334244 End = 0x7f22a7334244 and Size = 0
makeRemoteSection: Making remote section with Start = 0x7f22a7334244 End = 0x7f22a7334244 and Size = 0
makeRemoteSection: Making remote section with Start = 0x7f22a7334244 End = 0x7f22a7334244 and Size = 0
makeRemoteSection: Making remote section with Start = 0x7f22a7334244 End = 0x7f22a7334244 and Size = 0
makeRemoteSection: Making remote section with Start = 0x7f22a7349180 End = 0x7f22a734927c and Size = 252
makeRemoteSection: Making remote section with Start = 0x7f22a7334244 End = 0x7f22a7334244 and Size = 0
makeRemoteSection: Making remote section with Start = 0x7f22a74f640c End = 0x7f22a74f6a40 and Size = 1588
makeRemoteSection: Making remote section with Start = 0x7f22a74f63f4 End = 0x7f22a74f640c and Size = 24
makeRemoteSection: Making remote section with Start = 0x7f22a74f3b1c End = 0x7f22a74f3b1c and Size = 0
makeRemoteSection: Making remote section with Start = 0x7f22a74f3b1c End = 0x7f22a74f3b1c and Size = 0
makeRemoteSection: Making remote section with Start = 0x7f22a74f63d0 End = 0x7f22a74f63f3 and Size = 35
makeRemoteSection: Making remote section with Start = 0x7f22a74f36a9 End = 0x7f22a74f3b05 and Size = 1116
makeRemoteSection: Making remote section with Start = 0x7f22a7b25344 End = 0x7f22a7b254a4 and Size = 352
makeRemoteSection: Making remote section with Start = 0x7f22a7b2530c End = 0x7f22a7b25344 and Size = 56
makeRemoteSection: Making remote section with Start = 0x7f22a7b21cce End = 0x7f22a7b21cce and Size = 0
makeRemoteSection: Making remote section with Start = 0x7f22a7b21cce End = 0x7f22a7b21cce and Size = 0
makeRemoteSection: Making remote section with Start = 0x7f22a7b25228 End = 0x7f22a7b25309 and Size = 225
makeRemoteSection: Making remote section with Start = 0x7f22a7b21c00 End = 0x7f22a7b21cbe and Size = 190
makeRemoteSection: Making remote section with Start = 0x560e295150dc End = 0x560e295150f8 and Size = 28
makeRemoteSection: Making remote section with Start = 0x560e295131ee End = 0x560e295131ee and Size = 0
makeRemoteSection: Making remote section with Start = 0x560e295131ee End = 0x560e295131ee and Size = 0
makeRemoteSection: Making remote section with Start = 0x560e295131ee End = 0x560e295131ee and Size = 0
makeRemoteSection: Making remote section with Start = 0x560e295150d0 End = 0x560e295150dc and Size = 12
makeRemoteSection: Making remote section with Start = 0x560e295131ec End = 0x560e295131ee and Size = 2
I think the second block is the easiest to look at, since all sections, except 1, have size 0. The old algorithm would mistakenly assume that the sections would go from address 0x7f22a7334244 up to 0x7f22a734927c, which is 15038 bytes long.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, by "subsection" I mean one of the individual areas referenced in the reflection_info
struct, like field
, associated_types
, and so on. Anyway, the swift_reflection_info
and swift_reflection_addReflectionInfo
interfaces are obsolete, and I'm saying it would be good to name these new ones swift_reflection_addReflectionInfo2
or something like that to make it clear it should supersede the old interface.
@@ -48,11 +48,22 @@ typedef struct swift_reflection_section { | |||
void *End; | |||
} swift_reflection_section_t; | |||
|
|||
/// Represents the remote address and size of an image. | |||
typedef struct swift_remote_reflection_section { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this actually a section as per the file format or is this really just the specific metadata table?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is supposed to represent the counterpart of the already existing swift_reflection_section
struct. That's why I named it swift_remote_reflection_section
. Is this name wrong? Aren't associated_types
, builtin_types
, capture
, etc sections?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
They are sections only on ELF because of the restrictions from the file format. Each one of those is a separate metadata table. In fact, if you look at MachO, they are all in the __DATA
section and each is a segment. PE/COFF does something similar - entries are grouped, and then emitted entirely into the .data
section. If this is meant to be ELF specific, please put that into the name (e.g. swift_remote_reflection_elf_section
).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You have that backwards, __DATA
is the segment (they're actually in __TEXT
, though, because they're constant), and __TEXT, __swift5_foo
is the section, in Mach-O parlance. The name seems correct to me.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, okay, if that is constant across all the formats, sounds reasonable.
@@ -48,11 +48,22 @@ typedef struct swift_reflection_section { | |||
void *End; | |||
} swift_reflection_section_t; | |||
|
|||
/// Represents the remote address and size of an image. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think that this really describes the structure and its usage. The address and size would be inferred from the structure itself. What does it actually represent? I believe that it is really a metadata table chunk.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're right. Maybe "/// Represents the remote address and size of an image's section."?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Like the previous comment, I don't think that the term section should play into this. I would say that it represents a (contiguous) region in the image's address space.
typedef struct swift_reflection_section_pair { | ||
swift_reflection_section_t section; | ||
swift_reflection_ptr_t offset; ///< DEPRECATED. Must be zero | ||
} swift_reflection_section_pair_t; | ||
|
||
typedef struct swift_local_and_remote_reflection_section { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Again, Im not sure what section
here really refers to. Given the type, I believe that this is really the bidirectional mapping from local to remote? Why not something like swift_remote_reflection_metadata_mapping
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I used section
as this was the existing nomenclature I found. This matches with what's in SwiftReflectionTest
(a ReflectionInfo
contains many Section
s) and the exisiting swift_reflection_section
as well. Is the name "section" wrong here? If not, what about swift_reflection_section_mapping
, would that be better?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I don't think that it really is correct to encode the details of a specific file format into the name. The nomenclature in the ReflectionInfo
stems from it being specific to ELF. If we want this to be limited to ELF, I think that we should be putting ELF into the name of the types (assuming that we will want custom types for MachO, WASM, COFF). I think that the types here are pretty generic though. I think that something like swift_reflection_address_mapping
works well as this maps the local address to the remote address.
@@ -71,6 +82,17 @@ typedef struct swift_reflection_info { | |||
swift_reflection_ptr_t RemoteStartAddress; | |||
} swift_reflection_info_t; | |||
|
|||
/// Represents the set of Swift reflection sections of an image, | |||
/// but doesn't assume that the sections share contiguous memory. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is no real guarantee that reflection is contiguous. I think that it is sufficient to say:
Represents the Swift reflection metadata from an image.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wanted to emphasize that this data structure doesn't assume the memory isn't contiguous to contrast the already existing swift_reflection_info
, which does assume that. Should I remove that?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that the clarification that was made further up is critical here. It isn't that the reflection info is non-contiguous. The metadata layout is contiguous. The mapping from local to remote is non-contiguous. Is that understanding incorrect? If not, this is misleading, and I would say that this is better named as perhaps swift_remote_reflection_data_slice
to indicate that this is a sliver of the full metadata information.
stdlib/public/core/Misc.swift
Outdated
@_silgen_name("swift_getMetadataSectionName") | ||
public func _getMetadataSectionName( | ||
_ metadata_section: UnsafeRawPointer) | ||
-> UnsafePointer<CChar> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These don't seem to be following the standard library style.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are these declarations conditionalized to when we're building a debug runtime that contains the symbols?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jckarter I just remembered why they aren't conditionalized here. The problem is that SwiftReflectionTest.swift
is built even when assertions are off. To conditionalize them here, I'd have to change the CMake config to only build this file in debug or on Mac. I initally did that, but was asked to roll-back that change. These functions are conditionalized in C++ though, so I believe calling them would crash the program, which isn't ideal.
In order to conditionalize these symbols, in SwiftReflectionTest.swift
, when on Linux but not in debug, stub the required functions so it as least compiles. Is this solution ok?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What was wrong with conditionalizing SwiftReflectionTest.swift? If touching CMake is inappropriate, maybe we could #if out the contents.
@@ -4,7 +4,7 @@ | |||
|
|||
// RUN: %target-run %target-swift-reflection-test %t/reflect_UInt16 | %FileCheck %s --check-prefix=CHECK-%target-ptrsize | |||
|
|||
// REQUIRES: objc_interop | |||
// REQUIRES: basic_reflection_support |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should the condition be called reflection_test_support
or something more specific?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@vedantk what do you think? I'm ok with either.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
'reflection_test_support' sounds better than 'basic_reflection_support' to me, since it's not clear what the basic/non-basic distinction is.
b2e9c37
to
12a801e
Compare
@jckarter @compnerd I've updated the new data-structures and function names:
Are these names all right? |
Thanks for the updates, those look way better. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks great, thanks!
@swift-ci smoke test and merge |
@swift-ci smoke test |
@augusto2112 it appears that availability markup is now required for these:
(either that, or the list in test/api-digester/stability-stdlib-abi-with-asserts.test can be updated). The new requirement came into effect on 7/17 with a8c785b. https://ci.swift.org/job/swift-PR-osx-smoke-test/23940/consoleText |
@vedantk I see. Since these functions should only be available in debug builds, should we mark it with
|
Instead of applying a fake at-available attribute, maybe it'd be simpler to add exceptions to the test/api-digester/stability-stdlib-abi-with-asserts.test test? |
742cb09
to
3bcf957
Compare
…flection tests on Linux
3bcf957
to
5016b3f
Compare
@vedantk My mistake, I was looking at the old I've updated the pr, could you re-run the tests please? |
@swift-ci smoke test |
🎉 |
9999-availability isn't fake -- it's a placeholder for whatever stdlib release will first include these entry points. Without availability declarations, adopters will not be able to link with earlier stdlib releases. |
This PR will add the necessary functionality in order to enable SwiftReflectionTest to work on Linux. This will be done by adding entry points in the Swift runtime that only build in debug builds