Skip to content

Disable resilience for modules imported by the MemoryBuffer loader. #39032

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
Sep 20, 2021
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
9 changes: 9 additions & 0 deletions include/swift/AST/Module.h
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,9 @@ class ModuleDecl

AccessNotesFile accessNotes;

/// Used by the debugger to bypass resilient access to fields.
bool BypassResilience = false;

ModuleDecl(Identifier name, ASTContext &ctx, ImplicitImportInfo importInfo);

public:
Expand Down Expand Up @@ -290,6 +293,12 @@ class ModuleDecl
AccessNotesFile &getAccessNotes() { return accessNotes; }
const AccessNotesFile &getAccessNotes() const { return accessNotes; }

/// Return whether the module was imported with resilience disabled. The
/// debugger does this to access private fields.
bool getBypassResilience() const { return BypassResilience; }
/// Only to be called by MemoryBufferSerializedModuleLoader.
void setBypassResilience() { BypassResilience = true; }

ArrayRef<FileUnit *> getFiles() {
assert(!Files.empty() || failedToLoad());
return Files;
Expand Down
13 changes: 8 additions & 5 deletions include/swift/Serialization/SerializedModuleLoader.h
Original file line number Diff line number Diff line change
Expand Up @@ -261,9 +261,11 @@ class MemoryBufferSerializedModuleLoader : public SerializedModuleLoaderBase {
MemoryBufferSerializedModuleLoader(ASTContext &ctx,
DependencyTracker *tracker,
ModuleLoadingMode loadMode,
bool IgnoreSwiftSourceInfo)
bool IgnoreSwiftSourceInfo,
bool BypassResilience)
: SerializedModuleLoaderBase(ctx, tracker, loadMode,
IgnoreSwiftSourceInfo) {}
IgnoreSwiftSourceInfo),
BypassResilience(BypassResilience) {}

std::error_code findModuleFilesInDirectory(
ImportPath::Element ModuleID,
Expand All @@ -279,6 +281,7 @@ class MemoryBufferSerializedModuleLoader : public SerializedModuleLoaderBase {
StringRef moduleName,
const SerializedModuleBaseName &BaseName) override;

bool BypassResilience;
public:
virtual ~MemoryBufferSerializedModuleLoader();

Expand Down Expand Up @@ -308,10 +311,10 @@ class MemoryBufferSerializedModuleLoader : public SerializedModuleLoaderBase {
static std::unique_ptr<MemoryBufferSerializedModuleLoader>
create(ASTContext &ctx, DependencyTracker *tracker = nullptr,
ModuleLoadingMode loadMode = ModuleLoadingMode::PreferSerialized,
bool IgnoreSwiftSourceInfo = false) {
bool IgnoreSwiftSourceInfo = false, bool BypassResilience = false) {
return std::unique_ptr<MemoryBufferSerializedModuleLoader>{
new MemoryBufferSerializedModuleLoader(ctx, tracker, loadMode,
IgnoreSwiftSourceInfo)};
new MemoryBufferSerializedModuleLoader(
ctx, tracker, loadMode, IgnoreSwiftSourceInfo, BypassResilience)};
}
};

Expand Down
2 changes: 1 addition & 1 deletion lib/AST/Decl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1879,7 +1879,7 @@ static bool isDirectToStorageAccess(const DeclContext *UseDC,
// If the storage is resilient, we cannot access it directly at all.
if (var->isResilient(UseDC->getParentModule(),
UseDC->getResilienceExpansion()))
return false;
return var->getModuleContext()->getBypassResilience();

if (isa<ConstructorDecl>(AFD) || isa<DestructorDecl>(AFD)) {
// The access must also be a member access on 'self' in all language modes.
Expand Down
5 changes: 4 additions & 1 deletion lib/IRGen/GenDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4968,7 +4968,10 @@ llvm::Constant *IRGenModule::getAddrOfGlobalUTF16String(StringRef utf8) {
/// - For enums, new cases can be added
/// - For classes, the superclass might change the size or number
/// of stored properties
bool IRGenModule::isResilient(NominalTypeDecl *D, ResilienceExpansion expansion) {
bool IRGenModule::isResilient(NominalTypeDecl *D,
ResilienceExpansion expansion) {
if (D->getModuleContext()->getBypassResilience())
return false;
if (expansion == ResilienceExpansion::Maximal &&
Types.getLoweringMode() == TypeConverter::Mode::CompletelyFragile) {
return false;
Expand Down
33 changes: 21 additions & 12 deletions lib/SIL/Verifier/SILVerifier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,15 @@ static bool isArchetypeValidInFunction(ArchetypeType *A, const SILFunction *F) {

namespace {

/// When resilience is bypassed, direct access is legal, but the decls are still
/// resilient.
template <typename DeclType>
bool checkResilience(DeclType *D, ModuleDecl *M,
ResilienceExpansion expansion) {
return !D->getModuleContext()->getBypassResilience() &&
D->isResilient(M, expansion);
}

/// Metaprogramming-friendly base class.
template <class Impl>
class SILVerifierBase : public SILInstructionVisitor<Impl> {
Expand Down Expand Up @@ -234,7 +243,7 @@ void verifyKeyPathComponent(SILModule &M,
"property decl should be a member of the base with the same type "
"as the component");
require(property->hasStorage(), "property must be stored");
require(!property->isResilient(M.getSwiftModule(), expansion),
require(!checkResilience(property, M.getSwiftModule(), expansion),
"cannot access storage of resilient property");
auto propertyTy =
loweredBaseTy.getFieldType(property, M, typeExpansionContext);
Expand Down Expand Up @@ -1970,7 +1979,7 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
void checkAllocGlobalInst(AllocGlobalInst *AGI) {
SILGlobalVariable *RefG = AGI->getReferencedGlobal();
if (auto *VD = RefG->getDecl()) {
require(!VD->isResilient(F.getModule().getSwiftModule(),
require(!checkResilience(VD, F.getModule().getSwiftModule(),
F.getResilienceExpansion()),
"cannot access storage of resilient global");
}
Expand All @@ -1989,7 +1998,7 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
RefG->getLoweredTypeInContext(F.getTypeExpansionContext()),
"global_addr/value must be the type of the variable it references");
if (auto *VD = RefG->getDecl()) {
require(!VD->isResilient(F.getModule().getSwiftModule(),
require(!checkResilience(VD, F.getModule().getSwiftModule(),
F.getResilienceExpansion()),
"cannot access storage of resilient global");
}
Expand Down Expand Up @@ -2677,8 +2686,8 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
require(!structDecl->hasUnreferenceableStorage(),
"Cannot build a struct with unreferenceable storage from elements "
"using StructInst");
require(!structDecl->isResilient(F.getModule().getSwiftModule(),
F.getResilienceExpansion()),
require(!checkResilience(structDecl, F.getModule().getSwiftModule(),
F.getResilienceExpansion()),
"cannot access storage of resilient struct");
require(SI->getType().isObject(),
"StructInst must produce an object");
Expand Down Expand Up @@ -2879,8 +2888,8 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
require(cd, "Operand of dealloc_ref must be of class type");

if (!DI->canAllocOnStack()) {
require(!cd->isResilient(F.getModule().getSwiftModule(),
F.getResilienceExpansion()),
require(!checkResilience(cd, F.getModule().getSwiftModule(),
F.getResilienceExpansion()),
"cannot directly deallocate resilient class");
}
}
Expand Down Expand Up @@ -2996,7 +3005,7 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
"result of struct_extract cannot be address");
StructDecl *sd = operandTy.getStructOrBoundGenericStruct();
require(sd, "must struct_extract from struct");
require(!sd->isResilient(F.getModule().getSwiftModule(),
require(!checkResilience(sd, F.getModule().getSwiftModule(),
F.getResilienceExpansion()),
"cannot access storage of resilient struct");
require(!EI->getField()->isStatic(),
Expand Down Expand Up @@ -3045,7 +3054,7 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
"must derive struct_element_addr from address");
StructDecl *sd = operandTy.getStructOrBoundGenericStruct();
require(sd, "struct_element_addr operand must be struct address");
require(!sd->isResilient(F.getModule().getSwiftModule(),
require(!checkResilience(sd, F.getModule().getSwiftModule(),
F.getResilienceExpansion()),
"cannot access storage of resilient struct");
require(EI->getType().isAddress(),
Expand Down Expand Up @@ -3078,7 +3087,7 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
SILType operandTy = EI->getOperand()->getType();
ClassDecl *cd = operandTy.getClassOrBoundGenericClass();
require(cd, "ref_element_addr operand must be a class instance");
require(!cd->isResilient(F.getModule().getSwiftModule(),
require(!checkResilience(cd, F.getModule().getSwiftModule(),
F.getResilienceExpansion()),
"cannot access storage of resilient class");

Expand All @@ -3102,7 +3111,7 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
SILType operandTy = RTAI->getOperand()->getType();
ClassDecl *cd = operandTy.getClassOrBoundGenericClass();
require(cd, "ref_tail_addr operand must be a class instance");
require(!cd->isResilient(F.getModule().getSwiftModule(),
require(!checkResilience(cd, F.getModule().getSwiftModule(),
F.getResilienceExpansion()),
"cannot access storage of resilient class");
require(cd, "ref_tail_addr operand must be a class instance");
Expand All @@ -3112,7 +3121,7 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
SILType operandTy = DSI->getOperand()->getType();
StructDecl *sd = operandTy.getStructOrBoundGenericStruct();
require(sd, "must struct_extract from struct");
require(!sd->isResilient(F.getModule().getSwiftModule(),
require(!checkResilience(sd, F.getModule().getSwiftModule(),
F.getResilienceExpansion()),
"cannot access storage of resilient struct");
if (F.hasOwnership()) {
Expand Down
5 changes: 5 additions & 0 deletions lib/Serialization/SerializedModuleLoader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1205,6 +1205,11 @@ MemoryBufferSerializedModuleLoader::loadModule(SourceLoc importLoc,
if (!file)
return nullptr;

// The MemoryBuffer loader is used by LLDB during debugging. Modules imported
// from .swift_ast sections are never produced from textual interfaces. By
// disabling resilience the debugger can directly access private members.
if (BypassResilience)
M->setBypassResilience();
M->addFile(*file);
Ctx.addLoadedModule(M);
return M;
Expand Down