Skip to content

Commit e754f5a

Browse files
committed
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
1 parent 86a715d commit e754f5a

File tree

6 files changed

+48
-19
lines changed

6 files changed

+48
-19
lines changed

include/swift/AST/Module.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,9 @@ class ModuleDecl
257257

258258
AccessNotesFile accessNotes;
259259

260+
/// Used by the debugger to bypass resilient access to fields.
261+
bool BypassResilience = false;
262+
260263
ModuleDecl(Identifier name, ASTContext &ctx, ImplicitImportInfo importInfo);
261264

262265
public:
@@ -290,6 +293,12 @@ class ModuleDecl
290293
AccessNotesFile &getAccessNotes() { return accessNotes; }
291294
const AccessNotesFile &getAccessNotes() const { return accessNotes; }
292295

296+
/// Return whether the module was imported with resilience disabled. The
297+
/// debugger does this to access private fields.
298+
bool getBypassResilience() const { return BypassResilience; }
299+
/// Only to be called by MemoryBufferSerializedModuleLoader.
300+
void setBypassResilience() { BypassResilience = true; }
301+
293302
ArrayRef<FileUnit *> getFiles() {
294303
assert(!Files.empty() || failedToLoad());
295304
return Files;

include/swift/Serialization/SerializedModuleLoader.h

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -261,9 +261,11 @@ class MemoryBufferSerializedModuleLoader : public SerializedModuleLoaderBase {
261261
MemoryBufferSerializedModuleLoader(ASTContext &ctx,
262262
DependencyTracker *tracker,
263263
ModuleLoadingMode loadMode,
264-
bool IgnoreSwiftSourceInfo)
264+
bool IgnoreSwiftSourceInfo,
265+
bool BypassResilience)
265266
: SerializedModuleLoaderBase(ctx, tracker, loadMode,
266-
IgnoreSwiftSourceInfo) {}
267+
IgnoreSwiftSourceInfo),
268+
BypassResilience(BypassResilience) {}
267269

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

284+
bool BypassResilience;
282285
public:
283286
virtual ~MemoryBufferSerializedModuleLoader();
284287

@@ -308,10 +311,10 @@ class MemoryBufferSerializedModuleLoader : public SerializedModuleLoaderBase {
308311
static std::unique_ptr<MemoryBufferSerializedModuleLoader>
309312
create(ASTContext &ctx, DependencyTracker *tracker = nullptr,
310313
ModuleLoadingMode loadMode = ModuleLoadingMode::PreferSerialized,
311-
bool IgnoreSwiftSourceInfo = false) {
314+
bool IgnoreSwiftSourceInfo = false, bool BypassResilience = false) {
312315
return std::unique_ptr<MemoryBufferSerializedModuleLoader>{
313-
new MemoryBufferSerializedModuleLoader(ctx, tracker, loadMode,
314-
IgnoreSwiftSourceInfo)};
316+
new MemoryBufferSerializedModuleLoader(
317+
ctx, tracker, loadMode, IgnoreSwiftSourceInfo, BypassResilience)};
315318
}
316319
};
317320

lib/AST/Decl.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1879,7 +1879,7 @@ static bool isDirectToStorageAccess(const DeclContext *UseDC,
18791879
// If the storage is resilient, we cannot access it directly at all.
18801880
if (var->isResilient(UseDC->getParentModule(),
18811881
UseDC->getResilienceExpansion()))
1882-
return false;
1882+
return var->getModuleContext()->getBypassResilience();
18831883

18841884
if (isa<ConstructorDecl>(AFD) || isa<DestructorDecl>(AFD)) {
18851885
// The access must also be a member access on 'self' in all language modes.

lib/IRGen/GenDecl.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4968,7 +4968,10 @@ llvm::Constant *IRGenModule::getAddrOfGlobalUTF16String(StringRef utf8) {
49684968
/// - For enums, new cases can be added
49694969
/// - For classes, the superclass might change the size or number
49704970
/// of stored properties
4971-
bool IRGenModule::isResilient(NominalTypeDecl *D, ResilienceExpansion expansion) {
4971+
bool IRGenModule::isResilient(NominalTypeDecl *D,
4972+
ResilienceExpansion expansion) {
4973+
if (D->getModuleContext()->getBypassResilience())
4974+
return false;
49724975
if (expansion == ResilienceExpansion::Maximal &&
49734976
Types.getLoweringMode() == TypeConverter::Mode::CompletelyFragile) {
49744977
return false;

lib/SIL/Verifier/SILVerifier.cpp

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,15 @@ static bool isArchetypeValidInFunction(ArchetypeType *A, const SILFunction *F) {
104104

105105
namespace {
106106

107+
/// When resilience is bypassed, direct access is legal, but the decls are still
108+
/// resilient.
109+
template <typename DeclType>
110+
bool checkResilience(DeclType *D, ModuleDecl *M,
111+
ResilienceExpansion expansion) {
112+
return !D->getModuleContext()->getBypassResilience() &&
113+
D->isResilient(M, expansion);
114+
}
115+
107116
/// Metaprogramming-friendly base class.
108117
template <class Impl>
109118
class SILVerifierBase : public SILInstructionVisitor<Impl> {
@@ -234,7 +243,7 @@ void verifyKeyPathComponent(SILModule &M,
234243
"property decl should be a member of the base with the same type "
235244
"as the component");
236245
require(property->hasStorage(), "property must be stored");
237-
require(!property->isResilient(M.getSwiftModule(), expansion),
246+
require(!checkResilience(property, M.getSwiftModule(), expansion),
238247
"cannot access storage of resilient property");
239248
auto propertyTy =
240249
loweredBaseTy.getFieldType(property, M, typeExpansionContext);
@@ -1970,7 +1979,7 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
19701979
void checkAllocGlobalInst(AllocGlobalInst *AGI) {
19711980
SILGlobalVariable *RefG = AGI->getReferencedGlobal();
19721981
if (auto *VD = RefG->getDecl()) {
1973-
require(!VD->isResilient(F.getModule().getSwiftModule(),
1982+
require(!checkResilience(VD, F.getModule().getSwiftModule(),
19741983
F.getResilienceExpansion()),
19751984
"cannot access storage of resilient global");
19761985
}
@@ -1989,7 +1998,7 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
19891998
RefG->getLoweredTypeInContext(F.getTypeExpansionContext()),
19901999
"global_addr/value must be the type of the variable it references");
19912000
if (auto *VD = RefG->getDecl()) {
1992-
require(!VD->isResilient(F.getModule().getSwiftModule(),
2001+
require(!checkResilience(VD, F.getModule().getSwiftModule(),
19932002
F.getResilienceExpansion()),
19942003
"cannot access storage of resilient global");
19952004
}
@@ -2677,8 +2686,8 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
26772686
require(!structDecl->hasUnreferenceableStorage(),
26782687
"Cannot build a struct with unreferenceable storage from elements "
26792688
"using StructInst");
2680-
require(!structDecl->isResilient(F.getModule().getSwiftModule(),
2681-
F.getResilienceExpansion()),
2689+
require(!checkResilience(structDecl, F.getModule().getSwiftModule(),
2690+
F.getResilienceExpansion()),
26822691
"cannot access storage of resilient struct");
26832692
require(SI->getType().isObject(),
26842693
"StructInst must produce an object");
@@ -2879,8 +2888,8 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
28792888
require(cd, "Operand of dealloc_ref must be of class type");
28802889

28812890
if (!DI->canAllocOnStack()) {
2882-
require(!cd->isResilient(F.getModule().getSwiftModule(),
2883-
F.getResilienceExpansion()),
2891+
require(!checkResilience(cd, F.getModule().getSwiftModule(),
2892+
F.getResilienceExpansion()),
28842893
"cannot directly deallocate resilient class");
28852894
}
28862895
}
@@ -2996,7 +3005,7 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
29963005
"result of struct_extract cannot be address");
29973006
StructDecl *sd = operandTy.getStructOrBoundGenericStruct();
29983007
require(sd, "must struct_extract from struct");
2999-
require(!sd->isResilient(F.getModule().getSwiftModule(),
3008+
require(!checkResilience(sd, F.getModule().getSwiftModule(),
30003009
F.getResilienceExpansion()),
30013010
"cannot access storage of resilient struct");
30023011
require(!EI->getField()->isStatic(),
@@ -3045,7 +3054,7 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
30453054
"must derive struct_element_addr from address");
30463055
StructDecl *sd = operandTy.getStructOrBoundGenericStruct();
30473056
require(sd, "struct_element_addr operand must be struct address");
3048-
require(!sd->isResilient(F.getModule().getSwiftModule(),
3057+
require(!checkResilience(sd, F.getModule().getSwiftModule(),
30493058
F.getResilienceExpansion()),
30503059
"cannot access storage of resilient struct");
30513060
require(EI->getType().isAddress(),
@@ -3078,7 +3087,7 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
30783087
SILType operandTy = EI->getOperand()->getType();
30793088
ClassDecl *cd = operandTy.getClassOrBoundGenericClass();
30803089
require(cd, "ref_element_addr operand must be a class instance");
3081-
require(!cd->isResilient(F.getModule().getSwiftModule(),
3090+
require(!checkResilience(cd, F.getModule().getSwiftModule(),
30823091
F.getResilienceExpansion()),
30833092
"cannot access storage of resilient class");
30843093

@@ -3102,7 +3111,7 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
31023111
SILType operandTy = RTAI->getOperand()->getType();
31033112
ClassDecl *cd = operandTy.getClassOrBoundGenericClass();
31043113
require(cd, "ref_tail_addr operand must be a class instance");
3105-
require(!cd->isResilient(F.getModule().getSwiftModule(),
3114+
require(!checkResilience(cd, F.getModule().getSwiftModule(),
31063115
F.getResilienceExpansion()),
31073116
"cannot access storage of resilient class");
31083117
require(cd, "ref_tail_addr operand must be a class instance");
@@ -3112,7 +3121,7 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
31123121
SILType operandTy = DSI->getOperand()->getType();
31133122
StructDecl *sd = operandTy.getStructOrBoundGenericStruct();
31143123
require(sd, "must struct_extract from struct");
3115-
require(!sd->isResilient(F.getModule().getSwiftModule(),
3124+
require(!checkResilience(sd, F.getModule().getSwiftModule(),
31163125
F.getResilienceExpansion()),
31173126
"cannot access storage of resilient struct");
31183127
if (F.hasOwnership()) {

lib/Serialization/SerializedModuleLoader.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1205,6 +1205,11 @@ MemoryBufferSerializedModuleLoader::loadModule(SourceLoc importLoc,
12051205
if (!file)
12061206
return nullptr;
12071207

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

0 commit comments

Comments
 (0)