diff --git a/stdlib/public/SwiftShims/swift/shims/MetadataSections.h b/stdlib/public/SwiftShims/swift/shims/MetadataSections.h index 1e419e4b8f763..2ccb54c4c2619 100644 --- a/stdlib/public/SwiftShims/swift/shims/MetadataSections.h +++ b/stdlib/public/SwiftShims/swift/shims/MetadataSections.h @@ -58,24 +58,15 @@ struct MetadataSections { /// symbol in the image that contains these sections. /// /// For Mach-O images, set this field to \c __dso_handle (i.e. the Mach header - /// for the image.) For ELF images, set it to \c __dso_handle (the runtime - /// will adjust it to the start of the ELF image when the image is loaded.) - /// For COFF images, set this field to \c __ImageBase. + /// for the image.) For ELF images, set it to \c __ehdr_start. For COFF + /// images, set this field to \c __ImageBase. /// /// For platforms that have a single statically-linked image or no dynamic - /// loader (i.e. no equivalent of \c __dso_handle or \c __ImageBase), this - /// field is ignored and should be set to \c nullptr. - /// - /// \bug When imported into Swift, this field is not atomic. + /// loader (i.e. no equivalent of \c __dso_handle, \c __ehdr_start, or + /// \c __ImageBase), this field is ignored and should be set to \c nullptr. /// /// \sa swift_addNewDSOImage() -#if defined(__swift__) || defined(__STDC_NO_ATOMICS__) const void *baseAddress; -#elif defined(__cplusplus) - std::atomic baseAddress; -#else - _Atomic(const void *) baseAddress; -#endif /// Unused. /// diff --git a/stdlib/public/runtime/ImageInspectionCommon.cpp b/stdlib/public/runtime/ImageInspectionCommon.cpp index e1e1da0a4a8f3..ffd28c29bd449 100644 --- a/stdlib/public/runtime/ImageInspectionCommon.cpp +++ b/stdlib/public/runtime/ImageInspectionCommon.cpp @@ -28,67 +28,25 @@ #include "swift/Runtime/Concurrent.h" #include -#include #include namespace swift { - -static Lazy> registered; - -/// Adjust the \c baseAddress field of a metadata sections structure. -/// -/// \param sections A pointer to a valid \c swift::MetadataSections structure. -/// -/// This function should be called at least once before the structure or its -/// address is passed to code outside this file to ensure that the structure's -/// \c baseAddress field correctly points to the base address of the image it -/// is describing. -static void fixupMetadataSectionBaseAddress(swift::MetadataSections *sections) { - bool fixupNeeded = false; - -#if defined(__ELF__) - // If the base address was set but the image is an ELF image, it is going to - // be __dso_handle which is not the value we expect (Dl_info::dli_fbase), so - // we need to fix it up. - fixupNeeded = true; -#elif !defined(__MACH__) - // For non-ELF, non-Apple platforms, if the base address is nullptr, it - // implies that this image was built against an older version of the runtime - // that did not capture any value for the base address. - auto oldBaseAddress = sections->baseAddress.load(std::memory_order_relaxed); - if (!oldBaseAddress) { - fixupNeeded = true; - } -#endif - - if (fixupNeeded) { - // We need to fix up the base address. We'll need a known-good address in - // the same image: `sections` itself will work nicely. - auto symbolInfo = SymbolInfo::lookup(sections); - if (symbolInfo.has_value() && symbolInfo->getBaseAddress()) { - sections->baseAddress.store(symbolInfo->getBaseAddress(), - std::memory_order_relaxed); - } - } -} + static Lazy> registered; } SWIFT_RUNTIME_EXPORT void swift_addNewDSOImage(swift::MetadataSections *sections) { -#if 0 - // Ensure the base address of the sections structure is correct. - // - // Currently disabled because none of the registration functions below - // actually do anything with the baseAddress field. Instead, - // swift_enumerateAllMetadataSections() is called by other individual - // functions, lower in this file, that yield metadata section pointers. - // - // If one of these registration functions starts needing the baseAddress - // field, this call should be enabled and the calls elsewhere in the file can - // be removed. - swift::fixupMetadataSectionBaseAddress(sections); +#if defined(__ELF__) + if (!sections->baseAddress || sections->version <= 4) { + // The base address was either unavailable at link time or is set to the + // wrong value and will need to be recomputed. We can use the address of the + // sections structure and derive the base address from there. + if (auto info = swift::SymbolInfo::lookup(sections)) { + sections->baseAddress = info->getBaseAddress(); + } + } #endif - auto baseAddress = sections->baseAddress.load(std::memory_order_relaxed); + auto baseAddress = sections->baseAddress; const auto &protocols_section = sections->swift5_protocols; const void *protocols = reinterpret_cast(protocols_section.start); @@ -144,9 +102,6 @@ void swift_enumerateAllMetadataSections( ) { auto snapshot = swift::registered->snapshot(); for (swift::MetadataSections *sections : snapshot) { - // Ensure the base address is fixed up before yielding the pointer. - swift::fixupMetadataSectionBaseAddress(sections); - // Yield the pointer and (if the callback returns false) break the loop. if (!(* body)(sections, context)) { return; @@ -180,11 +135,6 @@ const swift::MetadataSections *swift_getMetadataSection(size_t index) { result = snapshot[index]; } - if (result) { - // Ensure the base address is fixed up before returning it. - swift::fixupMetadataSectionBaseAddress(result); - } - return result; } @@ -208,11 +158,7 @@ void swift_getMetadataSectionBaseAddress(const swift::MetadataSections *section, } else { *out_actual = nullptr; } - - // fixupMetadataSectionBaseAddress() was already called by - // swift_getMetadataSection(), presumably on the same thread, so we don't need - // to call it again here. - *out_expected = section->baseAddress.load(std::memory_order_relaxed); + *out_expected = section->baseAddress; } SWIFT_RUNTIME_EXPORT diff --git a/stdlib/public/runtime/ImageInspectionCommon.h b/stdlib/public/runtime/ImageInspectionCommon.h index 85ab85a49e4da..9624b55876ace 100644 --- a/stdlib/public/runtime/ImageInspectionCommon.h +++ b/stdlib/public/runtime/ImageInspectionCommon.h @@ -51,7 +51,7 @@ namespace swift { struct MetadataSections; -static constexpr const uintptr_t CurrentSectionMetadataVersion = 4; +static constexpr const uintptr_t CurrentSectionMetadataVersion = 5; } struct SectionInfo { diff --git a/stdlib/public/runtime/SwiftRT-ELF-WASM.cpp b/stdlib/public/runtime/SwiftRT-ELF-WASM.cpp index 1bd1eed9f807f..7cbde16180a5d 100644 --- a/stdlib/public/runtime/SwiftRT-ELF-WASM.cpp +++ b/stdlib/public/runtime/SwiftRT-ELF-WASM.cpp @@ -19,11 +19,7 @@ #include #if defined(__ELF__) -extern "C" const char __dso_handle[]; -#elif defined(__wasm__) -// NOTE: Multi images in a single process is not yet -// stabilized in WebAssembly toolchain outside of Emscripten. -static constexpr const void *__dso_handle = nullptr; +extern "C" const char __ehdr_start[] __attribute__((__weak__)); #endif #if SWIFT_ENABLE_BACKTRACING @@ -92,9 +88,19 @@ static void swift_image_constructor() { { reinterpret_cast(&__start_##name), \ static_cast(&__stop_##name - &__start_##name) } + const void *baseAddress = nullptr; +#if defined(__ELF__) + if (&__ehdr_start != nullptr) { + baseAddress = __ehdr_start; + } +#elif defined(__wasm__) + // NOTE: Multi images in a single process is not yet stabilized in WebAssembly + // toolchain outside of Emscripten. +#endif + ::new (§ions) swift::MetadataSections { swift::CurrentSectionMetadataVersion, - { __dso_handle }, + baseAddress, nullptr, nullptr,