Skip to content

Commit 2576d7d

Browse files
committed
LoadableByAddress: convert types of functions which are contained in structs inside global static initializers
We missed converting such types inside static initializers of global variables. This results in ptrauth crashes when ptrauth is enabled. rdar://108165425
1 parent 893d94d commit 2576d7d

File tree

2 files changed

+75
-57
lines changed

2 files changed

+75
-57
lines changed

lib/IRGen/LoadableByAddress.cpp

Lines changed: 59 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include "swift/SIL/DebugUtils.h"
2727
#include "swift/SIL/SILArgument.h"
2828
#include "swift/SIL/SILBuilder.h"
29+
#include "swift/SIL/SILCloner.h"
2930
#include "swift/SIL/SILUndef.h"
3031
#include "swift/SILOptimizer/PassManager/Transforms.h"
3132
#include "swift/SILOptimizer/Utils/InstOptUtils.h"
@@ -1713,6 +1714,8 @@ class LoadableByAddress : public SILModuleTransform {
17131714

17141715
bool shouldTransformGlobal(SILGlobalVariable *global);
17151716

1717+
bool shouldTransformInitExprOfGlobal(SILGlobalVariable *global);
1718+
17161719
private:
17171720
llvm::SetVector<SILFunction *> modFuncs;
17181721
llvm::SetVector<SingleValueInstruction *> conversionInstrs;
@@ -1724,6 +1727,8 @@ class LoadableByAddress : public SILModuleTransform {
17241727
llvm::SetVector<StoreInst *> storeToBlockStorageInstrs;
17251728
llvm::SetVector<SILInstruction *> modApplies;
17261729
llvm::MapVector<SILInstruction *, SILValue> allApplyRetToAllocMap;
1730+
1731+
public:
17271732
LargeSILTypeMapper MapperCache;
17281733
};
17291734
} // end anonymous namespace
@@ -2940,6 +2945,42 @@ bool LoadableByAddress::shouldTransformGlobal(SILGlobalVariable *global) {
29402945
return false;
29412946
}
29422947

2948+
bool LoadableByAddress::shouldTransformInitExprOfGlobal(SILGlobalVariable *global) {
2949+
for (const SILInstruction &initInst : *global) {
2950+
if (auto *fri = dyn_cast<FunctionRefBaseInst>(&initInst)) {
2951+
SILFunction *refF = fri->getInitiallyReferencedFunction();
2952+
if (modFuncs.count(refF) != 0)
2953+
return true;
2954+
}
2955+
}
2956+
return false;
2957+
}
2958+
2959+
namespace {
2960+
class GlobalInitCloner : public SILCloner<GlobalInitCloner> {
2961+
LoadableByAddress *pass;
2962+
IRGenModule *irgenModule;
2963+
public:
2964+
GlobalInitCloner(SILGlobalVariable *global, LoadableByAddress *pass,
2965+
IRGenModule *irgenModule)
2966+
: SILCloner<GlobalInitCloner>(global), pass(pass), irgenModule(irgenModule) {
2967+
}
2968+
2969+
SILType remapType(SILType ty) {
2970+
if (auto fnType = ty.getAs<SILFunctionType>()) {
2971+
GenericEnvironment *genEnv = getSubstGenericEnvironment(fnType);
2972+
return SILType::getPrimitiveObjectType(
2973+
pass->MapperCache.getNewSILFunctionType(genEnv, fnType, *irgenModule));
2974+
}
2975+
return ty;
2976+
}
2977+
2978+
void clone(SILInstruction *inst) {
2979+
visit(inst);
2980+
}
2981+
};
2982+
}
2983+
29432984
/// The entry point to this function transformation.
29442985
void LoadableByAddress::run() {
29452986
// Set the SIL state before the PassManager has a chance to run
@@ -3078,72 +3119,34 @@ void LoadableByAddress::run() {
30783119
updateLoweredTypes(F);
30793120
}
30803121

3081-
auto computeNewResultType = [&](SILType ty, IRGenModule *mod) -> SILType {
3082-
auto currSILFunctionType = ty.castTo<SILFunctionType>();
3083-
GenericEnvironment *genEnv =
3084-
getSubstGenericEnvironment(currSILFunctionType);
3085-
return SILType::getPrimitiveObjectType(
3086-
MapperCache.getNewSILFunctionType(genEnv, currSILFunctionType, *mod));
3087-
};
3088-
30893122
// Update globals' initializer.
30903123
SmallVector<SILGlobalVariable *, 16> deadGlobals;
30913124
for (SILGlobalVariable &global : getModule()->getSILGlobals()) {
3092-
SILInstruction *init = global.getStaticInitializerValue();
3093-
if (!init)
3094-
continue;
3095-
auto silTy = global.getLoweredType();
3096-
if (!isa<SILFunctionType>(silTy.getASTType()))
3097-
continue;
3098-
auto *decl = global.getDecl();
3099-
IRGenModule *currIRMod = getIRGenModule()->IRGen.getGenModule(
3100-
decl ? decl->getDeclContext() : nullptr);
3101-
auto silFnTy = global.getLoweredFunctionType();
3102-
GenericEnvironment *genEnv = getSubstGenericEnvironment(silFnTy);
3103-
3104-
// Update the global's type.
3105-
if (MapperCache.shouldTransformFunctionType(genEnv, silFnTy, *currIRMod)) {
3106-
auto newSILFnType =
3107-
MapperCache.getNewSILFunctionType(genEnv, silFnTy, *currIRMod);
3108-
global.unsafeSetLoweredType(
3109-
SILType::getPrimitiveObjectType(newSILFnType));
3125+
if (shouldTransformInitExprOfGlobal(&global)) {
3126+
auto *decl = global.getDecl();
3127+
IRGenModule *currIRMod = getIRGenModule()->IRGen.getGenModule(
3128+
decl ? decl->getDeclContext() : nullptr);
3129+
3130+
auto silTy = global.getLoweredType();
3131+
if (isa<SILFunctionType>(silTy.getASTType())) {
3132+
auto silFnTy = global.getLoweredFunctionType();
3133+
GenericEnvironment *genEnv = getSubstGenericEnvironment(silFnTy);
3134+
if (MapperCache.shouldTransformFunctionType(genEnv, silFnTy, *currIRMod)) {
3135+
auto newSILFnType =
3136+
MapperCache.getNewSILFunctionType(genEnv, silFnTy, *currIRMod);
3137+
global.unsafeSetLoweredType(SILType::getPrimitiveObjectType(newSILFnType));
3138+
}
3139+
}
31103140

31113141
// Rewrite the init basic block...
31123142
SmallVector<SILInstruction *, 8> initBlockInsts;
31133143
for (auto it = global.begin(), end = global.end(); it != end; ++it) {
31143144
initBlockInsts.push_back(const_cast<SILInstruction *>(&*it));
31153145
}
3146+
GlobalInitCloner cloner(&global, this, currIRMod);
31163147
for (auto *oldInst : initBlockInsts) {
3117-
if (auto *f = dyn_cast<FunctionRefInst>(oldInst)) {
3118-
SILBuilder builder(&global);
3119-
auto *newInst = builder.createFunctionRef(
3120-
f->getLoc(), f->getInitiallyReferencedFunction(), f->getKind());
3121-
f->replaceAllUsesWith(newInst);
3122-
global.unsafeRemove(f, *getModule());
3123-
} else if (auto *cvt = dyn_cast<ConvertFunctionInst>(oldInst)) {
3124-
auto newType = computeNewResultType(cvt->getType(), currIRMod);
3125-
SILBuilder builder(&global);
3126-
auto *newInst = builder.createConvertFunction(
3127-
cvt->getLoc(), cvt->getOperand(), newType,
3128-
cvt->withoutActuallyEscaping());
3129-
cvt->replaceAllUsesWith(newInst);
3130-
global.unsafeRemove(cvt, *getModule());
3131-
} else if (auto *thinToThick =
3132-
dyn_cast<ThinToThickFunctionInst>(oldInst)) {
3133-
auto newType =
3134-
computeNewResultType(thinToThick->getType(), currIRMod);
3135-
SILBuilder builder(&global);
3136-
auto *newInstr = builder.createThinToThickFunction(
3137-
thinToThick->getLoc(), thinToThick->getOperand(), newType);
3138-
thinToThick->replaceAllUsesWith(newInstr);
3139-
global.unsafeRemove(thinToThick, *getModule());
3140-
} else {
3141-
auto *sv = cast<SingleValueInstruction>(oldInst);
3142-
auto *newInst = cast<SingleValueInstruction>(oldInst->clone());
3143-
global.unsafeAppend(newInst);
3144-
sv->replaceAllUsesWith(newInst);
3145-
global.unsafeRemove(oldInst, *getModule());
3146-
}
3148+
cloner.clone(oldInst);
3149+
global.unsafeRemove(oldInst, *getModule());
31473150
}
31483151
}
31493152
}

test/IRGen/big_types_coroutine.sil renamed to test/IRGen/big_types.sil

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// RUN: %target-sil-opt -loadable-address -enable-sil-verify-all %s | %FileCheck %s
22

3-
// REQUIRES: CPU=x86_64
3+
// REQUIRES: PTRSIZE=64
44
// REQUIRES: OS=macosx
55

66
sil_stage canonical
@@ -19,9 +19,24 @@ public struct BigStruct {
1919
var i8 : Int32 = 8
2020
}
2121

22+
public struct ContainsClosure {
23+
let c: () -> BigStruct
24+
}
25+
2226
sil @make_big_struct : $@convention(thin) () -> BigStruct
2327
sil @use_big_struct : $@convention(thin) (BigStruct) -> ()
2428

29+
// CHECK-LABEL: sil_global @globalWithClosureInStruct : $ContainsClosure = {
30+
// CHECK: %0 = function_ref @make_big_struct : $@convention(thin) () -> @out BigStruct
31+
// CHECK-NEXT: %1 = thin_to_thick_function %0 : $@convention(thin) () -> @out BigStruct to $@callee_guaranteed () -> @out BigStruct
32+
// CHECK-NEXT: %initval = struct $ContainsClosure (%1 : $@callee_guaranteed () -> @out BigStruct)
33+
// CHECK-NEXT: }
34+
sil_global @globalWithClosureInStruct : $ContainsClosure = {
35+
%0 = function_ref @make_big_struct : $@convention(thin) () -> BigStruct
36+
%1 = thin_to_thick_function %0 : $@convention(thin) () -> BigStruct to $@callee_guaranteed () -> BigStruct
37+
%initval = struct $ContainsClosure (%1 : $@callee_guaranteed () -> BigStruct)
38+
}
39+
2540
// CHECK-LABEL: sil @test_yield_big : $@yield_once @convention(thin) () -> @yields @in BigStruct {
2641
// CHECK: bb0:
2742
// CHECK-NEXT: [[TEMP:%.*]] = alloc_stack $BigStruct

0 commit comments

Comments
 (0)