llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang-codegen Author: Jacek Caban (cjacek) <details> <summary>Changes</summary> MSVC always emits minimal CodeView metadata containing compiler information, even when debug info is otherwise disabled. While this data is typically not meaningful on its own, the linker may use it to detect whether the object file was built with hotpatch support. To match this behavior, emit compiler info whenever the hotpatch option is enabled. --- Full diff: https://github.com/llvm/llvm-project/pull/142970.diff 10 Files Affected: - (modified) clang/lib/CodeGen/BackendUtil.cpp (-1) - (modified) clang/lib/CodeGen/CodeGenModule.cpp (+7-3) - (modified) clang/test/CodeGen/patchable-function-entry.c (+2) - (modified) llvm/include/llvm/Target/TargetOptions.h (+1-4) - (modified) llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp (+6-2) - (modified) llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp (+28-5) - (modified) llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h (+3) - (added) llvm/test/DebugInfo/PDB/hotpatch-dwarf.c (+59) - (added) llvm/test/DebugInfo/PDB/hotpatch-nodebug.c (+57) - (added) llvm/test/DebugInfo/PDB/hotpatch.test (+57) ``````````diff diff --git a/clang/lib/CodeGen/BackendUtil.cpp b/clang/lib/CodeGen/BackendUtil.cpp index cd5fc48c4a22b..2365f675b2dc3 100644 --- a/clang/lib/CodeGen/BackendUtil.cpp +++ b/clang/lib/CodeGen/BackendUtil.cpp @@ -473,7 +473,6 @@ static bool initTargetOptions(const CompilerInstance &CI, Options.LoopAlignment = CodeGenOpts.LoopAlignment; Options.DebugStrictDwarf = CodeGenOpts.DebugStrictDwarf; Options.ObjectFilenameForDebug = CodeGenOpts.ObjectFilenameForDebug; - Options.Hotpatch = CodeGenOpts.HotPatch; Options.JMCInstrument = CodeGenOpts.JMCInstrument; Options.XCOFFReadOnlyPointers = CodeGenOpts.XCOFFReadOnlyPointers; diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 468fc6e0e5c56..ddad9a66766fd 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -408,11 +408,11 @@ CodeGenModule::CodeGenModule(ASTContext &C, TBAA.reset(new CodeGenTBAA(Context, getTypes(), TheModule, CodeGenOpts, getLangOpts())); - // If debug info or coverage generation is enabled, create the CGDebugInfo - // object. + // If debug info, coverage generation or hotpatch is enabled, create the + // CGDebugInfo object. if (CodeGenOpts.getDebugInfo() != llvm::codegenoptions::NoDebugInfo || CodeGenOpts.CoverageNotesFile.size() || - CodeGenOpts.CoverageDataFile.size()) + CodeGenOpts.CoverageDataFile.size() || CodeGenOpts.HotPatch) DebugInfo.reset(new CGDebugInfo(*this)); Block.GlobalUniqueCount = 0; @@ -1031,6 +1031,10 @@ void CodeGenModule::Release() { // Function ID tables for EH Continuation Guard. getModule().addModuleFlag(llvm::Module::Warning, "ehcontguard", 1); } + if (CodeGenOpts.HotPatch) { + // Note if we are compiling with /hotpatch. + getModule().addModuleFlag(llvm::Module::Warning, "ms-hotpatch", 1); + } if (Context.getLangOpts().Kernel) { // Note if we are compiling with /kernel. getModule().addModuleFlag(llvm::Module::Warning, "ms-kernel", 1); diff --git a/clang/test/CodeGen/patchable-function-entry.c b/clang/test/CodeGen/patchable-function-entry.c index 2acd748758490..748d5c8bc5ae3 100644 --- a/clang/test/CodeGen/patchable-function-entry.c +++ b/clang/test/CodeGen/patchable-function-entry.c @@ -39,3 +39,5 @@ void f(void) {} // HOTPATCH: attributes #1 = { {{.*}} "patchable-function"="prologue-short-redirect" // HOTPATCH: attributes #2 = { {{.*}} "patchable-function"="prologue-short-redirect" // HOTPATCH: attributes #3 = { {{.*}} "patchable-function"="prologue-short-redirect" +// HOTPATCH: !0 = distinct !DICompileUnit(language: DW_LANG_C11, file: !1, producer: "clang version 21.0.0git", isOptimized: false, runtimeVersion: 0, emissionKind: NoDebug, splitDebugInlining: false, nameTableKind: None) +// HOTPATCH: !{{.}} = !{i32 2, !"ms-hotpatch", i32 1} diff --git a/llvm/include/llvm/Target/TargetOptions.h b/llvm/include/llvm/Target/TargetOptions.h index fd8dad4f6f791..25bbb73e9dedc 100644 --- a/llvm/include/llvm/Target/TargetOptions.h +++ b/llvm/include/llvm/Target/TargetOptions.h @@ -150,7 +150,7 @@ namespace llvm { EmitAddrsig(false), BBAddrMap(false), EmitCallSiteInfo(false), SupportsDebugEntryValues(false), EnableDebugEntryValues(false), ValueTrackingVariableLocations(false), ForceDwarfFrameSection(false), - XRayFunctionIndex(true), DebugStrictDwarf(false), Hotpatch(false), + XRayFunctionIndex(true), DebugStrictDwarf(false), PPCGenScalarMASSEntries(false), JMCInstrument(false), EnableCFIFixup(false), MisExpect(false), XCOFFReadOnlyPointers(false), VerifyArgABICompliance(true), @@ -363,9 +363,6 @@ namespace llvm { /// By default, it is set to false. unsigned DebugStrictDwarf : 1; - /// Emit the hotpatch flag in CodeView debug. - unsigned Hotpatch : 1; - /// Enables scalar MASS conversions unsigned PPCGenScalarMASSEntries : 1; diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp index bcfc64c6f36bb..d58e89dffc5c3 100644 --- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -561,8 +561,12 @@ bool AsmPrinter::doInitialization(Module &M) { if (MAI->doesSupportDebugInformation()) { bool EmitCodeView = M.getCodeViewFlag(); - if (EmitCodeView && - (TM.getTargetTriple().isOSWindows() || TM.getTargetTriple().isUEFI())) + // MSVC always emits minimal CodeView information with compiler metadata, + // even when debug info is otherwise disabled. While it's usually not + // meaningful, the linker may use it to detect whether the object file has + // hotpatching enabled. Emit compiler info in such cases. + if ((TM.getTargetTriple().isOSWindows() || TM.getTargetTriple().isUEFI()) && + (EmitCodeView || M.getModuleFlag("ms-hotpatch"))) Handlers.push_back(std::make_unique<CodeViewDebug>(this)); if (!EmitCodeView || M.getDwarfVersion()) { if (hasDebugInfo()) { diff --git a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp index fc43bc6f7776d..a0013fb30aa80 100644 --- a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp @@ -613,7 +613,8 @@ static SourceLanguage MapDWLangToCVLang(unsigned DWLang) { void CodeViewDebug::beginModule(Module *M) { // If module doesn't have named metadata anchors or COFF debug section // is not available, skip any debug info related stuff. - if (!Asm->hasDebugInfo() || + if (!(Asm->hasDebugInfo() || + MMI->getModule()->getModuleFlag("ms-hotpatch")) || !Asm->getObjFileLowering().getCOFFDebugSymbolsSection()) { Asm = nullptr; return; @@ -622,10 +623,21 @@ void CodeViewDebug::beginModule(Module *M) { TheCPU = mapArchToCVCPUType(M->getTargetTriple().getArch()); // Get the current source language. - const MDNode *Node = *M->debug_compile_units_begin(); + const MDNode *Node; + if (Asm->hasDebugInfo()) { + Node = *M->debug_compile_units_begin(); + } else { + // When emitting only compiler information, we may have only NoDebug CUs, + // which would be skipped by debug_compile_units_begin. + NamedMDNode *CUs = MMI->getModule()->getNamedMetadata("llvm.dbg.cu"); + Node = *CUs->operands().begin(); + } const auto *CU = cast<DICompileUnit>(Node); CurrentSourceLanguage = MapDWLangToCVLang(CU->getSourceLanguage()); + NoDebug = !M->getCodeViewFlag(); + if (NoDebug) + return; collectGlobalVariableInfo(); @@ -636,7 +648,7 @@ void CodeViewDebug::beginModule(Module *M) { } void CodeViewDebug::endModule() { - if (!Asm || !Asm->hasDebugInfo()) + if (!Asm) return; // The COFF .debug$S section consists of several subsections, each starting @@ -653,6 +665,9 @@ void CodeViewDebug::endModule() { emitCompilerInformation(); endCVSubsection(CompilerInfo); + if (NoDebug) + return; + emitInlineeLinesSubsection(); // Emit per-function debug information. @@ -846,8 +861,8 @@ void CodeViewDebug::emitCompilerInformation() { } using ArchType = llvm::Triple::ArchType; ArchType Arch = MMI->getModule()->getTargetTriple().getArch(); - if (Asm->TM.Options.Hotpatch || Arch == ArchType::thumb || - Arch == ArchType::aarch64) { + if (Arch == ArchType::thumb || Arch == ArchType::aarch64 || + MMI->getModule()->getModuleFlag("ms-hotpatch")) { Flags |= static_cast<uint32_t>(CompileSym3Flags::HotPatch); } @@ -1440,6 +1455,9 @@ void CodeViewDebug::collectVariableInfo(const DISubprogram *SP) { } void CodeViewDebug::beginFunctionImpl(const MachineFunction *MF) { + if (NoDebug) + return; + const TargetSubtargetInfo &TSI = MF->getSubtarget(); const TargetRegisterInfo *TRI = TSI.getRegisterInfo(); const MachineFrameInfo &MFI = MF->getFrameInfo(); @@ -3031,6 +3049,9 @@ void CodeViewDebug::collectLexicalBlockInfo( } void CodeViewDebug::endFunctionImpl(const MachineFunction *MF) { + if (NoDebug) + return; + const Function &GV = MF->getFunction(); assert(FnDebugInfo.count(&GV)); assert(CurFn == FnDebugInfo[&GV].get()); @@ -3089,6 +3110,8 @@ static bool isUsableDebugLoc(DebugLoc DL) { void CodeViewDebug::beginInstruction(const MachineInstr *MI) { DebugHandlerBase::beginInstruction(MI); + if (NoDebug) + return; // Ignore DBG_VALUE and DBG_LABEL locations and function prologue. if (!Asm || !CurFn || MI->isDebugInstr() || diff --git a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h index d13b315135ad9..3bf3e6db768d7 100644 --- a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h +++ b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h @@ -98,6 +98,9 @@ class LLVM_LIBRARY_VISIBILITY CodeViewDebug : public DebugHandlerBase { /// The codeview CPU type used by the translation unit. codeview::CPUType TheCPU; + /// Whether to emit compiler information only. + bool NoDebug = false; + static LocalVarDef createDefRangeMem(uint16_t CVRegister, int Offset); /// Similar to DbgVariable in DwarfDebug, but not dwarf-specific. diff --git a/llvm/test/DebugInfo/PDB/hotpatch-dwarf.c b/llvm/test/DebugInfo/PDB/hotpatch-dwarf.c new file mode 100644 index 0000000000000..5b1682ee20efd --- /dev/null +++ b/llvm/test/DebugInfo/PDB/hotpatch-dwarf.c @@ -0,0 +1,59 @@ +; RUN: llc -filetype=obj -o - %s | llvm-readobj --codeview - | FileCheck %s + +; ModuleID = 'a.c' +source_filename = "a.c" +target datalayout = "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-windows-msvc19.33.0" + +; Function Attrs: noinline nounwind optnone uwtable +define dso_local void @test() #0 !dbg !10 { +entry: + ret void, !dbg !13 +} + +attributes #0 = { noinline nounwind optnone uwtable "min-legal-vector-width"="0" "no-trapping-math"="true" "patchable-function"="prologue-short-redirect" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!2, !3, !4, !5, !6, !7, !8} +!llvm.ident = !{!9} + +!0 = distinct !DICompileUnit(language: DW_LANG_C11, file: !1, producer: "clang version 21.0.0git", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None) +!1 = !DIFile(filename: "a.c", directory: "/tmp") +!2 = !{i32 7, !"Dwarf Version", i32 4} +!3 = !{i32 2, !"ms-hotpatch", i32 1} +!4 = !{i32 2, !"Debug Info Version", i32 3} +!5 = !{i32 1, !"wchar_size", i32 2} +!6 = !{i32 8, !"PIC Level", i32 2} +!7 = !{i32 7, !"uwtable", i32 2} +!8 = !{i32 1, !"MaxTLSAlign", i32 65536} +!9 = !{!"clang version 21.0.0git"} +!10 = distinct !DISubprogram(name: "test", scope: !1, file: !1, line: 1, type: !11, scopeLine: 1, spFlags: DISPFlagDefinition, unit: !0) +!11 = !DISubroutineType(types: !12) +!12 = !{null} +!13 = !DILocation(line: 1, column: 14, scope: !10) + + +; CHECK: CodeViewDebugInfo [ +; CHECK-NEXT: Section: .debug$S (4) +; CHECK-NEXT: Magic: 0x4 +; CHECK-NEXT: Subsection [ +; CHECK-NEXT: SubSectionType: Symbols (0xF1) +; CHECK-NEXT: SubSectionSize: 0x40 +; CHECK-NEXT: ObjNameSym { +; CHECK-NEXT: Kind: S_OBJNAME (0x1101) +; CHECK-NEXT: Signature: 0x0 +; CHECK-NEXT: ObjectName: +; CHECK-NEXT: } +; CHECK-NEXT: Compile3Sym { +; CHECK-NEXT: Kind: S_COMPILE3 (0x113C) +; CHECK-NEXT: Language: C (0x0) +; CHECK-NEXT: Flags [ (0x4000) +; CHECK-NEXT: HotPatch (0x4000) +; CHECK-NEXT: ] +; CHECK-NEXT: Machine: X64 (0xD0) +; CHECK-NEXT: FrontendVersion: 21.0.0.0 +; CHECK-NEXT: BackendVersion: 21000.0.0.0 +; CHECK-NEXT: VersionName: clang version 21.0.0git +; CHECK-NEXT: } +; CHECK-NEXT: ] +; CHECK-NEXT: ] diff --git a/llvm/test/DebugInfo/PDB/hotpatch-nodebug.c b/llvm/test/DebugInfo/PDB/hotpatch-nodebug.c new file mode 100644 index 0000000000000..abce081746188 --- /dev/null +++ b/llvm/test/DebugInfo/PDB/hotpatch-nodebug.c @@ -0,0 +1,57 @@ +; RUN: llc -filetype=obj -o - %s | llvm-readobj --codeview - | FileCheck %s + +; ModuleID = 'a.c' +source_filename = "a.c" +target datalayout = "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-windows-msvc19.33.0" + +; Function Attrs: noinline nounwind optnone uwtable +define dso_local void @test() #0 !dbg !9 { +entry: + ret void, !dbg !12 +} + +attributes #0 = { noinline nounwind optnone uwtable "min-legal-vector-width"="0" "no-trapping-math"="true" "patchable-function"="prologue-short-redirect" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!2, !3, !4, !5, !6, !7} +!llvm.ident = !{!8} + +!0 = distinct !DICompileUnit(language: DW_LANG_C11, file: !1, producer: "clang version 21.0.0git", isOptimized: false, runtimeVersion: 0, emissionKind: NoDebug, splitDebugInlining: false, nameTableKind: None) +!1 = !DIFile(filename: "a.c", directory: "/tmp") +!2 = !{i32 2, !"ms-hotpatch", i32 1} +!3 = !{i32 2, !"Debug Info Version", i32 3} +!4 = !{i32 1, !"wchar_size", i32 2} +!5 = !{i32 8, !"PIC Level", i32 2} +!6 = !{i32 7, !"uwtable", i32 2} +!7 = !{i32 1, !"MaxTLSAlign", i32 65536} +!8 = !{!"clang version 21.0.0git"} +!9 = distinct !DISubprogram(name: "test", scope: !1, file: !1, line: 1, type: !10, scopeLine: 1, spFlags: DISPFlagDefinition, unit: !0) +!10 = !DISubroutineType(types: !11) +!11 = !{} +!12 = !DILocation(line: 1, column: 14, scope: !9) + +; CHECK: CodeViewDebugInfo [ +; CHECK-NEXT: Section: .debug$S (4) +; CHECK-NEXT: Magic: 0x4 +; CHECK-NEXT: Subsection [ +; CHECK-NEXT: SubSectionType: Symbols (0xF1) +; CHECK-NEXT: SubSectionSize: 0x40 +; CHECK-NEXT: ObjNameSym { +; CHECK-NEXT: Kind: S_OBJNAME (0x1101) +; CHECK-NEXT: Signature: 0x0 +; CHECK-NEXT: ObjectName: +; CHECK-NEXT: } +; CHECK-NEXT: Compile3Sym { +; CHECK-NEXT: Kind: S_COMPILE3 (0x113C) +; CHECK-NEXT: Language: C (0x0) +; CHECK-NEXT: Flags [ (0x4000) +; CHECK-NEXT: HotPatch (0x4000) +; CHECK-NEXT: ] +; CHECK-NEXT: Machine: X64 (0xD0) +; CHECK-NEXT: FrontendVersion: 21.0.0.0 +; CHECK-NEXT: BackendVersion: 21000.0.0.0 +; CHECK-NEXT: VersionName: clang version 21.0.0git +; CHECK-NEXT: } +; CHECK-NEXT: ] +; CHECK-NEXT: ] diff --git a/llvm/test/DebugInfo/PDB/hotpatch.test b/llvm/test/DebugInfo/PDB/hotpatch.test new file mode 100644 index 0000000000000..7ff15fa3c69a4 --- /dev/null +++ b/llvm/test/DebugInfo/PDB/hotpatch.test @@ -0,0 +1,57 @@ +; RUN: llc -filetype=obj -o - %s | llvm-readobj --codeview - | FileCheck %s + +; ModuleID = 'a.c' +source_filename = "a.c" +target datalayout = "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-windows-msvc19.33.0" + +; Function Attrs: noinline nounwind optnone uwtable +define dso_local void @test() #0 !dbg !10 { +entry: + ret void, !dbg !13 +} + +attributes #0 = { noinline nounwind optnone uwtable "min-legal-vector-width"="0" "no-trapping-math"="true" "patchable-function"="prologue-short-redirect" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!2, !3, !4, !5, !6, !7, !8} +!llvm.ident = !{!9} + +!0 = distinct !DICompileUnit(language: DW_LANG_C11, file: !1, producer: "clang version 21.0.0git", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None) +!1 = !DIFile(filename: "a.c", directory: "/tmp", checksumkind: CSK_MD5, checksum: "c59e1f6192de3124537b024248301dd1") +!2 = !{i32 2, !"CodeView", i32 1} +!3 = !{i32 2, !"ms-hotpatch", i32 1} +!4 = !{i32 2, !"Debug Info Version", i32 3} +!5 = !{i32 1, !"wchar_size", i32 2} +!6 = !{i32 8, !"PIC Level", i32 2} +!7 = !{i32 7, !"uwtable", i32 2} +!8 = !{i32 1, !"MaxTLSAlign", i32 65536} +!9 = !{!"clang version 21.0.0git"} +!10 = distinct !DISubprogram(name: "test", scope: !1, file: !1, line: 1, type: !11, scopeLine: 1, spFlags: DISPFlagDefinition, unit: !0) +!11 = !DISubroutineType(types: !12) +!12 = !{null} +!13 = !DILocation(line: 1, scope: !10) + +; CHECK: CodeViewDebugInfo [ +; CHECK-NEXT: Section: .debug$S (4) +; CHECK-NEXT: Magic: 0x4 +; CHECK-NEXT: Subsection [ +; CHECK-NEXT: SubSectionType: Symbols (0xF1) +; CHECK-NEXT: SubSectionSize: 0x40 +; CHECK-NEXT: ObjNameSym { +; CHECK-NEXT: Kind: S_OBJNAME (0x1101) +; CHECK-NEXT: Signature: 0x0 +; CHECK-NEXT: ObjectName: +; CHECK-NEXT: } +; CHECK-NEXT: Compile3Sym { +; CHECK-NEXT: Kind: S_COMPILE3 (0x113C) +; CHECK-NEXT: Language: C (0x0) +; CHECK-NEXT: Flags [ (0x4000) +; CHECK-NEXT: HotPatch (0x4000) +; CHECK-NEXT: ] +; CHECK-NEXT: Machine: X64 (0xD0) +; CHECK-NEXT: FrontendVersion: 21.0.0.0 +; CHECK-NEXT: BackendVersion: 21000.0.0.0 +; CHECK-NEXT: VersionName: clang version 21.0.0git +; CHECK-NEXT: } +; CHECK-NEXT: ] `````````` </details> https://github.com/llvm/llvm-project/pull/142970 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits