mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Fix an issue on COFF/ELF targets where the runtime would register each loaded image twice (at least early on.)
This commit is contained in:
@@ -39,7 +39,25 @@ typedef struct MetadataSectionRange {
|
||||
/// Identifies the address space ranges for the Swift metadata required by the Swift runtime.
|
||||
struct MetadataSections {
|
||||
__swift_uintptr_t version;
|
||||
__swift_uintptr_t reserved;
|
||||
|
||||
/// The base address of the image where this metadata section was defined, as
|
||||
/// reported when the section was registered with the Swift runtime.
|
||||
///
|
||||
/// The value of this field is equivalent to the value of
|
||||
/// \c SymbolInfo::baseAddress as returned from \c lookupSymbol() for a 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 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.
|
||||
///
|
||||
/// \sa swift_addNewDSOImage()
|
||||
const void *baseAddress;
|
||||
|
||||
/// `next` and `prev` are used by the runtime to construct a
|
||||
/// circularly doubly linked list to quickly iterate over the metadata
|
||||
|
||||
@@ -98,8 +98,8 @@ static void _registerAccessibleFunctions(AccessibleFunctionsState &C,
|
||||
C.SectionsToScan.push_back(section);
|
||||
}
|
||||
|
||||
void swift::addImageAccessibleFunctionsBlockCallbackUnsafe(const void *functions,
|
||||
uintptr_t size) {
|
||||
void swift::addImageAccessibleFunctionsBlockCallbackUnsafe(
|
||||
const void *baseAddress, const void *functions, uintptr_t size) {
|
||||
assert(
|
||||
size % sizeof(AccessibleFunctionRecord) == 0 &&
|
||||
"accessible function section not a multiple of AccessibleFunctionRecord");
|
||||
@@ -108,10 +108,10 @@ void swift::addImageAccessibleFunctionsBlockCallbackUnsafe(const void *functions
|
||||
_registerAccessibleFunctions(C, AccessibleFunctionsSection{functions, size});
|
||||
}
|
||||
|
||||
void swift::addImageAccessibleFunctionsBlockCallback(const void *functions,
|
||||
uintptr_t size) {
|
||||
void swift::addImageAccessibleFunctionsBlockCallback(
|
||||
const void *baseAddress, const void *functions, uintptr_t size) {
|
||||
Functions.get();
|
||||
addImageAccessibleFunctionsBlockCallbackUnsafe(functions, size);
|
||||
addImageAccessibleFunctionsBlockCallbackUnsafe(baseAddress, functions, size);
|
||||
}
|
||||
|
||||
static const AccessibleFunctionRecord *
|
||||
|
||||
@@ -77,22 +77,31 @@ void initializeDynamicReplacementLookup();
|
||||
void initializeAccessibleFunctionsLookup();
|
||||
|
||||
// Callbacks to register metadata from an image to the runtime.
|
||||
void addImageProtocolsBlockCallback(const void *start, uintptr_t size);
|
||||
void addImageProtocolsBlockCallbackUnsafe(const void *start, uintptr_t size);
|
||||
void addImageProtocolConformanceBlockCallback(const void *start,
|
||||
void addImageProtocolsBlockCallback(const void *baseAddress,
|
||||
const void *start, uintptr_t size);
|
||||
void addImageProtocolsBlockCallbackUnsafe(const void *baseAddress,
|
||||
const void *start, uintptr_t size);
|
||||
void addImageProtocolConformanceBlockCallback(const void *baseAddress,
|
||||
const void *start,
|
||||
uintptr_t size);
|
||||
void addImageProtocolConformanceBlockCallbackUnsafe(const void *start,
|
||||
void addImageProtocolConformanceBlockCallbackUnsafe(const void *baseAddress,
|
||||
const void *start,
|
||||
uintptr_t size);
|
||||
void addImageTypeMetadataRecordBlockCallback(const void *start,
|
||||
void addImageTypeMetadataRecordBlockCallback(const void *baseAddress,
|
||||
const void *start,
|
||||
uintptr_t size);
|
||||
void addImageTypeMetadataRecordBlockCallbackUnsafe(const void *start,
|
||||
void addImageTypeMetadataRecordBlockCallbackUnsafe(const void *baseAddress,
|
||||
const void *start,
|
||||
uintptr_t size);
|
||||
void addImageDynamicReplacementBlockCallback(const void *start, uintptr_t size,
|
||||
void addImageDynamicReplacementBlockCallback(const void *baseAddress,
|
||||
const void *start, uintptr_t size,
|
||||
const void *start2,
|
||||
uintptr_t size2);
|
||||
void addImageAccessibleFunctionsBlockCallback(const void *start,
|
||||
void addImageAccessibleFunctionsBlockCallback(const void *baseAddress,
|
||||
const void *start,
|
||||
uintptr_t size);
|
||||
void addImageAccessibleFunctionsBlockCallbackUnsafe(const void *start,
|
||||
void addImageAccessibleFunctionsBlockCallbackUnsafe(const void *baseAddress,
|
||||
const void *start,
|
||||
uintptr_t size);
|
||||
|
||||
int lookupSymbol(const void *address, SymbolInfo *info);
|
||||
|
||||
@@ -28,9 +28,10 @@
|
||||
|
||||
namespace swift {
|
||||
|
||||
#ifndef NDEBUG
|
||||
static swift::MetadataSections *registered = nullptr;
|
||||
|
||||
void record(swift::MetadataSections *sections) {
|
||||
static void record(swift::MetadataSections *sections) {
|
||||
if (registered == nullptr) {
|
||||
registered = sections;
|
||||
sections->next = sections->prev = sections;
|
||||
@@ -41,34 +42,70 @@ void record(swift::MetadataSections *sections) {
|
||||
registered->prev = sections;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static const void *
|
||||
getMetadataSectionBaseAddress(swift::MetadataSections *sections) {
|
||||
// If the base address was not set by the caller of swift_addNewDSOImage()
|
||||
// then we can assume that the caller was built against an older version of
|
||||
// the runtime that did not capture a value for this field. Currently nothing
|
||||
// is actively using the image's base address outside of tests that are built
|
||||
// with the runtime/stdlib, so there's no need to try to fix up the value. If
|
||||
// something in the runtime starts using it, we will want to either:
|
||||
// 1. Resolve the address from a known-good address like swift5_protocols when
|
||||
// the image is first loaded (in this function);
|
||||
// 1. Resolve the address from a known-good address like swift5_protocols when
|
||||
// the address is first used (and atomically swap the address back so we
|
||||
// don't incur the cost of lookupSymbol() each time we need it; or
|
||||
// 3. Introduce an ABI-breaking change so that all binaries are rebuilt and
|
||||
// start supplying a value for this field.
|
||||
|
||||
#ifndef NDEBUG
|
||||
#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. Since the base address is currently unused by the
|
||||
// runtime outside tests, we don't normally do this work.
|
||||
if (auto baseAddress = sections->baseAddress) {
|
||||
swift::SymbolInfo symbolInfo;
|
||||
if (lookupSymbol(baseAddress, &symbolInfo) && symbolInfo.baseAddress) {
|
||||
sections->baseAddress = symbolInfo.baseAddress;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
return sections->baseAddress;
|
||||
}
|
||||
}
|
||||
|
||||
SWIFT_RUNTIME_EXPORT
|
||||
void swift_addNewDSOImage(const void *addr) {
|
||||
// We cast off the const in order to update the linked list
|
||||
// data structure. This is safe to do since we don't touch
|
||||
// any other fields.
|
||||
swift::MetadataSections *sections =
|
||||
static_cast<swift::MetadataSections *>(const_cast<void *>(addr));
|
||||
|
||||
void swift_addNewDSOImage(swift::MetadataSections *sections) {
|
||||
#ifndef NDEBUG
|
||||
record(sections);
|
||||
#endif
|
||||
|
||||
auto baseAddress = swift::getMetadataSectionBaseAddress(sections);
|
||||
|
||||
const auto &protocols_section = sections->swift5_protocols;
|
||||
const void *protocols = reinterpret_cast<void *>(protocols_section.start);
|
||||
if (protocols_section.length)
|
||||
swift::addImageProtocolsBlockCallback(protocols, protocols_section.length);
|
||||
swift::addImageProtocolsBlockCallback(baseAddress,
|
||||
protocols, protocols_section.length);
|
||||
|
||||
const auto &protocol_conformances = sections->swift5_protocol_conformances;
|
||||
const void *conformances =
|
||||
reinterpret_cast<void *>(protocol_conformances.start);
|
||||
if (protocol_conformances.length)
|
||||
swift::addImageProtocolConformanceBlockCallback(conformances,
|
||||
swift::addImageProtocolConformanceBlockCallback(baseAddress, conformances,
|
||||
protocol_conformances.length);
|
||||
|
||||
const auto &type_metadata = sections->swift5_type_metadata;
|
||||
const void *metadata = reinterpret_cast<void *>(type_metadata.start);
|
||||
if (type_metadata.length)
|
||||
swift::addImageTypeMetadataRecordBlockCallback(metadata, type_metadata.length);
|
||||
swift::addImageTypeMetadataRecordBlockCallback(baseAddress,
|
||||
metadata,
|
||||
type_metadata.length);
|
||||
|
||||
const auto &dynamic_replacements = sections->swift5_replace;
|
||||
const auto *replacements =
|
||||
@@ -77,7 +114,7 @@ void swift_addNewDSOImage(const void *addr) {
|
||||
const auto &dynamic_replacements_some = sections->swift5_replac2;
|
||||
const auto *replacements_some =
|
||||
reinterpret_cast<void *>(dynamic_replacements_some.start);
|
||||
swift::addImageDynamicReplacementBlockCallback(
|
||||
swift::addImageDynamicReplacementBlockCallback(baseAddress,
|
||||
replacements, dynamic_replacements.length, replacements_some,
|
||||
dynamic_replacements_some.length);
|
||||
}
|
||||
@@ -87,70 +124,22 @@ void swift_addNewDSOImage(const void *addr) {
|
||||
reinterpret_cast<void *>(accessible_funcs_section.start);
|
||||
if (accessible_funcs_section.length)
|
||||
swift::addImageAccessibleFunctionsBlockCallback(
|
||||
functions, accessible_funcs_section.length);
|
||||
baseAddress, functions, accessible_funcs_section.length);
|
||||
}
|
||||
|
||||
void swift::initializeProtocolLookup() {
|
||||
const swift::MetadataSections *sections = registered;
|
||||
while (true) {
|
||||
const swift::MetadataSectionRange &protocols =
|
||||
sections->swift5_protocols;
|
||||
if (protocols.length)
|
||||
addImageProtocolsBlockCallbackUnsafe(
|
||||
reinterpret_cast<void *>(protocols.start), protocols.length);
|
||||
|
||||
if (sections->next == registered)
|
||||
break;
|
||||
sections = sections->next;
|
||||
}
|
||||
}
|
||||
|
||||
void swift::initializeProtocolConformanceLookup() {
|
||||
const swift::MetadataSections *sections = registered;
|
||||
while (true) {
|
||||
const swift::MetadataSectionRange &conformances =
|
||||
sections->swift5_protocol_conformances;
|
||||
if (conformances.length)
|
||||
addImageProtocolConformanceBlockCallbackUnsafe(
|
||||
reinterpret_cast<void *>(conformances.start), conformances.length);
|
||||
|
||||
if (sections->next == registered)
|
||||
break;
|
||||
sections = sections->next;
|
||||
}
|
||||
}
|
||||
|
||||
void swift::initializeTypeMetadataRecordLookup() {
|
||||
const swift::MetadataSections *sections = registered;
|
||||
while (true) {
|
||||
const swift::MetadataSectionRange &type_metadata =
|
||||
sections->swift5_type_metadata;
|
||||
if (type_metadata.length)
|
||||
addImageTypeMetadataRecordBlockCallbackUnsafe(
|
||||
reinterpret_cast<void *>(type_metadata.start), type_metadata.length);
|
||||
|
||||
if (sections->next == registered)
|
||||
break;
|
||||
sections = sections->next;
|
||||
}
|
||||
}
|
||||
|
||||
void swift::initializeDynamicReplacementLookup() {
|
||||
}
|
||||
|
||||
void swift::initializeAccessibleFunctionsLookup() {
|
||||
const swift::MetadataSections *sections = registered;
|
||||
while (true) {
|
||||
const swift::MetadataSectionRange &functions =
|
||||
sections->swift5_accessible_functions;
|
||||
if (functions.length)
|
||||
addImageAccessibleFunctionsBlockCallbackUnsafe(
|
||||
reinterpret_cast<void *>(functions.start), functions.length);
|
||||
|
||||
if (sections->next == registered)
|
||||
break;
|
||||
sections = sections->next;
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
@@ -173,9 +162,10 @@ const swift::MetadataSections *swift_getMetadataSection(size_t index) {
|
||||
}
|
||||
|
||||
SWIFT_RUNTIME_EXPORT
|
||||
const char *swift_getMetadataSectionName(void *metadata_section) {
|
||||
const char *
|
||||
swift_getMetadataSectionName(const swift::MetadataSections *section) {
|
||||
swift::SymbolInfo info;
|
||||
if (lookupSymbol(metadata_section, &info)) {
|
||||
if (lookupSymbol(section, &info)) {
|
||||
if (info.fileName) {
|
||||
return info.fileName;
|
||||
}
|
||||
@@ -183,6 +173,20 @@ const char *swift_getMetadataSectionName(void *metadata_section) {
|
||||
return "";
|
||||
}
|
||||
|
||||
SWIFT_RUNTIME_EXPORT
|
||||
void swift_getMetadataSectionBaseAddress(const swift::MetadataSections *section,
|
||||
void const **out_actual,
|
||||
void const **out_expected) {
|
||||
swift::SymbolInfo info;
|
||||
if (lookupSymbol(section, &info)) {
|
||||
*out_actual = info.baseAddress;
|
||||
} else {
|
||||
*out_actual = nullptr;
|
||||
}
|
||||
|
||||
*out_expected = section->baseAddress;
|
||||
}
|
||||
|
||||
SWIFT_RUNTIME_EXPORT
|
||||
size_t swift_getMetadataSectionCount() {
|
||||
if (swift::registered == nullptr)
|
||||
|
||||
@@ -52,7 +52,7 @@
|
||||
|
||||
namespace swift {
|
||||
struct MetadataSections;
|
||||
static constexpr const uintptr_t CurrentSectionMetadataVersion = 1;
|
||||
static constexpr const uintptr_t CurrentSectionMetadataVersion = 2;
|
||||
}
|
||||
|
||||
struct SectionInfo {
|
||||
@@ -60,14 +60,27 @@ struct SectionInfo {
|
||||
const char *data;
|
||||
};
|
||||
|
||||
// Called by injected constructors when a dynamic library is loaded.
|
||||
/// Called by injected constructors when a dynamic library is loaded.
|
||||
///
|
||||
/// \param sections A structure describing the metadata sections in the
|
||||
/// newly-loaded image.
|
||||
///
|
||||
/// \warning The runtime keeps a reference to \a sections and may mutate it, so
|
||||
/// it \em must be mutable and long-lived (that is, statically or dynamically
|
||||
/// allocated.) The effect of passing a pointer to a local value is undefined.
|
||||
SWIFT_RUNTIME_EXPORT
|
||||
void swift_addNewDSOImage(const void *addr);
|
||||
void swift_addNewDSOImage(struct swift::MetadataSections *sections);
|
||||
|
||||
#ifndef NDEBUG
|
||||
|
||||
SWIFT_RUNTIME_EXPORT
|
||||
const char *swift_getMetadataSectionName(void *metadata_section);
|
||||
const char *
|
||||
swift_getMetadataSectionName(const struct swift::MetadataSections *section);
|
||||
|
||||
SWIFT_RUNTIME_EXPORT
|
||||
void swift_getMetadataSectionBaseAddress(
|
||||
const struct swift::MetadataSections *section,
|
||||
void const **out_actual, void const **out_expected);
|
||||
|
||||
SWIFT_RUNTIME_EXPORT
|
||||
size_t swift_getMetadataSectionCount();
|
||||
|
||||
@@ -54,7 +54,8 @@ using mach_header_platform = mach_header;
|
||||
#endif
|
||||
|
||||
template <const char *SEGMENT_NAME, const char *SECTION_NAME,
|
||||
void CONSUME_BLOCK(const void *start, uintptr_t size)>
|
||||
void CONSUME_BLOCK(const void *baseAddress,
|
||||
const void *start, uintptr_t size)>
|
||||
void addImageCallback(const mach_header *mh) {
|
||||
#if __POINTER_WIDTH__ == 64
|
||||
assert(mh->magic == MH_MAGIC_64 && "loaded non-64-bit image?!");
|
||||
@@ -70,17 +71,19 @@ void addImageCallback(const mach_header *mh) {
|
||||
if (!section)
|
||||
return;
|
||||
|
||||
CONSUME_BLOCK(section, size);
|
||||
CONSUME_BLOCK(mh, section, size);
|
||||
}
|
||||
template <const char *SEGMENT_NAME, const char *SECTION_NAME,
|
||||
void CONSUME_BLOCK(const void *start, uintptr_t size)>
|
||||
void CONSUME_BLOCK(const void *baseAddress,
|
||||
const void *start, uintptr_t size)>
|
||||
void addImageCallback(const mach_header *mh, intptr_t vmaddr_slide) {
|
||||
addImageCallback<SEGMENT_NAME, SECTION_NAME, CONSUME_BLOCK>(mh);
|
||||
}
|
||||
|
||||
template <const char *SEGMENT_NAME, const char *SECTION_NAME,
|
||||
const char *SEGMENT_NAME2, const char *SECTION_NAME2,
|
||||
void CONSUME_BLOCK(const void *start, uintptr_t size,
|
||||
void CONSUME_BLOCK(const void *baseAddress,
|
||||
const void *start, uintptr_t size,
|
||||
const void *start2, uintptr_t size2)>
|
||||
void addImageCallback2Sections(const mach_header *mh) {
|
||||
#if __POINTER_WIDTH__ == 64
|
||||
@@ -106,11 +109,12 @@ void addImageCallback2Sections(const mach_header *mh) {
|
||||
if (!section2)
|
||||
size2 = 0;
|
||||
|
||||
CONSUME_BLOCK(section, size, section2, size2);
|
||||
CONSUME_BLOCK(mh, section, size, section2, size2);
|
||||
}
|
||||
template <const char *SEGMENT_NAME, const char *SECTION_NAME,
|
||||
const char *SEGMENT_NAME2, const char *SECTION_NAME2,
|
||||
void CONSUME_BLOCK(const void *start, uintptr_t size,
|
||||
void CONSUME_BLOCK(const void *baseAddress,
|
||||
const void *start, uintptr_t size,
|
||||
const void *start2, uintptr_t size2)>
|
||||
void addImageCallback2Sections(const mach_header *mh, intptr_t vmaddr_slide) {
|
||||
addImageCallback2Sections<SEGMENT_NAME, SECTION_NAME,
|
||||
|
||||
@@ -22,6 +22,8 @@
|
||||
#include "ImageInspection.h"
|
||||
#include "ImageInspectionCommon.h"
|
||||
|
||||
extern "C" const char __dso_handle[];
|
||||
|
||||
using namespace swift;
|
||||
|
||||
#define GET_SECTION_START_AND_SIZE(start, size, _seg, _sec) \
|
||||
@@ -37,7 +39,7 @@ void swift::initializeProtocolLookup() {
|
||||
MachOProtocolsSection);
|
||||
if (start == nullptr || size == 0)
|
||||
return;
|
||||
addImageProtocolsBlockCallbackUnsafe(start, size);
|
||||
addImageProtocolsBlockCallbackUnsafe(__dso_handle, start, size);
|
||||
}
|
||||
|
||||
void swift::initializeProtocolConformanceLookup() {
|
||||
@@ -47,7 +49,7 @@ void swift::initializeProtocolConformanceLookup() {
|
||||
MachOProtocolConformancesSection);
|
||||
if (start == nullptr || size == 0)
|
||||
return;
|
||||
addImageProtocolConformanceBlockCallbackUnsafe(start, size);
|
||||
addImageProtocolConformanceBlockCallbackUnsafe(__dso_handle, start, size);
|
||||
}
|
||||
void swift::initializeTypeMetadataRecordLookup() {
|
||||
void *start;
|
||||
@@ -56,7 +58,7 @@ void swift::initializeTypeMetadataRecordLookup() {
|
||||
MachOTypeMetadataRecordSection);
|
||||
if (start == nullptr || size == 0)
|
||||
return;
|
||||
addImageTypeMetadataRecordBlockCallbackUnsafe(start, size);
|
||||
addImageTypeMetadataRecordBlockCallbackUnsafe(__dso_handle, start, size);
|
||||
}
|
||||
|
||||
void swift::initializeDynamicReplacementLookup() {
|
||||
@@ -72,7 +74,8 @@ void swift::initializeDynamicReplacementLookup() {
|
||||
MachODynamicReplacementSection);
|
||||
if (start2 == nullptr || size2 == 0)
|
||||
return;
|
||||
addImageDynamicReplacementBlockCallback(start1, size1, start2, size2);
|
||||
addImageDynamicReplacementBlockCallback(__dso_handle,
|
||||
start1, size1, start2, size2);
|
||||
}
|
||||
void swift::initializeAccessibleFunctionsLookup() {
|
||||
void *start;
|
||||
@@ -81,7 +84,7 @@ void swift::initializeAccessibleFunctionsLookup() {
|
||||
MachOAccessibleFunctionsSection);
|
||||
if (start == nullptr || size == 0)
|
||||
return;
|
||||
addImageAccessibleFunctionsBlockCallbackUnsafe(start, size);
|
||||
addImageAccessibleFunctionsBlockCallbackUnsafe(__dso_handle, start, size);
|
||||
}
|
||||
|
||||
#endif // defined(__MACH__) && defined(SWIFT_RUNTIME_STATIC_IMAGE_INSPECTION)
|
||||
|
||||
@@ -263,6 +263,7 @@ _registerTypeMetadataRecords(TypeMetadataPrivateState &T,
|
||||
}
|
||||
|
||||
void swift::addImageTypeMetadataRecordBlockCallbackUnsafe(
|
||||
const void *baseAddress,
|
||||
const void *records, uintptr_t recordsSize) {
|
||||
assert(recordsSize % sizeof(TypeMetadataRecord) == 0
|
||||
&& "weird-sized type metadata section?!");
|
||||
@@ -282,10 +283,12 @@ void swift::addImageTypeMetadataRecordBlockCallbackUnsafe(
|
||||
recordsBegin, recordsEnd);
|
||||
}
|
||||
|
||||
void swift::addImageTypeMetadataRecordBlockCallback(const void *records,
|
||||
void swift::addImageTypeMetadataRecordBlockCallback(const void *baseAddress,
|
||||
const void *records,
|
||||
uintptr_t recordsSize) {
|
||||
TypeMetadataRecords.get();
|
||||
addImageTypeMetadataRecordBlockCallbackUnsafe(records, recordsSize);
|
||||
addImageTypeMetadataRecordBlockCallbackUnsafe(baseAddress,
|
||||
records, recordsSize);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -834,7 +837,8 @@ _registerProtocols(ProtocolMetadataPrivateState &C,
|
||||
C.SectionsToScan.push_back(ProtocolSection{begin, end});
|
||||
}
|
||||
|
||||
void swift::addImageProtocolsBlockCallbackUnsafe(const void *protocols,
|
||||
void swift::addImageProtocolsBlockCallbackUnsafe(const void *baseAddress,
|
||||
const void *protocols,
|
||||
uintptr_t protocolsSize) {
|
||||
assert(protocolsSize % sizeof(ProtocolRecord) == 0 &&
|
||||
"protocols section not a multiple of ProtocolRecord");
|
||||
@@ -851,10 +855,11 @@ void swift::addImageProtocolsBlockCallbackUnsafe(const void *protocols,
|
||||
recordsBegin, recordsEnd);
|
||||
}
|
||||
|
||||
void swift::addImageProtocolsBlockCallback(const void *protocols,
|
||||
void swift::addImageProtocolsBlockCallback(const void *baseAddress,
|
||||
const void *protocols,
|
||||
uintptr_t protocolsSize) {
|
||||
Protocols.get();
|
||||
addImageProtocolsBlockCallbackUnsafe(protocols, protocolsSize);
|
||||
addImageProtocolsBlockCallbackUnsafe(baseAddress, protocols, protocolsSize);
|
||||
}
|
||||
|
||||
void swift::swift_registerProtocols(const ProtocolRecord *begin,
|
||||
@@ -2477,6 +2482,7 @@ public:
|
||||
} // anonymous namespace
|
||||
|
||||
void swift::addImageDynamicReplacementBlockCallback(
|
||||
const void *baseAddress,
|
||||
const void *replacements, uintptr_t replacementsSize,
|
||||
const void *replacementsSome, uintptr_t replacementsSomeSize) {
|
||||
|
||||
|
||||
@@ -530,6 +530,7 @@ static void _registerProtocolConformances(ConformanceState &C,
|
||||
}
|
||||
|
||||
void swift::addImageProtocolConformanceBlockCallbackUnsafe(
|
||||
const void *baseAddress,
|
||||
const void *conformances, uintptr_t conformancesSize) {
|
||||
assert(conformancesSize % sizeof(ProtocolConformanceRecord) == 0 &&
|
||||
"conformances section not a multiple of ProtocolConformanceRecord");
|
||||
@@ -574,9 +575,11 @@ void swift::addImageProtocolConformanceBlockCallbackUnsafe(
|
||||
}
|
||||
|
||||
void swift::addImageProtocolConformanceBlockCallback(
|
||||
const void *baseAddress,
|
||||
const void *conformances, uintptr_t conformancesSize) {
|
||||
Conformances.get();
|
||||
addImageProtocolConformanceBlockCallbackUnsafe(conformances,
|
||||
addImageProtocolConformanceBlockCallbackUnsafe(baseAddress,
|
||||
conformances,
|
||||
conformancesSize);
|
||||
}
|
||||
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
extern "C" const char __ImageBase[];
|
||||
|
||||
#define PASTE_EXPANDED(a,b) a##b
|
||||
#define PASTE(a,b) PASTE_EXPANDED(a,b)
|
||||
|
||||
@@ -62,7 +64,7 @@ static void swift_image_constructor() {
|
||||
|
||||
sections = {
|
||||
swift::CurrentSectionMetadataVersion,
|
||||
0,
|
||||
__ImageBase,
|
||||
|
||||
nullptr,
|
||||
nullptr,
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
extern "C" const char __dso_handle[];
|
||||
|
||||
// Create empty sections to ensure that the start/stop symbols are synthesized
|
||||
// by the linker. Otherwise, we may end up with undefined symbol references as
|
||||
// the linker table section was never constructed.
|
||||
@@ -53,7 +55,7 @@ static void swift_image_constructor() {
|
||||
|
||||
sections = {
|
||||
swift::CurrentSectionMetadataVersion,
|
||||
0,
|
||||
__dso_handle,
|
||||
|
||||
nullptr,
|
||||
nullptr,
|
||||
|
||||
57
test/Runtime/loaded_image_uniqueness.swift
Normal file
57
test/Runtime/loaded_image_uniqueness.swift
Normal file
@@ -0,0 +1,57 @@
|
||||
// RUN: %target-run-simple-swift
|
||||
// REQUIRES: executable_test
|
||||
|
||||
import StdlibUnittest
|
||||
|
||||
// On Darwin platforms, dyld is expected to manage loaded sections/images for us
|
||||
// so there's no requirement to test that sections are correctly uniqued.
|
||||
#if INTERNAL_CHECKS_ENABLED && !canImport(Darwin)
|
||||
@_silgen_name("swift_getMetadataSection")
|
||||
internal func _getMetadataSection(_ index: UInt) -> UnsafeRawPointer?
|
||||
|
||||
@_silgen_name("swift_getMetadataSectionCount")
|
||||
internal func _getMetadataSectionCount() -> UInt
|
||||
|
||||
@_silgen_name("swift_getMetadataSectionName")
|
||||
internal func _getMetadataSectionName(
|
||||
_ metadata_section: UnsafeRawPointer
|
||||
) -> UnsafePointer<CChar>
|
||||
|
||||
@_silgen_name("swift_getMetadataSectionBaseAddress")
|
||||
internal func _getMetadataSectionBaseAddress(
|
||||
_ metadata_section: UnsafeRawPointer,
|
||||
_ outActual: UnsafeMutablePointer<UnsafeRawPointer?>,
|
||||
_ outExpected: UnsafeMutablePointer<UnsafeRawPointer?>
|
||||
) -> Void
|
||||
|
||||
do {
|
||||
let sectionCount = _getMetadataSectionCount()
|
||||
expectGT(sectionCount, 0)
|
||||
|
||||
var sections = Set<UnsafeRawPointer>()
|
||||
var images = Set<UnsafeRawPointer?>()
|
||||
for i in 0 ..< sectionCount {
|
||||
guard let section = _getMetadataSection(i) else {
|
||||
fatalError("Section \(i) failed to resolve.")
|
||||
}
|
||||
let name = String(cString: _getMetadataSectionName(section))
|
||||
|
||||
var actual: UnsafeRawPointer? = nil
|
||||
var expected: UnsafeRawPointer? = nil
|
||||
_getMetadataSectionBaseAddress(section, &actual, &expected)
|
||||
expectEqual(
|
||||
actual, expected,
|
||||
"""
|
||||
Section \(name) was expected at \(String(describing: expected)) but was
|
||||
found at \(String(describing: actual)) instead.
|
||||
"""
|
||||
)
|
||||
|
||||
expectFalse(sections.contains(section), "Section \(name) was found twice!")
|
||||
sections.insert(section)
|
||||
|
||||
expectFalse(images.contains(expected), "Image \(name) was found twice!")
|
||||
images.insert(expected)
|
||||
}
|
||||
}
|
||||
#endif
|
||||
Reference in New Issue
Block a user