Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 4 additions & 13 deletions stdlib/public/SwiftShims/swift/shims/MetadataSections.h
Original file line number Diff line number Diff line change
Expand Up @@ -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<const void *> baseAddress;
#else
_Atomic(const void *) baseAddress;
#endif

/// Unused.
///
Expand Down
78 changes: 12 additions & 66 deletions stdlib/public/runtime/ImageInspectionCommon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,67 +28,25 @@
#include "swift/Runtime/Concurrent.h"

#include <algorithm>
#include <atomic>
#include <cstdlib>

namespace swift {

static Lazy<ConcurrentReadableArray<swift::MetadataSections *>> 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<ConcurrentReadableArray<swift::MetadataSections *>> 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<void *>(protocols_section.start);
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
}

Expand All @@ -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
Expand Down
2 changes: 1 addition & 1 deletion stdlib/public/runtime/ImageInspectionCommon.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@

namespace swift {
struct MetadataSections;
static constexpr const uintptr_t CurrentSectionMetadataVersion = 4;
static constexpr const uintptr_t CurrentSectionMetadataVersion = 5;
}

struct SectionInfo {
Expand Down
18 changes: 12 additions & 6 deletions stdlib/public/runtime/SwiftRT-ELF-WASM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,7 @@
#include <new>

#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
Expand Down Expand Up @@ -92,9 +88,19 @@ static void swift_image_constructor() {
{ reinterpret_cast<uintptr_t>(&__start_##name), \
static_cast<uintptr_t>(&__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 (&sections) swift::MetadataSections {
swift::CurrentSectionMetadataVersion,
{ __dso_handle },
baseAddress,

nullptr,
nullptr,
Expand Down