mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Disable resilience for modules imported by the MemoryBuffer loader.
The MemoryBuffer loader is used by LLDB during debugging to import binary Swift modules from .swift_ast sections. Modules imported from .swift_ast sections are never produced from textual interfaces. By disabling resilience the expression evaluator in the debugger can directly access private members. rdar://79462915
This commit is contained in:
@@ -257,6 +257,9 @@ private:
|
|||||||
|
|
||||||
AccessNotesFile accessNotes;
|
AccessNotesFile accessNotes;
|
||||||
|
|
||||||
|
/// Used by the debugger to bypass resilient access to fields.
|
||||||
|
bool BypassResilience = false;
|
||||||
|
|
||||||
ModuleDecl(Identifier name, ASTContext &ctx, ImplicitImportInfo importInfo);
|
ModuleDecl(Identifier name, ASTContext &ctx, ImplicitImportInfo importInfo);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@@ -290,6 +293,12 @@ public:
|
|||||||
AccessNotesFile &getAccessNotes() { return accessNotes; }
|
AccessNotesFile &getAccessNotes() { return accessNotes; }
|
||||||
const AccessNotesFile &getAccessNotes() const { 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() {
|
ArrayRef<FileUnit *> getFiles() {
|
||||||
assert(!Files.empty() || failedToLoad());
|
assert(!Files.empty() || failedToLoad());
|
||||||
return Files;
|
return Files;
|
||||||
|
|||||||
@@ -261,9 +261,11 @@ class MemoryBufferSerializedModuleLoader : public SerializedModuleLoaderBase {
|
|||||||
MemoryBufferSerializedModuleLoader(ASTContext &ctx,
|
MemoryBufferSerializedModuleLoader(ASTContext &ctx,
|
||||||
DependencyTracker *tracker,
|
DependencyTracker *tracker,
|
||||||
ModuleLoadingMode loadMode,
|
ModuleLoadingMode loadMode,
|
||||||
bool IgnoreSwiftSourceInfo)
|
bool IgnoreSwiftSourceInfo,
|
||||||
|
bool BypassResilience)
|
||||||
: SerializedModuleLoaderBase(ctx, tracker, loadMode,
|
: SerializedModuleLoaderBase(ctx, tracker, loadMode,
|
||||||
IgnoreSwiftSourceInfo) {}
|
IgnoreSwiftSourceInfo),
|
||||||
|
BypassResilience(BypassResilience) {}
|
||||||
|
|
||||||
std::error_code findModuleFilesInDirectory(
|
std::error_code findModuleFilesInDirectory(
|
||||||
ImportPath::Element ModuleID,
|
ImportPath::Element ModuleID,
|
||||||
@@ -279,6 +281,7 @@ class MemoryBufferSerializedModuleLoader : public SerializedModuleLoaderBase {
|
|||||||
StringRef moduleName,
|
StringRef moduleName,
|
||||||
const SerializedModuleBaseName &BaseName) override;
|
const SerializedModuleBaseName &BaseName) override;
|
||||||
|
|
||||||
|
bool BypassResilience;
|
||||||
public:
|
public:
|
||||||
virtual ~MemoryBufferSerializedModuleLoader();
|
virtual ~MemoryBufferSerializedModuleLoader();
|
||||||
|
|
||||||
@@ -308,10 +311,10 @@ public:
|
|||||||
static std::unique_ptr<MemoryBufferSerializedModuleLoader>
|
static std::unique_ptr<MemoryBufferSerializedModuleLoader>
|
||||||
create(ASTContext &ctx, DependencyTracker *tracker = nullptr,
|
create(ASTContext &ctx, DependencyTracker *tracker = nullptr,
|
||||||
ModuleLoadingMode loadMode = ModuleLoadingMode::PreferSerialized,
|
ModuleLoadingMode loadMode = ModuleLoadingMode::PreferSerialized,
|
||||||
bool IgnoreSwiftSourceInfo = false) {
|
bool IgnoreSwiftSourceInfo = false, bool BypassResilience = false) {
|
||||||
return std::unique_ptr<MemoryBufferSerializedModuleLoader>{
|
return std::unique_ptr<MemoryBufferSerializedModuleLoader>{
|
||||||
new MemoryBufferSerializedModuleLoader(ctx, tracker, loadMode,
|
new MemoryBufferSerializedModuleLoader(
|
||||||
IgnoreSwiftSourceInfo)};
|
ctx, tracker, loadMode, IgnoreSwiftSourceInfo, BypassResilience)};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1879,7 +1879,7 @@ static bool isDirectToStorageAccess(const DeclContext *UseDC,
|
|||||||
// If the storage is resilient, we cannot access it directly at all.
|
// If the storage is resilient, we cannot access it directly at all.
|
||||||
if (var->isResilient(UseDC->getParentModule(),
|
if (var->isResilient(UseDC->getParentModule(),
|
||||||
UseDC->getResilienceExpansion()))
|
UseDC->getResilienceExpansion()))
|
||||||
return false;
|
return var->getModuleContext()->getBypassResilience();
|
||||||
|
|
||||||
if (isa<ConstructorDecl>(AFD) || isa<DestructorDecl>(AFD)) {
|
if (isa<ConstructorDecl>(AFD) || isa<DestructorDecl>(AFD)) {
|
||||||
// The access must also be a member access on 'self' in all language modes.
|
// The access must also be a member access on 'self' in all language modes.
|
||||||
|
|||||||
@@ -4968,7 +4968,10 @@ llvm::Constant *IRGenModule::getAddrOfGlobalUTF16String(StringRef utf8) {
|
|||||||
/// - For enums, new cases can be added
|
/// - For enums, new cases can be added
|
||||||
/// - For classes, the superclass might change the size or number
|
/// - For classes, the superclass might change the size or number
|
||||||
/// of stored properties
|
/// 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 &&
|
if (expansion == ResilienceExpansion::Maximal &&
|
||||||
Types.getLoweringMode() == TypeConverter::Mode::CompletelyFragile) {
|
Types.getLoweringMode() == TypeConverter::Mode::CompletelyFragile) {
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -104,6 +104,15 @@ static bool isArchetypeValidInFunction(ArchetypeType *A, const SILFunction *F) {
|
|||||||
|
|
||||||
namespace {
|
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.
|
/// Metaprogramming-friendly base class.
|
||||||
template <class Impl>
|
template <class Impl>
|
||||||
class SILVerifierBase : public SILInstructionVisitor<Impl> {
|
class SILVerifierBase : public SILInstructionVisitor<Impl> {
|
||||||
@@ -234,7 +243,7 @@ void verifyKeyPathComponent(SILModule &M,
|
|||||||
"property decl should be a member of the base with the same type "
|
"property decl should be a member of the base with the same type "
|
||||||
"as the component");
|
"as the component");
|
||||||
require(property->hasStorage(), "property must be stored");
|
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");
|
"cannot access storage of resilient property");
|
||||||
auto propertyTy =
|
auto propertyTy =
|
||||||
loweredBaseTy.getFieldType(property, M, typeExpansionContext);
|
loweredBaseTy.getFieldType(property, M, typeExpansionContext);
|
||||||
@@ -1970,7 +1979,7 @@ public:
|
|||||||
void checkAllocGlobalInst(AllocGlobalInst *AGI) {
|
void checkAllocGlobalInst(AllocGlobalInst *AGI) {
|
||||||
SILGlobalVariable *RefG = AGI->getReferencedGlobal();
|
SILGlobalVariable *RefG = AGI->getReferencedGlobal();
|
||||||
if (auto *VD = RefG->getDecl()) {
|
if (auto *VD = RefG->getDecl()) {
|
||||||
require(!VD->isResilient(F.getModule().getSwiftModule(),
|
require(!checkResilience(VD, F.getModule().getSwiftModule(),
|
||||||
F.getResilienceExpansion()),
|
F.getResilienceExpansion()),
|
||||||
"cannot access storage of resilient global");
|
"cannot access storage of resilient global");
|
||||||
}
|
}
|
||||||
@@ -1989,7 +1998,7 @@ public:
|
|||||||
RefG->getLoweredTypeInContext(F.getTypeExpansionContext()),
|
RefG->getLoweredTypeInContext(F.getTypeExpansionContext()),
|
||||||
"global_addr/value must be the type of the variable it references");
|
"global_addr/value must be the type of the variable it references");
|
||||||
if (auto *VD = RefG->getDecl()) {
|
if (auto *VD = RefG->getDecl()) {
|
||||||
require(!VD->isResilient(F.getModule().getSwiftModule(),
|
require(!checkResilience(VD, F.getModule().getSwiftModule(),
|
||||||
F.getResilienceExpansion()),
|
F.getResilienceExpansion()),
|
||||||
"cannot access storage of resilient global");
|
"cannot access storage of resilient global");
|
||||||
}
|
}
|
||||||
@@ -2677,7 +2686,7 @@ public:
|
|||||||
require(!structDecl->hasUnreferenceableStorage(),
|
require(!structDecl->hasUnreferenceableStorage(),
|
||||||
"Cannot build a struct with unreferenceable storage from elements "
|
"Cannot build a struct with unreferenceable storage from elements "
|
||||||
"using StructInst");
|
"using StructInst");
|
||||||
require(!structDecl->isResilient(F.getModule().getSwiftModule(),
|
require(!checkResilience(structDecl, F.getModule().getSwiftModule(),
|
||||||
F.getResilienceExpansion()),
|
F.getResilienceExpansion()),
|
||||||
"cannot access storage of resilient struct");
|
"cannot access storage of resilient struct");
|
||||||
require(SI->getType().isObject(),
|
require(SI->getType().isObject(),
|
||||||
@@ -2879,7 +2888,7 @@ public:
|
|||||||
require(cd, "Operand of dealloc_ref must be of class type");
|
require(cd, "Operand of dealloc_ref must be of class type");
|
||||||
|
|
||||||
if (!DI->canAllocOnStack()) {
|
if (!DI->canAllocOnStack()) {
|
||||||
require(!cd->isResilient(F.getModule().getSwiftModule(),
|
require(!checkResilience(cd, F.getModule().getSwiftModule(),
|
||||||
F.getResilienceExpansion()),
|
F.getResilienceExpansion()),
|
||||||
"cannot directly deallocate resilient class");
|
"cannot directly deallocate resilient class");
|
||||||
}
|
}
|
||||||
@@ -2996,7 +3005,7 @@ public:
|
|||||||
"result of struct_extract cannot be address");
|
"result of struct_extract cannot be address");
|
||||||
StructDecl *sd = operandTy.getStructOrBoundGenericStruct();
|
StructDecl *sd = operandTy.getStructOrBoundGenericStruct();
|
||||||
require(sd, "must struct_extract from struct");
|
require(sd, "must struct_extract from struct");
|
||||||
require(!sd->isResilient(F.getModule().getSwiftModule(),
|
require(!checkResilience(sd, F.getModule().getSwiftModule(),
|
||||||
F.getResilienceExpansion()),
|
F.getResilienceExpansion()),
|
||||||
"cannot access storage of resilient struct");
|
"cannot access storage of resilient struct");
|
||||||
require(!EI->getField()->isStatic(),
|
require(!EI->getField()->isStatic(),
|
||||||
@@ -3045,7 +3054,7 @@ public:
|
|||||||
"must derive struct_element_addr from address");
|
"must derive struct_element_addr from address");
|
||||||
StructDecl *sd = operandTy.getStructOrBoundGenericStruct();
|
StructDecl *sd = operandTy.getStructOrBoundGenericStruct();
|
||||||
require(sd, "struct_element_addr operand must be struct address");
|
require(sd, "struct_element_addr operand must be struct address");
|
||||||
require(!sd->isResilient(F.getModule().getSwiftModule(),
|
require(!checkResilience(sd, F.getModule().getSwiftModule(),
|
||||||
F.getResilienceExpansion()),
|
F.getResilienceExpansion()),
|
||||||
"cannot access storage of resilient struct");
|
"cannot access storage of resilient struct");
|
||||||
require(EI->getType().isAddress(),
|
require(EI->getType().isAddress(),
|
||||||
@@ -3078,7 +3087,7 @@ public:
|
|||||||
SILType operandTy = EI->getOperand()->getType();
|
SILType operandTy = EI->getOperand()->getType();
|
||||||
ClassDecl *cd = operandTy.getClassOrBoundGenericClass();
|
ClassDecl *cd = operandTy.getClassOrBoundGenericClass();
|
||||||
require(cd, "ref_element_addr operand must be a class instance");
|
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()),
|
F.getResilienceExpansion()),
|
||||||
"cannot access storage of resilient class");
|
"cannot access storage of resilient class");
|
||||||
|
|
||||||
@@ -3102,7 +3111,7 @@ public:
|
|||||||
SILType operandTy = RTAI->getOperand()->getType();
|
SILType operandTy = RTAI->getOperand()->getType();
|
||||||
ClassDecl *cd = operandTy.getClassOrBoundGenericClass();
|
ClassDecl *cd = operandTy.getClassOrBoundGenericClass();
|
||||||
require(cd, "ref_tail_addr operand must be a class instance");
|
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()),
|
F.getResilienceExpansion()),
|
||||||
"cannot access storage of resilient class");
|
"cannot access storage of resilient class");
|
||||||
require(cd, "ref_tail_addr operand must be a class instance");
|
require(cd, "ref_tail_addr operand must be a class instance");
|
||||||
@@ -3112,7 +3121,7 @@ public:
|
|||||||
SILType operandTy = DSI->getOperand()->getType();
|
SILType operandTy = DSI->getOperand()->getType();
|
||||||
StructDecl *sd = operandTy.getStructOrBoundGenericStruct();
|
StructDecl *sd = operandTy.getStructOrBoundGenericStruct();
|
||||||
require(sd, "must struct_extract from struct");
|
require(sd, "must struct_extract from struct");
|
||||||
require(!sd->isResilient(F.getModule().getSwiftModule(),
|
require(!checkResilience(sd, F.getModule().getSwiftModule(),
|
||||||
F.getResilienceExpansion()),
|
F.getResilienceExpansion()),
|
||||||
"cannot access storage of resilient struct");
|
"cannot access storage of resilient struct");
|
||||||
if (F.hasOwnership()) {
|
if (F.hasOwnership()) {
|
||||||
|
|||||||
@@ -1205,6 +1205,11 @@ MemoryBufferSerializedModuleLoader::loadModule(SourceLoc importLoc,
|
|||||||
if (!file)
|
if (!file)
|
||||||
return nullptr;
|
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);
|
M->addFile(*file);
|
||||||
Ctx.addLoadedModule(M);
|
Ctx.addLoadedModule(M);
|
||||||
return M;
|
return M;
|
||||||
|
|||||||
Reference in New Issue
Block a user