Skip to content

[runtime] Refactor binary section data loading into separate file #5046

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

Closed
wants to merge 1 commit into from
Closed
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
1 change: 1 addition & 0 deletions stdlib/public/runtime/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ set(swift_runtime_sources
ProtocolConformance.cpp
ReflectionNative.cpp
RuntimeEntrySymbols.cpp
SectionData.cpp
SwiftObjectNative.cpp)

# Acknowledge that the following sources are known.
Expand Down
74 changes: 11 additions & 63 deletions stdlib/public/runtime/MetadataLookup.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,7 @@
#include "llvm/ADT/PointerIntPair.h"
#include "llvm/ADT/StringExtras.h"
#include "Private.h"

#if defined(__APPLE__) && defined(__MACH__)
#include <mach-o/dyld.h>
#include <mach-o/getsect.h>
#elif defined(__ELF__) || defined(__ANDROID__)
#include <elf.h>
#include <link.h>
#endif
#include "SectionData.h"

using namespace swift;
using namespace Demangle;
Expand All @@ -43,14 +36,6 @@ using namespace Demangle;
#include <objc/objc.h>
#endif

#if defined(__APPLE__) && defined(__MACH__)
#define SWIFT_TYPE_METADATA_SECTION "__swift2_types"
#elif defined(__ELF__)
#define SWIFT_TYPE_METADATA_SECTION ".swift2_type_metadata_start"
#elif defined(__CYGWIN__) || defined(_MSC_VER)
#define SWIFT_TYPE_METADATA_SECTION ".sw2tymd"
#endif

// Type Metadata Cache.

namespace {
Expand Down Expand Up @@ -89,18 +74,18 @@ namespace {
};
}

#if defined(__APPLE__) && defined(__MACH__)
static void _initializeCallbacksToInspectDylib();
#else
namespace swift {
void _swift_initializeCallbacksToInspectDylib(
void (*fnAddImageBlock)(const uint8_t *, size_t),
const char *sectionName);
}

static void _addImageTypeMetadataRecordsBlock(const uint8_t *records,
size_t recordsSize);

static InspectArgs metadataSectionArgs = {
#if defined(__APPLE__) && defined(__MACH__)
[](const mach_header *mh, intptr_t vmaddr_slide) {
_swift_readSectionData(mh, &metadataSectionArgs);
},
#endif
_addImageTypeMetadataRecordsBlock,
SWIFT_TYPE_METADATA_SECTION
};

struct TypeMetadataState {
ConcurrentMap<TypeMetadataCacheEntry> Cache;
Expand All @@ -109,15 +94,8 @@ struct TypeMetadataState {

TypeMetadataState() {
SectionsToScan.reserve(16);
#if defined(__APPLE__) && defined(__MACH__)
_initializeCallbacksToInspectDylib();
#else
_swift_initializeCallbacksToInspectDylib(
_addImageTypeMetadataRecordsBlock,
SWIFT_TYPE_METADATA_SECTION);
#endif
_swift_initializeCallbacksForSectionData(&metadataSectionArgs);
}

};

static Lazy<TypeMetadataState> TypeMetadataRecords;
Expand Down Expand Up @@ -147,36 +125,6 @@ static void _addImageTypeMetadataRecordsBlock(const uint8_t *records,
recordsBegin, recordsEnd);
}

#if defined(__APPLE__) && defined(__MACH__)
static void _addImageTypeMetadataRecords(const mach_header *mh,
intptr_t vmaddr_slide) {
#ifdef __LP64__
using mach_header_platform = mach_header_64;
assert(mh->magic == MH_MAGIC_64 && "loaded non-64-bit image?!");
#else
using mach_header_platform = mach_header;
#endif

// Look for a __swift2_types section.
unsigned long recordsSize;
const uint8_t *records =
getsectiondata(reinterpret_cast<const mach_header_platform *>(mh),
SEG_TEXT, SWIFT_TYPE_METADATA_SECTION,
&recordsSize);

if (!records)
return;

_addImageTypeMetadataRecordsBlock(records, recordsSize);
}

static void _initializeCallbacksToInspectDylib() {
// Install our dyld callback.
// Dyld will invoke this on our behalf for all images that have already
// been loaded.
_dyld_register_func_for_add_image(_addImageTypeMetadataRecords);
}
#endif

void
swift::swift_registerTypeMetadataRecords(const TypeMetadataRecord *begin,
Expand Down
182 changes: 11 additions & 171 deletions stdlib/public/runtime/ProtocolConformance.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,22 +20,7 @@
#include "swift/Runtime/Metadata.h"
#include "swift/Runtime/Mutex.h"
#include "Private.h"

#if defined(__APPLE__) && defined(__MACH__)
#include <mach-o/dyld.h>
#include <mach-o/getsect.h>
#elif defined(__ELF__) || defined(__ANDROID__)
#include <elf.h>
#include <link.h>
#endif

#if defined(_MSC_VER)
#define WIN32_LEAN_AND_MEAN
#define NOMINMAX
#include <windows.h>
#else
#include <dlfcn.h>
#endif
#include "SectionData.h"

using namespace swift;

Expand Down Expand Up @@ -146,14 +131,6 @@ const {
}
}

#if defined(__APPLE__) && defined(__MACH__)
#define SWIFT_PROTOCOL_CONFORMANCES_SECTION "__swift2_proto"
#elif defined(__ELF__)
#define SWIFT_PROTOCOL_CONFORMANCES_SECTION ".swift2_protocol_conformances_start"
#elif defined(__CYGWIN__) || defined(_MSC_VER)
#define SWIFT_PROTOCOL_CONFORMANCES_SECTION ".sw2prtc"
#endif

namespace {
struct ConformanceSection {
const ProtocolConformanceRecord *Begin, *End;
Expand Down Expand Up @@ -232,18 +209,19 @@ namespace {
}

// Conformance Cache.
#if defined(__APPLE__) && defined(__MACH__)
static void _initializeCallbacksToInspectDylib();
#else
namespace swift {
void _swift_initializeCallbacksToInspectDylib(
void (*fnAddImageBlock)(const uint8_t *, size_t),
const char *sectionName);
}

static void _addImageProtocolConformancesBlock(const uint8_t *conformances,
size_t conformancesSize);

static InspectArgs conformanceSectionArgs = {
#if defined(__APPLE__) && defined(__MACH__)
[](const mach_header *mh, intptr_t vmaddr_slide) {
_swift_readSectionData(mh, &conformanceSectionArgs);
},
#endif
_addImageProtocolConformancesBlock,
SWIFT_PROTOCOL_CONFORMANCES_SECTION
};

struct ConformanceState {
ConcurrentMap<ConformanceCacheEntry> Cache;
Expand All @@ -252,13 +230,7 @@ struct ConformanceState {

ConformanceState() {
SectionsToScan.reserve(16);
#if defined(__APPLE__) && defined(__MACH__)
_initializeCallbacksToInspectDylib();
#else
_swift_initializeCallbacksToInspectDylib(
_addImageProtocolConformancesBlock,
SWIFT_PROTOCOL_CONFORMANCES_SECTION);
#endif
_swift_initializeCallbacksForSectionData(&conformanceSectionArgs);
}

void cacheSuccess(const void *type, const ProtocolDescriptor *proto,
Expand Down Expand Up @@ -317,138 +289,6 @@ static void _addImageProtocolConformancesBlock(const uint8_t *conformances,
recordsBegin, recordsEnd);
}

#if !defined(__APPLE__) || !defined(__MACH__)
// Common Structure
struct InspectArgs {
void (*fnAddImageBlock)(const uint8_t *, size_t);
const char *sectionName;
};
#endif

#if defined(__APPLE__) && defined(__MACH__)
static void _addImageProtocolConformances(const mach_header *mh,
intptr_t vmaddr_slide) {
#ifdef __LP64__
using mach_header_platform = mach_header_64;
assert(mh->magic == MH_MAGIC_64 && "loaded non-64-bit image?!");
#else
using mach_header_platform = mach_header;
#endif

// Look for a __swift2_proto section.
unsigned long conformancesSize;
const uint8_t *conformances =
getsectiondata(reinterpret_cast<const mach_header_platform *>(mh),
SEG_TEXT, SWIFT_PROTOCOL_CONFORMANCES_SECTION,
&conformancesSize);

if (!conformances)
return;

_addImageProtocolConformancesBlock(conformances, conformancesSize);
}

static void _initializeCallbacksToInspectDylib() {
// Install our dyld callback.
// Dyld will invoke this on our behalf for all images that have already
// been loaded.
_dyld_register_func_for_add_image(_addImageProtocolConformances);
}

#elif defined(__ELF__) || defined(__ANDROID__)
static int _addImageProtocolConformances(struct dl_phdr_info *info,
size_t size, void *data) {
// inspectArgs contains addImage*Block function and the section name
InspectArgs *inspectArgs = reinterpret_cast<InspectArgs *>(data);

void *handle;
if (!info->dlpi_name || info->dlpi_name[0] == '\0') {
handle = dlopen(nullptr, RTLD_LAZY);
} else
handle = dlopen(info->dlpi_name, RTLD_LAZY | RTLD_NOLOAD);

if (!handle) {
// Not a shared library.
return 0;
}

auto conformances = reinterpret_cast<const uint8_t*>(
dlsym(handle, inspectArgs->sectionName));

if (!conformances) {
// if there are no conformances, don't hold this handle open.
dlclose(handle);
return 0;
}

// Extract the size of the conformances block from the head of the section
auto conformancesSize = *reinterpret_cast<const uint64_t*>(conformances);
conformances += sizeof(conformancesSize);

inspectArgs->fnAddImageBlock(conformances, conformancesSize);

dlclose(handle);
return 0;
}

void swift::_swift_initializeCallbacksToInspectDylib(
void (*fnAddImageBlock)(const uint8_t *, size_t),
const char *sectionName) {
InspectArgs inspectArgs = {fnAddImageBlock, sectionName};

// Search the loaded dls. Unlike the above, this only searches the already
// loaded ones.
// FIXME: Find a way to have this continue to happen after.
// rdar://problem/19045112
dl_iterate_phdr(_addImageProtocolConformances, &inspectArgs);
}
#elif defined(__CYGWIN__) || defined(_MSC_VER)
static int _addImageProtocolConformances(struct dl_phdr_info *info,
size_t size, void *data) {
InspectArgs *inspectArgs = (InspectArgs *)data;
// inspectArgs contains addImage*Block function and the section name
#if defined(_MSC_VER)
HMODULE handle;

if (!info->dlpi_name || info->dlpi_name[0] == '\0')
handle = GetModuleHandle(nullptr);
else
handle = GetModuleHandle(info->dlpi_name);
#else
void *handle;
if (!info->dlpi_name || info->dlpi_name[0] == '\0')
handle = dlopen(nullptr, RTLD_LAZY);
else
handle = dlopen(info->dlpi_name, RTLD_LAZY | RTLD_NOLOAD);
#endif

unsigned long conformancesSize;
const uint8_t *conformances =
_swift_getSectionDataPE(handle, inspectArgs->sectionName,
&conformancesSize);

if (conformances)
inspectArgs->fnAddImageBlock(conformances, conformancesSize);

#if defined(_MSC_VER)
FreeLibrary(handle);
#else
dlclose(handle);
#endif
return 0;
}

void swift::_swift_initializeCallbacksToInspectDylib(
void (*fnAddImageBlock)(const uint8_t *, size_t),
const char *sectionName) {
InspectArgs inspectArgs = {fnAddImageBlock, sectionName};

_swift_dl_iterate_phdr(_addImageProtocolConformances, &inspectArgs);
}
#else
# error No known mechanism to inspect dynamic libraries on this platform.
#endif

// This variable is used to signal when a cache was generated and
// it is correct to avoid a new scan.
static unsigned ConformanceCacheGeneration = 0;
Expand Down
Loading