Skip to content

Add extraction of protocol conformance descriptor info, as read from an object file image, to TypeRefBuilder. #41027

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 8 commits into from
Feb 2, 2022
Merged
49 changes: 48 additions & 1 deletion include/swift/ABI/Metadata.h
Original file line number Diff line number Diff line change
Expand Up @@ -540,6 +540,9 @@ namespace {

using TypeContextDescriptor = TargetTypeContextDescriptor<InProcess>;

template<template <typename Runtime> class ObjCInteropKind, unsigned PointerSize>
using ExternalTypeContextDescriptor = TargetTypeContextDescriptor<External<ObjCInteropKind<RuntimeTarget<PointerSize>>>>;

// FIXME: https://bugs.swift.org/browse/SR-1155
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Winvalid-offsetof"
Expand Down Expand Up @@ -2106,7 +2109,10 @@ using ProtocolRequirement = TargetProtocolRequirement<InProcess>;

template<typename Runtime> struct TargetProtocolDescriptor;
using ProtocolDescriptor = TargetProtocolDescriptor<InProcess>;


template<template <typename Runtime> class ObjCInteropKind, unsigned PointerSize>
using ExternalProtocolDescriptor = TargetProtocolDescriptor<External<ObjCInteropKind<RuntimeTarget<PointerSize>>>>;

/// A witness table for a protocol.
///
/// With the exception of the initial protocol conformance descriptor,
Expand Down Expand Up @@ -2722,6 +2728,16 @@ struct TargetProtocolConformanceDescriptor final
return TypeRef.getTypeDescriptor(getTypeKind());
}

constexpr inline auto
getTypeRefDescriptorOffset() const -> typename Runtime::StoredSize {
return offsetof(typename std::remove_reference<decltype(*this)>::type, TypeRef);
}

constexpr inline auto
getProtocolDescriptorOffset() const -> typename Runtime::StoredSize {
return offsetof(typename std::remove_reference<decltype(*this)>::type, Protocol);
}

TargetContextDescriptor<Runtime> * __ptrauth_swift_type_descriptor *
_getTypeDescriptorLocation() const {
if (getTypeKind() != TypeReferenceKind::IndirectTypeDescriptor)
Expand Down Expand Up @@ -2840,6 +2856,12 @@ using TargetProtocolConformanceRecord =

using ProtocolConformanceRecord = TargetProtocolConformanceRecord<InProcess>;

template<template <typename Runtime> class ObjCInteropKind, unsigned PointerSize>
using ExternalProtocolConformanceDescriptor = TargetProtocolConformanceDescriptor<External<ObjCInteropKind<RuntimeTarget<PointerSize>>>>;

template<template <typename Runtime> class ObjCInteropKind, unsigned PointerSize>
using ExternalProtocolConformanceRecord = TargetProtocolConformanceRecord<External<ObjCInteropKind<RuntimeTarget<PointerSize>>>>;

template<typename Runtime>
struct TargetGenericContext;

Expand Down Expand Up @@ -2876,6 +2898,11 @@ struct TargetContextDescriptor {
: 0;
}

constexpr inline auto
getParentOffset() const -> typename Runtime::StoredSize {
return offsetof(typename std::remove_reference<decltype(*this)>::type, Parent);
}

#ifndef NDEBUG
LLVM_ATTRIBUTE_DEPRECATED(void dump() const,
"only for use in the debugger");
Expand All @@ -2889,6 +2916,8 @@ struct TargetContextDescriptor {
};

using ContextDescriptor = TargetContextDescriptor<InProcess>;
template<template <typename Runtime> class ObjCInteropKind, unsigned PointerSize>
using ExternalContextDescriptor = TargetContextDescriptor<External<ObjCInteropKind<RuntimeTarget<PointerSize>>>>;

inline bool isCImportedModuleName(llvm::StringRef name) {
// This does not include MANGLING_MODULE_CLANG_IMPORTER because that's
Expand All @@ -2908,13 +2937,21 @@ struct TargetModuleContextDescriptor final : TargetContextDescriptor<Runtime> {
return isCImportedModuleName(Name.get());
}

constexpr inline auto
getNameOffset() const -> typename Runtime::StoredSize {
return offsetof(typename std::remove_reference<decltype(*this)>::type, Name);
}

static bool classof(const TargetContextDescriptor<Runtime> *cd) {
return cd->getKind() == ContextDescriptorKind::Module;
}
};

using ModuleContextDescriptor = TargetModuleContextDescriptor<InProcess>;

template<template <typename Runtime> class ObjCInteropKind, unsigned PointerSize>
using ExternalModuleContextDescriptor = TargetModuleContextDescriptor<External<ObjCInteropKind<RuntimeTarget<PointerSize>>>>;

template<typename Runtime>
inline bool TargetContextDescriptor<Runtime>::isCImportedContext() const {
return getModuleContext()->isCImportedContext();
Expand Down Expand Up @@ -3413,6 +3450,11 @@ struct TargetProtocolDescriptor final
NumRequirements};
}

constexpr inline auto
getNameOffset() const -> typename Runtime::StoredSize {
return offsetof(typename std::remove_reference<decltype(*this)>::type, Name);
}

/// Retrieve the requirement base descriptor address.
ConstTargetPointer<Runtime, TargetProtocolRequirement<Runtime>>
getRequirementBaseDescriptor() const {
Expand Down Expand Up @@ -4077,6 +4119,11 @@ class TargetTypeContextDescriptor
/// type's metadata. The returned value is measured in sizeof(StoredPointer).
int32_t getGenericArgumentOffset() const;

constexpr inline auto
getNameOffset() const -> typename Runtime::StoredSize {
return offsetof(typename std::remove_reference<decltype(*this)>::type, Name);
}

/// Return the start of the generic arguments array in the nominal
/// type's metadata. The returned value is measured in sizeof(StoredPointer).
const TargetMetadata<Runtime> * const *getGenericArguments(
Expand Down
18 changes: 16 additions & 2 deletions include/swift/ABI/ObjectFile.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,16 @@

namespace swift {

/// Represents the six reflection sections used by Swift
/// Represents the eight reflection sections used by Swift
enum ReflectionSectionKind : uint8_t {
fieldmd,
assocty,
builtin,
capture,
typeref,
reflstr
reflstr,
conform,
protocs
};

/// Abstract base class responsible for providing the correct reflection section
Expand Down Expand Up @@ -47,6 +49,10 @@ class SwiftObjectFileFormatMachO : public SwiftObjectFileFormat {
return "__swift5_typeref";
case reflstr:
return "__swift5_reflstr";
case conform:
return "__swift5_proto";
case protocs:
return "__swift5_protos";
}
llvm_unreachable("Section type not found.");
}
Expand All @@ -69,6 +75,10 @@ class SwiftObjectFileFormatELF : public SwiftObjectFileFormat {
return "swift5_typeref";
case reflstr:
return "swift5_reflstr";
case conform:
return "swift5_protocol_conformances";
case protocs:
return "swift5_protocols";
}
llvm_unreachable("Section type not found.");
}
Expand All @@ -91,6 +101,10 @@ class SwiftObjectFileFormatCOFF : public SwiftObjectFileFormat {
return ".sw5tyrf";
case reflstr:
return ".sw5rfst";
case conform:
return ".sw5prtc$B";
case protocs:
return ".sw5prt$B";
}
llvm_unreachable("Section not found.");
}
Expand Down
15 changes: 15 additions & 0 deletions include/swift/Basic/RelativePointer.h
Original file line number Diff line number Diff line change
Expand Up @@ -442,6 +442,17 @@ class RelativeDirectPointerImpl {
return reinterpret_cast<PointerTy>(absolute);
}

/// Apply the offset to a parameter, instead of `this`.
PointerTy getRelative(void *base) const & {
// Check for null.
if (Nullable && RelativeOffset == 0)
return nullptr;

// The value is addressed relative to `base`.
uintptr_t absolute = detail::applyRelativeOffset(base, RelativeOffset);
return reinterpret_cast<PointerTy>(absolute);
}

/// A zero relative offset encodes a null reference.
bool isNull() const & {
return RelativeOffset == 0;
Expand Down Expand Up @@ -476,6 +487,10 @@ class RelativeDirectPointer<T, Nullable, Offset,
return this->get();
}

const typename super::ValueTy* getRelative(void *base) const & {
return this->super::getRelative(base);
}

using super::isNull;
};

Expand Down
34 changes: 25 additions & 9 deletions include/swift/Reflection/ReflectionContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -219,8 +219,9 @@ class ReflectionContext
for (unsigned I = 0; I < NumSect; ++I) {
auto S = reinterpret_cast<typename T::Section *>(
SectionsBuf + (I * sizeof(typename T::Section)));
if (strncmp(S->sectname, Name.data(), strlen(Name.data())) != 0)
if (strncmp(S->sectname, Name.data(), sizeof(S->sectname)) != 0)
continue;

auto RemoteSecStart = S->addr + Slide;
auto LocalSectBuf =
this->getReader().readBytes(RemoteAddress(RemoteSecStart), S->size);
Expand All @@ -247,13 +248,16 @@ class ReflectionContext
ObjectFileFormat.getSectionName(ReflectionSectionKind::typeref));
auto ReflStrMdSec = findMachOSectionByName(
ObjectFileFormat.getSectionName(ReflectionSectionKind::reflstr));
auto ConformMdSec = findMachOSectionByName(
ObjectFileFormat.getSectionName(ReflectionSectionKind::conform));

if (FieldMdSec.first == nullptr &&
AssocTySec.first == nullptr &&
BuiltinTySec.first == nullptr &&
CaptureSec.first == nullptr &&
TypeRefMdSec.first == nullptr &&
ReflStrMdSec.first == nullptr)
ReflStrMdSec.first == nullptr &&
ConformMdSec.first == nullptr)
return false;

ReflectionInfo info = {
Expand All @@ -262,7 +266,8 @@ class ReflectionContext
{BuiltinTySec.first, BuiltinTySec.second},
{CaptureSec.first, CaptureSec.second},
{TypeRefMdSec.first, TypeRefMdSec.second},
{ReflStrMdSec.first, ReflStrMdSec.second}};
{ReflStrMdSec.first, ReflStrMdSec.second},
{ConformMdSec.first, ConformMdSec.second}};

this->addReflectionInfo(info);

Expand Down Expand Up @@ -365,13 +370,16 @@ class ReflectionContext
ObjectFileFormat.getSectionName(ReflectionSectionKind::typeref));
auto ReflStrMdSec = findCOFFSectionByName(
ObjectFileFormat.getSectionName(ReflectionSectionKind::reflstr));
auto ConformMdSec = findCOFFSectionByName(
ObjectFileFormat.getSectionName(ReflectionSectionKind::conform));

if (FieldMdSec.first == nullptr &&
AssocTySec.first == nullptr &&
BuiltinTySec.first == nullptr &&
CaptureSec.first == nullptr &&
TypeRefMdSec.first == nullptr &&
ReflStrMdSec.first == nullptr)
ReflStrMdSec.first == nullptr &&
ConformMdSec.first == nullptr)
return false;

ReflectionInfo Info = {
Expand All @@ -380,7 +388,8 @@ class ReflectionContext
{BuiltinTySec.first, BuiltinTySec.second},
{CaptureSec.first, CaptureSec.second},
{TypeRefMdSec.first, TypeRefMdSec.second},
{ReflStrMdSec.first, ReflStrMdSec.second}};
{ReflStrMdSec.first, ReflStrMdSec.second},
{ConformMdSec.first, ConformMdSec.second}};
this->addReflectionInfo(Info);
return true;
}
Expand Down Expand Up @@ -544,6 +553,8 @@ class ReflectionContext
ObjectFileFormat.getSectionName(ReflectionSectionKind::typeref));
auto ReflStrMdSec = findELFSectionByName(
ObjectFileFormat.getSectionName(ReflectionSectionKind::reflstr));
auto ConformMdSec = findELFSectionByName(
ObjectFileFormat.getSectionName(ReflectionSectionKind::conform));

if (Error)
return false;
Expand All @@ -555,7 +566,8 @@ class ReflectionContext
BuiltinTySec.first == nullptr &&
CaptureSec.first == nullptr &&
TypeRefMdSec.first == nullptr &&
ReflStrMdSec.first == nullptr)
ReflStrMdSec.first == nullptr &&
ConformMdSec.first == nullptr)
return false;

ReflectionInfo info = {
Expand All @@ -564,7 +576,8 @@ class ReflectionContext
{BuiltinTySec.first, BuiltinTySec.second},
{CaptureSec.first, CaptureSec.second},
{TypeRefMdSec.first, TypeRefMdSec.second},
{ReflStrMdSec.first, ReflStrMdSec.second}};
{ReflStrMdSec.first, ReflStrMdSec.second},
{ConformMdSec.first, ConformMdSec.second}};

this->addReflectionInfo(info);
return true;
Expand Down Expand Up @@ -665,7 +678,9 @@ class ReflectionContext
auto Sections = {
ReflectionSectionKind::fieldmd, ReflectionSectionKind::assocty,
ReflectionSectionKind::builtin, ReflectionSectionKind::capture,
ReflectionSectionKind::typeref, ReflectionSectionKind::reflstr};
ReflectionSectionKind::typeref, ReflectionSectionKind::reflstr,
ReflectionSectionKind::conform
};

llvm::SmallVector<std::pair<RemoteRef<void>, uint64_t>, 6> Pairs;
for (auto Section : Sections) {
Expand All @@ -687,7 +702,8 @@ class ReflectionContext
ReflectionInfo Info = {
{Pairs[0].first, Pairs[0].second}, {Pairs[1].first, Pairs[1].second},
{Pairs[2].first, Pairs[2].second}, {Pairs[3].first, Pairs[3].second},
{Pairs[4].first, Pairs[4].second}, {Pairs[5].first, Pairs[5].second}};
{Pairs[4].first, Pairs[4].second}, {Pairs[5].first, Pairs[5].second},
{Pairs[6].first, Pairs[6].second}};
this->addReflectionInfo(Info);
return true;
}
Expand Down
Loading