-
Notifications
You must be signed in to change notification settings - Fork 10.7k
ELF: Overhaul metadata extraction #87285
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
base: main
Are you sure you want to change the base?
Changes from all commits
55cb0fb
23237b0
e39c460
bf00f2f
e48bf9f
fe80037
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,34 @@ | ||
| //===--- MetadataSectionNames.def -----------------------------------------===// | ||
| // | ||
| // This source file is part of the Swift.org open source project | ||
| // | ||
| // Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors | ||
| // Licensed under Apache License v2.0 with Runtime Library Exception | ||
| // | ||
| // See https://swift.org/LICENSE.txt for license information | ||
| // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| #ifndef HANDLE_SWIFT_SECTION | ||
| #error "HANDLE_SWIFT_SECTION(elfname, coffname) not defined" | ||
| #endif | ||
|
|
||
| // NOTE: This table is ABI. Don't rearrange it! | ||
| // NOTE: If adding fields, remember to add the field to ReflectionContext.h | ||
|
|
||
| HANDLE_SWIFT_SECTION(swift5_protocols, sw5prt) | ||
| HANDLE_SWIFT_SECTION(swift5_protocol_conformances, sw5prtc) | ||
| HANDLE_SWIFT_SECTION(swift5_type_metadata, sw5tymd) | ||
| HANDLE_SWIFT_SECTION(swift5_typeref, sw5tyrf) | ||
| HANDLE_SWIFT_SECTION(swift5_reflstr, sw5rfst) | ||
| HANDLE_SWIFT_SECTION(swift5_fieldmd, sw5flmd) | ||
| HANDLE_SWIFT_SECTION(swift5_assocty, sw5asty) | ||
| HANDLE_SWIFT_SECTION(swift5_replace, sw5repl) | ||
| HANDLE_SWIFT_SECTION(swift5_replac2, sw5reps) | ||
| HANDLE_SWIFT_SECTION(swift5_builtin, sw5bltn) | ||
| HANDLE_SWIFT_SECTION(swift5_capture, sw5cptr) | ||
| HANDLE_SWIFT_SECTION(swift5_mpenum, sw5mpen) | ||
| HANDLE_SWIFT_SECTION(swift5_accessible_functions, sw5acfn) | ||
| HANDLE_SWIFT_SECTION(swift5_runtime_attributes, sw5ratt) | ||
| HANDLE_SWIFT_SECTION(swift5_tests, sw5test) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,188 @@ | ||
| //===--- SwiftRT-ELF.cpp --------------------------------------------------===// | ||
| // | ||
| // This source file is part of the Swift.org open source project | ||
| // | ||
| // Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors | ||
| // Licensed under Apache License v2.0 with Runtime Library Exception | ||
| // | ||
| // See https://swift.org/LICENSE.txt for license information | ||
| // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| #include "ImageInspectionCommon.h" | ||
| #include "swift/Runtime/Backtrace.h" | ||
| #include "swift/Runtime/Config.h" | ||
| #include "swift/shims/MetadataSections.h" | ||
|
|
||
| #include <cstddef> | ||
| #include <new> | ||
|
|
||
| #define SWIFT_METADATA_SEGMENT_TYPE 0x73356d64 // s5md or dms5 on little-endian | ||
|
|
||
| extern "C" const char __ehdr_start[] __attribute__((__weak__)); | ||
|
|
||
| #if SWIFT_ENABLE_BACKTRACING | ||
| // Drag in a symbol from the backtracer, to force the static linker to include | ||
| // the code. | ||
| static const void *__backtraceRef __attribute__((used, retain)) = | ||
| (const void *)swift::runtime::backtrace::_swift_backtrace_isThunkFunction; | ||
| #endif | ||
|
|
||
| // Create empty sections to ensure that the start/stop symbols are synthesized | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I haven't tried, but if we declare the symbols we add as |
||
| // by the linker. Otherwise, we may end up with undefined symbol references as | ||
| // the linker table section was never constructed. | ||
| #define DECLARE_EMPTY_METADATA_SECTION(name) \ | ||
| __asm__("\t.section " #name ",\"aR\"\n"); | ||
|
|
||
| #define BOUNDS_VISIBILITY \ | ||
| __attribute__((__visibility__("hidden"), __aligned__(1))) | ||
|
|
||
| #define DECLARE_BOUNDS(name) \ | ||
| BOUNDS_VISIBILITY extern const char __start_##name; \ | ||
| BOUNDS_VISIBILITY extern const char __stop_##name; | ||
|
|
||
| #define DECLARE_SWIFT_SECTION(name) \ | ||
| DECLARE_EMPTY_METADATA_SECTION(name) \ | ||
| DECLARE_BOUNDS(name) | ||
|
|
||
| // These may or may not be present, depending on compiler switches; it's | ||
| // worth calling them out as a result. | ||
| #define DECLARE_SWIFT_REFLECTION_SECTION(name) DECLARE_SWIFT_SECTION(name) | ||
|
|
||
| extern "C" { | ||
| DECLARE_SWIFT_SECTION(swift5_protocols) | ||
| DECLARE_SWIFT_SECTION(swift5_protocol_conformances) | ||
| DECLARE_SWIFT_SECTION(swift5_type_metadata) | ||
|
|
||
| DECLARE_SWIFT_REFLECTION_SECTION(swift5_fieldmd) | ||
| DECLARE_SWIFT_REFLECTION_SECTION(swift5_builtin) | ||
| DECLARE_SWIFT_REFLECTION_SECTION(swift5_assocty) | ||
| DECLARE_SWIFT_REFLECTION_SECTION(swift5_capture) | ||
| DECLARE_SWIFT_REFLECTION_SECTION(swift5_reflstr) | ||
| DECLARE_SWIFT_REFLECTION_SECTION(swift5_typeref) | ||
| DECLARE_SWIFT_REFLECTION_SECTION(swift5_mpenum) | ||
|
|
||
| DECLARE_SWIFT_SECTION(swift5_replace) | ||
| DECLARE_SWIFT_SECTION(swift5_replac2) | ||
| DECLARE_SWIFT_SECTION(swift5_accessible_functions) | ||
| DECLARE_SWIFT_SECTION(swift5_runtime_attributes) | ||
|
|
||
| DECLARE_SWIFT_SECTION(swift5_tests) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We can mark this section as "maybe not present" too. |
||
| } | ||
|
|
||
| #undef DECLARE_SWIFT_SECTION | ||
|
|
||
| namespace { | ||
| struct ElfNoteHeader { | ||
| uint32_t namesz; | ||
| uint32_t descsz; | ||
| uint32_t type; | ||
| }; | ||
|
|
||
| struct SectionRange { | ||
| uintptr_t start; | ||
| uintptr_t stop; | ||
| }; | ||
|
|
||
| // If you update this table, remember to update the reader in | ||
| // ReflectionContext.h! | ||
| struct MetadataSections { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Moving this type out of SwiftShims will break Swift Testing.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Different metadata sections (open to a new name, did't like The
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Alrighty. We should synchronize our PRs so we can drop |
||
| uintptr_t version; | ||
| uintptr_t base; | ||
| uintptr_t unused0; | ||
| uintptr_t unused1; | ||
|
|
||
| #define HANDLE_SWIFT_SECTION(name, coff) SectionRange name; | ||
| #include "MetadataSectionNames.def" | ||
| #undef HANDLE_SWIFT_SECTION | ||
| }; | ||
|
|
||
| struct __attribute__((__packed__)) SwiftMetadataNote { | ||
| ElfNoteHeader header; | ||
| char name[8]; // "swift6\0" + 1 byte(s) of padding | ||
|
|
||
| MetadataSections sections; | ||
| }; | ||
|
|
||
| /// .note.swift_metadata section stores the table of start/stop symbols for | ||
| /// ingestion into the runtime and for static tool access. | ||
| // TODO: We should replace addNewDSOImage with something that takes a pointer to | ||
| // the table directly, removing the need for the additional global constructor | ||
| // that converts the start/stop symbol pointer ranges to start/byte-count, | ||
| // before stabilizing any ELF platform ABIs. This will help reduce program | ||
| // launch times. | ||
| // This will require changes to Swift Testing and the runtime metadata | ||
| // registration. | ||
| __asm__(".section .note.swift_metadata, \"a\", @note"); | ||
|
|
||
| SWIFT_ALLOWED_RUNTIME_GLOBAL_CTOR_BEGIN | ||
| __attribute__((section(".note.swift_metadata"), used, aligned(4))) | ||
| const static SwiftMetadataNote swiftMetadataNote = { | ||
| // header | ||
| .header = | ||
| { | ||
| .namesz = 7, // namesz: "swift6\0" | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You might want to pick a slightly more specific name in case we decide we want to do more with notes in the future.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That is what the segment type is for. The type is namespaced to the name, so we can use any 4-byte number. I went with the bytes that spell out
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm suggesting we make the type |
||
| .descsz = sizeof(MetadataSections), | ||
| .type = SWIFT_METADATA_SEGMENT_TYPE, | ||
| }, // 4 + 4 + 4 = 12, 0x0c | ||
| .name = | ||
| { | ||
| 's', 'w', 'i', 'f', 't', '6', '\0', | ||
| static_cast<char>(0xff), // padding | ||
| }, // 12 + 7 + 1 = 20, 0x14 | ||
| .sections = | ||
| { | ||
| .version = 5, | ||
| .base = reinterpret_cast<uintptr_t>(&__ehdr_start), | ||
| .unused0 = 0xa1a1a1a1, | ||
| .unused1 = 0xb2b2b2b2, | ||
|
|
||
| #define HANDLE_SWIFT_SECTION(elfname, coffname) \ | ||
| .elfname = { \ | ||
| reinterpret_cast<uintptr_t>(&__start_##elfname), \ | ||
| reinterpret_cast<uintptr_t>(&__stop_##elfname), \ | ||
| }, | ||
|
|
||
| #include "MetadataSectionNames.def" | ||
|
|
||
| #undef HANDLE_SWIFT_SECTION | ||
|
|
||
| }, | ||
| }; | ||
| SWIFT_ALLOWED_RUNTIME_GLOBAL_CTOR_END | ||
|
|
||
| } // anonymous namespace | ||
|
|
||
| namespace { | ||
| static swift::MetadataSections sections{}; | ||
| } | ||
|
|
||
| SWIFT_ALLOWED_RUNTIME_GLOBAL_CTOR_BEGIN | ||
| __attribute__((__constructor__)) static void swift_image_constructor() { | ||
| #define SWIFT_SECTION_RANGE(name) \ | ||
| { \ | ||
| swiftMetadataNote.sections.name.start, \ | ||
| swiftMetadataNote.sections.name.stop - \ | ||
| swiftMetadataNote.sections.name.start, \ | ||
| } | ||
|
|
||
| ::new (§ions) swift::MetadataSections{ | ||
| swiftMetadataNote.sections.version, | ||
| reinterpret_cast<const char *>(swiftMetadataNote.sections.base), | ||
|
|
||
| reinterpret_cast<void *>(swiftMetadataNote.sections.unused0), | ||
| reinterpret_cast<void *>(swiftMetadataNote.sections.unused1), | ||
|
|
||
| #define HANDLE_SWIFT_SECTION(elfname, coffname) SWIFT_SECTION_RANGE(elfname), | ||
|
|
||
| #include "MetadataSectionNames.def" | ||
|
|
||
| #undef HANDLE_SWIFT_SECTION | ||
| }; | ||
|
|
||
| #undef SWIFT_SECTION_RANGE | ||
|
|
||
| swift_addNewDSOImage(§ions); | ||
| } | ||
| SWIFT_ALLOWED_RUNTIME_GLOBAL_CTOR_END | ||
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.
Why not change the type of Segment's Contents from StringRef to
std::string? Doesn't look like you useRelocatedSegmentStorageoutside of this function. The StringRef to a reference to a mutable string makes me slightly worried that a code change in the future that mutates the string could cause a dangling pointer.