Skip to content

Unify COFF and ELF data structures and procedures #32478

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

Merged
merged 1 commit into from
Jun 30, 2020
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
6 changes: 2 additions & 4 deletions include/swift/Reflection/ReflectionContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -320,10 +320,8 @@ class ReflectionContext

// FIXME: This code needs to be cleaned up and updated
// to make it work for 32 bit platforms.
if (SectionName != ".sw5cptr" && SectionName != ".sw5bltn") {
Begin = Begin.atByteOffset(8);
Size -= 16;
}
Begin = Begin.atByteOffset(8);
Size -= 16;

return {Begin, Size};
}
Expand Down
11 changes: 11 additions & 0 deletions stdlib/public/SwiftShims/MetadataSections.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,15 +29,26 @@ namespace swift {
extern "C" {
#endif

/// Specifies the address range corresponding to a section.
typedef struct MetadataSectionRange {
__swift_uintptr_t start;
__swift_size_t length;
} MetadataSectionRange;


/// Identifies the address space ranges for the Swift metadata required by the Swift runtime.
struct MetadataSections {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you please add doxygen comments to each type declaration (and any non-obvious members)?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added a doxygen comment for each declaration, although I'm not sure if they're very useful right now.

@compnerd since you wrote these data structures, do you think I should add something more to the documentation?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor nit: the doxygen comments in this repository uses /// for the comment leader.
I would describe them as:

/// Specifies the address range corresponding to a section.

and

/// Identifies the address space ranges for the Swift metadata required by the Swift runtime.

The two fields that are are "non-obvious" are next and prev:

/// `next` and `prev` are used by the runtime to construct a
/// circularly doubly linked list to quickly iterate over the metadata
/// from each image loaded into the address space.  These are invasive
/// to enable the runtime registration, which occurs at image load time, to
/// be allocation-free as it is invoked from an image constructor function
/// context where the system may not yet be ready to perform allocations.
/// Additionally, avoiding the allocation enables a fast load operation, which
/// directly impacts application load time.

__swift_uintptr_t version;
__swift_uintptr_t reserved;

/// `next` and `prev` are used by the runtime to construct a
/// circularly doubly linked list to quickly iterate over the metadata
/// from each image loaded into the address space. These are invasive
/// to enable the runtime registration, which occurs at image load time, to
/// be allocation-free as it is invoked from an image constructor function
/// context where the system may not yet be ready to perform allocations.
/// Additionally, avoiding the allocation enables a fast load operation, which
/// directly impacts application load time.
struct MetadataSections *next;
struct MetadataSections *prev;

Expand Down
1 change: 1 addition & 0 deletions stdlib/public/runtime/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ set(swift_runtime_sources
Float16Support.cpp
Heap.cpp
HeapObject.cpp
ImageInspectionCommon.cpp
ImageInspectionMachO.cpp
ImageInspectionELF.cpp
ImageInspectionCOFF.cpp
Expand Down
109 changes: 0 additions & 109 deletions stdlib/public/runtime/ImageInspectionCOFF.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
#if !defined(__ELF__) && !defined(__MACH__)

#include "ImageInspection.h"
#include "ImageInspectionCOFF.h"

#if defined(__CYGWIN__)
#include <dlfcn.h>
Expand All @@ -26,108 +25,6 @@

using namespace swift;

namespace {
static const swift::MetadataSections *registered = nullptr;

void record(const swift::MetadataSections *sections) {
if (registered == nullptr) {
registered = sections;
sections->next = sections->prev = sections;
} else {
registered->prev->next = sections;
sections->next = registered;
sections->prev = registered->prev;
registered->prev = sections;
}
}
}

void swift::initializeProtocolLookup() {
const swift::MetadataSections *sections = registered;
while (true) {
const swift::MetadataSections::Range &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::MetadataSections::Range &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::MetadataSections::Range &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() {
}

SWIFT_RUNTIME_EXPORT
void swift_addNewDSOImage(const void *addr) {
const swift::MetadataSections *sections =
static_cast<const swift::MetadataSections *>(addr);

record(sections);

const auto &protocols_section = sections->swift5_protocols;
const void *protocols =
reinterpret_cast<void *>(protocols_section.start);
if (protocols_section.length)
addImageProtocolsBlockCallback(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)
addImageProtocolConformanceBlockCallback(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)
addImageTypeMetadataRecordBlockCallback(metadata, type_metadata.length);

const auto &dynamic_replacements = sections->swift5_repl;
const auto *replacements =
reinterpret_cast<void *>(dynamic_replacements.start);
if (dynamic_replacements.length) {
const auto &dynamic_replacements_some = sections->swift5_reps;
const auto *replacements_some =
reinterpret_cast<void *>(dynamic_replacements_some.start);
addImageDynamicReplacementBlockCallback(
replacements, dynamic_replacements.length, replacements_some,
dynamic_replacements_some.length);
}
}

int swift::lookupSymbol(const void *address, SymbolInfo *info) {
#if defined(__CYGWIN__)
Dl_info dlinfo;
Expand Down Expand Up @@ -173,10 +70,4 @@ int swift::lookupSymbol(const void *address, SymbolInfo *info) {
#endif // defined(__CYGWIN__) || defined(_WIN32)
}

// This is only used for backward deployment hooks, which we currently only support for
// MachO. Add a stub here to make sure it still compiles.
void *swift::lookupSection(const char *segment, const char *section, size_t *outSize) {
return nullptr;
}

#endif // !defined(__ELF__) && !defined(__MACH__)
66 changes: 0 additions & 66 deletions stdlib/public/runtime/ImageInspectionCOFF.h

This file was deleted.

143 changes: 143 additions & 0 deletions stdlib/public/runtime/ImageInspectionCommon.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
//===--- ImageInspectionCommon.cpp - Image inspection routines --*- C++ -*-===//
//
// 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
//
//===----------------------------------------------------------------------===//
///
/// \file
///
/// This file unifies common ELF and COFF image inspection routines
///
//===----------------------------------------------------------------------===//

#ifndef SWIFT_RUNTIME_IMAGEINSPECTIONCOMMON_H
#define SWIFT_RUNTIME_IMAGEINSPECTIONCOMMON_H

#if !defined(__MACH__)

#include "../SwiftShims/Visibility.h"
#include "../SwiftShims/MetadataSections.h"
#include "ImageInspection.h"


namespace swift {

static swift::MetadataSections *registered = nullptr;

void record(swift::MetadataSections *sections) {
if (registered == nullptr) {
registered = sections;
sections->next = sections->prev = sections;
} else {
registered->prev->next = sections;
sections->next = registered;
sections->prev = registered->prev;
registered->prev = sections;
}
}
}

SWIFT_RUNTIME_EXPORT
void swift_addNewDSOImage(const void *addr) {
const swift::MetadataSections *sections =
static_cast<const swift::MetadataSections *>(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.
auto casted_sections = const_cast<swift::MetadataSections *>(sections);
record(casted_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);

const auto &protocol_conformances = sections->swift5_protocol_conformances;
const void *conformances =
reinterpret_cast<void *>(protocol_conformances.start);
if (protocol_conformances.length)
swift::addImageProtocolConformanceBlockCallback(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);

const auto &dynamic_replacements = sections->swift5_replace;
const auto *replacements =
reinterpret_cast<void *>(dynamic_replacements.start);
if (dynamic_replacements.length) {
const auto &dynamic_replacements_some = sections->swift5_replac2;
const auto *replacements_some =
reinterpret_cast<void *>(dynamic_replacements_some.start);
swift::addImageDynamicReplacementBlockCallback(
replacements, dynamic_replacements.length, replacements_some,
dynamic_replacements_some.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() {
}

// This is only used for backward deployment hooks, which we currently only support for
// MachO. Add a stub here to make sure it still compiles.
void *swift::lookupSection(const char *segment, const char *section, size_t *outSize) {
return nullptr;
}

#endif // !defined(__MACH__)

#endif // SWIFT_RUNTIME_IMAGEINSPECTIONCOMMON_H
Loading