Author: Qinkun Bao Date: 2025-06-24T13:11:52-04:00 New Revision: 4b4782bc868bcca7a92f1253529f148eb61cb628
URL: https://github.com/llvm/llvm-project/commit/4b4782bc868bcca7a92f1253529f148eb61cb628 DIFF: https://github.com/llvm/llvm-project/commit/4b4782bc868bcca7a92f1253529f148eb61cb628.diff LOG: Revert "Add support for Windows Secure Hot-Patching" (#145553) Reverts llvm/llvm-project#138972 Added: Modified: clang/include/clang/Basic/CodeGenOptions.h clang/include/clang/Driver/Options.td clang/lib/CodeGen/CGCall.cpp clang/lib/CodeGen/CodeGenModule.cpp clang/lib/CodeGen/CodeGenModule.h clang/lib/Driver/ToolChains/Clang.cpp llvm/include/llvm/CodeGen/Passes.h llvm/include/llvm/DebugInfo/CodeView/CodeViewSymbols.def llvm/include/llvm/DebugInfo/CodeView/SymbolRecord.h llvm/include/llvm/IR/Attributes.td llvm/include/llvm/InitializePasses.h llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h llvm/lib/CodeGen/CMakeLists.txt llvm/lib/CodeGen/TargetPassConfig.cpp llvm/lib/DebugInfo/CodeView/SymbolDumper.cpp llvm/lib/DebugInfo/CodeView/SymbolRecordMapping.cpp llvm/lib/ObjectYAML/CodeViewYAMLSymbols.cpp llvm/tools/llvm-pdbutil/MinimalSymbolDumper.cpp Removed: clang/test/CodeGen/X86/ms-secure-hotpatch-bad-file.c clang/test/CodeGen/X86/ms-secure-hotpatch-cpp.cpp clang/test/CodeGen/X86/ms-secure-hotpatch-eh.cpp clang/test/CodeGen/X86/ms-secure-hotpatch-globals.c clang/test/CodeGen/X86/ms-secure-hotpatch-lto.c clang/test/CodeGen/X86/ms-secure-hotpatch.c llvm/lib/CodeGen/WindowsSecureHotPatching.cpp llvm/test/CodeGen/X86/ms-secure-hotpatch-attr.ll llvm/test/CodeGen/X86/ms-secure-hotpatch-bad-file.ll llvm/test/CodeGen/X86/ms-secure-hotpatch-direct-global-access.ll llvm/test/CodeGen/X86/ms-secure-hotpatch-functions-file.ll llvm/test/CodeGen/X86/ms-secure-hotpatch-functions-list.ll ################################################################################ diff --git a/clang/include/clang/Basic/CodeGenOptions.h b/clang/include/clang/Basic/CodeGenOptions.h index 77a0c559f7689..7ba21fca6dd6b 100644 --- a/clang/include/clang/Basic/CodeGenOptions.h +++ b/clang/include/clang/Basic/CodeGenOptions.h @@ -495,13 +495,6 @@ class CodeGenOptions : public CodeGenOptionsBase { /// A list of functions that are replacable by the loader. std::vector<std::string> LoaderReplaceableFunctionNames; - /// The name of a file that contains functions which will be compiled for - /// hotpatching. See -fms-secure-hotpatch-functions-file. - std::string MSSecureHotPatchFunctionsFile; - - /// A list of functions which will be compiled for hotpatching. - /// See -fms-secure-hotpatch-functions-list. - std::vector<std::string> MSSecureHotPatchFunctionsList; public: // Define accessors/mutators for code generation options of enumeration type. diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 26e953f7ac613..4f91b82a3bfa6 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -3838,24 +3838,6 @@ def fms_hotpatch : Flag<["-"], "fms-hotpatch">, Group<f_Group>, Visibility<[ClangOption, CC1Option, CLOption]>, HelpText<"Ensure that all functions can be hotpatched at runtime">, MarshallingInfoFlag<CodeGenOpts<"HotPatch">>; - -// See llvm/lib/CodeGen/WindowsSecureHotPatching.cpp -def fms_secure_hotpatch_functions_file - : Joined<["-"], "fms-secure-hotpatch-functions-file=">, - Group<f_Group>, - Visibility<[ClangOption, CC1Option, CLOption]>, - MarshallingInfoString<CodeGenOpts<"MSSecureHotPatchFunctionsFile">>, - HelpText<"Path to a file that contains a list of mangled names of " - "functions that should be hot-patched for Windows Secure " - "Hot-Patching">; -def fms_secure_hotpatch_functions_list - : CommaJoined<["-"], "fms-secure-hotpatch-functions-list=">, - Group<f_Group>, - Visibility<[ClangOption, CC1Option, CLOption]>, - MarshallingInfoStringVector<CodeGenOpts<"MSSecureHotPatchFunctionsList">>, - HelpText<"List of mangled symbol names of functions that should be " - "hot-patched for Windows Secure Hot-Patching">; - def fpcc_struct_return : Flag<["-"], "fpcc-struct-return">, Group<f_Group>, Visibility<[ClangOption, CC1Option]>, HelpText<"Override the default ABI to return all structs on the stack">; diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index c8c3d6b20c496..fd75de42515da 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -2660,13 +2660,6 @@ void CodeGenModule::ConstructAttributeList(StringRef Name, // CPU/feature overrides. addDefaultFunctionDefinitionAttributes // handles these separately to set them based on the global defaults. GetCPUAndFeaturesAttributes(CalleeInfo.getCalleeDecl(), FuncAttrs); - - // Windows hotpatching support - if (!MSHotPatchFunctions.empty()) { - bool IsHotPatched = llvm::binary_search(MSHotPatchFunctions, Name); - if (IsHotPatched) - FuncAttrs.addAttribute("marked_for_windows_hot_patching"); - } } // Mark functions that are replaceable by the loader. diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 96fdab212beb1..16688810d0685 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -458,35 +458,6 @@ CodeGenModule::CodeGenModule(ASTContext &C, if (Context.getTargetInfo().getTriple().getArch() == llvm::Triple::x86) getModule().addModuleFlag(llvm::Module::Error, "NumRegisterParameters", CodeGenOpts.NumRegisterParameters); - - // If there are any functions that are marked for Windows secure hot-patching, - // then build the list of functions now. - if (!CGO.MSSecureHotPatchFunctionsFile.empty() || - !CGO.MSSecureHotPatchFunctionsList.empty()) { - if (!CGO.MSSecureHotPatchFunctionsFile.empty()) { - auto BufOrErr = - llvm::MemoryBuffer::getFile(CGO.MSSecureHotPatchFunctionsFile); - if (BufOrErr) { - const llvm::MemoryBuffer &FileBuffer = **BufOrErr; - for (llvm::line_iterator I(FileBuffer.getMemBufferRef(), true), E; - I != E; ++I) - this->MSHotPatchFunctions.push_back(std::string{*I}); - } else { - auto &DE = Context.getDiagnostics(); - unsigned DiagID = - DE.getCustomDiagID(DiagnosticsEngine::Error, - "failed to open hotpatch functions file " - "(-fms-hotpatch-functions-file): %0 : %1"); - DE.Report(DiagID) << CGO.MSSecureHotPatchFunctionsFile - << BufOrErr.getError().message(); - } - } - - for (const auto &FuncName : CGO.MSSecureHotPatchFunctionsList) - this->MSHotPatchFunctions.push_back(FuncName); - - llvm::sort(this->MSHotPatchFunctions); - } } CodeGenModule::~CodeGenModule() {} diff --git a/clang/lib/CodeGen/CodeGenModule.h b/clang/lib/CodeGen/CodeGenModule.h index cb013feb769fc..1b67d4354efc0 100644 --- a/clang/lib/CodeGen/CodeGenModule.h +++ b/clang/lib/CodeGen/CodeGenModule.h @@ -678,11 +678,6 @@ class CodeGenModule : public CodeGenTypeCache { AtomicOptions AtomicOpts; - // A set of functions which should be hot-patched; see - // -fms-hotpatch-functions-file (and -list). This will nearly always be empty. - // The list is sorted for binary-searching. - std::vector<std::string> MSHotPatchFunctions; - public: CodeGenModule(ASTContext &C, IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS, const HeaderSearchOptions &headersearchopts, diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index be9c1c466fbfb..87d04a42fcd70 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -6803,14 +6803,6 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, Args.AddLastArg(CmdArgs, options::OPT_fms_hotpatch); - if (Arg *A = Args.getLastArg(options::OPT_fms_secure_hotpatch_functions_file)) - Args.AddLastArg(CmdArgs, options::OPT_fms_secure_hotpatch_functions_file); - - for (const auto &A : - Args.getAllArgValues(options::OPT_fms_secure_hotpatch_functions_list)) - CmdArgs.push_back( - Args.MakeArgString("-fms-secure-hotpatch-functions-list=" + Twine(A))); - if (TC.SupportsProfiling()) { Args.AddLastArg(CmdArgs, options::OPT_pg); diff --git a/clang/test/CodeGen/X86/ms-secure-hotpatch-bad-file.c b/clang/test/CodeGen/X86/ms-secure-hotpatch-bad-file.c deleted file mode 100644 index 839dd44f7ff61..0000000000000 --- a/clang/test/CodeGen/X86/ms-secure-hotpatch-bad-file.c +++ /dev/null @@ -1,18 +0,0 @@ -// REQUIRES: x86-registered-target - -// This verifies that we correctly handle a -fms-secure-hotpatch-functions-file argument that points -// to a missing file. -// -// RUN: not %clang_cl -c --target=x86_64-windows-msvc -O2 /Z7 -fms-secure-hotpatch-functions-file=%S/this-file-is-intentionally-missing-do-not-create-it.txt /Fo%t.obj %s 2>&1 | FileCheck %s -// CHECK: failed to open hotpatch functions file - -void this_might_have_side_effects(); - -int __declspec(noinline) this_gets_hotpatched() { - this_might_have_side_effects(); - return 42; -} - -int __declspec(noinline) this_does_not_get_hotpatched() { - return this_gets_hotpatched() + 100; -} diff --git a/clang/test/CodeGen/X86/ms-secure-hotpatch-cpp.cpp b/clang/test/CodeGen/X86/ms-secure-hotpatch-cpp.cpp deleted file mode 100644 index 3dc75c95d76f7..0000000000000 --- a/clang/test/CodeGen/X86/ms-secure-hotpatch-cpp.cpp +++ /dev/null @@ -1,24 +0,0 @@ -// REQUIRES: x86-registered-target - -// This verifies that hotpatch function attributes are correctly propagated when compiling directly to OBJ, -// and that name mangling works as expected. -// -// RUN: %clang_cl -c --target=x86_64-windows-msvc -O2 /Z7 -fms-secure-hotpatch-functions-list=?this_gets_hotpatched@@YAHXZ /Fo%t.obj %s -// RUN: llvm-readobj --codeview %t.obj | FileCheck %s - -void this_might_have_side_effects(); - -int __declspec(noinline) this_gets_hotpatched() { - this_might_have_side_effects(); - return 42; -} - -// CHECK: Kind: S_HOTPATCHFUNC (0x1169) -// CHECK-NEXT: Function: this_gets_hotpatched -// CHECK-NEXT: Name: ?this_gets_hotpatched@@YAHXZ - -extern "C" int __declspec(noinline) this_does_not_get_hotpatched() { - return this_gets_hotpatched() + 100; -} - -// CHECK-NOT: S_HOTPATCHFUNC diff --git a/clang/test/CodeGen/X86/ms-secure-hotpatch-eh.cpp b/clang/test/CodeGen/X86/ms-secure-hotpatch-eh.cpp deleted file mode 100644 index 69704626c8cb6..0000000000000 --- a/clang/test/CodeGen/X86/ms-secure-hotpatch-eh.cpp +++ /dev/null @@ -1,26 +0,0 @@ -// REQUIRES: x86-registered-target - -// Global constant data such as exception handler tables should not be redirected by Windows Secure Hot-Patching -// -// RUN: %clang_cl -c --target=x86_64-windows-msvc /EHsc -O2 -fms-secure-hotpatch-functions-list=this_gets_hotpatched /Fo%t.obj /clang:-S /clang:-o- %s 2>& 1 | FileCheck %s - -class Foo { -public: - int x; -}; - -void this_might_throw(); - -extern "C" int this_gets_hotpatched(int k) { - int ret; - try { - this_might_throw(); - ret = 1; - } catch (Foo& f) { - ret = 2; - } - return ret; -} - -// We expect that RTTI data is not redirected. -// CHECK-NOT: "__ref_??_R0?AVFoo@@@8" diff --git a/clang/test/CodeGen/X86/ms-secure-hotpatch-globals.c b/clang/test/CodeGen/X86/ms-secure-hotpatch-globals.c deleted file mode 100644 index d76d2aa6d8acc..0000000000000 --- a/clang/test/CodeGen/X86/ms-secure-hotpatch-globals.c +++ /dev/null @@ -1,135 +0,0 @@ -// REQUIRES: x86-registered-target - -// This verifies that global variable redirection works correctly when using hotpatching. -// -// RUN: %clang_cl -c --target=x86_64-windows-msvc -O2 /Z7 \ -// RUN: -fms-secure-hotpatch-functions-list=hp1,hp2,hp3,hp4,hp5_phi_ptr_mixed,hp_phi_ptr_both,hp_const_ptr_sub \ -// RUN: /clang:-S /clang:-o- %s | FileCheck %s - -#ifdef __clang__ -#define NO_TAIL __attribute__((disable_tail_calls)) -#else -#define NO_TAIL -#endif - -extern int g_data[10]; - -struct SomeData { - int x; - int y; -}; - -const struct SomeData g_this_is_const = { 100, 200 }; - -struct HasPointers { - int* ptr; - int x; -}; - -extern struct HasPointers g_has_pointers; - -void take_data(const void* p); - -void do_side_effects(); -void do_other_side_effects(); - -void hp1() NO_TAIL { - take_data(&g_data[5]); -} - -// CHECK: hp1: -// CHECK: mov rcx, qword ptr [rip + __ref_g_data] -// CHECK: add rcx, 20 -// CHECK: call take_data -// CHECK: .seh_endproc - -void hp2() NO_TAIL { - // We do not expect string literals to be redirected. - take_data("hello, world!"); -} - -// CHECK: hp2: -// CHECK: lea rcx, [rip + "??_C@_0O@KJBLMJCB@hello?0?5world?$CB?$AA@"] -// CHECK: call take_data -// CHECK: .seh_endproc - -void hp3() NO_TAIL { - // We do not expect g_this_is_const to be redirected because it is const - // and contains no pointers. - take_data(&g_this_is_const); -} - -// CHECK: hp3: -// CHECK: lea rcx, [rip + g_this_is_const] -// CHECK: call take_data -// CHECK-NOT: __ref_g_this_is_const -// CHECK: .seh_endproc - -void hp4() NO_TAIL { - take_data(&g_has_pointers); - // We expect &g_has_pointers to be redirected. -} - -// CHECK: hp4: -// CHECK: mov rcx, qword ptr [rip + __ref_g_has_pointers] -// CHECK: call take_data -// CHECK: .seh_endproc - -// This case checks that global variable redirection interacts correctly with PHI nodes. -// The IR for this generates a "phi ptr g_has_pointers, g_this_is_const" node. -// We expect g_has_pointers to be redirected, but not g_this_is_const. -void hp5_phi_ptr_mixed(int x) NO_TAIL { - const void* y; - if (x) { - y = &g_has_pointers; - do_side_effects(); - } else { - y = &g_this_is_const; - do_other_side_effects(); - } - take_data(y); -} - -// CHECK: hp5_phi_ptr_mixed -// CHECK: .seh_endprologue -// CHECK: test ecx, ecx -// CHECK: mov rsi, qword ptr [rip + __ref_g_has_pointers] -// CHECK: call do_side_effects -// CHECK: jmp -// CHECK: call do_other_side_effects -// CHECK: lea rsi, [rip + g_this_is_const] -// CHECK: mov rcx, rsi -// CHECK: call take_data -// CHECK: .seh_endproc - -// This case tests that global variable redirection interacts correctly with PHI nodes, -// where two (all) operands of a given PHI node are globabl variables that redirect. -void hp_phi_ptr_both(int x) NO_TAIL { - const void* y; - if (x) { - y = &g_has_pointers; - do_side_effects(); - } else { - y = &g_data[5]; - do_other_side_effects(); - } - take_data(y); -} - -// CHECK: hp_phi_ptr_both: -// CHECK: .seh_endprologue -// CHECK: test ecx, ecx -// CHECK: mov rsi, qword ptr [rip + __ref_g_has_pointers] -// CHECK: mov rsi, qword ptr [rip + __ref_g_data] -// CHECK: take_data -// CHECK: .seh_endproc - -// Test a constant expression which references global variable addresses. -size_t hp_const_ptr_sub() NO_TAIL { - return (unsigned char*)&g_has_pointers - (unsigned char*)&g_data; -} - -// CHECK: hp_const_ptr_sub: -// CHECK: mov rax, qword ptr [rip + __ref_g_has_pointers] -// CHECK: sub rax, qword ptr [rip + __ref_g_data] -// CHECK: ret diff --git a/clang/test/CodeGen/X86/ms-secure-hotpatch-lto.c b/clang/test/CodeGen/X86/ms-secure-hotpatch-lto.c deleted file mode 100644 index 6adb0b1818e31..0000000000000 --- a/clang/test/CodeGen/X86/ms-secure-hotpatch-lto.c +++ /dev/null @@ -1,26 +0,0 @@ -// REQUIRES: x86-registered-target - -// This verifies that hotpatch function attributes are correctly propagated through LLVM IR when compiling with LTO. -// -// RUN: %clang_cl -c --target=x86_64-windows-msvc -O2 /Z7 -fms-secure-hotpatch-functions-list=this_gets_hotpatched -flto /Fo%t.bc %s -// RUN: llvm-dis %t.bc -o - | FileCheck %s -// -// CHECK-LABEL: define dso_local noundef i32 @this_gets_hotpatched() -// CHECK-SAME: #0 -// -// CHECK-LABEL: define dso_local noundef i32 @this_does_not_get_hotpatched() -// CHECK-SAME: #1 - -// CHECK: attributes #0 -// CHECK-SAME: "marked_for_windows_hot_patching" - -// CHECK: attributes #1 -// CHECK-NOT: "marked_for_windows_hot_patching" - -int __declspec(noinline) this_gets_hotpatched() { - return 42; -} - -int __declspec(noinline) this_does_not_get_hotpatched() { - return this_gets_hotpatched() + 100; -} diff --git a/clang/test/CodeGen/X86/ms-secure-hotpatch.c b/clang/test/CodeGen/X86/ms-secure-hotpatch.c deleted file mode 100644 index b829e5acc5c83..0000000000000 --- a/clang/test/CodeGen/X86/ms-secure-hotpatch.c +++ /dev/null @@ -1,23 +0,0 @@ -// REQUIRES: x86-registered-target - -// This verifies that hotpatch function attributes are correctly propagated when compiling directly to OBJ. -// -// RUN: echo this_gets_hotpatched > %t.patch-functions.txt -// RUN: %clang_cl -c --target=x86_64-windows-msvc -O2 /Z7 -fms-secure-hotpatch-functions-file=%t.patch-functions.txt /Fo%t.obj %s -// RUN: llvm-readobj --codeview %t.obj | FileCheck %s - -void this_might_have_side_effects(); - -int __declspec(noinline) this_gets_hotpatched() { - this_might_have_side_effects(); - return 42; -} - -// CHECK: Kind: S_HOTPATCHFUNC (0x1169) -// CHECK-NEXT: Function: this_gets_hotpatched - -int __declspec(noinline) this_does_not_get_hotpatched() { - return this_gets_hotpatched() + 100; -} - -// CHECK-NOT: S_HOTPATCHFUNC diff --git a/llvm/include/llvm/CodeGen/Passes.h b/llvm/include/llvm/CodeGen/Passes.h index 18df5d657064a..990452fa11fec 100644 --- a/llvm/include/llvm/CodeGen/Passes.h +++ b/llvm/include/llvm/CodeGen/Passes.h @@ -618,9 +618,6 @@ LLVM_ABI FunctionPass *createSelectOptimizePass(); LLVM_ABI FunctionPass *createCallBrPass(); -/// Creates Windows Secure Hot Patch pass. \see WindowsSecureHotPatching.cpp -ModulePass *createWindowsSecureHotPatchingPass(); - /// Lowers KCFI operand bundles for indirect calls. LLVM_ABI FunctionPass *createKCFIPass(); } // namespace llvm diff --git a/llvm/include/llvm/DebugInfo/CodeView/CodeViewSymbols.def b/llvm/include/llvm/DebugInfo/CodeView/CodeViewSymbols.def index b38bdb482df43..9d85acc49fa02 100644 --- a/llvm/include/llvm/DebugInfo/CodeView/CodeViewSymbols.def +++ b/llvm/include/llvm/DebugInfo/CodeView/CodeViewSymbols.def @@ -256,8 +256,6 @@ SYMBOL_RECORD_ALIAS(S_GTHREAD32 , 0x1113, GlobalTLS, ThreadLocalDataSym) SYMBOL_RECORD(S_UNAMESPACE , 0x1124, UsingNamespaceSym) SYMBOL_RECORD(S_ANNOTATION , 0x1019, AnnotationSym) -SYMBOL_RECORD(S_HOTPATCHFUNC , 0x1169, HotPatchFuncSym) - #undef CV_SYMBOL #undef SYMBOL_RECORD #undef SYMBOL_RECORD_ALIAS diff --git a/llvm/include/llvm/DebugInfo/CodeView/SymbolRecord.h b/llvm/include/llvm/DebugInfo/CodeView/SymbolRecord.h index f5f6fe69430cc..5b4f0d31e6427 100644 --- a/llvm/include/llvm/DebugInfo/CodeView/SymbolRecord.h +++ b/llvm/include/llvm/DebugInfo/CodeView/SymbolRecord.h @@ -177,21 +177,6 @@ class CallerSym : public SymbolRecord { uint32_t RecordOffset = 0; }; -class HotPatchFuncSym : public SymbolRecord { -public: - explicit HotPatchFuncSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {} - HotPatchFuncSym(uint32_t RecordOffset) - : SymbolRecord(SymbolRecordKind::HotPatchFuncSym), - RecordOffset(RecordOffset) {} - - // This is an ItemID in the IPI stream, which points to an LF_FUNC_ID or - // LF_MFUNC_ID record. - TypeIndex Function; - StringRef Name; - - uint32_t RecordOffset = 0; -}; - struct DecodedAnnotation { StringRef Name; ArrayRef<uint8_t> Bytes; diff --git a/llvm/include/llvm/IR/Attributes.td b/llvm/include/llvm/IR/Attributes.td index 0bcd15eeed879..d488c5f419b82 100644 --- a/llvm/include/llvm/IR/Attributes.td +++ b/llvm/include/llvm/IR/Attributes.td @@ -389,16 +389,6 @@ def CoroDestroyOnlyWhenComplete : EnumAttr<"coro_only_destroy_when_complete", In /// pipeline to perform elide on the call or invoke instruction. def CoroElideSafe : EnumAttr<"coro_elide_safe", IntersectPreserve, [FnAttr]>; -/// Function is marked for Windows Hot Patching -def MarkedForWindowsSecureHotPatching - : StrBoolAttr<"marked_for_windows_hot_patching">; - -/// Global variable should not be accessed through a "__ref_" global variable in -/// a hot patching function This attribute is applied to the global variable -/// decl, not the hotpatched function. -def AllowDirectAccessInHotPatchFunction - : StrBoolAttr<"allow_direct_access_in_hot_patch_function">; - /// Target-independent string attributes. def LessPreciseFPMAD : StrBoolAttr<"less-precise-fpmad">; def NoInfsFPMath : StrBoolAttr<"no-infs-fp-math">; diff --git a/llvm/include/llvm/InitializePasses.h b/llvm/include/llvm/InitializePasses.h index 1c4ed3843b390..1b5b1d5888824 100644 --- a/llvm/include/llvm/InitializePasses.h +++ b/llvm/include/llvm/InitializePasses.h @@ -336,7 +336,6 @@ LLVM_ABI void initializeVerifierLegacyPassPass(PassRegistry &); LLVM_ABI void initializeVirtRegMapWrapperLegacyPass(PassRegistry &); LLVM_ABI void initializeVirtRegRewriterLegacyPass(PassRegistry &); LLVM_ABI void initializeWasmEHPreparePass(PassRegistry &); -LLVM_ABI void initializeWindowsSecureHotPatchingPass(PassRegistry &); LLVM_ABI void initializeWinEHPreparePass(PassRegistry &); LLVM_ABI void initializeWriteBitcodePassPass(PassRegistry &); LLVM_ABI void initializeXRayInstrumentationLegacyPass(PassRegistry &); diff --git a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp index 5e1b313b4d2fa..ea57a8fa1f793 100644 --- a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp @@ -669,8 +669,6 @@ void CodeViewDebug::endModule() { if (!Asm) return; - emitSecureHotPatchInformation(); - emitInlineeLinesSubsection(); // Emit per-function debug information. @@ -825,28 +823,6 @@ void CodeViewDebug::emitObjName() { endSymbolRecord(CompilerEnd); } -void CodeViewDebug::emitSecureHotPatchInformation() { - MCSymbol *hotPatchInfo = nullptr; - - for (const auto &F : MMI->getModule()->functions()) { - if (!F.isDeclarationForLinker() && - F.hasFnAttribute("marked_for_windows_hot_patching")) { - if (hotPatchInfo == nullptr) - hotPatchInfo = beginCVSubsection(DebugSubsectionKind::Symbols); - MCSymbol *HotPatchEnd = beginSymbolRecord(SymbolKind::S_HOTPATCHFUNC); - auto *SP = F.getSubprogram(); - OS.AddComment("Function"); - OS.emitInt32(getFuncIdForSubprogram(SP).getIndex()); - OS.AddComment("Name"); - emitNullTerminatedSymbolName(OS, F.getName()); - endSymbolRecord(HotPatchEnd); - } - } - - if (hotPatchInfo != nullptr) - endCVSubsection(hotPatchInfo); -} - namespace { struct Version { int Part[4]; diff --git a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h index c862802d835d7..5f4f30271d9cb 100644 --- a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h +++ b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h @@ -337,8 +337,6 @@ class LLVM_LIBRARY_VISIBILITY CodeViewDebug : public DebugHandlerBase { void emitCompilerInformation(); - void emitSecureHotPatchInformation(); - void emitBuildInfo(); void emitInlineeLinesSubsection(); diff --git a/llvm/lib/CodeGen/CMakeLists.txt b/llvm/lib/CodeGen/CMakeLists.txt index f8f9bbba53e43..5dd6413431255 100644 --- a/llvm/lib/CodeGen/CMakeLists.txt +++ b/llvm/lib/CodeGen/CMakeLists.txt @@ -250,7 +250,6 @@ add_llvm_component_library(LLVMCodeGen VirtRegMap.cpp WasmEHPrepare.cpp WindowScheduler.cpp - WindowsSecureHotPatching.cpp WinEHPrepare.cpp XRayInstrumentation.cpp ${GeneratedMLSources} diff --git a/llvm/lib/CodeGen/TargetPassConfig.cpp b/llvm/lib/CodeGen/TargetPassConfig.cpp index 7d7c6e743fa76..4ae52b056d844 100644 --- a/llvm/lib/CodeGen/TargetPassConfig.cpp +++ b/llvm/lib/CodeGen/TargetPassConfig.cpp @@ -893,9 +893,6 @@ void TargetPassConfig::addIRPasses() { if (EnableGlobalMergeFunc) addPass(createGlobalMergeFuncPass()); - - if (TM->getTargetTriple().isOSWindows()) - addPass(createWindowsSecureHotPatchingPass()); } /// Turn exception handling constructs into something the code generators can diff --git a/llvm/lib/CodeGen/WindowsSecureHotPatching.cpp b/llvm/lib/CodeGen/WindowsSecureHotPatching.cpp deleted file mode 100644 index 6267207dbcbff..0000000000000 --- a/llvm/lib/CodeGen/WindowsSecureHotPatching.cpp +++ /dev/null @@ -1,617 +0,0 @@ -//===------ WindowsHotPatch.cpp - Support for Windows hotpatching ---------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// Provides support for the Windows "Secure Hot-Patching" feature. -// -// Windows contains technology, called "Secure Hot-Patching" (SHP), for securely -// applying hot-patches to a running system. Hot-patches may be applied to the -// kernel, kernel-mode components, device drivers, user-mode system services, -// etc. -// -// SHP relies on integration between many tools, including compiler, linker, -// hot-patch generation tools, and the Windows kernel. This file implements that -// part of the workflow needed in compilers / code generators. -// -// SHP is not intended for productivity scenarios such as Edit-and-Continue or -// interactive development. SHP is intended to minimize downtime during -// installation of Windows OS patches. -// -// In order to work with SHP, LLVM must do all of the following: -// -// * On some architectures (X86, AMD64), the function prolog must begin with -// hot-patchable instructions. This is handled by the MSVC `/hotpatch` option -// and the equivalent `-fms-hotpatch` function. This is necessary because we -// generally cannot anticipate which functions will need to be patched in the -// future. This option ensures that a function can be hot-patched in the -// future, but does not actually generate any hot-patch for it. -// -// * For a selected set of functions that are being hot-patched (which are -// identified using command-line options), LLVM must generate the -// `S_HOTPATCHFUNC` CodeView record (symbol). This record indicates that a -// function was compiled with hot-patching enabled. -// -// This implementation uses the `MarkedForWindowsHotPatching` attribute to -// annotate those functions that were marked for hot-patching by command-line -// parameters. The attribute may be specified by a language front-end by -// setting an attribute when a function is created in LLVM IR, or it may be -// set by passing LLVM arguments. -// -// * For those functions that are hot-patched, LLVM must rewrite references to -// global variables so that they are indirected through a `__ref_*` pointer -// variable. For each global variable, that is accessed by a hot-patched -// function, e.g. `FOO`, a `__ref_FOO` global pointer variable is created and -// all references to the original `FOO` are rewritten as dereferences of the -// `__ref_FOO` pointer. -// -// Some globals do not need `__ref_*` indirection. The pointer indirection -// behavior can be disabled for these globals by marking them with the -// `AllowDirectAccessInHotPatchFunction`. -// -// Rewriting references to global variables has some complexity. -// -// For ordinary instructions that reference GlobalVariables, we rewrite the -// operand of the instruction to a Load of the __ref_* variable. -// -// For constant expressions, we have to convert the constant expression (and -// transitively all constant expressions in its parent chain) to non-constant -// expressions, i.e. to a sequence of instructions. -// -// Pass 1: -// * Enumerate all instructions in all basic blocks. -// -// * If an instruction references a GlobalVariable (and it is not marked -// as being ignored), then we create (if necessary) the __ref_* variable -// for the GlobalVariable reference. However, we do not yet modify the -// Instruction. -// -// * If an instruction has an operand that is a ConstantExpr and the -// ConstantExpression tree contains a reference to a GlobalVariable, then -// we similarly create __ref_*. Similarly, we do not yet modify the -// Instruction or the ConstantExpr tree. -// -// After Pass 1 completes, we will know whether we found any references to -// globals in this pass. If the function does not use any globals (and most -// functions do not use any globals), then we return immediately. -// -// If a function does reference globals, then we iterate the list of globals -// used by this function and we generate Load instructions for each (unique) -// global. -// -// Next, we do another pass over all instructions: -// -// Pass 2: -// * Re-visit the instructions that were found in Pass 1. -// -// * If an instruction operand is a GlobalVariable, then look up the -// replacement -// __ref_* global variable and the Value that came from the Load instruction -// for it. Replace the operand of the GlobalVariable with the Load Value. -// -// * If an instruction operand is a ConstantExpr, then recursively examine the -// operands of all instructions in the ConstantExpr tree. If an operand is -// a GlobalVariable, then replace the operand with the result of the load -// *and* convert the ConstantExpr to a non-constant instruction. This -// instruction will need to be inserted into the BB of the instruction whose -// operand is being modified, ideally immediately before the instruction -// being modified. -// -// Limitations -// -// This feature is not intended to work in every situation. There are many -// legitimate code changes (patches) for which it is not possible to generate -// a hot-patch. Developers who are writing hot-patches are expected to -// understand the limitations. -// -// Tools which generate hot-patch metadata may also check that certain -// variables are upheld, and some of these invariants may be global (may require -// whole-program knowledge, not available in any single compiland). However, -// such tools are not required to be perfect; they are also best-effort. -// -// For these reasons, the hot-patching support implemented in this file is -// "best effort". It does not recognize every possible code pattern that could -// be patched, nor does it generate diagnostics for certain code patterns that -// could result in a binary that does not work with hot-patching. For example, -// const GlobalVariables that point to other non-const GlobalVariables are not -// compatible with hot-patching because they cannot use __ref_*-based -// redirection. -// -// References -// -// * "Hotpatching on Windows": -// https://techcommunity.microsoft.com/blog/windowsosplatform/hotpatching-on-windows/2959541 -// -// * "Hotpatch for Windows client now available": -// https://techcommunity.microsoft.com/blog/windows-itpro-blog/hotpatch-for-windows-client-now-available/4399808 -// -// * "Get hotpatching for Windows Server": -// https://www.microsoft.com/en-us/windows-server/blog/2025/04/24/tired-of-all-the-restarts-get-hotpatching-for-windows-server/ -// -//===----------------------------------------------------------------------===// - -#include "llvm/ADT/SmallSet.h" -#include "llvm/CodeGen/Passes.h" -#include "llvm/IR/Attributes.h" -#include "llvm/IR/DIBuilder.h" -#include "llvm/IR/DiagnosticInfo.h" -#include "llvm/IR/Function.h" -#include "llvm/IR/IRBuilder.h" -#include "llvm/IR/InstIterator.h" -#include "llvm/IR/Module.h" -#include "llvm/InitializePasses.h" -#include "llvm/Pass.h" -#include "llvm/Support/CommandLine.h" -#include "llvm/Support/LineIterator.h" -#include "llvm/Support/MemoryBuffer.h" - -using namespace llvm; - -#define DEBUG_TYPE "windows-secure-hot-patch" - -// A file containing list of mangled function names to mark for hot patching. -static cl::opt<std::string> LLVMMSSecureHotPatchFunctionsFile( - "ms-secure-hotpatch-functions-file", cl::value_desc("filename"), - cl::desc("A file containing list of mangled function names to mark for " - "Windows Secure Hot-Patching")); - -// A list of mangled function names to mark for hot patching. -static cl::list<std::string> LLVMMSSecureHotPatchFunctionsList( - "ms-secure-hotpatch-functions-list", cl::value_desc("list"), - cl::desc("A list of mangled function names to mark for Windows Secure " - "Hot-Patching"), - cl::CommaSeparated); - -namespace { - -struct GlobalVariableUse { - // GlobalVariable *GV; - Instruction *User; - unsigned Op; -}; - -class WindowsSecureHotPatching : public ModulePass { -public: - static char ID; - - WindowsSecureHotPatching() : ModulePass(ID) { - initializeWindowsSecureHotPatchingPass(*PassRegistry::getPassRegistry()); - } - - void getAnalysisUsage(AnalysisUsage &AU) const override { - AU.setPreservesCFG(); - } - - bool doInitialization(Module &) override; - bool runOnModule(Module &M) override { return false; } - -private: - bool - runOnFunction(Function &F, - SmallDenseMap<GlobalVariable *, GlobalVariable *> &RefMapping); -}; - -} // end anonymous namespace - -char WindowsSecureHotPatching::ID = 0; - -INITIALIZE_PASS(WindowsSecureHotPatching, "windows-secure-hot-patch", - "Mark functions for Windows hot patch support", false, false) -ModulePass *llvm::createWindowsSecureHotPatchingPass() { - return new WindowsSecureHotPatching(); -} - -// Find functions marked with Attribute::MarkedForWindowsHotPatching and modify -// their code (if necessary) to account for accesses to global variables. -// -// This runs during doInitialization() instead of runOnModule() because it needs -// to run before CodeViewDebug::collectGlobalVariableInfo(). -bool WindowsSecureHotPatching::doInitialization(Module &M) { - // The front end may have already marked functions for hot-patching. However, - // we also allow marking functions by passing -ms-hotpatch-functions-file or - // -ms-hotpatch-functions-list directly to LLVM. This allows hot-patching to - // work with languages that have not yet updated their front-ends. - if (!LLVMMSSecureHotPatchFunctionsFile.empty() || - !LLVMMSSecureHotPatchFunctionsList.empty()) { - std::vector<std::string> HotPatchFunctionsList; - - if (!LLVMMSSecureHotPatchFunctionsFile.empty()) { - auto BufOrErr = MemoryBuffer::getFile(LLVMMSSecureHotPatchFunctionsFile); - if (BufOrErr) { - const MemoryBuffer &FileBuffer = **BufOrErr; - for (line_iterator I(FileBuffer.getMemBufferRef(), true), E; I != E; - ++I) - HotPatchFunctionsList.push_back(std::string{*I}); - } else { - M.getContext().diagnose(DiagnosticInfoGeneric{ - Twine("failed to open hotpatch functions file " - "(--ms-hotpatch-functions-file): ") + - LLVMMSSecureHotPatchFunctionsFile + Twine(" : ") + - BufOrErr.getError().message()}); - } - } - - if (!LLVMMSSecureHotPatchFunctionsList.empty()) - for (const auto &FuncName : LLVMMSSecureHotPatchFunctionsList) - HotPatchFunctionsList.push_back(FuncName); - - // Build a set for quick lookups. This points into HotPatchFunctionsList, so - // HotPatchFunctionsList must live longer than HotPatchFunctionsSet. - SmallSet<StringRef, 16> HotPatchFunctionsSet; - for (const auto &FuncName : HotPatchFunctionsList) - HotPatchFunctionsSet.insert(StringRef{FuncName}); - - // Iterate through all of the functions and check whether they need to be - // marked for hotpatching using the list provided directly to LLVM. - for (auto &F : M.functions()) { - // Ignore declarations that are not definitions. - if (F.isDeclarationForLinker()) - continue; - - if (HotPatchFunctionsSet.contains(F.getName())) - F.addFnAttr("marked_for_windows_hot_patching"); - } - } - - SmallDenseMap<GlobalVariable *, GlobalVariable *> RefMapping; - bool MadeChanges = false; - for (auto &F : M.functions()) { - if (F.hasFnAttribute("marked_for_windows_hot_patching")) { - if (runOnFunction(F, RefMapping)) - MadeChanges = true; - } - } - return MadeChanges; -} - -static bool TypeContainsPointers(Type *ty) { - switch (ty->getTypeID()) { - case Type::PointerTyID: - return true; - - case Type::ArrayTyID: - return TypeContainsPointers(ty->getArrayElementType()); - - case Type::StructTyID: { - unsigned NumElements = ty->getStructNumElements(); - for (unsigned I = 0; I < NumElements; ++I) { - if (TypeContainsPointers(ty->getStructElementType(I))) { - return true; - } - } - return false; - } - - default: - return false; - } -} - -// Returns true if GV needs redirection through a __ref_* variable. -static bool globalVariableNeedsRedirect(GlobalVariable *GV) { - // If a global variable is explictly marked as allowing access in hot-patched - // functions, then do not redirect it. - if (GV->hasAttribute("allow_direct_access_in_hot_patch_function")) - return false; - - // If the global variable is not a constant, then we want to redirect it. - if (!GV->isConstant()) { - if (GV->getName().starts_with("??_R")) { - // This is the name mangling prefix that MSVC uses for RTTI data. - // Clang is currently generating RTTI data that is marked non-constant. - // We override that and treat it like it is constant. - return false; - } - - // In general, if a global variable is not a constant, then redirect it. - return true; - } - - // If the type of GV cannot contain pointers, then it cannot point to - // other global variables. In this case, there is no need for redirects. - // For example, string literals do not contain pointers. - return TypeContainsPointers(GV->getValueType()); -} - -// Get or create a new global variable that points to the old one and whose -// name begins with `__ref_`. -// -// In hot-patched images, the __ref_* variables point to global variables in -// the original (unpatched) image. Hot-patched functions in the hot-patch -// image use these __ref_* variables to access global variables. This ensures -// that all code (both unpatched and patched) is using the same instances of -// global variables. -// -// The Windows hot-patch infrastructure handles modifying these __ref_* -// variables. By default, they are initialized with pointers to the equivalent -// global variables, so when a hot-patch module is loaded *as* a base image -// (such as after a system reboot), hot-patch functions will access the -// instances of global variables that are compiled into the hot-patch image. -// This is the desired outcome, since in this situation (normal boot) the -// hot-patch image *is* the base image. -// -// When we create the GlobalVariable for the __ref_* variable, we must create -// it as a *non-constant* global variable. The __ref_* pointers will not change -// during the runtime of the program, so it is tempting to think that they -// should be constant. However, they still need to be updateable by the -// hot-patching infrastructure. Also, if the GlobalVariable is created as a -// constant, then the LLVM optimizer will assume that it can dereference the -// definition of the __ref_* variable at compile time, which defeats the -// purpose of the indirection (pointer). -// -// The RefMapping table spans the entire module, not just a single function. -static GlobalVariable *getOrCreateRefVariable( - Function &F, SmallDenseMap<GlobalVariable *, GlobalVariable *> &RefMapping, - GlobalVariable *GV) { - GlobalVariable *&ReplaceWithRefGV = RefMapping.try_emplace(GV).first->second; - if (ReplaceWithRefGV != nullptr) { - // We have already created a __ref_* pointer for this GlobalVariable. - return ReplaceWithRefGV; - } - - Module *M = F.getParent(); - - const DISubprogram *Subprogram = F.getSubprogram(); - DICompileUnit *Unit = Subprogram != nullptr ? Subprogram->getUnit() : nullptr; - DIFile *File = Subprogram != nullptr ? Subprogram->getFile() : nullptr; - DIBuilder DebugInfo{*F.getParent(), true, Unit}; - - auto PtrTy = PointerType::get(M->getContext(), 0); - - Constant *AddrOfOldGV = - ConstantExpr::getGetElementPtr(PtrTy, GV, ArrayRef<Value *>{}); - - GlobalVariable *RefGV = - new GlobalVariable(*M, PtrTy, false, GlobalValue::LinkOnceAnyLinkage, - AddrOfOldGV, Twine("__ref_").concat(GV->getName()), - nullptr, GlobalVariable::NotThreadLocal); - - // Create debug info for the replacement global variable. - DataLayout Layout = M->getDataLayout(); - DIType *DebugType = DebugInfo.createPointerType( - nullptr, Layout.getTypeSizeInBits(GV->getValueType())); - DIGlobalVariableExpression *GVE = DebugInfo.createGlobalVariableExpression( - Unit, RefGV->getName(), StringRef{}, File, - /*LineNo*/ 0, DebugType, - /*IsLocalToUnit*/ false); - RefGV->addDebugInfo(GVE); - - // Store the __ref_* in RefMapping so that future calls use the same RefGV. - ReplaceWithRefGV = RefGV; - - return RefGV; -} - -// Given a ConstantExpr, this searches for GlobalVariable references within -// the expression tree. If found, it will generate instructions and will -// return a non-null Value* that points to the new root instruction. -// -// If C does not contain any GlobalVariable references, this returns nullptr. -// -// If this function creates new instructions, then it will insert them -// before InsertionPoint. -static Value *rewriteGlobalVariablesInConstant( - Constant *C, SmallDenseMap<GlobalVariable *, Value *> &GVLoadMap, - IRBuilder<> &IRBuilderAtEntry) { - if (C->getValueID() == Value::GlobalVariableVal) { - GlobalVariable *GV = cast<GlobalVariable>(C); - if (globalVariableNeedsRedirect(GV)) { - return GVLoadMap.at(GV); - } else { - return nullptr; - } - } - - // Scan the operands of this expression. - - SmallVector<Value *, 8> ReplacedValues; - bool ReplacedAnyOperands = false; - - unsigned NumOperands = C->getNumOperands(); - for (unsigned OpIndex = 0; OpIndex < NumOperands; ++OpIndex) { - Value *OldValue = C->getOperand(OpIndex); - Value *ReplacedValue = nullptr; - if (Constant *OldConstant = dyn_cast<Constant>(OldValue)) { - ReplacedValue = rewriteGlobalVariablesInConstant(OldConstant, GVLoadMap, - IRBuilderAtEntry); - } - // Do not use short-circuiting, here. We need to traverse the whole tree. - ReplacedAnyOperands |= ReplacedValue != nullptr; - ReplacedValues.push_back(ReplacedValue); - } - - // If none of our operands were replaced, then don't rewrite this expression. - if (!ReplacedAnyOperands) { - return nullptr; - } - - // We need to rewrite this expression. Convert this constant expression - // to an instruction, then replace any operands as needed. - Instruction *NewInst = cast<ConstantExpr>(C)->getAsInstruction(); - for (unsigned OpIndex = 0; OpIndex < NumOperands; ++OpIndex) { - Value *ReplacedValue = ReplacedValues[OpIndex]; - if (ReplacedValue != nullptr) { - NewInst->setOperand(OpIndex, ReplacedValue); - } - } - - // Insert the new instruction before the reference instruction. - IRBuilderAtEntry.Insert(NewInst); - - return NewInst; -} - -static bool searchConstantExprForGlobalVariables( - Value *V, SmallDenseMap<GlobalVariable *, Value *> &GVLoadMap, - SmallVector<GlobalVariableUse> &GVUses) { - - SmallVector<Value *, 8> ReplacedOperands; - - if (GlobalVariable *GV = dyn_cast<GlobalVariable>(V)) { - if (globalVariableNeedsRedirect(GV)) { - GVLoadMap[GV] = nullptr; - return true; - } else { - return false; - } - } - - if (User *U = dyn_cast<User>(V)) { - unsigned NumOperands = U->getNumOperands(); - bool FoundAny = false; - for (unsigned OpIndex = 0; OpIndex < NumOperands; ++OpIndex) { - Value *Op = U->getOperand(OpIndex); - // Do not use short-circuiting, here. We need to traverse the whole tree. - FoundAny |= searchConstantExprForGlobalVariables(Op, GVLoadMap, GVUses); - } - return FoundAny; - } else { - return false; - } -} - -// Processes a function that is marked for hot-patching. -// -// If a function is marked for hot-patching, we generate an S_HOTPATCHFUNC -// CodeView debug symbol. Tools that generate hot-patches look for -// S_HOTPATCHFUNC in final PDBs so that they can find functions that have been -// hot-patched and so that they can distinguish hot-patched functions from -// non-hot-patched functions. -// -// Also, in functions that are hot-patched, we must indirect all access to -// (mutable) global variables through a pointer. This pointer may point into the -// unpatched ("base") binary or may point into the patched image, depending on -// whether a hot-patch was loaded as a patch or as a base image. These -// indirections go through a new global variable, named `__ref_<Foo>` where -// `<Foo>` is the original symbol name of the global variable. -// -// This function handles rewriting accesses to global variables, but the -// generation of S_HOTPATCHFUNC occurs in -// CodeViewDebug::emitHotPatchInformation(). -// -// Returns true if any global variable references were found and rewritten. -bool WindowsSecureHotPatching::runOnFunction( - Function &F, - SmallDenseMap<GlobalVariable *, GlobalVariable *> &RefMapping) { - // Scan the function for references to global variables. If we find such a - // reference, create (if necessary) the __ref_* variable, then add an entry - // to the GVUses table. - // - // We ignore references to global variables if the variable is marked with - // AllowDirectAccessInHotPatchFunction. - - SmallDenseMap<GlobalVariable *, Value *> GVLoadMap; - SmallVector<GlobalVariableUse> GVUses; - - for (auto &I : instructions(F)) { - unsigned NumOperands = I.getNumOperands(); - for (unsigned OpIndex = 0; OpIndex < NumOperands; ++OpIndex) { - Value *V = I.getOperand(OpIndex); - - bool FoundAnyGVUses = false; - - switch (V->getValueID()) { - case Value::GlobalVariableVal: { - // Discover all uses of GlobalVariable, these will need to be replaced. - GlobalVariable *GV = cast<GlobalVariable>(V); - if (globalVariableNeedsRedirect(GV)) { - GVLoadMap.insert(std::make_pair(GV, nullptr)); - FoundAnyGVUses = true; - } - break; - } - - case Value::ConstantExprVal: { - ConstantExpr *CE = cast<ConstantExpr>(V); - if (searchConstantExprForGlobalVariables(CE, GVLoadMap, GVUses)) { - FoundAnyGVUses = true; - } - break; - } - - default: - break; - } - - if (FoundAnyGVUses) { - GVUses.push_back(GlobalVariableUse{&I, OpIndex}); - } - } - } - - // If this function did not reference any global variables then we have no - // work to do. Most functions do not access global variables. - if (GVUses.empty()) { - return false; - } - - // We know that there is at least one instruction that needs to be rewritten. - // Generate a Load instruction for each unique GlobalVariable used by this - // function. The Load instructions are inserted at the beginning of the - // entry block. Since entry blocks cannot contain PHI instructions, there is - // no need to skip PHI instructions. - - // We use a single IRBuilder for inserting Load instructions as well as the - // constants that we convert to instructions. Because constants do not - // depend on any dynamic values (they're constant, after all!), it is safe - // to move them to the start of entry BB. - - auto &EntryBlock = F.getEntryBlock(); - IRBuilder<> IRBuilderAtEntry(&EntryBlock, EntryBlock.begin()); - - for (auto &[GV, LoadValue] : GVLoadMap) { - assert(LoadValue == nullptr); - GlobalVariable *RefGV = getOrCreateRefVariable(F, RefMapping, GV); - LoadValue = IRBuilderAtEntry.CreateLoad(RefGV->getValueType(), RefGV); - } - - const DISubprogram *Subprogram = F.getSubprogram(); - DICompileUnit *Unit = Subprogram != nullptr ? Subprogram->getUnit() : nullptr; - DIBuilder DebugInfo{*F.getParent(), true, Unit}; - - // Go back to the instructions and rewrite their uses of GlobalVariable. - // Because a ConstantExpr can be a tree, it may reference more than one - // GlobalVariable. - - for (auto &GVUse : GVUses) { - Value *OldOperandValue = GVUse.User->getOperand(GVUse.Op); - Value *NewOperandValue; - - switch (OldOperandValue->getValueID()) { - case Value::GlobalVariableVal: { - // This is easy. Look up the replacement value and store the operand. - Value *OperandValue = GVUse.User->getOperand(GVUse.Op); - GlobalVariable *GV = cast<GlobalVariable>(OperandValue); - NewOperandValue = GVLoadMap.at(GV); - break; - } - - case Value::ConstantExprVal: { - // Walk the recursive tree of the ConstantExpr. If we find a - // GlobalVariable then replace it with the loaded value and rewrite - // the ConstantExpr to an Instruction and insert it before the - // current instruction. - Value *OperandValue = GVUse.User->getOperand(GVUse.Op); - ConstantExpr *CE = cast<ConstantExpr>(OperandValue); - NewOperandValue = - rewriteGlobalVariablesInConstant(CE, GVLoadMap, IRBuilderAtEntry); - assert(NewOperandValue != nullptr); - break; - } - - default: - // We should only ever get here because a GVUse was created in the first - // pass, and this only happens for GlobalVariableVal and ConstantExprVal. - llvm_unreachable_internal( - "unexpected Value in second pass of hot-patching"); - break; - } - - GVUse.User->setOperand(GVUse.Op, NewOperandValue); - } - - return true; -} diff --git a/llvm/lib/DebugInfo/CodeView/SymbolDumper.cpp b/llvm/lib/DebugInfo/CodeView/SymbolDumper.cpp index 9cb3bca8d6e5e..f56739db7c75f 100644 --- a/llvm/lib/DebugInfo/CodeView/SymbolDumper.cpp +++ b/llvm/lib/DebugInfo/CodeView/SymbolDumper.cpp @@ -672,13 +672,6 @@ Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, return Error::success(); } -Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, - HotPatchFuncSym &HotPatchFunc) { - printTypeIndex("Function", HotPatchFunc.Function); - W.printString("Name", HotPatchFunc.Name); - return Error::success(); -} - Error CVSymbolDumperImpl::visitUnknownSymbol(CVSymbol &CVR) { W.printNumber("Length", CVR.length()); return Error::success(); diff --git a/llvm/lib/DebugInfo/CodeView/SymbolRecordMapping.cpp b/llvm/lib/DebugInfo/CodeView/SymbolRecordMapping.cpp index 525343b90a3ae..b5e366b965a95 100644 --- a/llvm/lib/DebugInfo/CodeView/SymbolRecordMapping.cpp +++ b/llvm/lib/DebugInfo/CodeView/SymbolRecordMapping.cpp @@ -496,13 +496,6 @@ Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR, return Error::success(); } -Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR, - HotPatchFuncSym &HotPatchFunc) { - error(IO.mapInteger(HotPatchFunc.Function)); - error(IO.mapStringZ(HotPatchFunc.Name)); - return Error::success(); -} - RegisterId codeview::decodeFramePtrReg(EncodedFramePtrReg EncodedReg, CPUType CPU) { assert(unsigned(EncodedReg) < 4); diff --git a/llvm/lib/ObjectYAML/CodeViewYAMLSymbols.cpp b/llvm/lib/ObjectYAML/CodeViewYAMLSymbols.cpp index 3056251809308..b15919f68725f 100644 --- a/llvm/lib/ObjectYAML/CodeViewYAMLSymbols.cpp +++ b/llvm/lib/ObjectYAML/CodeViewYAMLSymbols.cpp @@ -605,11 +605,6 @@ template <> void SymbolRecordImpl<JumpTableSym>::map(IO &IO) { IO.mapRequired("EntriesCount", Symbol.EntriesCount); } -template <> void SymbolRecordImpl<HotPatchFuncSym>::map(IO &IO) { - IO.mapRequired("Function", Symbol.Function); - IO.mapRequired("Name", Symbol.Name); -} - } // end namespace detail } // end namespace CodeViewYAML } // end namespace llvm diff --git a/llvm/test/CodeGen/X86/ms-secure-hotpatch-attr.ll b/llvm/test/CodeGen/X86/ms-secure-hotpatch-attr.ll deleted file mode 100644 index 7e60e6a047507..0000000000000 --- a/llvm/test/CodeGen/X86/ms-secure-hotpatch-attr.ll +++ /dev/null @@ -1,38 +0,0 @@ -; This tests directly annotating a function with marked_for_windows_hot_patching. -; -; RUN: llc -mtriple=x86_64-windows < %s | FileCheck %s - -source_filename = ".\\ms-secure-hotpatch-attr.ll" -target datalayout = "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" -target triple = "x86_64-pc-windows-msvc19.36.32537" - -@some_global_var = external global i32 - -define noundef i32 @this_gets_hotpatched() #0 { - %1 = load i32, ptr @some_global_var - %2 = add i32 %1, 1 - ret i32 %2 -} - -attributes #0 = { "marked_for_windows_hot_patching" mustprogress noinline nounwind optnone uwtable } - -; CHECK: this_gets_hotpatched: # @this_gets_hotpatched -; CHECK-NEXT: bb.0: -; CHECK-NEXT: movq __ref_some_global_var(%rip), %rax -; CHECK-NEXT: movl (%rax), %eax -; CHECK-NEXT: addl $1, %eax -; CHECK-NEXT: retq - -define noundef i32 @this_does_not_get_hotpatched() #1 { - %1 = load i32, ptr @some_global_var - %2 = add i32 %1, 1 - ret i32 %2 -} - -attributes #1 = { mustprogress noinline nounwind optnone uwtable } - -; CHECK: this_does_not_get_hotpatched: # @this_does_not_get_hotpatched -; CHECK-NEXT: bb.0: -; CHECK-NEXT: movl some_global_var(%rip), %eax -; CHECK-NEXT: addl $1, %eax -; CHECK-NEXT: retq diff --git a/llvm/test/CodeGen/X86/ms-secure-hotpatch-bad-file.ll b/llvm/test/CodeGen/X86/ms-secure-hotpatch-bad-file.ll deleted file mode 100644 index 5fec1c48495a2..0000000000000 --- a/llvm/test/CodeGen/X86/ms-secure-hotpatch-bad-file.ll +++ /dev/null @@ -1,16 +0,0 @@ -; RUN: not llc -mtriple=x86_64-windows --ms-secure-hotpatch-functions-file=%S/this-file-is-intentionally-missing-do-not-create-it.txt < %s 2>&1 | FileCheck %s -; CHECK: failed to open hotpatch functions file - -source_filename = ".\\ms-secure-hotpatch.ll" -target datalayout = "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" -target triple = "x86_64-pc-windows-msvc19.36.32537" - -@some_global_var = external global i32 - -define noundef i32 @this_gets_hotpatched() #0 { - %1 = load i32, ptr @some_global_var - %2 = add i32 %1, 1 - ret i32 %2 -} - -attributes #0 = { "marked_for_windows_hot_patching" mustprogress noinline nounwind optnone uwtable } diff --git a/llvm/test/CodeGen/X86/ms-secure-hotpatch-direct-global-access.ll b/llvm/test/CodeGen/X86/ms-secure-hotpatch-direct-global-access.ll deleted file mode 100644 index 5606b03760be1..0000000000000 --- a/llvm/test/CodeGen/X86/ms-secure-hotpatch-direct-global-access.ll +++ /dev/null @@ -1,39 +0,0 @@ -; This tests hotpatching functions that bypass double-indirection for global variables. -; -; RUN: llc -mtriple=x86_64-windows < %s | FileCheck %s - -source_filename = ".\\ms-secure-hotpatch-direct-global-access.ll" -target datalayout = "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" -target triple = "x86_64-pc-windows-msvc19.36.32537" - -@some_global_var = external global i32 #2 - -define noundef i32 @this_gets_hotpatched() #0 { - %1 = load i32, ptr @some_global_var - %2 = add i32 %1, 1 - ret i32 %2 -} - -attributes #0 = { "marked_for_windows_hot_patching" mustprogress noinline nounwind optnone uwtable } - -; CHECK: this_gets_hotpatched: # @this_gets_hotpatched -; CHECK-NEXT: bb.0: -; CHECK-NEXT: movl some_global_var(%rip), %eax -; CHECK-NEXT: addl $1, %eax -; CHECK-NEXT: retq - -define noundef i32 @this_does_not_get_hotpatched() #1 { - %1 = load i32, ptr @some_global_var - %2 = add i32 %1, 1 - ret i32 %2 -} - -attributes #1 = { mustprogress noinline nounwind optnone uwtable } - -attributes #2 = { "allow_direct_access_in_hot_patch_function" } - -; CHECK: this_does_not_get_hotpatched: # @this_does_not_get_hotpatched -; CHECK-NEXT: bb.0: -; CHECK-NEXT: movl some_global_var(%rip), %eax -; CHECK-NEXT: addl $1, %eax -; CHECK-NEXT: retq diff --git a/llvm/test/CodeGen/X86/ms-secure-hotpatch-functions-file.ll b/llvm/test/CodeGen/X86/ms-secure-hotpatch-functions-file.ll deleted file mode 100644 index bb79e08683aa7..0000000000000 --- a/llvm/test/CodeGen/X86/ms-secure-hotpatch-functions-file.ll +++ /dev/null @@ -1,39 +0,0 @@ -; This tests annotating a function with marked_for_windows_hot_patching by using --ms-hotpatch-functions-file. -; -; RUN: echo this_gets_hotpatched > %t.patch-functions.txt -; RUN: llc -mtriple=x86_64-windows --ms-secure-hotpatch-functions-file=%t.patch-functions.txt < %s | FileCheck %s - -source_filename = ".\\ms-secure-hotpatch-functions-file.ll" -target datalayout = "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" -target triple = "x86_64-pc-windows-msvc19.36.32537" - -@some_global_var = external global i32 - -define noundef i32 @this_gets_hotpatched() #0 { - %1 = load i32, ptr @some_global_var - %2 = add i32 %1, 1 - ret i32 %2 -} - -attributes #0 = { mustprogress noinline nounwind optnone uwtable } - -; CHECK: this_gets_hotpatched: # @this_gets_hotpatched -; CHECK-NEXT: bb.0: -; CHECK-NEXT: movq __ref_some_global_var(%rip), %rax -; CHECK-NEXT: movl (%rax), %eax -; CHECK-NEXT: addl $1, %eax -; CHECK-NEXT: retq - -define noundef i32 @this_does_not_get_hotpatched() #1 { - %1 = load i32, ptr @some_global_var - %2 = add i32 %1, 1 - ret i32 %2 -} - -attributes #1 = { mustprogress noinline nounwind optnone uwtable } - -; CHECK: this_does_not_get_hotpatched: # @this_does_not_get_hotpatched -; CHECK-NEXT: bb.0: -; CHECK-NEXT: movl some_global_var(%rip), %eax -; CHECK-NEXT: addl $1, %eax -; CHECK-NEXT: retq diff --git a/llvm/test/CodeGen/X86/ms-secure-hotpatch-functions-list.ll b/llvm/test/CodeGen/X86/ms-secure-hotpatch-functions-list.ll deleted file mode 100644 index b1da1a2db66dc..0000000000000 --- a/llvm/test/CodeGen/X86/ms-secure-hotpatch-functions-list.ll +++ /dev/null @@ -1,38 +0,0 @@ -; This tests annotating a function with marked_for_windows_hot_patching by using --ms-hotpatch-functions-list. -; -; RUN: llc -mtriple=x86_64-windows --ms-secure-hotpatch-functions-list=this_gets_hotpatched < %s | FileCheck %s - -source_filename = ".\\ms-secure-hotpatch-functions-list.ll" -target datalayout = "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" -target triple = "x86_64-pc-windows-msvc19.36.32537" - -@some_global_var = external global i32 - -define noundef i32 @this_gets_hotpatched() #0 { - %1 = load i32, ptr @some_global_var - %2 = add i32 %1, 1 - ret i32 %2 -} - -attributes #0 = { mustprogress noinline nounwind optnone uwtable } - -; CHECK: this_gets_hotpatched: # @this_gets_hotpatched -; CHECK-NEXT: bb.0: -; CHECK-NEXT: movq __ref_some_global_var(%rip), %rax -; CHECK-NEXT: movl (%rax), %eax -; CHECK-NEXT: addl $1, %eax -; CHECK-NEXT: retq - -define noundef i32 @this_does_not_get_hotpatched() #1 { - %1 = load i32, ptr @some_global_var - %2 = add i32 %1, 1 - ret i32 %2 -} - -attributes #1 = { mustprogress noinline nounwind optnone uwtable } - -; CHECK: this_does_not_get_hotpatched: # @this_does_not_get_hotpatched -; CHECK-NEXT: bb.0: -; CHECK-NEXT: movl some_global_var(%rip), %eax -; CHECK-NEXT: addl $1, %eax -; CHECK-NEXT: retq diff --git a/llvm/tools/llvm-pdbutil/MinimalSymbolDumper.cpp b/llvm/tools/llvm-pdbutil/MinimalSymbolDumper.cpp index 66a091f50d6b2..479d025835188 100644 --- a/llvm/tools/llvm-pdbutil/MinimalSymbolDumper.cpp +++ b/llvm/tools/llvm-pdbutil/MinimalSymbolDumper.cpp @@ -955,11 +955,3 @@ Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, JumpTable.EntriesCount); return Error::success(); } - -Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, - HotPatchFuncSym &JumpTable) { - AutoIndent Indent(P, 7); - P.formatLine("function = {0}, name = {1}", typeIndex(JumpTable.Function), - JumpTable.Name); - return Error::success(); -} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits